Skip to content

Commit 6cbbbb5

Browse files
LocalIdentityLocalIdentity
andauthored
Use Characters.ot and Monsters.ot files for many magic numbers (#9286)
* Use Characters.ot and Monsters.ot files for many magic numbers Port of PathOfBuildingCommunity/PathOfBuilding-PoE2#1184 These 2 files contain many constants we had currently hardcoded in various files * Fix impale tests New phys damage reduction cap was breaking them --------- Co-authored-by: LocalIdentity <[email protected]>
1 parent 14a0aae commit 6cbbbb5

File tree

9 files changed

+281
-81
lines changed

9 files changed

+281
-81
lines changed

spec/System/TestImpale_spec.lua

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -112,34 +112,34 @@ describe("TestAttacks", function()
112112
build.configTab.input.customMods = "\z
113113
never deal critical strikes\n\z
114114
"
115-
build.configTab.input.enemyPhysicalReduction = 10
115+
build.configTab.input.enemyPhysicalReduction = 8
116116
build.configTab.input.enemyArmour = 1000 -- 50% dr for 200 damage, 66.6% dr for 100 dmg (impale stacks)
117117
build.configTab:BuildModList()
118118
runCallback("OnFrame")
119119

120120
-- dam * (1 - (armourDR + additionalDR)
121-
assert.are.equals(200 * (1 - (0.5 + 0.1)), build.calcsTab.mainOutput.MainHand.PhysicalHitAverage)
121+
assert.are.equals(200 * (1 - (0.5 + 0.08)), build.calcsTab.mainOutput.MainHand.PhysicalHitAverage)
122122
assert.are.equals(200, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg)
123123
assert.are.equals(200, build.calcsTab.mainOutput.impaleStoredHitAvg)
124124
-- [5 impales * 10% stored damage] * 1.3 attacks * (armour mod - phys DR)
125-
assert.are.near(100 * 1.3 * (1 - (2/3 + 0.1)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
125+
assert.are.near(100 * 1.3 * (1 - (2/3 + 0.08)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
126126

127127

128128
-- 100% crit
129129
build.configTab.input.customMods = "\z
130130
+100% critical strike chance\n\z
131131
"
132-
build.configTab.input.enemyPhysicalReduction = 10
132+
build.configTab.input.enemyPhysicalReduction = 8
133133
build.configTab.input.enemyArmour = 1500 -- 50% dr for 300 damage, 66.6% dr for 150 dmg (impale stacks)
134134
build.configTab:BuildModList()
135135
runCallback("OnFrame")
136136

137137
-- dam * (1 - (armourDR + additionalDR)
138-
assert.are.equals(300 * (1 - (0.5 + 0.1)), build.calcsTab.mainOutput.MainHand.PhysicalCritAverage)
138+
assert.are.equals(300 * (1 - (0.5 + 0.08)), build.calcsTab.mainOutput.MainHand.PhysicalCritAverage)
139139
assert.are.equals(300, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg)
140140
assert.are.equals(300, build.calcsTab.mainOutput.impaleStoredHitAvg)
141141
-- [5 impales * 10% stored damage] * 1.3 attacks * (armour mod - phys DR)
142-
assert.are.near(150 * 1.3 * (1 - (2/3 + 0.1)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
142+
assert.are.near(150 * 1.3 * (1 - (2/3 + 0.08)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
143143

144144
end)
145145

@@ -149,35 +149,35 @@ describe("TestAttacks", function()
149149
never deal critical strikes\n\z
150150
Nearby enemies take 100% increased physical damage\n\z
151151
"
152-
build.configTab.input.enemyPhysicalReduction = 10
152+
build.configTab.input.enemyPhysicalReduction = 8
153153
build.configTab.input.enemyArmour = 1000 -- 50% dr for 200 damage, 66.6% dr for 100 dmg (impale stacks) .. damage taken is after armour
154154
build.configTab:BuildModList()
155155
runCallback("OnFrame")
156156

157157
-- taken * dam * (1 - (armourDR + additionalDR)
158-
assert.are.equals(2 * 200 * (1 - (0.5 + 0.1)), build.calcsTab.mainOutput.MainHand.PhysicalHitAverage)
158+
assert.are.equals(2 * 200 * (1 - (0.5 + 0.08)), build.calcsTab.mainOutput.MainHand.PhysicalHitAverage)
159159
assert.are.equals(200, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg)
160160
assert.are.equals(200, build.calcsTab.mainOutput.impaleStoredHitAvg)
161161
-- taken * [5 impales * 10% stored damage] * 1.3 attacks * (armour mod - phys DR)
162-
assert.are.near(2 * 100 * 1.3 * (1 - (2/3 + 0.1)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
162+
assert.are.near(2 * 100 * 1.3 * (1 - (2/3 + 0.08)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
163163

164164

165165
-- 100% crit
166166
build.configTab.input.customMods = "\z
167167
+100% critical strike chance\n\z
168168
Nearby enemies take 100% increased physical damage\n\z
169169
"
170-
build.configTab.input.enemyPhysicalReduction = 10
170+
build.configTab.input.enemyPhysicalReduction = 8
171171
build.configTab.input.enemyArmour = 1500 -- 50% dr for 300 damage, 66.6% dr for 150 dmg (impale stacks)
172172
build.configTab:BuildModList()
173173
runCallback("OnFrame")
174174

175175
-- taken * dam * (1 - (armourDR + additionalDR)
176-
assert.are.equals(2 * 300 * (1 - (0.5 + 0.1)), build.calcsTab.mainOutput.MainHand.PhysicalCritAverage)
176+
assert.are.equals(2 * 300 * (1 - (0.5 + 0.08)), build.calcsTab.mainOutput.MainHand.PhysicalCritAverage)
177177
assert.are.equals(300, build.calcsTab.mainOutput.MainHand.impaleStoredHitAvg)
178178
assert.are.equals(300, build.calcsTab.mainOutput.impaleStoredHitAvg)
179179
-- taken * [5 impales * 10% stored damage] * 1.3 attacks * (armour mod - phys DR)
180-
assert.are.near(2 * 150 * 1.3 * (1 - (2/3 + 0.1)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
180+
assert.are.near(2 * 150 * 1.3 * (1 - (2/3 + 0.08)), build.calcsTab.mainOutput.ImpaleDPS, 0.0000001) -- floating point math
181181

182182
end)
183183

src/Data/Misc.lua

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,153 @@ data.gameConstants = {
5555
["GoldPlusPercentPerAffix"] = 10,
5656
["UniqueBaseGoldCost"] = 2000,
5757
}
58+
-- From Metadata/Characters/Character.ot
59+
data.characterConstants = {
60+
["level"] = 1,
61+
["is_player"] = 1,
62+
["energy_shield_recharge_rate_per_minute_%"] = 2000,
63+
["mana_regeneration_rate_per_minute_%"] = 105,
64+
["base_maximum_all_resistances_%"] = 75,
65+
["maximum_physical_damage_reduction_%"] = 90,
66+
["maximum_block_%"] = 75,
67+
["base_maximum_spell_block_%"] = 75,
68+
["base_attack_speed_+%_per_frenzy_charge"] = 4,
69+
["base_cast_speed_+%_per_frenzy_charge"] = 4,
70+
["object_inherent_damage_+%_final_per_frenzy_charge"] = 4,
71+
["physical_damage_reduction_%_per_endurance_charge"] = 4,
72+
["elemental_damage_reduction_%_per_endurance_charge"] = 4,
73+
["critical_strike_chance_+%_per_power_charge"] = 50,
74+
["max_viper_strike_orbs"] = 4,
75+
["dual_wield_inherent_attack_speed_+%_final"] = 10,
76+
["max_fuse_arrow_orbs"] = 5,
77+
["max_fire_beam_stacks"] = 8,
78+
["base_evasion_rating"] = 15,
79+
["life_per_level"] = 12,
80+
["mana_per_level"] = 6,
81+
["accuracy_rating_per_level"] = 2,
82+
["inherent_block_while_dual_wielding_%"] = 20,
83+
["base_critical_strike_multiplier"] = 150,
84+
["critical_ailment_dot_multiplier_+"] = 50,
85+
["strength_per_level"] = 0,
86+
["dexterity_per_level"] = 0,
87+
["intelligence_per_level"] = 0,
88+
["max_endurance_charges"] = 3,
89+
["max_frenzy_charges"] = 3,
90+
["max_power_charges"] = 3,
91+
["maximum_righteous_charges"] = 5,
92+
["maximum_blood_scythe_charges"] = 5,
93+
["base_number_of_totems_allowed"] = 1,
94+
["base_number_of_traps_allowed"] = 15,
95+
["base_number_of_remote_mines_allowed"] = 15,
96+
["max_charged_attack_stacks"] = 6,
97+
["max_talisman_degen_stacks"] = 20,
98+
["max_frost_nova_stacks"] = 20,
99+
["max_rampage_stacks"] = 1000,
100+
["damage_+%_per_10_rampage_stacks"] = 2,
101+
["movement_velocity_+%_per_10_rampage_stacks"] = 1,
102+
["pvp_shield_damage_+%_final"] = -15,
103+
["maximum_life_leech_rate_%_per_minute"] = 1200,
104+
["maximum_mana_leech_rate_%_per_minute"] = 1200,
105+
["maximum_energy_shield_leech_rate_%_per_minute"] = 600,
106+
["minions_have_labyrinth_trap_degen_effect_+%"] = -90,
107+
["minions_are_immune_to_labyrinth_degen_effect"] = 0,
108+
["minion_damage_taken_+%_from_spike_traps_final"] = -90,
109+
["minion_damage_taken_+%_from_arrow_traps_final"] = 0,
110+
["minion_damage_taken_+%_from_guillotine_traps_final"] = -90,
111+
["minion_global_always_hit"] = 1,
112+
["traps_explode_on_timeout"] = 1,
113+
["maximum_rage"] = 30,
114+
["max_delve_degen_stacks"] = 5000,
115+
["max_azurite_debuff_stacks"] = 10,
116+
["melee_variation"] = 1,
117+
["impaled_debuff_base_duration_ms"] = 8000,
118+
["impaled_debuff_number_of_reflected_hits"] = 5,
119+
["base_total_number_of_sigils_allowed"] = 3,
120+
["maximum_life_leech_amount_per_leech_%_max_life"] = 10,
121+
["maximum_mana_leech_amount_per_leech_%_max_mana"] = 10,
122+
["maximum_energy_shield_leech_amount_per_leech_%_max_energy_shield"] = 10,
123+
["enable_movement_skill_animation_skipping"] = 1,
124+
["melee_hit_damage_stun_multiplier_+%"] = 25,
125+
["non_physical_hit_damage_stun_multiplier_+%"] = -25,
126+
["non_melee_hit_damage_stun_multiplier_+%_final"] = -25,
127+
["object_inherent_melee_hit_stun_duration_+%_final"] = 50,
128+
["additional_insanity_effects_while_delirious"] = 1,
129+
["max_steel_ammo"] = 12,
130+
["chance_to_deal_triple_damage_%_per_brutal_charge"] = 3,
131+
["stun_threshold_+%_per_brutal_charge"] = 10,
132+
["ailment_damage_+%_final_per_affliction_charge"] = 8,
133+
["non_damaging_ailment_effect_+%_final_per_affliction_charge"] = 8,
134+
["elemental_damage_taken_goes_to_energy_shield_over_4_seconds_%_per_absorption_charge"] = 12,
135+
["actor_scale_+%_limit"] = 100,
136+
["mines_invulnerable_for_duration_ms"] = 2000,
137+
["traps_invulnerable_for_duration_ms"] = 2000,
138+
["damage_taken_when_hit_+%_final_per_fortification"] = -1,
139+
["base_max_fortification"] = 20,
140+
["base_presence_radius"] = 80,
141+
["mtx_max_killcounter_stacks"] = 30000,
142+
["soul_eater_maximum_stacks"] = 45,
143+
["rage_loss_delay_ms"] = 2000,
144+
["trigger_attack_graft_each_second_channeling"] = 1,
145+
["base_speed"] = 37,
146+
}
147+
-- From Metadata/Monsters/Monster.ot
148+
data.monsterConstants = {
149+
["item_drop_slots"] = 1,
150+
["energy_shield_recharge_rate_per_minute_%"] = 2000,
151+
["mana_regeneration_rate_per_minute_%"] = 100,
152+
["base_maximum_mana"] = 200,
153+
["maximum_physical_damage_reduction_%"] = 75,
154+
["max_viper_strike_orbs"] = 4,
155+
["base_maximum_all_resistances_%"] = 75,
156+
["max_fuse_arrow_orbs"] = 5,
157+
["max_fire_beam_stacks"] = 8,
158+
["max_charged_attack_stacks"] = 10,
159+
["base_critical_strike_multiplier"] = 130,
160+
["critical_ailment_dot_multiplier_+"] = 30,
161+
["max_endurance_charges"] = 3,
162+
["max_frenzy_charges"] = 3,
163+
["max_power_charges"] = 3,
164+
["base_attack_speed_+%_per_frenzy_charge"] = 4,
165+
["base_attack_speed_+%_per_frenzy_charge_if_not_player_minion"] = 11,
166+
["base_cast_speed_+%_per_frenzy_charge"] = 4,
167+
["base_cast_speed_+%_per_frenzy_charge_if_not_player_minion"] = 11,
168+
["movement_velocity_+%_per_frenzy_charge_if_not_player_minion"] = 5,
169+
["object_inherent_damage_+%_final_per_frenzy_charge"] = 4,
170+
["physical_damage_reduction_%_per_endurance_charge"] = 4,
171+
["physical_damage_reduction_%_per_endurance_charge_if_not_player_minion"] = 11,
172+
["elemental_damage_reduction_%_per_endurance_charge_if_player_minion"] = 4,
173+
["resist_all_elements_%_per_endurance_charge_if_not_player_minion"] = 15,
174+
["critical_strike_chance_+%_per_power_charge"] = 50,
175+
["critical_strike_chance_+%_per_power_charge_if_not_player_minion"] = 150,
176+
["maximum_block_%"] = 75,
177+
["base_maximum_spell_block_%"] = 75,
178+
["base_number_of_totems_allowed"] = 1,
179+
["base_number_of_traps_allowed"] = 3,
180+
["base_number_of_remote_mines_allowed"] = 5,
181+
["movement_velocity_cap"] = 128,
182+
["maximum_life_leech_rate_%_per_minute"] = 1200,
183+
["maximum_mana_leech_rate_%_per_minute"] = 1200,
184+
["maximum_energy_shield_leech_rate_%_per_minute"] = 600,
185+
["monster_ignite_damage_+%_final"] = -72,
186+
["monster_bleeding_damage_+%_final"] = -86,
187+
["monster_poison_damage_+%_final"] = -50,
188+
["bleeding_moving_damage_%_of_base_override"] = 500,
189+
["max_azurite_debuff_stacks"] = 10,
190+
["impaled_debuff_base_duration_ms"] = 8000,
191+
["impaled_debuff_number_of_reflected_hits"] = 5,
192+
["ignore_skill_weapon_restrictions"] = 1,
193+
["base_total_number_of_sigils_allowed"] = 3,
194+
["maximum_life_leech_amount_per_leech_%_max_life"] = 10,
195+
["maximum_mana_leech_amount_per_leech_%_max_mana"] = 10,
196+
["maximum_energy_shield_leech_amount_per_leech_%_max_energy_shield"] = 10,
197+
["object_inherent_melee_hit_stun_duration_+%_final"] = 20,
198+
["scale_melee_range_to_actor_scale"] = 1,
199+
["use_melee_pattern_range"] = 1,
200+
["actor_scale_+%_limit"] = 100,
201+
["damage_taken_when_hit_+%_final_per_fortification"] = -1,
202+
["base_max_fortification"] = 20,
203+
["soul_eater_maximum_stacks"] = 45,
204+
}
58205
-- From MonsterVarieties.dat combined with SkillTotemVariations.dat
59206
data.totemLifeMult = { [1] = 1, [2] = 1, [3] = 1, [4] = 1.2, [5] = 1, [6] = 1.2, [7] = 1.2, [8] = 1.2, [9] = 1, [10] = 1, [11] = 1, [12] = 1, [13] = 1.2, [15] = 1.2, [16] = 7.44, [17] = 1.2, [18] = 1, [19] = 1, [20] = 1.2, [21] = 1.2, }
60207
data.monsterVarietyLifeMult = {

src/Export/Classes/GGPKData.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ function GGPKClass:GetNeededFiles()
308308
"Metadata/StatDescriptions/tincture_stat_descriptions.txt",
309309
"Metadata/StatDescriptions/graft_stat_descriptions.txt",
310310
}
311+
local otFiles = {
312+
"Metadata/Characters/Character.ot",
313+
"Metadata/Monsters/Monster.ot",
314+
}
311315
local itFiles = {
312316
"Metadata/Items/Quivers/AbstractQuiver.it",
313317
"Metadata/Items/Rings/AbstractRing.it",
@@ -351,5 +355,5 @@ function GGPKClass:GetNeededFiles()
351355
"Metadata/Items/Tinctures/AbstractTincture.it",
352356
"Metadata/Items/Jewels/AbstractAnimalCharm.it",
353357
}
354-
return datFiles, txtFiles, itFiles
358+
return datFiles, txtFiles, otFiles, itFiles
355359
end

src/Export/Scripts/miscdata.lua

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,48 @@ for row in dat("GameConstants"):Rows() do
4848
end
4949
out:write('}\n')
5050

51+
out:write('-- From Metadata/Characters/Character.ot\n')
52+
out:write('data.characterConstants = {\n')
53+
local file = getFile("Metadata/Characters/Character.ot")
54+
if not file then return nil end
55+
local text = convertUTF16to8(file)
56+
local inWantedBlock = false
57+
for line in text:gmatch("[^\r\n]+") do
58+
-- Detect start of a block
59+
if line:match("^Stats") or line:match("^Pathfinding") then
60+
inWantedBlock = true
61+
elseif inWantedBlock and line:match("^}") then
62+
inWantedBlock = false
63+
elseif inWantedBlock and line:find("=") then
64+
local key, value = line:gsub("%s+",""):match("^(.-)=(.+)$")
65+
if key and value then
66+
out:write('\t["' .. key .. '"] = ' .. value .. ',\n')
67+
end
68+
end
69+
end
70+
out:write('}\n')
71+
72+
out:write('-- From Metadata/Monsters/Monster.ot\n')
73+
out:write('data.monsterConstants = {\n')
74+
local file = getFile("Metadata/Monsters/Monster.ot")
75+
if not file then return nil end
76+
local text = convertUTF16to8(file)
77+
local inWantedBlock = false
78+
for line in text:gmatch("[^\r\n]+") do
79+
-- Detect start of a block
80+
if line:match("^Stats") then
81+
inWantedBlock = true
82+
elseif inWantedBlock and line:match("^}") then
83+
inWantedBlock = false
84+
elseif inWantedBlock and line:find("=") then
85+
local key, value = line:gsub("%s+",""):match("^(.-)=(.+)$")
86+
if key and value then
87+
out:write('\t["' .. key .. '"] = ' .. value .. ',\n')
88+
end
89+
end
90+
end
91+
out:write('}\n')
92+
5193
local totemMult = ""
5294
local keys = { }
5395
for var in dat("SkillTotemVariations"):Rows() do

src/Modules/CalcOffence.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3198,7 +3198,7 @@ function calcs.offence(env, actor, activeSkill)
31983198
if skillModList:Flag(cfg, "IgnoreEnemyPhysicalDamageReduction") or ChanceToIgnoreEnemyPhysicalDamageReduction >= 100 then
31993199
resist = 0
32003200
else
3201-
resist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction") + skillModList:Sum("BASE", cfg, "EnemyPhysicalDamageReduction") + armourReduction), data.misc.DamageReductionCap)
3201+
resist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction") + skillModList:Sum("BASE", cfg, "EnemyPhysicalDamageReduction") + armourReduction), data.misc.EnemyPhysicalDamageReductionCap)
32023202
resist = resist > 0 and resist * (1 - (skillModList:Sum("BASE", nil, "PartialIgnoreEnemyPhysicalDamageReduction") / 100 + ChanceToIgnoreEnemyPhysicalDamageReduction / 100)) or resist
32033203
end
32043204
else
@@ -4204,7 +4204,7 @@ function calcs.offence(env, actor, activeSkill)
42044204
skillFlags.duration = true
42054205
local effMult = 1
42064206
if env.mode_effective then
4207-
local resist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction")), data.misc.DamageReductionCap)
4207+
local resist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction")), data.misc.EnemyPhysicalDamageReductionCap)
42084208
local takenInc = enemyDB:Sum("INC", dotCfg, "DamageTaken", "DamageTakenOverTime", "PhysicalDamageTaken", "PhysicalDamageTakenOverTime")
42094209
local takenMore = enemyDB:More(dotCfg, "DamageTaken", "DamageTakenOverTime", "PhysicalDamageTaken", "PhysicalDamageTakenOverTime")
42104210
effMult = (1 - resist / 100) * (1 + takenInc / 100) * takenMore
@@ -5209,7 +5209,7 @@ function calcs.offence(env, actor, activeSkill)
52095209

52105210
local enemyArmour = m_max(calcLib.val(enemyDB, "Armour"), 0)
52115211
local impaleArmourReduction = calcs.armourReductionF(enemyArmour, impaleHitDamageMod * output.impaleStoredHitAvg)
5212-
local impaleResist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction") + skillModList:Sum("BASE", cfg, "EnemyImpalePhysicalDamageReduction") + impaleArmourReduction), data.misc.DamageReductionCap)
5212+
local impaleResist = m_min(m_max(0, enemyDB:Sum("BASE", nil, "PhysicalDamageReduction") + skillModList:Sum("BASE", cfg, "EnemyImpalePhysicalDamageReduction") + impaleArmourReduction), data.misc.EnemyPhysicalDamageReductionCap)
52135213
if skillModList:Flag(cfg, "IgnoreEnemyImpalePhysicalDamageReduction") then
52145214
impaleResist = 0
52155215
end
@@ -5422,7 +5422,7 @@ function calcs.offence(env, actor, activeSkill)
54225422
local takenInc = enemyDB:Sum("INC", dotTakenCfg, "DamageTaken", "DamageTakenOverTime", damageType.."DamageTaken", damageType.."DamageTakenOverTime") + (isElemental[damageType] and enemyDB:Sum("INC", dotTakenCfg, "ElementalDamageTaken") or 0)
54235423
local takenMore = enemyDB:More(dotTakenCfg, "DamageTaken", "DamageTakenOverTime", damageType.."DamageTaken", damageType.."DamageTakenOverTime") * (isElemental[damageType] and enemyDB:More(dotTakenCfg, "ElementalDamageTaken") or 1)
54245424
if damageType == "Physical" then
5425-
resist = m_max(0, m_min(enemyDB:Sum("BASE", nil, "PhysicalDamageReduction"), data.misc.DamageReductionCap))
5425+
resist = m_max(0, m_min(enemyDB:Sum("BASE", nil, "PhysicalDamageReduction"), data.misc.EnemyPhysicalDamageReductionCap))
54265426
else
54275427
resist = calcResistForType(damageType, dotTypeCfg)
54285428
end

0 commit comments

Comments
 (0)