Skip to content
Open
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: 2 additions & 0 deletions Core/GameEngine/Include/GameLogic/Damage.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ class DamageInfoInput : public Snapshot
m_deathType = DEATH_NORMAL;
m_amount = 0;
m_kill = FALSE;
m_enterSecondLife = FALSE;

m_shockWaveVector.zero();
m_shockWaveAmount = 0.0f;
Expand All @@ -286,6 +287,7 @@ class DamageInfoInput : public Snapshot
DeathType m_deathType; ///< if this kills us, death type to be used
Real m_amount; ///< # value of how much damage to inflict
Bool m_kill; ///< will always cause object to die regardless of damage.
Bool m_enterSecondLife;

// These are used for damage causing shockwave, forcing units affected to be pushed around
Coord3D m_shockWaveVector; ///< This represents the incoming damage vector
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class BattleBusSlowDeathBehavior : public SlowDeathBehavior
// slow death methods
virtual void onDie( const DamageInfo *damageInfo ) override;
virtual void beginSlowDeath( const DamageInfo *damageInfo ) override;
virtual Bool isRealDeath() const override { return m_isRealDeath; }
virtual UpdateSleepTime update() override;

protected:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ class SlowDeathBehaviorInterface
virtual void beginSlowDeath( const DamageInfo *damageInfo ) = 0;
virtual Int getProbabilityModifier( const DamageInfo *damageInfo ) const = 0;
virtual Bool isDieApplicable(const DamageInfo *damageInfo) const = 0;
virtual Bool isRealDeath() const = 0;
};

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -151,13 +152,17 @@ class SlowDeathBehavior : public UpdateModule,
// SlowDeathBehaviorInterface
virtual void beginSlowDeath( const DamageInfo *damageInfo ) override;
virtual Int getProbabilityModifier( const DamageInfo *damageInfo ) const override;
virtual Bool isDieApplicable(const DamageInfo *damageInfo) const override { return getSlowDeathBehaviorModuleData()->m_dieMuxData.isDieApplicable(getObject(), damageInfo); }
virtual Bool isDieApplicable(const DamageInfo *damageInfo) const override;
virtual Bool isRealDeath() const override { return true; }

static Int computeTotalSlowDeathProbability(const Object *obj, const DamageInfo *damageInfo);

protected:

void doPhaseStuff(SlowDeathPhaseType sdphase);
Bool isSlowDeathActivated() const { return (m_flags & (1<<SLOW_DEATH_ACTIVATED)) != 0; }
UnsignedInt getDestructionFrame() const { return m_destructionFrame; }
Bool canEnterSecondLife() const { return !isRealDeath(); }

private:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class UndeadBody : public ActiveBody
Bool m_isSecondLife; /** This is false until I detect death the first time, then I
change my Max, Initial, and Current health and stop intercepting anything.
*/
void startSecondLife(DamageInfo *damageInfo);
Bool startSecondLife(DamageInfo *damageInfo);
void applySecondLife(DamageInfo *damageInfo);

};
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,19 @@ Int SlowDeathBehavior::getProbabilityModifier( const DamageInfo *damageInfo ) co
return max( getSlowDeathBehaviorModuleData()->m_probabilityModifier + overkillModifier, 1 );
}

Bool SlowDeathBehavior::isDieApplicable(const DamageInfo *damageInfo) const
{
if (!getSlowDeathBehaviorModuleData()->m_dieMuxData.isDieApplicable(getObject(), damageInfo))
return false;

#if !RETAIL_COMPATIBLE_CRC
if (damageInfo->in.m_enterSecondLife != canEnterSecondLife())
return false;
#endif

return true;
}

//-------------------------------------------------------------------------------------------------
static void calcRandomForce(Real minMag, Real maxMag, Real minPitch, Real maxPitch, Coord3D& force)
{
Expand Down Expand Up @@ -490,23 +503,13 @@ void SlowDeathBehavior::onDie( const DamageInfo *damageInfo )
// deselect this unit for all players.
TheGameLogic->deselectObject(obj, PLAYERMASK_ALL, TRUE);

Int total = 0;
BehaviorModule** update = obj->getBehaviorModules();
for (; *update; ++update)
{
SlowDeathBehaviorInterface* sdu = (*update)->getSlowDeathBehaviorInterface();
if (sdu != nullptr && sdu->isDieApplicable(damageInfo))
{
total += sdu->getProbabilityModifier( damageInfo );
}
}
const Int total = computeTotalSlowDeathProbability(obj, damageInfo);
DEBUG_ASSERTCRASH(total > 0, ("Hmm, this is wrong"));


// this returns a value from 1...total, inclusive
Int roll = GameLogicRandomValue(1, total);

for (/* UpdateModuleInterface** */ update = obj->getBehaviorModules(); *update; ++update)
for (BehaviorModule** update = obj->getBehaviorModules(); *update; ++update)
{
SlowDeathBehaviorInterface* sdu = (*update)->getSlowDeathBehaviorInterface();
if (sdu != nullptr && sdu->isDieApplicable(damageInfo))
Expand All @@ -523,6 +526,24 @@ void SlowDeathBehavior::onDie( const DamageInfo *damageInfo )
DEBUG_CRASH(("We should never get here"));
}


// ------------------------------------------------------------------------------------------------
Int SlowDeathBehavior::computeTotalSlowDeathProbability(const Object *obj, const DamageInfo *damageInfo)
{
Int total = 0;

for (BehaviorModule** update = obj->getBehaviorModules(); *update; ++update)
{
SlowDeathBehaviorInterface* sdu = (*update)->getSlowDeathBehaviorInterface();
if (sdu != nullptr && sdu->isDieApplicable(damageInfo))
{
total += sdu->getProbabilityModifier( damageInfo );
}
}

return total;
}

// ------------------------------------------------------------------------------------------------
/** CRC */
// ------------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ UndeadBody::~UndeadBody()
// ------------------------------------------------------------------------------------------------
void UndeadBody::attemptDamage( DamageInfo *damageInfo )
{
// If we are on our first life, see if this damage will kill us. If it will, bind it to one hitpoint
// remaining, then go ahead and take it.
// If we are on our first life, see if this damage will kill us.
Bool shouldStartSecondLife = FALSE;

if( damageInfo->in.m_damageType != DAMAGE_UNRESISTABLE
Expand All @@ -90,65 +89,88 @@ void UndeadBody::attemptDamage( DamageInfo *damageInfo )
&& IsHealthDamagingDamage(damageInfo->in.m_damageType)
)
{
damageInfo->in.m_amount = min( damageInfo->in.m_amount, getHealth() - 1 );
shouldStartSecondLife = TRUE;
}

ActiveBody::attemptDamage(damageInfo);

// After we take it (which allows for damaging special effects), we will do our modifications to the body module
if( shouldStartSecondLife )
startSecondLife(damageInfo);
{
if( !startSecondLife(damageInfo) )
{
#if !RETAIL_COMPATIBLE_CRC
damageInfo->in.m_kill = true;
damageInfo->in.m_enterSecondLife = false;
ActiveBody::attemptDamage(damageInfo);
#endif
}
}
else
{
ActiveBody::attemptDamage(damageInfo);
}
}

// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
void UndeadBody::startSecondLife(DamageInfo *damageInfo)
Bool UndeadBody::startSecondLife(DamageInfo *damageInfo)
{
const UndeadBodyModuleData *data = getUndeadBodyModuleData();

// Flag module as no longer intercepting damage
m_isSecondLife = TRUE;
#if RETAIL_COMPATIBLE_CRC
applySecondLife(damageInfo);
#endif
Comment thread
greptile-apps[bot] marked this conversation as resolved.

// Modify ActiveBody's max health and initial health
setMaxHealth(data->m_secondLifeMaxHealth, FULLY_HEAL);
damageInfo->in.m_enterSecondLife = TRUE;

// Set Armor set flag to use second life armor
setArmorSetFlag(ARMORSET_SECOND_LIFE);

// Fire the Slow Death module. The fact that this is not the result of an onDie will cause the special behavior
Int total = 0;
BehaviorModule** update = getObject()->getBehaviorModules();
for( ; *update; ++update )
{
SlowDeathBehaviorInterface* sdu = (*update)->getSlowDeathBehaviorInterface();
if (sdu != nullptr && sdu->isDieApplicable(damageInfo) )
{
total += sdu->getProbabilityModifier( damageInfo );
}
}
DEBUG_ASSERTCRASH(total > 0, ("Hmm, this is wrong"));
const Int total = SlowDeathBehavior::computeTotalSlowDeathProbability(getObject(), damageInfo);

#if !RETAIL_COMPATIBLE_CRC
if (total == 0)
return false;
#endif

// this returns a value from 1...total, inclusive
Int roll = GameLogicRandomValue(1, total);

for( update = getObject()->getBehaviorModules(); *update; ++update)
// Fire one of the Slow Death modules with Second Life at random.
// The fact that this is not the result of an onDie will cause the special behavior.
for (BehaviorModule** update = getObject()->getBehaviorModules(); *update; ++update)
{
SlowDeathBehaviorInterface* sdu = (*update)->getSlowDeathBehaviorInterface();
if (sdu != nullptr && sdu->isDieApplicable(damageInfo))
{
roll -= sdu->getProbabilityModifier( damageInfo );
if (roll <= 0)
{
#if !RETAIL_COMPATIBLE_CRC
applySecondLife(damageInfo);
#endif
sdu->beginSlowDeath(damageInfo);
return;
return true;
}
}
}

return false;
}

// ------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
void UndeadBody::applySecondLife(DamageInfo *damageInfo)
{
// In second life, bind it to one hit point remaining, then go ahead and take it
damageInfo->in.m_amount = min(damageInfo->in.m_amount, getHealth() - 1);

// Damage first to apply hit effects
ActiveBody::attemptDamage(damageInfo);

// Flag module as no longer intercepting damage
m_isSecondLife = TRUE;

// Modify ActiveBody's max health and initial health
setMaxHealth(getUndeadBodyModuleData()->m_secondLifeMaxHealth, FULLY_HEAL);

// Set Armor set flag to use second life armor
setArmorSetFlag(ARMORSET_SECOND_LIFE);
}

// ------------------------------------------------------------------------------------------------
/** CRC */
Expand Down
Loading