Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.17.1
rev: v0.17.2
hooks:
# Run the linter.
- id: ruff
Expand Down
88 changes: 62 additions & 26 deletions poetry.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "Deadbot"
version = "1.18.7"
version = "1.18.8"
description = "Bot that lives to serve deadlock.wiki"
readme = "README.md"
authors=[]
Expand Down
2 changes: 1 addition & 1 deletion src/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.18.7'
__version__ = '1.18.8'
1 change: 1 addition & 0 deletions src/decompiler/decompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def _import_localization_data(self):
'citadel_heroes',
'citadel_main',
'citadel_mods',
'citadel_seasonal',
]

# Loop through each folder in the array
Expand Down
2 changes: 1 addition & 1 deletion src/parser/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def __init__(
def _get_localization_groups(self):
# set group priority as some keys are duplicated across groups,
# where some values have mistakes. Eg. 'mods' has many mistakes and is low priority
GROUPS = ['main', 'gc', 'gc_mod_names', 'gc_hero_names', 'heroes', 'attributes', 'mods']
GROUPS = ['main', 'gc', 'gc_mod_names', 'gc_hero_names', 'heroes', 'attributes', 'seasonal', 'mods']

# validate that no groups have been missed from GROUPS
all_groups = os.listdir(os.path.join(self.DATA_DIR, 'localizations'))
Expand Down
41 changes: 14 additions & 27 deletions src/parser/parsers/heroes.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ def run(self):
hero_stats['TechDuration'] = hero_stats['TechDuration'] - 1
hero_stats['ReloadSpeed'] = hero_stats['ReloadSpeed'] - 1

# Transformed Silver's weapon never reloads
if hero_key == 'hero_werewolf_transformed':
hero_stats['ReloadSpeed'] = 0

hero_stats['SpiritScaling'] = self._parse_spirit_scaling(hero_value)

# Parse weapon data and nest it under a 'Weapon' key
Expand Down Expand Up @@ -152,12 +156,6 @@ def _create_werewolf_transformed(self):
# Remove the alt-fire key to keep the data clean
del upgrades['MODIFIER_VALUE_BASE_BULLET_DAMAGE_FROM_LEVEL_ALT_FIRE']

# Treat claws as having no ammo limit (continuous attacks during transformation)
claws_id = 'citadel_weapon_werewolf_claws'
weapon = self._parse_weapon_stats(self.abilities_data[claws_id])
if weapon:
weapon['m_iClipSize'] = 0

transformation_ability = self.abilities_data['ability_werewolf_transformation']
modifier = transformation_ability['m_WerewolfModifier']

Expand All @@ -171,10 +169,10 @@ def _create_werewolf_transformed(self):
return werewolf_transformed

def _apply_transformation_stats(self, werewolf_transformed, transformation_ability):
"""Apply the stats the transformation modifier grants to the transformed hero.
"""Apply the crit reduction the transformation modifier grants to the transformed hero.

The werewolf modifier auto-registers several ability properties against hero modifier values,
which are not part of the hero's base data. Fold them into the transformed copy so it matches the
The werewolf modifier auto-registers HeadshotResist against the hero's crit damage received scale,
which is not part of the hero's base data. Fold it into the transformed copy so it matches the
stats the hero actually has while transformed.
"""
ability_properties = transformation_ability.get('m_mapAbilityProperties', {})
Expand All @@ -186,24 +184,6 @@ def _apply_transformation_stats(self, werewolf_transformed, transformation_abili
crit_scale_key = self._find_stat_key(starting_stats, 'CritDamageReceivedScale')
starting_stats[crit_scale_key] *= 1 + num_utils.remove_uom(headshot_resist) / 100

# BonusHealth grants flat max health, plus extra health per boon through its scale function
bonus_health = ability_properties.get('BonusHealth', {})
health_value = bonus_health.get('m_strValue')
if health_value is not None:
starting_stats[self._find_stat_key(starting_stats, 'MaxHealth')] += num_utils.remove_uom(health_value)

health_scale = bonus_health.get('m_subclassScaleFunction', {})
if health_scale.get('m_eSpecificStatScaleType') == 'ELevelUpBoons':
boon_health_key = 'MODIFIER_VALUE_BASE_HEALTH_FROM_LEVEL'
boon_health = num_utils.remove_uom(health_scale.get('m_flStatScale', 0.0))
level_upgrades = werewolf_transformed.setdefault('m_mapStandardLevelUpUpgrades', {})
level_upgrades[boon_health_key] = level_upgrades.get(boon_health_key, 0.0) + boon_health

# BonusMoveSpeed grants flat max move speed
move_speed = ability_properties.get('BonusMoveSpeed', {}).get('m_strValue')
if move_speed is not None:
starting_stats[self._find_stat_key(starting_stats, 'MaxMoveSpeed')] += num_utils.remove_uom(move_speed)

def _find_stat_key(self, starting_stats, stat_name):
"""Get the raw starting stat key for a stat name, which carries an 'E' prefix in the game files"""
for stat_key in starting_stats:
Expand Down Expand Up @@ -318,6 +298,13 @@ def _parse_hero_weapon(self, hero_value, hero_key):
weapon_prim_id = bound_abilities[primary_slot]
if weapon_prim_id in self.abilities_data:
primary_ability_data = self.abilities_data[weapon_prim_id]
if hero_key == 'hero_werewolf_transformed':
# Transformed Silver's claws have no ammo count and no reload
primary_ability_data = copy.deepcopy(primary_ability_data)
weapon_info = weapon_parser.get_weapon_data(primary_ability_data)
if weapon_info:
weapon_info['m_iClipSize'] = 0
weapon_info['m_reloadDuration'] = 0
weapon_stats = self._parse_weapon_stats(primary_ability_data)
if weapon_stats:
# The primary weapon name/description key is constructed from the hero's key, not its own ability ID.
Expand Down