#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 "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 "email.h" #include "Map Screen Interface.h" #include "Campaign.h" #include "Soldier Add.h" #include "screenids.h" #include "jascreens.h" #include "Soldier macros.h" #include "finances.h" #include "GameSettings.h" #include "Quests.h" #include "Facilities.h" #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() { SoldierID id; SoldierID lastid; 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 ); id = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; lastid = gTacticalStatus.Team[ gbPlayerNum ].bLastID; //loop though all the mercs for ( ; id <= lastid; ++id) { pSoldier = id; //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 { //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, FormatMoney(sSalary).data() ); //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++; } } //reset the counter for ( id = 0; id <= lastid; ++id ) { pSoldier = id; //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( UINT16 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 ) { SoldierID 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 ( ; bMercID <= bLastTeamID; ++bMercID ) { pSoldier = bMercID; 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 ( ; bOtherID <= bLastTeamID; ++bOtherID ) { pOtherSoldier = bOtherID; // 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 ) { SoldierID bMercID, bLastTeamID; SOLDIERTYPE * pSoldier; BOOLEAN camoWoreOff = FALSE; bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID; // loop through all mercs for ( ; bMercID <= bLastTeamID; ++bMercID ) { pSoldier = bMercID; 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