void HandleNotifyPlayerCanAffordInsurance( SOLDIERTYPE *pSoldier, UINT8 ubLength, INT32 iCost ) { CHAR16 sString[ 128 ]; CHAR16 sStringA[ 32 ]; //parse the cost swprintf( sStringA, L"%d",iCost ); // insert the commans and dollar sign InsertCommasForDollarFigure( sStringA ); InsertDollarSignInToString( sStringA ); swprintf( sString, zMarksMapScreenText[ 10 ], pSoldier->GetName(), sStringA, ubLength ); //Set the length to the global variable ( so we know how long the contract is in the callback ) gubContractLength = ubLength; gpInsuranceSoldier = pSoldier; //Remember the soldier aswell pContractReHireSoldier = pSoldier; // now pop up the message box DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_YESNO, ExtendMercInsuranceContractCallBack ); return; }
void DisplayCurrentBalanceForMapBottom( void ) { // show the current balance for the player on the map panel bottom CHAR16 sString[ 128 ]; INT16 sFontX, sFontY; // ste the font buffer SetFontDestBuffer( FRAME_BUFFER, 0, 0, 640, 480, FALSE ); // set up the font SetFont( COMPFONT ); SetFontForeground( 183 ); SetFontBackground( FONT_BLACK ); swprintf( sString, L"%d", LaptopSaveInfo.iCurrentBalance ); // insert InsertCommasForDollarFigure( sString ); InsertDollarSignInToString( sString ); // center it VarFindFontCenterCoordinates( 359, 387 + 2, 437 - 359, 10, COMPFONT, &sFontX, &sFontY, sString ); // print it mprintf( sFontX, sFontY, L"%s", sString ); return; }
void DisplayProjectedDailyMineIncome( void ) { INT32 iRate = 0; static INT32 iOldRate = -1; CHAR16 sString[ 128 ]; INT16 sFontX, sFontY; // grab the rate from the financial system iRate = GetProjectedTotalDailyIncome( ); if( iRate != iOldRate ) { iOldRate = iRate; fMapScreenBottomDirty = TRUE; // if screen was not dirtied, leave if( fMapBottomDirtied == FALSE ) { return; } } // ste the font buffer SetFontDestBuffer( FRAME_BUFFER, 0, 0, 640, 480, FALSE ); // set up the font SetFont( COMPFONT ); SetFontForeground( 183 ); SetFontBackground( FONT_BLACK ); swprintf( sString, L"%d", iRate ); // insert InsertCommasForDollarFigure( sString ); InsertDollarSignInToString( sString ); // center it VarFindFontCenterCoordinates( 359, 433 + 2, 437 - 359, 10, COMPFONT, &sFontX, &sFontY, sString ); // print it mprintf( sFontX, sFontY, L"%s", sString ); return; }
// adds text to mine info box void AddTextToMineBox( void ) { UINT8 ubMineIndex; UINT8 ubTown; UINT32 hStringHandle; CHAR16 wString[ 64 ]; ubMineIndex = GetMineIndexForSector( bCurrentTownMineSectorX, bCurrentTownMineSectorY ); // name of town followed by "mine" //swprintf( wString, L"%s %s", pTownNames[ GetTownAssociatedWithMine( ubMineIndex ) ], pwMineStrings[ 0 ] ); swprintf( wString, L"%s %s", pTownNames[ GetTownAssociatedWithMine( ubMineIndex ) ], MineralsName[gMineStatus[ubMineIndex].ubMineType].sType ); AddMonoString( &hStringHandle, wString ); // blank line AddMonoString( &hStringHandle, L"" ); // sector AddSectorToBox(); // mine status swprintf( wString, L"%s:", pwMineStrings[ 9 ]); AddMonoString( &hStringHandle, wString ); // check if mine is empty (abandoned) or running out if (gMineStatus[ ubMineIndex ].fEmpty) { // abandonded wcscpy( wString, pwMineStrings[ 5 ] ); } else if (gMineStatus[ ubMineIndex ].fShutDown) { // shut down wcscpy( wString, pwMineStrings[ 6 ] ); } else if (gMineStatus[ ubMineIndex ].fRunningOut) { // running out wcscpy( wString, pwMineStrings[ 7 ] ); } else { // producing wcscpy( wString, pwMineStrings[ 8 ] ); } AddSecondColumnMonoString( &hStringHandle, wString ); // if still producing if (!gMineStatus[ ubMineIndex ].fEmpty) { // current production swprintf( wString, L"%s:", pwMineStrings[ 3 ]); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d", PredictDailyIncomeFromAMine( ubMineIndex, TRUE ) ); InsertCommasForDollarFigure( wString ); InsertDollarSignInToString( wString ); AddSecondColumnMonoString( &hStringHandle, wString ); // potential production swprintf( wString, L"%s:", pwMineStrings[ 4 ]); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d", GetMaxDailyRemovalFromMine( ubMineIndex ) ); InsertCommasForDollarFigure( wString ); InsertDollarSignInToString( wString ); AddSecondColumnMonoString( &hStringHandle, wString ); // if potential is not nil if (GetMaxPeriodicRemovalFromMine(ubMineIndex) > 0) { // production rate (current production as a percentage of potential production) swprintf( wString, L"%s:", pwMineStrings[ 10 ]); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d%%%%", (PredictDailyIncomeFromAMine(ubMineIndex, TRUE) * 100 ) / GetMaxDailyRemovalFromMine(ubMineIndex) ); AddSecondColumnMonoString( &hStringHandle, wString ); } // town control percentage swprintf( wString, L"%s:", pwMineStrings[ 12 ]); AddMonoString( &hStringHandle, wString ); //swprintf( wString, L"%d%%%%", (GetTownSectorsUnderControl( gMineLocation[ ubMineIndex ].bAssociatedTown ) * 100) / GetTownSectorSize( gMineLocation[ ubMineIndex ].bAssociatedTown )); swprintf( wString, L"%d%%%%", (GetTownSectorsUnderControl( gMineStatus[ ubMineIndex ].bAssociatedTown ) * 100) / GetTownSectorSize( gMineStatus[ ubMineIndex ].bAssociatedTown )); AddSecondColumnMonoString( &hStringHandle, wString ); //ubTown = gMineLocation[ ubMineIndex ].bAssociatedTown; ubTown = gMineStatus[ ubMineIndex ].bAssociatedTown; if( gTownLoyalty[ ubTown ].fStarted && gfTownUsesLoyalty[ ubTown ]) { // town loyalty percentage swprintf( wString, L"%s:", pwMineStrings[ 13 ]); AddMonoString( &hStringHandle, wString ); //swprintf( wString, L"%d%%%%", gTownLoyalty[ gMineLocation[ ubMineIndex ].bAssociatedTown ].ubRating); swprintf( wString, L"%d%%%%", gTownLoyalty[ gMineStatus[ ubMineIndex ].bAssociatedTown ].ubRating); AddSecondColumnMonoString( &hStringHandle, wString ); } /* gradual monster infestation concept was ditched, now simply IN PRODUCTION or SHUT DOWN // percentage of miners working swprintf( wString, L"%s:", pwMineStrings[ 14 ]); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d%%%%", gubMonsterMineInfestation[ gMineStatus[ ubMineIndex ].bMonsters ]); AddSecondColumnMonoString( &hStringHandle, wString ); */ // ore type (silver/gold swprintf( wString, L"%s:", pwMineStrings[ 11 ]); AddMonoString( &hStringHandle, wString ); AddSecondColumnMonoString( &hStringHandle, MineralsName[gMineStatus[ubMineIndex].ubMineType].sMinerals ); //AddSecondColumnMonoString( &hStringHandle, (gMineStatus[ubMineIndex].ubMineType == SILVER_MINE) ? pwMineStrings[ 1 ] : pwMineStrings[ 2 ] ); } #ifdef _DEBUG // dollar amount remaining in mine wcscpy( wString, L"Remaining (DEBUG):"); AddMonoString( &hStringHandle, wString ); swprintf( wString, L"%d", GetTotalLeftInMine( ubMineIndex ) ); InsertCommasForDollarFigure( wString ); InsertDollarSignInToString( wString ); AddSecondColumnMonoString( &hStringHandle, wString ); #endif }
// 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; INT8 bLastTeamID; SOLDIERTYPE *pSoldier; //SOLDIERTYPE *pQuitList[ 21 ]; MERCPROFILESTRUCT *pProfile; UINT32 uiChance; INT32 iOffset = 0; BOOLEAN fFoundSomeOneForMenuShowing = FALSE; //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 ].bPersonalityTrait ) { case HEAT_INTOLERANT: case CLAUSTROPHOBIC: case NONSWIMMER: case FEAR_OF_INSECTS: // 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; //if the character is an RPC if( pSoldier->ubProfile >= FIRST_RPC && pSoldier->ubProfile < FIRST_NPC ) { 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 ); } } } } 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 ); } } } } } //Loop through all the profiles for( cnt = 0; cnt < NUM_PROFILES; 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 )) { continue; } // if he's an AIM/M.E.R.C. merc if ( cnt < AIM_AND_MERC_MERCS ) { // 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 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; // 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() ); } } } } else // was already available today { // if it's an AIM or M.E.R.C. merc if (cnt < AIM_AND_MERC_MERCS) { // check to see if he goes on another assignment if (cnt < MAX_NUMBER_MERCS) { // 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 { // 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; } } if (Random(100) < uiChance) { 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 ); HandleSlayDailyEvent( ); // rebuild list for mapscreen ReBuildCharactersList( ); }