Spaces:
Runtime error
Runtime error
04.22 commit
Browse files- .github/workflows/pyinstaller-app.yml +92 -0
- base/buff.py +19 -49
- base/constant.py +6 -6
- base/skill.py +26 -5
- parse_new_school.py +1 -1
- schools/bei_ao_jue/skills.py +3 -3
- schools/shan_hai_xin_jue/__init__.py +6 -0
- schools/shan_hai_xin_jue/attribute.py +33 -0
- schools/shan_hai_xin_jue/buffs.py +3 -1
- schools/shan_hai_xin_jue/skills.py +12 -5
- schools/shan_hai_xin_jue/talents.py +83 -0
- utils/analyzer.py +18 -16
- utils/parser.py +80 -11
.github/workflows/pyinstaller-app.yml
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
|
| 2 |
+
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
|
| 3 |
+
|
| 4 |
+
name: Pyinstaller Packaging
|
| 5 |
+
|
| 6 |
+
on:
|
| 7 |
+
push:
|
| 8 |
+
branches: [ "master" ]
|
| 9 |
+
pull_request:
|
| 10 |
+
branches: [ "master" ]
|
| 11 |
+
|
| 12 |
+
permissions:
|
| 13 |
+
contents: write
|
| 14 |
+
|
| 15 |
+
jobs:
|
| 16 |
+
setup:
|
| 17 |
+
runs-on: ubuntu-latest
|
| 18 |
+
outputs:
|
| 19 |
+
PACKAGE_PREFIX: ${{ steps.get-package_prefix.outputs.PACKAGE_PREFIX }}
|
| 20 |
+
TAG_NAME: ${{ steps.get-package_prefix.outputs.TAG_NAME }}
|
| 21 |
+
HEAD_SHA_SHORT: ${{ steps.get-package_prefix.outputs.HEAD_SHA_SHORT }}
|
| 22 |
+
steps:
|
| 23 |
+
- uses: actions/checkout@v2
|
| 24 |
+
with:
|
| 25 |
+
fetch-depth: '0'
|
| 26 |
+
- name: get-package_prefix
|
| 27 |
+
id: get-package_prefix
|
| 28 |
+
run: |
|
| 29 |
+
LIB_NAME=Formulator
|
| 30 |
+
TAG_NAME=pre
|
| 31 |
+
HEAD_SHA_SHORT=$(git rev-parse --short HEAD)
|
| 32 |
+
echo "::set-output name=PACKAGE_PREFIX::${LIB_NAME}_${TAG_NAME}"
|
| 33 |
+
echo "::set-output name=TAG_NAME::${TAG_NAME}"
|
| 34 |
+
echo "::set-output name=HEAD_SHA_SHORT::${HEAD_SHA_SHORT}"
|
| 35 |
+
|
| 36 |
+
release:
|
| 37 |
+
needs: [setup]
|
| 38 |
+
runs-on: ubuntu-latest
|
| 39 |
+
outputs:
|
| 40 |
+
Up_Url: ${{ steps.create_release.outputs.upload_url }}
|
| 41 |
+
steps:
|
| 42 |
+
- name: create_release
|
| 43 |
+
id: create_release
|
| 44 |
+
uses: actions/create-release@v1
|
| 45 |
+
env:
|
| 46 |
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
| 47 |
+
with:
|
| 48 |
+
tag_name: v0.0
|
| 49 |
+
release_name: Pre Release
|
| 50 |
+
draft: true
|
| 51 |
+
prerelease: true
|
| 52 |
+
|
| 53 |
+
windows:
|
| 54 |
+
needs: [setup, release]
|
| 55 |
+
runs-on: windows-latest
|
| 56 |
+
env:
|
| 57 |
+
PACKAGENAME: ${{ needs.setup.outputs.PACKAGE_PREFIX }}_windows_x64
|
| 58 |
+
steps:
|
| 59 |
+
- uses: actions/checkout@v4
|
| 60 |
+
- name: Set up Python 3.11
|
| 61 |
+
uses: actions/setup-python@v5
|
| 62 |
+
with:
|
| 63 |
+
python-version: "3.11"
|
| 64 |
+
|
| 65 |
+
- name: Install dependencies
|
| 66 |
+
run: |
|
| 67 |
+
python -m pip install --upgrade pip
|
| 68 |
+
pip install pyinstaller
|
| 69 |
+
pip install pyside6
|
| 70 |
+
- name: Build
|
| 71 |
+
run: |
|
| 72 |
+
mv qt/assets/icon.ico ./
|
| 73 |
+
pyinstaller -F -w -i icon.ico app.py
|
| 74 |
+
mv dist formulator
|
| 75 |
+
mv qt/assets formulator/assets
|
| 76 |
+
mkdir ${{ env.PACKAGENAME }}
|
| 77 |
+
mv formulator ${{ env.PACKAGENAME }}
|
| 78 |
+
7z a -t7z -r "$($Env:PACKAGENAME + '.7z')" "formulator"
|
| 79 |
+
- name: Upload
|
| 80 |
+
uses: actions/upload-artifact@v4
|
| 81 |
+
with:
|
| 82 |
+
name: formulator
|
| 83 |
+
path: ${{ env.PACKAGENAME }}
|
| 84 |
+
- name: upload-win
|
| 85 |
+
uses: actions/upload-release-asset@v1
|
| 86 |
+
env:
|
| 87 |
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
| 88 |
+
with:
|
| 89 |
+
upload_url: ${{ needs.release.outputs.Up_Url }}
|
| 90 |
+
asset_path: ${{ env.PACKAGENAME }}.7z
|
| 91 |
+
asset_name: ${{ env.PACKAGENAME }}.7z
|
| 92 |
+
asset_content_type: application/zip
|
base/buff.py
CHANGED
|
@@ -20,6 +20,7 @@ class Buff:
|
|
| 20 |
gain_attributes: ATTR_DICT = None
|
| 21 |
|
| 22 |
SNAPSHOT_ATTRS = ["attack_power", "critical_strike", "critical_power", "strain", "damage_addition"]
|
|
|
|
| 23 |
|
| 24 |
def __post_init__(self):
|
| 25 |
if self.gain_skills is None:
|
|
@@ -37,47 +38,24 @@ class Buff:
|
|
| 37 |
else:
|
| 38 |
return value
|
| 39 |
|
| 40 |
-
def add(self, attribute: Attribute, skill: Skill, snapshot=None):
|
| 41 |
-
if snapshot is None:
|
| 42 |
-
self.add_all(attribute, skill)
|
| 43 |
-
elif snapshot:
|
| 44 |
-
self.add_snapshot(attribute, skill)
|
| 45 |
-
else:
|
| 46 |
-
self.add_current(attribute, skill)
|
| 47 |
-
|
| 48 |
def add_all(self, attribute: Attribute, skill: Skill):
|
| 49 |
for attr, value in self.gain_attributes.items():
|
| 50 |
setattr(attribute, attr, getattr(attribute, attr) + self.level_value(value) * self.buff_stack)
|
| 51 |
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 52 |
setattr(skill, attr, getattr(skill, attr) + self.level_value(value) * self.buff_stack)
|
| 53 |
|
| 54 |
-
def
|
| 55 |
for attr, value in self.gain_attributes.items():
|
| 56 |
-
if
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
if all(snapshot_attr not in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 61 |
-
continue
|
| 62 |
-
setattr(skill, attr, getattr(skill, attr) + self.level_value(value) * self.buff_stack)
|
| 63 |
|
| 64 |
-
def add_current(self, attribute: Attribute, skill: Skill):
|
| 65 |
-
for attr, value in self.gain_attributes.items():
|
| 66 |
-
if any(snapshot_attr in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 67 |
-
continue
|
| 68 |
-
setattr(attribute, attr, getattr(attribute, attr) + self.level_value(value) * self.buff_stack)
|
| 69 |
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 70 |
-
if any(snapshot_attr in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
def sub(self, attribute: Attribute, skill: Skill, snapshot=None):
|
| 75 |
-
if snapshot is None:
|
| 76 |
-
self.sub_all(attribute, skill)
|
| 77 |
-
elif snapshot:
|
| 78 |
-
self.sub_snapshot(attribute, skill)
|
| 79 |
-
else:
|
| 80 |
-
self.sub_current(attribute, skill)
|
| 81 |
|
| 82 |
def sub_all(self, attribute: Attribute, skill: Skill):
|
| 83 |
for attr, value in self.gain_attributes.items():
|
|
@@ -85,22 +63,14 @@ class Buff:
|
|
| 85 |
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 86 |
setattr(skill, attr, getattr(skill, attr) - self.level_value(value) * self.buff_stack)
|
| 87 |
|
| 88 |
-
def
|
| 89 |
-
for attr, value in self.gain_attributes.items():
|
| 90 |
-
if all(snapshot_attr not in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 91 |
-
continue
|
| 92 |
-
setattr(attribute, attr, getattr(attribute, attr) - self.level_value(value) * self.buff_stack)
|
| 93 |
-
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 94 |
-
if all(snapshot_attr not in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 95 |
-
continue
|
| 96 |
-
setattr(skill, attr, getattr(skill, attr) - self.level_value(value) * self.buff_stack)
|
| 97 |
-
|
| 98 |
-
def sub_current(self, attribute: Attribute, skill: Skill):
|
| 99 |
for attr, value in self.gain_attributes.items():
|
| 100 |
-
if any(snapshot_attr in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 101 |
-
|
| 102 |
-
|
|
|
|
| 103 |
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 104 |
-
if any(snapshot_attr in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 105 |
-
|
| 106 |
-
|
|
|
|
|
|
| 20 |
gain_attributes: ATTR_DICT = None
|
| 21 |
|
| 22 |
SNAPSHOT_ATTRS = ["attack_power", "critical_strike", "critical_power", "strain", "damage_addition"]
|
| 23 |
+
PET_ATTRS = ["attack_power", "critical_power", "overcome", "strain"]
|
| 24 |
|
| 25 |
def __post_init__(self):
|
| 26 |
if self.gain_skills is None:
|
|
|
|
| 38 |
else:
|
| 39 |
return value
|
| 40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
def add_all(self, attribute: Attribute, skill: Skill):
|
| 42 |
for attr, value in self.gain_attributes.items():
|
| 43 |
setattr(attribute, attr, getattr(attribute, attr) + self.level_value(value) * self.buff_stack)
|
| 44 |
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 45 |
setattr(skill, attr, getattr(skill, attr) + self.level_value(value) * self.buff_stack)
|
| 46 |
|
| 47 |
+
def add_dot(self, attribute: Attribute, skill: Skill, snapshot: bool = True):
|
| 48 |
for attr, value in self.gain_attributes.items():
|
| 49 |
+
if snapshot and any(snapshot_attr in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 50 |
+
setattr(attribute, attr, getattr(attribute, attr) + self.level_value(value) * self.buff_stack)
|
| 51 |
+
elif not snapshot and all(snapshot_attr not in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 52 |
+
setattr(attribute, attr, getattr(attribute, attr) + self.level_value(value) * self.buff_stack)
|
|
|
|
|
|
|
|
|
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 55 |
+
if snapshot and any(snapshot_attr in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 56 |
+
setattr(skill, attr, getattr(skill, attr) + self.level_value(value) * self.buff_stack)
|
| 57 |
+
elif not snapshot and all(snapshot_attr not in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 58 |
+
setattr(skill, attr, getattr(skill, attr) + self.level_value(value) * self.buff_stack)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
def sub_all(self, attribute: Attribute, skill: Skill):
|
| 61 |
for attr, value in self.gain_attributes.items():
|
|
|
|
| 63 |
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 64 |
setattr(skill, attr, getattr(skill, attr) - self.level_value(value) * self.buff_stack)
|
| 65 |
|
| 66 |
+
def sub_dot(self, attribute: Attribute, skill: Skill, snapshot: bool = True):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
for attr, value in self.gain_attributes.items():
|
| 68 |
+
if snapshot and any(snapshot_attr in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 69 |
+
setattr(attribute, attr, getattr(attribute, attr) - self.level_value(value) * self.buff_stack)
|
| 70 |
+
elif not snapshot and all(snapshot_attr not in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 71 |
+
setattr(attribute, attr, getattr(attribute, attr) - self.level_value(value) * self.buff_stack)
|
| 72 |
for attr, value in self.gain_skills.get(skill.skill_id, {}).items():
|
| 73 |
+
if snapshot and any(snapshot_attr in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 74 |
+
setattr(skill, attr, getattr(skill, attr) - self.level_value(value) * self.buff_stack)
|
| 75 |
+
elif not snapshot and all(snapshot_attr not in attr for snapshot_attr in self.SNAPSHOT_ATTRS):
|
| 76 |
+
setattr(skill, attr, getattr(skill, attr) - self.level_value(value) * self.buff_stack)
|
base/constant.py
CHANGED
|
@@ -33,12 +33,12 @@ SHIELD_BASE_MAP = {
|
|
| 33 |
MAJOR_BASE = 41
|
| 34 |
BASE_CRITICAL_POWER = 1.75
|
| 35 |
|
| 36 |
-
AGILITY_TO_CRITICAL_STRIKE =
|
| 37 |
-
STRENGTH_TO_ATTACK_POWER =
|
| 38 |
-
STRENGTH_TO_OVERCOME =
|
| 39 |
-
SPIRIT_TO_CRITICAL_STRIKE =
|
| 40 |
-
SPUNK_TO_ATTACK_POWER =
|
| 41 |
-
SPUNK_TO_OVERCOME =
|
| 42 |
|
| 43 |
DELTA_SCALE = 1
|
| 44 |
MAJOR_DELTA = 198
|
|
|
|
| 33 |
MAJOR_BASE = 41
|
| 34 |
BASE_CRITICAL_POWER = 1.75
|
| 35 |
|
| 36 |
+
AGILITY_TO_CRITICAL_STRIKE = 0.64
|
| 37 |
+
STRENGTH_TO_ATTACK_POWER = 0.15
|
| 38 |
+
STRENGTH_TO_OVERCOME = 0.3
|
| 39 |
+
SPIRIT_TO_CRITICAL_STRIKE = 0.64
|
| 40 |
+
SPUNK_TO_ATTACK_POWER = 0.18
|
| 41 |
+
SPUNK_TO_OVERCOME = 0.3
|
| 42 |
|
| 43 |
DELTA_SCALE = 1
|
| 44 |
MAJOR_DELTA = 198
|
base/skill.py
CHANGED
|
@@ -34,6 +34,7 @@ class Skill:
|
|
| 34 |
weapon_damage_cof_gain: float = 0.
|
| 35 |
|
| 36 |
skill_damage_addition: int = 0
|
|
|
|
| 37 |
_skill_shield_gain: Union[List[int], int] = 0
|
| 38 |
skill_critical_strike: int = 0
|
| 39 |
skill_critical_power: int = 0
|
|
@@ -142,7 +143,7 @@ class Skill:
|
|
| 142 |
damage = strain_result(damage, attribute.strain)
|
| 143 |
critical_damage = strain_result(critical_damage, attribute.strain)
|
| 144 |
damage = pve_addition_result(damage, attribute.pve_addition)
|
| 145 |
-
critical_damage = pve_addition_result(critical_damage, attribute.pve_addition)
|
| 146 |
damage = vulnerable_result(damage, attribute.vulnerable)
|
| 147 |
critical_damage = vulnerable_result(critical_damage, attribute.vulnerable)
|
| 148 |
critical_strike = min(1, attribute.critical_strike + self.skill_critical_strike_gain)
|
|
@@ -152,7 +153,27 @@ class Skill:
|
|
| 152 |
return damage, critical_damage, expected_damage, critical_strike
|
| 153 |
|
| 154 |
|
| 155 |
-
class
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
@property
|
| 157 |
def attack_power_cof(self):
|
| 158 |
return PHYSICAL_ATTACK_POWER_COF(super().attack_power_cof + self.interval)
|
|
@@ -162,13 +183,13 @@ class PhysicalDamage(Skill):
|
|
| 162 |
self._attack_power_cof = attack_power_cof
|
| 163 |
|
| 164 |
|
| 165 |
-
class MagicalDamage(
|
| 166 |
@property
|
| 167 |
def attack_power_cof(self):
|
| 168 |
return MAGICAL_ATTACK_POWER_COF(super().attack_power_cof + self.interval)
|
| 169 |
|
| 170 |
|
| 171 |
-
class PhysicalDotDamage(
|
| 172 |
@property
|
| 173 |
def attack_power_cof(self):
|
| 174 |
return PHYSICAL_DOT_ATTACK_POWER_COF(super().attack_power_cof, self.interval)
|
|
@@ -178,7 +199,7 @@ class PhysicalDotDamage(Skill):
|
|
| 178 |
self._attack_power_cof = attack_power_cof
|
| 179 |
|
| 180 |
|
| 181 |
-
class MagicalDotDamage(
|
| 182 |
@property
|
| 183 |
def attack_power_cof(self):
|
| 184 |
return MAGICAL_DOT_ATTACK_POWER_COF(super().attack_power_cof, self.interval)
|
|
|
|
| 34 |
weapon_damage_cof_gain: float = 0.
|
| 35 |
|
| 36 |
skill_damage_addition: int = 0
|
| 37 |
+
skill_pve_addition: int = 0
|
| 38 |
_skill_shield_gain: Union[List[int], int] = 0
|
| 39 |
skill_critical_strike: int = 0
|
| 40 |
skill_critical_power: int = 0
|
|
|
|
| 143 |
damage = strain_result(damage, attribute.strain)
|
| 144 |
critical_damage = strain_result(critical_damage, attribute.strain)
|
| 145 |
damage = pve_addition_result(damage, attribute.pve_addition)
|
| 146 |
+
critical_damage = pve_addition_result(critical_damage, attribute.pve_addition + self.skill_pve_addition)
|
| 147 |
damage = vulnerable_result(damage, attribute.vulnerable)
|
| 148 |
critical_damage = vulnerable_result(critical_damage, attribute.vulnerable)
|
| 149 |
critical_strike = min(1, attribute.critical_strike + self.skill_critical_strike_gain)
|
|
|
|
| 153 |
return damage, critical_damage, expected_damage, critical_strike
|
| 154 |
|
| 155 |
|
| 156 |
+
class DotSkill(Skill):
|
| 157 |
+
pass
|
| 158 |
+
|
| 159 |
+
|
| 160 |
+
class DotConsumeSkill(Skill):
|
| 161 |
+
pass
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
class Damage(Skill):
|
| 165 |
+
pass
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
class DotDamage(Damage):
|
| 169 |
+
pass
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
class PetDamage(Damage):
|
| 173 |
+
pass
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
class PhysicalDamage(Damage):
|
| 177 |
@property
|
| 178 |
def attack_power_cof(self):
|
| 179 |
return PHYSICAL_ATTACK_POWER_COF(super().attack_power_cof + self.interval)
|
|
|
|
| 183 |
self._attack_power_cof = attack_power_cof
|
| 184 |
|
| 185 |
|
| 186 |
+
class MagicalDamage(Damage):
|
| 187 |
@property
|
| 188 |
def attack_power_cof(self):
|
| 189 |
return MAGICAL_ATTACK_POWER_COF(super().attack_power_cof + self.interval)
|
| 190 |
|
| 191 |
|
| 192 |
+
class PhysicalDotDamage(DotDamage):
|
| 193 |
@property
|
| 194 |
def attack_power_cof(self):
|
| 195 |
return PHYSICAL_DOT_ATTACK_POWER_COF(super().attack_power_cof, self.interval)
|
|
|
|
| 199 |
self._attack_power_cof = attack_power_cof
|
| 200 |
|
| 201 |
|
| 202 |
+
class MagicalDotDamage(DotDamage):
|
| 203 |
@property
|
| 204 |
def attack_power_cof(self):
|
| 205 |
return MAGICAL_DOT_ATTACK_POWER_COF(super().attack_power_cof, self.interval)
|
parse_new_school.py
CHANGED
|
@@ -58,4 +58,4 @@ class Parser:
|
|
| 58 |
|
| 59 |
if __name__ == '__main__':
|
| 60 |
parser = Parser()
|
| 61 |
-
parser("
|
|
|
|
| 58 |
|
| 59 |
if __name__ == '__main__':
|
| 60 |
parser = Parser()
|
| 61 |
+
parser("new.jcl")
|
schools/bei_ao_jue/skills.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
from typing import Dict
|
| 2 |
|
| 3 |
-
from base.skill import PhysicalDamage, PhysicalDotDamage
|
| 4 |
from general.skills import GENERAL_SKILLS
|
| 5 |
|
| 6 |
SKILLS: Dict[int, Skill | dict] = {
|
|
@@ -60,7 +60,7 @@ SKILLS: Dict[int, Skill | dict] = {
|
|
| 60 |
"interval": 48
|
| 61 |
},
|
| 62 |
17060: {
|
| 63 |
-
"skill_class":
|
| 64 |
"skill_name": "闹须弥",
|
| 65 |
"bind_skill": 11447,
|
| 66 |
"tick": 8
|
|
@@ -367,7 +367,7 @@ SKILLS: Dict[int, Skill | dict] = {
|
|
| 367 |
|
| 368 |
},
|
| 369 |
26934: {
|
| 370 |
-
"skill_class":
|
| 371 |
"skill_name": "背水沉舟",
|
| 372 |
"bind_skill": 19555,
|
| 373 |
"max_stack": 3,
|
|
|
|
| 1 |
from typing import Dict
|
| 2 |
|
| 3 |
+
from base.skill import Skill, DotSkill, PhysicalDamage, PhysicalDotDamage
|
| 4 |
from general.skills import GENERAL_SKILLS
|
| 5 |
|
| 6 |
SKILLS: Dict[int, Skill | dict] = {
|
|
|
|
| 60 |
"interval": 48
|
| 61 |
},
|
| 62 |
17060: {
|
| 63 |
+
"skill_class": DotSkill,
|
| 64 |
"skill_name": "闹须弥",
|
| 65 |
"bind_skill": 11447,
|
| 66 |
"tick": 8
|
|
|
|
| 367 |
|
| 368 |
},
|
| 369 |
26934: {
|
| 370 |
+
"skill_class": DotSkill,
|
| 371 |
"skill_name": "背水沉舟",
|
| 372 |
"bind_skill": 19555,
|
| 373 |
"max_stack": 3,
|
schools/shan_hai_xin_jue/__init__.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from schools.shan_hai_xin_jue.skills import SKILLS
|
| 2 |
+
from schools.shan_hai_xin_jue.buffs import BUFFS
|
| 3 |
+
from schools.shan_hai_xin_jue.talents import TALENT_GAINS, TALENTS, TALENT_DECODER, TALENT_ENCODER
|
| 4 |
+
# from schools.bei_ao_jue.recipes import RECIPE_GAINS, RECIPES
|
| 5 |
+
# from schools.shan_hai_xin_jue.gains import GAINS
|
| 6 |
+
from schools.shan_hai_xin_jue.attribute import ShanHaiXinJue
|
schools/shan_hai_xin_jue/attribute.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from base.attribute import PhysicalAttribute
|
| 2 |
+
from base.constant import *
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class ShanHaiXinJue(PhysicalAttribute):
|
| 6 |
+
AGILITY_TO_ATTACK_POWER = 1485 / BINARY_SCALE
|
| 7 |
+
AGILITY_TO_CRITICAL_STRIKE = 594 / BINARY_SCALE
|
| 8 |
+
|
| 9 |
+
def __init__(self):
|
| 10 |
+
super().__init__()
|
| 11 |
+
self.physical_attack_power_base += 3277
|
| 12 |
+
self.physical_critical_strike_base += 2929
|
| 13 |
+
self.pve_addition += 82
|
| 14 |
+
|
| 15 |
+
self.grad_attrs = {
|
| 16 |
+
"agility_base": MAJOR_DELTA,
|
| 17 |
+
"strength_base": MAJOR_DELTA,
|
| 18 |
+
"surplus": MINOR_DELTA,
|
| 19 |
+
"strain_base": MINOR_DELTA,
|
| 20 |
+
"physical_attack_power_base": PHYSICAL_DELTA,
|
| 21 |
+
"physical_critical_strike_base": MINOR_DELTA,
|
| 22 |
+
"physical_critical_power_base": MINOR_DELTA,
|
| 23 |
+
"physical_overcome_base": MINOR_DELTA,
|
| 24 |
+
"weapon_damage_base": WEAPON_DELTA
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
@property
|
| 28 |
+
def extra_physical_attack_power(self):
|
| 29 |
+
return int(self.agility * self.AGILITY_TO_ATTACK_POWER)
|
| 30 |
+
|
| 31 |
+
@property
|
| 32 |
+
def extra_physical_critical_strike(self):
|
| 33 |
+
return int(self.agility * self.AGILITY_TO_CRITICAL_STRIKE)
|
schools/shan_hai_xin_jue/buffs.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
|
|
|
|
|
| 1 |
from base.buff import Buff
|
| 2 |
from general.buffs import GENERAL_BUFFS
|
| 3 |
|
| 4 |
-
BUFFS = {
|
| 5 |
16025: {
|
| 6 |
"buff_name": "雷引",
|
| 7 |
"gain_attributes": {
|
|
|
|
| 1 |
+
from typing import Dict
|
| 2 |
+
|
| 3 |
from base.buff import Buff
|
| 4 |
from general.buffs import GENERAL_BUFFS
|
| 5 |
|
| 6 |
+
BUFFS: Dict[int, Buff | dict] = {
|
| 7 |
16025: {
|
| 8 |
"buff_name": "雷引",
|
| 9 |
"gain_attributes": {
|
schools/shan_hai_xin_jue/skills.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
| 1 |
from typing import Dict
|
| 2 |
|
| 3 |
-
from base.skill import PhysicalDamage, PhysicalDotDamage
|
| 4 |
from general.skills import GENERAL_SKILLS
|
| 5 |
|
| 6 |
SKILLS: Dict[int, Skill | dict] = {
|
| 7 |
-
|
| 8 |
"skill_class": PhysicalDamage,
|
| 9 |
"skill_name": "破",
|
| 10 |
"surplus_cof": 0
|
|
@@ -13,7 +13,8 @@ SKILLS: Dict[int, Skill | dict] = {
|
|
| 13 |
"skill_class": PhysicalDamage,
|
| 14 |
"skill_name": "风矢",
|
| 15 |
"attack_power_cof": 16,
|
| 16 |
-
"weapon_damage_cof": 1024
|
|
|
|
| 17 |
},
|
| 18 |
35866: {
|
| 19 |
"skill_class": PhysicalDamage,
|
|
@@ -63,12 +64,18 @@ SKILLS: Dict[int, Skill | dict] = {
|
|
| 63 |
"attack_power_cof": 0
|
| 64 |
},
|
| 65 |
26856: {
|
| 66 |
-
"skill_class":
|
| 67 |
"skill_name": "贯穿(DOT)",
|
| 68 |
"attack_power_cof": 0
|
| 69 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
35771: {
|
| 71 |
-
"skill_class":
|
| 72 |
"skill_name": "贯穿",
|
| 73 |
"bind_skill": 26856,
|
| 74 |
"max_stack": 6,
|
|
|
|
| 1 |
from typing import Dict
|
| 2 |
|
| 3 |
+
from base.skill import Skill, DotSkill, DotConsumeSkill, PhysicalDamage, PhysicalDotDamage
|
| 4 |
from general.skills import GENERAL_SKILLS
|
| 5 |
|
| 6 |
SKILLS: Dict[int, Skill | dict] = {
|
| 7 |
+
36177: {
|
| 8 |
"skill_class": PhysicalDamage,
|
| 9 |
"skill_name": "破",
|
| 10 |
"surplus_cof": 0
|
|
|
|
| 13 |
"skill_class": PhysicalDamage,
|
| 14 |
"skill_name": "风矢",
|
| 15 |
"attack_power_cof": 16,
|
| 16 |
+
"weapon_damage_cof": 1024,
|
| 17 |
+
"skill_damage_addition": 205
|
| 18 |
},
|
| 19 |
35866: {
|
| 20 |
"skill_class": PhysicalDamage,
|
|
|
|
| 64 |
"attack_power_cof": 0
|
| 65 |
},
|
| 66 |
26856: {
|
| 67 |
+
"skill_class": PhysicalDotDamage,
|
| 68 |
"skill_name": "贯穿(DOT)",
|
| 69 |
"attack_power_cof": 0
|
| 70 |
},
|
| 71 |
+
36165: {
|
| 72 |
+
"skill_class": DotConsumeSkill,
|
| 73 |
+
"skill_name": "贯穿",
|
| 74 |
+
"bind_skill": 26856,
|
| 75 |
+
"tick": 3
|
| 76 |
+
},
|
| 77 |
35771: {
|
| 78 |
+
"skill_class": DotSkill,
|
| 79 |
"skill_name": "贯穿",
|
| 80 |
"bind_skill": 26856,
|
| 81 |
"max_stack": 6,
|
schools/shan_hai_xin_jue/talents.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Dict
|
| 2 |
+
|
| 3 |
+
from base.attribute import Attribute
|
| 4 |
+
from base.gain import Gain
|
| 5 |
+
from base.skill import Skill
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class 彤弓(Gain):
|
| 9 |
+
def add_skills(self, skills: Dict[int, Skill]):
|
| 10 |
+
skills[35866].skill_critical_strike += 102
|
| 11 |
+
skills[35866].skill_critical_power += 102
|
| 12 |
+
|
| 13 |
+
def sub_skills(self, skills: Dict[int, Skill]):
|
| 14 |
+
skills[35866].skill_critical_strike -= 102
|
| 15 |
+
skills[35866].skill_critical_power -= 102
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class 素矰(Gain):
|
| 19 |
+
def add_skills(self, skills: Dict[int, Skill]):
|
| 20 |
+
skills[26856].attack_power_cof_gain += 0.05
|
| 21 |
+
|
| 22 |
+
def sub_skills(self, skills: Dict[int, Skill]):
|
| 23 |
+
skills[26856].attack_power_cof_gain -= 0.05
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class 桑柘(Gain):
|
| 27 |
+
def add_skills(self, skills: Dict[int, Skill]):
|
| 28 |
+
skills[35771].tick += 1
|
| 29 |
+
|
| 30 |
+
def sub_skills(self, skills: Dict[int, Skill]):
|
| 31 |
+
skills[35771].tick -= 1
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
class 卢令(Gain):
|
| 35 |
+
def add_attribute(self, attribute: Attribute):
|
| 36 |
+
attribute.agility_gain += 102
|
| 37 |
+
|
| 38 |
+
def sub_attribute(self, attribute: Attribute):
|
| 39 |
+
attribute.agility_gain -= 102
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class 贯侯(Gain):
|
| 43 |
+
def add_skills(self, skills: Dict[int, Skill]):
|
| 44 |
+
skills[26856].skill_pve_addition += 205
|
| 45 |
+
|
| 46 |
+
def sub_skills(self, skills: Dict[int, Skill]):
|
| 47 |
+
skills[26856].skill_pve_addition -= 205
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
TALENT_GAINS: Dict[int, Gain] = {
|
| 51 |
+
35715: 素矰("素矰"),
|
| 52 |
+
35714: 彤弓("彤弓"),
|
| 53 |
+
35718: Gain("棘矢"),
|
| 54 |
+
35719: Gain("孰湖"),
|
| 55 |
+
35721: Gain("襄尺"),
|
| 56 |
+
35725: Gain("长右"),
|
| 57 |
+
35729: Gain("鹿蜀"),
|
| 58 |
+
35736: 桑柘("桑柘"),
|
| 59 |
+
35737: Gain("于狩"),
|
| 60 |
+
35745: 卢令("卢令"),
|
| 61 |
+
35749: Gain("托月"),
|
| 62 |
+
35751: Gain("佩弦"),
|
| 63 |
+
35757: 贯侯("贯侯"),
|
| 64 |
+
35764: Gain("朝仪万汇"),
|
| 65 |
+
35761: Gain("朱厌")
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
TALENTS = [
|
| 69 |
+
[35715, 35714],
|
| 70 |
+
[35718, 35719],
|
| 71 |
+
[35721],
|
| 72 |
+
[35725],
|
| 73 |
+
[35729],
|
| 74 |
+
[35736],
|
| 75 |
+
[35737],
|
| 76 |
+
[35745],
|
| 77 |
+
[35749],
|
| 78 |
+
[35751],
|
| 79 |
+
[35757],
|
| 80 |
+
[35764, 35761]
|
| 81 |
+
]
|
| 82 |
+
TALENT_DECODER = {talent_id: talent.gain_name for talent_id, talent in TALENT_GAINS.items()}
|
| 83 |
+
TALENT_ENCODER = {v: k for k, v in TALENT_DECODER.items()}
|
utils/analyzer.py
CHANGED
|
@@ -3,7 +3,7 @@ from collections import defaultdict
|
|
| 3 |
from typing import Dict
|
| 4 |
|
| 5 |
from base.attribute import Attribute
|
| 6 |
-
from base.skill import Skill
|
| 7 |
from utils.parser import School
|
| 8 |
|
| 9 |
|
|
@@ -46,22 +46,22 @@ def add_buffs(current_buffs, snapshot_buffs, attribute: Attribute, skill: Skill)
|
|
| 46 |
if not snapshot_buffs:
|
| 47 |
for buff in current_buffs:
|
| 48 |
buff.add_all(attribute, skill)
|
| 49 |
-
|
| 50 |
for buff in snapshot_buffs:
|
| 51 |
-
buff.
|
| 52 |
for buff in current_buffs:
|
| 53 |
-
buff.
|
| 54 |
|
| 55 |
|
| 56 |
def sub_buffs(current_buffs, snapshot_buffs, attribute: Attribute, skill: Skill):
|
| 57 |
if not snapshot_buffs:
|
| 58 |
for buff in current_buffs:
|
| 59 |
buff.sub_all(attribute, skill)
|
| 60 |
-
|
| 61 |
for buff in snapshot_buffs:
|
| 62 |
-
buff.
|
| 63 |
for buff in current_buffs:
|
| 64 |
-
buff.
|
| 65 |
|
| 66 |
|
| 67 |
def concat_buffs(current_buffs, snapshot_buffs):
|
|
@@ -117,15 +117,17 @@ def analyze_details(record, duration: int, attribute: Attribute, school: School)
|
|
| 117 |
for attr, residual_damage in detail.gradients.items():
|
| 118 |
skill_total.gradients[attr] += residual_damage * len(timeline)
|
| 119 |
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
|
|
|
|
|
|
|
| 129 |
for attr, residual_damage in skill_total.gradients.items():
|
| 130 |
total.gradients[attr] += residual_damage
|
| 131 |
skill_total.gradients[attr] /= skill_total.count
|
|
|
|
| 3 |
from typing import Dict
|
| 4 |
|
| 5 |
from base.attribute import Attribute
|
| 6 |
+
from base.skill import Skill, DotDamage
|
| 7 |
from utils.parser import School
|
| 8 |
|
| 9 |
|
|
|
|
| 46 |
if not snapshot_buffs:
|
| 47 |
for buff in current_buffs:
|
| 48 |
buff.add_all(attribute, skill)
|
| 49 |
+
elif isinstance(skill, DotDamage):
|
| 50 |
for buff in snapshot_buffs:
|
| 51 |
+
buff.add_dot(attribute, skill, True)
|
| 52 |
for buff in current_buffs:
|
| 53 |
+
buff.add_dot(attribute, skill, False)
|
| 54 |
|
| 55 |
|
| 56 |
def sub_buffs(current_buffs, snapshot_buffs, attribute: Attribute, skill: Skill):
|
| 57 |
if not snapshot_buffs:
|
| 58 |
for buff in current_buffs:
|
| 59 |
buff.sub_all(attribute, skill)
|
| 60 |
+
elif isinstance(skill, DotDamage):
|
| 61 |
for buff in snapshot_buffs:
|
| 62 |
+
buff.sub_dot(attribute, skill, True)
|
| 63 |
for buff in current_buffs:
|
| 64 |
+
buff.sub_dot(attribute, skill, False)
|
| 65 |
|
| 66 |
|
| 67 |
def concat_buffs(current_buffs, snapshot_buffs):
|
|
|
|
| 117 |
for attr, residual_damage in detail.gradients.items():
|
| 118 |
skill_total.gradients[attr] += residual_damage * len(timeline)
|
| 119 |
|
| 120 |
+
if skill_total.count:
|
| 121 |
+
total.expected_damage += skill_total.expected_damage
|
| 122 |
+
skill_summary.expected_damage += skill_total.expected_damage
|
| 123 |
+
skill_summary.critical_count += skill_total.critical_strike
|
| 124 |
+
skill_summary.count += skill_total.count
|
| 125 |
+
skill_total.damage /= skill_total.count
|
| 126 |
+
skill_total.critical_damage /= skill_total.count
|
| 127 |
+
skill_total.expected_damage /= skill_total.count
|
| 128 |
+
skill_total.critical_strike /= skill_total.count
|
| 129 |
+
else:
|
| 130 |
+
summary.pop(skill_name)
|
| 131 |
for attr, residual_damage in skill_total.gradients.items():
|
| 132 |
total.gradients[attr] += residual_damage
|
| 133 |
skill_total.gradients[attr] /= skill_total.count
|
utils/parser.py
CHANGED
|
@@ -5,8 +5,8 @@ from collections import defaultdict
|
|
| 5 |
from base.attribute import Attribute
|
| 6 |
from base.buff import Buff
|
| 7 |
from base.gain import Gain
|
| 8 |
-
from base.skill import Skill
|
| 9 |
-
from schools import bei_ao_jue
|
| 10 |
from utils.lua import parse
|
| 11 |
|
| 12 |
SKILL_TYPE = Tuple[int, int, int]
|
|
@@ -80,6 +80,39 @@ SUPPORT_SCHOOL = {
|
|
| 80 |
"strain": "无双",
|
| 81 |
"surplus": "破招",
|
| 82 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
)
|
| 84 |
}
|
| 85 |
|
|
@@ -107,8 +140,10 @@ class Parser:
|
|
| 107 |
records: Dict[int, List[RECORD_TYPE]]
|
| 108 |
status: Dict[int, STATUS_TYPE]
|
| 109 |
snapshot: Dict[int, SNAPSHOT_TYPE]
|
|
|
|
| 110 |
stacks: Dict[int, Dict[int, int]]
|
| 111 |
ticks: Dict[int, Dict[int, int]]
|
|
|
|
| 112 |
|
| 113 |
fight_flag: Dict[int, bool]
|
| 114 |
start_time: Dict[int, List[int]]
|
|
@@ -148,8 +183,10 @@ class Parser:
|
|
| 148 |
self.records = defaultdict(list)
|
| 149 |
self.status = defaultdict(dict)
|
| 150 |
self.snapshot = defaultdict(dict)
|
|
|
|
| 151 |
self.stacks = defaultdict(lambda: defaultdict(lambda: 1))
|
| 152 |
self.ticks = defaultdict(lambda: defaultdict(int))
|
|
|
|
| 153 |
|
| 154 |
self.fight_flag = defaultdict(bool)
|
| 155 |
self.start_time = defaultdict(list)
|
|
@@ -190,6 +227,12 @@ class Parser:
|
|
| 190 |
self.select_equipments[player_id] = self.parse_equipments(detail[5])
|
| 191 |
self.select_talents[player_id] = self.parse_talents(detail[6])
|
| 192 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
def parse_time(self, row, timestamp):
|
| 194 |
detail = row.strip("{}").split(",")
|
| 195 |
player_id = int(detail[0])
|
|
@@ -218,7 +261,12 @@ class Parser:
|
|
| 218 |
|
| 219 |
def parse_skill(self, row, timestamp):
|
| 220 |
detail = row.strip("{}").split(",")
|
| 221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 222 |
if not self.fight_flag[player_id] or player_id not in self.school:
|
| 223 |
return
|
| 224 |
skill_id, skill_level, critical = int(detail[4]), int(detail[5]), detail[6] == "true"
|
|
@@ -226,21 +274,34 @@ class Parser:
|
|
| 226 |
return
|
| 227 |
timestamp = int(timestamp) - self.start_time[player_id][-1]
|
| 228 |
skill_stack = self.stacks[player_id][skill_id]
|
| 229 |
-
if self.ticks[player_id][skill_id]:
|
| 230 |
-
self.ticks[player_id][skill_id] -= 1
|
| 231 |
-
if not self.ticks[player_id][skill_id]:
|
| 232 |
-
self.stacks[player_id].pop(skill_id)
|
| 233 |
|
| 234 |
-
skill_tuple = (skill_id, skill_level, skill_stack)
|
| 235 |
skill = self.school[player_id].skills[skill_id]
|
| 236 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
| 237 |
self.stacks[player_id][bind_skill] = min(self.stacks[player_id][bind_skill] + 1, skill.max_stack)
|
| 238 |
-
self.ticks[player_id][bind_skill] = skill.tick if not self.ticks[player_id][bind_skill] else skill.tick - 1
|
| 239 |
self.snapshot[player_id][bind_skill] = self.status[player_id].copy()
|
| 240 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 241 |
current_record = self.records[player_id][len(self.start_time) - 1]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
status_tuple = self.available_status(player_id, skill_id)
|
|
|
|
| 243 |
current_record[skill_tuple][status_tuple].append((timestamp, critical))
|
|
|
|
|
|
|
|
|
|
| 244 |
|
| 245 |
def __call__(self, file_name):
|
| 246 |
self.reset()
|
|
@@ -253,6 +314,8 @@ class Parser:
|
|
| 253 |
row = line.split("\t")
|
| 254 |
if row[4] == "5":
|
| 255 |
self.parse_time(row[-1], row[3])
|
|
|
|
|
|
|
| 256 |
elif row[4] == "13":
|
| 257 |
self.parse_buff(row[-1])
|
| 258 |
elif row[4] == "21":
|
|
@@ -265,3 +328,9 @@ class Parser:
|
|
| 265 |
}
|
| 266 |
for player_id in self.end_time
|
| 267 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
from base.attribute import Attribute
|
| 6 |
from base.buff import Buff
|
| 7 |
from base.gain import Gain
|
| 8 |
+
from base.skill import Skill, DotSkill, DotConsumeSkill, Damage, DotDamage
|
| 9 |
+
from schools import bei_ao_jue, shan_hai_xin_jue
|
| 10 |
from utils.lua import parse
|
| 11 |
|
| 12 |
SKILL_TYPE = Tuple[int, int, int]
|
|
|
|
| 80 |
"strain": "无双",
|
| 81 |
"surplus": "破招",
|
| 82 |
}
|
| 83 |
+
),
|
| 84 |
+
10756: School(
|
| 85 |
+
school="万灵",
|
| 86 |
+
major="身法",
|
| 87 |
+
kind="外功",
|
| 88 |
+
attribute=shan_hai_xin_jue.ShanHaiXinJue,
|
| 89 |
+
formation="苍梧引灵阵",
|
| 90 |
+
skills=shan_hai_xin_jue.SKILLS,
|
| 91 |
+
buffs=shan_hai_xin_jue.BUFFS,
|
| 92 |
+
talent_gains=shan_hai_xin_jue.TALENT_GAINS,
|
| 93 |
+
talents=shan_hai_xin_jue.TALENTS,
|
| 94 |
+
talent_decoder=shan_hai_xin_jue.TALENT_DECODER,
|
| 95 |
+
talent_encoder=shan_hai_xin_jue.TALENT_ENCODER,
|
| 96 |
+
recipe_gains=None,
|
| 97 |
+
recipes=None,
|
| 98 |
+
gains=None,
|
| 99 |
+
display_attrs={
|
| 100 |
+
"agility": "身法",
|
| 101 |
+
"base_physical_attack_power": "基础攻击",
|
| 102 |
+
"physical_attack_power": "攻击",
|
| 103 |
+
"base_physical_critical_strike": "会心等级",
|
| 104 |
+
"physical_critical_strike": "会心",
|
| 105 |
+
"physical_critical_power_base": "会效等级",
|
| 106 |
+
"physical_critical_power": "会效",
|
| 107 |
+
"base_physical_overcome": "基础破防",
|
| 108 |
+
"final_physical_overcome": "最终破防",
|
| 109 |
+
"physical_overcome": "破防",
|
| 110 |
+
"weapon_damage_base": "基础武器伤害",
|
| 111 |
+
"weapon_damage_rand": "浮动武器伤害",
|
| 112 |
+
"strain_base": "无双等级",
|
| 113 |
+
"strain": "无双",
|
| 114 |
+
"surplus": "破招",
|
| 115 |
+
}
|
| 116 |
)
|
| 117 |
}
|
| 118 |
|
|
|
|
| 140 |
records: Dict[int, List[RECORD_TYPE]]
|
| 141 |
status: Dict[int, STATUS_TYPE]
|
| 142 |
snapshot: Dict[int, SNAPSHOT_TYPE]
|
| 143 |
+
last_dot: Dict[int, Dict[int, Tuple[Tuple[int, int, int], Tuple[tuple, tuple]]]]
|
| 144 |
stacks: Dict[int, Dict[int, int]]
|
| 145 |
ticks: Dict[int, Dict[int, int]]
|
| 146 |
+
pets: Dict[int, int]
|
| 147 |
|
| 148 |
fight_flag: Dict[int, bool]
|
| 149 |
start_time: Dict[int, List[int]]
|
|
|
|
| 183 |
self.records = defaultdict(list)
|
| 184 |
self.status = defaultdict(dict)
|
| 185 |
self.snapshot = defaultdict(dict)
|
| 186 |
+
self.last_dot = defaultdict(dict)
|
| 187 |
self.stacks = defaultdict(lambda: defaultdict(lambda: 1))
|
| 188 |
self.ticks = defaultdict(lambda: defaultdict(int))
|
| 189 |
+
self.pets = {}
|
| 190 |
|
| 191 |
self.fight_flag = defaultdict(bool)
|
| 192 |
self.start_time = defaultdict(list)
|
|
|
|
| 227 |
self.select_equipments[player_id] = self.parse_equipments(detail[5])
|
| 228 |
self.select_talents[player_id] = self.parse_talents(detail[6])
|
| 229 |
|
| 230 |
+
def parse_pet(self, row):
|
| 231 |
+
detail = row.strip("{}").split(",")
|
| 232 |
+
pet_id, player_id = int(detail[0]), int(detail[3])
|
| 233 |
+
if player_id in self.school:
|
| 234 |
+
self.pets[pet_id] = player_id
|
| 235 |
+
|
| 236 |
def parse_time(self, row, timestamp):
|
| 237 |
detail = row.strip("{}").split(",")
|
| 238 |
player_id = int(detail[0])
|
|
|
|
| 261 |
|
| 262 |
def parse_skill(self, row, timestamp):
|
| 263 |
detail = row.strip("{}").split(",")
|
| 264 |
+
caster_id = int(detail[0])
|
| 265 |
+
if caster_id in self.pets:
|
| 266 |
+
player_id = self.pets[caster_id]
|
| 267 |
+
else:
|
| 268 |
+
player_id = caster_id
|
| 269 |
+
|
| 270 |
if not self.fight_flag[player_id] or player_id not in self.school:
|
| 271 |
return
|
| 272 |
skill_id, skill_level, critical = int(detail[4]), int(detail[5]), detail[6] == "true"
|
|
|
|
| 274 |
return
|
| 275 |
timestamp = int(timestamp) - self.start_time[player_id][-1]
|
| 276 |
skill_stack = self.stacks[player_id][skill_id]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 277 |
|
|
|
|
| 278 |
skill = self.school[player_id].skills[skill_id]
|
| 279 |
+
if isinstance(skill, DotSkill):
|
| 280 |
+
bind_skill = skill.bind_skill
|
| 281 |
+
if not self.ticks[player_id][bind_skill]:
|
| 282 |
+
self.stacks[player_id][bind_skill] = 0
|
| 283 |
+
self.ticks[player_id][bind_skill] = skill.tick
|
| 284 |
self.stacks[player_id][bind_skill] = min(self.stacks[player_id][bind_skill] + 1, skill.max_stack)
|
|
|
|
| 285 |
self.snapshot[player_id][bind_skill] = self.status[player_id].copy()
|
| 286 |
+
elif isinstance(skill, DotConsumeSkill):
|
| 287 |
+
bind_skill = skill.bind_skill
|
| 288 |
+
skill_tuple, status_tuple = self.last_dot[player_id][bind_skill]
|
| 289 |
+
skill_id, skill_level, skill_stack = skill_tuple
|
| 290 |
+
self.ticks[player_id][skill_id] += 1
|
| 291 |
+
tick = min(self.ticks[player_id][skill_id], skill.tick)
|
| 292 |
current_record = self.records[player_id][len(self.start_time) - 1]
|
| 293 |
+
current_record[(skill_id, skill_level, skill_stack * tick)][status_tuple].append(
|
| 294 |
+
current_record[skill_tuple][status_tuple].pop()
|
| 295 |
+
)
|
| 296 |
+
self.ticks[player_id][skill_id] -= tick
|
| 297 |
+
elif isinstance(skill, Damage):
|
| 298 |
+
skill_tuple = (skill_id, skill_level, skill_stack)
|
| 299 |
status_tuple = self.available_status(player_id, skill_id)
|
| 300 |
+
current_record = self.records[player_id][len(self.start_time) - 1]
|
| 301 |
current_record[skill_tuple][status_tuple].append((timestamp, critical))
|
| 302 |
+
if isinstance(skill, DotDamage):
|
| 303 |
+
self.last_dot[player_id][skill_id] = (skill_tuple, status_tuple)
|
| 304 |
+
self.ticks[player_id][skill_id] -= 1
|
| 305 |
|
| 306 |
def __call__(self, file_name):
|
| 307 |
self.reset()
|
|
|
|
| 314 |
row = line.split("\t")
|
| 315 |
if row[4] == "5":
|
| 316 |
self.parse_time(row[-1], row[3])
|
| 317 |
+
if row[4] == "8":
|
| 318 |
+
self.parse_pet(row[-1])
|
| 319 |
elif row[4] == "13":
|
| 320 |
self.parse_buff(row[-1])
|
| 321 |
elif row[4] == "21":
|
|
|
|
| 328 |
}
|
| 329 |
for player_id in self.end_time
|
| 330 |
}
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
if __name__ == '__main__':
|
| 334 |
+
parser = Parser()
|
| 335 |
+
parser("../new.jcl")
|
| 336 |
+
print(parser)
|