mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
New Trait: Snitch (Trait 22) (by anv)
Every midnight snitches will give you a report about their collegues' opinions. Information includes: - merc whining about high death rate, - merc whining about player reputation, - merc whining about his low morale, - merc whining about some other merc (unliked, not only hated), - merc planning to quit (leave without renewing contract, only AIM mercs) next day, - merc whining about player inactivity, - merc whining about player owing them money (you can only owe money to MERC mercs). List of snitches (trait 22) Beth Bud Buzz Carp Ears Gary Hurl Lance Leon Weasel see: http://www.bears-pit.com/board/ubbthreads.php/topics/329412/Snitches_+_Externalised_morale.html git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6723 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+339
-42
@@ -31,15 +31,19 @@
|
||||
|
||||
#include "connect.h"
|
||||
#include "fresh_header.h"
|
||||
#define MORALE_MOD_MAX 50 // morale *mod* range is -50 to 50, if you change this, check the decay formulas!
|
||||
|
||||
#define DRUG_EFFECT_MORALE_MOD 150
|
||||
#define ALCOHOL_EFFECT_MORALE_MOD 160
|
||||
#include "Random.h"
|
||||
|
||||
#define HOURS_BETWEEN_STRATEGIC_DECAY 3
|
||||
#include "Merc Contract.h"
|
||||
|
||||
#define PHOBIC_LIMIT -20
|
||||
//#define MORALE_MOD_MAX 50 // morale *mod* range is -50 to 50, if you change this, check the decay formulas!
|
||||
|
||||
//#define DRUG_EFFECT_MORALE_MOD 150
|
||||
//#define ALCOHOL_EFFECT_MORALE_MOD 160
|
||||
|
||||
//#define HOURS_BETWEEN_STRATEGIC_DECAY 3
|
||||
|
||||
//#define PHOBIC_LIMIT -20
|
||||
|
||||
// macros
|
||||
#define SOLDIER_IN_SECTOR( pSoldier, sX, sY, bZ ) ( !pSoldier->flags.fBetweenSectors && ( pSoldier->sSectorX == sX ) && ( pSoldier->sSectorY == sY ) && ( pSoldier->bSectorZ == bZ ) )
|
||||
@@ -94,6 +98,13 @@ MoraleEvent gbMoraleEvent[NUM_MORALE_EVENTS] =
|
||||
{ TACTICAL_MORALE_EVENT, 5}, //MORALE_GOOD_FOOD,
|
||||
{ TACTICAL_MORALE_EVENT, -1}, //MORALE_BAD_FOOD,
|
||||
{ TACTICAL_MORALE_EVENT, -5}, //MORALE_LOATHSOME_FOOD,
|
||||
// added by anv
|
||||
{ STRATEGIC_MORALE_EVENT, -5}, //MORALE_BUDDY_FIRED,
|
||||
{ STRATEGIC_MORALE_EVENT, -8}, //MORALE_BUDDY_FIRED_ON_BAD_TERMS,
|
||||
{ STRATEGIC_MORALE_EVENT, -8}, //MORALE_BUDDY_FIRED_EARLY
|
||||
{ STRATEGIC_MORALE_EVENT, -2}, //MORALE_BAD_EQUIPMENT,
|
||||
{ STRATEGIC_MORALE_EVENT, -3}, //MORALE_OWED_MONEY,
|
||||
{ STRATEGIC_MORALE_EVENT, -3}, //MORALE_PLAYER_INACTIVE,
|
||||
};
|
||||
|
||||
BOOLEAN gfSomeoneSaidMoraleQuote = FALSE;
|
||||
@@ -207,7 +218,7 @@ void DecayTacticalMoraleModifiers( void )
|
||||
if ( pSoldier->bSectorZ > 0 )
|
||||
{
|
||||
// underground, no recovery... in fact, if tact morale is high, decay
|
||||
if ( pSoldier->aiData.bTacticalMoraleMod > PHOBIC_LIMIT )
|
||||
if ( pSoldier->aiData.bTacticalMoraleMod > gMoraleSettings.bModifiers[PHOBIC_LIMIT] )
|
||||
{
|
||||
HandleMoraleEvent( pSoldier, MORALE_CLAUSTROPHOBE_UNDERGROUND, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
|
||||
}
|
||||
@@ -257,7 +268,7 @@ void DecayTacticalMoraleModifiers( void )
|
||||
|
||||
if ( fHandleNervous )
|
||||
{
|
||||
if ( pSoldier->aiData.bTacticalMoraleMod == PHOBIC_LIMIT )
|
||||
if ( pSoldier->aiData.bTacticalMoraleMod == gMoraleSettings.bModifiers[PHOBIC_LIMIT] )
|
||||
{
|
||||
// don't change morale
|
||||
//continue;
|
||||
@@ -321,11 +332,12 @@ void RefreshSoldierMorale( SOLDIERTYPE * pSoldier )
|
||||
}
|
||||
|
||||
// CJC, April 19, 1999: added up to 20% morale boost according to progress
|
||||
iActualMorale = DEFAULT_MORALE + (INT32) pSoldier->aiData.bTeamMoraleMod + (INT32) pSoldier->aiData.bTacticalMoraleMod + (INT32) pSoldier->aiData.bStrategicMoraleMod + (INT32) (CurrentPlayerProgressPercentage() / 5);
|
||||
//iActualMorale = DEFAULT_MORALE + (INT32) pSoldier->aiData.bTeamMoraleMod + (INT32) pSoldier->aiData.bTacticalMoraleMod + (INT32) pSoldier->aiData.bStrategicMoraleMod + (INT32) (CurrentPlayerProgressPercentage() / 5);
|
||||
iActualMorale = gMoraleSettings.ubDefaultMorale + (INT32) pSoldier->aiData.bTeamMoraleMod + (INT32) pSoldier->aiData.bTacticalMoraleMod + (INT32) pSoldier->aiData.bStrategicMoraleMod + (INT32) (CurrentPlayerProgressPercentage() / 5);
|
||||
|
||||
// ATE: Modify morale based on drugs....
|
||||
iActualMorale += ( ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ] * DRUG_EFFECT_MORALE_MOD ) / 100 );
|
||||
iActualMorale += ( ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ALCOHOL ] * ALCOHOL_EFFECT_MORALE_MOD ) / 100 );
|
||||
iActualMorale += ( ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ADRENALINE ] * gMoraleSettings.sDrugAndAlcoholModifiers[DRUG_EFFECT_MORALE_MOD] ) / 100 );
|
||||
iActualMorale += ( ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_ALCOHOL ] * gMoraleSettings.sDrugAndAlcoholModifiers[ALCOHOL_EFFECT_MORALE_MOD] ) / 100 );
|
||||
|
||||
iActualMorale = __min( 100, iActualMorale );
|
||||
iActualMorale = __max( 0, iActualMorale );
|
||||
@@ -405,7 +417,7 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
}//hayden
|
||||
|
||||
ubType = gbMoraleEvent[bMoraleEvent].ubType;
|
||||
bMoraleMod = gbMoraleEvent[bMoraleEvent].bChange;
|
||||
bMoraleMod = gReputationSettings.bValues[bMoraleEvent];//gbMoraleEvent[bMoraleEvent].bChange;
|
||||
|
||||
pProfile = &(gMercProfiles[ pSoldier->ubProfile ]);
|
||||
|
||||
@@ -426,19 +438,19 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
case CHAR_TRAIT_SOCIABLE:
|
||||
bNumMercs = CheckMercsNearForCharTraits( pSoldier->ubProfile, CHAR_TRAIT_SOCIABLE );
|
||||
if ( bNumMercs == 0 )
|
||||
bMoraleMod -= 5;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_SOCIABLE_NO_MERCS_NEARBY];// -= 5;
|
||||
else if ( bNumMercs == 1 )
|
||||
bMoraleMod -= 2;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_SOCIABLE_ONE_MERC_NEARBY];// -= 2;
|
||||
break;
|
||||
case CHAR_TRAIT_LONER:
|
||||
bNumMercs = CheckMercsNearForCharTraits( pSoldier->ubProfile, CHAR_TRAIT_LONER );
|
||||
if ( bNumMercs > 1 )
|
||||
bMoraleMod -= 5;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_LONER_MORE_MERCS_NEARBY];// -= 5;
|
||||
else if ( bNumMercs == 1 )
|
||||
bMoraleMod -= 2;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_LONER_ONE_MERC_NEARBY];// -= 2;
|
||||
break;
|
||||
case CHAR_TRAIT_OPTIMIST:
|
||||
bMoraleMod += 1;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OPTIMIST];//1;
|
||||
break;
|
||||
case CHAR_TRAIT_AGGRESSIVE:
|
||||
switch ( bMoraleEvent )
|
||||
@@ -447,7 +459,7 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
case MORALE_DID_LOTS_OF_DAMAGE:
|
||||
case MORALE_MONSTER_QUEEN_KILLED:
|
||||
case MORALE_DEIDRANNA_KILLED:
|
||||
bMoraleMod += 1;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_AGRESSIVE_VIOLENT_ACTION];//1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -462,14 +474,14 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
case MORALE_MONSTER_QUEEN_KILLED:
|
||||
case MORALE_DEIDRANNA_KILLED:
|
||||
case MORALE_QUEEN_BATTLE_WON:
|
||||
bMoraleMod -= 5;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_PACIFIST_VIOLENT_ACTION];//-= 5;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( IsShowOffNearBy( pSoldier ) )
|
||||
{
|
||||
bMoraleMod -= 2;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_SHOWOFF_AROUND];//-= 2;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -478,11 +490,13 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
switch( pProfile->bAttitude )
|
||||
{
|
||||
case ATT_OPTIMIST:
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OT_OPTIMIST_GOOD_EVENT];//1;
|
||||
break;
|
||||
case ATT_AGGRESSIVE:
|
||||
bMoraleMod += 1;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OT_AGGRESSIVE_GOOD_EVENT];//1;
|
||||
break;
|
||||
case ATT_PESSIMIST:
|
||||
bMoraleMod -= 1;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OT_PESSIMIST_GOOD_EVENT];//-= 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -518,7 +532,7 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
// Check for character traits
|
||||
if ( pProfile->bCharacterTrait == CHAR_TRAIT_OPTIMIST )
|
||||
{
|
||||
bMoraleMod += 1;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OPTIMIST];//1;
|
||||
}
|
||||
// Fearless character does not suffer morale loss for these so much
|
||||
else if( pProfile->bCharacterTrait == CHAR_TRAIT_DAUNTLESS )
|
||||
@@ -526,12 +540,16 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
switch ( bMoraleEvent )
|
||||
{
|
||||
case MORALE_SQUADMATE_DIED:
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_DAUNTLESS_SQUADMATE_DIED];//3;
|
||||
break;
|
||||
case MORALE_SUPPRESSED:
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_DAUNTLESS_SUPPRESSED];//3;
|
||||
break;
|
||||
case MORALE_TOOK_LOTS_OF_DAMAGE:
|
||||
bMoraleMod += 3;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_DAUNTLESS_TOOK_LOTS_OF_DAMAGE];//3;
|
||||
break;
|
||||
case MORALE_TEAMMATE_DIED:
|
||||
bMoraleMod += 2;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_DAUNTLESS_TEAMMATE_DIED];//2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -541,13 +559,13 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
switch( pProfile->bAttitude )
|
||||
{
|
||||
case ATT_OPTIMIST:
|
||||
bMoraleMod += 1;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OT_OPTIMIST_BAD_EVENT];//1;
|
||||
break;
|
||||
case ATT_PESSIMIST:
|
||||
bMoraleMod -= 1;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OT_PESSIMIST_BAD_EVENT];//-= 1;
|
||||
break;
|
||||
case ATT_COWARD:
|
||||
bMoraleMod -= 2;
|
||||
bMoraleMod += gMoraleSettings.bModifiers[MORALE_MODIFIER_OT_COWARD_BAD_EVENT];//-= 2;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -573,22 +591,22 @@ void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
|
||||
if (ubType == TACTICAL_MORALE_EVENT)
|
||||
{
|
||||
iMoraleModTotal = (INT32) pSoldier->aiData.bTacticalMoraleMod + (INT32) bMoraleMod;
|
||||
iMoraleModTotal = __min( iMoraleModTotal, MORALE_MOD_MAX );
|
||||
iMoraleModTotal = __max( iMoraleModTotal, -MORALE_MOD_MAX );
|
||||
iMoraleModTotal = __min( iMoraleModTotal, gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
iMoraleModTotal = __max( iMoraleModTotal, -gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
pSoldier->aiData.bTacticalMoraleMod = (INT8) iMoraleModTotal;
|
||||
}
|
||||
else if ( gTacticalStatus.fEnemyInSector && !pSoldier->bInSector ) // delayed strategic
|
||||
{
|
||||
iMoraleModTotal = (INT32) pSoldier->bDelayedStrategicMoraleMod + (INT32) bMoraleMod;
|
||||
iMoraleModTotal = __min( iMoraleModTotal, MORALE_MOD_MAX );
|
||||
iMoraleModTotal = __max( iMoraleModTotal, -MORALE_MOD_MAX );
|
||||
iMoraleModTotal = __min( iMoraleModTotal, gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
iMoraleModTotal = __max( iMoraleModTotal, -gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
pSoldier->bDelayedStrategicMoraleMod = (INT8) iMoraleModTotal;
|
||||
}
|
||||
else // strategic
|
||||
{
|
||||
iMoraleModTotal = (INT32) pSoldier->aiData.bStrategicMoraleMod + (INT32) bMoraleMod;
|
||||
iMoraleModTotal = __min( iMoraleModTotal, MORALE_MOD_MAX );
|
||||
iMoraleModTotal = __max( iMoraleModTotal, -MORALE_MOD_MAX );
|
||||
iMoraleModTotal = __min( iMoraleModTotal, gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
iMoraleModTotal = __max( iMoraleModTotal, -gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
pSoldier->aiData.bStrategicMoraleMod = (INT8) iMoraleModTotal;
|
||||
}
|
||||
|
||||
@@ -674,7 +692,7 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I
|
||||
Assert( pSoldier );
|
||||
// affects the soldier only, should be ignored if tactical morale mod is -20 or less
|
||||
// SANDRO - really?? I think it also shouldn't go lower if strategic morale mod is less than -20
|
||||
if ( pSoldier->aiData.bTacticalMoraleMod > PHOBIC_LIMIT && pSoldier->aiData.bStrategicMoraleMod > PHOBIC_LIMIT )
|
||||
if ( pSoldier->aiData.bTacticalMoraleMod > gMoraleSettings.bModifiers[PHOBIC_LIMIT] && pSoldier->aiData.bStrategicMoraleMod > gMoraleSettings.bModifiers[PHOBIC_LIMIT] )
|
||||
{
|
||||
HandleMoraleEventForSoldier( pSoldier, bMoraleEvent );
|
||||
}
|
||||
@@ -771,7 +789,7 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I
|
||||
{
|
||||
if ( gGameOptions.fNewTraitSystem && bMoraleEvent != MORALE_DEIDRANNA_KILLED)
|
||||
{
|
||||
if ( !SOLDIER_IN_SECTOR( pTeamSoldier, sMapX, sMapY, bMapZ ) && ( gbMoraleEvent[bMoraleEvent].bChange > 0 ) &&
|
||||
if ( !SOLDIER_IN_SECTOR( pTeamSoldier, sMapX, sMapY, bMapZ ) && ( gMoraleSettings.bValues[bMoraleEvent] > 0 ) && //( gbMoraleEvent[bMoraleEvent].bChange > 0 ) &&
|
||||
gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE )
|
||||
{
|
||||
// No morale gain for assertive people from actions of others
|
||||
@@ -988,7 +1006,12 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I
|
||||
case MORALE_DEIDRANNA_KILLED:
|
||||
ModifyPlayerReputation(REPUTATION_KILLED_DEIDRANNA);
|
||||
break;
|
||||
|
||||
case MORALE_BAD_EQUIPMENT:
|
||||
ModifyPlayerReputation(REPUTATION_MERC_COMPLAIN_EQUIPMENT);
|
||||
case MORALE_OWED_MONEY:
|
||||
ModifyPlayerReputation(REPUTATION_MERC_OWED_MONEY);
|
||||
case MORALE_PLAYER_INACTIVE_DAYS:
|
||||
ModifyPlayerReputation(REPUTATION_PLAYER_IS_INACTIVE);
|
||||
default:
|
||||
// no reputation impact
|
||||
break;
|
||||
@@ -1168,11 +1191,11 @@ void HourlyMoraleUpdate( void )
|
||||
// SANDRO - morale is going down faster if not fighting for malicious characters
|
||||
if ( gGameOptions.fNewTraitSystem && pProfile->bCharacterTrait == CHAR_TRAIT_MALICIOUS )
|
||||
{
|
||||
bTeamMoraleModChange -= 1;
|
||||
bTeamMoraleModChange += gMoraleSettings.bModifiers[MORALE_MODIFIER_MALICIOUS_HOURLY_DECAY];//-= 1;
|
||||
}
|
||||
pSoldier->aiData.bTeamMoraleMod += bTeamMoraleModChange;
|
||||
pSoldier->aiData.bTeamMoraleMod = __min( pSoldier->aiData.bTeamMoraleMod, MORALE_MOD_MAX );
|
||||
pSoldier->aiData.bTeamMoraleMod = __max( pSoldier->aiData.bTeamMoraleMod, -MORALE_MOD_MAX );
|
||||
pSoldier->aiData.bTeamMoraleMod = __min( pSoldier->aiData.bTeamMoraleMod, gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
pSoldier->aiData.bTeamMoraleMod = __max( pSoldier->aiData.bTeamMoraleMod, -gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
|
||||
// New, December 3rd, 1998, by CJC --
|
||||
// If delayed strategic modifier exists then incorporate it in strategic mod
|
||||
@@ -1180,8 +1203,8 @@ void HourlyMoraleUpdate( void )
|
||||
{
|
||||
pSoldier->aiData.bStrategicMoraleMod += pSoldier->bDelayedStrategicMoraleMod;
|
||||
pSoldier->bDelayedStrategicMoraleMod = 0;
|
||||
pSoldier->aiData.bStrategicMoraleMod = __min( pSoldier->aiData.bStrategicMoraleMod, MORALE_MOD_MAX );
|
||||
pSoldier->aiData.bStrategicMoraleMod = __max( pSoldier->aiData.bStrategicMoraleMod, -MORALE_MOD_MAX );
|
||||
pSoldier->aiData.bStrategicMoraleMod = __min( pSoldier->aiData.bStrategicMoraleMod, gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
pSoldier->aiData.bStrategicMoraleMod = __max( pSoldier->aiData.bStrategicMoraleMod, -gMoraleSettings.bModifiers[MORALE_MOD_MAX] );
|
||||
}
|
||||
|
||||
// refresh the morale value for the soldier based on the recalculated team modifier
|
||||
@@ -1191,7 +1214,7 @@ void HourlyMoraleUpdate( void )
|
||||
|
||||
bStrategicMoraleUpdateCounter++;
|
||||
|
||||
if ( bStrategicMoraleUpdateCounter == HOURS_BETWEEN_STRATEGIC_DECAY )
|
||||
if ( bStrategicMoraleUpdateCounter == gMoraleSettings.ubHoursBetweenStrategicDelay )
|
||||
{
|
||||
DecayStrategicMoraleModifiers();
|
||||
bStrategicMoraleUpdateCounter = 0;
|
||||
@@ -1199,6 +1222,280 @@ void HourlyMoraleUpdate( void )
|
||||
|
||||
}
|
||||
|
||||
void HandleSnitchCheck( void )
|
||||
{
|
||||
INT8 bMercID, bOtherID;
|
||||
INT8 bOpinion=-1;
|
||||
INT8 bLastTeamID;
|
||||
SOLDIERTYPE * pSoldier;
|
||||
SOLDIERTYPE * pOtherSoldier;
|
||||
MERCPROFILESTRUCT * pProfile;
|
||||
BOOLEAN fSameGroupOnly;
|
||||
// anv: save merc id and his negative morale event for snitches
|
||||
INT8 ubSnitchEventsCounter = 0;
|
||||
INT8 bSnitchesCounter = 0;
|
||||
SnitchEvent SnitchEvents[64];
|
||||
|
||||
bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
||||
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
|
||||
|
||||
// loop through all mercs to calculate their morale
|
||||
for ( pSoldier = MercPtrs[ bMercID ]; bMercID <= bLastTeamID; bMercID++,pSoldier++)
|
||||
{
|
||||
//if the merc is active, in Arulco, not POW
|
||||
if ( pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE &&
|
||||
!(pSoldier->bAssignment == IN_TRANSIT ||
|
||||
pSoldier->bAssignment == ASSIGNMENT_DEAD ||
|
||||
pSoldier->bAssignment == ASSIGNMENT_POW) )
|
||||
{
|
||||
// calculate the guy's opinion of the people he is with
|
||||
pProfile = &(gMercProfiles[ pSoldier->ubProfile ]);
|
||||
|
||||
// if we're moving
|
||||
if (pSoldier->ubGroupID != 0 && PlayerIDGroupInMotion( pSoldier->ubGroupID ))
|
||||
{
|
||||
// we only check our opinions of people in our squad
|
||||
fSameGroupOnly = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fSameGroupOnly = FALSE;
|
||||
}
|
||||
// loop through all other mercs
|
||||
bOtherID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
||||
for ( pOtherSoldier = MercPtrs[ bOtherID ]; bOtherID <= bLastTeamID; bOtherID++,pOtherSoldier++)
|
||||
{
|
||||
// skip past ourselves and all inactive mercs
|
||||
if (bOtherID != bMercID && pOtherSoldier->bActive && pOtherSoldier->ubProfile != NO_PROFILE &&
|
||||
!(pOtherSoldier->bAssignment == IN_TRANSIT ||
|
||||
pOtherSoldier->bAssignment == ASSIGNMENT_DEAD ||
|
||||
pOtherSoldier->bAssignment == ASSIGNMENT_POW))
|
||||
{
|
||||
if (fSameGroupOnly)
|
||||
{
|
||||
// all we have to check is the group ID
|
||||
if (pSoldier->ubGroupID != pOtherSoldier->ubGroupID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check to see if the location is the same
|
||||
if (pOtherSoldier->sSectorX != pSoldier->sSectorX ||
|
||||
pOtherSoldier->sSectorY != pSoldier->sSectorY ||
|
||||
pOtherSoldier->bSectorZ != pSoldier->bSectorZ)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if the OTHER soldier is in motion then we don't do anything!
|
||||
if (pOtherSoldier->ubGroupID != 0 && PlayerIDGroupInMotion( pOtherSoldier->ubGroupID ))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
bOpinion = SoldierRelation( pSoldier, pOtherSoldier);
|
||||
if( bOpinion <= gSkillTraitValues.bSNTMercOpinionAboutMercTreshold )
|
||||
{
|
||||
ubSnitchEventsCounter = RememberSnitchableEvent(pSoldier->ubProfile,pOtherSoldier->ubProfile,fSameGroupOnly,SNITCH_HATED_PERSON,SnitchEvents,ubSnitchEventsCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check death rate vs. merc's tolerance once/day (ignores buddies!)
|
||||
if( MercThinksDeathRateTooHigh( pSoldier->ubProfile ) )
|
||||
{
|
||||
// too high, inform
|
||||
ubSnitchEventsCounter = RememberSnitchableEvent(pSoldier->ubProfile,NOBODY,fSameGroupOnly,SNITCH_DEATH_RATE,SnitchEvents,ubSnitchEventsCounter);
|
||||
}
|
||||
|
||||
// check his morale vs. his morale tolerance once/day (ignores buddies!)
|
||||
if( MercThinksHisMoraleIsTooLow( pSoldier ) )
|
||||
{
|
||||
// too low, inform
|
||||
ubSnitchEventsCounter = RememberSnitchableEvent(pSoldier->ubProfile,NOBODY,fSameGroupOnly,SNITCH_LOW_MORALE,SnitchEvents,ubSnitchEventsCounter);
|
||||
}
|
||||
|
||||
// check his opinion about player's reputation
|
||||
if( MercThinksBadReputationTooHigh( pSoldier->ubProfile ) )
|
||||
{
|
||||
// too high, inform
|
||||
ubSnitchEventsCounter = RememberSnitchableEvent(pSoldier->ubProfile,NOBODY,fSameGroupOnly,SNITCH_REPUTATION,SnitchEvents,ubSnitchEventsCounter);
|
||||
}
|
||||
|
||||
// check his opinion about player activity
|
||||
if( MercThinksPlayerIsInactiveTooLong( pSoldier->ubProfile ) )
|
||||
{
|
||||
// player inactive, inform
|
||||
ubSnitchEventsCounter = RememberSnitchableEvent(pSoldier->ubProfile,NOBODY,fSameGroupOnly,SNITCH_PROGRESS,SnitchEvents,ubSnitchEventsCounter);
|
||||
}
|
||||
|
||||
// check if player owes him money
|
||||
if( MercIsOwedTooMuchMoney( pSoldier->ubProfile ) )
|
||||
{
|
||||
// player owes him money, inform
|
||||
ubSnitchEventsCounter = RememberSnitchableEvent(pSoldier->ubProfile,NOBODY,fSameGroupOnly,SNITCH_OWED_MONEY,SnitchEvents,ubSnitchEventsCounter);
|
||||
}
|
||||
|
||||
// check if contract is running out, and will not renew
|
||||
// but only if he hasn't another contract signed, so there's still a chance to renew if player reacts properly
|
||||
if( ContractIsGoingToExpireSoon(pSoldier) )
|
||||
{
|
||||
if( ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC ) )
|
||||
{
|
||||
// Only do this if they don't want to renew.....
|
||||
if ( !WillMercRenew( pSoldier, FALSE ) && !(pSoldier->flags.fSignedAnotherContract) )
|
||||
{
|
||||
ubSnitchEventsCounter = RememberSnitchableEvent(pSoldier->ubProfile,NOBODY,fSameGroupOnly,SNITCH_GONNA_QUIT,SnitchEvents,ubSnitchEventsCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// anv: handle snitches informing player about reasons for morale drops
|
||||
HandleSnitchesReports( SnitchEvents, ubSnitchEventsCounter );
|
||||
}
|
||||
|
||||
void HandleSnitchesReports( SnitchEvent *SnitchEvents, UINT8 ubSnitchEventsCounter )
|
||||
{
|
||||
UINT8 bSnitchID;
|
||||
SOLDIERTYPE *pSnitch;
|
||||
BOOLEAN fSleepingSnitch = FALSE;
|
||||
|
||||
|
||||
|
||||
for( UINT8 bCounter = 0; bCounter < ubSnitchEventsCounter; bCounter++ )
|
||||
{
|
||||
if( SnitchEvents[bCounter].ubEventType != NOBODY )
|
||||
{
|
||||
bSnitchID = SnitchEvents[bCounter].ubSnitchID;
|
||||
pSnitch = FindSoldierByProfileID(bSnitchID,TRUE);
|
||||
|
||||
if( pSnitch->flags.fMercAsleep )
|
||||
fSleepingSnitch = TRUE;
|
||||
|
||||
// snitch introduction
|
||||
|
||||
if( fSleepingSnitch )
|
||||
TacticalCharacterDialogueWithSpecialEvent( FindSoldierByProfileID(bSnitchID,TRUE), 0, DIALOGUE_SPECIAL_EVENT_SLEEP, 0,0 );
|
||||
|
||||
SnitchTacticalCharacterDialogue(FindSoldierByProfileID(bSnitchID,TRUE),0,SNITCH_INTRODUCTION,NOBODY,NOBODY);
|
||||
|
||||
// process all reports by the same snitch in row
|
||||
for(UINT8 bCounter2 = bCounter; bCounter2 < ubSnitchEventsCounter; bCounter2++ )
|
||||
{
|
||||
if( SnitchEvents[bCounter2].ubSnitchID == bSnitchID )
|
||||
{
|
||||
// say this info
|
||||
SnitchTacticalCharacterDialogue(FindSoldierByProfileID(bSnitchID,TRUE),SnitchEvents[bCounter2].ubEventType,SnitchEvents[bCounter2].ubEventType,
|
||||
SnitchEvents[bCounter2].ubTargetProfile,SnitchEvents[bCounter2].ubSecondaryTargetProfile);
|
||||
|
||||
// clear info
|
||||
SnitchEvents[bCounter2].ubEventType = NOBODY;
|
||||
}
|
||||
}
|
||||
if( fSleepingSnitch )
|
||||
TacticalCharacterDialogueWithSpecialEvent( FindSoldierByProfileID(bSnitchID,TRUE), 0, DIALOGUE_SPECIAL_EVENT_SLEEP, 1,0 );
|
||||
}
|
||||
}
|
||||
ubSnitchEventsCounter = 0;
|
||||
}
|
||||
|
||||
INT8 RememberSnitchableEvent( UINT8 ubTargetProfile, UINT8 ubSecondaryTargetProfile, BOOLEAN fSameGroupOnly, UINT8 ubEventType, SnitchEvent SnitchEvents[], INT8 ubSnitchEventsCounter )
|
||||
{
|
||||
INT8 bSnitchID;
|
||||
INT16 sSnitchingChance = 0;
|
||||
UINT8 ubSnitchProfile;
|
||||
SOLDIERTYPE * pSnitch;
|
||||
SOLDIERTYPE * pSoldier;
|
||||
SOLDIERTYPE * pOtherSoldier;
|
||||
|
||||
pSoldier = FindSoldierByProfileID(ubTargetProfile,FALSE);
|
||||
pOtherSoldier = FindSoldierByProfileID(ubSecondaryTargetProfile,FALSE);
|
||||
|
||||
|
||||
// loop through all other mercs
|
||||
bSnitchID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
||||
for ( pSnitch = MercPtrs[ bSnitchID ]; bSnitchID <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; bSnitchID++,pSnitch++)
|
||||
{
|
||||
ubSnitchProfile = pSnitch->ubProfile;
|
||||
// skip past ourselves and all inactive mercs
|
||||
if (ProfileHasSkillTrait(ubSnitchProfile,SNITCH_NT) &&
|
||||
ubSnitchProfile != ubTargetProfile && ubSnitchProfile != ubSecondaryTargetProfile
|
||||
&& pSnitch->bActive && ubSnitchProfile != NO_PROFILE &&
|
||||
!(pSnitch->bAssignment == IN_TRANSIT ||
|
||||
pSnitch->bAssignment == ASSIGNMENT_DEAD ||
|
||||
pSnitch->bAssignment == ASSIGNMENT_POW))
|
||||
{
|
||||
if (fSameGroupOnly)
|
||||
{
|
||||
// all we have to check is the group ID
|
||||
if (pSoldier->ubGroupID != pSnitch->ubGroupID)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check to see if the location is the same
|
||||
if (pSnitch->sSectorX != pSoldier->sSectorX ||
|
||||
pSnitch->sSectorY != pSoldier->sSectorY ||
|
||||
pSnitch->bSectorZ != pSoldier->bSectorZ)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// if snitch is in motion then we don't do anything!
|
||||
if (pSnitch->ubGroupID != 0 && PlayerIDGroupInMotion( pSnitch->ubGroupID ))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// calculate chances of snitching
|
||||
|
||||
// decreased if target doesn't like snitch, increased if snitch doesn't like him
|
||||
sSnitchingChance = gSkillTraitValues.ubSNTBaseChance;
|
||||
sSnitchingChance = (INT16)(sSnitchingChance +
|
||||
SoldierRelation( pSoldier, pSnitch)*gSkillTraitValues.fSNTMercOpinionAboutSnitchBonusModifier+
|
||||
SoldierRelation( pSnitch, pSoldier)*gSkillTraitValues.fSNTSnitchOpinionAboutMercBonusModifier+
|
||||
gMercProfiles[ubSnitchProfile].bLeadership*gSkillTraitValues.fSNTSnitchLeadershipBonusModifer);
|
||||
if ( pSoldier->bAssignment == pSnitch->bAssignment )
|
||||
{
|
||||
sSnitchingChance += gSkillTraitValues.bSNTSameAssignmentBonus;
|
||||
}
|
||||
if ( gMercProfiles[pSnitch->ubProfile].bCharacterTrait == CHAR_TRAIT_SOCIABLE )
|
||||
{
|
||||
sSnitchingChance += gSkillTraitValues.bSNTSociableMercBonus;
|
||||
}
|
||||
if ( gMercProfiles[pSnitch->ubProfile].bCharacterTrait == CHAR_TRAIT_LONER)
|
||||
{
|
||||
sSnitchingChance += gSkillTraitValues.bSNTLonerMercBonus;
|
||||
}
|
||||
if ( ubEventType == SNITCH_HATED_PERSON )
|
||||
{
|
||||
if ( gSkillTraitValues.bSNTMercOpinionAboutMercTreshold != HATED_OPINION )
|
||||
{
|
||||
sSnitchingChance = (INT16)( sSnitchingChance *
|
||||
( 1.0 - (FLOAT)( SoldierRelation( pSoldier, pOtherSoldier ) - HATED_OPINION ) /
|
||||
(FLOAT)( gSkillTraitValues.bSNTMercOpinionAboutMercTreshold - HATED_OPINION ) ) );
|
||||
}
|
||||
}
|
||||
sSnitchingChance = max(0, sSnitchingChance);
|
||||
if( Random(100) < (UINT8)sSnitchingChance )
|
||||
{
|
||||
//information gathered succesfully, remember event to report it later
|
||||
SnitchEvents[ubSnitchEventsCounter].ubEventType = ubEventType;
|
||||
SnitchEvents[ubSnitchEventsCounter].ubSnitchID = ubSnitchProfile;
|
||||
SnitchEvents[ubSnitchEventsCounter].ubTargetProfile = ubTargetProfile;
|
||||
SnitchEvents[ubSnitchEventsCounter].ubSecondaryTargetProfile = ubSecondaryTargetProfile;
|
||||
ubSnitchEventsCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ubSnitchEventsCounter;
|
||||
}
|
||||
|
||||
void DailyMoraleUpdate(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user