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 GeneralsMD/Code/GameEngine/Include/Common/DrawModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@ class ObjectDrawInterface

virtual void setSelectable(Bool selectable) = 0;

virtual void setNeedUpdateTurretPositioning(Bool set) = 0;

/**
This call says, "I want the current animation (if any) to take n frames to complete a single cycle".
If it's a looping anim, each loop will take n frames. someday, we may want to add the option to insert
Expand Down
2 changes: 2 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameClient/Drawable.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,8 @@ class Drawable : public Thing,
Real getAnimationScrubScalar( void ) const; // lorenzen // returns 0 to 1... where are we between start and finish?
#endif

void setNeedUpdateTurretPositioning(Bool set);

UnsignedInt getExpirationDate() const { return m_expirationDate; }
void setExpirationDate(UnsignedInt frame) { m_expirationDate = frame; }

Expand Down
4 changes: 4 additions & 0 deletions GeneralsMD/Code/GameEngine/Include/GameLogic/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,8 @@ class Object : public Thing, public Snapshot
// player. These are friend_s for player.
void friend_adjustPowerForPlayer( Bool incoming );

void setNeedUpdateTurretPositioning(Bool set);

protected:

void setOrRestoreTeam( Team* team, Bool restoring );
Expand Down Expand Up @@ -813,6 +815,8 @@ class Object : public Thing, public Snapshot
Bool m_singleUseCommandUsed;
Bool m_isReceivingDifficultyBonus;

Bool m_turretNeedPositioning;

};

// deleteInstance is not meant to be used with Object in order to require the use of TheGameLogic->destroyObject()
Expand Down
11 changes: 11 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameClient/Drawable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,17 @@ Real Drawable::getAnimationScrubScalar( void ) const // lorenzen
}
#endif

//-------------------------------------------------------------------------------------------------
void Drawable::setNeedUpdateTurretPositioning(Bool set)
{
for (DrawModule** dm = getDrawModules(); *dm; ++dm)
{
ObjectDrawInterface* di = (*dm)->getObjectDrawInterface();
if (di)
di->setNeedUpdateTurretPositioning(set);
}
}

//-------------------------------------------------------------------------------------------------
Int Drawable::getPristineBonePositions(const char* boneNamePrefix, Int startIndex, Coord3D* positions, Matrix3D* transforms, Int maxBones) const
{
Expand Down
9 changes: 9 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/AI/TurretAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1219,13 +1219,17 @@ StateReturnType TurretAIRecenterTurretState::update()
if( getMachineOwner()->testStatus( OBJECT_STATUS_UNDER_CONSTRUCTION))
return STATE_CONTINUE;//ML so that under-construction base-defenses do not re-center while under construction

getMachineOwner()->setNeedUpdateTurretPositioning(TRUE);

TurretAI* turret = getTurretAI();
Bool angleAligned = turret->friend_turnTowardsAngle(turret->getNaturalTurretAngle(), 0.5f, 0.0f);
Bool pitchAligned = turret->friend_turnTowardsPitch(turret->getNaturalTurretPitch(), 0.5f);

if( angleAligned && pitchAligned )
{
getMachineOwner()->setNeedUpdateTurretPositioning(FALSE);
return STATE_SUCCESS;
}

return STATE_CONTINUE;
}
Expand Down Expand Up @@ -1373,11 +1377,16 @@ StateReturnType TurretAIIdleScanState::update()
if( getMachineOwner()->testStatus( OBJECT_STATUS_UNDER_CONSTRUCTION))
return STATE_CONTINUE;//ML so that under-construction base-defenses do not idle-scan while under construction

getMachineOwner()->setNeedUpdateTurretPositioning(TRUE);

Bool angleAligned = getTurretAI()->friend_turnTowardsAngle(getTurretAI()->getNaturalTurretAngle() + m_desiredAngle, 0.5f, 0.0f);
Bool pitchAligned = getTurretAI()->friend_turnTowardsPitch(getTurretAI()->getNaturalTurretPitch(), 0.5f);

if( angleAligned && pitchAligned )
{
getMachineOwner()->setNeedUpdateTurretPositioning(FALSE);
return STATE_SUCCESS;
}

return STATE_CONTINUE;
}
Expand Down
13 changes: 13 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,8 @@ Object::Object( const ThingTemplate *tt, const ObjectStatusMaskType &objectStatu
m_soleHealingBenefactorID = INVALID_ID; ///< who is the only other object that can give me this non-stacking heal benefit?
m_soleHealingBenefactorExpirationFrame = 0; ///< on what frame can I accept healing (thus to switch) from a new benefactor

m_turretNeedPositioning = FALSE;

// TheSuperHackers @bugfix Mauller/xezon 02/08/2025 sendObjectCreated needs calling before CreateModule's are initialized to prevent drawable related crashes
// This predominantly occurs with the veterancy create module when the chemical suits upgrade is unlocked as it tries to set the terrain decal.

Expand Down Expand Up @@ -4452,6 +4454,7 @@ void Object::loadPostProcess()
else
m_containedBy = NULL;

setNeedUpdateTurretPositioning(TRUE);
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -6452,3 +6455,13 @@ ObjectID Object::calculateCountermeasureToDivertTo( const Object& victim )
}
return INVALID_ID;
}

//-------------------------------------------------------------------------------------------------
void Object::setNeedUpdateTurretPositioning(Bool set)
{
if(m_turretNeedPositioning != set && getDrawable())
{
m_turretNeedPositioning = set;
getDrawable()->setNeedUpdateTurretPositioning(set);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ void AIUpdateInterface::setTurretTargetObject(WhichTurretType tur, Object* o, Bo
{
if (m_turretAI[tur])
{
getObject()->setNeedUpdateTurretPositioning(TRUE);
m_turretAI[tur]->setTurretTargetObject(o, forceAttacking);
}
}
Expand All @@ -682,6 +683,7 @@ void AIUpdateInterface::setTurretTargetPosition(WhichTurretType tur, const Coord
{
if (m_turretAI[tur])
{
getObject()->setNeedUpdateTurretPositioning(TRUE);
m_turretAI[tur]->setTurretTargetPosition(pos);
}
}
Expand All @@ -691,6 +693,7 @@ void AIUpdateInterface::setTurretEnabled(WhichTurretType tur, Bool enabled)
{
if (m_turretAI[tur])
{
getObject()->setNeedUpdateTurretPositioning(TRUE);
m_turretAI[tur]->setTurretEnabled( enabled );
}
}
Expand All @@ -700,6 +703,7 @@ void AIUpdateInterface::recenterTurret(WhichTurretType tur)
{
if (m_turretAI[tur])
{
getObject()->setNeedUpdateTurretPositioning(TRUE);
m_turretAI[tur]->recenterTurret();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,8 @@ class W3DModelDraw : public DrawModule, public ObjectDrawInterface
virtual Real getAnimationScrubScalar( void ) const;
#endif

virtual void setNeedUpdateTurretPositioning(Bool set);

virtual ObjectDrawInterface* getObjectDrawInterface() { return this; }
virtual const ObjectDrawInterface* getObjectDrawInterface() const { return this; }

Expand Down Expand Up @@ -508,6 +510,9 @@ class W3DModelDraw : public DrawModule, public ObjectDrawInterface
Bool m_pauseAnimation;
Int m_animationMode;

Bool m_needUpdateTurretPosition;
Bool m_doHandleRecoil;

void adjustAnimation(const ModelConditionInfo* prevState, Real prevAnimFraction);
Real getCurrentAnimFraction() const;
void applyCorrectModelStateAnimation();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,8 @@ W3DModelDraw::W3DModelDraw(Thing *thing, const ModuleData* moduleData) : DrawMod
}
m_needRecalcBoneParticleSystems = false;
m_fullyObscuredByShroud = false;
m_needUpdateTurretPosition = true;
m_doHandleRecoil = true;

// only validate the current time-of-day and weather conditions by default.
getW3DModelDrawModuleData()->validateStuffForTimeAndWeather(getDrawable(),
Expand Down Expand Up @@ -2417,7 +2419,7 @@ void W3DModelDraw::stopClientParticleSystems()
*/
void W3DModelDraw::handleClientTurretPositioning()
{
if (!m_curState || !(m_curState->m_validStuff & ModelConditionInfo::TURRETS_VALID))
if (!m_curState || !(m_curState->m_validStuff & ModelConditionInfo::TURRETS_VALID) || !m_needUpdateTurretPosition)
return;

for (int tslot = 0; tslot < MAX_TURRETS; ++tslot)
Expand Down Expand Up @@ -2491,14 +2493,18 @@ void W3DModelDraw::handleClientTurretPositioning()

@todo fix me someday (srj)
*/
// TheSuperHackers @performance IamInnocent 01/01/26 - Adjust Turret Positioning, Recoil, and Muzzle to only Update when Necessary
void W3DModelDraw::handleClientRecoil()
{
const W3DModelDrawModuleData* d = getW3DModelDrawModuleData();
if (!(m_curState->m_validStuff & ModelConditionInfo::BARRELS_VALID))
if (!(m_curState->m_validStuff & ModelConditionInfo::BARRELS_VALID) || !m_doHandleRecoil)
{
return;
}

// Set the Requirement of Recoil Update to False first, if there is any recoil while checking, it is set to True.
m_doHandleRecoil = FALSE;

// do recoil, if any
for (int wslot = 0; wslot < WEAPONSLOT_COUNT; ++wslot)
{
Expand All @@ -2518,6 +2524,8 @@ void W3DModelDraw::handleClientRecoil()
Bool hidden = recoils[i].m_state != WeaponRecoilInfo::RECOIL_START;
//DEBUG_LOG(("adjust muzzleflash %08lx for Draw %08lx state %s to %d at frame %d",subObjToHide,this,m_curState->m_description.str(),hidden?1:0,TheGameLogic->getFrame()));
barrels[i].setMuzzleFlashHidden(m_renderObject, hidden);
if(!hidden)
m_doHandleRecoil = TRUE; // There's more recoil, need to update
}

const Real TINY_RECOIL = 0.01f;
Expand All @@ -2542,6 +2550,7 @@ void W3DModelDraw::handleClientRecoil()
{
recoils[i].m_state = WeaponRecoilInfo::SETTLE;
}
m_doHandleRecoil = TRUE; // There's more recoil, need to update
break;

case WeaponRecoilInfo::SETTLE:
Expand All @@ -2551,6 +2560,7 @@ void W3DModelDraw::handleClientRecoil()
recoils[i].m_shift = 0.0f;
recoils[i].m_state = WeaponRecoilInfo::IDLE;
}
m_doHandleRecoil = TRUE; // There's more recoil, need to update
break;
}

Expand Down Expand Up @@ -3764,6 +3774,8 @@ Bool W3DModelDraw::handleWeaponFireFX(WeaponSlotType wslot, Int specificBarrelTo

if (info.m_recoilBone || info.m_muzzleFlashBone)
{
m_doHandleRecoil = TRUE;

//DEBUG_LOG(("START muzzleflash %08lx for Draw %08lx state %s at frame %d",info.m_muzzleFlashBone,this,m_curState->m_description.str(),TheGameLogic->getFrame()));
WeaponRecoilInfo& recoil = m_weaponRecoilInfoVec[wslot][specificBarrelToUse];
recoil.m_state = WeaponRecoilInfo::RECOIL_START;
Expand Down Expand Up @@ -3906,6 +3918,8 @@ void W3DModelDraw::rebuildWeaponRecoilInfo(const ModelConditionInfo* state)
}
}
}
// Resetting Model calls for this function, everytime new recoil Info is configured, need to configure to check for new recoil or Muzzle
m_doHandleRecoil = TRUE;
}

//-------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -4016,6 +4030,12 @@ void W3DModelDraw::updateSubObjects()
}
}

//-------------------------------------------------------------------------------------------------
void W3DModelDraw::setNeedUpdateTurretPositioning(Bool set)
{
m_needUpdateTurretPosition = set;
}

// ------------------------------------------------------------------------------------------------
/** CRC */
// ------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -4275,6 +4295,9 @@ void W3DModelDraw::loadPostProcess( void )
// extend base class
DrawModule::loadPostProcess();

m_needUpdateTurretPosition = TRUE;
m_doHandleRecoil = TRUE;

}

// ------------------------------------------------------------------------------------------------
Expand Down
Loading