Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,10 @@ class PoisonedBehavior : public UpdateModule,
Real m_poisonDamageAmount;
ObjectID m_poisonSource;
DeathType m_deathType;
// TheSuperHackers @bugfix ZsoltFeher 07/20/2026 Reentrancy guard so our own periodic poison
// damage-over-time tick (see update()) does not re-trigger onDamage() on ourselves now that
// it deals real POISON damage. damage.in.m_sourceID cannot be used for this since it is set
// to the original poisoner (for XP credit), which could legitimately re-poison us again.
Bool m_dealingPeriodicDamage;

};
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ PoisonedBehavior::PoisonedBehavior( Thing *thing, const ModuleData* moduleData )
m_poisonDamageAmount = 0.0f;
m_poisonSource = INVALID_ID;
m_deathType = DEATH_POISONED;
m_dealingPeriodicDamage = FALSE;
setWakeFrame(getObject(), UPDATE_SLEEP_FOREVER);
}

Expand All @@ -87,7 +88,16 @@ PoisonedBehavior::~PoisonedBehavior()
void PoisonedBehavior::onDamage( DamageInfo *damageInfo )
{
if( damageInfo->in.m_damageType == DAMAGE_POISON )
{
#if !RETAIL_COMPATIBLE_CRC
// TheSuperHackers @bugfix ZsoltFeher 07/20/2026 Our own periodic poison damage-over-time tick
// (see update()) now deals real POISON damage so that POISON resistance applies to it. Ignore
// it here so it does not re-arm/re-trigger this same PoisonedBehavior instance on ourselves.
if( m_dealingPeriodicDamage )
return;
#endif
startPoisonedEffects( damageInfo );
}
}

// ------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -119,9 +129,23 @@ UpdateSleepTime PoisonedBehavior::update()
DamageInfo damage;
damage.in.m_amount = m_poisonDamageAmount;
damage.in.m_sourceID = m_poisonSource;
#if RETAIL_COMPATIBLE_CRC
damage.in.m_damageType = DAMAGE_UNRESISTABLE; // Not poison, as that will infect us again
#else
// TheSuperHackers @bugfix ZsoltFeher 07/20/2026 Deal actual POISON damage on the periodic tick
// so the target's POISON resistance (e.g. Chemical Suits) is properly applied. This used to be
// UNRESISTABLE to avoid re-triggering ourselves; onDamage() now guards against that explicitly
// via the m_dealingPeriodicDamage reentrancy flag instead.
damage.in.m_damageType = DAMAGE_POISON;
#endif
damage.in.m_deathType = m_deathType;
#if !RETAIL_COMPATIBLE_CRC
m_dealingPeriodicDamage = TRUE;
#endif
getObject()->attemptDamage( &damage );
#if !RETAIL_COMPATIBLE_CRC
m_dealingPeriodicDamage = FALSE;
#endif

m_poisonDamageFrame = now + d->m_poisonDamageIntervalData;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,10 @@ class PoisonedBehavior : public UpdateModule,
Real m_poisonDamageAmount;
ObjectID m_poisonSource;
DeathType m_deathType;
// TheSuperHackers @bugfix ZsoltFeher 07/20/2026 Reentrancy guard so our own periodic poison
// damage-over-time tick (see update()) does not re-trigger onDamage() on ourselves now that
// it deals real POISON damage. damage.in.m_sourceID cannot be used for this since it is set
// to the original poisoner (for XP credit), which could legitimately re-poison us again.
Bool m_dealingPeriodicDamage;

};
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ PoisonedBehavior::PoisonedBehavior( Thing *thing, const ModuleData* moduleData )
m_poisonDamageAmount = 0.0f;
m_poisonSource = INVALID_ID;
m_deathType = DEATH_POISONED;
m_dealingPeriodicDamage = FALSE;
setWakeFrame(getObject(), UPDATE_SLEEP_FOREVER);
}

Expand All @@ -87,7 +88,16 @@ PoisonedBehavior::~PoisonedBehavior()
void PoisonedBehavior::onDamage( DamageInfo *damageInfo )
{
if( damageInfo->in.m_damageType == DAMAGE_POISON )
{
#if !RETAIL_COMPATIBLE_CRC
// TheSuperHackers @bugfix ZsoltFeher 07/20/2026 Our own periodic poison damage-over-time tick
// (see update()) now deals real POISON damage so that POISON resistance applies to it. Ignore
// it here so it does not re-arm/re-trigger this same PoisonedBehavior instance on ourselves.
if( m_dealingPeriodicDamage )
return;
#endif
startPoisonedEffects( damageInfo );
}
}

// ------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -119,10 +129,24 @@ UpdateSleepTime PoisonedBehavior::update()
DamageInfo damage;
damage.in.m_amount = m_poisonDamageAmount;
damage.in.m_sourceID = m_poisonSource;
#if RETAIL_COMPATIBLE_CRC
damage.in.m_damageType = DAMAGE_UNRESISTABLE; // Not poison, as that will infect us again
#else
// TheSuperHackers @bugfix ZsoltFeher 07/20/2026 Deal actual POISON damage on the periodic tick
// so the target's POISON resistance (e.g. Chemical Suits) is properly applied. This used to be
// UNRESISTABLE to avoid re-triggering ourselves; onDamage() now guards against that explicitly
// via the m_dealingPeriodicDamage reentrancy flag instead.
damage.in.m_damageType = DAMAGE_POISON;
#endif
damage.in.m_damageFXOverride = DAMAGE_POISON; // but this will ensure that the right effect is played
damage.in.m_deathType = m_deathType;
#if !RETAIL_COMPATIBLE_CRC
m_dealingPeriodicDamage = TRUE;
#endif
getObject()->attemptDamage( &damage );
#if !RETAIL_COMPATIBLE_CRC
m_dealingPeriodicDamage = FALSE;
#endif

m_poisonDamageFrame = now + d->m_poisonDamageIntervalData;
}
Expand Down