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
6 changes: 5 additions & 1 deletion Generals/Code/GameEngine/Include/GameLogic/Weapon.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,10 @@ struct HistoricWeaponDamageInfo
// The time and location this weapon was fired
UnsignedInt frame;
Coord3D location;
UnsignedInt triggerId; ///< Unique Id assigned to any grouped damage instances

HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) :
frame(f), location(l)
frame(f), location(l), triggerId(0)
{
}
};
Expand Down Expand Up @@ -460,6 +461,8 @@ class WeaponTemplate : public MemoryPoolObject
// actually deal out the damage.
void dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const;
void trimOldHistoricDamage() const;
void trimTriggeredHistoricDamage() const;
void processHistoricDamage(const Object* source, const Coord3D* pos) const;

private:

Expand Down Expand Up @@ -536,6 +539,7 @@ class WeaponTemplate : public MemoryPoolObject
Real m_infantryInaccuracyDist; ///< When this weapon is used against infantry, it can randomly miss by as much as this distance.
UnsignedInt m_suspendFXDelay; ///< The fx can be suspended for any delay, in frames, then they will execute as normal
mutable HistoricWeaponDamageList m_historicDamage;
mutable UnsignedInt m_historicDamageTriggerId;
};

// ---------------------------------------------------------
Expand Down
104 changes: 93 additions & 11 deletions Generals/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ WeaponTemplate::WeaponTemplate() : m_nextTemplate(NULL)
m_continueAttackRange = 0.0f;
m_infantryInaccuracyDist = 0.0f;
m_suspendFXDelay = 0;

m_historicDamageTriggerId = 0;
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -1093,6 +1095,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate
}

//-------------------------------------------------------------------------------------------------
#if RETAIL_COMPATIBLE_CRC
void WeaponTemplate::trimOldHistoricDamage() const
{
UnsignedInt expirationDate = TheGameLogic->getFrame() - TheGlobalData->m_historicDamageLimit;
Expand All @@ -1112,6 +1115,40 @@ void WeaponTemplate::trimOldHistoricDamage() const
}
}
}
#else
void WeaponTemplate::trimOldHistoricDamage() const
{
if (m_historicDamage.empty())
return;

const UnsignedInt currentFrame = TheGameLogic->getFrame();
const UnsignedInt expirationFrame = currentFrame - m_historicBonusTime;

HistoricWeaponDamageList::iterator it = m_historicDamage.begin();

while (it != m_historicDamage.end())
{
if (it->frame <= expirationFrame)
it = m_historicDamage.erase(it);
else
break;
}
}
#endif

//-------------------------------------------------------------------------------------------------
void WeaponTemplate::trimTriggeredHistoricDamage() const
{
HistoricWeaponDamageList::iterator it = m_historicDamage.begin();

while (it != m_historicDamage.end())
{
if (it->triggerId == m_historicDamageTriggerId)
it = m_historicDamage.erase(it);
else
++it;
}
}

//-------------------------------------------------------------------------------------------------
static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real distSqr)
Expand All @@ -1121,27 +1158,20 @@ static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real dis
}

//-------------------------------------------------------------------------------------------------
void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const
#if RETAIL_COMPATIBLE_CRC
void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const
{
if (sourceID == 0) // must have a source
return;

if (victimID == 0 && pos == NULL) // must have some sort of destination
return;

Object *source = TheGameLogic->findObjectByID(sourceID); // might be null...

//
/** @todo We need to rewrite the historic stuff ... if you fire 5 missiles, and the 5th,
// one creates a firestorm ... and then half a second later another volley of 5 missiles
// come in, the second wave of 5 missiles would all do a historic weapon, making 5 more
// firestorms (CBD) */
//

trimOldHistoricDamage();

if( m_historicBonusCount > 0 && m_historicBonusWeapon != this )
{
trimOldHistoricDamage();

Real radSqr = m_historicBonusRadius * m_historicBonusRadius;
Int count = 0;
UnsignedInt frameNow = TheGameLogic->getFrame();
Expand Down Expand Up @@ -1176,6 +1206,58 @@ void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, co
}

}
}
#else
void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const
{
if (m_historicBonusCount > 0 && m_historicBonusWeapon != this)
{
trimOldHistoricDamage();

++m_historicDamageTriggerId;

const Int requiredCount = m_historicBonusCount - 1; // minus 1 since we include ourselves implicitly
if (m_historicDamage.size() >= requiredCount)
{
const Real radSqr = m_historicBonusRadius * m_historicBonusRadius;
Int count = 0;

for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it)
{
if (is2DDistSquaredLessThan(*pos, it->location, radSqr))
{
// This one is close enough in time and distance, so count it. This is tracked by template since it applies
// across units, so don't try to clear historicDamage on success in here.
it->triggerId = m_historicDamageTriggerId;

if (++count == requiredCount)
{
TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos);
trimTriggeredHistoricDamage();
return;
}
}
}
}

// add AFTER checking for historic stuff
m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos));
}
}
#endif

//-------------------------------------------------------------------------------------------------
void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const
{
if (sourceID == 0) // must have a source
return;

if (victimID == 0 && pos == NULL) // must have some sort of destination
return;

Object *source = TheGameLogic->findObjectByID(sourceID); // might be null...

processHistoricDamage(source, pos);

//DEBUG_LOG(("WeaponTemplate::dealDamageInternal: dealing damage %s at frame %d",m_name.str(),TheGameLogic->getFrame()));

Expand Down
6 changes: 5 additions & 1 deletion GeneralsMD/Code/GameEngine/Include/GameLogic/Weapon.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,10 @@ struct HistoricWeaponDamageInfo
// The time and location this weapon was fired
UnsignedInt frame;
Coord3D location;
UnsignedInt triggerId; ///< Unique Id assigned to any grouped damage instances

HistoricWeaponDamageInfo(UnsignedInt f, const Coord3D& l) :
frame(f), location(l)
frame(f), location(l), triggerId(0)
{
}
};
Expand Down Expand Up @@ -480,6 +481,8 @@ class WeaponTemplate : public MemoryPoolObject
// actually deal out the damage.
void dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const;
void trimOldHistoricDamage() const;
void trimTriggeredHistoricDamage() const;
void processHistoricDamage(const Object* source, const Coord3D* pos) const;

private:

Expand Down Expand Up @@ -564,6 +567,7 @@ class WeaponTemplate : public MemoryPoolObject
Bool m_dieOnDetonate;

mutable HistoricWeaponDamageList m_historicDamage;
mutable UnsignedInt m_historicDamageTriggerId;
};

// ---------------------------------------------------------
Expand Down
104 changes: 93 additions & 11 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Weapon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@ WeaponTemplate::WeaponTemplate() : m_nextTemplate(NULL)
m_damageStatusType = OBJECT_STATUS_NONE;
m_suspendFXDelay = 0;
m_dieOnDetonate = FALSE;

m_historicDamageTriggerId = 0;
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -1171,6 +1173,7 @@ UnsignedInt WeaponTemplate::fireWeaponTemplate
}

//-------------------------------------------------------------------------------------------------
#if RETAIL_COMPATIBLE_CRC
void WeaponTemplate::trimOldHistoricDamage() const
{
UnsignedInt expirationDate = TheGameLogic->getFrame() - TheGlobalData->m_historicDamageLimit;
Expand All @@ -1190,6 +1193,40 @@ void WeaponTemplate::trimOldHistoricDamage() const
}
}
}
#else
void WeaponTemplate::trimOldHistoricDamage() const
{
if (m_historicDamage.empty())
return;

const UnsignedInt currentFrame = TheGameLogic->getFrame();
const UnsignedInt expirationFrame = currentFrame - m_historicBonusTime;

HistoricWeaponDamageList::iterator it = m_historicDamage.begin();

while (it != m_historicDamage.end())
{
if (it->frame <= expirationFrame)
it = m_historicDamage.erase(it);
else
break;
}
}
#endif

//-------------------------------------------------------------------------------------------------
void WeaponTemplate::trimTriggeredHistoricDamage() const
{
HistoricWeaponDamageList::iterator it = m_historicDamage.begin();

while (it != m_historicDamage.end())
{
if (it->triggerId == m_historicDamageTriggerId)
it = m_historicDamage.erase(it);
else
++it;
}
}

//-------------------------------------------------------------------------------------------------
static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real distSqr)
Expand All @@ -1199,27 +1236,20 @@ static Bool is2DDistSquaredLessThan(const Coord3D& a, const Coord3D& b, Real dis
}

//-------------------------------------------------------------------------------------------------
void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const
#if RETAIL_COMPATIBLE_CRC
void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const
{
if (sourceID == 0) // must have a source
return;

if (victimID == 0 && pos == NULL) // must have some sort of destination
return;

Object *source = TheGameLogic->findObjectByID(sourceID); // might be null...

//
/** @todo We need to rewrite the historic stuff ... if you fire 5 missiles, and the 5th,
// one creates a firestorm ... and then half a second later another volley of 5 missiles
// come in, the second wave of 5 missiles would all do a historic weapon, making 5 more
// firestorms (CBD) */
//

trimOldHistoricDamage();

if( m_historicBonusCount > 0 && m_historicBonusWeapon != this )
{
trimOldHistoricDamage();

Real radSqr = m_historicBonusRadius * m_historicBonusRadius;
Int count = 0;
UnsignedInt frameNow = TheGameLogic->getFrame();
Expand Down Expand Up @@ -1254,6 +1284,58 @@ void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, co
}

}
}
#else
void WeaponTemplate::processHistoricDamage(const Object* source, const Coord3D* pos) const
{
if (m_historicBonusCount > 0 && m_historicBonusWeapon != this)
{
trimOldHistoricDamage();

++m_historicDamageTriggerId;

const Int requiredCount = m_historicBonusCount - 1; // minus 1 since we include ourselves implicitly
if (m_historicDamage.size() >= requiredCount)
{
const Real radSqr = m_historicBonusRadius * m_historicBonusRadius;
Int count = 0;

for (HistoricWeaponDamageList::iterator it = m_historicDamage.begin(); it != m_historicDamage.end(); ++it)
{
if (is2DDistSquaredLessThan(*pos, it->location, radSqr))
{
// This one is close enough in time and distance, so count it. This is tracked by template since it applies
// across units, so don't try to clear historicDamage on success in here.
it->triggerId = m_historicDamageTriggerId;

if (++count == requiredCount)
{
TheWeaponStore->createAndFireTempWeapon(m_historicBonusWeapon, source, pos);
trimTriggeredHistoricDamage();
return;
}
}
}
}

// add AFTER checking for historic stuff
m_historicDamage.push_back(HistoricWeaponDamageInfo(TheGameLogic->getFrame(), *pos));
}
}
#endif

//-------------------------------------------------------------------------------------------------
void WeaponTemplate::dealDamageInternal(ObjectID sourceID, ObjectID victimID, const Coord3D *pos, const WeaponBonus& bonus, Bool isProjectileDetonation) const
{
if (sourceID == 0) // must have a source
return;

if (victimID == 0 && pos == NULL) // must have some sort of destination
return;

Object *source = TheGameLogic->findObjectByID(sourceID); // might be null...

processHistoricDamage(source, pos);

//DEBUG_LOG(("WeaponTemplate::dealDamageInternal: dealing damage %s at frame %d",m_name.str(),TheGameLogic->getFrame()));

Expand Down
Loading