When buff suppression expires, only clients get ReapplyBuff() called to
restore visual and state effects (illusions, procs, silence, etc.).
Pets and NPCs had no equivalent handling, causing permanent loss of
illusions, weapon procs, and other active effects after suppression.
Add non-client effect restoration in the suppression expiry path of
BuffFadeBySlot() that handles illusions, silence, amnesia, and weapon
procs for pets, NPCs, and bots.
Fixes#32
When BuffFadeBySlot() is called on a suppressed slot (e.g., when
suppression timer expires), the effect removal loop accesses
spells[SPELL_SUPPRESSED] (index 0xFFFD) which is out-of-bounds.
This is unnecessary since effects were already removed when the buff
was first suppressed. Skip the loop entirely for SPELL_SUPPRESSED
slots to prevent OOB memory access and let execution proceed directly
to the restoration branch.
Fixes#29
BuffFadeNonPersistDeath(), BuffFadeBeneficial(), BuffFadeDetrimental(),
and BuffFadeByEffect() all use IsValidSpell() which returns false for
SPELL_SUPPRESSED (0xFFFD), causing suppressed buffs to survive death
and mass-dispels. Worse, if BuffFadeBySlot() were called on a
suppressed slot, it would restore the buff instead of clearing it.
Add explicit handling for SPELL_SUPPRESSED slots in each function:
check the suppressedid against the fade criteria and clear the slot
directly (set to SPELL_UNKNOWN) rather than calling BuffFadeBySlot().
Fixes#31
BuffProcess() calls DoBuffTic() on all valid-or-suppressed spells, but
DoBuffTic() accesses spells[buff.spellid] which for SPELL_SUPPRESSED
(0xFFFD) could read out-of-bounds memory. Add an explicit check to skip
DoBuffTic() for suppressed slots since they should only have their timer
decremented, not their effects ticked.
Fixes#30
When a player zones while having suppressed buffs (via the spell
suppression system), the suppression state was not saved to the
database. On zone-in, suppressed buffs were restored as normal active
buffs, causing non-persistent illusions to be incorrectly removed.
Changes:
- Add 'suppressed' column to character_buffs table (tinyint, default 0)
- SaveBuffs(): Save suppressed flag (1 when buff is in SPELL_SUPPRESSED state)
- LoadBuffs(): Restore buffs in suppressed state when suppressed=1,
setting spellid=SPELL_SUPPRESSED and populating suppressedid/
suppressedticsremaining from the saved spell_id and ticsremaining
- LoadBuffs(): Skip suppressed buffs in the illusion/charm removal loop
so they are not incorrectly stripped on zone-in
Fixes#33
Add skip-duplicate-actions to avoid rebuilding on push to master when
the same code already built successfully on the PR. This saves CI time
and resources by detecting when file content (tree hash) matches a
previous successful run.
- Add pre_job that checks for duplicate runs using fkirc/skip-duplicate-actions
- PR builds always run (never skipped) to ensure status before merge
- Push builds to master skip if identical code already built successfully
- Both linux and windows jobs depend on pre_job skip check