From 6d14282538cdac9d8c74cb40d00fc9a6fdb97517 Mon Sep 17 00:00:00 2001 From: Sevenfm Date: Fri, 15 Oct 2021 08:44:57 +0000 Subject: [PATCH] NEW_SUPPRESSION_CODE: - use effective experience level when calculating base suppression tolerance, so nearby squad leaders may raise effective level and help fight suppression - if NEARBY_FRIENDLIES_AFFECT_TOLERANCE option is active, nearby friends can help increase suppression tolerance, up to +-3 points added depending on distance, only for merc bodytypes CheckStatusNearbyFriendlies: minor code improvements, fixed variable names, use INT16 for calculation git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@9182 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Tactical/Overhead.cpp | 120 +++++++++++++++++++++++++---------- Tactical/Overhead.h | 2 + Tactical/Soldier Control.cpp | 8 +++ Tactical/Soldier Control.h | 1 + 4 files changed, 96 insertions(+), 35 deletions(-) diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 9547f498c..3aa663369 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -8751,14 +8751,9 @@ INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier ) // Calculate basic tolerance value if (gGameExternalOptions.fNewSuppressionCode) { - INT8 bToleranceMorale; - INT8 bToleranceSkill; - UINT8 ubMaxShock = gGameExternalOptions.ubMaxSuppressionShock; - // limit base tolerance to 75% when having max morale and experience level - bToleranceSkill = (pSoldier->aiData.bMorale + 20 * pSoldier->stats.bExpLevel) / 4; // calculate tolerance as percent of max tolerance from INI - bTolerance = gGameExternalOptions.ubSuppressionToleranceMax * bToleranceSkill / 100; + bTolerance = gGameExternalOptions.ubSuppressionToleranceMax * (pSoldier->aiData.bMorale + 20 * EffectiveExpLevel(pSoldier, TRUE)) / 400; } else { @@ -8823,9 +8818,12 @@ INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier ) // HEADROCK HAM 3.2: This is actually a feature from HAM 2.9. It adds bonuses/penalties for nearby friends. // sevenfm: disabled with new code as nearby friends should help morale which affects base tolerance - if (gGameExternalOptions.fFriendliesAffectTolerance && !gGameExternalOptions.fNewSuppressionCode) + if (gGameExternalOptions.fFriendliesAffectTolerance) { - bTolerance += CheckStatusNearbyFriendlies( pSoldier ); + if (gGameExternalOptions.fNewSuppressionCode) + bTolerance += CheckStatusNearbyFriendliesSimple(pSoldier); + else + bTolerance += CheckStatusNearbyFriendlies( pSoldier ); } // HEADROCK HAM 3.3: Moving rapidly makes one less prone to suppression. @@ -10816,11 +10814,10 @@ void RevealAllDroppedEnemyItems() INT8 CheckStatusNearbyFriendlies( SOLDIERTYPE *pSoldier ) { SOLDIERTYPE * pLeader; - UINT8 sModifier = 0; - INT16 usEffectiveLeadership = 0; - UINT16 usEffectiveRangeToLeader = 0; - INT16 usBestLeader = 0; - INT16 usFriendBonus = 0; + INT16 sEffectiveLeadership = 0; + INT16 sEffectiveRangeToLeader = 0; + INT16 sBestLeader = 0; + INT16 sFriendBonus = 0; INT8 bLevelDifference = 0; // Run through each friendly. @@ -10834,75 +10831,128 @@ INT8 CheckStatusNearbyFriendlies( SOLDIERTYPE *pSoldier ) { bLevelDifference = pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel; // Calculate character's leadership and range/3 - usEffectiveLeadership = (EffectiveLeadership( pLeader ) - 25) / 15; - usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ) / 3; + sEffectiveLeadership = (EffectiveLeadership( pLeader ) - 25) / 15; + sEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ) / 3; // SANDRO - add effective leadership and level to determine if we can help our friend to feel better :) if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pLeader, SQUADLEADER_NT ) ) { bLevelDifference += (gSkillTraitValues.ubSLEffectiveLevelAsStandby * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); - usEffectiveLeadership += (gSkillTraitValues.ubSLEffectiveLevelAsStandby * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); + sEffectiveLeadership += (gSkillTraitValues.ubSLEffectiveLevelAsStandby * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); } if ( bLevelDifference >= 0 ) { // If leader is within range of his leadership stat - if (usEffectiveRangeToLeader <= usEffectiveLeadership+1) + if (sEffectiveRangeToLeader <= sEffectiveLeadership+1) { // The difference in experience level is important! - usEffectiveLeadership += bLevelDifference; + sEffectiveLeadership += bLevelDifference; // Reduce effective leadership with every 3 tiles of distance - usEffectiveLeadership -= usEffectiveRangeToLeader-1; + sEffectiveLeadership -= sEffectiveRangeToLeader-1; // If this is the best leader we've seen so far, - if (usEffectiveLeadership > usBestLeader) + if (sEffectiveLeadership > sBestLeader) { // Set this as the best leader - usBestLeader = usEffectiveLeadership; + sBestLeader = sEffectiveLeadership; } // Friends within range always give at least one tolerance bonus point. - usFriendBonus += 1; + sFriendBonus += 1; } } } // Incapacitated or heavily suppressed friends will not be good for our tolerance! else if ( (pLeader->aiData.bShock > pSoldier->aiData.bShock || pLeader->stats.bLife < OKLIFE) ) { - usEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ); + sEffectiveRangeToLeader = PythSpacesAway( pSoldier->sGridNo, pLeader->sGridNo ); // If they are no more than 5 tiles away, - if (usEffectiveRangeToLeader <= 5) + if (sEffectiveRangeToLeader <= 5) { // Penalty is based on the difference between experience levels, and the range between them, // and is never less than 1 point. - usEffectiveLeadership = (pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel) / __max(1,(usEffectiveRangeToLeader/2)); - usFriendBonus -= __max(1, usEffectiveLeadership); + sEffectiveLeadership = (pLeader->stats.bExpLevel - pSoldier->stats.bExpLevel) / __max(1,(sEffectiveRangeToLeader/2)); + sFriendBonus -= __max(1, sEffectiveLeadership); } // SANDRO - however, dead squadleader is very bad for our psychics if ( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( pLeader, SQUADLEADER_NT ) && - ( pLeader->flags.uiStatusFlags & SOLDIER_DEAD ) && usEffectiveRangeToLeader <= 10 ) + ( pLeader->flags.uiStatusFlags & SOLDIER_DEAD ) && sEffectiveRangeToLeader <= 10 ) { - usFriendBonus -= ( gSkillTraitValues.ubSLDeathMoralelossMultiplier * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); + sFriendBonus -= ( gSkillTraitValues.ubSLDeathMoralelossMultiplier * NUM_SKILL_TRAITS( pLeader, SQUADLEADER_NT )); } } } // If we did find someone who's a good enough leader to help us out, - if (usBestLeader > 0) + if (sBestLeader > 0) { // Add his leadership bonus, minus the point we got for him before. He'll give at least one // point, like anybody else. - usFriendBonus += __max(usBestLeader-1, 1); + sFriendBonus += max(sBestLeader-1, 1); } // Add no more than five points for nearby friends. - usFriendBonus = __min(usFriendBonus, 5); - usFriendBonus = __max(usFriendBonus, -5); - sModifier += usFriendBonus; - - return(sModifier); + sFriendBonus = min(sFriendBonus, 5); + sFriendBonus = max(sFriendBonus, -5); + return sFriendBonus; } +// sevenfm: simplified version +INT8 CheckStatusNearbyFriendliesSimple(SOLDIERTYPE *pSoldier) +{ + SOLDIERTYPE * pFriend; + FLOAT iFriendBonus = 0.0f; + FLOAT iModifier; + INT16 sDistance; + INT16 sMinDistance = TACTICAL_RANGE / 4; + + if (!pSoldier || !IS_MERC_BODY_TYPE(pSoldier) || pSoldier->stats.bLife < OKLIFE || pSoldier->IsCowering() || pSoldier->IsUnconscious()) + { + return 0; + } + + // Run through each friendly. + for (UINT8 iCounter = gTacticalStatus.Team[ pSoldier->bTeam ].bFirstID ; iCounter <= gTacticalStatus.Team[ pSoldier->bTeam ].bLastID ; iCounter ++) + { + pFriend = MercPtrs[ iCounter ]; + + // Make sure that character is alive and active + if (pFriend && + pFriend != pSoldier && + pFriend->bActive && + IS_MERC_BODY_TYPE(pFriend) && + SoldierToSoldierLineOfSightTest(pSoldier, pFriend, TRUE, CALC_FROM_ALL_DIRS)) + { + sDistance = PythSpacesAway(pSoldier->sGridNo, pFriend->sGridNo); + + // modifier depends on distance + iModifier = 1.0f * (FLOAT)sMinDistance / (FLOAT)max(sMinDistance, sDistance); + + if (pFriend->stats.bLife >= OKLIFE) + { + // suppressed, half bonus + if(pFriend->IsCowering() || pFriend->IsUnconscious()) + { + iModifier = iModifier / 2; + } + } + else + { + // dying, negative effect + iModifier = -iModifier; + } + + iFriendBonus += iModifier; + } + } + + // Add no more than five points for nearby friends. + iFriendBonus = min(iFriendBonus, 3.0f); + iFriendBonus = max(iFriendBonus, -3.0f); + + return (INT8)iFriendBonus; +} #ifdef JA2UB void SetMsgBoxForPlayerBeNotifiedOfSomeoneElseInSector() diff --git a/Tactical/Overhead.h b/Tactical/Overhead.h index 2b88c7eee..47d936539 100644 --- a/Tactical/Overhead.h +++ b/Tactical/Overhead.h @@ -291,6 +291,8 @@ SOLDIERTYPE * ReduceAttackBusyCount( ); INT8 CalcSuppressionTolerance( SOLDIERTYPE * pSoldier ); // HEADROCK HAM 3.2: A new function for checking the condition of nearby friendlies and returning a modifier. INT8 CheckStatusNearbyFriendlies( SOLDIERTYPE *pSoldier ); +// sevenfm: simplified version +INT8 CheckStatusNearbyFriendliesSimple(SOLDIERTYPE *pSoldier); void CommonEnterCombatModeCode( ); void CheckForPotentialAddToBattleIncrement( SOLDIERTYPE *pSoldier ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index fbf04a3da..e6dfcdcf0 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -26104,6 +26104,14 @@ BOOLEAN SOLDIERTYPE::IsCowering(void) return FALSE; } +BOOLEAN SOLDIERTYPE::IsUnconscious(void) +{ + if (this->bCollapsed && this->bBreath < OKBREATH) + return TRUE; + + return FALSE; +} + void SOLDIERTYPE::StopCoweringAnimation(void) { if (this->usAnimState == COWERING) diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index 37d933276..1e605d500 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -1871,6 +1871,7 @@ public: UINT8 ShockLevelPercent(void); BOOLEAN TakenLargeHit(void); BOOLEAN IsCowering(void); + BOOLEAN IsUnconscious(void); BOOLEAN IsGivingAid(void); // sevenfm: for player mercs