diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d20b64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..433612a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "test_plugindata.py", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/test_plugindata.py", + "console": "integratedTerminal", + "justMyCode": false + }, + { + "name": "Python Debugger: Python File", + "type": "debugpy", + "request": "launch", + "program": "${file}" + } + ] +} \ No newline at end of file diff --git a/base/attribute.py b/base/attribute.py index 833a27a..b68af4a 100644 --- a/base/attribute.py +++ b/base/attribute.py @@ -17,7 +17,9 @@ def kind_type(self): else: return SKILL_KIND_TYPE.NONE - def __init__(self, major_type: str = "", damage_type: str = "", critical_type: str = ""): + def __init__( + self, major_type: str = "", damage_type: str = "", critical_type: str = "" + ): self.major_type = major_type self.damage_type = damage_type self.critical_type = critical_type @@ -129,12 +131,16 @@ def base_magical_attack_power(self): @property def base_solar_attack_power(self): - base_attack_power = self.solar_attack_power_base + self.solar_and_lunar_attack_power_base + base_attack_power = ( + self.solar_attack_power_base + self.solar_and_lunar_attack_power_base + ) return base_attack_power + self.magical_attack_power_base @property def base_lunar_attack_power(self): - base_attack_power = self.lunar_attack_power_base + self.solar_and_lunar_attack_power_base + base_attack_power = ( + self.lunar_attack_power_base + self.solar_and_lunar_attack_power_base + ) return base_attack_power + self.base_solar_attack_power @property @@ -164,35 +170,61 @@ class ExtraAttackPower(Major): @property def extra_physical_attack_power(self): - extra_attack_power = Int(self.agility * self.agility_to_physical_attack_power / BINARY_SCALE) - extra_attack_power += Int(self.strength * self.strength_to_physical_attack_power / BINARY_SCALE) - extra_attack_power += Int(self.vitality * self.vitality_to_physical_attack_power / BINARY_SCALE) + extra_attack_power = Int( + self.agility * self.agility_to_physical_attack_power / BINARY_SCALE + ) + extra_attack_power += Int( + self.strength * self.strength_to_physical_attack_power / BINARY_SCALE + ) + extra_attack_power += Int( + self.vitality * self.vitality_to_physical_attack_power / BINARY_SCALE + ) return extra_attack_power @property def extra_solar_attack_power(self): - extra_attack_power = Int(self.spunk * self.spunk_to_solar_attack_power / BINARY_SCALE) - extra_attack_power += Int(self.spunk * self.spunk_to_solar_and_lunar_attack_power / BINARY_SCALE) - extra_attack_power += Int(self.vitality * self.vitality_to_solar_attack_power / BINARY_SCALE) + extra_attack_power = Int( + self.spunk * self.spunk_to_solar_attack_power / BINARY_SCALE + ) + extra_attack_power += Int( + self.spunk * self.spunk_to_solar_and_lunar_attack_power / BINARY_SCALE + ) + extra_attack_power += Int( + self.vitality * self.vitality_to_solar_attack_power / BINARY_SCALE + ) return extra_attack_power @property def extra_lunar_attack_power(self): - extra_attack_power = Int(self.spirit * self.spirit_to_lunar_attack_power / BINARY_SCALE) - extra_attack_power += Int(self.spunk * self.spunk_to_solar_and_lunar_attack_power / BINARY_SCALE) - extra_attack_power += Int(self.vitality * self.vitality_to_lunar_attack_power / BINARY_SCALE) + extra_attack_power = Int( + self.spirit * self.spirit_to_lunar_attack_power / BINARY_SCALE + ) + extra_attack_power += Int( + self.spunk * self.spunk_to_solar_and_lunar_attack_power / BINARY_SCALE + ) + extra_attack_power += Int( + self.vitality * self.vitality_to_lunar_attack_power / BINARY_SCALE + ) return extra_attack_power @property def extra_neutral_attack_power(self): - extra_attack_power = Int(self.spunk * self.spunk_to_neutral_attack_power / BINARY_SCALE) - extra_attack_power += Int(self.spirit * self.spirit_to_neutral_attack_power / BINARY_SCALE) + extra_attack_power = Int( + self.spunk * self.spunk_to_neutral_attack_power / BINARY_SCALE + ) + extra_attack_power += Int( + self.spirit * self.spirit_to_neutral_attack_power / BINARY_SCALE + ) return extra_attack_power @property def extra_poison_attack_power(self): - extra_attack_power = Int(self.spunk * self.spunk_to_poison_attack_power / BINARY_SCALE) - extra_attack_power += Int(self.spirit * self.spirit_to_poison_attack_power / BINARY_SCALE) + extra_attack_power = Int( + self.spunk * self.spunk_to_poison_attack_power / BINARY_SCALE + ) + extra_attack_power += Int( + self.spirit * self.spirit_to_poison_attack_power / BINARY_SCALE + ) return extra_attack_power @property @@ -227,30 +259,44 @@ def attack_power_gain(self): class AttackPower(BaseAttackPower, ExtraAttackPower, AttackPowerGain): - @property def physical_attack_power(self): - attack_power = Int(self.base_physical_attack_power * (1 + self.physical_attack_power_gain / BINARY_SCALE)) + attack_power = Int( + self.base_physical_attack_power + * (1 + self.physical_attack_power_gain / BINARY_SCALE) + ) return attack_power + self.extra_physical_attack_power @property def solar_attack_power(self): - attack_power = Int(self.base_solar_attack_power * (1 + self.solar_attack_power_gain / BINARY_SCALE)) + attack_power = Int( + self.base_solar_attack_power + * (1 + self.solar_attack_power_gain / BINARY_SCALE) + ) return attack_power + self.extra_solar_attack_power @property def lunar_attack_power(self): - attack_power = Int(self.base_lunar_attack_power * (1 + self.lunar_attack_power_gain / BINARY_SCALE)) + attack_power = Int( + self.base_lunar_attack_power + * (1 + self.lunar_attack_power_gain / BINARY_SCALE) + ) return attack_power + self.extra_lunar_attack_power @property def neutral_attack_power(self): - attack_power = Int(self.base_neutral_attack_power * (1 + self.neutral_attack_power_gain / BINARY_SCALE)) + attack_power = Int( + self.base_neutral_attack_power + * (1 + self.neutral_attack_power_gain / BINARY_SCALE) + ) return attack_power + self.extra_neutral_attack_power @property def poison_attack_power(self): - attack_power = Int(self.base_poison_attack_power * (1 + self.poison_attack_power_gain / BINARY_SCALE)) + attack_power = Int( + self.base_poison_attack_power + * (1 + self.poison_attack_power_gain / BINARY_SCALE) + ) return attack_power + self.extra_poison_attack_power @property @@ -278,22 +324,34 @@ def critical_strike_base(self, value): @property def base_physical_critical_strike(self): - base_critical_strike = self.physical_critical_strike_base + self.all_critical_strike_base - return base_critical_strike + Int(self.agility * AGILITY_TO_CRITICAL_STRIKE / BINARY_SCALE) + base_critical_strike = ( + self.physical_critical_strike_base + self.all_critical_strike_base + ) + return base_critical_strike + Int( + self.agility * AGILITY_TO_CRITICAL_STRIKE / BINARY_SCALE + ) @property def base_magical_critical_strike(self): - base_critical_strike = self.magical_critical_strike_base + self.all_critical_strike_base - return base_critical_strike + Int(self.spirit * SPIRIT_TO_CRITICAL_STRIKE / BINARY_SCALE) + base_critical_strike = ( + self.magical_critical_strike_base + self.all_critical_strike_base + ) + return base_critical_strike + Int( + self.spirit * SPIRIT_TO_CRITICAL_STRIKE / BINARY_SCALE + ) @property def base_solar_critical_strike(self): - base_critical_strike = self.solar_critical_strike_base + self.solar_and_lunar_critical_strike_base + base_critical_strike = ( + self.solar_critical_strike_base + self.solar_and_lunar_critical_strike_base + ) return base_critical_strike + self.base_magical_critical_strike @property def base_lunar_critical_strike(self): - base_critical_strike = self.lunar_critical_strike_base + self.solar_and_lunar_critical_strike_base + base_critical_strike = ( + self.lunar_critical_strike_base + self.solar_and_lunar_critical_strike_base + ) return base_critical_strike + self.base_magical_critical_strike @property @@ -325,37 +383,59 @@ class ExtraCriticalStrike(Major): @property def extra_physical_critical_strike(self): - extra_critical_strike = Int(self.agility * self.agility_to_physical_critical_strike / BINARY_SCALE) - extra_critical_strike += Int(self.strength * self.strength_to_physical_critical_strike / BINARY_SCALE) - extra_critical_strike += Int(self.spunk * self.spunk_to_physical_critical_strike / BINARY_SCALE) + extra_critical_strike = Int( + self.agility * self.agility_to_physical_critical_strike / BINARY_SCALE + ) + extra_critical_strike += Int( + self.strength * self.strength_to_physical_critical_strike / BINARY_SCALE + ) + extra_critical_strike += Int( + self.spunk * self.spunk_to_physical_critical_strike / BINARY_SCALE + ) return extra_critical_strike @property def extra_magical_critical_strike(self): - extra_critical_strike = Int(self.vitality * self.vitality_to_magical_critical_strike / BINARY_SCALE) + extra_critical_strike = Int( + self.vitality * self.vitality_to_magical_critical_strike / BINARY_SCALE + ) return extra_critical_strike @property def extra_solar_critical_strike(self): - extra_critical_strike = Int(self.spunk * self.spunk_to_solar_critical_strike / BINARY_SCALE) - extra_critical_strike += Int(self.spunk * self.spunk_to_solar_and_lunar_critical_strike / BINARY_SCALE) + extra_critical_strike = Int( + self.spunk * self.spunk_to_solar_critical_strike / BINARY_SCALE + ) + extra_critical_strike += Int( + self.spunk * self.spunk_to_solar_and_lunar_critical_strike / BINARY_SCALE + ) return extra_critical_strike + self.extra_magical_critical_strike @property def extra_lunar_critical_strike(self): - extra_critical_strike = Int(self.spirit * self.spirit_to_lunar_critical_strike / BINARY_SCALE) - extra_critical_strike += Int(self.spunk * self.spunk_to_solar_and_lunar_critical_strike / BINARY_SCALE) + extra_critical_strike = Int( + self.spirit * self.spirit_to_lunar_critical_strike / BINARY_SCALE + ) + extra_critical_strike += Int( + self.spunk * self.spunk_to_solar_and_lunar_critical_strike / BINARY_SCALE + ) return extra_critical_strike + self.extra_magical_critical_strike @property def extra_neutral_critical_strike(self): - extra_critical_strike = Int(self.spirit * self.spirit_to_neutral_critical_strike / BINARY_SCALE) - extra_critical_strike += Int(self.spunk * self.spunk_to_neutral_critical_strike / BINARY_SCALE) + extra_critical_strike = Int( + self.spirit * self.spirit_to_neutral_critical_strike / BINARY_SCALE + ) + extra_critical_strike += Int( + self.spunk * self.spunk_to_neutral_critical_strike / BINARY_SCALE + ) return extra_critical_strike + self.extra_magical_critical_strike @property def extra_poison_critical_strike(self): - extra_critical_strike = Int(self.spirit * self.spirit_to_poison_critical_strike / BINARY_SCALE) + extra_critical_strike = Int( + self.spirit * self.spirit_to_poison_critical_strike / BINARY_SCALE + ) return extra_critical_strike + self.extra_magical_critical_strike @@ -388,27 +468,37 @@ def final_critical_strike(self): class CriticalStrikePercent(FinalCriticalStrike): @property def physical_critical_strike_percent(self): - critical_strike_percent = self.final_physical_critical_strike / CRITICAL_STRIKE_SCALE + critical_strike_percent = ( + self.final_physical_critical_strike / CRITICAL_STRIKE_SCALE + ) return Int(critical_strike_percent * DECIMAL_SCALE) / DECIMAL_SCALE @property def solar_critical_strike_percent(self): - critical_strike_percent = self.final_solar_critical_strike / CRITICAL_STRIKE_SCALE + critical_strike_percent = ( + self.final_solar_critical_strike / CRITICAL_STRIKE_SCALE + ) return Int(critical_strike_percent * DECIMAL_SCALE) / DECIMAL_SCALE @property def lunar_critical_strike_percent(self): - critical_strike_percent = self.final_lunar_critical_strike / CRITICAL_STRIKE_SCALE + critical_strike_percent = ( + self.final_lunar_critical_strike / CRITICAL_STRIKE_SCALE + ) return Int(critical_strike_percent * DECIMAL_SCALE) / DECIMAL_SCALE @property def neutral_critical_strike_percent(self): - critical_strike_percent = self.final_neutral_critical_strike / CRITICAL_STRIKE_SCALE + critical_strike_percent = ( + self.final_neutral_critical_strike / CRITICAL_STRIKE_SCALE + ) return Int(critical_strike_percent * DECIMAL_SCALE) / DECIMAL_SCALE @property def poison_critical_strike_percent(self): - critical_strike_percent = self.final_poison_critical_strike / CRITICAL_STRIKE_SCALE + critical_strike_percent = ( + self.final_poison_critical_strike / CRITICAL_STRIKE_SCALE + ) return Int(critical_strike_percent * DECIMAL_SCALE) / DECIMAL_SCALE @property @@ -431,27 +521,42 @@ def critical_strike_rate(self): class CriticalStrike(CriticalStrikePercent, CriticalStrikeRate): @property def physical_critical_strike(self): - critical_strike = self.physical_critical_strike_percent + self.physical_critical_strike_rate / DECIMAL_SCALE + critical_strike = ( + self.physical_critical_strike_percent + + self.physical_critical_strike_rate / DECIMAL_SCALE + ) return critical_strike @property def solar_critical_strike(self): - critical_strike = self.solar_critical_strike_percent + self.solar_critical_strike_rate / DECIMAL_SCALE + critical_strike = ( + self.solar_critical_strike_percent + + self.solar_critical_strike_rate / DECIMAL_SCALE + ) return critical_strike @property def lunar_critical_strike(self): - critical_strike = self.lunar_critical_strike_percent + self.lunar_critical_strike_rate / DECIMAL_SCALE + critical_strike = ( + self.lunar_critical_strike_percent + + self.lunar_critical_strike_rate / DECIMAL_SCALE + ) return critical_strike @property def neutral_critical_strike(self): - critical_strike = self.neutral_critical_strike_percent + self.neutral_critical_strike_rate / DECIMAL_SCALE + critical_strike = ( + self.neutral_critical_strike_percent + + self.neutral_critical_strike_rate / DECIMAL_SCALE + ) return critical_strike @property def poison_critical_strike(self): - critical_strike = self.poison_critical_strike_percent + self.poison_critical_strike_rate / DECIMAL_SCALE + critical_strike = ( + self.poison_critical_strike_percent + + self.poison_critical_strike_rate / DECIMAL_SCALE + ) return critical_strike @property @@ -521,14 +626,22 @@ class ExtraOvercome(Major): @property def extra_physical_overcome(self): - extra_overcome = Int(self.agility * self.agility_to_physical_overcome / BINARY_SCALE) - extra_overcome += Int(self.strength * self.strength_to_physical_overcome / BINARY_SCALE) - extra_overcome += Int(self.vitality * self.vitality_to_physical_overcome / BINARY_SCALE) + extra_overcome = Int( + self.agility * self.agility_to_physical_overcome / BINARY_SCALE + ) + extra_overcome += Int( + self.strength * self.strength_to_physical_overcome / BINARY_SCALE + ) + extra_overcome += Int( + self.vitality * self.vitality_to_physical_overcome / BINARY_SCALE + ) return extra_overcome @property def extra_magical_overcome(self): - extra_overcome = Int(self.vitality * self.vitality_to_magical_overcome / BINARY_SCALE) + extra_overcome = Int( + self.vitality * self.vitality_to_magical_overcome / BINARY_SCALE + ) return extra_overcome @property @@ -546,7 +659,9 @@ def extra_neutral_overcome(self): @property def extra_poison_overcome(self): - extra_overcome = Int(self.spirit * self.spirit_to_poison_overcome / BINARY_SCALE) + extra_overcome = Int( + self.spirit * self.spirit_to_poison_overcome / BINARY_SCALE + ) return extra_overcome + self.extra_magical_overcome @@ -561,27 +676,38 @@ class OvercomeGain: class FinalOvercome(BaseOvercome, ExtraOvercome, OvercomeGain): @property def final_physical_overcome(self): - final_overcome = Int(self.base_physical_overcome * (1 + self.physical_overcome_gain / BINARY_SCALE)) + final_overcome = Int( + self.base_physical_overcome + * (1 + self.physical_overcome_gain / BINARY_SCALE) + ) return final_overcome + self.extra_physical_overcome @property def final_solar_overcome(self): - final_overcome = Int(self.base_solar_overcome * (1 + self.solar_overcome_gain / BINARY_SCALE)) + final_overcome = Int( + self.base_solar_overcome * (1 + self.solar_overcome_gain / BINARY_SCALE) + ) return final_overcome + self.extra_solar_overcome @property def final_lunar_overcome(self): - final_overcome = Int(self.base_lunar_overcome * (1 + self.lunar_overcome_gain / BINARY_SCALE)) + final_overcome = Int( + self.base_lunar_overcome * (1 + self.lunar_overcome_gain / BINARY_SCALE) + ) return final_overcome + self.extra_lunar_overcome @property def final_neutral_overcome(self): - final_overcome = Int(self.base_neutral_overcome * (1 + self.neutral_overcome_gain / BINARY_SCALE)) + final_overcome = Int( + self.base_neutral_overcome * (1 + self.neutral_overcome_gain / BINARY_SCALE) + ) return final_overcome + self.extra_neutral_overcome @property def final_poison_overcome(self): - final_overcome = Int(self.base_poison_overcome * (1 + self.poison_overcome_gain / BINARY_SCALE)) + final_overcome = Int( + self.base_poison_overcome * (1 + self.poison_overcome_gain / BINARY_SCALE) + ) return final_overcome + self.extra_poison_overcome @property @@ -648,12 +774,16 @@ def base_magical_critical_power(self): @property def base_solar_critical_power(self): - critical_power = self.solar_critical_power_base + self.solar_and_lunar_critical_power_base + critical_power = ( + self.solar_critical_power_base + self.solar_and_lunar_critical_power_base + ) return critical_power + self.base_magical_critical_power @property def base_lunar_critical_power(self): - critical_power = self.lunar_critical_power_base + self.solar_and_lunar_critical_power_base + critical_power = ( + self.lunar_critical_power_base + self.solar_and_lunar_critical_power_base + ) return critical_power + self.base_magical_critical_power @property @@ -672,7 +802,9 @@ def base_critical_power(self): class CriticalPowerPercent(BaseCriticalPower): @property def physical_critical_power_percent(self): - critical_power_percent = self.base_physical_critical_power / CRITICAL_POWER_SCALE + critical_power_percent = ( + self.base_physical_critical_power / CRITICAL_POWER_SCALE + ) return Int(critical_power_percent * BINARY_SCALE) / BINARY_SCALE @property @@ -738,31 +870,46 @@ def all_critical_power_rate(self, value): class CriticalPower(CriticalPowerPercent, CriticalPowerRate): @property def physical_critical_power(self): - critical_power = self.physical_critical_power_percent + self.physical_critical_power_rate / BINARY_SCALE + critical_power = ( + self.physical_critical_power_percent + + self.physical_critical_power_rate / BINARY_SCALE + ) critical_power = Min(critical_power, MAX_CRITICAL_POWER) return critical_power + self.unlimit_critical_power_rate / BINARY_SCALE @property def solar_critical_power(self): - critical_power = self.solar_critical_power_percent + self.solar_critical_power_rate / BINARY_SCALE + critical_power = ( + self.solar_critical_power_percent + + self.solar_critical_power_rate / BINARY_SCALE + ) critical_power = Min(critical_power, MAX_CRITICAL_POWER) return critical_power + self.unlimit_critical_power_rate / BINARY_SCALE @property def lunar_critical_power(self): - critical_power = self.lunar_critical_power_percent + self.lunar_critical_power_rate / BINARY_SCALE + critical_power = ( + self.lunar_critical_power_percent + + self.lunar_critical_power_rate / BINARY_SCALE + ) critical_power = Min(critical_power, MAX_CRITICAL_POWER) return critical_power + self.unlimit_critical_power_rate / BINARY_SCALE @property def neutral_critical_power(self): - critical_power = self.neutral_critical_power_percent + self.neutral_critical_power_rate / BINARY_SCALE + critical_power = ( + self.neutral_critical_power_percent + + self.neutral_critical_power_rate / BINARY_SCALE + ) critical_power = Min(critical_power, MAX_CRITICAL_POWER) return critical_power + self.unlimit_critical_power_rate / BINARY_SCALE @property def poison_critical_power(self): - critical_power = self.poison_critical_power_percent + self.poison_critical_power_rate / BINARY_SCALE + critical_power = ( + self.poison_critical_power_percent + + self.poison_critical_power_rate / BINARY_SCALE + ) critical_power = Min(critical_power, MAX_CRITICAL_POWER) return critical_power + self.unlimit_critical_power_rate / BINARY_SCALE @@ -812,12 +959,16 @@ class ExtraShield(Major): @property def extra_physical_shield(self): - extra_shield = Int(self.vitality * self.vitality_to_physical_shield / BINARY_SCALE) + extra_shield = Int( + self.vitality * self.vitality_to_physical_shield / BINARY_SCALE + ) return extra_shield + self.physical_shield_add @property def extra_magical_shield(self): - extra_shield = Int(self.vitality * self.vitality_to_magical_shield / BINARY_SCALE) + extra_shield = Int( + self.vitality * self.vitality_to_magical_shield / BINARY_SCALE + ) return extra_shield @property @@ -852,27 +1003,37 @@ def shield_gain(self): class Shield(BaseShield, ExtraShield, ShieldGain): @property def physical_shield(self): - final_shield = Int(self.base_physical_shield * (1 + self.physical_shield_gain / BINARY_SCALE)) + final_shield = Int( + self.base_physical_shield * (1 + self.physical_shield_gain / BINARY_SCALE) + ) return Max(final_shield, 0) + self.extra_physical_shield @property def solar_shield(self): - final_shield = Int(self.base_solar_shield * (1 + self.solar_shield_gain / BINARY_SCALE)) + final_shield = Int( + self.base_solar_shield * (1 + self.solar_shield_gain / BINARY_SCALE) + ) return Max(final_shield, 0) + self.extra_magical_shield @property def lunar_shield(self): - final_shield = Int(self.base_lunar_shield * (1 + self.lunar_shield_gain / BINARY_SCALE)) + final_shield = Int( + self.base_lunar_shield * (1 + self.lunar_shield_gain / BINARY_SCALE) + ) return Max(final_shield, 0) + self.extra_magical_shield @property def neutral_shield(self): - final_shield = Int(self.base_neutral_shield * (1 + self.neutral_shield_gain / BINARY_SCALE)) + final_shield = Int( + self.base_neutral_shield * (1 + self.neutral_shield_gain / BINARY_SCALE) + ) return Max(final_shield, 0) + self.extra_magical_shield @property def poison_shield(self): - final_shield = Int(self.base_poison_shield * (1 + self.poison_shield_gain / BINARY_SCALE)) + final_shield = Int( + self.base_poison_shield * (1 + self.poison_shield_gain / BINARY_SCALE) + ) return Max(final_shield, 0) + self.extra_magical_shield @@ -966,7 +1127,9 @@ class WeaponDamage: @property def weapon_damage(self): - return Int(self.weapon_damage_base * (1 + self.weapon_damage_gain / BINARY_SCALE)) + return Int( + self.weapon_damage_base * (1 + self.weapon_damage_gain / BINARY_SCALE) + ) class Haste: @@ -1060,7 +1223,10 @@ def extra_parry(self): @property def final_parry(self): - return Int(self.parry_base * (1 + self.parry_gain / BINARY_SCALE)) + self.extra_parry + return ( + Int(self.parry_base * (1 + self.parry_gain / BINARY_SCALE)) + + self.extra_parry + ) @property def parry_percent(self): @@ -1073,13 +1239,20 @@ def parry(self): @property def extra_parry_value(self): - extra_parry_value = Int(self.agility * self.agility_to_parry_value / BINARY_SCALE) - extra_parry_value += Int(self.vitality * self.vitality_to_parry_value / BINARY_SCALE) + extra_parry_value = Int( + self.agility * self.agility_to_parry_value / BINARY_SCALE + ) + extra_parry_value += Int( + self.vitality * self.vitality_to_parry_value / BINARY_SCALE + ) return extra_parry_value @property def parry_value(self): - return Int(self.parry_value_base * (1 + self.parry_value_gain / BINARY_SCALE)) + self.extra_parry_value + return ( + Int(self.parry_value_base * (1 + self.parry_value_gain / BINARY_SCALE)) + + self.extra_parry_value + ) class Therapy(Major): @@ -1088,6 +1261,8 @@ class Therapy(Major): spirit_to_therapy: int = 0 + therapy_power_base: int = 0 + @property def extra_therapy(self): return Int(self.spirit * self.spirit_to_therapy / BINARY_SCALE) @@ -1125,8 +1300,7 @@ def max_life(self): return Int(self.final_max_life * (1 + self.max_life_final_gain / BINARY_SCALE)) -class Mana(Major): - ... +class Mana(Major): ... class DecriticalPower: @@ -1136,7 +1310,9 @@ class DecriticalPower: @property def final_decritical_power(self): - return Int(self.decritical_power_base * (1 + self.decritical_power_gain / BINARY_SCALE)) + return Int( + self.decritical_power_base * (1 + self.decritical_power_gain / BINARY_SCALE) + ) @property def decritical_power_percent(self): @@ -1145,7 +1321,9 @@ def decritical_power_percent(self): @property def decritical_power(self): - return self.decritical_power_percent + self.decritical_power_rate / DECIMAL_SCALE + return ( + self.decritical_power_percent + self.decritical_power_rate / DECIMAL_SCALE + ) class Toughness: @@ -1213,8 +1391,25 @@ def resist_critical_strike(self): class BaseAttribute( - AttackPower, CriticalStrike, Overcome, CriticalPower, Shield, DamageBase, DamageCof, - WeaponDamage, Haste, Surplus, Strain, Dodge, Parry, Therapy, Life, Mana, DecriticalPower, Toughness, Other + AttackPower, + CriticalStrike, + Overcome, + CriticalPower, + Shield, + DamageBase, + DamageCof, + WeaponDamage, + Haste, + Surplus, + Strain, + Dodge, + Parry, + Therapy, + Life, + Mana, + DecriticalPower, + Toughness, + Other, ): level: int = 0 diff --git a/extra/export.py b/extra/export.py index 488e5f0..65c4e8a 100644 --- a/extra/export.py +++ b/extra/export.py @@ -1,7 +1,10 @@ +import copy import json +import luadata from extra.attribute import Attribute from extra.gear import Gears +from extra.gear import STONES_by_enchant def main(info: dict): @@ -15,5 +18,34 @@ def main(info: dict): return None -if __name__ == '__main__': +def convert2jx3api(equips: list[dict]): + result = [] + for e in equips: + if e.get("nPos") in {1}: + continue + data = copy.copy(e) + data["aSlotItem"] = [[-1, x] for x in e.get("aDiamondEnchant", [])] + color_stone = e.get("dwItemFEAEnchantID") or 0 + if color_stone: + color_stone = STONES_by_enchant.get(color_stone) + color_stone = color_stone and color_stone.get("item_id") or 0 + color_stone = {"0": [-1, color_stone]} + data["ColorInfo"] = color_stone + result.append(data) + return result + + +def run_by_plugin_data(data: str): + import base64 + import zlib + + decoded_data = base64.urlsafe_b64decode(data + "=" * (-len(data) % 4)) + decompressed_data = zlib.decompress(decoded_data).decode("utf-8") + equips = luadata.unserialize(decompressed_data, encoding="utf-8", multival=False) + equips = convert2jx3api(equips) + attribute = main({"equip_data": equips}) + return attribute + + +if __name__ == "__main__": main(json.load(open("", encoding="utf-8"))) diff --git a/extra/gear.py b/extra/gear.py index 7f79177..9369252 100644 --- a/extra/gear.py +++ b/extra/gear.py @@ -6,13 +6,12 @@ ARMORS = json.load(open("assets/json/armors.json", encoding="utf-8")) TRINKETS = json.load(open("assets/json/trinkets.json", encoding="utf-8")) WEAPONS = json.load(open("assets/json/weapons.json", encoding="utf-8")) -EQUIPMENTS = { - 6: WEAPONS, - 7: ARMORS, - 8: TRINKETS -} +EQUIPMENTS = {6: WEAPONS, 7: ARMORS, 8: TRINKETS} ENCHANTS = json.load(open("assets/json/enchants.json", encoding="utf-8")) STONES = json.load(open("assets/json/stones.json", encoding="utf-8")) +STONES_by_enchant = { + STONES[x].get("enchant_id"): STONES[x] | {"item_id": x} for x in STONES +} SLOT_MAPPING = { **{24442 + i: i + 1 for i in range(8)}, @@ -20,16 +19,16 @@ } FLOAT_ATTRS = { "atMeleeWeaponDamageBase": "atMeleeWeaponDamageRand", - "atRangeWeaponDamageBase": "atRangeWeaponDamageRand" + "atRangeWeaponDamageBase": "atRangeWeaponDamageRand", } BINARY_ATTRS = ["atMeleeWeaponAttackSpeedBase", "atRangeWeaponAttackSpeedBase"] STONE_POSITIONS = ["primary_weapon"] def is_attribute(attr): - if not attr['attr_type']: + if not attr["attr_type"]: return False - if attr['attr_type'] in ['recipe', 'event']: + if attr["attr_type"] in ["recipe", "event"]: return False return True @@ -82,26 +81,26 @@ def base_attributes(self): for attr in self.base: if not is_attribute(attr): continue - attributes[attr['attr_type']] += int(attr['value']) + attributes[attr["attr_type"]] += int(attr["value"]) return attributes @property def base_desc(self): desc_list = [] for attr in self.base: - if float_attr := FLOAT_ATTRS.get(attr['attr']): - min_value = int(attr['value']) + if float_attr := FLOAT_ATTRS.get(attr["attr"]): + min_value = int(attr["value"]) max_value = min_value for sub_attr in self.base: - if sub_attr['attr'] == float_attr: - max_value += int(sub_attr['value']) + if sub_attr["attr"] == float_attr: + max_value += int(sub_attr["value"]) break - desc_list.append(attr['desc'].format(f"{min_value} - {max_value}")) - elif attr['attr'] in BINARY_ATTRS: - value = round(int(attr['value']) / FRAME_PER_SECOND, 1) - desc_list.append(attr['desc'].format(value)) - elif attr['desc']: - desc_list.append(attr['desc'].format(int(attr['value']))) + desc_list.append(attr["desc"].format(f"{min_value} - {max_value}")) + elif attr["attr"] in BINARY_ATTRS: + value = round(int(attr["value"]) / FRAME_PER_SECOND, 1) + desc_list.append(attr["desc"].format(value)) + elif attr["desc"]: + desc_list.append(attr["desc"].format(int(attr["value"]))) return desc_list @property @@ -111,11 +110,11 @@ def magic_attributes(self): if not is_attribute(attr): continue elif not self.strength_level: - value = int(attr['value']) + value = int(attr["value"]) else: - value = int(attr['value']) + value = int(attr["value"]) value += ROUND(value * STRENGTH_COF(self.strength_level)) - attributes[attr['attr_type']] += value + attributes[attr["attr_type"]] += value return attributes @property @@ -123,14 +122,14 @@ def magic_desc(self): desc_list = [] for attr in self.magic: if self.strength_level: - if attr['attr_type'] in ['recipe', 'event']: - desc_list.append(attr['desc']) + if attr["attr_type"] in ["recipe", "event"]: + desc_list.append(attr["desc"]) else: - value = int(attr['value']) + value = int(attr["value"]) extra_value = ROUND(value * STRENGTH_COF(self.strength_level)) - desc_list.append(attr['desc'].format(f"{value}(+{extra_value})")) + desc_list.append(attr["desc"].format(f"{value}(+{extra_value})")) else: - desc_list.append(attr['desc'].format(attr['value'])) + desc_list.append(attr["desc"].format(attr["value"])) return desc_list @property @@ -139,18 +138,18 @@ def embed_attributes(self): for attr, embed_level in zip(self.embed, self.embed_levels): if not is_attribute(attr): continue - value = int(attr['value']) + value = int(attr["value"]) value = int(value * EMBED_COF(embed_level)) - attributes[attr['attr_type']] += value + attributes[attr["attr_type"]] += value return attributes @property def embed_desc(self): desc_list = [] for attr, embed_level in zip(self.embed, self.embed_levels): - value = int(attr['value']) + value = int(attr["value"]) value = int(value * EMBED_COF(embed_level)) - desc_list.append(attr['desc'].format(value)) + desc_list.append(attr["desc"].format(value)) return desc_list @property @@ -186,7 +185,7 @@ def content(self): for attr in self.attributes: if not is_attribute(attr): continue - attributes[attr['attr_type']] += int(attr['value']) + attributes[attr["attr_type"]] += int(attr["value"]) return attributes @@ -199,7 +198,9 @@ class Stone: attributes: list[dict] def __init__(self, item_id): - for k, v in STONES.get(str(item_id), {}).items(): + stone = STONES.get(str(item_id), {}) + stone = stone or STONES_by_enchant.get(item_id, {}) + for k, v in stone.items(): setattr(self, k, v) def __bool__(self): @@ -211,11 +212,19 @@ def content(self): for attr in self.attributes: if not is_attribute(attr): continue - attributes[attr['attr_type']] += int(attr['value']) + attributes[attr["attr_type"]] += int(attr["value"]) return attributes class Gear: + @classmethod + def get_tabid_from_npos(cls, nPos: int): + if nPos in {0, 1, 2}: + return 6 + if nPos in {4, 5, 6, 7}: + return 8 + return 7 + equipment: Equipment temporary_enchant: Enchant @@ -224,14 +233,18 @@ class Gear: stone: Stone def __init__(self, equip_data: dict): - tab_id, equipment_id = equip_data['dwTabType'], equip_data['dwTabIndex'] - strength_level = equip_data['nStrengthLevel'] - embed_levels = [SLOT_MAPPING.get(slot, 0) for _, slot in equip_data['aSlotItem']] + tab_id, equipment_id = equip_data.get("dwTabType"), equip_data["dwTabIndex"] + if not tab_id: + tab_id = self.get_tabid_from_npos(equip_data.get("nPos")) + strength_level = equip_data["nStrengthLevel"] + embed_levels = [ + SLOT_MAPPING.get(slot, 0) for _, slot in equip_data["aSlotItem"] + ] self.equipment = Equipment(tab_id, equipment_id, strength_level, embed_levels) - self.temporary_enchant = Enchant(equip_data['dwTemporaryEnchantID']) - self.permanent_enchant = Enchant(equip_data['dwPermanentEnchantID']) + self.temporary_enchant = Enchant(equip_data["dwTemporaryEnchantID"]) + self.permanent_enchant = Enchant(equip_data["dwPermanentEnchantID"]) _, stone_id = equip_data["ColorInfo"]["0"] - self.stone = Stone(stone_id) + self.stone = Stone(stone_id) if stone_id else None def __bool__(self): return bool(self.equipment) @@ -261,7 +274,7 @@ class Gears: def __init__(self, info: dict): self.gears = [] - for equip_data in info['equip_data']: + for equip_data in info["equip_data"]: if gear := Gear(equip_data): self.gears.append(gear) @@ -280,9 +293,9 @@ def content(self): for need_count, attrs in set_attrs.items(): if count >= need_count: for attr in attrs: - if not attr['attr_type']: + if not attr["attr_type"]: continue - set_attributes[attr['attr']] += int(attr['value']) + set_attributes[attr["attr"]] += int(attr["value"]) attributes += set_attributes return attributes @@ -292,4 +305,4 @@ def kungfu_info(self): for gear in self.gears: if gear.is_primary_weapon: return gear.equipment.school, gear.equipment.kind - return None \ No newline at end of file + return None diff --git a/requirements.txt b/requirements.txt index 6872985..81da222 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ pyside6 pandas tqdm +luadata \ No newline at end of file diff --git a/test_plugindata.py b/test_plugindata.py new file mode 100644 index 0000000..f71fc20 --- /dev/null +++ b/test_plugindata.py @@ -0,0 +1,5 @@ +from extra.export import run_by_plugin_data +# 陈南乔pvphps = 'eJzNlk1u2zAQhS_EAsN_cqFFAaeAgaZIkVyAjonGqEUbqtzEMHz3UIqbSrSpUGLQZqMFOZLme284nMPB3daVdT_qh6_2t10XAvkFc__z264sMFo-3pnF7W4xd0v7VHzCyM12lVms1qt6X1DF4CXibr-1hUTu-860O8wvz2tbfrn6fOXuH4yr57MCkLvZ_Gr3_CsvX8QgMEhkZitTbtzyFFwcBCEMNY9jE23L7aYy1f7vt7AAoH7rxlalcdbVnS2uwP_q2jydgfm1IP0jyuBnzY9G89M-vwLGp_ATIiP8AnQSf5N-Fj-lYgI_Jn0BpIaJAvCoAJKnCNDknyUAYVMKQAUHAIiYwM-1jvH7A6BS-Jv0s_gZJRP4MYQFoPR4ASBqPkmrfp97Fvw08zEO3ec0Co_lgPsi6j5Pqv5s97v0Ko2ed-EZEyJi_FjPMcMpyP-cVwe8OnLVjebV4kPyij6vJBc6-2hWxv4bKx9glT1WTtWFc_w-rOp9WYOxRbxhLZW-PbfEvb7NCCN4oG1P6d1cqiSv_0wubUPN0iIYYd7S4mR9b4JhFOuIECPxBQGdgn95boEutdbD3K8BITYewg5GV8gt-EsXNZzdU97r4_NMAGlK' +陈南乔pvedps = 'eJzN1M1qAyEQB_AX8qCj68fBQyEpLJQQaF_AZqUprW7Z2C-WfffStLRR9jBbKuTiQWT88Z_RcYzb_mAp6V5v3G0bO_9mudbKkHidBh_v0v7Kv_hHK4lb3bvQx24dd3sXkx0lgCA_y_RZwoenfnDD-_eZdnWsvPVDcNHHlG-3yYfL9cXvJlf6eK_bPWyeg2UT-dJBpjOgJVK3zMQka9Sci86h-CmKUaEpW5LZP8Q1yxIlS2LDqspqTlkCjGpqtVDgUapANZgOLgcZNEgWIIl5hjVBupwmBucwTSbLiVNU4_42TYBGMZqHxTXocwiLsaKJii_63au5IHdJabCfQh3X9AHf1nOq' +result = run_by_plugin_data(陈南乔pvedps) +pass \ No newline at end of file