From 2f86327903580b9b1b358cec433cf2519ce576c7 Mon Sep 17 00:00:00 2001 From: kai <168676383+kai8484@users.noreply.github.com> Date: Wed, 14 Oct 2026 00:25:50 +0100 Subject: [PATCH 1/3] feat: format hero changelog sections with HeroChanges template (#461) --- src/changelogs/wikitext_formatter.py | 52 +++++++++++++++++++++------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/src/changelogs/wikitext_formatter.py b/src/changelogs/wikitext_formatter.py index 4fd950e0..208a78dd 100644 --- a/src/changelogs/wikitext_formatter.py +++ b/src/changelogs/wikitext_formatter.py @@ -129,17 +129,23 @@ def _format_entries( section['ability_sections'][ability] = [] section['ability_order'].append(ability) - formatted = _format_body(_capitalize_first(cleaned), heroes, abilities, items, link_targets, excluded_ability=ability) - section['ability_sections'][ability].append(f'* {{{{Change|}}}} {formatted}') + cleaned = _capitalize_first(cleaned) + formatted = _format_body(cleaned, heroes, abilities, items, link_targets, excluded_ability=ability) + section['ability_sections'][ability].append(f'** {{{{Change|}}}} {formatted}') else: formatted = _format_body(body, heroes, abilities, items, link_targets) - section['general'].append(f'* {{{{Change|}}}} {formatted}') + section['general'].append(f'** {{{{Change|}}}} {formatted}') return _build_output(general, modes, mode_order, item_sections, item_order, hero_sections, hero_order) def _collect_names(hero_data, item_data, ability_data) -> Tuple[List[str], List[str], List[str]]: - return _active_names(hero_data), _active_names(item_data), _active_names(ability_data) + # Only abilities bound to a hero, so generic ones like "Dash" in "Move and Dash Speed" aren't iconified + hero_ability_keys = { + ability['Key'] for hero in (hero_data or {}).values() for ability in (hero.get('BoundAbilities') or {}).values() if ability.get('Key') + } + hero_abilities = {key: ability_data[key] for key in hero_ability_keys if key in (ability_data or {})} + return _active_names(hero_data), _active_names(item_data), _active_names(hero_abilities) def _active_names(data: Dict[str, Any]) -> List[str]: @@ -232,7 +238,7 @@ def protect(value: str) -> str: protected.append(value) return token - def wrap(terms: List[str], template_name: str) -> None: + def wrap(terms: List[str], template_name: str, stat_link: bool = False) -> None: nonlocal text # Process longer names first so "Smoke Bomb" is matched before "Smoke". for term in sorted(dict.fromkeys(terms), key=len, reverse=True): @@ -240,13 +246,20 @@ def wrap(terms: List[str], template_name: str) -> None: continue pattern = re.compile(r'(? item > hero. # Exclude the ability that was already used as a sub-heading to avoid redundancy. ability_terms = [a for a in abilities if a != excluded_ability] wrap(ability_terms, 'AbilityIcon') - wrap(items, 'ItemIcon') + wrap(items, 'ItemIcon', stat_link=True) wrap(heroes, 'HeroIcon') # Apply link_targets auto-links for terms not already claimed by icon templates. @@ -292,6 +305,10 @@ def _remove_ability_mention(text: str, start: int, end: int) -> str: return re.sub(r'\s+', ' ', remaining).strip() +# Matches a numeric value at the end of the text, i.e. "+10% " or "5 " +_STAT_VALUE_BEFORE_RE = re.compile(r'[+-]?\d+(?:\.\d+)?%?\s+$') + + def _capitalize_first(text: str) -> str: return text[:1].upper() + text[1:] if text else text @@ -304,7 +321,8 @@ def _build_output(general, modes, mode_order, item_sections, item_order, hero_se 1. General entries (no prefix match) 2. Game mode sections (``== [[Mode]] ==``) 3. ``== Items ==`` with per-item sub-headings - 4. ``== Heroes ==`` with per-hero and per-ability sub-headings + 4. ``== Heroes ==`` with a ``{{HeroChanges}}`` block per hero, grouping + non-ability changes under '''Stats''' followed by each ability """ lines: List[str] = [] @@ -329,10 +347,20 @@ def _build_output(general, modes, mode_order, item_sections, item_order, hero_se lines.append('== Heroes ==') for hero in hero_order: section = hero_sections[hero] - lines.append(f'=== {{{{HeroIcon|{hero}}}}} ===') - lines.extend(section['general']) + groups = [] + if section['general']: + groups.append(["* '''Stats'''"] + section['general']) for ability in section['ability_order']: - lines.append(f'==== {{{{AbilityIcon|{ability}}}}} ====') - lines.extend(section['ability_sections'][ability]) + groups.append([f'* {{{{AbilityIcon|{ability}}}}}'] + section['ability_sections'][ability]) + + lines.append('') + lines.append('{{HeroChanges') + lines.append(f'|hero={hero}') + lines.append('|changes=') + for i, group in enumerate(groups): + if i > 0: + lines.append('') + lines.extend(group) + lines.append('}}') return '\n'.join(lines).strip() From 654b9abb7768410ab8abe5a954dbd137d7ec13a3 Mon Sep 17 00:00:00 2001 From: CarelessDoug Date: Wed, 14 Oct 2026 15:08:49 -0400 Subject: [PATCH 2/3] Bump DeadlockEntityHelper to v2.1.1 (#469) --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8f8c31ae..4812873d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,7 +19,7 @@ RUN wget https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownl && rm DepotDownloader-linux-x64.zip \ && chmod +x DepotDownloader -ENV ENTITY_HELPER_VER="v2.1.0" +ENV ENTITY_HELPER_VER="v2.1.1" RUN wget https://github.com/deadlock-wiki/DeadlockEntityHelper/releases/download/$ENTITY_HELPER_VER/DeadlockEntityHelper \ && chmod +x DeadlockEntityHelper From cd8995c26e5695b48d321d4f8141fba71a9f2bf6 Mon Sep 17 00:00:00 2001 From: Deadbot0 Date: Wed, 14 Oct 2026 19:14:50 +0000 Subject: [PATCH 3/3] [skip ci] chore: bumped version to 1.18.6 --- pyproject.toml | 2 +- src/_version.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fe66ee28..b2e0ad0d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "Deadbot" -version = "1.18.5" +version = "1.18.6" description = "Bot that lives to serve deadlock.wiki" readme = "README.md" authors=[] diff --git a/src/_version.py b/src/_version.py index dfcd902f..7002b984 100644 --- a/src/_version.py +++ b/src/_version.py @@ -1 +1 @@ -__version__ = '1.18.5' +__version__ = '1.18.6'