Skip to content

Commit 56641af

Browse files
committed
bugfix(module): Fix missing horde condition of Nationalism and Fanaticism weapon bonuses
This fix is opt-in by setting Action=HORDE_FIXED in HordeUpdate behavior modules
1 parent d61ce1f commit 56641af

File tree

4 files changed

+147
-118
lines changed

4 files changed

+147
-118
lines changed

GeneralsMD/Code/GameEngine/Include/GameLogic/Module/AIUpdate.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class AssaultTransportAIInterface;
6060
class JetAIUpdate;
6161

6262
enum AIStateType CPP_11(: Int);
63+
enum HordeActionType CPP_11(: Int);
6364
enum ObjectID CPP_11(: Int);
6465

6566

@@ -562,7 +563,8 @@ class AIUpdateInterface : public UpdateModule, public AICommandInterface
562563
void setAttitude( AttitudeType tude ); ///< set the behavior modifier for this agent
563564

564565
// Common AI "status" effects -------------------------------------------------------------------
565-
void evaluateMoraleBonus( void );
566+
void evaluateMoraleBonus( Bool inHorde, Bool allowNationalism, HordeActionType type );
567+
void evaluateMoraleBonusImpl( Bool inHorde, Bool allowNationalism, Bool classicImplementation );
566568

567569
#ifdef ALLOW_DEMORALIZE
568570
// demoralization ... what a nifty word to write.

GeneralsMD/Code/GameEngine/Include/GameLogic/Module/HordeUpdate.h

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,33 @@ class UpgradeTemplate;
4444
//-------------------------------------------------------------------------------------------------
4545
//-------------------------------------------------------------------------------------------------
4646

47+
// TheSuperHackers @bugfix Adds the new HORDEACTION_HORDE_FIXED type.
48+
//
49+
// TheSuperHackers @todo If we want more control over the horde setup, then we need to implement
50+
// filters for separate weapon bonuses and required upgrades. But adding more behavior modules will
51+
// be a performance concern. Example INI setup:
52+
//
53+
// Behavior = HordeUpdate ModuleTag
54+
// Action = NATIONALISM
55+
// ;ApplyWeaponBonus = NATIONALISM
56+
// UpgradeRequired = Upgrade_Nationalism
57+
// End
58+
//
4759
enum HordeActionType CPP_11(: Int)
4860
{
49-
HORDEACTION_HORDE = 0,
61+
HORDEACTION_HORDE, ///< Classic action, applies the Horde bonus correctly, but Nationalism and Fanaticism bonuses are not removed after leaving horde.
62+
HORDEACTION_HORDE_FIXED, ///< Applies the Horde, Nationalism and Fanaticism bonuses correctly.
5063

51-
HORDEACTION_COUNT
64+
HORDEACTION_COUNT,
65+
HORDEACTION_DEFAULT = HORDEACTION_HORDE_FIXED, ///< Uses the fixed horde action by default. This is retail compatible, because all modules explicitly set Action = HORDE.
5266
};
5367

5468
#ifdef DEFINE_HORDEACTION_NAMES
5569
static const char *TheHordeActionTypeNames[] =
5670
{
5771
"HORDE",
72+
"HORDE_FIXED",
73+
5874
NULL
5975
};
6076
#endif
@@ -89,7 +105,7 @@ class HordeUpdateInterface
89105
virtual Bool hasFlag() const = 0;
90106
virtual Bool isTrueHordeMember() const = 0;
91107
virtual Bool isAllowedNationalism() const = 0;
92-
108+
virtual HordeActionType getHordeActionType() const = 0;
93109
};
94110

95111
//-------------------------------------------------------------------------------------------------
@@ -107,9 +123,10 @@ class HordeUpdate : public UpdateModule, public HordeUpdateInterface
107123

108124
virtual void onDrawableBoundToObject();
109125
virtual Bool isInHorde() const { return m_inHorde; }
126+
virtual Bool hasFlag() const { return m_hasFlag; }
110127
virtual Bool isTrueHordeMember() const { return m_trueHordeMember && m_inHorde; }
111128
virtual Bool isAllowedNationalism() const;
112-
virtual Bool hasFlag() const { return m_hasFlag; }
129+
virtual HordeActionType getHordeActionType() const { return getHordeUpdateModuleData()->m_action; };
113130
virtual UpdateSleepTime update(); ///< update this object's AI
114131

115132
protected:
@@ -119,8 +136,8 @@ class HordeUpdate : public UpdateModule, public HordeUpdateInterface
119136

120137
private:
121138
UnsignedInt m_lastHordeRefreshFrame; //Just like it sounds
122-
Bool m_inHorde; //I amy be a trueMember, or I may merely inherit hordehood from a neighbor who is
123-
Bool m_trueHordeMember; //meaning, I have enough hordesman near me to qualify
139+
Bool m_inHorde; //I may be a true member, or I may merely inherit hordehood from a neighbor who is
140+
Bool m_trueHordeMember; //meaning, I have enough hordesmen near me to qualify
124141
Bool m_hasFlag;
125142

126143
};

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate.cpp

Lines changed: 103 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -4678,56 +4678,39 @@ setTmpValue(now);
46784678

46794679
// ------------------------------------------------------------------------------------------------
46804680
// ------------------------------------------------------------------------------------------------
4681-
void AIUpdateInterface::evaluateMoraleBonus( void )
4681+
void AIUpdateInterface::evaluateMoraleBonusImpl( Bool inHorde, Bool allowNationalism, Bool classicImplementation )
46824682
{
46834683
Object *us = getObject();
4684-
#ifdef ALLOW_DEMORALIZE
4685-
Bool demoralized = isDemoralized();
4686-
#endif
4687-
Bool horde = FALSE;
4688-
Bool nationalism = FALSE;
4689-
Bool fanaticism = FALSE;
4690-
4691-
// do we have nationalism
4692-
///@todo Find a better way to represent nationalism without hardcoding here (CBD)
4693-
static const UpgradeTemplate *nationalismTemplate = TheUpgradeCenter->findUpgrade( "Upgrade_Nationalism" );
4694-
DEBUG_ASSERTCRASH( nationalismTemplate != NULL, ("AIUpdateInterface::evaluateMoraleBonus - Nationalism upgrade not found") );
4695-
Player *player = us->getControllingPlayer();
4696-
if( player && player->hasUpgradeComplete( nationalismTemplate ) )
4697-
nationalism = TRUE;
4698-
4699-
// do we have fanaticism
4700-
///@todo Find a better way to represent fanaticism without hardcoding here (MAL)
4701-
static const UpgradeTemplate *fanaticismTemplate = TheUpgradeCenter->findUpgrade( "Upgrade_Fanaticism" );
4702-
DEBUG_ASSERTCRASH( fanaticismTemplate != NULL, ("AIUpdateInterface::evaluateMoraleBonus - Fanaticism upgrade not found") );
4703-
if( player && player->hasUpgradeComplete( fanaticismTemplate ) )
4704-
fanaticism = TRUE;
4705-
4706-
// are we in a horde
4707-
HordeUpdateInterface *hui;
4708-
for( BehaviorModule** u = us->getBehaviorModules(); *u; ++u )
4709-
{
4710-
4711-
hui = (*u)->getHordeUpdateInterface();
4712-
if( hui && hui->isInHorde() )
4713-
{
4714-
horde = TRUE;
4715-
4716-
if( !hui->isAllowedNationalism() )
4717-
{
4718-
// Sorry CBD and MAL, but the cancer has spread to the lymph nodes. After Alpha, just pump full of painkillers.
4719-
nationalism = FALSE;
4720-
fanaticism = FALSE;
4721-
}
4722-
}
4723-
4724-
}
47254684

47264685
#ifdef ALLOW_DEMORALIZE
47274686
// if we are are not demoralized we can have horde and nationalism effects
4728-
if( demoralized == FALSE )
4687+
if( !isDemoralized() )
47294688
#endif
47304689
{
4690+
Player *player = us->getControllingPlayer();
4691+
4692+
Bool nationalism;
4693+
Bool fanaticism;
4694+
4695+
if (player && allowNationalism)
4696+
{
4697+
// do we have nationalism
4698+
///@todo Find a better way to represent nationalism without hard coding here (CBD)
4699+
static const UpgradeTemplate *nationalismTemplate = TheUpgradeCenter->findUpgrade( "Upgrade_Nationalism" );
4700+
DEBUG_ASSERTCRASH( nationalismTemplate != NULL, ("AIUpdateInterface::evaluateMoraleBonusImpl - Nationalism upgrade not found") );
4701+
nationalism = player->hasUpgradeComplete( nationalismTemplate );
4702+
4703+
// do we have fanaticism
4704+
///@todo Find a better way to represent fanaticism without hard coding here (MAL)
4705+
static const UpgradeTemplate *fanaticismTemplate = TheUpgradeCenter->findUpgrade( "Upgrade_Fanaticism" );
4706+
DEBUG_ASSERTCRASH( fanaticismTemplate != NULL, ("AIUpdateInterface::evaluateMoraleBonusImpl - Fanaticism upgrade not found") );
4707+
fanaticism = player->hasUpgradeComplete( fanaticismTemplate );
4708+
}
4709+
else
4710+
{
4711+
nationalism = FALSE;
4712+
fanaticism = FALSE;
4713+
}
47314714

47324715
#ifdef ALLOW_DEMORALIZE
47334716
// demoralized
@@ -4739,29 +4722,61 @@ void AIUpdateInterface::evaluateMoraleBonus( void )
47394722
//if ( draw && !us->isKindOf( KINDOF_PORTABLE_STRUCTURE ) )
47404723
// draw->setTerrainDecal(TERRAIN_DECAL_NONE);
47414724

4742-
// horde
4743-
if( horde )
4725+
if (classicImplementation)
47444726
{
4745-
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_HORDE );
4727+
// TheSuperHackers @info The classic implementation.
4728+
// Is not great, because Nationalism and Fanaticism bonuses are not disabled when leaving the horde.
47464729

4730+
if( inHorde )
4731+
{
4732+
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_HORDE );
4733+
}
4734+
else
4735+
{
4736+
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_HORDE );
4737+
}
4738+
4739+
if( nationalism )
4740+
{
4741+
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_NATIONALISM );
4742+
4743+
if ( fanaticism )
4744+
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_FANATICISM );
4745+
else
4746+
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_FANATICISM );
4747+
}
4748+
else
4749+
{
4750+
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_NATIONALISM );
4751+
}
47474752
}
47484753
else
4749-
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_HORDE );
4750-
4751-
// nationalism
4752-
if( nationalism )
4753-
{
4754-
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_NATIONALISM );
4755-
// fanaticism
4756-
if ( fanaticism )
4757-
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_FANATICISM );// FOR THE NEW GC INFANTRY GENERAL
4758-
else
4759-
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_FANATICISM );
4760-
}
4761-
else
4762-
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_NATIONALISM );
4754+
{
4755+
// TheSuperHackers @bugfix The fixed implementation.
4756+
// Nationalism and Fanaticism are now tied to the horde status.
4757+
// And Fanaticism is no longer dependent on Nationalism.
47634758

4759+
if( inHorde )
4760+
{
4761+
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_HORDE );
4762+
4763+
if( nationalism )
4764+
{
4765+
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_NATIONALISM );
4766+
}
47644767

4768+
if( fanaticism )
4769+
{
4770+
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_FANATICISM );
4771+
}
4772+
}
4773+
else
4774+
{
4775+
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_HORDE );
4776+
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_NATIONALISM );
4777+
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_FANATICISM );
4778+
}
4779+
}
47654780

47664781
}
47674782
#ifdef ALLOW_DEMORALIZE
@@ -4771,28 +4786,37 @@ void AIUpdateInterface::evaluateMoraleBonus( void )
47714786
// demoralized
47724787
us->setWeaponBonusCondition( WEAPONBONUSCONDITION_DEMORALIZED );
47734788

4774-
// we cannot have horde bonus condition
4789+
// we cannot have horde bonuses
47754790
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_HORDE );
4791+
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_NATIONALISM );
4792+
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_FANATICISM );
4793+
47764794
Drawable *draw = us->getDrawable();
47774795
if( draw && !us->isKindOf( KINDOF_PORTABLE_STRUCTURE ) )
47784796
{
47794797
draw->setTerrainDecal(TERRAIN_DECAL_DEMORALIZED);
47804798
}
47814799

4782-
// we cannot have nationalism bonus condition
4783-
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_NATIONALISM );
4784-
us->clearWeaponBonusCondition( WEAPONBONUSCONDITION_FANATICISM );
4785-
47864800
}
47874801
#endif
47884802

4789-
/*
4790-
UnicodeString msg;
4791-
msg.format( L"'%S' Horde=%d,Nationalism=%d,Demoralized=%d",
4792-
us->getTemplate()->getName().str(), horde, nationalism, demoralized );
4793-
TheInGameUI->message( msg );
4794-
*/
4803+
}
4804+
4805+
// ------------------------------------------------------------------------------------------------
4806+
// ------------------------------------------------------------------------------------------------
4807+
void AIUpdateInterface::evaluateMoraleBonus( Bool inHorde, Bool allowNationalism, HordeActionType type )
4808+
{
4809+
switch (type)
4810+
{
4811+
case HORDEACTION_HORDE:
4812+
evaluateMoraleBonusImpl(inHorde, allowNationalism, TRUE);
4813+
break;
47954814

4815+
default:
4816+
case HORDEACTION_HORDE_FIXED:
4817+
evaluateMoraleBonusImpl(inHorde, allowNationalism, FALSE);
4818+
break;
4819+
}
47964820
}
47974821

47984822
#ifdef ALLOW_DEMORALIZE
@@ -4809,12 +4833,16 @@ void AIUpdateInterface::setDemoralized( UnsignedInt durationInFrames )
48094833
if( (prevDemoralizedFrames == 0 && m_demoralizedFramesLeft > 0) ||
48104834
(prevDemoralizedFrames > 0 && m_demoralizedFramesLeft == 0) )
48114835
{
4812-
48134836
// evaluate demoralization, nationalism, and horde effect as they are all intertwined
4814-
evaluateMoraleBonus();
4815-
4837+
Object *us = getObject();
4838+
for( BehaviorModule** u = us->getBehaviorModules(); *u; ++u )
4839+
{
4840+
if ( HordeUpdateInterface *hui = (*u)->getHordeUpdateInterface() )
4841+
{
4842+
evaluateMoraleBonus( hui->isInHorde(), hui->isAllowedNationalism(), hui->getHordeActionType() );
4843+
}
4844+
}
48164845
}
4817-
48184846
}
48194847
#endif
48204848

0 commit comments

Comments
 (0)