#include "laptop.h" #include "mercs.h" #include "Utilities.h" #include "WCheck.h" #include "WordWrap.h" #include "Cursors.h" #include "Overhead.h" #include "Soldier Add.h" #include "email.h" #include "Game Clock.h" #include "faces.h" #include "Dialogue Control.h" #include "MercTextBox.h" #include "Merc Hiring.h" #include "random.h" #include "LaptopSave.h" #include "GameSettings.h" #include "Text.h" #include "Speck Quotes.h" #include "mercs Account.h" #include "Soldier Profile.h" #include "Game Event Hook.h" #include "Quests.h" #include "AimMembers.h" #ifdef JA2UB #include "Ja25_Tactical.h" #include "Ja25 Strategic Ai.h" #include "Speck Quotes.h" #endif #include "connect.h" UINT8 NUMBER_OF_MERCS = 0; UINT8 LAST_MERC_ID = -1; UINT8 NUMBER_OF_BAD_MERCS = -1; #define MERC_TEXT_FONT FONT12ARIAL #define MERC_TEXT_COLOR FONT_MCOLOR_WHITE #define MERC_VIDEO_TITLE_FONT FONT10ARIAL #define MERC_VIDEO_TITLE_COLOR FONT_MCOLOR_LTYELLOW #define MERC_BACKGROUND_WIDTH 125 #define MERC_BACKGROUND_HEIGHT 100 #define MERC_TITLE_X LAPTOP_SCREEN_UL_X + 135 #define MERC_TITLE_Y LAPTOP_SCREEN_WEB_UL_Y + 20 #define MERC_PORTRAIT_X LAPTOP_SCREEN_UL_X + 198 #define MERC_PORTRAIT_Y LAPTOP_SCREEN_WEB_UL_Y + 96 #define MERC_PORTRAIT_TEXT_X MERC_PORTRAIT_X #define MERC_PORTRAIT_TEXT_Y MERC_PORTRAIT_Y + 109 #define MERC_PORTRAIT_TEXT_WIDTH 115 #define MERC_ACCOUNT_BOX_X LAPTOP_SCREEN_UL_X + 138 #define MERC_ACCOUNT_BOX_Y LAPTOP_SCREEN_WEB_UL_Y + 251 #define MERC_ACCOUNT_BOX_TEXT_X MERC_ACCOUNT_BOX_X #define MERC_ACCOUNT_BOX_TEXT_Y MERC_ACCOUNT_BOX_Y + 20 #define MERC_ACCOUNT_BOX_TEXT_WIDTH 110 #define MERC_ACCOUNT_ARROW_X MERC_ACCOUNT_BOX_X + 125 #define MERC_ACCOUNT_ARROW_Y MERC_ACCOUNT_BOX_Y + 18 #define MERC_ACCOUNT_BUTTON_X MERC_ACCOUNT_BOX_X + 133 #define MERC_ACCOUNT_BUTTON_Y MERC_ACCOUNT_BOX_Y + 8 #define MERC_FILE_BOX_X MERC_ACCOUNT_BOX_X #define MERC_FILE_BOX_Y LAPTOP_SCREEN_WEB_UL_Y + 321 #define MERC_FILE_BOX_TEXT_X MERC_FILE_BOX_X #define MERC_FILE_BOX_TEXT_Y MERC_FILE_BOX_Y + 20 #define MERC_FILE_BOX_TEXT_WIDTH MERC_ACCOUNT_BOX_TEXT_WIDTH #define MERC_FILE_ARROW_X MERC_FILE_BOX_X + 125 #define MERC_FILE_ARROW_Y MERC_FILE_BOX_Y + 18 #define MERC_FILE_BUTTON_X MERC_ACCOUNT_BUTTON_X #define MERC_FILE_BUTTON_Y MERC_FILE_BOX_Y + 8 // Video Conference Defines #define MERC_VIDEO_BACKGROUND_X MERC_PORTRAIT_X #define MERC_VIDEO_BACKGROUND_Y MERC_PORTRAIT_Y #define MERC_VIDEO_BACKGROUND_WIDTH 116 #define MERC_VIDEO_BACKGROUND_HEIGHT 108 #define MERC_VIDEO_FACE_X MERC_VIDEO_BACKGROUND_X + 10 #define MERC_VIDEO_FACE_Y MERC_VIDEO_BACKGROUND_Y + 17 #define MERC_VIDEO_FACE_WIDTH 96 #define MERC_VIDEO_FACE_HEIGHT 86 #define MERC_X_TO_CLOSE_VIDEO_X MERC_VIDEO_BACKGROUND_X + 104 #define MERC_X_TO_CLOSE_VIDEO_Y MERC_VIDEO_BACKGROUND_Y + 3 #define MERC_X_VIDEO_TITLE_X MERC_VIDEO_BACKGROUND_X + 5 #define MERC_X_VIDEO_TITLE_Y MERC_VIDEO_BACKGROUND_Y + 3 #define MERC_INTRO_TIME 1000 #define MERC_EXIT_TIME 500 #define MERC_VIDEO_MERC_ID_FOR_SPECKS 159//255 #define MERC_TEXT_BOX_POS_Y iScreenHeightOffset + 255 #define SPECK_IDLE_CHAT_DELAY 10000 #ifdef JA2UB #define MERC_NUMBER_OF_RANDOM_QUOTES 20//19//14 #else #define MERC_NUMBER_OF_RANDOM_QUOTES 19//14 #endif #define MERC_FIRST_MERC BIFF #define MERC_LAST_MERC BUBBA //number of payment days ( # of merc days paid ) to get next set of mercs #define MERC_NUM_DAYS_TILL_FIRST_MERC_AVAILABLE 10 #define MERC_NUM_DAYS_TILL_SECOND_MERC_AVAILABLE 16 #define MERC_NUM_DAYS_TILL_THIRD_MERC_AVAILABLE 24 #define MERC_NUM_DAYS_TILL_FOURTH_MERC_AVAILABLE 30 #define MERC__AMOUNT_OF_MONEY_FOR_BUBBA 6000 #define MERC__DAY_WHEN_BUBBA_CAN_BECOME_AVAILABLE 10 CONTITION_FOR_MERC_AVAILABLE_TEMP gConditionsForMercAvailabilityTemp[ NUM_PROFILES ]; CONTITION_FOR_MERC_AVAILABLE gConditionsForMercAvailability[ NUM_PROFILES ]; //NUM_MERC_ARRIVALS ]; //= /* { 5000, 8, 6, //BUBBA 10000, 15, 7, //Larry 15000, 20, 9, //Numb 16000, 21, 10, //Tex 18000, 23, 11, //Biggens 20000, 25, 12, //Cougar 25000, 30, 13, //Gaston 26000, 31, 14, //Stogie }; */ enum { MERC_DISTORTION_NO_DISTORTION, MERC_DISTORTION_PIXELATE_UP, MERC_DISTORTION_PIXELATE_DOWN, MERC_DISRTORTION_DISTORT_IMAGE, }; enum { MERC_SITE_NEVER_VISITED, MERC_SITE_FIRST_VISIT, MERC_SITE_SECOND_VISIT, MERC_SITE_THIRD_OR_MORE_VISITS, }; // Image Indetifiers UINT32 guiAccountBox; UINT32 guiArrow; UINT32 guiFilesBox; UINT32 guiMercSymbol; UINT32 guiSpecPortrait; UINT32 guiMercBackGround; UINT32 guiMercVideoFaceBackground; UINT32 guiMercVideoPopupBackground; UINT8 gubMercArray[ NUM_PROFILES ]; //MAX_NUMBER_OF_MERCS UINT8 gubCurMercIndex; INT32 iMercPopUpBox = -1; UINT16 gusPositionOfSpecksDialogBox_X; CHAR16 gsSpeckDialogueTextPopUp[ 900 ]; UINT16 gusSpeckDialogueX; UINT16 gusSpeckDialogueActualWidth; BOOLEAN gfInMercSite=FALSE; //this flag is set when inide of the merc site //Merc Video Conferencing Mode enum { MERC_VIDEO_NO_VIDEO_MODE, MERC_VIDEO_INIT_VIDEO_MODE, MERC_VIDEO_VIDEO_MODE, MERC_VIDEO_EXIT_VIDEO_MODE, }; UINT8 gubCurrentMercVideoMode; BOOLEAN gfMercVideoIsBeingDisplayed; INT32 giVideoSpeckFaceIndex; UINT16 gusMercVideoSpeckSpeech; BOOLEAN gfDisplaySpeckTextBox=FALSE; BOOLEAN gfJustEnteredMercSite=FALSE; UINT8 gubArrivedFromMercSubSite=MERC_CAME_FROM_OTHER_PAGE; //the merc is arriving from one of the merc sub pages BOOLEAN gfDoneIntroSpeech=TRUE; BOOLEAN gfMercSiteScreenIsReDrawn=FALSE; BOOLEAN gfJustHiredAMercMerc=FALSE; BOOLEAN fMercHireOverPlayerLimitMerc=FALSE; BOOLEAN gfRedrawMercSite=FALSE; BOOLEAN gfFirstTimeIntoMERCSiteSinceEnteringLaptop=FALSE; //used for the random quotes to try to balance the ones that are said typedef struct { UINT8 ubQuoteID; UINT32 uiNumberOfTimesQuoteSaid; } NUMBER_TIMES_QUOTE_SAID; NUMBER_TIMES_QUOTE_SAID gNumberOfTimesQuoteSaid[ MERC_NUMBER_OF_RANDOM_QUOTES ] = { #ifdef JA2UB { SPECK_QUOTE_BIFF_DEAD_WHEN_IMPORTING, 0 }, #endif { SPECK_QUOTE_RANDOM_CHIT_CHAT_1, 0 }, { SPECK_QUOTE_RANDOM_CHIT_CHAT_2, 0 }, #ifdef JA2UB { SPECK_QUOTE_RANDOM_CHIT_CHAT_3, 0 }, #endif { SPECK_QUOTE_ADVERTISE_GASTON, 0 }, { SPECK_QUOTE_ADVERTISE_STOGIE, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_BIFF, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_HAYWIRE, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_GASKET, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_RAZOR, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_FLO, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_GUMPY, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_LARRY, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_COUGER, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_NUMB, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_BUBBA, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_AIM_SLANDER_1, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_AIM_SLANDER_2, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_AIM_SLANDER_3, 0 }, { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_AIM_SLANDER_4, 0 }, #ifdef JA2UB #else { SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_HIMSELF, 0 }, #endif }; // // Buttons // // The Account Box button void BtnAccountBoxButtonCallback(GUI_BUTTON *btn,INT32 reason); UINT32 guiAccountBoxButton; INT32 guiAccountBoxButtonImage; //File Box UINT32 guiFileBoxButton; void BtnFileBoxButtonCallback(GUI_BUTTON *btn,INT32 reason); // The 'X' to close the video conf window button void BtnXToCloseMercVideoButtonCallback(GUI_BUTTON *btn,INT32 reason); UINT32 guiXToCloseMercVideoButton; INT32 guiXToCloseMercVideoButtonImage; //Mouse region for the subtitles region when the merc is talking MOUSE_REGION gMercSiteSubTitleMouseRegion; void MercSiteSubTitleRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason ); BOOLEAN LoadNewMercsFromLoadGameFile( HWFILE hFile ); BOOLEAN SaveNewMercsToSaveGameFile( HWFILE hFile ); //******************************* // // Function Prototypes // //******************************* BOOLEAN StartSpeckTalking(UINT16 usQuoteNum); void InitMercVideoFace(); BOOLEAN HandleSpeckTalking( BOOLEAN fReset ); //BOOLEAN PixelateVideoMercImage(); BOOLEAN PixelateVideoMercImage( BOOLEAN fUp, UINT16 usPosX, UINT16 usPosY, UINT16 usWidth, UINT16 usHeight); BOOLEAN InitDestroyXToCloseVideoWindow( BOOLEAN fCreate ); BOOLEAN DisplayMercVideoIntro( UINT16 usTimeTillFinish ); void HandleCurrentMercDistortion(); void HandleTalkingSpeck(); //BOOLEAN DistortVideoMercImage(); BOOLEAN DistortVideoMercImage( UINT16 usPosX, UINT16 usPosY, UINT16 usWidth, UINT16 usHeight ); BOOLEAN IsAnyMercMercsHired( ); BOOLEAN IsAnyMercMercsDead(); UINT8 CountNumberOfMercMercsHired(); UINT8 CountNumberOfMercMercsWhoAreDead(); BOOLEAN GetSpeckConditionalOpening( BOOLEAN fJustEnteredScreen ); void RemoveSpeckPopupTextBox(); BOOLEAN ShouldSpeckStartTalkingDueToActionOnSubPage(); BOOLEAN ShouldSpeckSayAQuote(); void HandleSpeckIdleConversation( BOOLEAN fReset ); INT16 GetRandomQuoteThatHasBeenSaidTheLeast( ); void StopSpeckFromTalking( ); BOOLEAN HasLarryRelapsed(); void IncreaseMercRandomQuoteValue( UINT8 ubQuoteID, UINT8 ubValue ); BOOLEAN ShouldTheMercSiteServerGoDown(); void DrawMercVideoBackGround(); BOOLEAN CanMercQuoteBeSaid( UINT32 uiQuoteID ); UINT8 NumberOfMercMercsDead(); //void MakeBiffAwayForCoupleOfDays(); // anv: moved to mercs.h BOOLEAN AreAnyOfTheNewMercsAvailable(); void ShouldAnyNewMercMercBecomeAvailable(); BOOLEAN CanMercBeAvailableYet( UINT8 ubMercToCheck ); UINT32 CalcMercDaysServed(); void RevaluateMercArray(); // silversurfer: for better savegame compatibility #ifdef JA2UB void MarkSpeckImportantQuoteUsed( UINT32 uiQuoteNum ); BOOLEAN HasImportantSpeckQuoteBeingSaid( UINT32 uiQuoteNum ); INT8 IsSpeckQuoteImportantQuote( UINT32 uiQuoteNum ); #endif //ppp BOOLEAN SaveNewMercsToSaveGameFile( HWFILE hFile ) { UINT32 uiNumBytesWritten; FileWrite( hFile, &gConditionsForMercAvailability, sizeof( gConditionsForMercAvailability), &uiNumBytesWritten ); if( uiNumBytesWritten != sizeof( gConditionsForMercAvailability ) ) { return( FALSE ); } return( TRUE ); } BOOLEAN LoadNewMercsFromLoadGameFile( HWFILE hFile ) { UINT32 uiNumBytesRead; CONTITION_FOR_MERC_AVAILABLE ConditionsForMercAvailabilityLoad[ NUM_PROFILES ]; FileRead( hFile, &ConditionsForMercAvailabilityLoad, sizeof( ConditionsForMercAvailabilityLoad ), &uiNumBytesRead ); if( uiNumBytesRead != sizeof( ConditionsForMercAvailabilityLoad ) ) { return( FALSE ); } // silversurfer: Now update the true gConditionsForMercAvailability array with the data from the savegame. // Take every index of gConditionsForMercAvailability array that we initialized in GameInitMercs() and see // if we can find a matching profile ID in ConditionsForMercAvailabilityLoad array that we loaded from the savegame. // This prevents some issues when old savegames are loaded with updated MercAvailability.xml. for ( UINT8 i=0; iuiFlags |= BUTTON_FORCE_UNDIRTY; #else DrawButton( guiAccountBoxButton ); ButtonList[ guiAccountBoxButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY; #endif RenderMercPopUpBoxFromIndex( iMercPopUpBox, gusSpeckDialogueX, MERC_TEXT_BOX_POS_Y, FRAME_BUFFER); } MarkButtonsDirty( ); RenderWWWProgramTitleBar( ); //if the page is redrawn, and we are in video conferencing, redraw the VC backgrund graphic gfMercSiteScreenIsReDrawn = TRUE; #ifdef JA2UB //JA25: removed ButtonList[ guiAccountBoxButton ]->uiFlags &= ~BUTTON_FORCE_UNDIRTY; #else ButtonList[ guiAccountBoxButton ]->uiFlags &= ~BUTTON_FORCE_UNDIRTY; #endif InvalidateRegion(LAPTOP_SCREEN_UL_X,LAPTOP_SCREEN_WEB_UL_Y,LAPTOP_SCREEN_LR_X,LAPTOP_SCREEN_WEB_LR_Y); } BOOLEAN InitMercBackGround() { VOBJECT_DESC VObjectDesc; // load the Merc background graphic and add it VObjectDesc.fCreateFlags=VOBJECT_CREATE_FROMFILE; FilenameForBPP("LAPTOP\\MERCBackGround.sti", VObjectDesc.ImageFile); CHECKF(AddVideoObject(&VObjectDesc, &guiMercBackGround)); return(TRUE); } BOOLEAN DrawMecBackGround() { WebPageTileBackground(4, 4, MERC_BACKGROUND_WIDTH, MERC_BACKGROUND_HEIGHT, guiMercBackGround); return(TRUE); } BOOLEAN RemoveMercBackGround() { DeleteVideoObjectFromIndex(guiMercBackGround); return(TRUE); } #ifdef JA2UB //no UB #else void BtnAccountBoxButtonCallback(GUI_BUTTON *btn,INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags |= BUTTON_CLICKED_ON; InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) { if (btn->uiFlags & BUTTON_CLICKED_ON) { btn->uiFlags &= (~BUTTON_CLICKED_ON ); if( LaptopSaveInfo.gubPlayersMercAccountStatus == MERC_NO_ACCOUNT ) guiCurrentLaptopMode = LAPTOP_MODE_MERC_NO_ACCOUNT; else guiCurrentLaptopMode = LAPTOP_MODE_MERC_ACCOUNT; if( iMercPopUpBox != -1 ) { ButtonList[ guiAccountBoxButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY; RenderMercPopUpBoxFromIndex( iMercPopUpBox, gusSpeckDialogueX, MERC_TEXT_BOX_POS_Y, FRAME_BUFFER); } InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } } if(reason & MSYS_CALLBACK_REASON_LOST_MOUSE) { btn->uiFlags &= (~BUTTON_CLICKED_ON ); InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } } #endif void BtnFileBoxButtonCallback(GUI_BUTTON *btn,INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags |= BUTTON_CLICKED_ON; InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) { if (btn->uiFlags & BUTTON_CLICKED_ON) { btn->uiFlags &= (~BUTTON_CLICKED_ON ); guiCurrentLaptopMode = LAPTOP_MODE_MERC_FILES; InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } } if(reason & MSYS_CALLBACK_REASON_LOST_MOUSE) { btn->uiFlags &= (~BUTTON_CLICKED_ON ); InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } } void DailyUpdateOfMercSite( UINT16 usDate) { SOLDIERTYPE *pSoldier; SoldierID sSoldierID; INT16 i; UINT8 ubMercID; INT32 iNumDays; //if its the first day, leave if( usDate == 1 ) return; iNumDays = 0; //loop through all of the hired mercs from M.E.R.C. for(i=0; iubProfile ) ) { gMercProfiles[ pSoldier->ubProfile ].iMercMercContractLength += 1; // pSoldier->iTotalContractLength++; } #ifdef JA2UB //JA25: MERC does a 1 time fee, no longer pay as you go #else //Get the longest time if( gMercProfiles[ pSoldier->ubProfile ].iMercMercContractLength > iNumDays ) iNumDays = gMercProfiles[ pSoldier->ubProfile ].iMercMercContractLength; #endif } } #ifdef JA2UB //JA25: No longer pay as you go, now pay up front #else //if the players hasnt paid for a while, get email him to tell him to pay //iTotalContractLength if( iNumDays > MERC_NUM_DAYS_TILL_ACCOUNT_INVALID ) { if( LaptopSaveInfo.gubPlayersMercAccountStatus != MERC_ACCOUNT_INVALID ) { LaptopSaveInfo.gubPlayersMercAccountStatus = MERC_ACCOUNT_INVALID; if( IsSpeckComAvailable() ) { AddEmail(MERC_INVALID, MERC_INVALID_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin(), -1, -1, TYPE_EMAIL_EMAIL_EDT, XML_SPECK_NOTICE); } else { // anv: Have speck complain personally TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ) , SPECK_PLAYABLE_QUOTE_PLAYER_OWES_SPECK_ACCOUNT_SUSPENDED ); } } } else if( iNumDays > MERC_NUM_DAYS_TILL_ACCOUNT_SUSPENDED ) { if( LaptopSaveInfo.gubPlayersMercAccountStatus != MERC_ACCOUNT_SUSPENDED ) { LaptopSaveInfo.gubPlayersMercAccountStatus = MERC_ACCOUNT_SUSPENDED; if( IsSpeckComAvailable() ) { AddEmail(MERC_WARNING, MERC_WARNING_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin(), -1, -1, TYPE_EMAIL_EMAIL_EDT, XML_SPECK_DELINQUENT); // Have speck complain next time player come to site LaptopSaveInfo.uiSpeckQuoteFlags |= SPECK_QUOTE__SENT_EMAIL_ABOUT_LACK_OF_PAYMENT; } else { // anv: Have speck complain personally TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ) , SPECK_PLAYABLE_QUOTE_PLAYER_OWES_SPECK_ALMOST_BANKRUPT_2); } } } else if( iNumDays > MERC_NUM_DAYS_TILL_FIRST_WARNING) { if( LaptopSaveInfo.gubPlayersMercAccountStatus != MERC_ACCOUNT_VALID_FIRST_WARNING ) { LaptopSaveInfo.gubPlayersMercAccountStatus = MERC_ACCOUNT_VALID_FIRST_WARNING; if( IsSpeckComAvailable() ) { AddEmail(MERC_FIRST_WARNING, MERC_FIRST_WARNING_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin(), -1, -1, TYPE_EMAIL_EMAIL_EDT, XML_SPECK_PLEASEPAY); // Have speck complain next time player come to site LaptopSaveInfo.uiSpeckQuoteFlags |= SPECK_QUOTE__SENT_EMAIL_ABOUT_LACK_OF_PAYMENT; } else { // anv: Have speck complain personally TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ) , SPECK_PLAYABLE_QUOTE_PLAYER_OWES_SPECK_ALMOST_BANKRUPT_1 ); } } } #endif //Check and act if any new Merc Mercs should become available ShouldAnyNewMercMercBecomeAvailable(); /* //If we should advacne the number of days that the good mercs arrive // if( LaptopSaveInfo.guiNumberOfMercPaymentsInDays > 4 ) { UINT8 ubNumDays; // ubNumDays = (UINT8) LaptopSaveInfo.guiNumberOfMercPaymentsInDays / 4; ubNumDays = (UINT8) LaptopSaveInfo.guiNumberOfMercPaymentsInDays; // LaptopSaveInfo.guiNumberOfMercPaymentsInDays = LaptopSaveInfo.guiNumberOfMercPaymentsInDays % 4; LaptopSaveInfo.guiNumberOfMercPaymentsInDays = 0; //for the first merc //if the merc is not already here if( LaptopSaveInfo.gbNumDaysTillFirstMercArrives != -1 ) { //We advance the day the merc arrives on if( LaptopSaveInfo.gbNumDaysTillFirstMercArrives > ubNumDays ) { LaptopSaveInfo.gbNumDaysTillFirstMercArrives -= ubNumDays; } else { //its time to add the new mercs LaptopSaveInfo.gubLastMercIndex = NUMBER_MERCS_AFTER_FIRST_MERC_ARRIVES; //Set the fact that there are new mercs available LaptopSaveInfo.fNewMercsAvailableAtMercSite = TRUE; //if we havent already sent an email this turn if( !fAlreadySentEmailToPlayerThisTurn ) { AddEmail( NEW_MERCS_AT_MERC, NEW_MERCS_AT_MERC_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin(), TYPE_EMAIL_EMAIL_EDT); fAlreadySentEmailToPlayerThisTurn = TRUE; } LaptopSaveInfo.gbNumDaysTillFirstMercArrives = -1; } } //for the Second merc //if the merc is not already here if( LaptopSaveInfo.gbNumDaysTillSecondMercArrives != -1 ) { //We advance the day the merc arrives on if( LaptopSaveInfo.gbNumDaysTillSecondMercArrives > ubNumDays ) { LaptopSaveInfo.gbNumDaysTillSecondMercArrives -= ubNumDays; } else { //its time to add the new mercs LaptopSaveInfo.gubLastMercIndex = NUMBER_MERCS_AFTER_SECOND_MERC_ARRIVES; //Set the fact that there are new mercs available LaptopSaveInfo.fNewMercsAvailableAtMercSite = TRUE; //if we havent already sent an email this turn if( !fAlreadySentEmailToPlayerThisTurn ) { AddEmail( NEW_MERCS_AT_MERC, NEW_MERCS_AT_MERC_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin()); fAlreadySentEmailToPlayerThisTurn = TRUE; } LaptopSaveInfo.gbNumDaysTillSecondMercArrives = -1; } } //for the Third merc //if the merc is not already here if( LaptopSaveInfo.gbNumDaysTillThirdMercArrives != -1 ) { //We advance the day the merc arrives on if( LaptopSaveInfo.gbNumDaysTillThirdMercArrives > ubNumDays ) { LaptopSaveInfo.gbNumDaysTillThirdMercArrives -= ubNumDays; } else { //its time to add the new mercs LaptopSaveInfo.gubLastMercIndex = NUMBER_MERCS_AFTER_THIRD_MERC_ARRIVES; //Set the fact that there are new mercs available LaptopSaveInfo.fNewMercsAvailableAtMercSite = TRUE; //if we havent already sent an email this turn if( !fAlreadySentEmailToPlayerThisTurn ) { AddEmail( NEW_MERCS_AT_MERC, NEW_MERCS_AT_MERC_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin()); fAlreadySentEmailToPlayerThisTurn = TRUE; } LaptopSaveInfo.gbNumDaysTillThirdMercArrives = -1; } } //for the Fourth merc //if the merc is not already here if( LaptopSaveInfo.gbNumDaysTillFourthMercArrives != -1 ) { //We advance the day the merc arrives on if( LaptopSaveInfo.gbNumDaysTillFourthMercArrives > ubNumDays ) { LaptopSaveInfo.gbNumDaysTillFourthMercArrives -= ubNumDays; } else { //its time to add the new mercs LaptopSaveInfo.gubLastMercIndex = NUMBER_MERCS_AFTER_FOURTH_MERC_ARRIVES; //Set the fact that there are new mercs available LaptopSaveInfo.fNewMercsAvailableAtMercSite = TRUE; //if we havent already sent an email this turn if( !fAlreadySentEmailToPlayerThisTurn ) { AddEmail( NEW_MERCS_AT_MERC, NEW_MERCS_AT_MERC_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin()); fAlreadySentEmailToPlayerThisTurn = TRUE; } LaptopSaveInfo.gbNumDaysTillFourthMercArrives = -1; } } } */ // If the merc site has never gone down, the number of MERC payment days is above 'X', // and the players account status is ok ( cant have the merc site going down when the player owes him money, player may lose account that way ) #ifdef JA2UB // no UB #else if( ShouldTheMercSiteServerGoDown() ) { UINT32 uiTimeInMinutes=0; //Set the fact the site has gone down LaptopSaveInfo.fMercSiteHasGoneDownYet = TRUE; //No lnger removing the bookmark, leave it up, and the user will go to the broken link page //Remove the book mark // RemoveBookMark( MERC_BOOKMARK ); //Get the site up the next day at 6:00 pm uiTimeInMinutes = GetMidnightOfFutureDayInMinutes( 1 ) + 18 * 60; //Add an event that will get the site back up and running AddStrategicEvent( EVENT_MERC_SITE_BACK_ONLINE, uiTimeInMinutes, 0 ); } #endif } // anv: Gets the actually available merc. For use in displaying unlocked mercs on MERC website. UINT8 GetAvailableMercIndex(UINT8 gubCurMercIndex) { UINT8 returnID = 0; if( gubCurMercIndex <= NUM_PROFILES ) { UINT8 availableID = 0; UINT8 ID = 0; //go through mercs, but only consider those unlocked while( availableID < gubCurMercIndex ) { ID++; if( gConditionsForMercAvailability[ ID ].StartMercsAvailable == TRUE ) availableID++; } returnID = ID; } // Is this a drunken merc (e.g Larry) and has an additional drunken profile if( gConditionsForMercAvailability[ returnID ].Drunk == TRUE && gConditionsForMercAvailability[ returnID ].uiAlternateIndex != 255) { if ( HasLarryRelapsed() ) { // Drunken Larry if (gConditionsForMercAvailability[ returnID ].uiIndex <= NUM_PROFILES) { returnID = gConditionsForMercAvailability[ returnID ].uiIndex; } else { Assert(0); return( TRUE ); } } else { // Normal Larry (Normal Profile is one returnID = gConditionsForMercAvailability[ returnID ].uiAlternateIndex; } } return returnID; } UINT8 GetAvailableMercIDFromMERCArray(UINT8 ubMercID) { return gubMercArray[GetAvailableMercIndex(ubMercID)]; } //Gets the actual merc id from the array UINT8 GetMercIDFromMERCArray(UINT8 ubMercID) { // Is this a drunken merc (e.g Larry) and has an additional drunken profile if( gConditionsForMercAvailability[ ubMercID ].Drunk == TRUE && gConditionsForMercAvailability[ ubMercID ].uiAlternateIndex != 255) { if ( HasLarryRelapsed() ) { // Drunken Larry if (gConditionsForMercAvailability[ ubMercID ].uiIndex <= NUM_PROFILES) { return( gubMercArray[ gConditionsForMercAvailability[ ubMercID ].uiIndex ] ); } else { Assert(0); return( TRUE ); } } else { // Normal Larry (Normal Profile is one return( gubMercArray[ gConditionsForMercAvailability[ ubMercID ].uiAlternateIndex ] ); } } // Merc is not drunken else if( ubMercID <= NUM_PROFILES ) { return( gubMercArray[ ubMercID ] ); } //else its an error else { Assert(0); return( TRUE ); } } /* BOOLEAN InitDeleteMercVideoConferenceMode() { static BOOLEAN fVideoConfModeCreated = FALSE; if( !fVideoConfModeCreated && gubCurrentMercVideoMode == MERC_VIDEO_INIT_VIDEO_MODE ) { // InitMercVideoFace(); } if( fVideoConfModeCreated && gubCurrentMercVideoMode == MERC_VIDEO_EXIT_VIDEO_MODE ) { //If merc is talking, stop him from talking ShutupaYoFace( giVideoSpeckFaceIndex ); //Delete the face DeleteFace( giVideoSpeckFaceIndex ); gfMercVideoIsBeingDisplayed = FALSE; } return(TRUE); } */ void InitMercVideoFace() { //Alocates space, and loads the sti for SPECK // giVideoSpeckFaceIndex = InternalInitFace( NO_PROFILE, NOBODY, 0, MERC_VIDEO_MERC_ID_FOR_SPECKS, 3000, 2000 ); giVideoSpeckFaceIndex = InitFace( MERC_VIDEO_MERC_ID_FOR_SPECKS, NOBODY, 0 ); // Sets up the eyes blinking and the mouth moving // InternalSetAutoFaceActive( guiMercVideoFaceBackground, FACE_AUTO_RESTORE_BUFFER , giVideoSpeckFaceIndex, 0, 0, 8, 9, 7, 25 ); SetAutoFaceActive( guiMercVideoFaceBackground, FACE_AUTO_RESTORE_BUFFER , giVideoSpeckFaceIndex, 0, 0); //Renders the face to the background RenderAutoFace( giVideoSpeckFaceIndex ); //enables the global flag indicating the the video is being displayed gfMercVideoIsBeingDisplayed = TRUE; } BOOLEAN StartSpeckTalking(UINT16 usQuoteNum) { if(is_networked) return( FALSE ); if( usQuoteNum == MERC_VIDEO_SPECK_SPEECH_NOT_TALKING || usQuoteNum == MERC_VIDEO_SPECK_HAS_TO_TALK_BUT_QUOTE_NOT_CHOSEN_YET ) return( FALSE ); //Reset the time for when speck starts to do the random quotes HandleSpeckIdleConversation( TRUE ); //Start Speck talking if(!CharacterDialogue( MERC_VIDEO_MERC_ID_FOR_SPECKS, usQuoteNum, giVideoSpeckFaceIndex, DIALOGUE_SPECK_CONTACT_PAGE_UI, FALSE, FALSE ) ) { Assert(0); return(FALSE); } gusMercVideoSpeckSpeech = MERC_VIDEO_SPECK_SPEECH_NOT_TALKING; return(TRUE); } // Performs the frame by frame update BOOLEAN HandleSpeckTalking( BOOLEAN fReset ) { static BOOLEAN fWasTheMercTalking=FALSE; BOOLEAN fIsTheMercTalking; SGPRect SrcRect; SGPRect DestRect; if( fReset ) { fWasTheMercTalking = FALSE; return( TRUE ); } SrcRect.iLeft = 0; SrcRect.iTop = 0; SrcRect.iRight = 48; SrcRect.iBottom = 43; DestRect.iLeft = MERC_VIDEO_FACE_X; DestRect.iTop = MERC_VIDEO_FACE_Y; DestRect.iRight = DestRect.iLeft + MERC_VIDEO_FACE_WIDTH; DestRect.iBottom = DestRect.iTop + MERC_VIDEO_FACE_HEIGHT; HandleDialogue(); HandleAutoFaces( ); HandleTalkingAutoFaces( ); //Blt the face surface to the video background surface if( !BltStretchVideoSurface(FRAME_BUFFER, guiMercVideoFaceBackground, 0, 0, VO_BLT_SRCTRANSPARENCY, &SrcRect, &DestRect ) ) return(FALSE); //HandleCurrentMercDistortion(); InvalidateRegion(MERC_VIDEO_BACKGROUND_X, MERC_VIDEO_BACKGROUND_Y, (MERC_VIDEO_BACKGROUND_X + MERC_VIDEO_BACKGROUND_WIDTH), (MERC_VIDEO_BACKGROUND_Y + MERC_VIDEO_BACKGROUND_HEIGHT) ); //find out if the merc just stopped talking fIsTheMercTalking = gFacesData[ giVideoSpeckFaceIndex ].fTalking; //if the merc just stopped talking if(fWasTheMercTalking && !fIsTheMercTalking) { fWasTheMercTalking = FALSE; if( DialogueQueueIsEmpty( ) ) { RemoveSpeckPopupTextBox(); gfDisplaySpeckTextBox = FALSE; gusMercVideoSpeckSpeech = MERC_VIDEO_SPECK_SPEECH_NOT_TALKING; //Reset the time for when speck starts to do the random quotes HandleSpeckIdleConversation( TRUE ); } else fIsTheMercTalking = TRUE; } fWasTheMercTalking = fIsTheMercTalking; return(fIsTheMercTalking); } void HandleCurrentMercDistortion() { static UINT8 ubCurrentMercDistortionMode = MERC_DISTORTION_NO_DISTORTION; BOOLEAN fReturnStatus; //if there is no current distortion mode, randomly choose one if( ubCurrentMercDistortionMode == MERC_DISTORTION_NO_DISTORTION ) { UINT8 ubRandom; ubRandom = (UINT8)Random(200); if( ubRandom < 40 ) { ubRandom = (UINT8)Random(100); if( ubRandom < 10 ) ubCurrentMercDistortionMode = MERC_DISRTORTION_DISTORT_IMAGE; else if( ubRandom < 30 ) ubCurrentMercDistortionMode = MERC_DISTORTION_PIXELATE_UP; } } // Perform whichever video distortion mode is current switch( ubCurrentMercDistortionMode ) { case MERC_DISTORTION_NO_DISTORTION: break; case MERC_DISTORTION_PIXELATE_UP: // fReturnStatus = PixelateVideoMercImage( TRUE ); fReturnStatus = PixelateVideoMercImage( TRUE, MERC_VIDEO_FACE_X, MERC_VIDEO_FACE_Y, MERC_VIDEO_FACE_WIDTH, MERC_VIDEO_FACE_HEIGHT ); if( fReturnStatus ) ubCurrentMercDistortionMode = MERC_DISTORTION_PIXELATE_DOWN; break; case MERC_DISTORTION_PIXELATE_DOWN: // fReturnStatus = PixelateVideoMercImage( FALSE ); fReturnStatus = PixelateVideoMercImage( FALSE, MERC_VIDEO_FACE_X, MERC_VIDEO_FACE_Y, MERC_VIDEO_FACE_WIDTH, MERC_VIDEO_FACE_HEIGHT ); if( fReturnStatus ) ubCurrentMercDistortionMode = MERC_DISTORTION_NO_DISTORTION; break; case MERC_DISRTORTION_DISTORT_IMAGE: // fReturnStatus = DistortVideoMercImage(); fReturnStatus = DistortVideoMercImage( MERC_VIDEO_FACE_X, MERC_VIDEO_FACE_Y, MERC_VIDEO_FACE_WIDTH, MERC_VIDEO_FACE_HEIGHT ); if( fReturnStatus ) ubCurrentMercDistortionMode = MERC_DISTORTION_NO_DISTORTION; break; } } BOOLEAN PixelateVideoMercImage( BOOLEAN fUp, UINT16 usPosX, UINT16 usPosY, UINT16 usWidth, UINT16 usHeight) { static UINT32 uiLastTime; UINT32 uiCurTime = GetJA2Clock(); UINT16 *pBuffer=NULL, DestColor; UINT32 uiPitch; UINT16 i, j; static UINT8 ubPixelationAmount=255; BOOLEAN fReturnStatus=FALSE; i=0; pBuffer = (UINT16*)LockVideoSurface( FRAME_BUFFER, &uiPitch ); Assert( pBuffer ); if( ubPixelationAmount == 255 ) { if( fUp ) ubPixelationAmount = 1; else ubPixelationAmount = 4; uiLastTime = GetJA2Clock(); } //is it time to change the animation if( ( uiCurTime - uiLastTime ) > 100 ) { //if we are starting to pixelate the image if( fUp ) { //the varying degrees of pixelation if( ubPixelationAmount <= 4 ) { ubPixelationAmount++; fReturnStatus = FALSE; } else { ubPixelationAmount = 255; fReturnStatus = TRUE; } } //else we are pixelating down else { if( ubPixelationAmount > 1 ) { ubPixelationAmount--; fReturnStatus = FALSE; } else { ubPixelationAmount = 255; fReturnStatus = TRUE; } } uiLastTime = GetJA2Clock(); } else i=i; uiPitch /= 2; i=j=0; DestColor = pBuffer[ (j*uiPitch) + i ]; for(j=usPosY; j= usPosY+usHeight ) { usDistortionValue = 0; uiReturnValue = TRUE; } else { usDistortionValue++; uiReturnValue = FALSE; if( usDistortionValue + 10 >= usHeight ) usEndOnLine = usHeight-1; else usEndOnLine = usDistortionValue + 10; for(j=usPosY+usDistortionValue; j> 8); blue = (UINT8)(uiColor >> 16); DestColor = Get16BPPColor(FROMRGB( 255-red, 250-green, 250-blue) ); pBuffer[ (j*uiPitch) + i ] = DestColor; } } } UnLockVideoSurface( FRAME_BUFFER ); return(uiReturnValue); } BOOLEAN InitDestroyXToCloseVideoWindow( BOOLEAN fCreate ) { static BOOLEAN fButtonCreated=FALSE; //if we are asked to create the buttons and the button isnt already created if( fCreate && !fButtonCreated ) { guiXToCloseMercVideoButtonImage = LoadButtonImage("LAPTOP\\CloseButton.sti", -1,0,-1,1,-1 ); guiXToCloseMercVideoButton = QuickCreateButton( guiXToCloseMercVideoButtonImage, MERC_X_TO_CLOSE_VIDEO_X, MERC_X_TO_CLOSE_VIDEO_Y, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, BtnXToCloseMercVideoButtonCallback); SetButtonCursor(guiXToCloseMercVideoButton, CURSOR_LAPTOP_SCREEN); fButtonCreated = TRUE; } //if we are asked to destroy the buttons and the buttons are created if( !fCreate && fButtonCreated ) { UnloadButtonImage( guiXToCloseMercVideoButtonImage ); RemoveButton( guiXToCloseMercVideoButton ); fButtonCreated = FALSE; } return(TRUE); } void BtnXToCloseMercVideoButtonCallback(GUI_BUTTON *btn,INT32 reason) { if(reason & MSYS_CALLBACK_REASON_LBUTTON_DWN ) { btn->uiFlags |= BUTTON_CLICKED_ON; InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } if(reason & MSYS_CALLBACK_REASON_LBUTTON_UP ) { if (btn->uiFlags & BUTTON_CLICKED_ON) { btn->uiFlags &= (~BUTTON_CLICKED_ON ); //Stop speck from talking // ShutupaYoFace( giVideoSpeckFaceIndex ); StopSpeckFromTalking( ); //make sure we are done the intro speech gfDoneIntroSpeech = TRUE; //remove the video conf mode gubCurrentMercVideoMode = MERC_VIDEO_EXIT_VIDEO_MODE; gusMercVideoSpeckSpeech = MERC_VIDEO_SPECK_SPEECH_NOT_TALKING; InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } } if(reason & MSYS_CALLBACK_REASON_LOST_MOUSE) { btn->uiFlags &= (~BUTTON_CLICKED_ON ); InvalidateRegion(btn->Area.RegionTopLeftX, btn->Area.RegionTopLeftY, btn->Area.RegionBottomRightX, btn->Area.RegionBottomRightY); } } BOOLEAN DisplayMercVideoIntro( UINT16 usTimeTillFinish ) { UINT32 uiCurTime = GetJA2Clock(); static UINT32 uiLastTime=0; //init variable if( uiLastTime == 0 ) uiLastTime = uiCurTime; ColorFillVideoSurfaceArea( FRAME_BUFFER, MERC_VIDEO_FACE_X, MERC_VIDEO_FACE_Y, MERC_VIDEO_FACE_X+MERC_VIDEO_FACE_WIDTH, MERC_VIDEO_FACE_Y+MERC_VIDEO_FACE_HEIGHT, Get16BPPColor( FROMRGB( 0, 0, 0 ) ) ); //if the intro is done if( (uiCurTime - uiLastTime) > usTimeTillFinish ) { uiLastTime = 0; return(TRUE); } else return(FALSE); } void HandleTalkingSpeck() { BOOLEAN fIsSpeckTalking = TRUE; switch( gubCurrentMercVideoMode ) { //Init the video conferencing case MERC_VIDEO_INIT_VIDEO_MODE: //perform some opening animation. When its done start Speck talking //if the intro is finished if( DisplayMercVideoIntro( MERC_INTRO_TIME ) ) { //NULL out the string gsSpeckDialogueTextPopUp[0] = '\0'; //Start speck talking if( gusMercVideoSpeckSpeech != MERC_VIDEO_SPECK_SPEECH_NOT_TALKING && gusMercVideoSpeckSpeech != MERC_VIDEO_SPECK_HAS_TO_TALK_BUT_QUOTE_NOT_CHOSEN_YET ) StartSpeckTalking( gusMercVideoSpeckSpeech ); gusMercVideoSpeckSpeech = MERC_VIDEO_SPECK_SPEECH_NOT_TALKING; gubCurrentMercVideoMode = MERC_VIDEO_VIDEO_MODE; } break; //Display his talking and blinking face case MERC_VIDEO_VIDEO_MODE: //Make sure the accounts button does not overwrite the dialog text // ButtonList[ guiAccountBoxButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY; //def: if( gfJustEnteredMercSite && gubArrivedFromMercSubSite != MERC_CAME_FROM_OTHER_PAGE || gfFirstTimeIntoMERCSiteSinceEnteringLaptop ) { gfFirstTimeIntoMERCSiteSinceEnteringLaptop = FALSE; GetSpeckConditionalOpening( FALSE ); gfJustEnteredMercSite = FALSE; } else { fIsSpeckTalking = HandleSpeckTalking( FALSE ); if( !fIsSpeckTalking ) fIsSpeckTalking = GetSpeckConditionalOpening( FALSE ); //if speck didnt start talking, see if he just hired someone if( !fIsSpeckTalking ) { fIsSpeckTalking = ShouldSpeckStartTalkingDueToActionOnSubPage(); } } if( !fIsSpeckTalking ) gubCurrentMercVideoMode = MERC_VIDEO_EXIT_VIDEO_MODE; if( gfDisplaySpeckTextBox && gGameSettings.fOptions[ TOPTION_SUBTITLES ] ) { if( !gfInMercSite ) { StopSpeckFromTalking( ); return; } if( gsSpeckDialogueTextPopUp[0] != L'\0' ) { // DrawButton( guiAccountBoxButton ); // ButtonList[ guiAccountBoxButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY; if( iMercPopUpBox != -1 ) { #ifdef JA2UB //JA25: removed DrawButton( guiAccountBoxButton ); //JA25: removed ButtonList[ guiAccountBoxButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY; #else DrawButton( guiAccountBoxButton ); ButtonList[ guiAccountBoxButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY; #endif RenderMercPopUpBoxFromIndex( iMercPopUpBox, gusSpeckDialogueX, MERC_TEXT_BOX_POS_Y, FRAME_BUFFER); } } } break; // shut down the video conferencing case MERC_VIDEO_EXIT_VIDEO_MODE: //if the exit animation is finished, exit the video conf window if( DisplayMercVideoIntro( MERC_EXIT_TIME ) ) { StopSpeckFromTalking( ); //Delete the face DeleteFace( giVideoSpeckFaceIndex ); InitDestroyXToCloseVideoWindow( FALSE ); gfRedrawMercSite = TRUE; gfMercVideoIsBeingDisplayed = FALSE; //Remove the merc popup RemoveSpeckPopupTextBox(); //maybe display ending animation gubCurrentMercVideoMode = MERC_VIDEO_NO_VIDEO_MODE; } else { //else we are done the exit animation. The area is not being invalidated anymore InvalidateRegion( MERC_VIDEO_FACE_X, MERC_VIDEO_FACE_Y, MERC_VIDEO_FACE_X+MERC_VIDEO_FACE_WIDTH, MERC_VIDEO_FACE_Y+MERC_VIDEO_FACE_HEIGHT ); } break; } } void DisplayTextForSpeckVideoPopUp(STR16 pString) { UINT16 usActualHeight; INT32 iOldMercPopUpBoxId = iMercPopUpBox; //If the user has selected no subtitles if( !gGameSettings.fOptions[ TOPTION_SUBTITLES ] ) return; // wcscpy(gsSpeckDialogueTextPopUp, pString); //add the "" around the speech. swprintf( gsSpeckDialogueTextPopUp, L"\"%s\"", pString ); gfDisplaySpeckTextBox = TRUE; //Set this so the popup box doesnt render in RenderMercs() iMercPopUpBox = -1; //Render the screen to get rid of any old text popup boxes RenderMercs(); iMercPopUpBox = iOldMercPopUpBoxId; if( gfMercVideoIsBeingDisplayed && gfMercSiteScreenIsReDrawn ) { DrawMercVideoBackGround(); } //never use it anymore //SET_USE_WINFONTS( TRUE ); //SET_WINFONT( giSubTitleWinFont ); //Create the popup box iMercPopUpBox = PrepareMercPopupBox( iMercPopUpBox, BASIC_MERC_POPUP_BACKGROUND, BASIC_MERC_POPUP_BORDER, gsSpeckDialogueTextPopUp, 300, 0, 0, 0, &gusSpeckDialogueActualWidth, &usActualHeight); //SET_USE_WINFONTS( FALSE ); gusSpeckDialogueX = iScreenWidthOffset + 111 + ((640 - 111) / 2 - (gusSpeckDialogueActualWidth / 2)); //Render the pop box RenderMercPopUpBoxFromIndex( iMercPopUpBox, gusSpeckDialogueX, MERC_TEXT_BOX_POS_Y, FRAME_BUFFER); //check to make sure the region is not already initialized if( !( gMercSiteSubTitleMouseRegion.uiFlags & MSYS_REGION_EXISTS ) ) { MSYS_DefineRegion( &gMercSiteSubTitleMouseRegion, gusSpeckDialogueX, MERC_TEXT_BOX_POS_Y, (INT16)(gusSpeckDialogueX + gusSpeckDialogueActualWidth), (INT16)(MERC_TEXT_BOX_POS_Y + usActualHeight), MSYS_PRIORITY_HIGH, CURSOR_LAPTOP_SCREEN, MSYS_NO_CALLBACK, MercSiteSubTitleRegionCallBack ); MSYS_AddRegion( &gMercSiteSubTitleMouseRegion ); } } void CheatToGetAll5Merc() { LaptopSaveInfo.guiNumberOfMercPaymentsInDays += 20; /* LaptopSaveInfo.gbNumDaysTillFirstMercArrives = 1; LaptopSaveInfo.gbNumDaysTillSecondMercArrives = 1; LaptopSaveInfo.gbNumDaysTillThirdMercArrives = 1; LaptopSaveInfo.gbNumDaysTillFourthMercArrives = 1; */ LaptopSaveInfo.gubLastMercIndex = NUMBER_MERCS_AFTER_FOURTH_MERC_ARRIVES; } BOOLEAN GetSpeckConditionalOpening( BOOLEAN fJustEnteredScreen ) { static UINT16 usQuoteToSay=MERC_VIDEO_SPECK_SPEECH_NOT_TALKING; UINT8 ubCnt; BOOLEAN fCanSayLackOfPaymentQuote = TRUE; BOOLEAN fCanUseIdleTag = FALSE; //If we just entered the screen, reset some variables if( fJustEnteredScreen ) { gfDoneIntroSpeech = FALSE; #ifdef JA2UB usQuoteToSay = SPECK_QUOTE_NEW_INTRO_1; #else usQuoteToSay = 0; #endif return( FALSE ); } //if we are done the intro speech, or arrived from a sub page, get out of the function if( gfDoneIntroSpeech || gubArrivedFromMercSubSite != MERC_CAME_FROM_OTHER_PAGE ) { return( FALSE ); } gfDoneIntroSpeech = TRUE; //set the opening quote based on if the player has been here before #ifdef JA2UB if( LaptopSaveInfo.ubPlayerBeenToMercSiteStatus == MERC_SITE_FIRST_VISIT && usQuoteToSay <= SPECK_QUOTE_NEW_INTRO_7 ) //!= 0 ) #else if( LaptopSaveInfo.ubPlayerBeenToMercSiteStatus == MERC_SITE_FIRST_VISIT && usQuoteToSay <= 8 ) //!= 0 ) #endif { StartSpeckTalking( usQuoteToSay ); usQuoteToSay++; #ifdef JA2UB if( usQuoteToSay <= SPECK_QUOTE_NEW_INTRO_7 ) #else if( usQuoteToSay <= 8 ) #endif gfDoneIntroSpeech = FALSE; } #ifdef JA2UB //else if its the first time back since the laptop went down else if( gJa25SaveStruct.fHaveAimandMercOffferItems && !HasImportantSpeckQuoteBeingSaid( SPECK_QUOTE_2ND_INTRO_LAPTOP_WORKING_AGAIN_1 ) ) { StartSpeckTalking( SPECK_QUOTE_2ND_INTRO_LAPTOP_WORKING_AGAIN_1 ); StartSpeckTalking( SPECK_QUOTE_2ND_INTRO_LAPTOP_WORKING_AGAIN_2 ); StartSpeckTalking( SPECK_QUOTE_2ND_INTRO_LAPTOP_WORKING_AGAIN_3 ); StartSpeckTalking( SPECK_QUOTE_2ND_INTRO_LAPTOP_WORKING_AGAIN_4 ); StartSpeckTalking( SPECK_QUOTE_2ND_INTRO_LAPTOP_WORKING_AGAIN_5 ); StartSpeckTalking( SPECK_QUOTE_2ND_INTRO_LAPTOP_WORKING_AGAIN_6 ); } #else //if its the players second visit else if( LaptopSaveInfo.ubPlayerBeenToMercSiteStatus == MERC_SITE_SECOND_VISIT ) { StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_1_TOUGH_START ); fCanUseIdleTag = TRUE; } #endif // We have been here at least 2 times before, Check which quote we should use else { //if the player has not hired any MERC mercs before // CJC Dec 1 2002: fixing this, so near-bankrupt msg will play #ifdef JA2UB if( !IsAnyMercMercsHired( ) && CalcMercDaysServed() == 0) StartSpeckTalking( SPECK_QUOTE_DEFAULT_INTRO_HAVENT_HIRED_MERCS ); else StartSpeckTalking( SPECK_QUOTE_DEFAULT_INTRO_HAVE_HIRED_MERCS ); #endif #ifdef JA2UB //JA25: not using quote quote #else //if the player has not hired any MERC mercs before if( !IsAnyMercMercsHired( ) && CalcMercDaysServed() == 0) { StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_2_BUSINESS_BAD ); } #endif #ifdef JA2UB //JA25: not using quote quote #else //else if it is the first visit since the server went down else if( LaptopSaveInfo.fFirstVisitSinceServerWentDown == TRUE ) { LaptopSaveInfo.fFirstVisitSinceServerWentDown = 2; StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_9_FIRST_VISIT_SINCE_SERVER_WENT_DOWN ); fCanUseIdleTag = TRUE; } #endif /* //else if new mercs are available else if( LaptopSaveInfo.fNewMercsAvailableAtMercSite ) { LaptopSaveInfo.fNewMercsAvailableAtMercSite = FALSE; StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_11_NEW_MERCS_AVAILABLE ); } */ //else if lots of MERC mercs are DEAD, and speck can say the quote ( dont want him to continously say it ) #ifdef JA2UB if( CountNumberOfMercMercsWhoAreDead() >= 2 && LaptopSaveInfo.ubSpeckCanSayPlayersLostQuote ) #else else if( CountNumberOfMercMercsWhoAreDead() >= 2 && LaptopSaveInfo.ubSpeckCanSayPlayersLostQuote ) #endif { StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_12_PLAYERS_LOST_MERCS ); //Set it so speck Wont say the quote again till someone else dies LaptopSaveInfo.ubSpeckCanSayPlayersLostQuote = 0; } #ifdef JA2UB //JA25: not using quote quote #else //else if player owes lots of money else if( LaptopSaveInfo.gubPlayersMercAccountStatus == MERC_ACCOUNT_SUSPENDED ) { StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_5_PLAYER_OWES_SPECK_ACCOUNT_SUSPENDED ); fCanSayLackOfPaymentQuote = FALSE; } #endif //else if the player owes speck a large sum of money, have speck say so #ifdef JA2UB //JA25: not using quote quote #else else if ( CalculateHowMuchPlayerOwesSpeck( ) > gGameExternalOptions.usMERCBankruptWarning ) { StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_6_PLAYER_OWES_SPECK_ALMOST_BANKRUPT_1 ); StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_6_PLAYER_OWES_SPECK_ALMOST_BANKRUPT_2 ); fCanSayLackOfPaymentQuote = FALSE; } #endif else { #ifdef JA2UB UINT8 ubNumMercsDead = NumberOfMercMercsDead(); BOOLEAN fCanUseIdleTag = FALSE; #endif UINT8 ubRandom = ( UINT8 ) Random( 100 ); #ifdef JA2UB //JA25: not using quote quote #else //if business is good // if( ubRandom < 40 && ubNumMercsDead < 2 && CountNumberOfMercMercsHired() > 1 ) if( ubRandom < 40 && AreAnyOfTheNewMercsAvailable() && CountNumberOfMercMercsHired() > 1 ) { StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_3_BUSINESS_GOOD ); fCanUseIdleTag = TRUE; } #endif //or if still trying to recruit ( the last recruit hasnt arrived and the player has paid for some of his mercs ) // else if( ubRandom < 80 && LaptopSaveInfo.gbNumDaysTillFourthMercArrives != -1 && LaptopSaveInfo.gbNumDaysTillFirstMercArrives < MERC_NUM_DAYS_TILL_FIRST_MERC_AVAILABLE ) #ifdef JA2UB //JA25: not using quote quote #else else if( ubRandom < 80 && gConditionsForMercAvailability[ LaptopSaveInfo.ubLastMercAvailableId ].usMoneyPaid <= LaptopSaveInfo.uiTotalMoneyPaidToSpeck && CanMercBeAvailableYet( LaptopSaveInfo.ubLastMercAvailableId ) ) { StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_4_TRYING_TO_RECRUIT ); fCanUseIdleTag = TRUE; } //else use the generic opening else #endif { #ifdef JA2UB //JA25: not using quote quote #else StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_10_GENERIC_OPENING ); fCanUseIdleTag = TRUE; //JA25: not using quote quote //if the merc hasnt said the line before if( !LaptopSaveInfo.fSaidGenericOpeningInMercSite ) { LaptopSaveInfo.fSaidGenericOpeningInMercSite = TRUE; StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_10_TAG_FOR_20 ); } } #endif } #ifdef JA2UB //no UB #else if( fCanUseIdleTag ) { UINT8 ubRandom = Random( 100 ); if( ubRandom < 50 ) { ubRandom = Random( 4 ); switch( ubRandom ) { case 0: StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_TAG_ON_AFTER_OTHER_TAGS_1 ); break; case 1: StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_TAG_ON_AFTER_OTHER_TAGS_2 ); break; case 2: StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_TAG_ON_AFTER_OTHER_TAGS_3 ); break; case 3: StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_TAG_ON_AFTER_OTHER_TAGS_4 ); break; default: Assert( 0 ); } } #endif } } #ifdef JA2UB //JA25: not using quote quote #else //If Speck has sent an email to the player, and the player still hasnt paid, has speck complain about it. // CJC Dec 1 2002 ACTUALLY HOOKED IN THAT CHECK if (fCanSayLackOfPaymentQuote) { if( LaptopSaveInfo.uiSpeckQuoteFlags & SPECK_QUOTE__SENT_EMAIL_ABOUT_LACK_OF_PAYMENT ) { LaptopSaveInfo.uiSpeckQuoteFlags &= ~SPECK_QUOTE__SENT_EMAIL_ABOUT_LACK_OF_PAYMENT; StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_TAG_PLAYER_OWES_MONEY ); } } //if new mercs are available if( LaptopSaveInfo.fNewMercsAvailableAtMercSite ) { LaptopSaveInfo.fNewMercsAvailableAtMercSite = FALSE; StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_11_NEW_MERCS_AVAILABLE ); } #endif //if any mercs are dead if( IsAnyMercMercsDead() ) { UINT8 ubMercID; //if no merc has died before #ifdef JA2UB //JA25: not using quote quote #else if( !LaptopSaveInfo.fHasAMercDiedAtMercSite ) { LaptopSaveInfo.fHasAMercDiedAtMercSite = TRUE; StartSpeckTalking( SPECK_QUOTE_ALTERNATE_OPENING_TAG_FIRST_MERC_DIES ); } #endif //loop through all the mercs and see if any are dead and the quote is not said for( ubCnt=0; ubCnt= 2000 ) { #ifdef JA2UB //Gaston is hired if ( ubHiredMercID == GASTON_UB ) { //if biff is available, advertise for biff if( IsMercMercAvailable( FLO ) ) StartSpeckTalking( SPECK_QUOTE_PLAYER_HIRES_GASTON ); } //Stogie is hired else if ( ubHiredMercID == STOGIE_UB ) { //if biff is available, advertise for biff if( IsMercMercAvailable( BIFF ) ) StartSpeckTalking( SPECK_QUOTE_PLAYER_HIRES_STOGIE ); } #endif //determine which quote to say based on the merc that was hired switch( ubHiredMercID ) { //Biff is hired case BIFF: //if Larry is available, advertise for larry if( IsMercMercAvailable( LARRY_NORMAL ) || IsMercMercAvailable( LARRY_DRUNK ) ) StartSpeckTalking( SPECK_QUOTE_PLAYERS_HIRES_BIFF_SPECK_PLUGS_LARRY ); //if flo is available, advertise for flo if( IsMercMercAvailable( FLO ) ) StartSpeckTalking( SPECK_QUOTE_PLAYERS_HIRES_BIFF_SPECK_PLUGS_FLO ); break; //haywire is hired case HAYWIRE: //if razor is available, advertise for razor if( IsMercMercAvailable( RAZOR ) ) StartSpeckTalking( SPECK_QUOTE_PLAYERS_HIRES_HAYWIRE_SPECK_PLUGS_RAZOR ); break; //razor is hired case RAZOR: //if haywire is available, advertise for haywire if( IsMercMercAvailable( HAYWIRE ) ) StartSpeckTalking( SPECK_QUOTE_PLAYERS_HIRES_RAZOR_SPECK_PLUGS_HAYWIRE ); break; //flo is hired case FLO: //if biff is available, advertise for biff if( IsMercMercAvailable( BIFF ) ) StartSpeckTalking( SPECK_QUOTE_PLAYERS_HIRES_FLO_SPECK_PLUGS_BIFF ); break; //larry is hired case LARRY_NORMAL: case LARRY_DRUNK: //if biff is available, advertise for biff if( IsMercMercAvailable( BIFF ) ) StartSpeckTalking( SPECK_QUOTE_PLAYERS_HIRES_LARRY_SPECK_PLUGS_BIFF ); break; #ifdef JA2UB #else //Gaston is hired case GASTON: //if biff is available, advertise for biff if( IsMercMercAvailable( FLO ) ) StartSpeckTalking( SPECK_QUOTE_PLAYER_HIRES_GASTON ); break; //Stogie is hired case STOGIE: //if biff is available, advertise for biff if( IsMercMercAvailable( BIFF ) ) StartSpeckTalking( SPECK_QUOTE_PLAYER_HIRES_STOGIE ); break; // anv: Speck is hired case SPECK_PLAYABLE: if( IsMercOnTeam( VICKI, FALSE, FALSE ) ) StartSpeckTalking( SPECK_QUOTE_PLAYER_HIRES_SPECK_TOGETHER_WITH_VICKI ); else StartSpeckTalking( SPECK_QUOTE_PLAYER_HIRES_SPECK ); break; #endif } } gubArrivedFromMercSubSite = MERC_CAME_FROM_HIRE_PAGE; } BOOLEAN IsMercMercAvailable( UINT8 ubMercID ) { UINT8 cnt; //loop through the array of mercs for( cnt=0; cnt 50 ) StartSpeckTalking( SPECK_QUOTE_GENERIC_THANKS_FOR_HIRING_MERCS_1 ); else StartSpeckTalking( SPECK_QUOTE_GENERIC_THANKS_FOR_HIRING_MERCS_2 ); #ifdef JA2UB //if it hasnt been said, say the encouraged to shop quote if( !HasImportantSpeckQuoteBeingSaid( SPECK_QUOTE_ENCOURAGE_SHOP_TAG_ON ) ) { StartSpeckTalking( SPECK_QUOTE_ENCOURAGE_SHOP_TAG_ON ); } #endif } gfJustHiredAMercMerc = FALSE; // gfDoneIntroSpeech = TRUE; return( TRUE ); } return( FALSE ); } #ifdef JA2UB #else BOOLEAN IsSpeckComAvailable() // anv: Prevent Speck from talking if his playable version is out of reach { //he's hired, travelling, dead or POW, he cant' talk if( ( ( IsMercOnTeam( SPECK_PLAYABLE, FALSE, FALSE ) || gMercProfiles[ SPECK_PLAYABLE ].bMercStatus == MERC_IS_DEAD || gMercProfiles[ SPECK_PLAYABLE ].bMercStatus == MERC_RETURNING_HOME || gMercProfiles[ SPECK_PLAYABLE ].bMercStatus == MERC_FIRED_AS_A_POW ) ) //he still can talk if he was just hired, so he can say his recruitment quote && ( GetAvailableMercIDFromMERCArray( gubCurMercIndex ) != SPECK_PLAYABLE || gusMercVideoSpeckSpeech == SPECK_QUOTE_PLAYER_TRIES_TO_HIRE_ALREADY_HIRED_MERC || gusMercVideoSpeckSpeech == SPECK_QUOTE_BIFF_UNAVALIABLE || gusMercVideoSpeckSpeech == SPECK_QUOTE_SPECK_UNAVAILABLE ) ) { return(FALSE); } return(TRUE); } void HandleSpeckWitnessingEmployeeDeath( SOLDIERTYPE* pSoldier ) // anv: handle playable Speck witnessing his employee death { if(pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__MERC) { // first blood if( !LaptopSaveInfo.fHasAMercDiedAtMercSite ) { LaptopSaveInfo.fHasAMercDiedAtMercSite = TRUE; TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_FIRST_MERC_DIES ); } // numerous casualties, Speck whines... else if( CountNumberOfMercMercsWhoAreDead() >= 2 && LaptopSaveInfo.ubSpeckCanSayPlayersLostQuote ) { TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_PLAYERS_LOST_MERCS ); //Set it so speck Wont say the quote again till someone else dies LaptopSaveInfo.ubSpeckCanSayPlayersLostQuote = 0; } // merc specific requiem switch( pSoldier->ubProfile ) { case BIFF: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_BIFF_IS_DEAD ); break; case HAYWIRE: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_HAYWIRE_IS_DEAD); break; case GASKET: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_GASKET_IS_DEAD ); break; case RAZOR: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_RAZOR_IS_DEAD ); break; case FLO: //if biff is dead if( IsMercDead( BIFF ) ) TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_FLO_IS_DEAD_BIFF_IS_DEAD ); else { TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_FLO_IS_DEAD_BIFF_ALIVE); MakeBiffAwayForCoupleOfDays(); } break; case GUMPY: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_GUMPY_IS_DEAD); break; case LARRY_NORMAL: case LARRY_DRUNK: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_LARRY_IS_DEAD); break; case COUGAR: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_COUGER_IS_DEAD); break; case NUMB: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_NUMB_IS_DEAD); break; case BUBBA: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_BUBBA_IS_DEAD); break; case GASTON: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_GASTON_DEAD); break; case STOGIE: TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_STOGIE_DEAD); break; } } } #endif void AddJohnAsMerc() // anv: add John as playable merc after escorting Kulbas out of country { LaptopSaveInfo.bJohnEscorted = TRUE; LaptopSaveInfo.uiJohnEscortedDate = GetWorldDay(); return; } BOOLEAN ShouldSpeckSayAQuote() { //if we are entering from anywhere except a sub page, and we should say the opening quote if( gfJustEnteredMercSite && gubArrivedFromMercSubSite == MERC_CAME_FROM_OTHER_PAGE ) { //if the merc has something to say if( gusMercVideoSpeckSpeech != MERC_VIDEO_SPECK_SPEECH_NOT_TALKING ) return( FALSE ); } //if the player just hired a merc if( gfJustHiredAMercMerc ) { gusMercVideoSpeckSpeech = MERC_VIDEO_SPECK_HAS_TO_TALK_BUT_QUOTE_NOT_CHOSEN_YET; return( TRUE ); /* //if the merc has something to say if( gusMercVideoSpeckSpeech != MERC_VIDEO_SPECK_SPEECH_NOT_TALKING ) return( TRUE ); else { gusMercVideoSpeckSpeech = MERC_VIDEO_SPECK_HAS_TO_TALK_BUT_QUOTE_NOT_CHOSEN_YET; return( TRUE ); } */ } //If it is the first time into the merc site if( gfFirstTimeIntoMERCSiteSinceEnteringLaptop ) { // gfFirstTimeIntoMERCSiteSinceEnteringLaptop = FALSE; gusMercVideoSpeckSpeech = MERC_VIDEO_SPECK_HAS_TO_TALK_BUT_QUOTE_NOT_CHOSEN_YET; return( TRUE ); } /* //if we are entering from anywhere except a sub page if( gubArrivedFromMercSubSite == MERC_CAME_FROM_OTHER_PAGE ) { GetSpeckConditionalOpening( FALSE ); return( TRUE ); } */ return( FALSE ); } void HandleSpeckIdleConversation( BOOLEAN fReset ) { static UINT32 uiLastTime=0; UINT32 uiCurTime = GetJA2Clock(); INT16 sLeastSaidQuote; //if we should reset the variables if( fReset ) { uiLastTime = GetJA2Clock(); return; } if( ( uiCurTime - uiLastTime ) > SPECK_IDLE_CHAT_DELAY ) { //if Speck is not talking if( !gfMercVideoIsBeingDisplayed ) { sLeastSaidQuote = GetRandomQuoteThatHasBeenSaidTheLeast( ); if( sLeastSaidQuote != -1 ) gusMercVideoSpeckSpeech = (UINT8)sLeastSaidQuote; //Say the aim slander quotes the least if( sLeastSaidQuote >= 47 && sLeastSaidQuote <= 57 ) { IncreaseMercRandomQuoteValue( (UINT8)sLeastSaidQuote, 1 ); } #ifdef JA2UB //if its the biff is dead quote, only say the quote once else if( sLeastSaidQuote == SPECK_QUOTE_BIFF_DEAD_WHEN_IMPORTING ) IncreaseMercRandomQuoteValue( (UINT8)sLeastSaidQuote, 255 ); #endif else if( sLeastSaidQuote != -1 ) IncreaseMercRandomQuoteValue( (UINT8)sLeastSaidQuote, 3 ); } uiLastTime = GetJA2Clock(); } } INT16 GetRandomQuoteThatHasBeenSaidTheLeast( ) { UINT8 cnt; INT16 sSmallestNumber=255; for( cnt=0; cnt 255 ) gNumberOfTimesQuoteSaid[ cnt ].uiNumberOfTimesQuoteSaid = 255; else gNumberOfTimesQuoteSaid[ cnt ].uiNumberOfTimesQuoteSaid += ubValue; break; } } } void StopSpeckFromTalking( ) { if( giVideoSpeckFaceIndex == -1 ) return; //Stop speck from talking ShutupaYoFace( giVideoSpeckFaceIndex ); RemoveSpeckPopupTextBox(); gusMercVideoSpeckSpeech = MERC_VIDEO_SPECK_SPEECH_NOT_TALKING; } BOOLEAN HasLarryRelapsed() { return( CheckFact( FACT_LARRY_CHANGED, 0 ) ); } //Gets Called on each enter into laptop. void EnterInitMercSite() { gfFirstTimeIntoMERCSiteSinceEnteringLaptop = TRUE; gubCurMercIndex = 0; } BOOLEAN ShouldTheMercSiteServerGoDown() { UINT32 uiDay = GetWorldDay(); // If the merc site has never gone down, the first new merc has shown ( which shows the player is using the site ), // and the players account status is ok ( cant have the merc site going down when the player owes him money, player may lose account that way ) // if( !LaptopSaveInfo.fMercSiteHasGoneDownYet && LaptopSaveInfo.gbNumDaysTillThirdMercArrives <= 6 && LaptopSaveInfo.gubPlayersMercAccountStatus == MERC_ACCOUNT_VALID ) if( !LaptopSaveInfo.fMercSiteHasGoneDownYet && LaptopSaveInfo.ubLastMercAvailableId >= 1 && LaptopSaveInfo.gubPlayersMercAccountStatus == MERC_ACCOUNT_VALID ) { if( Random( 100 ) < ( uiDay * 2 + 10 ) ) { return( TRUE ); } else { return( FALSE ); } } return( FALSE ); } #ifdef JA2UB //no UB #else void GetMercSiteBackOnline() { if( IsSpeckComAvailable() ) { //Add an email telling the user the site is back up AddEmail(MERC_NEW_SITE_ADDRESS, MERC_NEW_SITE_ADDRESS_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin(), -1, -1, TYPE_EMAIL_EMAIL_EDT, XML_SPECK_NEWSITE); //Set a flag indicating that the server just went up ( so speck can make a comment when the player next visits the site ) LaptopSaveInfo.fFirstVisitSinceServerWentDown = TRUE; } else { // anv: Have Speck inform player personally TacticalCharacterDialogue( FindSoldierByProfileID( SPECK_PLAYABLE , TRUE ), SPECK_PLAYABLE_QUOTE_SERVER_WENT_DOWN ); // don't bring this up again LaptopSaveInfo.fFirstVisitSinceServerWentDown = 2; } } #endif void DrawMercVideoBackGround() { HVOBJECT hPixHandle; GetVideoObject(&hPixHandle, guiMercVideoPopupBackground); BltVideoObject(FRAME_BUFFER, hPixHandle, 0,MERC_VIDEO_BACKGROUND_X, MERC_VIDEO_BACKGROUND_Y, VO_BLT_SRCTRANSPARENCY, NULL); //put the title on the window DrawTextToScreen(MercHomePageText[MERC_SPECK_COM], MERC_X_VIDEO_TITLE_X, MERC_X_VIDEO_TITLE_Y, 0, MERC_VIDEO_TITLE_FONT, MERC_VIDEO_TITLE_COLOR, FONT_MCOLOR_BLACK, FALSE, LEFT_JUSTIFIED); InvalidateRegion(MERC_VIDEO_BACKGROUND_X, MERC_VIDEO_BACKGROUND_Y, (MERC_VIDEO_BACKGROUND_X + MERC_VIDEO_BACKGROUND_WIDTH), (MERC_VIDEO_BACKGROUND_Y + MERC_VIDEO_BACKGROUND_HEIGHT) ); } void DisableMercSiteButton() { if( iMercPopUpBox != -1 ) { #ifdef JA2UB //JA25: removed ButtonList[ guiAccountBoxButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY; #else ButtonList[ guiAccountBoxButton ]->uiFlags |= BUTTON_FORCE_UNDIRTY; #endif } } BOOLEAN CanMercQuoteBeSaid( UINT32 uiQuoteID ) { BOOLEAN fRetVal = TRUE; //switch onb the quote being said, if hes plugging a merc that has already been hired, dont say it switch( uiQuoteID ) { case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_BIFF: if( !IsMercMercAvailable( BIFF ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_HAYWIRE: if( !IsMercMercAvailable( HAYWIRE ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_GASKET: if( !IsMercMercAvailable( GASKET ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_RAZOR: if( !IsMercMercAvailable( RAZOR ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_FLO: if( !IsMercMercAvailable( FLO ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_GUMPY: if( !IsMercMercAvailable( GUMPY ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_LARRY: if( !IsMercMercAvailable( LARRY_NORMAL ) || IsMercMercAvailable( LARRY_DRUNK ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_COUGER: if( !IsMercMercAvailable( COUGAR ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_NUMB: if( !IsMercMercAvailable( NUMB ) ) fRetVal = FALSE; break; case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_BUBBA: if( !IsMercMercAvailable( BUBBA ) ) fRetVal = FALSE; break; #ifdef JA2UB #else //anv: playable Speck case SPECK_QUOTE_PLAYER_NOT_DOING_ANYTHING_SPECK_SELLS_HIMSELF: if( !IsMercMercAvailable( SPECK_PLAYABLE ) ) fRetVal = FALSE; break; #endif #ifdef JA2UB case SPECK_QUOTE_BIFF_DEAD_WHEN_IMPORTING: if( !gJa25SaveStruct.fBiffWasKilledWhenImportingSave ) fRetVal = FALSE; break; case SPECK_QUOTE_ADVERTISE_GASTON: if( !IsMercMercAvailable( GASTON_UB ) )//GASTON fRetVal = FALSE; break; case SPECK_QUOTE_ADVERTISE_STOGIE: if( !IsMercMercAvailable( STOGIE_UB ) )//STOGIE fRetVal = FALSE; break; #else case SPECK_QUOTE_ADVERTISE_GASTON: if( !IsMercMercAvailable( GASTON ) ) fRetVal = FALSE; break; case SPECK_QUOTE_ADVERTISE_STOGIE: if( !IsMercMercAvailable( STOGIE ) ) fRetVal = FALSE; break; #endif } return( fRetVal ); } void InitializeNumDaysMercArrive() { /* LaptopSaveInfo.gbNumDaysTillFirstMercArrives = MERC_NUM_DAYS_TILL_FIRST_MERC_AVAILABLE; LaptopSaveInfo.gbNumDaysTillSecondMercArrives = MERC_NUM_DAYS_TILL_SECOND_MERC_AVAILABLE; LaptopSaveInfo.gbNumDaysTillThirdMercArrives = MERC_NUM_DAYS_TILL_THIRD_MERC_AVAILABLE; LaptopSaveInfo.gbNumDaysTillFourthMercArrives = MERC_NUM_DAYS_TILL_FOURTH_MERC_AVAILABLE; */ } void MakeBiffAwayForCoupleOfDays() { gMercProfiles[ BIFF ].uiDayBecomesAvailable = Random( 2 ) + 2; } BOOLEAN AreAnyOfTheNewMercsAvailable() { UINT8 ubMercID; if( LaptopSaveInfo.fNewMercsAvailableAtMercSite ) return( FALSE ); for(UINT8 i=0; i 0 && gConditionsForMercAvailability[gConditionsForMercAvailability[i - 1].uiIndex].uiAlternateIndex != 255) { // Previous merc has alternate (drunk) merc, skip his one! //LaptopSaveInfo.gubLastMercIndex = LaptopSaveInfo.gubLastMercIndex + 2; LaptopSaveInfo.gubLastMercIndex = LaptopSaveInfo.gubLastMercIndex++; } else { LaptopSaveInfo.gubLastMercIndex++; } } //gConditionsForMercAvailability[gConditionsForMercAvailability[i].uiIndex].NewMercsAvailable = TRUE; LaptopSaveInfo.ubLastMercAvailableId = gConditionsForMercAvailability[i].uiIndex; gConditionsForMercAvailability[i].StartMercsAvailable = TRUE; #ifdef JA2UB if (!sentNewMercsEmail) { sentNewMercsEmail = true; AddEmail(NEW_MERCS_AT_MERC, NEW_MERCS_AT_MERC_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin(), -1, -1, TYPE_EMAIL_EMAIL_EDT); } //new mercs are available LaptopSaveInfo.fNewMercsAvailableAtMercSite = TRUE; #else if (IsSpeckComAvailable()) { if (!sentNewMercsEmail) { sentNewMercsEmail = true; AddEmail(NEW_MERCS_AT_MERC, NEW_MERCS_AT_MERC_LENGTH, SPECK_FROM_MERC, GetWorldTotalMin(), -1, -1, TYPE_EMAIL_EMAIL_EDT, XML_SPECK_NEWPERSONNEL); } //new mercs are available LaptopSaveInfo.fNewMercsAvailableAtMercSite = TRUE; } else { // anv: Have speck inform player personally TacticalCharacterDialogue(FindSoldierByProfileID(SPECK_PLAYABLE, TRUE), SPECK_PLAYABLE_QUOTE_NEW_MERCS_AVAILABLE); } #endif } } } } //used for older saves void CalcAproximateAmountPaidToSpeck() { UINT8 i, ubMercID; //loop through all the mercs and tally up the amount speck should have been paid for(i=0; i