Morale changes for AI soldiers:

- GetMoraleModifier: use bMorale for both player and AI.
- CalcSuppressionTolerance: use morale as a base for tolerance for AI soldiers.
- HandleSuppressionFire: morale loss for AI soldiers.
- EVENT_BeginMercTurn: increase morale for AI soldiers.
- TacticalCreateSoldier: Set morale = 60 + 2 * bExpLevel + Random(20) when creating AI soldier.

NEW_SUPPRESSION_CODE: UseGun, UseGunNCTH: reduce shock when firing gun.
AI_NEW_MORALE: limit AI morale depending on morale and shock level.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@9181 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Sevenfm
2021-10-15 05:52:09 +00:00
parent 7a7f554908
commit 7978ad77f3
6 changed files with 98 additions and 32 deletions
+14 -2
View File
@@ -170,7 +170,19 @@ INT8 GetMoraleModifier( SOLDIERTYPE * pSoldier )
{
INT8 morale = 0;
if (pSoldier->flags.uiStatusFlags & SOLDIER_PC)
// sevenfm: use bMorale for both player and AI
if (pSoldier->aiData.bMorale > 50)
{
// give +1 at 55, +3 at 65, up to +5 at 95 and above
morale = (pSoldier->aiData.bMorale - 45) / 10;
}
else
{
// give penalties down to -20 at 0 (-2 at 45, -4 by 40...)
morale = (pSoldier->aiData.bMorale - 50) * 2 / 5;
}
/*if (pSoldier->flags.uiStatusFlags & SOLDIER_PC)
{
if (pSoldier->aiData.bMorale > 50)
{
@@ -199,7 +211,7 @@ INT8 GetMoraleModifier( SOLDIERTYPE * pSoldier )
default:
morale = 0;
}
}
}*/
// Flugente: morale modifiers
morale = max( morale, morale * pSoldier->GetMoraleModifier( ) );
+13 -28
View File
@@ -8755,13 +8755,8 @@ INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier )
INT8 bToleranceSkill;
UINT8 ubMaxShock = gGameExternalOptions.ubMaxSuppressionShock;
if (pSoldier->flags.uiStatusFlags & SOLDIER_PC)
bToleranceMorale = pSoldier->aiData.bMorale;
else
bToleranceMorale = (20 + 80 * pSoldier->stats.bLife / max(OKLIFE, pSoldier->stats.bLifeMax) - 40 * min(ubMaxShock, pSoldier->aiData.bShock) / max(1, ubMaxShock));
// limit base tolerance to 75% when having max morale and experience level
bToleranceSkill = (bToleranceMorale + 20 * pSoldier->stats.bExpLevel) / 4;
bToleranceSkill = (pSoldier->aiData.bMorale + 20 * pSoldier->stats.bExpLevel) / 4;
// calculate tolerance as percent of max tolerance from INI
bTolerance = gGameExternalOptions.ubSuppressionToleranceMax * bToleranceSkill / 100;
}
@@ -9020,27 +9015,6 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
else
sFinalSuppressionEffectiveness = sFinalShooterDependentEffectiveness * gGameExternalOptions.usSuppressionEffectivenessAI / 100;
// INI-Controlled intensity. SuppressionEffectiveness acts as a percentage applied to the number of lost APs.
// To turn off the entire Suppression system, simply set the INI value to 0. (0% AP Loss)
// The default is obviously 100%. You can increase or decrease it, at will.
// PLEASE NOTE that AP loss governs ALL OTHER SUPPRESSION EFFECTS.
// sevenfm: commented out duplicated code: we don't want to apply ubFinalSuppressionEffectivness twice
// ubPointsLost = ( ubPointsLost * sFinalSuppressionEffectiveness ) / 100;
// This is an upper cap for the number of APs we can lose per attack.
// sevenfm: commented out duplicated code:
/*
if (usLimitSuppressionAPsLostPerAttack > 0)
{
if (ubPointsLost > usLimitSuppressionAPsLostPerAttack)
{
// Flugente: eh.. wouldn't this _always_ be 255? I suspect this should be __min
//ubPointsLost = __max(255,(UINT8)usLimitSuppressionAPsLostPerAttack);
ubPointsLost = __min(255,(UINT8)usLimitSuppressionAPsLostPerAttack);
}
}
*/
// INI-Controlled intensity. SuppressionEffectiveness acts as a percentage applied to the number of lost APs.
// To turn off the entire Suppression system, simply set the INI value to 0. (0% AP Loss)
// The default is obviously 100%. You can increase or decrease it, at will.
@@ -9134,7 +9108,18 @@ void HandleSuppressionFire( UINT8 ubTargetedMerc, UINT8 ubCausedAttacker )
{
for ( ubLoop2 = 0; ubLoop2 < (sPointsLost / APBPConstants[AP_LOST_PER_MORALE_DROP]); ubLoop2++ )
{
HandleMoraleEvent( pSoldier, MORALE_SUPPRESSED, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
// sevenfm: morale loss for AI soldiers
if (pSoldier->ubProfile == NO_PROFILE)
{
if (IS_MERC_BODY_TYPE(pSoldier))
{
pSoldier->aiData.bMorale = max(20 + 2 * pSoldier->stats.bExpLevel, pSoldier->aiData.bMorale - 4);
}
}
else
{
HandleMoraleEvent(pSoldier, MORALE_SUPPRESSED, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ);
}
// sevenfm: update ubLastMorale
pSoldier->ubLastMorale++;
}
+12
View File
@@ -7967,6 +7967,18 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
// reduce the effects of any residual shock from past injuries by half
this->aiData.bShock /= 2;
// sevenfm: increase morale for AI soldiers
if (this->ubProfile == NO_PROFILE &&
!(this->flags.uiStatusFlags & SOLDIER_VEHICLE) &&
!AM_A_ROBOT(this) &&
!ARMED_VEHICLE(this) &&
this->aiData.bShock == 0 &&
!this->aiData.bUnderFire &&
this->aiData.bMorale < 80 + 2 * this->stats.bExpLevel)
{
this->aiData.bMorale = __min(80 + 2 * this->stats.bExpLevel, this->aiData.bMorale + 2 + this->stats.bExpLevel / 5);
}
// if this person has heard a noise that hasn't been investigated
if ( this->aiData.sNoiseGridno != NOWHERE )
{
+6
View File
@@ -966,6 +966,12 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *
Soldier.uiAnimSubFlags |= SUB_ANIM_BIGGUYTHREATENSTANCE;
}
// sevenfm: max morale for AI soldiers
if (Soldier.ubProfile == NO_PROFILE)
{
Soldier.aiData.bMorale = 60 + 2 * Soldier.stats.bExpLevel + Random(20);
}
//For inventory, look for any face class items that may be located in the big pockets and if found, move
//that item to a face slot and clear the pocket!
if( Soldier.bTeam != OUR_TEAM )
+48
View File
@@ -2460,6 +2460,30 @@ BOOLEAN UseGunNCTH( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
OBJECTTYPE* pObjAttHand = pSoldier->GetUsedWeapon( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
UINT16 usUBItem = pSoldier->GetUsedWeaponNumber( &pSoldier->inv[ pSoldier->ubAttackingHand ] );
// sevenfm: reduce shock when firing gun, for autofire shots - apply once
SOLDIERTYPE* pTarget = SimpleFindSoldier(sTargetGridNo, pSoldier->bTargetLevel);
if (gGameExternalOptions.fNewSuppressionCode &&
Item[usUBItem].usItemClass == IC_GUN &&
pTarget &&
(pSoldier->bDoBurst == 1 || pSoldier->bDoBurst == 0))
{
UINT16 noisefactor = GetPercentNoiseVolume(pObjHand);
UINT8 ubDamage = Weapon[usUBItem].ubImpact;
INT8 bShotsToFire = 1;
if (pSoldier->bDoBurst)
{
bShotsToFire = pSoldier->bDoAutofire ? pSoldier->bDoAutofire : GetShotsPerBurst(pObjHand);
}
// calculate shock reduction value 0-50%
UINT8 ubShockReductPercent = (50 - 400 / (bShotsToFire + 8)) * noisefactor * Weapon[usUBItem].ubAttackVolume / (50 * 100);
if (pSoldier->IsValidSecondHandShot())
ubShockReductPercent = ubShockReductPercent * 3 / 2;
ubShockReductPercent = __min(50, ubShockReductPercent);
pSoldier->aiData.bShock -= pSoldier->aiData.bShock * ubShockReductPercent / 100;
}
// CALC MUZZLE SWAY
if ( Item[ usUBItem ].usItemClass == IC_THROWING_KNIFE )
{
@@ -3201,6 +3225,30 @@ BOOLEAN UseGun( SOLDIERTYPE *pSoldier , INT32 sTargetGridNo )
usItemNum = pSoldier->usAttackingWeapon;
// sevenfm: reduce shock when firing gun, for autofire shots - apply once
SOLDIERTYPE* pTarget = SimpleFindSoldier(sTargetGridNo, pSoldier->bTargetLevel);
if (gGameExternalOptions.fNewSuppressionCode &&
Item[usUBItem].usItemClass == IC_GUN &&
pTarget &&
(pSoldier->bDoBurst == 1 || pSoldier->bDoBurst == 0))
{
UINT16 noisefactor = GetPercentNoiseVolume(pObjUsed);
UINT8 ubDamage = Weapon[usUBItem].ubImpact;
INT8 bShotsToFire = 1;
if (pSoldier->bDoBurst)
{
bShotsToFire = pSoldier->bDoAutofire ? pSoldier->bDoAutofire : GetShotsPerBurst(pObjUsed);
}
// calculate shock reduction value 0-50%
UINT8 ubShockReductPercent = (50 - 400 / (bShotsToFire + 8)) * noisefactor * Weapon[usUBItem].ubAttackVolume / (50 * 100);
if (pSoldier->IsValidSecondHandShot())
ubShockReductPercent = ubShockReductPercent * 3 / 2;
ubShockReductPercent = __min(50, ubShockReductPercent);
pSoldier->aiData.bShock -= pSoldier->aiData.bShock * ubShockReductPercent / 100;
}
// DEDUCT APs
if (pSoldier->bDoBurst)
{
+5 -2
View File
@@ -3925,10 +3925,13 @@ INT8 CalcMoraleNew(SOLDIERTYPE *pSoldier)
}
// limit AI morale when soldier is under heavy fire
if (pSoldier->ShockLevelPercent() > 75)
/*if (pSoldier->ShockLevelPercent() > 75)
bMoraleCategory = min(bMoraleCategory, MORALE_NORMAL);
else if (pSoldier->ShockLevelPercent() > 50)
bMoraleCategory = min(bMoraleCategory, MORALE_CONFIDENT);
bMoraleCategory = min(bMoraleCategory, MORALE_CONFIDENT);*/
// limit AI morale depending on morale and shock level
bMoraleCategory = min(bMoraleCategory, max(MORALE_WORRIED, ((pSoldier->aiData.bOrders == SEEKENEMY ? pSoldier->aiData.bMorale + 20 : pSoldier->aiData.bMorale) * 100 / (100 + pSoldier->ShockLevelPercent())) / 20));
// prevent hopeless morale when not under attack
if (bMoraleCategory == MORALE_HOPELESS && !pSoldier->aiData.bUnderFire)