Files
source/Strategic/Strategic Merc Handler.cpp
T
2024-11-20 20:12:05 +02:00

1542 lines
50 KiB
C++

#include "Types.h"
#include "Strategic Merc Handler.h"
#include "History.h"
#include "Game clock.h"
#include "insurance Contract.h"
#include "Soldier Profile.h"
#include "Game Event Hook.h"
#include "Assignments.h"
#include "Overhead.h"
#include "Merc Contract.h"
#include "Merc Hiring.h"
#include "Dialogue Control.h"
#include "Random.h"
#include "Morale.h"
#include "Mercs.h"
#include "Mapscreen.h"
#include "weapons.h"
#include "Personnel.h"
#include "Strategic Movement.h"
#include "LaptopSave.h"
#include "Message.h"
#include "Text.h"
#include "Interface.h"
#include "strategic.h"
#include "strategicmap.h"
#include "Strategic Status.h"
#include "aim.h"
#include "email.h"
#include "Map Screen Interface.h"
#include "Campaign.h"
#include "Soldier Add.h"
#include "screenids.h"
#include "gameloop.h"
#include "jascreens.h"
#include "Soldier macros.h"
#include "finances.h"
#include "GameSettings.h"
#include "Quests.h"
// HEADROCK HAM B1: Additional Include for Dynamic Roaming Restrictions
#include "MilitiaSquads.h"
// HEADROCK HAM 3.6: Additional include for Facility Operating Deby
#include "Facilities.h"
// HEADROCK HAM 3.6: And another include, for militia upkeep costs.
#include "Town Militia.h"
#include "DynamicDialogue.h" // added by Flugente for HandleDynamicOpinionsDailyRefresh()
#ifdef JA2UB
#include "ub_config.h"
#endif
//forward declarations of common classes to eliminate includes
class OBJECTTYPE;
class SOLDIERTYPE;
#define NUM_DAYS_TILL_UNPAID_RPC_QUITS 3
// can you say me too after someone has said thier contract about to end
BOOLEAN fContractOverMeTooFlag = FALSE;
BOOLEAN fContractOverAndIWontRenewMeTooFlag = FALSE;
BOOLEAN fProcessingAMerc = FALSE;
SOLDIERTYPE *pProcessingSoldier = NULL;
extern BOOLEAN gfFirstMercSayingQuoteWillLeaveNoMatterWhat = FALSE;
// build a list of mercs based on departure time
void BuildMercQuitList( SOLDIERTYPE *pMercList );
void StrategicHandlePlayerTeamMercDeath( SOLDIERTYPE *pSoldier )
{
SOLDIERTYPE *pKiller = NULL;
INT16 sSectorX, sSectorY;
//if the soldier HAS a profile
if( pSoldier->ubProfile != NO_PROFILE )
{
//shadooow: moved here so the "merc is dead" message appears before "history log changed" which is what happens in tactical
if (guiCurrentScreen != GAME_SCREEN || !pSoldier->bInSector)
{
ScreenMsg(FONT_RED, MSG_INTERFACE, pMercDeadString[0], pSoldier->name);
}
//add to the history log the fact that the merc died and the circumstances
if( pSoldier->ubAttackerID != NOBODY )
{
pKiller = pSoldier->ubAttackerID;
}
// CJC Nov 11, 2002
// Use the soldier's sector location unless impossible
if (pSoldier->sSectorX != 0 && pSoldier->sSectorY != 0)
{
sSectorX = pSoldier->sSectorX;
sSectorY = pSoldier->sSectorY;
}
else
{
sSectorX = gWorldSectorX;
sSectorY = gWorldSectorY;
}
if( pKiller && pKiller->bTeam == OUR_TEAM )
{
AddHistoryToPlayersLog( HISTORY_MERC_KILLED_CHARACTER, pSoldier->ubProfile, GetWorldTotalMin(), sSectorX, sSectorY );
}
else
{
AddHistoryToPlayersLog( HISTORY_MERC_KILLED, pSoldier->ubProfile, GetWorldTotalMin(), sSectorX, sSectorY );
}
}
// robot, vehicles and EPCs don't count against death rate - the mercs back home don't particularly give a damn about locals & machines!
if ( !AM_AN_EPC( pSoldier ) && !AM_A_ROBOT( pSoldier ) && !(pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE))
{
// keep track of how many mercs have died under player's command (for death rate, can't wait until removed from team)
gStrategicStatus.ubMercDeaths++;
}
pSoldier->flags.uiStatusFlags |= SOLDIER_DEAD;
// Set breath to 0!
pSoldier->bBreathMax = pSoldier->bBreath = 0;
// not asleep, DEAD!
pSoldier->flags.fMercAsleep = FALSE;
//if the merc had life insurance
if( pSoldier->usLifeInsurance )
{
// if he didn't die during auto-resolve
if( guiCurrentScreen != AUTORESOLVE_SCREEN )
{
// check whether this was obviously a suspicious death
// if killed within an hour of being insured
if ( pSoldier->uiStartTimeOfInsuranceContract <= GetWorldTotalMin() && GetWorldTotalMin() - pSoldier->uiStartTimeOfInsuranceContract < 60 )
{
gMercProfiles[ pSoldier->ubProfile ].ubSuspiciousDeath = VERY_SUSPICIOUS_DEATH;
}
// if killed by someone on our team, or while there weren't any opponents around
else if (pSoldier->ubAttackerID->bTeam == OUR_TEAM || !gTacticalStatus.fEnemyInSector )
{
// cause insurance company to suspect fraud and investigate this claim
gMercProfiles[ pSoldier->ubProfile ].ubSuspiciousDeath = SUSPICIOUS_DEATH;
}
}
AddLifeInsurancePayout( pSoldier );
}
// robot and EPCs don't penalize morale - merc don't care about fighting machines and the lives of locals much
if ( !AM_AN_EPC( pSoldier ) && !AM_A_ROBOT( pSoldier ) )
{
// Change morale of others based on this
HandleMoraleEvent( pSoldier, MORALE_TEAMMATE_DIED, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
}
//if its a MERC merc, record the time of his death
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC )
{
pSoldier->iEndofContractTime = GetWorldTotalMin();
//set is so Speck can say that a merc is dead
LaptopSaveInfo.ubSpeckCanSayPlayersLostQuote = 1;
}
//Set the fact that the merc is DEAD!!
gMercProfiles[ pSoldier->ubProfile ].bMercStatus = MERC_IS_DEAD;
if( pSoldier->bAssignment != ASSIGNMENT_DEAD )
{
SetTimeOfAssignmentChangeForMerc( pSoldier );
}
// handle strategic level death
HandleStrategicDeath( pSoldier );
}
// MercDailyUpdate() gets called every day at midnight. If something is to happen to a merc that day, add an event for it.
void MercDailyUpdate()
{
INT32 cnt;
UINT16 bLastTeamID;
SOLDIERTYPE *pSoldier;
//SOLDIERTYPE *pQuitList[ 21 ];
MERCPROFILESTRUCT *pProfile;
UINT32 uiChance;
INT32 iOffset = 0;
//if its the first day, leave
if( GetWorldDay() == 1 )
return;
// debug message
ScreenMsg( MSG_FONT_RED, MSG_DEBUG, L"%s - Doing MercDailyUpdate", WORLDTIMESTR );
// if the death rate is very low (this is independent of mercs' personal deathrate tolerances)
if (CalcDeathRate() < 5)
{
// everyone gets a morale bonus, which also gets player a reputation bonus.
HandleMoraleEvent( NULL, MORALE_LOW_DEATHRATE, -1, -1, -1 );
}
//add an event so the merc will say the departing warning ( 2 hours prior to leaving
// Do so for all time slots they will depart from
AddSameDayStrategicEvent( EVENT_MERC_ABOUT_TO_LEAVE, MERC_ARRIVE_TIME_SLOT_1 - ( 2 * 60 ), 0 );
AddSameDayStrategicEvent( EVENT_MERC_ABOUT_TO_LEAVE, MERC_ARRIVE_TIME_SLOT_2 - ( 2 * 60 ), 0 );
AddSameDayStrategicEvent( EVENT_MERC_ABOUT_TO_LEAVE, MERC_ARRIVE_TIME_SLOT_3 - ( 2 * 60 ), 0 );
AddSameDayStrategicEvent( EVENT_BEGIN_CONTRACT_RENEWAL_SEQUENCE, MERC_ARRIVE_TIME_SLOT_1, 0 );
AddSameDayStrategicEvent( EVENT_BEGIN_CONTRACT_RENEWAL_SEQUENCE, MERC_ARRIVE_TIME_SLOT_2, 0 );
AddSameDayStrategicEvent( EVENT_BEGIN_CONTRACT_RENEWAL_SEQUENCE, MERC_ARRIVE_TIME_SLOT_3, 0 );
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
//loop though all the mercs
for ( pSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; ++cnt,++pSoldier)
{
//if the merc is active
if ( ( pSoldier->bActive )&&( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != IN_TRANSIT ) )
{
//CJC: Reset dialogue flags for quotes that can be said once/day
pSoldier->usQuoteSaidFlags &= ( ~SOLDIER_QUOTE_SAID_ANNOYING_MERC );
// ATE: Reset likes gun flag
pSoldier->usQuoteSaidFlags &= ( ~SOLDIER_QUOTE_SAID_LIKESGUN );
// ATE: Reset seen corpse flag
pSoldier->usQuoteSaidFlags &= ( ~SOLDIER_QUOTE_SAID_ROTTINGCORPSE );
// ATE; Reset found something nice flag...
pSoldier->usQuoteSaidFlags &= ( ~SOLDIER_QUOTE_SAID_FOUND_SOMETHING_NICE );
// ATE: Decrement tolerance value...
pSoldier->bCorpseQuoteTolerance--;
if ( pSoldier->bCorpseQuoteTolerance < 0 )
{
pSoldier->bCorpseQuoteTolerance = 0;
}
// CJC: For some personalities, reset personality quote said flag
if ( pSoldier->ubProfile != NO_PROFILE )
{
switch( gMercProfiles[ pSoldier->ubProfile ].bDisability )
{
case HEAT_INTOLERANT:
case CLAUSTROPHOBIC:
case NONSWIMMER:
case FEAR_OF_INSECTS:
case AFRAID_OF_HEIGHTS:
// repeatable once per day
pSoldier->usQuoteSaidFlags &= ( ~SOLDIER_QUOTE_SAID_PERSONALITY );
break;
default:
break;
}
}
//ATE: Try to see if our equipment sucks!
if ( SoldierHasWorseEquipmentThanUsedTo( pSoldier ) )
{
// Randomly anytime between 6:00, and 10:00
AddSameDayStrategicEvent( EVENT_MERC_COMPLAIN_EQUIPMENT, 360 + Random( 1080 ) , pSoldier->ubProfile );
}
// increment days served by this grunt
gMercProfiles[pSoldier->ubProfile].usTotalDaysServed++;
// player has hired him, so he'll eligible to get killed off on another job
gMercProfiles[pSoldier->ubProfile].ubMiscFlags3 |= PROFILE_MISC_FLAG3_PLAYER_HAD_CHANCE_TO_HIRE;
//handle Slay differently if SlayForever is enabled
if( pSoldier->ubProfile == SLAY && gGameExternalOptions.fEnableSlayForever == TRUE)
{
}
//if the character is an RPC
else if ( gMercProfiles[pSoldier->ubProfile].Type == PROFILETYPE_RPC )
{
INT16 sSalary = gMercProfiles[ pSoldier->ubProfile ].sSalary;
INT32 iMoneyOwedToMerc = 0;
//increment the number of days the mercs has been on the team
pSoldier->iTotalContractLength++;
//if the player owes the npc money, the balance field will be negative
if( gMercProfiles[ pSoldier->ubProfile ].iBalance < 0 )
{
//the player owes the npc the salary and whatever money the player owes the npc
iMoneyOwedToMerc = sSalary + ( - gMercProfiles[ pSoldier->ubProfile ].iBalance );
}
else
{
//else the player only owes the salary
iMoneyOwedToMerc = sSalary;
}
//if the player owes money
if( iMoneyOwedToMerc != 0 )
{
//if the player can afford to pay them
if( LaptopSaveInfo.iCurrentBalance >= iMoneyOwedToMerc )
{
//add the transaction to the player
AddTransactionToPlayersBook( PAYMENT_TO_NPC, pSoldier->ubProfile, GetWorldTotalMin(), -iMoneyOwedToMerc);
//if the player owed money to the npc
if( gMercProfiles[ pSoldier->ubProfile ].iBalance < 0 )
{
// reset the amount
gMercProfiles[ pSoldier->ubProfile ].iBalance = 0;
}
}
else
{
CHAR16 zMoney[128];
//create a string for the salary owed to the npc
swprintf( zMoney, L"%d", sSalary );
InsertCommasForDollarFigure( zMoney );
InsertDollarSignInToString( zMoney );
//Display a screen msg indicating that the npc was NOT paid
ScreenMsg( FONT_MCOLOR_WHITE, MSG_INTERFACE, pMessageStrings[ MSG_CANT_AFFORD_TO_PAY_NPC_DAILY_SALARY_MSG ], gMercProfiles[ pSoldier->ubProfile ].zNickname, zMoney );
//if the merc hasnt been paid for NUM_DAYS_TILL_UNPAID_RPC_QUITS days, the merc will quit
if( ( gMercProfiles[ pSoldier->ubProfile ].iBalance - sSalary ) <= -( sSalary * NUM_DAYS_TILL_UNPAID_RPC_QUITS ) )
{
//
//Set it up so the merc quits
//
MercsContractIsFinished( pSoldier->ubID );
}
else
{
//set how much money the player owes the merc
gMercProfiles[ pSoldier->ubProfile ].iBalance -= sSalary;
// Add even for displaying a dialogue telling the player this....
AddSameDayStrategicEvent( EVENT_RPC_WHINE_ABOUT_PAY, MERC_ARRIVE_TIME_SLOT_1, pSoldier->ubID );
}
}
}
}
if( !MercThinksHisMoraleIsTooLow( pSoldier ) && ProfileHasSkillTrait( pSoldier->ubProfile, SNITCH_NT ) )
{
ModifyPlayerReputation( gSkillTraitValues.ubSNTPassiveReputationGain );
}
DailyMoraleUpdate( pSoldier );
CheckIfMercGetsAnotherContract( pSoldier );
}
else
{
if( ( pSoldier->bActive ) && ( pSoldier->bAssignment == ASSIGNMENT_POW ) )
{
pSoldier->iEndofContractTime += 1440;
}
}
// if active, here, & alive (POW is ok, don't care)
if( ( pSoldier->bActive ) && ( pSoldier->bAssignment != ASSIGNMENT_DEAD ) &&
( pSoldier->bAssignment != IN_TRANSIT ) )
{
// increment the "man days" played counter for each such merc in the player's employment
gStrategicStatus.uiManDaysPlayed++;
}
}
//r eset the counter
cnt = 0;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; cnt++,pSoldier++)
{
//if the merc is active
if ( ( pSoldier->bActive )&&( pSoldier->bAssignment != ASSIGNMENT_POW ) && ( pSoldier->bAssignment != IN_TRANSIT ) )
{
//if its a MERC merc, determine if the merc should leave ( because player refused to pay for merc )
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC )
{
//if the players account status is invalid
if( LaptopSaveInfo.gubPlayersMercAccountStatus == MERC_ACCOUNT_INVALID )
{
//if the soldier is alive anc concious
if( IsTheSoldierAliveAndConcious( pSoldier ) )
{
//if the merc should leave today
MercsContractIsFinished( pSoldier->ubID );
}
}
}
}
}
// WANNE: Only send mails from the original 1.13 merc, and not from the wildfire merc,
// otherwise we get wrong mails cause of hardcoded Email.edt structure!!!!!
UINT16 numOriginalProfiles = 255;
for( cnt = 0; cnt < numOriginalProfiles; ++cnt)
{
pProfile = &(gMercProfiles[ cnt ]);
// dead guys don't do nuthin' !
if ( pProfile->bMercStatus == MERC_IS_DEAD )
{
continue;
}
//Every day reset this variable
pProfile->uiPrecedentQuoteSaid = 0;
// skip anyone currently on the player's team
if ( IsMercOnTeam( (UINT8) cnt, FALSE, FALSE ))
{
continue;
}
// if he's an AIM/M.E.R.C. merc
if( IsProfileIdAnAimOrMERCMerc( (UINT8)cnt ) )
{
// if he's not just on his way home
if ( pProfile->bMercStatus != MERC_RETURNING_HOME )
{
// check if any of his stats improve through working or training
HandleUnhiredMercImprovement(pProfile);
// if he's working on another job
if (pProfile->bMercStatus == MERC_WORKING_ELSEWHERE)
{
// check if he's killed
//Kaiden: Externalized if Mercs get killed
if (gGameExternalOptions.gfMercsDieOnAssignment)
HandleUnhiredMercDeaths( cnt );
}
}
}
// if merc is currently unavailable
if( pProfile->uiDayBecomesAvailable > 0 )
{
// reduce time til available by one day
pProfile->uiDayBecomesAvailable--;
// Check to see if the merc has become available
if (pProfile->uiDayBecomesAvailable == 0)
{
//if the merc CAN become ready
if( pProfile->bMercStatus != MERC_FIRED_AS_A_POW )
{
pProfile->bMercStatus = MERC_OK;
// if the player has left a message for this merc
if ( pProfile->ubMiscFlags3 & PROFILE_MISC_FLAG3_PLAYER_LEFT_MSG_FOR_MERC_AT_AIM )
{
iOffset = AIM_REPLY_BARRY;
//remove the Flag, so if the merc goes on another assignment, the player can leave an email.
pProfile->ubMiscFlags3 &= ~PROFILE_MISC_FLAG3_PLAYER_LEFT_MSG_FOR_MERC_AT_AIM;
#ifdef JA2UB
//if the Laptop is NOT broken
if( gubQuest[ QUEST_FIX_LAPTOP ] != QUESTINPROGRESS && gGameUBOptions.LaptopQuestEnabled == TRUE )
{
#endif
// Read from EmailMercAvailable.xml
UINT8 pMerc = 0;
UINT8 iMerc = 0;
UINT8 oMerc = 0;
if ( ReadXMLEmail == TRUE )
{
oMerc = cnt;
iMerc = oMerc * 1;
if ( oMerc != 0 )
pMerc = oMerc + 1;
else
pMerc = 0;
if ( gMercProfiles[cnt].Type == PROFILETYPE_AIM )
AddEmailTypeXML( pMerc, iMerc, iMerc, GetWorldTotalMin(), -1 , TYPE_EMAIL_AIM_AVAILABLE);
}
else
{
// Read from Email.edt and sender (nickname) from MercProfiles.xml
if (cnt < 170)
{
// TO DO: send E-mail to player telling him the merc has returned from an assignment
AddEmail( ( UINT8 )( iOffset + ( cnt * AIM_REPLY_LENGTH_BARRY ) ), AIM_REPLY_LENGTH_BARRY, (UINT8) cnt, GetWorldTotalMin(), -1, -1 , TYPE_EMAIL_EMAIL_EDT_NAME_MERC);
}
else
{
// Wildfire mercs
if (cnt < 178)
{
UINT16 iMsgLength = cnt;
// Fake Barry Unger mail, but with the msgLength of the WF merc ID -> Correct in PreProcessEmail()
AddEmailWFMercAvailable( ( UINT8 )( iOffset + 0 * AIM_REPLY_LENGTH_BARRY ), iMsgLength, cnt, GetWorldTotalMin(), -1 , TYPE_EMAIL_EMAIL_EDT_NAME_MERC);
}
// Generic mail
else
{
// TODO.RW: Send generic mail
UINT16 iMsgLength = cnt;
// Fake Barry Unger mail, but with the msgLength of the WF merc ID -> Correct in PreProcessEmail()
AddEmailWFMercAvailable( ( UINT8 )( iOffset + 0 * AIM_REPLY_LENGTH_BARRY ), iMsgLength, cnt, GetWorldTotalMin(), -1 , TYPE_EMAIL_EMAIL_EDT_NAME_MERC);
}
}
}
// WANNE: Should we stop time compression. I don't know.
//StopTimeCompression();
#ifdef JA2UB
}
#endif
}
}
}
}
else // was already available today
{
// if it's an AIM or M.E.R.C. merc
if( IsProfileIdAnAimOrMERCMerc( (UINT8)cnt ) )
{
// check to see if he goes on another assignment
if ( gMercProfiles[cnt].Type == PROFILETYPE_AIM )
{
// A.I.M. merc
uiChance = 2 * pProfile->bExpLevel;
// player has now had a chance to hire him, so he'll eligible to get killed off on another job
pProfile->ubMiscFlags3 |= PROFILE_MISC_FLAG3_PLAYER_HAD_CHANCE_TO_HIRE;
}
else if ( gMercProfiles[cnt].Type == PROFILETYPE_MERC )
{
// M.E.R.C. merc - very rarely get other work
uiChance = 1 * pProfile->bExpLevel;
// player doesn't have a chance to hire any M.E.R.C's until after Speck's E-mail is sent
if (GetWorldDay() > DAYS_TIL_M_E_R_C_AVAIL)
{
// player has now had a chance to hire him, so he'll eligible to get killed off on another job
pProfile->ubMiscFlags3 |= PROFILE_MISC_FLAG3_PLAYER_HAD_CHANCE_TO_HIRE;
}
}
// tais: disable mercs being on assignment
if (Random(100) < uiChance && gGameExternalOptions.fMercsOnAssignment < 2)
{
pProfile->bMercStatus = MERC_WORKING_ELSEWHERE;
pProfile->uiDayBecomesAvailable = 1 + Random(6 + (pProfile->bExpLevel / 2) ); // 1-(6 to 11) days
}
}
}
// Decrement morale hangover (merc appears hirable, he just gives lame refusals during this time, though)
if( pProfile->ubDaysOfMoraleHangover > 0 )
{
pProfile->ubDaysOfMoraleHangover--;
}
}
// build quit list
//BuildMercQuitList( pQuitList );
#ifdef JA2UB
//no UB
#else
HandleSlayDailyEvent( );
#endif
// rebuild list for mapscreen
ReBuildCharactersList( );
// Buggler: Pay income for operating Facilities today.
if (giTotalEarnedForFacilityOperationsToday)
{
HandleDailyPaymentFacilityIncome();
}
// HEADROCK HAM 3.6: Pay debt for operating Facilities today. If can't be paid, apply loyalty hit.
if (giTotalOwedForFacilityOperationsToday)
{
HandleDailyPaymentFacilityDebt();
}
// HEADROCK HAM 3.6: Pay for militia upkeep
HandleMilitiaUpkeepPayment();
// anv: time for snitches to report
HandleSnitchCheck();
// Flugente: dynmaic opinion rollover
if (gGameExternalOptions.fDynamicOpinions)
{
HandleDynamicOpinionsDailyRefresh();
}
// Flugente: disease
HandleDiseaseDailyRefresh();
}
/*
void BuildMercQuitList( SOLDIERTYPE *pMercList )
{
// go through list of mercs on players team, fill pMercList sorted from most recent leave time, to furthest leave time
INT32 cnt;
INT8 bLastTeamID;
SOLDIERTYPE *pSoldier;
INT32 iCounter = 0;
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
//loop though all the mercs
for ( pSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; cnt++,pSoldier++, iCounter++ )
{
if ( pSoldier->bActive )
{
// copy to list
pMercList[ iCounter ] = pSoldier;
}
}
// now sort based on departure time..simple bubble sort
for( cnt = 0; cnt <=iCounter; cnt++ )
{
for( cntB = 0; cntB <=iCounter; cntB++ )
{
if( MercPtrs[ cntB ]->ubWhatKindOfMercAmI == MERC_TYPE__MERC )
{
//if the players account status is invalid
if( LaptopSaveInfo.gubPlayersMercAccountStatus == MERC_ACCOUNT_INVALID )
{
//if the soldier is alive anc concious
if( IsTheSoldierAliveAndConcious( MercPtrs[ cntB ] ) )
{
// swap
pSoldier = MercPtrs[ cntB ];
MercPtrs[ cntB ] = MercPtrs[ cnt ];
MercPtrs[ cnt ] = pSoldier;
}
}
}
else if( MercPtrs[ cntB ]->ubWhatKindOfMercAmI == MERC_TYPE__AIM )
{
if( MercPtrs[ cntB ]->iEndofContractTime < MercPtrs[ cnt ]->iEndofContractTime )
{
// swap
pSoldier = MercPtrs[ cntB ];
MercPtrs[ cntB ] = MercPtrs[ cnt ];
MercPtrs[ cnt ] = pSoldier;
}
}
else
{
// not a hirable guy, move to the botton
pSoldier = MercPtrs[ cnt ];
MercPtrs[ cnt ] = MercPtrs[ cntB ];
MercPtrs[ cntB ] = pSoldier;
}
}
}
return;
}
*/
/*
void HandleMercsAboutToLeave( SOLDIERTYPE *pMercList )
{
// run from top of list to bottom..if merc is gonna leave within a defined time frame of the previous guy and they are leaving the same day (today)
// then post then with the quote at the same time
for( iCounter = 0; iCounter < 21; iCounter++ )
{
if( iCounter == 0 )
{
// first guy, if he no leave today, no one is leave, go home
if( ( pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__MERC ) && ( pSoldier->ubWhatKindOfMercAmI != MERC_TYPE__AIM ) )
{
return;
}
else
{
if( ( pSoldier->iEndofContractTime / 1440 ) > (INT32)GetWorldDay( ) )
{
return;
}
else
{
//if the soldier is alive anc concious
if( IsTheSoldierAliveAndConcious( pSoldier ) )
{
//if the soldier is an AIM merc
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
{
//add an event so the merc will say the departing warning ( 2 hours prior to leaving
AddSameDayStrategicEvent( EVENT_MERC_ABOUT_TO_LEAVE_COMMENT, MERC_DEPARTURE_TIME_OF_DAY - 2 * 60, (UINT32) pSoldier->ubID );
}
else
{
// merc merc, they'll just leave
}
}
}
}
}
}
*/
// ATE: This function deals with MERC MERC and NPC's leaving because of not getting paid...
// NOT AIM renewals....
void MercsContractIsFinished( SoldierID ubID )
{
SOLDIERTYPE *pSoldier = ubID;
//if the soldier was removed before getting into this function, return
if( !pSoldier->bActive )
return;
if( fShowContractMenu )
{
fShowContractMenu = FALSE;
}
// go to mapscreen
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_ENTER_MAPSCREEN,0,0,0,0,0 );
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC )
{
//if the players account status is invalid
if( LaptopSaveInfo.gubPlayersMercAccountStatus == MERC_ACCOUNT_INVALID )
{
//Send the merc home
InterruptTime( );
PauseGame();
LockPauseState( 9 );
// Say quote for wishing to leave
TacticalCharacterDialogue( pSoldier, QUOTE_NOT_GETTING_PAID );
TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING_NO_ASK_EQUIP, 0, 0 );
pSoldier->ubLeaveHistoryCode = HISTORY_MERC_QUIT;
}
}
else if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC )
{
InterruptTime( );
PauseGame();
LockPauseState( 10 );
TacticalCharacterDialogue( pSoldier, QUOTE_NOT_GETTING_PAID_RPC );
TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING_NO_ASK_EQUIP, 0, 0 );
pSoldier->ubLeaveHistoryCode = HISTORY_MERC_QUIT;
}
}
// ATE: Called for RPCs who should now complain about no pay...
void RPCWhineAboutNoPay( SoldierID ubID )
{
SOLDIERTYPE *pSoldier = ubID;
//if the soldier was removed before getting into this function, return
if( !pSoldier->bActive )
return;
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC )
{
// Say quote for needing pay!
TacticalCharacterDialogue( pSoldier, QUOTE_NOT_GETTING_PAID );
}
}
// OK loop through and check!
BOOLEAN SoldierHasWorseEquipmentThanUsedTo( SOLDIERTYPE *pSoldier )
{
UINT16 usItem;
INT32 bBestArmour = -1;
INT32 bBestArmourIndex = -1;
INT32 bBestGun = -1;
INT32 bBestGunIndex = -1;
UINT32 invsize = pSoldier->inv.size();
for ( UINT32 cnt = 0; cnt < invsize; ++cnt )
{
// Look for best gun/armour
if ( pSoldier->inv[cnt].exists() == true )
{
usItem = pSoldier->inv[ cnt ].usItem;
// Check if it's a gun
if ( Item[ usItem ].usItemClass & IC_GUN )
{
if ( Weapon[ usItem ].ubDeadliness > bBestGun )
{
bBestGunIndex = (INT8)cnt;
bBestGun = Weapon[ usItem ].ubDeadliness;
}
}
// If it's armour
if ( Item[ usItem ].usItemClass & IC_ARMOUR )
{
if ( Armour[ Item[ usItem ].ubClassIndex ].ubProtection > bBestArmour )
{
bBestArmourIndex = (INT8)cnt;
bBestArmour = min(128,Armour[ Item[ usItem ].ubClassIndex ].ubProtection);
}
}
}
}
// Modify these values based on morale - lower opinion of equipment if morale low, increase if high
// this of course assumes default morale is 50
if ( bBestGun != -1 )
{
bBestGun = (bBestGun * (50 + pSoldier->aiData.bMorale)) / 100;
}
if ( bBestArmour != -1 )
{
bBestArmour = (bBestArmour * (50 + pSoldier->aiData.bMorale)) / 100;
}
// OK, check values!
if ( (bBestGun != -1 && bBestGun < ( gMercProfiles[ pSoldier->ubProfile ].bMainGunAttractiveness / 2 )) ||
(bBestArmour != -1 && bBestArmour < ( gMercProfiles[ pSoldier->ubProfile ].bArmourAttractiveness / 2 )) )
{
// Pipe up!
return( TRUE );
}
return( FALSE );
}
void MercComplainAboutEquipment( UINT8 ubProfile )
{
SOLDIERTYPE *pSoldier;
if ( ubProfile == LARRY_NORMAL )
{
if ( CheckFact( FACT_LARRY_CHANGED, 0 ) )
{
ubProfile = LARRY_DRUNK;
}
}
else if ( ubProfile == LARRY_DRUNK )
{
if ( CheckFact( FACT_LARRY_CHANGED, 0 ) == FALSE )
{
ubProfile = LARRY_NORMAL;
}
}
// Are we dead/ does merc still exist?
pSoldier = FindSoldierByProfileID( ubProfile, FALSE );
if ( pSoldier != NULL && pSoldier->stats.bLife >= OKLIFE )
{
if ( pSoldier->flags.fMercAsleep != TRUE && pSoldier->bAssignment < ON_DUTY )
{
//ATE: Double check that this problem still exists!
if ( SoldierHasWorseEquipmentThanUsedTo( pSoldier ) )
{
// Say quote!
TacticalCharacterDialogue( pSoldier, QUOTE_WHINE_EQUIPMENT );
// anv: morale hit
HandleMoraleEvent( pSoldier, MORALE_BAD_EQUIPMENT, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
ModifyPlayerReputation( REPUTATION_TOWN_LOST );
}
}
// if we can't complain right now, do it later
else
{
AddStrategicEvent( EVENT_MERC_COMPLAIN_EQUIPMENT, GetWorldTotalMin( ) + 60, ubProfile );
}
}
}
void UpdateBuddyAndHatedCounters( void )
{
UINT16 bMercID, bOtherID, bLastTeamID;
INT32 iLoop;
UINT8 ubOtherProfileID;
SOLDIERTYPE *pSoldier;
SOLDIERTYPE *pOtherSoldier;
MERCPROFILESTRUCT *pProfile;
BOOLEAN fSameGroupOnly;
BOOLEAN fUpdatedTimeTillNextHatedComplaint = FALSE;
bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
//loop though all the mercs
for ( pSoldier = MercPtrs[ bMercID ]; bMercID <= bLastTeamID; bMercID++,pSoldier++)
{
fSameGroupOnly = FALSE;
//if the merc is active and on a combat assignment
if ( pSoldier->bActive && pSoldier->bAssignment < ON_DUTY )
{
pProfile = &(gMercProfiles[ pSoldier->ubProfile ]);
// if we're moving, we only check vs other people in our squad
if (pSoldier->ubGroupID != 0 && PlayerIDGroupInMotion( pSoldier->ubGroupID ))
{
fSameGroupOnly = TRUE;
}
fUpdatedTimeTillNextHatedComplaint = FALSE;
bOtherID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pOtherSoldier = MercPtrs[ bOtherID ]; bOtherID <= bLastTeamID; bOtherID++, pOtherSoldier++)
{
// is this guy in the same sector and on active duty (or in the same moving group)
if (bOtherID != bMercID && pOtherSoldier->bActive && pOtherSoldier->bAssignment < ON_DUTY )
{
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;
}
}
ubOtherProfileID = pOtherSoldier->ubProfile;
for ( iLoop = 0; iLoop < 7; iLoop++ )
{
switch( iLoop )
{
case 0:
case 1:
case 2:
case 3:
case 4:
if (pProfile->bHated[iLoop] == ubOtherProfileID)
{
// arrgs, we're on assignment with the person we loathe!
if ( pProfile->bHatedCount[iLoop] > 0 )
{
pProfile->bHatedCount[iLoop]--;
if ( pProfile->bHatedCount[iLoop] == 0 && pSoldier->bInSector && gTacticalStatus.fEnemyInSector )
{
// just reduced count to 0 but we have enemy in sector...
pProfile->bHatedCount[iLoop] = 1;
}
else if (pProfile->bHatedCount[iLoop] > 0 && (pProfile->bHatedCount[iLoop] == pProfile->bHatedTime[iLoop] / 2 || ( pProfile->bHatedCount[iLoop] < pProfile->bHatedTime[iLoop] / 2 && pProfile->bHatedCount[iLoop] % TIME_BETWEEN_HATED_COMPLAINTS == 0 ) ) )
{
// complain!
if (iLoop == 0)
{
TacticalCharacterDialogue( pSoldier, QUOTE_HATED_1 );
}
else if (iLoop == 1)
{
TacticalCharacterDialogue( pSoldier, QUOTE_HATED_2 );
}
else if (iLoop == 2)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_3 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_3 );
}
else if (iLoop == 3)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_4 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_4 );
}
else if (iLoop == 4)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_5 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_5 );
}
StopTimeCompression();
}
else if ( pProfile->bHatedCount[iLoop] == 0 )
{
// zero count!
if (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC || pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC )
{
// MERC mercs leave now!
if (iLoop == 0)
{
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_HATED_1 );
}
else if (iLoop == 1)
{
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_HATED_2 );
}
else if (iLoop == 2)
{
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_HATED_3 );
}
else if (iLoop == 3)
{
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_HATED_4 );
}
else if (iLoop == 4)
{
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_HATED_5 );
}
// Leave now! ( handle equipment too )....
TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING, 0,0 );
pSoldier->ubLeaveHistoryCode = HISTORY_MERC_QUIT;
}
else
{
// complain!
if (iLoop == 0)
{
TacticalCharacterDialogue( pSoldier, QUOTE_HATED_1 );
}
else if (iLoop == 1)
{
TacticalCharacterDialogue( pSoldier, QUOTE_HATED_2 );
}
else if (iLoop == 2)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_3 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_3 );
}
else if (iLoop == 3)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_4 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_4 );
}
else if (iLoop == 4)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_5 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_5 );
}
pProfile->ubTimeTillNextHatedComplaint = TIME_BETWEEN_HATED_COMPLAINTS - 1;
}
}
}
else
{
// if we haven't updated the time till our next complaint, do so
// if it's 0, gripe.
if ( !fUpdatedTimeTillNextHatedComplaint )
{
if ( pProfile->ubTimeTillNextHatedComplaint == 0 )
{
pProfile->ubTimeTillNextHatedComplaint = TIME_BETWEEN_HATED_COMPLAINTS - 1;
}
else
{
pProfile->ubTimeTillNextHatedComplaint--;
}
fUpdatedTimeTillNextHatedComplaint = TRUE;
}
if ( pProfile->ubTimeTillNextHatedComplaint == 0 )
{
// complain!
if (iLoop == 0)
{
TacticalCharacterDialogue( pSoldier, QUOTE_HATED_1 );
}
else if (iLoop == 1)
{
TacticalCharacterDialogue( pSoldier, QUOTE_HATED_2 );
}
else if (iLoop == 2)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_3 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_3 );
}
else if (iLoop == 3)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_4 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_4 );
}
else if (iLoop == 4)
{
if( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
TacticalCharacterDialogue( pSoldier, QUOTE_AIM_HATED_5 );
else
TacticalCharacterDialogue( pSoldier, QUOTE_NON_AIM_HATED_5 );
}
}
}
}
break;
case 5:
if (pProfile->bLearnToHate == ubOtherProfileID)
{
if ( pProfile->bLearnToHateCount > 0 )
{
pProfile->bLearnToHateCount--;
if ( pProfile->bLearnToHateCount == 0 && pSoldier->bInSector && gTacticalStatus.fEnemyInSector )
{
// just reduced count to 0 but we have enemy in sector...
pProfile->bLearnToHateCount = 1;
}
else if (pProfile->bLearnToHateCount > 0 && (pProfile->bLearnToHateCount == pProfile->bLearnToHateTime / 2 || pProfile->bLearnToHateCount < pProfile->bLearnToHateTime / 2 && pProfile->bLearnToHateCount % TIME_BETWEEN_HATED_COMPLAINTS == 0 ) )
{
// complain!
TacticalCharacterDialogue( pSoldier, QUOTE_LEARNED_TO_HATE_MERC );
StopTimeCompression();
}
else if (pProfile->bLearnToHateCount == 0)
{
// set as bHated[2];
// anv: nope, we don't want to overwrite possible standard foe, instead added extra check to WhichHated(), CanMercBeHired()
if (OKToCheckOpinion(ubOtherProfileID)) {
//pProfile->bHated[2] = pProfile->bLearnToHate;
pProfile->bMercOpinion[ubOtherProfileID] = HATED_OPINION;
}
#ifdef JA2UB
if (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC || (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC && ( /* pSoldier->ubProfile == DEVIN || */ pSoldier->ubProfile == SLAY || pSoldier->ubProfile == IGGY || pSoldier->ubProfile == CONRAD ) ) )
#else
if (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC || (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC && (pSoldier->ubProfile == DEVIN || pSoldier->ubProfile == SLAY || pSoldier->ubProfile == IGGY || pSoldier->ubProfile == CONRAD ) ) )
#endif
{
// Leave now! ( handle equipment too )....
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_QUIT_LEARN_TO_HATE );
TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING, 0,0 );
pSoldier->ubLeaveHistoryCode = HISTORY_MERC_QUIT;
}
else if (pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__NPC)
{
// whine again
TacticalCharacterDialogue( pSoldier, QUOTE_LEARNED_TO_HATE_MERC );
}
}
if (pProfile->bLearnToHateCount < pProfile->bLearnToHateTime / 2)
{
// gradual opinion drop
if (OKToCheckOpinion(ubOtherProfileID)) {
pProfile->bMercOpinion[ubOtherProfileID] += (HATED_OPINION - pProfile->bMercOpinion[ubOtherProfileID]) / (pProfile->bLearnToHateCount + 1);
}
}
}
else
{
if ( !fUpdatedTimeTillNextHatedComplaint )
{
if ( pProfile->ubTimeTillNextHatedComplaint == 0 )
{
pProfile->ubTimeTillNextHatedComplaint = TIME_BETWEEN_HATED_COMPLAINTS - 1;
}
else
{
pProfile->ubTimeTillNextHatedComplaint--;
}
fUpdatedTimeTillNextHatedComplaint = TRUE;
}
if ( pProfile->ubTimeTillNextHatedComplaint == 0 )
{
// complain!
TacticalCharacterDialogue( pSoldier, QUOTE_LEARNED_TO_HATE_MERC );
}
}
}
break;
case 6:
if (pProfile->bLearnToLikeCount > 0 && pProfile->bLearnToLike == ubOtherProfileID)
{
pProfile->bLearnToLikeCount--;
if (pProfile->bLearnToLikeCount == 0)
{
// add to liked!
// anv: nope, we don't want to overwrite possible standard buddy, instead added extra check to WhichBuddy(), DoesMercHaveABuddyOnTheTeam(), CanMercBeHired()
if (OKToCheckOpinion(ubOtherProfileID)) {
//pProfile->bBuddy[2] = pProfile->bLearnToLike;
pProfile->bMercOpinion[ubOtherProfileID] = BUDDY_OPINION;
}
}
else if (pProfile->bLearnToLikeCount < pProfile->bLearnToLikeTime / 2)
{
// increase opinion of them!
if (OKToCheckOpinion(ubOtherProfileID)) {
pProfile->bMercOpinion[ubOtherProfileID] += (BUDDY_OPINION - pProfile->bMercOpinion[ubOtherProfileID]) / (pProfile->bLearnToLikeCount + 1);
}
break;
}
}
break;
}
}
}
}
}
}
}
void HourlyCamouflageUpdate( void )
{
UINT16 bMercID, bLastTeamID;
SOLDIERTYPE * pSoldier;
BOOLEAN camoWoreOff = FALSE;
bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
// loop through all mercs
for ( pSoldier = MercPtrs[ bMercID ]; bMercID <= bLastTeamID; bMercID++,pSoldier++)
{
if ( pSoldier->bActive )
{
// SANDRO - new Ranger trait reduces camo degrading, which replaces camouflage trait
// may be a little awkward solution with chances, but can work
if (gGameOptions.fNewTraitSystem)
{
if( pSoldier->bCamo > 0 )
{
// first limit camo to valid values
pSoldier->bCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->bCamo );
if ( HAS_SKILL_TRAIT( pSoldier, SURVIVAL_NT ) )
{
pSoldier->bCamo -= (Chance( __max( 0, 100 - gSkillTraitValues.ubSVCamoWornountSpeedReduction * NUM_SKILL_TRAITS( pSoldier, SURVIVAL_NT ) ) ) ? 1 : 0);
}
else
pSoldier->bCamo -= 1; // 2
if (pSoldier->bCamo <= 0)
{
pSoldier->bCamo = 0;
camoWoreOff = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_JUNGLE_WORN_OFF], pSoldier->name );
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
//legion camo, remove camo face and create face
gCamoFace[pSoldier->ubProfile].gCamoface = FALSE;
DeleteSoldierFace( pSoldier );
pSoldier->iFaceIndex = InitSoldierFace( pSoldier );
}
}
}
if( pSoldier->urbanCamo > 0 )
{
// first limit camo to valid values
pSoldier->urbanCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->urbanCamo );
if ( HAS_SKILL_TRAIT( pSoldier, SURVIVAL_NT ) )
{
pSoldier->urbanCamo -= (Chance( __max( 0, 100 - gSkillTraitValues.ubSVCamoWornountSpeedReduction * NUM_SKILL_TRAITS( pSoldier, SURVIVAL_NT ) ) ) ? 1 : 0);
}
else
pSoldier->urbanCamo -= 1; // 2
if (pSoldier->urbanCamo <= 0)
{
pSoldier->urbanCamo = 0;
camoWoreOff = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_URBAN_WORN_OFF], pSoldier->name );
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
//legion camo, remove camo face and create face
gCamoFace[pSoldier->ubProfile].gUrbanCamoface = FALSE;
DeleteSoldierFace( pSoldier );
pSoldier->iFaceIndex = InitSoldierFace( pSoldier );
}
}
}
if( pSoldier->desertCamo > 0 )
{
// first limit camo to valid values
pSoldier->desertCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->desertCamo );
if ( HAS_SKILL_TRAIT( pSoldier, SURVIVAL_NT ) )
{
pSoldier->desertCamo -= (Chance( __max( 0, 100 - gSkillTraitValues.ubSVCamoWornountSpeedReduction * NUM_SKILL_TRAITS( pSoldier, SURVIVAL_NT ) ) ) ? 1 : 0);
}
else
pSoldier->desertCamo -= 1; // 2
if (pSoldier->desertCamo <= 0)
{
pSoldier->desertCamo = 0;
camoWoreOff = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_DESERT_WORN_OFF], pSoldier->name );
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
//legion camo, remove camo face and create face
gCamoFace[pSoldier->ubProfile].gDesertCamoface = FALSE;
DeleteSoldierFace( pSoldier );
pSoldier->iFaceIndex = InitSoldierFace( pSoldier );
}
}
}
if( pSoldier->snowCamo > 0 )
{
// first limit camo to valid values
pSoldier->snowCamo = __min( gGameExternalOptions.bCamoKitArea, pSoldier->snowCamo );
if ( HAS_SKILL_TRAIT( pSoldier, SURVIVAL_NT ) )
{
pSoldier->snowCamo -= (Chance( __max( 0, 100 - gSkillTraitValues.ubSVCamoWornountSpeedReduction * NUM_SKILL_TRAITS( pSoldier, SURVIVAL_NT ) ) ) ? 1 : 0);
}
else
pSoldier->snowCamo -= 1; // 2
if (pSoldier->snowCamo <= 0)
{
pSoldier->snowCamo = 0;
camoWoreOff = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_SNOW_WORN_OFF], pSoldier->name );
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
//legion camo, remove camo face and create face
gCamoFace[pSoldier->ubProfile].gSnowCamoface = FALSE;
DeleteSoldierFace( pSoldier );
pSoldier->iFaceIndex = InitSoldierFace( pSoldier );
}
}
}
}
else
{
// if the merc has non-zero camo, degrade it by 1%
// SANDRO - different types of Camouflaged trait have been merged together
if( ( pSoldier->bCamo > 0) && ( !( HAS_SKILL_TRAIT( pSoldier, CAMOUFLAGED_OT) ) ) )
{
pSoldier->bCamo -= 1; // 2
if (pSoldier->bCamo <= 0)
{
pSoldier->bCamo = 0;
camoWoreOff = TRUE;
// ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_CAMMO_WORN_OFF], pSoldier->name );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_JUNGLE_WORN_OFF], pSoldier->name );
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
//legion camo, remove camo face and create face
gCamoFace[pSoldier->ubProfile].gCamoface = FALSE;
DeleteSoldierFace( pSoldier );
pSoldier->iFaceIndex = InitSoldierFace( pSoldier );
}
}
}
if( ( pSoldier->urbanCamo > 0) && ( !( HAS_SKILL_TRAIT( pSoldier, CAMOUFLAGED_OT) ) ) )
{
pSoldier->urbanCamo -= 1; // 2
if (pSoldier->urbanCamo <= 0)
{
pSoldier->urbanCamo = 0;
camoWoreOff = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_URBAN_WORN_OFF], pSoldier->name );
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
//legion camo, remove camo face and create face
gCamoFace[pSoldier->ubProfile].gUrbanCamoface = FALSE;
DeleteSoldierFace( pSoldier );
pSoldier->iFaceIndex = InitSoldierFace( pSoldier );
}
}
}
if( ( pSoldier->desertCamo > 0) && ( !( HAS_SKILL_TRAIT( pSoldier, CAMOUFLAGED_OT) ) ) )
{
pSoldier->desertCamo -= 1; // 2
if (pSoldier->desertCamo <= 0)
{
pSoldier->desertCamo = 0;
camoWoreOff = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_DESERT_WORN_OFF], pSoldier->name );
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
//legion camo, remove camo face and create face
gCamoFace[pSoldier->ubProfile].gDesertCamoface = FALSE;
DeleteSoldierFace( pSoldier );
pSoldier->iFaceIndex = InitSoldierFace( pSoldier );
}
}
}
if( ( pSoldier->snowCamo > 0) && ( !( HAS_SKILL_TRAIT( pSoldier, CAMOUFLAGED_OT) ) ) )
{
pSoldier->snowCamo -= 1; // 2
if (pSoldier->snowCamo <= 0)
{
pSoldier->snowCamo = 0;
camoWoreOff = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_SNOW_WORN_OFF], pSoldier->name );
if (gGameExternalOptions.fShowCamouflageFaces == TRUE )
{
//legion camo, remove camo face and create face
gCamoFace[pSoldier->ubProfile].gSnowCamoface = FALSE;
DeleteSoldierFace( pSoldier );
pSoldier->iFaceIndex = InitSoldierFace( pSoldier );
}
}
}
}
if ( camoWoreOff )
{
// Reload palettes....
if ( pSoldier->bInSector )
{
pSoldier->CreateSoldierPalettes( );
}
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
camoWoreOff = FALSE;
}
// if the merc has non-zero monster smell, degrade it by 1
if ( pSoldier->aiData.bMonsterSmell > 0 )
{
pSoldier->aiData.bMonsterSmell--;
/*
if (pSoldier->aiData.bMonsterSmell == 0)
{
// Reload palettes....
if ( pSoldier->bInSector )
{
pSoldier->CreateSoldierPalettes( );
}
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, Message[STR_CAMMO_WORN_OFF], pSoldier->name );
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
}
*/
}
}
}
}
#ifdef JA2UB
void HandleAddingAnyAimAwayEmailsWhenLaptopGoesOnline()
{
UINT32 cnt;
INT32 iOffset;
MERCPROFILESTRUCT *pProfile;
//Loop through all the profiles
for( cnt = 0; cnt < NUM_PROFILES; cnt++)
{
pProfile = &(gMercProfiles[ cnt ]);
if (pProfile->uiDayBecomesAvailable == 0)
{
//if the merc CAN become ready
if( pProfile->bMercStatus != MERC_FIRED_AS_A_POW )
{
// if the player has left a message for this merc
if ( pProfile->ubMiscFlags3 & PROFILE_MISC_FLAG3_PLAYER_LEFT_MSG_FOR_MERC_AT_AIM )
{
iOffset = AIM_REPLY_BARRY;
//remove the Flag, so if the merc goes on another assignment, the player can leave an email.
pProfile->ubMiscFlags3 &= ~PROFILE_MISC_FLAG3_PLAYER_LEFT_MSG_FOR_MERC_AT_AIM;
UINT8 pMerc = 0;
UINT8 iMerc = 0;
UINT8 oMerc = 0;
if ( ReadXMLEmail == TRUE )
{
oMerc = cnt;
iMerc = oMerc * 1;
if ( oMerc != 0 )
pMerc = oMerc + 1;
else
pMerc = 0;
if ( gMercProfiles[cnt].Type == PROFILETYPE_AIM )
AddEmailTypeXML( pMerc, iMerc, iMerc, GetWorldTotalMin(), -1 , TYPE_EMAIL_AIM_AVAILABLE);
}
else
{
// TO DO: send E-mail to player telling him the merc has returned from an assignment
AddEmail( ( UINT8 )( iOffset + ( cnt * AIM_REPLY_LENGTH_BARRY ) ), AIM_REPLY_LENGTH_BARRY, ( UINT8 )( 6 + cnt ), GetWorldTotalMin(),-1 ,-1, TYPE_EMAIL_EMAIL_EDT_NAME_MERC);
}
}
}
}
}
}
#endif