- New Feature: dynamic opinions allows mercs to form opinions about each other depening on actions they/the player take or do not take. These can be viewed in the 'MeLoDY 'website. See also http://www.bears-pit.com/board/ubbthreads.php/topics/333259.html#Post333259

- Requires GameDir r2050.
- new background property: <dislikebackground> allows mercs to dislike specific backgrounds
- Fix: snitches did not correctly prevent misbehaviour
- Fix: morale event was not handled
- Fix: DropDowns did not refresh when using the arrow buttons

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7240 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2014-05-28 22:10:42 +00:00
parent 6ea1d5dd8d
commit 5e9289b450
56 changed files with 3988 additions and 138 deletions
+4 -1
View File
@@ -234,9 +234,12 @@ BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject )
}
}
if ( (ubDrugType & DRUG_ALCOHOL) != 0 )
if ( (ubDrugType & DRUG_ALCOHOL) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_DRANK_SOME ], pSoldier->GetName(), ShortItemNames[ usItem ] );
// Flugente: dynamic opinions
HandleDynamicOpinionTeamDrinking( pSoldier );
}
else
{
+38
View File
@@ -616,6 +616,9 @@ void HourlyFoodAutoDigestion( SOLDIERTYPE *pSoldier )
EatFromInventory( pSoldier, FALSE );
}
// dynamic opinions: if we're still really hungry an someone in this sector has food, we get a lwoer opinion of him, as he obviously doesn't share
HandleDynamicOpinionFoodSharing( pSoldier );
}
}
@@ -1061,3 +1064,38 @@ void SoldierAutoFillCanteens(SOLDIERTYPE *pSoldier)
}
}
}
BOOLEAN HasFoodInInventory( SOLDIERTYPE *pSoldier, BOOLEAN fCheckFood, BOOLEAN fCheckDrink )
{
if ( !pSoldier )
return FALSE;
if ( !fCheckFood && !fCheckDrink )
return TRUE;
// search for food in our inventory
INT8 invsize = (INT8)pSoldier->inv.size( ); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop ) // ... for all items in our inventory ...
{
// ... if Item exists and is food ...
if ( pSoldier->inv[bLoop].exists( ) && Item[pSoldier->inv[bLoop].usItem].foodtype > 0 )
{
if ( fCheckFood && Food[Item[pSoldier->inv[bLoop].usItem].foodtype].bFoodPoints )
return TRUE;
if ( fCheckDrink && Food[Item[pSoldier->inv[bLoop].usItem].foodtype].bDrinkPoints )
{
if ( Item[pSoldier->inv[bLoop].usItem].canteen )
{
// empty canteens retain 1% status, so check ether something is in them
if ( pSoldier->inv[bLoop][0]->data.objectStatus > 1 )
return TRUE;
}
else
return TRUE;
}
}
}
return FALSE;
}
+2
View File
@@ -96,4 +96,6 @@ OBJECTTYPE* GetUsableWaterDrumInSector( void );
// soldier refills canteen while auto-consuming. Only clean sector water souces are consumed, an sector inventory is not touched (sector is likely not loaded)
void SoldierAutoFillCanteens(SOLDIERTYPE *pSoldier);
BOOLEAN HasFoodInInventory( SOLDIERTYPE *pSoldier, BOOLEAN fCheckFood, BOOLEAN fCheckDrink );
#endif
+22
View File
@@ -6890,4 +6890,26 @@ void NCTHShowMounted( SOLDIERTYPE* pSoldier, UINT16* ptrBuf, UINT32 uiPitch, INT
}
}
}
}
// Flugente: check a profile for a background flag without using SOLDIERTYPE
BOOLEAN HasBackgroundFlag( UINT8 usProfile, UINT64 aFlag )
{
if ( gGameOptions.fBackGround && usProfile != NO_PROFILE )
{
if ( zBackground[gMercProfiles[usProfile].usBackground].uiFlags & aFlag )
return TRUE;
}
return FALSE;
}
INT16 GetBackgroundValue( UINT8 usProfile, UINT16 aNr )
{
if ( gGameOptions.fBackGround && usProfile != NO_PROFILE )
{
return zBackground[gMercProfiles[usProfile].usBackground].value[aNr];
}
return 0;
}
+6
View File
@@ -187,6 +187,8 @@ enum {
BG_PERC_INSURANCE,
BG_PERC_SPOTTER,
BG_DISLIKEBG, // dislike any other background that has the negative of this value set
BG_MAX,
};
@@ -556,4 +558,8 @@ void NCTHDrawScopeModeIcon( SOLDIERTYPE *pSoldier, INT16 sNewX, INT16 sNewY );
void NCTHShowAimLevels( SOLDIERTYPE* pSoldier, INT16 curX, INT16 curY );
void NCTHShowMounted( SOLDIERTYPE* pSoldier, UINT16* ptrBuf, UINT32 uiPitch, INT16 sLeft, INT16 sTop, INT16 sRight, INT16 sBottom, INT16 sStartScreenX, INT16 sStartScreenY, INT16 zOffset );
// Flugente: check a profile for a background flag without using SOLDIERTYPE
BOOLEAN HasBackgroundFlag( UINT8 usProfile, UINT64 aFlag );
INT16 GetBackgroundValue( UINT8 usProfile, UINT16 aNr );
#endif
+3
View File
@@ -417,6 +417,9 @@ INT8 HireMerc( MERC_HIRE_STRUCT *pHireMerc)
//remove the merc from the Personnel screens departed list ( if they have never been hired before, its ok to call it )
RemoveNewlyHiredMercFromPersonnelDepartedList( pSoldier->ubProfile );
// Flugente: dynamic opinions
CheckForFriendsofHated( pSoldier );
gfAtLeastOneMercWasHired = TRUE;
return( MERC_HIRE_OK );
}
+815 -44
View File
@@ -27,6 +27,10 @@
#include "GameSettings.h"
#include "Isometric Utils.h"
#include "Food.h"
#include "Interface.h" // added by Flugente
#include "finances.h" // added by Flugente for EXTENDED_CONTRACT_BY_1_DAY
#include "Soldier Add.h" // added by Flugente for MERC_TYPE__AIM_MERC
#include "CampaignStats.h" // added by Flugente for gCurrentIncident
#endif
#include "connect.h"
@@ -289,6 +293,9 @@ void DecayTacticalMoraleModifiers( void )
pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY;
}
HandleMoraleEvent( pSoldier, MORALE_NERVOUS_ALONE, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( pSoldier );
}
}
}
@@ -970,6 +977,7 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I
case MORALE_BAD_EQUIPMENT:
case MORALE_OWED_MONEY:
case MORALE_PLAYER_INACTIVE_DAYS:
case MORALE_PREVENTED_MISBEHAVIOUR:
Assert( pSoldier );
HandleMoraleEventForSoldier( pSoldier, bMoraleEvent );
break;
@@ -1437,6 +1445,9 @@ void HandleSnitchesReports( std::vector<SnitchEvent>& aVec )
// clear info
event2.ubEventType = NUM_SNITCH_EVENTS;
// Flugente: dynamic opinions
AddOpinionEvent( event2.ubTargetProfile, pSnitch->ubProfile, OPINIONEVENT_SNITCHSOLDMEOUT );
}
}
@@ -1736,52 +1747,28 @@ INT8 SoldierRelation( SOLDIERTYPE* pSoldierA, SOLDIERTYPE* pSoldierB)
// some people care about how distuingished other people are. Malus if on different ends of the spectrum, a small bonus if on the same and its really important to the person
// also give a malus if the other person is a slob or snob and we are average but care extremely (we don't like people who behave differently)
switch ( gMercProfiles[ pSoldierB->ubProfile ].bRefinement )
// if we don't care, doesn't matter
if ( pProfile->bRefinementCareLevel == CARELEVEL_NONE )
{
case REFINEMENT_SLOB:
{
if ( pProfile->bRefinement == REFINEMENT_AVERAGE )
{
if ( pProfile->bRefinementCareLevel == CARELEVEL_EXTREME )
bOpinion -= gGameExternalOptions.sMoraleModRefinement;
}
if ( pProfile->bRefinement == REFINEMENT_SLOB )
{
if ( pProfile->bRefinementCareLevel == CARELEVEL_EXTREME )
bOpinion += gGameExternalOptions.sMoraleModRefinement;
}
else if ( pProfile->bRefinement == REFINEMENT_SNOB )
{
if ( pProfile->bRefinementCareLevel == CARELEVEL_SOME )
bOpinion -= gGameExternalOptions.sMoraleModRefinement;
else if ( pProfile->bRefinementCareLevel == CARELEVEL_EXTREME )
bOpinion -= gGameExternalOptions.sMoraleModRefinement * 2;
}
}
break;
case REFINEMENT_SNOB:
{
if ( pProfile->bRefinement == REFINEMENT_AVERAGE )
{
if ( pProfile->bRefinementCareLevel == CARELEVEL_EXTREME )
bOpinion -= gGameExternalOptions.sMoraleModRefinement;
}
if ( pProfile->bRefinement == REFINEMENT_SNOB )
{
if ( pProfile->bRefinementCareLevel == CARELEVEL_EXTREME )
bOpinion += gGameExternalOptions.sMoraleModRefinement;
}
else if ( pProfile->bRefinement == REFINEMENT_SLOB )
{
if ( pProfile->bRefinementCareLevel == CARELEVEL_SOME )
bOpinion -= gGameExternalOptions.sMoraleModRefinement;
else if ( pProfile->bRefinementCareLevel == CARELEVEL_EXTREME )
bOpinion -= gGameExternalOptions.sMoraleModRefinement * 2;
}
}
break;
// nothing to do...
}
// if we care somewhat, malus on slob/snob
else if ( pProfile->bRefinementCareLevel == CARELEVEL_SOME )
{
if ( pProfile->bRefinement * gMercProfiles[pSoldierB->ubProfile].bRefinement == 2 )
bOpinion -= gGameExternalOptions.sMoraleModRefinement;
}
// if we care extremely, reward for similarity, malus otherwise
else //if( pProfile->bRefinementCareLevel == CARELEVEL_EXTREME )
{
if ( pProfile->bRefinement * gMercProfiles[pSoldierB->ubProfile].bRefinement == 2 )
bOpinion -= 2 * gGameExternalOptions.sMoraleModRefinement;
else if ( pProfile->bRefinement * gMercProfiles[pSoldierB->ubProfile].bRefinement == 0 )
bOpinion -= gGameExternalOptions.sMoraleModRefinement;
else
bOpinion += gGameExternalOptions.sMoraleModRefinement;
}
// some people hate other nationalities (do not mix up with racism, which uses bRace)
if ( pProfile->bHatedNationality > -1 && gMercProfiles[ pSoldierB->ubProfile ].bNationality == pProfile->bHatedNationality )
{
@@ -1801,8 +1788,792 @@ INT8 SoldierRelation( SOLDIERTYPE* pSoldierA, SOLDIERTYPE* pSoldierB)
}
// Flugente: backgrounds
if ( pSoldierA->GetBackgroundValue( BG_DISLIKEBG ) && pSoldierA->GetBackgroundValue( BG_DISLIKEBG ) == -pSoldierB->GetBackgroundValue( BG_DISLIKEBG ) )
{
bOpinion -= 2;
}
if ( pSoldierA->HasBackgroundFlag( BACKGROUND_XENOPHOBIC ) && pSoldierB->ubProfile != NO_PROFILE && gMercProfiles[pSoldierA->ubProfile].usBackground != gMercProfiles[pSoldierB->ubProfile].usBackground )
bOpinion -= gGameExternalOptions.sMoraleModXenophobicBackGround;
// Flugente: dynamic opinions
if ( gGameExternalOptions.fDynamicOpinions )
{
for ( UINT8 opinionevent = OPINIONEVENT_FRIENDLYFIRE; opinionevent < OPINIONEVENT_MAX; ++opinionevent )
{
bOpinion += GetDynamicOpinion( pSoldierA->ubProfile, pSoldierB->ubProfile, opinionevent );
}
}
// reasonable values
bOpinion = min( BUDDY_OPINION, bOpinion );
bOpinion = max( HATED_OPINION, bOpinion );
return bOpinion;
}
// Flugente: dynamic opinions
void AddOpinionEvent( UINT8 usProfileA, UINT8 usProfileB, UINT8 usEvent )
{
if ( usProfileA == NO_PROFILE || usProfileA == NO_PROFILE )
return;
if ( usEvent >= OPINIONEVENT_MAX )
return;
// we add a flag signifiying that an event happened today
switch ( usEvent )
{
case OPINIONEVENT_FRIENDLYFIRE: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] |= OPINIONFLAG_STAGE1_FRIENDLYFIRE; break;
case OPINIONEVENT_SNITCHSOLDMEOUT: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] |= OPINIONFLAG_STAGE1_SNITCHSOLDMEOUT; break;
case OPINIONEVENT_SNITCHINTERFERENCE: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] |= OPINIONFLAG_STAGE1_INTERFERENCE; break;
case OPINIONEVENT_FRIENDSWITHHATED: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] |= OPINIONFLAG_STAGE1_FRIENDSWITHHATED; break;
case OPINIONEVENT_CONTRACTEXTENSION: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] |= OPINIONFLAG_STAGE1_CONTRACTEXTENSION; break;
case OPINIONEVENT_ORDEREDRETREAT: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] |= OPINIONFLAG_STAGE1_ORDEREDRETREAT; break;
case OPINIONEVENT_CIVKILLER: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] |= OPINIONFLAG_STAGE1_CIVKILLER; break;
case OPINIONEVENT_SLOWSUSDOWN: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] |= OPINIONFLAG_STAGE1_SLOWSUSDOWN; break;
case OPINIONEVENT_NOSHARINGFOOD: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] |= OPINIONFLAG_STAGE1_NOSHARINGFOOD; break;
case OPINIONEVENT_ANNOYINGDISABILITY: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] |= OPINIONFLAG_STAGE1_ANNOYINGDISABILITY; break;
case OPINIONEVENT_ADDICT: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] |= OPINIONFLAG_STAGE1_ADDICT; break;
case OPINIONEVENT_THIEF: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] |= OPINIONFLAG_STAGE1_THIEF; break;
case OPINIONEVENT_WORSTCOMMANDEREVER: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] |= OPINIONFLAG_STAGE1_WORSTCOMMANDEREVER; break;
case OPINIONEVENT_RICHGUY: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] |= OPINIONFLAG_STAGE1_RICHGUY; break;
case OPINIONEVENT_BETTERGEAR: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] |= OPINIONFLAG_STAGE1_BETTERGEAR; break;
case OPINIONEVENT_YOUMOUNTEDAGUNONMYBREASTS: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] |= OPINIONFLAG_STAGE1_YOUMOUNTEDAGUNONMYBREASTS; break;
case OPINIONEVENT_BANDAGED: gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] |= OPINIONFLAG_STAGE1_BANDAGED; break;
// drinking flags are a bit different - drinking can apply the GOOD or BAD flag, and they cancel each other out.
// GOOD on GOOD causes SUPER, which cannot be removed (and stops this for today)
// BAD on BAD causes WORSE, which cannot be removed (and stops this for today)
case OPINIONEVENT_DRINKBUDDIES_GOOD:
// if we do not already have the SUPER flag...
if ( !(gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & (OPINIONFLAG_STAGE1_DRINKBUDDIES_SUPER | OPINIONFLAG_STAGE1_DRINKBUDDIES_WORSE)) )
{
// if we already have GOOD, get SUPER
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_DRINKBUDDIES_GOOD )
{
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] |= OPINIONFLAG_STAGE1_DRINKBUDDIES_SUPER;
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] &= ~OPINIONFLAG_STAGE1_DRINKBUDDIES_GOOD;
}
// if we have BAD, cancel it out
else if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_DRINKBUDDIES_BAD )
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] &= ~OPINIONFLAG_STAGE1_DRINKBUDDIES_BAD;
// if we have nothing, get GOOD
else
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] |= OPINIONFLAG_STAGE1_DRINKBUDDIES_GOOD;
}
break;
case OPINIONEVENT_DRINKBUDDIES_BAD:
// if we do not already have the SUPER flag...
if ( !(gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & (OPINIONFLAG_STAGE1_DRINKBUDDIES_SUPER | OPINIONFLAG_STAGE1_DRINKBUDDIES_WORSE)) )
{
// if we already have BAD, get WORSE
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_DRINKBUDDIES_BAD )
{
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] |= OPINIONFLAG_STAGE1_DRINKBUDDIES_WORSE;
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] &= ~OPINIONFLAG_STAGE1_DRINKBUDDIES_BAD;
}
// if we have GOOD, cancel it out
else if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_DRINKBUDDIES_GOOD )
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] &= ~OPINIONFLAG_STAGE1_DRINKBUDDIES_GOOD;
// if we have nothing, get BAD
else
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] |= OPINIONFLAG_STAGE1_DRINKBUDDIES_BAD;
}
break;
default: break;
}
}
// get usProfileA's opinion of usProfileB concerning usEvent
INT8 GetDynamicOpinion( UINT8 usProfileA, UINT8 usProfileB, UINT8 usEvent )
{
INT32 opinion = 0;
if ( usProfileA == NO_PROFILE || usProfileA == NO_PROFILE )
return opinion;
if ( usEvent >= OPINIONEVENT_MAX )
return opinion;
// count how many relevant flags are set
UINT8 numflags = 0;
switch ( usEvent )
{
case OPINIONEVENT_FRIENDLYFIRE:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE1_FRIENDLYFIRE) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE2_FRIENDLYFIRE ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE3_FRIENDLYFIRE ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE4_FRIENDLYFIRE ) ++numflags;
break;
case OPINIONEVENT_SNITCHSOLDMEOUT:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE1_SNITCHSOLDMEOUT ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE2_SNITCHSOLDMEOUT ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE3_SNITCHSOLDMEOUT ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE4_SNITCHSOLDMEOUT ) ++numflags;
break;
case OPINIONEVENT_SNITCHINTERFERENCE:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE1_INTERFERENCE ) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE2_INTERFERENCE) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE3_INTERFERENCE ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE4_INTERFERENCE ) ++numflags;
break;
case OPINIONEVENT_FRIENDSWITHHATED:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE1_FRIENDSWITHHATED ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE2_FRIENDSWITHHATED ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE3_FRIENDSWITHHATED ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE4_FRIENDSWITHHATED ) ++numflags;
break;
case OPINIONEVENT_CONTRACTEXTENSION:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE1_CONTRACTEXTENSION ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE2_CONTRACTEXTENSION ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE3_CONTRACTEXTENSION ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE4_CONTRACTEXTENSION ) ++numflags;
break;
case OPINIONEVENT_ORDEREDRETREAT:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE1_ORDEREDRETREAT ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE2_ORDEREDRETREAT ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE3_ORDEREDRETREAT ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE4_ORDEREDRETREAT ) ++numflags;
break;
case OPINIONEVENT_CIVKILLER:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE1_CIVKILLER ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE2_CIVKILLER ) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE3_CIVKILLER) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE4_CIVKILLER) ++numflags;
break;
case OPINIONEVENT_SLOWSUSDOWN:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE1_SLOWSUSDOWN) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE2_SLOWSUSDOWN) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE3_SLOWSUSDOWN) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][0] & OPINIONFLAG_STAGE4_SLOWSUSDOWN) ++numflags;
break;
case OPINIONEVENT_NOSHARINGFOOD:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE1_NOSHARINGFOOD) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE2_NOSHARINGFOOD) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE3_NOSHARINGFOOD) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE4_NOSHARINGFOOD) ++numflags;
break;
case OPINIONEVENT_ANNOYINGDISABILITY:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE1_ANNOYINGDISABILITY) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE2_ANNOYINGDISABILITY) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE3_ANNOYINGDISABILITY) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE4_ANNOYINGDISABILITY) ++numflags;
break;
case OPINIONEVENT_ADDICT:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE1_ADDICT) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE2_ADDICT) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE3_ADDICT) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE4_ADDICT) ++numflags;
break;
case OPINIONEVENT_THIEF:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE1_THIEF) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE2_THIEF) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE3_THIEF) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE4_THIEF) ++numflags;
break;
case OPINIONEVENT_WORSTCOMMANDEREVER:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE1_WORSTCOMMANDEREVER) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE2_WORSTCOMMANDEREVER) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE3_WORSTCOMMANDEREVER) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE4_WORSTCOMMANDEREVER) ++numflags;
break;
case OPINIONEVENT_RICHGUY:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE1_RICHGUY) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE2_RICHGUY) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE3_RICHGUY) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE4_RICHGUY) ++numflags;
break;
case OPINIONEVENT_BETTERGEAR:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE1_BETTERGEAR) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE2_BETTERGEAR) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE3_BETTERGEAR) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE4_BETTERGEAR) ++numflags;
break;
case OPINIONEVENT_YOUMOUNTEDAGUNONMYBREASTS:
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE1_YOUMOUNTEDAGUNONMYBREASTS) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE2_YOUMOUNTEDAGUNONMYBREASTS) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE3_YOUMOUNTEDAGUNONMYBREASTS) ++numflags;
if (gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][1] & OPINIONFLAG_STAGE4_YOUMOUNTEDAGUNONMYBREASTS) ++numflags;
break;
case OPINIONEVENT_BANDAGED:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_BANDAGED ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE2_BANDAGED ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE3_BANDAGED ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE4_BANDAGED ) ++numflags;
break;
case OPINIONEVENT_DRINKBUDDIES_GOOD:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_DRINKBUDDIES_GOOD ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE2_DRINKBUDDIES_GOOD ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE3_DRINKBUDDIES_GOOD ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE4_DRINKBUDDIES_GOOD ) ++numflags;
break;
case OPINIONEVENT_DRINKBUDDIES_SUPER:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_DRINKBUDDIES_SUPER ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE2_DRINKBUDDIES_SUPER ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE3_DRINKBUDDIES_SUPER ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE4_DRINKBUDDIES_SUPER ) ++numflags;
break;
case OPINIONEVENT_DRINKBUDDIES_BAD:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_DRINKBUDDIES_BAD ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE2_DRINKBUDDIES_BAD ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE3_DRINKBUDDIES_BAD ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE4_DRINKBUDDIES_BAD ) ++numflags;
break;
case OPINIONEVENT_DRINKBUDDIES_WORSE:
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE1_DRINKBUDDIES_WORSE ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE2_DRINKBUDDIES_WORSE ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE3_DRINKBUDDIES_WORSE ) ++numflags;
if ( gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][2] & OPINIONFLAG_STAGE4_DRINKBUDDIES_WORSE ) ++numflags;
break;
default:
break;
}
// event opinion is number of times this happened times opinion modifer
opinion = numflags * gMoraleSettings.bDynamicOpinionModifiers[usEvent];
// cut it down to INT8
return (INT8)opinion;
}
// daily rollover of opinions
void HandleDynamicOpinions( )
{
for ( UINT8 usProfile = 0; usProfile < NUM_PROFILES; ++usProfile )
{
// each profile has its opinions on everyone else renewed
RolloverDynamicOpinions( usProfile );
}
SOLDIERTYPE* pSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE &&
!(pSoldier->bAssignment == IN_TRANSIT ||
pSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
// or each profile, check wether everyone else is a friend of someone else we hate
CheckForFriendsofHated( pSoldier );
// get annoyed on mercs that receive a lot more money than we do
HandleDynamicOpinionWageJealousy( pSoldier );
}
}
}
// a day has passed, 'age' opinions
void RolloverDynamicOpinions( UINT8 usProfileA )
{
for ( UINT8 usProfileB = 0; usProfileB < NUM_PROFILES; ++usProfileB )
{
for ( UINT8 i = 0; i < OPINION_FLAGMASKS_NUMBER; ++i )
{
// events that are at stage 4 are forgotten
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][i] &= ~OPINIONFLAG_STAGE4_ALL;
// all other events move up one stage
gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][i] = gMercProfiles[usProfileA].usDynamicOpinionFlagmask[usProfileB][i] << 1;
}
}
}
// check wether other people are friends with someone else we hate. All persons must be in Arulco
void CheckForFriendsofHated( SOLDIERTYPE* pSoldier )
{
INT8 bMercID, bOtherID, bThirdID;
INT8 bOpinion = -1;
INT8 bSecondOpinion = -1;
INT8 bLastTeamID;
SOLDIERTYPE* pOtherSoldier;
SOLDIERTYPE* pThirdSoldier;
bMercID = pSoldier->ubID;
bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
// 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 ) )
{
bOpinion = SoldierRelation( pSoldier, pOtherSoldier );
// we cannot simply check for HATED_OPINION here - this very feature makes opinions not so easy anymore. Simply check for a range
if ( bOpinion < -20 )
{
// there is someone in our team that we hate. We dislike his friends somewhat, purely because they like our foe
// loop through all other mercs
bThirdID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
for ( pThirdSoldier = MercPtrs[bThirdID]; bThirdID <= bLastTeamID; ++bThirdID, pThirdSoldier++ )
{
// skip past ourselves and all inactive mercs
if ( bThirdID != bMercID && bThirdID != bOtherID && pThirdSoldier->bActive && pThirdSoldier->ubProfile != NO_PROFILE &&
!(pThirdSoldier->bAssignment == IN_TRANSIT ||
pThirdSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
bSecondOpinion = SoldierRelation( pThirdSoldier, pOtherSoldier );
if ( bSecondOpinion > 20 )
{
// this guy is friends with someone we hate! We dislike him a bit for that
AddOpinionEvent( pSoldier->ubProfile, pThirdSoldier->ubProfile, OPINIONEVENT_FRIENDSWITHHATED );
}
}
}
}
}
}
}
void HandleDynamicOpinionOnContractExtension( UINT8 ubCode, UINT8 usProfile )
{
if ( usProfile == NO_PROFILE )
return;
if ( ubCode == EXTENDED_CONTRACT_BY_1_DAY || ubCode == EXTENDED_CONTRACT_BY_1_WEEK || ubCode == EXTENDED_CONTRACT_BY_2_WEEKS )
{
INT16 id = GetSoldierIDFromMercID( usProfile );
if ( id > -1 )
{
SOLDIERTYPE* pSoldierWhoGotPaid = MercPtrs[id];
// only for AIM mercs
if ( pSoldierWhoGotPaid->ubWhatKindOfMercAmI != MERC_TYPE__AIM_MERC )
return;
// determine the remaining length of his contract BEFORE it go renewed
INT32 oldcontract = pSoldierWhoGotPaid->iEndofContractTime;
if ( ubCode == EXTENDED_CONTRACT_BY_1_DAY )
oldcontract -= 1440;
else if ( ubCode == EXTENDED_CONTRACT_BY_1_WEEK )
oldcontract -= 7 * 1440;
else if ( ubCode == EXTENDED_CONTRACT_BY_2_WEEKS )
oldcontract -= 14 * 1440;
// someones contract got extended. Other mercs who have less time on their contract will be annoyed by this, as they feel they shoul be paid first
SOLDIERTYPE* pSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE && pSoldier->ubProfile != usProfile &&
!(pSoldier->bAssignment == IN_TRANSIT ||
pSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
// only for AIM mercs
if ( pSoldier->ubProfile == NO_PROFILE || pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__AIM_MERC )
continue;
if ( pSoldier->iEndofContractTime < oldcontract )
{
// this guy got paid at a point where we had less time than he did! Favouritism!
AddOpinionEvent( pSoldier->ubProfile, usProfile, OPINIONEVENT_CONTRACTEXTENSION );
}
}
}
}
}
}
void HandleDynamicOpinionCivKill( SOLDIERTYPE* pSoldier )
{
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
if ( (gMercProfiles[pTeamSoldier->ubProfile].ubMiscFlags3 & PROFILE_MISC_FLAG3_GOODGUY) )
{
AddOpinionEvent( pTeamSoldier->ubProfile, pSoldier->ubProfile, OPINIONEVENT_CIVKILLER );
}
}
}
}
void HandleDynamicOpinionSlowdown( SOLDIERTYPE* pSoldier )
{
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE )
return;
INT32 iPercentEncumbranceOffended = CalculateCarriedWeight( pSoldier );
if ( iPercentEncumbranceOffended > 100 )
{
// everyone else on the same squad gets annoyed, if they aren't overencumbered themselves, or at least not as much as the offender
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile && pTeamSoldier->bAssignment == pSoldier->bAssignment &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
INT32 iPercentEncumbrance = CalculateCarriedWeight( pTeamSoldier );
if ( iPercentEncumbrance < 100 || iPercentEncumbrance < 0.7 * iPercentEncumbranceOffended )
{
AddOpinionEvent( pTeamSoldier->ubProfile, pSoldier->ubProfile, OPINIONEVENT_SLOWSUSDOWN );
}
}
}
}
}
void HandleDynamicOpinionWageJealousy( SOLDIERTYPE* pSoldier )
{
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE )
return;
if ( !pSoldier->iTotalContractLength || (pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__AIM_MERC && pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__MERC && pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__NPC_WITH_UNEXTENDABLE_CONTRACT) )
return;
// determine our mean daily wage
UINT32 meanwage = gMercProfiles[pSoldier->ubProfile].uiTotalCostToDate / pSoldier->iTotalContractLength;
UINT8 explevel = pSoldier->stats.bExpLevel;
// hu?
if ( !explevel )
return;
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
if ( !pTeamSoldier->iTotalContractLength || (pTeamSoldier->ubWhatKindOfMercAmI != MERC_TYPE__AIM_MERC && pTeamSoldier->ubWhatKindOfMercAmI != MERC_TYPE__MERC && pTeamSoldier->ubWhatKindOfMercAmI != MERC_TYPE__NPC_WITH_UNEXTENDABLE_CONTRACT) )
continue;
// their wage
UINT32 theirmeanwage = gMercProfiles[pTeamSoldier->ubProfile].uiTotalCostToDate / pTeamSoldier->iTotalContractLength;
// adjust this for experience levels
FLOAT explevelfactor = gGameExternalOptions.fDynamicWageFactor * pTeamSoldier->stats.bExpLevel / explevel;
if ( theirmeanwage > explevelfactor * meanwage )
{
AddOpinionEvent( pSoldier->ubProfile, pTeamSoldier->ubProfile, OPINIONEVENT_RICHGUY );
}
}
}
}
void HandleDynamicOpinionDisability( SOLDIERTYPE* pSoldier )
{
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE )
return;
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector gets annoyed
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile &&
pTeamSoldier->sSectorX == pSoldier->sSectorX && pTeamSoldier->sSectorY == pSoldier->sSectorY && pTeamSoldier->bSectorZ == pSoldier->bSectorZ &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
AddOpinionEvent( pTeamSoldier->ubProfile, pSoldier->ubProfile, OPINIONEVENT_ANNOYINGDISABILITY );
}
}
}
void HandleDynamicOpinionAddict( SOLDIERTYPE* pSoldier )
{
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE )
return;
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
AddOpinionEvent( pTeamSoldier->ubProfile, pSoldier->ubProfile, OPINIONEVENT_ADDICT );
}
}
}
void HandleDynamicOpinionThief( SOLDIERTYPE* pSoldier )
{
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE )
return;
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector gets annoyed
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile &&
pTeamSoldier->sSectorX == pSoldier->sSectorX && pTeamSoldier->sSectorY == pSoldier->sSectorY && pTeamSoldier->bSectorZ == pSoldier->bSectorZ &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
AddOpinionEvent( pTeamSoldier->ubProfile, pSoldier->ubProfile, OPINIONEVENT_THIEF );
}
}
}
void HandleDynamicOpinionFoodSharing( SOLDIERTYPE* pSoldier )
{
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE )
return;
BOOLEAN fCheckFood = (pSoldier->bFoodLevel < FoodMoraleMods[FOOD_MERC_START_SHOW_HUNGER_SYMBOL].bThreshold);
BOOLEAN fCheckDrink = (pSoldier->bDrinkLevel < FoodMoraleMods[FOOD_MERC_START_SHOW_HUNGER_SYMBOL].bThreshold);
// no hunger - no problem
if ( !fCheckFood && !fCheckDrink )
return;
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector gets annoyed
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile &&
pTeamSoldier->sSectorX == pSoldier->sSectorX && pTeamSoldier->sSectorY == pSoldier->sSectorY && pTeamSoldier->bSectorZ == pSoldier->bSectorZ &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
if ( HasFoodInInventory( pTeamSoldier, fCheckFood, fCheckDrink ) )
{
AddOpinionEvent( pSoldier->ubProfile, pTeamSoldier->ubProfile, OPINIONEVENT_NOSHARINGFOOD );
}
}
}
}
void HandleDynamicOpinionGear( SOLDIERTYPE* pSoldier )
{
// only in combat squads
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE || pSoldier->bAssignment >= ON_DUTY )
return;
UINT8 highestcoolness = HighestInventoryCoolness( pSoldier );
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector gets annoyed
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile &&
pTeamSoldier->sSectorX == pSoldier->sSectorX && pTeamSoldier->sSectorY == pSoldier->sSectorY && pTeamSoldier->bSectorZ == pSoldier->bSectorZ &&
pTeamSoldier->bAssignment < ON_DUTY &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
if ( HighestInventoryCoolness( pTeamSoldier ) > highestcoolness + 2 )
{
AddOpinionEvent( pSoldier->ubProfile, pTeamSoldier->ubProfile, OPINIONEVENT_BETTERGEAR );
}
}
}
}
void HandleDynamicOpinionBattleLosses()
{
UINT32 badstuff = 0;
for ( UINT16 i = 0; i < CAMPAIGNHISTORY_SD_CIV; ++i )
{
badstuff += 5 * gCurrentIncident.usKills[i];
badstuff += gCurrentIncident.usWounds[i];
badstuff += 4 * gCurrentIncident.usPrisoners[i];
}
if ( badstuff > 100 )
{
// this was a disaster (Ignoring of how high the enemies losses were to create drama :-) )! Someone needs to be blamed!
SOLDIERTYPE* pScapeGoat = NULL;
FLOAT bestdommanderrating = 0.0f;
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector gets annoyed
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE &&
pTeamSoldier->sSectorX == SECTORX( gCurrentIncident.usSector ) && pTeamSoldier->sSectorY == SECTORY( gCurrentIncident.usSector ) && pTeamSoldier->bSectorZ == gCurrentIncident.usLevel &&
pTeamSoldier->bAssignment < ON_DUTY &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
FLOAT commanderrating = pTeamSoldier->stats.bExpLevel + NUM_SKILL_TRAITS( pTeamSoldier, SQUADLEADER_NT );
if ( commanderrating > bestdommanderrating )
{
bestdommanderrating = commanderrating;
pScapeGoat = pTeamSoldier;
}
}
}
// we've found someone competent. Let's all blame him for this disaster!
if ( bestdommanderrating > 0.0f )
{
bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector gets annoyed
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE &&
pTeamSoldier->ubProfile != pScapeGoat->ubProfile &&
pTeamSoldier->sSectorX == SECTORX( gCurrentIncident.usSector ) && pTeamSoldier->sSectorY == SECTORY( gCurrentIncident.usSector ) && pTeamSoldier->bSectorZ == gCurrentIncident.usLevel &&
pTeamSoldier->bAssignment < ON_DUTY &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
AddOpinionEvent( pTeamSoldier->ubProfile, pScapeGoat->ubProfile, OPINIONEVENT_WORSTCOMMANDEREVER );
}
}
}
}
}
void HandleDynamicOpinionRetreat()
{
// this was a disaster (Ignoring of how high the enemies losses were to create drama :-) )! Someone needs to be blamed!
SOLDIERTYPE* pScapeGoat = NULL;
FLOAT bestdommanderrating = 0.0f;
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector gets annoyed
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE &&
pTeamSoldier->sSectorX == gWorldSectorX && pTeamSoldier->sSectorY == gWorldSectorY && (pTeamSoldier->bSectorZ == gbWorldSectorZ) &&
pTeamSoldier->bAssignment < ON_DUTY &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
FLOAT commanderrating = pTeamSoldier->stats.bExpLevel + NUM_SKILL_TRAITS( pTeamSoldier, SQUADLEADER_NT );
if ( commanderrating > bestdommanderrating )
{
bestdommanderrating = commanderrating;
pScapeGoat = pTeamSoldier;
}
}
}
// we've found someone competent. Let's all blame him for this disaster!
if ( bestdommanderrating > 0.0f )
{
bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector gets annoyed
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE &&
pTeamSoldier->ubProfile != pScapeGoat->ubProfile &&
pTeamSoldier->sSectorX == gWorldSectorX && pTeamSoldier->sSectorY == gWorldSectorY && (pTeamSoldier->bSectorZ == gbWorldSectorZ) &&
pTeamSoldier->bAssignment < ON_DUTY &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
AddOpinionEvent( pTeamSoldier->ubProfile, pScapeGoat->ubProfile, OPINIONEVENT_ORDEREDRETREAT );
}
}
}
}
void HandleDynamicOpinionTeamDrinking( SOLDIERTYPE* pSoldier )
{
// need to be drunk for this
if ( !pSoldier || pSoldier->ubProfile == NO_PROFILE || !MercUnderTheInfluence( pSoldier, DRUG_TYPE_ALCOHOL ) )
return;
SOLDIERTYPE* pTeamSoldier = NULL;
UINT16 bMercID = gTacticalStatus.Team[gbPlayerNum].bFirstID;
UINT16 bLastTeamID = gTacticalStatus.Team[gbPlayerNum].bLastID;
for ( pTeamSoldier = MercPtrs[bMercID]; bMercID <= bLastTeamID; ++bMercID, pTeamSoldier++ )
{
// everybody other merc in the same sector can get updated if they are drugged too
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE && pTeamSoldier->ubProfile != pSoldier->ubProfile &&
pTeamSoldier->sSectorX == pSoldier->sSectorX && pTeamSoldier->sSectorY == pSoldier->sSectorY && pTeamSoldier->bSectorZ == pSoldier->bSectorZ &&
MercUnderTheInfluence( pTeamSoldier, DRUG_TYPE_ALCOHOL ) &&
!(pTeamSoldier->bAssignment == IN_TRANSIT ||
pTeamSoldier->bAssignment == ASSIGNMENT_DEAD) )
{
// both mercs drink together, they opinion either improve or worsen
if ( Chance( 67 ) )
AddOpinionEvent( pTeamSoldier->ubProfile, pSoldier->ubProfile, OPINIONEVENT_DRINKBUDDIES_GOOD );
else
AddOpinionEvent( pTeamSoldier->ubProfile, pSoldier->ubProfile, OPINIONEVENT_DRINKBUDDIES_BAD );
if ( Chance( 67 ) )
AddOpinionEvent( pSoldier->ubProfile, pTeamSoldier->ubProfile, OPINIONEVENT_DRINKBUDDIES_GOOD );
else
AddOpinionEvent( pSoldier->ubProfile, pTeamSoldier->ubProfile, OPINIONEVENT_DRINKBUDDIES_BAD );
}
}
}
UINT8 HighestInventoryCoolness( SOLDIERTYPE* pSoldier )
{
UINT8 coolness = 0;
if ( !pSoldier )
return coolness;
// search for food in our inventory
INT8 invsize = (INT8)pSoldier->inv.size( ); // remember inventorysize, so we don't call size() repeatedly
for ( INT8 bLoop = 0; bLoop < invsize; ++bLoop ) // ... for all items in our inventory ...
{
// ... if Item exists and is food ...
if ( pSoldier->inv[bLoop].exists( ) )
{
coolness = max( coolness, Item[pSoldier->inv[bLoop].usItem].ubCoolness );
}
}
return coolness;
}
+161
View File
@@ -148,6 +148,136 @@ typedef struct SnitchEvent
UINT8 ubSecondaryTargetProfile;
} SnitchEvent;
// -------- added by Flugente: flags for opinions --------
// easier than adding 32 differently named variables. DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
// if someone influences our opinion, STAGE1 gets set. Every day, stages move up one step, until we 'forget' them
// these flags describe what the other guy did to us....
// flagmask 1
#define OPINIONFLAG_STAGE1_FRIENDLYFIRE 0x00000001 //1 // fired on us
#define OPINIONFLAG_STAGE2_FRIENDLYFIRE 0x00000002 //2
#define OPINIONFLAG_STAGE3_FRIENDLYFIRE 0x00000004 //4
#define OPINIONFLAG_STAGE4_FRIENDLYFIRE 0x00000008 //8
#define OPINIONFLAG_STAGE1_SNITCHSOLDMEOUT 0x00000010 //16 // has been snitching to the player about us
#define OPINIONFLAG_STAGE2_SNITCHSOLDMEOUT 0x00000020 //32
#define OPINIONFLAG_STAGE3_SNITCHSOLDMEOUT 0x00000040 //64
#define OPINIONFLAG_STAGE4_SNITCHSOLDMEOUT 0x00000080 //128
#define OPINIONFLAG_STAGE1_INTERFERENCE 0x00000100 //256 // is interfering with us (stopped us from taking drugs or stealing)
#define OPINIONFLAG_STAGE2_INTERFERENCE 0x00000200 //512
#define OPINIONFLAG_STAGE3_INTERFERENCE 0x00000400 //1024
#define OPINIONFLAG_STAGE4_INTERFERENCE 0x00000800 //2048
#define OPINIONFLAG_STAGE1_FRIENDSWITHHATED 0x00001000 //4096 // is friends with someone we hate
#define OPINIONFLAG_STAGE2_FRIENDSWITHHATED 0x00002000 //8192
#define OPINIONFLAG_STAGE3_FRIENDSWITHHATED 0x00004000 //16384
#define OPINIONFLAG_STAGE4_FRIENDSWITHHATED 0x00008000 //32768
#define OPINIONFLAG_STAGE1_CONTRACTEXTENSION 0x00010000 //65536 // got his contract extended before we did, even though we had less time left
#define OPINIONFLAG_STAGE2_CONTRACTEXTENSION 0x00020000 //131072
#define OPINIONFLAG_STAGE3_CONTRACTEXTENSION 0x00040000 //262144
#define OPINIONFLAG_STAGE4_CONTRACTEXTENSION 0x00080000 //524288
#define OPINIONFLAG_STAGE1_ORDEREDRETREAT 0x00100000 //1048576 // was commander (most senior merc around) and ordered retreat
#define OPINIONFLAG_STAGE2_ORDEREDRETREAT 0x00200000 //2097152
#define OPINIONFLAG_STAGE3_ORDEREDRETREAT 0x00400000 //4194304
#define OPINIONFLAG_STAGE4_ORDEREDRETREAT 0x00800000 //8388608
#define OPINIONFLAG_STAGE1_CIVKILLER 0x01000000 //16777216 // killed an unarmed civilian
#define OPINIONFLAG_STAGE2_CIVKILLER 0x02000000 //33554432
#define OPINIONFLAG_STAGE3_CIVKILLER 0x04000000 //67108864
#define OPINIONFLAG_STAGE4_CIVKILLER 0x08000000 //134217728
#define OPINIONFLAG_STAGE1_SLOWSUSDOWN 0x10000000 //268435456 // is overloaded and thus slows us down
#define OPINIONFLAG_STAGE2_SLOWSUSDOWN 0x20000000 //536870912
#define OPINIONFLAG_STAGE3_SLOWSUSDOWN 0x40000000 //1073741824
#define OPINIONFLAG_STAGE4_SLOWSUSDOWN 0x80000000 //2147483648
// flagmask 2
#define OPINIONFLAG_STAGE1_NOSHARINGFOOD 0x00000001 //1 // had water/food when we needed it. So he did not share!
#define OPINIONFLAG_STAGE2_NOSHARINGFOOD 0x00000002 //2
#define OPINIONFLAG_STAGE3_NOSHARINGFOOD 0x00000004 //4
#define OPINIONFLAG_STAGE4_NOSHARINGFOOD 0x00000008 //8
#define OPINIONFLAG_STAGE1_ANNOYINGDISABILITY 0x00000010 //16 // disability kicked in at a bad time, putting the team at risk (forgeful, nervous, psycho...)
#define OPINIONFLAG_STAGE2_ANNOYINGDISABILITY 0x00000020 //32
#define OPINIONFLAG_STAGE3_ANNOYINGDISABILITY 0x00000040 //64
#define OPINIONFLAG_STAGE4_ANNOYINGDISABILITY 0x00000080 //128
#define OPINIONFLAG_STAGE1_ADDICT 0x00000100 //256 // is taking drugs
#define OPINIONFLAG_STAGE2_ADDICT 0x00000200 //512
#define OPINIONFLAG_STAGE3_ADDICT 0x00000400 //1024
#define OPINIONFLAG_STAGE4_ADDICT 0x00000800 //2048
#define OPINIONFLAG_STAGE1_THIEF 0x00001000 //4096 // is stealing items
#define OPINIONFLAG_STAGE2_THIEF 0x00002000 //8192
#define OPINIONFLAG_STAGE3_THIEF 0x00004000 //16384
#define OPINIONFLAG_STAGE4_THIEF 0x00008000 //32768
#define OPINIONFLAG_STAGE1_WORSTCOMMANDEREVER 0x00010000 //65536 // was commander (most senior merc around) when a lot of our people (including militia) died
#define OPINIONFLAG_STAGE2_WORSTCOMMANDEREVER 0x00020000 //131072
#define OPINIONFLAG_STAGE3_WORSTCOMMANDEREVER 0x00040000 //262144
#define OPINIONFLAG_STAGE4_WORSTCOMMANDEREVER 0x00080000 //524288
#define OPINIONFLAG_STAGE1_RICHGUY 0x00100000 //1048576 // gets paid a lot more than we do
#define OPINIONFLAG_STAGE2_RICHGUY 0x00200000 //2097152
#define OPINIONFLAG_STAGE3_RICHGUY 0x00400000 //4194304
#define OPINIONFLAG_STAGE4_RICHGUY 0x00800000 //8388608
#define OPINIONFLAG_STAGE1_BETTERGEAR 0x01000000 //16777216 // has a lot better gear than we do
#define OPINIONFLAG_STAGE2_BETTERGEAR 0x02000000 //33554432
#define OPINIONFLAG_STAGE3_BETTERGEAR 0x04000000 //67108864
#define OPINIONFLAG_STAGE4_BETTERGEAR 0x08000000 //134217728
#define OPINIONFLAG_STAGE1_YOUMOUNTEDAGUNONMYBREASTS 0x10000000 //268435456 // used our body to rest his gun on
#define OPINIONFLAG_STAGE2_YOUMOUNTEDAGUNONMYBREASTS 0x20000000 //536870912
#define OPINIONFLAG_STAGE3_YOUMOUNTEDAGUNONMYBREASTS 0x40000000 //1073741824
#define OPINIONFLAG_STAGE4_YOUMOUNTEDAGUNONMYBREASTS 0x80000000 //2147483648
// flagmask 3
#define OPINIONFLAG_STAGE1_BANDAGED 0x00000001 //1 // bandaged our wounds
#define OPINIONFLAG_STAGE2_BANDAGED 0x00000002 //2
#define OPINIONFLAG_STAGE3_BANDAGED 0x00000004 //4
#define OPINIONFLAG_STAGE4_BANDAGED 0x00000008 //8
#define OPINIONFLAG_STAGE1_DRINKBUDDIES_GOOD 0x00000010 //16 // had a drink with him, he's okay.
#define OPINIONFLAG_STAGE2_DRINKBUDDIES_GOOD 0x00000020 //32
#define OPINIONFLAG_STAGE3_DRINKBUDDIES_GOOD 0x00000040 //64
#define OPINIONFLAG_STAGE4_DRINKBUDDIES_GOOD 0x00000080 //128
#define OPINIONFLAG_STAGE1_DRINKBUDDIES_SUPER 0x00000100 //256 // had a drink with him, he's super okay
#define OPINIONFLAG_STAGE2_DRINKBUDDIES_SUPER 0x00000200 //512
#define OPINIONFLAG_STAGE3_DRINKBUDDIES_SUPER 0x00000400 //1024
#define OPINIONFLAG_STAGE4_DRINKBUDDIES_SUPER 0x00000800 //2048
#define OPINIONFLAG_STAGE1_DRINKBUDDIES_BAD 0x00001000 //4096 // had a drink with him, don't like him
#define OPINIONFLAG_STAGE2_DRINKBUDDIES_BAD 0x00002000 //8192
#define OPINIONFLAG_STAGE3_DRINKBUDDIES_BAD 0x00004000 //16384
#define OPINIONFLAG_STAGE4_DRINKBUDDIES_BAD 0x00008000 //32768
#define OPINIONFLAG_STAGE1_DRINKBUDDIES_WORSE 0x00010000 //65536 // had a drink with him, and I REALLY don't like him now
#define OPINIONFLAG_STAGE2_DRINKBUDDIES_WORSE 0x00020000 //131072
#define OPINIONFLAG_STAGE3_DRINKBUDDIES_WORSE 0x00040000 //262144
#define OPINIONFLAG_STAGE4_DRINKBUDDIES_WORSE 0x00080000 //524288
/*#define OPINIONFLAG_STAGE1_RICHGUY 0x00100000 //1048576 // gets paid a lot more than we do
#define OPINIONFLAG_STAGE2_RICHGUY 0x00200000 //2097152
#define OPINIONFLAG_STAGE3_RICHGUY 0x00400000 //4194304
#define OPINIONFLAG_STAGE4_RICHGUY 0x00800000 //8388608
#define OPINIONFLAG_STAGE1_BETTERGEAR 0x01000000 //16777216 // has a lot better gear than we do
#define OPINIONFLAG_STAGE2_BETTERGEAR 0x02000000 //33554432
#define OPINIONFLAG_STAGE3_BETTERGEAR 0x04000000 //67108864
#define OPINIONFLAG_STAGE4_BETTERGEAR 0x08000000 //134217728
#define OPINIONFLAG_STAGE1_YOUMOUNTEDAGUNONMYBREASTS 0x10000000 //268435456 // used our body to rest his gun on
#define OPINIONFLAG_STAGE2_YOUMOUNTEDAGUNONMYBREASTS 0x20000000 //536870912
#define OPINIONFLAG_STAGE3_YOUMOUNTEDAGUNONMYBREASTS 0x40000000 //1073741824
#define OPINIONFLAG_STAGE4_YOUMOUNTEDAGUNONMYBREASTS 0x80000000 //2147483648*/
#define OPINIONFLAG_STAGE4_ALL 0x88888888 // flags of all final stages, used when rolling over
// ----------------------------------------------------------------
extern void HandleMoraleEvent( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent, INT16 sMapX, INT16 sMapY, INT8 bMapZ );
extern void RefreshSoldierMorale( SOLDIERTYPE * pSoldier );
extern INT8 GetMoraleModifier( SOLDIERTYPE * pSoldier );
@@ -163,4 +293,35 @@ void DecayTacticalMoraleModifiers( void );
// Flugente: calculate A's opinion of B
INT8 SoldierRelation( SOLDIERTYPE* pSoldierA, SOLDIERTYPE* pSoldierB);
// Flugente: dynamic opinions
// modify usProfileA's opinion of usProfileB because of usEvent
void AddOpinionEvent( UINT8 usProfileA, UINT8 usProfileB, UINT8 usEvent );
// get usProfileA's opinion of usProfileB concerning usEvent
INT8 GetDynamicOpinion( UINT8 usProfileA, UINT8 usProfileB, UINT8 usEvent );
// daily rollover of opinions
void HandleDynamicOpinions();
// a day has passed, 'age' opinions
void RolloverDynamicOpinions( UINT8 usProfileA );
// check wether other people are friends with someone else we hate. All persons must be in Arulco
void CheckForFriendsofHated( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionOnContractExtension( UINT8 ubCode, UINT8 usProfile );
void HandleDynamicOpinionCivKill( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionSlowdown( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionWageJealousy( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionDisability( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionAddict( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionThief( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionFoodSharing( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionGear( SOLDIERTYPE* pSoldier );
void HandleDynamicOpinionBattleLosses();
void HandleDynamicOpinionRetreat();
void HandleDynamicOpinionTeamDrinking( SOLDIERTYPE* pSoldier );
UINT8 HighestInventoryCoolness( SOLDIERTYPE* pSoldier );
#endif
+9
View File
@@ -2488,6 +2488,9 @@ BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLE
fDontContinue = TRUE;
UnSetUIBusy( pSoldier->ubID );
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( pSoldier );
}
}
@@ -3227,6 +3230,9 @@ void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fF
{
TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT );
pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY;
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( pSoldier );
}
break;
default:
@@ -3237,6 +3243,9 @@ void InternalSelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fF
{
TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT );
pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY;
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( pSoldier );
}
}
break;
+3
View File
@@ -783,6 +783,9 @@ INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
if ( MercIsHot( pSoldier ) && pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__PLAYER_CHARACTER) // SANDRO - added this
{
TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT );
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( pSoldier );
}
// do we realize that we just can't do this?
if ( (100 - (pSoldier->ubSkillCheckAttempts - 2) * 20) < EffectiveWisdom( pSoldier ) )
+5
View File
@@ -3934,7 +3934,12 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
else if ( pSoldier->bTeam == CIV_TEAM && !pSoldier->aiData.bNeutral && pSoldier->bSide != gbPlayerNum )
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsHostiles++;
else
{
gMercProfiles[ MercPtrs[ ubAttacker ]->ubProfile ].records.usKillsOthers++;
// Flugente: dynamic opinions
HandleDynamicOpinionCivKill( MercPtrs[ubAttacker] );
}
break;
}
//gMercProfiles[ MercPtrs[ pSoldier->ubAttackerID ]->ubProfile ].usKills++;
+51 -7
View File
@@ -7691,6 +7691,9 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
{
TacticalCharacterDialogue( this, QUOTE_PERSONALITY_TRAIT );
this->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY;
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( this );
}
}
}
@@ -7704,6 +7707,9 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
{
TacticalCharacterDialogue( this, QUOTE_PERSONALITY_TRAIT );
this->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY;
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( this );
}
}
}
@@ -7718,8 +7724,10 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
{
TacticalCharacterDialogue( this, QUOTE_PERSONALITY_TRAIT );
this->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY;
}
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( this );
}
}
}
@@ -7735,6 +7743,9 @@ void SOLDIERTYPE::EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCou
{
TacticalCharacterDialogue( this, QUOTE_PERSONALITY_TRAIT );
this->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY;
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( this );
}
}
}
@@ -9626,6 +9637,12 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sPo
// reduce poison damage by poison resistance
sPoisonAdd = (INT16)(sPoisonAdd * (100 - this->GetPoisonResistance())/100);
// Flugente: dynamic opinions
if ( ubAttacker != NOBODY && MercPtrs[ubAttacker] )
{
AddOpinionEvent( this->ubProfile, MercPtrs[ubAttacker]->ubProfile, OPINIONEVENT_FRIENDLYFIRE );
}
// CJC Jan 21 99: add check to see if we are hurting an enemy in an enemy-controlled
// sector; if so, this is a sign of player activity
switch ( this->bTeam )
@@ -12682,6 +12699,9 @@ UINT32 SOLDIERTYPE::SoldierDressWound( SOLDIERTYPE *pVictim, INT16 sKitPts, INT1
return(0);
}
// Flugente: dynamic opinions
AddOpinionEvent( pVictim->ubProfile, this->ubProfile, OPINIONEVENT_BANDAGED );
bInitialBleeding = pVictim->bBleeding;
// in case he has multiple kits in hand, limit influence of kit status to 100%!
@@ -13707,6 +13727,9 @@ BOOLEAN SOLDIERTYPE::CheckForBreathCollapse( void )
if ( MercIsHot( this ) && this->ubWhatKindOfMercAmI != MERC_TYPE__PLAYER_CHARACTER )
{
TacticalCharacterDialogue( this, QUOTE_PERSONALITY_TRAIT );
// Flugente: dynamic opinions
HandleDynamicOpinionDisability( this );
}
else
{
@@ -14225,7 +14248,7 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
// for some reason I find EXTREMELY FRUSTRATING, we might get a heigth of 2 on a totally empty tile... so we check if we could occupy the tile
if ( !IsLocationSittable( nextGridNoinSight, 0 ) )
{
// resting our gun on people would be rude - only allow if nobody is there
// resting our gun on people is allowed sometimes
UINT usPersonID = WhoIsThere2( nextGridNoinSight, this->pathing.bLevel );
if( usPersonID == NOBODY )
applybipod = TRUE;
@@ -14233,13 +14256,18 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
{
SOLDIERTYPE* pSoldier = MercPtrs[ usPersonID ];
// if the other person is an ally an prone
// if the other person is an ally and prone
if ( this->bSide == pSoldier->bSide && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE )
{
// if we are facing the other guy in a 90 degree angle, we can mount our gun on his back
// Once merc's relationship allows angering mercs through actions of others, add a penalty here
if ( this->ubDirection == gTwoCCDirection[ pSoldier->ubDirection ] || this->ubDirection == gTwoCDirection[ pSoldier->ubDirection ] )
if ( this->ubDirection == gTwoCCDirection[pSoldier->ubDirection] || this->ubDirection == gTwoCDirection[pSoldier->ubDirection] )
{
applybipod = TRUE;
// Flugente: dynamic opinions
AddOpinionEvent( MercPtrs[usPersonID]->ubProfile, this->ubProfile, OPINIONEVENT_YOUMOUNTEDAGUNONMYBREASTS );
}
}
}
}
@@ -14285,9 +14313,25 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
{
// for some reason I find EXTREMELY FRUSTRATING, we might get a heigth of 2 on a totally empty tile... so we check if we could occupy the tile
if ( !IsLocationSittable( nextGridNoinSight, 0 ) )
// resting our gun on people would be rude - only allow if nobody is there
if( WhoIsThere2( nextGridNoinSight, 0 ) == NOBODY )
applybipod = TRUE;
{
// resting our gun on people is allowed sometimes
UINT usPersonID = WhoIsThere2( nextGridNoinSight, this->pathing.bLevel );
if ( usPersonID == NOBODY )
applybipod = TRUE;
else
{
SOLDIERTYPE* pSoldier = MercPtrs[usPersonID];
// if the other person is an ally and prone
if ( this->bSide == pSoldier->bSide && gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_CROUCH )
{
applybipod = TRUE;
// Flugente: dynamic opinions
AddOpinionEvent( MercPtrs[usPersonID]->ubProfile, this->ubProfile, OPINIONEVENT_YOUMOUNTEDAGUNONMYBREASTS );
}
}
}
}
}
+6
View File
@@ -125,6 +125,7 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha
strcmp(name, "cth_vs_creatures") == 0 ||
strcmp(name, "insurance") == 0 ||
strcmp(name, "spotter") == 0 ||
strcmp(name, "dislikebackground" ) == 0 ||
strcmp(name, "druguse") == 0 ||
strcmp(name, "xenophobic") == 0 ||
strcmp(name, "corruptionspread") == 0 ||
@@ -519,6 +520,11 @@ backgroundEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curBackground.value[BG_PERC_SPOTTER] = min(30, max(-30, (INT16) atol(pData->szCharData) ));
}
else if ( strcmp( name, "dislikebackground" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curBackground.value[BG_DISLIKEBG] = (INT16)atol( pData->szCharData );
}
else if(strcmp(name, "druguse") == 0)
{
pData->curElement = ELEMENT;
+6
View File
@@ -307,6 +307,9 @@ typedef enum
NUM_RACIST
} RacistLevels;
// Flugente: dynamic opinons: number of profile flagmasks
#define OPINION_FLAGMASKS_NUMBER 3
//////////////////////////////////////////////////////////////////////
typedef enum
@@ -952,6 +955,9 @@ public:
// anv: simplified ubExposedInSector, hours until snitch can go undercover after exposition
UINT8 ubSnitchExposedCooldown;
// Flugente: flagmasks for dynamic opinions on each and every other person. Yes, this is significant in size
UINT32 usDynamicOpinionFlagmask[NUM_PROFILES][OPINION_FLAGMASKS_NUMBER];
}; // MERCPROFILESTRUCT;
// WANNE - BMP: DONE!