Skip to content

Fix autobonus not working with ammo, item combos, and pets - #3446

Open
MrKeiKun wants to merge 2 commits into
HerculesWS:masterfrom
MrKeiKun:fix/issue-2764-autobonus
Open

Fix autobonus not working with ammo, item combos, and pets#3446
MrKeiKun wants to merge 2 commits into
HerculesWS:masterfrom
MrKeiKun:fix/issue-2764-autobonus

Conversation

@MrKeiKun

@MrKeiKun MrKeiKun commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Pull Request Prelude

Changes Proposed

autobonus()/autobonus2()/autobonus3() identified the source of an autobonus purely by reading status->current_equip_item_index (an inventory index) and deriving an EQP_* position bitmask from it. That global was only correctly maintained by the plain equip-item loop and the card loop in status_calc_pc_(), so every other script-execution path silently failed to register a working autobonus:

  • Ammo: the ammo script-execution block never set status->current_equip_item_index, so autobonus() called from an ammo item's script either no-op'd or registered against whatever equip slot was last processed by the main loop.
  • Item combos: combo scripts have no single backing equip slot, so there was no way to give them a valid position at all.
  • Pets: the pet equip-script block runs after current_equip_item_index is explicitly reset to -1, so autobonus() there was a guaranteed no-op.
  • Item + card collision: an item's own script and a card socketed in it both run with current_equip_item_index pointing at the same inventory slot, so their autobonuses shared the exact same identity and could suppress or interfere with each other.

This PR replaces the single EQP_*-bitmask identity with a proper struct s_autobonus_source { pos, card_id, combo_pos, pet_id }, threaded through pc_addautobonus/pc_delautobonus/pc_exeautobonus/autobonus_is_active and the three autobonus*() builtins. New context globals (current_equip_combo_pos, current_equip_pet_id) mirror the existing current_equip_card_id pattern and are set around the combo and pet-equip script executions in status_calc_pc_(). The old sd->state.autobonus position bitmask (which could only represent one active autobonus per equip slot) is removed in favor of per-entry lookups that re-validate the exact source (equip slot + specific card, or specific combo id, or specific pet id) against the character's live state.

Also fixes a related gap: pc_unequipitem() used to clear autobonus activation via that same bitmask unconditionally on unequip; since status_calc_pc() isn't always called synchronously after an unequip (e.g. PCUNEQUIPITEM_FORCE without PCUNEQUIPITEM_RECALC), this PR now calls pc->delautobonus(..., true) directly in pc_unequipitem() so an unequipped item's autobonus timer is always stopped promptly regardless of the caller's recalc flag.

Regenerated the affected HPMHooking trampolines/typedefs by hand for the changed pc->addautobonus/new pc->autobonus_is_active interface entries, since pc_addautobonus's signature changed; maintainers may want to re-run HPMHookGen.pl to confirm these match exactly.

Issues addressed: #2764

autobonus() only worked from a plain equipped item's or card's script,
keyed off a single EQP_* position bitmask read from a global that was
never set for ammo scripts, combo scripts, or pet equip scripts. Adds
a proper source identity (item/card/combo/pet) so autobonus registers
and persists correctly for all of them, and stops a card sharing an
equip slot with its host item from colliding with the item's own
autobonus.
Hercules' interface validator flags any top-level <ifname>_<method>
function that isn't registered on that interface. The new private
helpers were named pc_* / script_* without being interface members,
which tripped it; renamed them off that pattern.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant