diff --git a/GameSettings.cpp b/GameSettings.cpp
index e4a9d26e..4dfaf308 100644
--- a/GameSettings.cpp
+++ b/GameSettings.cpp
@@ -1894,8 +1894,12 @@ void LoadGameExternalOptions()
gGameExternalOptions.fDynamicOpinionsShowChange = iniReader.ReadBoolean("Dynamic Opinion Settings", "DYNAMIC_OPINIONS_SHOWCHANGE", TRUE );
gGameExternalOptions.fDynamicWageFactor = iniReader.ReadFloat("Dynamic Opinion Settings","WAGE_ACCEPTANCE_FACTOR", 1.5f, 0.1f, 10.0f );
- gGameExternalOptions.fDynamicDialogue = iniReader.ReadBoolean("Dynamic Dialogue Settings", "DYNAMIC_DIALOGUE", TRUE );
- gGameExternalOptions.usDynamicDialogueTimeOffset = iniReader.ReadInteger("Dynamic Dialogue Settings", "DYNAMIC_DIALOGUE_TIME_OFFSET", 3000, 500, 10000 );
+ gGameExternalOptions.fDynamicDialogue = iniReader.ReadBoolean("Dynamic Dialogue Settings", "DYNAMIC_DIALOGUE", FALSE );
+ gGameExternalOptions.sDynamicDialogueTimeOffset = iniReader.ReadInteger( "Dynamic Dialogue Settings", "DYNAMIC_DIALOGUE_TIME_OFFSET", 3000, 500, 10000 );
+
+ gGameExternalOptions.fPMC = iniReader.ReadBoolean( "PMC Settings", "PMC", TRUE );
+ gGameExternalOptions.usPMCMaxRegulars = iniReader.ReadInteger( "PMC Settings", "PMC_MAX_REGULARS", 35, 5, 100 );
+ gGameExternalOptions.usPMCMaxVeterans = iniReader.ReadInteger( "PMC Settings", "PMC_MAX_VETERANS", 20, 5, 100 );
//################# Laptop Settings ##################
diff --git a/GameSettings.h b/GameSettings.h
index c6443ae5..55aedaf9 100644
--- a/GameSettings.h
+++ b/GameSettings.h
@@ -1423,7 +1423,12 @@ typedef struct
// Flugente: dynamic dialogue
BOOLEAN fDynamicDialogue;
- UINT32 usDynamicDialogueTimeOffset;
+ INT32 sDynamicDialogueTimeOffset;
+
+ // Flugente: PMC
+ BOOLEAN fPMC;
+ UINT8 usPMCMaxRegulars;
+ UINT8 usPMCMaxVeterans;
// Flugente: enemy roles
BOOLEAN fEnemyRoles;
diff --git a/GameVersion.cpp b/GameVersion.cpp
index 12660e96..10846046 100644
--- a/GameVersion.cpp
+++ b/GameVersion.cpp
@@ -15,9 +15,9 @@
#ifdef JA2EDITOR
#ifdef JA2UB
- CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.7454 (Development Build)" };
+ CHAR16 zVersionLabel[256] = { L"Unfinished Business - Map Editor v1.13.7457 (Development Build)" };
#else
- CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.7454 (Development Build)" };
+ CHAR16 zVersionLabel[256] = { L"Map Editor v1.13.7457 (Development Build)" };
#endif
// ------------------------------
@@ -27,11 +27,11 @@
//DEBUG BUILD VERSION
#ifdef JA2UB
- CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.7454 (Development Build)" };
+ CHAR16 zVersionLabel[256] = { L"Debug: Unfinished Business - v1.13.7457 (Development Build)" };
#elif defined (JA113DEMO)
- CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.7454 (Development Build)" };
+ CHAR16 zVersionLabel[256] = { L"Debug: JA2 Demo - v1.13.7457 (Development Build)" };
#else
- CHAR16 zVersionLabel[256] = { L"Debug: v1.13.7454 (Development Build)" };
+ CHAR16 zVersionLabel[256] = { L"Debug: v1.13.7457 (Development Build)" };
#endif
#elif defined CRIPPLED_VERSION
@@ -46,16 +46,16 @@
//RELEASE BUILD VERSION
#ifdef JA2UB
- CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.7454 (Development Build)" };
+ CHAR16 zVersionLabel[256] = { L"Release Unfinished Business - v1.13.7457 (Development Build)" };
#elif defined (JA113DEMO)
- CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.7454 (Development Build)" };
+ CHAR16 zVersionLabel[256] = { L"Release JA2 Demo - v1.13.7457 (Development Build)" };
#else
- CHAR16 zVersionLabel[256] = { L"Release v1.13.7454 (Development Build)" };
+ CHAR16 zVersionLabel[256] = { L"Release v1.13.7457 (Development Build)" };
#endif
#endif
-CHAR8 czVersionNumber[16] = { "Build 14.08.28" }; //YY.MM.DD
+CHAR8 czVersionNumber[16] = { "Build 14.08.30" }; //YY.MM.DD
CHAR16 zTrackingNumber[16] = { L"Z" };
// SAVE_GAME_VERSION is defined in header, change it there
diff --git a/GameVersion.h b/GameVersion.h
index 2f471a56..8f154d5b 100644
--- a/GameVersion.h
+++ b/GameVersion.h
@@ -21,6 +21,7 @@ extern CHAR16 zTrackingNumber[16];
// Keeps track of the saved game version. Increment the saved game version whenever
// you will invalidate the saved game file
+#define PMC_WEBSITE 160 // Flugente: a new PMC allows us to hire trained militia
#define DISEASE_SYSTEM 159 // Flugente: mercs can get diseases
#define PRISONER_EXPANSION 158 // Flugente: more types of prisoners
#define DYNAMIC_DIALOGUE 157 // Flugente: mercs have dynamic dialogue depending on newly formed opinions, an the player can interact with them
@@ -78,7 +79,7 @@ extern CHAR16 zTrackingNumber[16];
#define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes
#define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system
-#define SAVE_GAME_VERSION DISEASE_SYSTEM
+#define SAVE_GAME_VERSION PMC_WEBSITE
//#define RUSSIANGOLD
#ifdef __cplusplus
diff --git a/Laptop/DropDown.h b/Laptop/DropDown.h
index cf4262f7..00bd6bf7 100644
--- a/Laptop/DropDown.h
+++ b/Laptop/DropDown.h
@@ -103,6 +103,8 @@ enum definedDropDowns
DROPDOWNNR_MERCCOMPARE1,
DROPDOWNNR_MERCCOMPARE2,
DROPDOWNNR_MERCCOMPARE_SQUADSELECTION,
+
+ DROPDOWNNR_PMC_LOCATION,
};
/*
@@ -210,6 +212,11 @@ public:
*/
BOOLEAN HasEntries( ) { return !mEntryVector.empty(); }
+ /*
+ * Remove all entries
+ */
+ void ClearEntries( ) { mSelectedEntry = 0; mEntryVector.clear( ); }
+
// call to open/close the drop down
void OpenDropDownRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason );
void CloseDropDownRegionCallBack(MOUSE_REGION * pRegion, INT32 iReason );
diff --git a/Laptop/Laptop_VS2005.vcproj b/Laptop/Laptop_VS2005.vcproj
index e12323eb..d1e88175 100644
--- a/Laptop/Laptop_VS2005.vcproj
+++ b/Laptop/Laptop_VS2005.vcproj
@@ -650,6 +650,10 @@
RelativePath=".\personnel.h"
>
+
+
@@ -968,6 +972,10 @@
RelativePath=".\personnel.cpp"
>
+
+
diff --git a/Laptop/Laptop_VS2008.vcproj b/Laptop/Laptop_VS2008.vcproj
index 2e279c28..9e28b3a0 100644
--- a/Laptop/Laptop_VS2008.vcproj
+++ b/Laptop/Laptop_VS2008.vcproj
@@ -650,6 +650,10 @@
RelativePath="personnel.h"
>
+
+
@@ -970,6 +974,10 @@
RelativePath="personnel.cpp"
>
+
+
diff --git a/Laptop/Laptop_VS2010.vcxproj b/Laptop/Laptop_VS2010.vcxproj
index a82a8606..d6c5a191 100644
--- a/Laptop/Laptop_VS2010.vcxproj
+++ b/Laptop/Laptop_VS2010.vcxproj
@@ -101,6 +101,7 @@
+
@@ -182,6 +183,7 @@
+
diff --git a/Laptop/Laptop_VS2010.vcxproj.filters b/Laptop/Laptop_VS2010.vcxproj.filters
index df9800c4..00f63304 100644
--- a/Laptop/Laptop_VS2010.vcxproj.filters
+++ b/Laptop/Laptop_VS2010.vcxproj.filters
@@ -201,6 +201,9 @@
Header Files
+
+ Header Files
+
Header Files
@@ -443,6 +446,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/Laptop/Laptop_VS2013.vcxproj b/Laptop/Laptop_VS2013.vcxproj
index 48872100..81ab6e9b 100644
--- a/Laptop/Laptop_VS2013.vcxproj
+++ b/Laptop/Laptop_VS2013.vcxproj
@@ -101,6 +101,7 @@
+
@@ -182,6 +183,7 @@
+
@@ -194,7 +196,7 @@
-
+
diff --git a/Laptop/Laptop_VS2013.vcxproj.filters b/Laptop/Laptop_VS2013.vcxproj.filters
index d3134a23..b6d32538 100644
--- a/Laptop/Laptop_VS2013.vcxproj.filters
+++ b/Laptop/Laptop_VS2013.vcxproj.filters
@@ -258,6 +258,9 @@
Header Files
+
+ Header Files
+
@@ -527,7 +530,10 @@
Source Files
-
+
+ Source Files
+
+
Source Files
diff --git a/Laptop/PMC.cpp b/Laptop/PMC.cpp
new file mode 100644
index 00000000..24d67fb9
--- /dev/null
+++ b/Laptop/PMC.cpp
@@ -0,0 +1,834 @@
+/**
+* @file
+* @author Flugente (bears-pit.com)
+*/
+
+#ifdef PRECOMPILEDHEADERS
+#include "Laptop All.h"
+#else
+#include "laptop.h"
+#include "insurance.h"
+#include "insurance Contract.h"
+#include "WCheck.h"
+#include "Utilities.h"
+#include "WordWrap.h"
+#include "Cursors.h"
+#include "Line.h"
+#include "Insurance Text.h"
+#include "Encrypted File.h"
+#include "Text.h"
+#include "Multi Language Graphic Utils.h"
+#include "PMC.h"
+#include "random.h"
+#include "Interface.h"
+#include "Soldier Add.h"
+#include "Soldier Profile.h"
+#include "DropDown.h"
+#include "Overhead.h"
+#include "Map Screen Interface.h"
+#include "Quests.h"
+#include "finances.h"
+#include "Game Clock.h"
+#include "Animation Data.h"
+
+#include "SaveLoadGame.h"
+#include "GameVersion.h"
+#include "message.h"
+#include "Game Event Hook.h"
+#include "militia control.h"
+#include "Town Militia.h"
+#endif
+
+extern INT32 ReadFieldByField( HWFILE hFile, PTR pDest, UINT32 uiFieldSize, UINT32 uiElementSize, UINT32 uiCurByteCount );
+
+std::vector gPMCHiringEvents;
+PMCGlobalData gPMCData;
+
+#define MERCOMP_FONT_COLOR 2
+#define CAMPHIS_FONT_COLOR_RED FONT_MCOLOR_RED
+#define CAMPHIS_FONT_BIG FONT14ARIAL
+#define CAMPHIS_FONT_MED FONT12ARIAL
+#define CAMPHIS_FONT_SMALL FONT10ARIAL
+
+#define MERCOMP_FONT_SHADOW FONT_MCOLOR_WHITE
+
+#define CAMPAIGN_HISTORY_LINK_START_X LAPTOP_SCREEN_UL_X
+#define CAMPAIGN_HISTORY_LINK_START_Y LAPTOP_SCREEN_WEB_UL_Y + 5
+#define CAMPAIGN_HISTORY_LINK_TEXT_WIDTH 107
+#define CAMPAIGN_HISTORY_LINK_STEP_Y 14
+
+#define BACKGROUND_WIDTH 125
+#define CAMPAIGN_HISTORY_BACKGROUND_HEIGHT 100
+
+#define CAMPAIGN_HISTORY_BIG_TITLE_X 115 + LAPTOP_SCREEN_UL_X
+#define CAMPAIGN_HISTORY_BIG_TITLE_Y 10 + LAPTOP_SCREEN_WEB_UL_Y
+
+#define CAMPAIGN_HISTORY_SUBTITLE_X CAMPAIGN_HISTORY_BIG_TITLE_X
+#define CAMPAIGN_HISTORY_SUBTITLE_Y CAMPAIGN_HISTORY_BIG_TITLE_Y + 20
+
+#define NUM_LINKS 3
+#define MCA_START_CONTENT_Y (LAPTOP_SCREEN_WEB_UL_Y + NUM_LINKS * 17)
+
+
+extern UINT32 guiInsuranceBackGround;
+extern UINT32 guiInsuranceSmallTitleImage;
+extern UINT32 guiInsuranceBigRedLineImage;
+extern UINT32 guiMercCompareBulletImage;
+extern UINT32 guiMercCompareLogoImage;
+
+//link to the various pages
+MOUSE_REGION gLinkRegion_PMC[NUM_LINKS];
+
+void SelectLinkRegionCallBack_PMC( MOUSE_REGION * pRegion, INT32 iReason )
+{
+ if ( iReason & MSYS_CALLBACK_REASON_INIT )
+ {
+ }
+ else if ( iReason & MSYS_CALLBACK_REASON_LBUTTON_UP )
+ {
+ UINT32 uiLink = MSYS_GetRegionUserData( pRegion, 0 );
+
+ if ( uiLink == 0 )
+ guiCurrentLaptopMode = LAPTOP_MODE_PMC_MAIN;
+ else if ( uiLink == 1 )
+ guiCurrentLaptopMode = LAPTOP_MODE_PMC_CONTRACT_MILITIA;
+ else if ( uiLink == 2 )
+ guiCurrentLaptopMode = LAPTOP_MODE_BROKEN_LINK;
+ }
+ else if ( iReason & MSYS_CALLBACK_REASON_RBUTTON_UP )
+ {
+ }
+}
+
+void InitDefaults_PMC( )
+{
+ VOBJECT_DESC VObjectDesc;
+
+ // load the Insurance bullet graphic and add it
+ VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
+ FilenameForBPP( "LAPTOP\\bullet.sti", VObjectDesc.ImageFile );
+ CHECKV( AddVideoObject( &VObjectDesc, &guiMercCompareBulletImage ) );
+
+ // load the Flower Account Box graphic and add it
+ VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
+ FilenameForBPP( "LAPTOP\\BackGroundTile.sti", VObjectDesc.ImageFile );
+ CHECKV( AddVideoObject( &VObjectDesc, &guiInsuranceBackGround ) );
+
+ // load the red bar on the side of the page and add it
+ VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
+ FilenameForBPP( "LAPTOP\\LargeBar.sti", VObjectDesc.ImageFile );
+ CHECKV( AddVideoObject( &VObjectDesc, &guiInsuranceBigRedLineImage ) );
+
+ VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
+ FilenameForBPP( "LAPTOP\\PressLogos.sti", VObjectDesc.ImageFile );
+ CHECKV( AddVideoObject( &VObjectDesc, &guiMercCompareLogoImage ) );
+
+ UINT16 usPosX = CAMPAIGN_HISTORY_LINK_START_X;
+ UINT16 usPosY = CAMPAIGN_HISTORY_LINK_START_Y;
+ for ( int i = 0; i void DropDownTemplate::SetRefresh( ) {
+ fPMCContractRedraw = TRUE;
+}
+
+INT32 gPMCButtonImage[4];
+INT32 gPMCButton[4] = {-1, -1, -1, -1};
+BOOLEAN gPMCButtonCreated[4] = {FALSE, FALSE, FALSE, FALSE};
+
+INT32 gPMCHireButton = -1;
+BOOLEAN gPMCHireButtonCreated = FALSE;
+
+typedef struct
+{
+ UINT8 usBodyType;
+ UINT8 usHair;
+ UINT8 usSkin;
+ UINT8 usVest;
+ UINT8 usPants;
+
+ UINT8 usToHire;
+
+ UINT16 usCostEach;
+} PMCPersonnelData;
+
+PMCPersonnelData pmcdata[2];
+
+// how much does it cost to hire a militia from the PMC?
+UINT16 GetMilitiaCostPMC( UINT8 aSoldierClass )
+{
+ switch ( aSoldierClass )
+ {
+ case REGULAR_MILITIA:
+ return (4 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier) / gGameExternalOptions.iTrainingSquadSize + 7 * gGameExternalOptions.usDailyCostTownRegular;
+ break;
+
+ case ELITE_MILITIA:
+ // elites are upgradded regulars, so we pay for the basic + specail training
+ return ((4 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iRegularCostModifier) + (2 * gGameExternalOptions.iMilitiaTrainingCost * gGameExternalOptions.iVeteranCostModifier)) / gGameExternalOptions.iTrainingSquadSize + 7 * gGameExternalOptions.usDailyCostTownElite;
+ break;
+ }
+
+ return 0;
+}
+
+void InitPMCData( )
+{
+ pmcdata[0].usBodyType = Random( ADULTFEMALEMONSTER );
+ pmcdata[0].usHair = Random( 5 );
+ pmcdata[0].usSkin = Random( 4 );
+ pmcdata[0].usVest = 7;
+ pmcdata[0].usPants = 4;
+
+ pmcdata[0].usToHire = 0;
+
+ pmcdata[1].usBodyType = Random( ADULTFEMALEMONSTER );
+ pmcdata[1].usHair = Random( 5 );
+ pmcdata[1].usSkin = Random( 4 );
+ pmcdata[1].usVest = 6;
+ pmcdata[1].usPants = 4;
+
+ pmcdata[1].usToHire = 0;
+}
+
+CHAR16 gPMCSectorNamesstr[10][64];
+
+BOOLEAN EnterPMCContract( )
+{
+ InitDefaults_PMC( );
+
+ InitPMCData();
+
+ UINT8 count = 0;
+ std::vector > dropdownvector;
+
+ for ( INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX )
+ {
+ for ( INT16 sY = 1; sY < MAP_WORLD_Y - 1; ++sY )
+ {
+ if ( SectorOursAndPeaceful( sX, sY, 0 ) )
+ {
+ // if militia can land in this sector, add it to our list
+ // Is there a prison in this sector?
+ UINT16 prisonerbaselimit = 0;
+ for ( UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt )
+ {
+ // Is this facility here?
+ if ( gFacilityLocations[SECTOR( sX, sY )][cnt].fFacilityHere )
+ {
+ // we determine wether this is a prison by checking for usPrisonBaseLimit
+ if ( gFacilityTypes[cnt].usFacilityFlags & FACILITYTYPE_PMCENTRYPOINT )
+ {
+ GetSectorIDString( sX, sY, 0, gPMCSectorNamesstr[count], TRUE );
+ gPMCSectorNamesstr[count][63] = '/0';
+
+ dropdownvector.push_back( std::make_pair( SECTOR( sX, sY ), gPMCSectorNamesstr[count] ) );
+
+ ++count;
+
+ break;
+ }
+ }
+ }
+ }
+
+ if ( count >= 10 )
+ break;
+ }
+
+ if ( count >= 10 )
+ break;
+ }
+
+ if ( !dropdownvector.empty( ) )
+ {
+ DropDownTemplate::getInstance( ).SetEntries( dropdownvector );
+ DropDownTemplate::getInstance( ).SetHelpText( szPMCWebSite[TEXT_PMC_CONTRACT_DROPDOWNTEXT] );
+ DropDownTemplate::getInstance( ).Create( LAPTOP_SCREEN_UL_X + 200, MCA_START_CONTENT_Y + 150 );
+ }
+ else
+ {
+ DropDownTemplate::getInstance( ).ClearEntries( );
+ }
+
+ return(TRUE);
+}
+
+void ExitPMCContract( )
+{
+ for ( int i = 0; i < 4; ++i )
+ {
+ if ( gPMCButtonCreated[i] )
+ {
+ // delete militia panel bottom
+ RemoveButton( gPMCButton[i] );
+ UnloadButtonImage( gPMCButtonImage[i] );
+
+ gPMCButtonCreated[i] = FALSE;
+ }
+ }
+
+ DropDownTemplate::getInstance( ).Destroy( );
+
+ if ( gPMCHireButtonCreated )
+ {
+ RemoveButton( gPMCHireButton );
+ gPMCHireButtonCreated = FALSE;
+ }
+
+ RemoveDefaults_PMC( );
+}
+
+void HandlePMCContract( )
+{
+ if ( fPMCContractRedraw )
+ {
+ RenderPMCContract( );
+ fPMCContractRedraw = FALSE;
+ }
+}
+
+
+BOOLEAN RenderMilitiaExamples( )
+{
+ VOBJECT_DESC VObjectDesc;
+ HVOBJECT hHandle;
+ UINT32 uiGraphicHandle;
+
+ // regular militia
+ UINT16 usPosX = LAPTOP_SCREEN_UL_X;
+ UINT16 usPosY = MCA_START_CONTENT_Y + 20;
+
+ // load it
+ VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
+
+ // Pick images based on body type
+ switch ( pmcdata[0].usBodyType )
+ {
+ case REGMALE: FilenameForBPP( "Laptop\\IMPSmallMercImages.sti", VObjectDesc.ImageFile ); break;
+ case BIGMALE: FilenameForBPP( "Laptop\\IMPBigMercImages.sti", VObjectDesc.ImageFile ); break;
+ case STOCKYMALE: FilenameForBPP( "Laptop\\IMPBigMercImages.sti", VObjectDesc.ImageFile ); break;
+ case REGFEMALE: FilenameForBPP( "Laptop\\IMPFemaleMercImages.sti", VObjectDesc.ImageFile ); break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ // safety check if loaded
+ CHECKF( AddVideoObject( &VObjectDesc, &uiGraphicHandle ) );
+
+ // Get it
+ GetVideoObject( &hHandle, uiGraphicHandle );
+
+ // show background first
+ BltVideoObject( FRAME_BUFFER, hHandle, 0, usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+
+ // show skin (1 - 4)
+ BltVideoObject( FRAME_BUFFER, hHandle, (pmcdata[0].usSkin + 1), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+ // show head (5 - 9)
+ BltVideoObject( FRAME_BUFFER, hHandle, (pmcdata[0].usHair + 5), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+ // show vest (10 - 20)
+ BltVideoObject( FRAME_BUFFER, hHandle, (pmcdata[0].usVest + 10), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+ // show pants (21 - 26)
+ BltVideoObject( FRAME_BUFFER, hHandle, (pmcdata[0].usPants + 21), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+
+ DeleteVideoObjectFromIndex( uiGraphicHandle );
+
+ // veteran militia
+ usPosX = LAPTOP_SCREEN_UL_X + 250;
+
+ // load it
+ VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
+
+ // Pick images based on body type
+ switch ( pmcdata[1].usBodyType )
+ {
+ case REGMALE: FilenameForBPP( "Laptop\\IMPSmallMercImages.sti", VObjectDesc.ImageFile ); break;
+ case BIGMALE: FilenameForBPP( "Laptop\\IMPBigMercImages.sti", VObjectDesc.ImageFile ); break;
+ case STOCKYMALE: FilenameForBPP( "Laptop\\IMPBigMercImages.sti", VObjectDesc.ImageFile ); break;
+ case REGFEMALE: FilenameForBPP( "Laptop\\IMPFemaleMercImages.sti", VObjectDesc.ImageFile ); break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ // safety check if loaded
+ CHECKF( AddVideoObject( &VObjectDesc, &uiGraphicHandle ) );
+
+ // Get it
+ GetVideoObject( &hHandle, uiGraphicHandle );
+
+ // show background first
+ BltVideoObject( FRAME_BUFFER, hHandle, 0, usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+
+ // show skin (1 - 4)
+ BltVideoObject( FRAME_BUFFER, hHandle, (pmcdata[1].usSkin + 1), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+ // show head (5 - 9)
+ BltVideoObject( FRAME_BUFFER, hHandle, (pmcdata[1].usHair + 5), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+ // show vest (10 - 20)
+ BltVideoObject( FRAME_BUFFER, hHandle, (pmcdata[1].usVest + 10), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+ // show pants (21 - 26)
+ BltVideoObject( FRAME_BUFFER, hHandle, (pmcdata[1].usPants + 21), usPosX, usPosY, VO_BLT_SRCTRANSPARENCY, NULL );
+
+ DeleteVideoObjectFromIndex( uiGraphicHandle );
+
+ return (TRUE);
+}
+
+void PMCButtonCallback( GUI_BUTTON *btn, INT32 reason )
+{
+ if ( reason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
+ {
+ btn->uiFlags |= (BUTTON_CLICKED_ON);
+ }
+ else if ( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
+ {
+ if ( btn->uiFlags & BUTTON_CLICKED_ON )
+ {
+ btn->uiFlags &= ~(BUTTON_CLICKED_ON);
+
+ if ( btn->IDNum == gPMCButton[0] )
+ pmcdata[0].usToHire = min( pmcdata[0].usToHire + 1, gPMCData.usRegularsAvailable );
+ else if ( btn->IDNum == gPMCButton[1] )
+ pmcdata[0].usToHire = max( pmcdata[0].usToHire - 1, 0 );
+ else if ( btn->IDNum == gPMCButton[2] )
+ pmcdata[1].usToHire = min( pmcdata[1].usToHire + 1, gPMCData.usVeteransAvailable );
+ else if ( btn->IDNum == gPMCButton[3] )
+ pmcdata[1].usToHire = max( pmcdata[1].usToHire - 1, 0 );
+
+ RenderPMCContract();
+ }
+ }
+}
+
+void PMCConfirmationCallback( UINT8 val )
+{
+ fPMCContractRedraw = TRUE;
+}
+
+void PMCTeamHireCallback( GUI_BUTTON *btn, INT32 reason )
+{
+ if ( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
+ {
+ AddTransactionToPlayersBook( PMC_CONTRACT, 0, GetWorldTotalMin( ), (-1) * (INT32)(pmcdata[0].usToHire * GetMilitiaCostPMC( REGULAR_MILITIA ) + pmcdata[1].usToHire * GetMilitiaCostPMC( ELITE_MILITIA )) );
+
+ PMCReinforcesHireEvent hiringevent;
+
+ // look for a free ID
+ UINT8 id = 0;
+ BOOLEAN found = FALSE;
+ for ( UINT8 i = 0; i < 255; ++i )
+ {
+ found = TRUE;
+
+ std::vector::iterator itend = gPMCHiringEvents.end();
+ for ( std::vector::iterator it = gPMCHiringEvents.begin( ); it != itend; ++it )
+ {
+ if ( (*it).usId == id )
+ {
+ ++id;
+ found = FALSE;
+ break;
+ }
+ }
+
+ if ( found = TRUE )
+ break;
+ }
+
+ hiringevent.usId = id;
+ hiringevent.usRegulars = pmcdata[0].usToHire;
+ hiringevent.usVeterans = pmcdata[1].usToHire;
+ hiringevent.usSectorToArrive = (UINT8)DropDownTemplate::getInstance( ).GetSelectedEntryKey( );
+ hiringevent.usTimeToArrive = GetWorldTotalMin() + 1440;
+
+ gPMCData.usRegularsHired += hiringevent.usRegulars;
+ gPMCData.usVeteransHired += hiringevent.usVeterans;
+ gPMCData.usTotalMoneyEarned += pmcdata[0].usToHire * GetMilitiaCostPMC( REGULAR_MILITIA ) + pmcdata[1].usToHire * GetMilitiaCostPMC( ELITE_MILITIA );
+
+ gPMCHiringEvents.push_back( hiringevent );
+
+ AddStrategicEvent( EVENT_PMC_REINFORCEMENT_ARRIVAL, hiringevent.usTimeToArrive, hiringevent.usId );
+
+ gPMCData.usRegularsAvailable -= pmcdata[0].usToHire;
+ pmcdata[0].usToHire = 0;
+
+ gPMCData.usVeteransAvailable -= pmcdata[1].usToHire;
+ pmcdata[1].usToHire = 0;
+
+ CHAR16 sString[256];
+ swprintf( sString, szPMCWebSite[TEXT_PMC_CONFIRMATION], ((GetWorldTotalMin( ) + 1440) % 1440) / 60, ((GetWorldTotalMin( ) + 1440) % 1440) % 60 );
+
+ DoLowerScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, PMCConfirmationCallback );
+ }
+}
+
+void RenderPMCContract( )
+{
+ CHAR16 sText[800];
+ swprintf( sText, L"" );
+ UINT16 usPosX, usPosY;
+
+ DisplayDefaults_PMC( );
+
+ SetFontShadow( MERCOMP_FONT_SHADOW );
+
+ usPosX = LAPTOP_SCREEN_UL_X;
+ usPosY = MCA_START_CONTENT_Y;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_CONTRACT_TEAM_INTRO] );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ // show example pics of militia
+ RenderMilitiaExamples( );
+
+ for ( int i = 0; i < 4; ++i )
+ {
+ if ( gPMCButtonCreated[i] )
+ {
+ // delete militia panel bottom
+ RemoveButton( gPMCButton[i] );
+ UnloadButtonImage( gPMCButtonImage[i] );
+
+ gPMCButtonCreated[i] = FALSE;
+ }
+ }
+
+ gPMCButtonImage[0] = LoadButtonImage( "INTERFACE\\plusminusbuttons.sti", -1, 0, -1, 0, -1 );
+ gPMCButtonImage[1] = LoadButtonImage( "INTERFACE\\plusminusbuttons.sti", -1, 1, -1, 1, -1 );
+ gPMCButtonImage[2] = LoadButtonImage( "INTERFACE\\plusminusbuttons.sti", -1, 0, -1, 0, -1 );
+ gPMCButtonImage[3] = LoadButtonImage( "INTERFACE\\plusminusbuttons.sti", -1, 1, -1, 1, -1 );
+
+ // regulars
+ usPosX = LAPTOP_SCREEN_UL_X + 120;
+ usPosY = MCA_START_CONTENT_Y + 20;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_REGULAR] );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ usPosY += 10;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_DETAIL], gPMCData.usRegularsAvailable, GetMilitiaCostPMC( REGULAR_MILITIA ) );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ gPMCButton[0] = QuickCreateButton( gPMCButtonImage[0], usPosX, usPosY, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)PMCButtonCallback );
+ gPMCButtonCreated[0] = TRUE;
+ gPMCButton[1] = QuickCreateButton( gPMCButtonImage[1], usPosX + 20, usPosY, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)PMCButtonCallback );
+ gPMCButtonCreated[1] = TRUE;
+
+ usPosY += 20;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_DETAIL + 1], pmcdata[0].usToHire );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_DETAIL + 2], pmcdata[0].usToHire * GetMilitiaCostPMC( REGULAR_MILITIA ) );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ // veterans
+ usPosX = LAPTOP_SCREEN_UL_X + 370;
+ usPosY = MCA_START_CONTENT_Y + 20;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_VETERAN] );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ usPosY += 10;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_DETAIL], gPMCData.usVeteransAvailable, GetMilitiaCostPMC( ELITE_MILITIA ) );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ gPMCButton[2] = QuickCreateButton( gPMCButtonImage[2], usPosX, usPosY, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)PMCButtonCallback );
+ gPMCButtonCreated[2] = TRUE;
+ gPMCButton[3] = QuickCreateButton( gPMCButtonImage[3], usPosX + 20, usPosY, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, BtnGenericMouseMoveButtonCallback, (GUI_CALLBACK)PMCButtonCallback );
+ gPMCButtonCreated[3] = TRUE;
+
+ usPosY += 20;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_DETAIL + 1], pmcdata[1].usToHire );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_DETAIL + 2], pmcdata[1].usToHire * GetMilitiaCostPMC( REGULAR_MILITIA ) );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ usPosX = LAPTOP_SCREEN_UL_X;
+ usPosY = MCA_START_CONTENT_Y + 158;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_SELECTAREA] );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ usPosY += 10;
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_TOTALCOST], pmcdata[0].usToHire * GetMilitiaCostPMC( REGULAR_MILITIA ) + pmcdata[1].usToHire * GetMilitiaCostPMC( ELITE_MILITIA ) );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ swprintf( sText, szPMCWebSite[TEXT_PMC_ETA], ((GetWorldTotalMin( ) + 1440) % 1440) / 60, ((GetWorldTotalMin( ) + 1440) % 1440) % 60 );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+
+ if ( gPMCHireButtonCreated )
+ {
+ RemoveButton( gPMCHireButton );
+ gPMCHireButtonCreated = FALSE;
+ }
+
+ if ( DropDownTemplate::getInstance().HasEntries() )
+ {
+ gPMCHireButton = CreateTextButton( szPMCWebSite[TEXT_PMC_CONTRACTBUTTON], CAMPHIS_FONT_MED, FONT_YELLOW, FONT_BLACK, BUTTON_USE_DEFAULT,
+ usPosX, usPosY, 100, 20, BUTTON_TOGGLE, MSYS_PRIORITY_HIGH, DEFAULT_MOVE_CALLBACK, PMCTeamHireCallback );
+ gPMCHireButtonCreated = TRUE;
+ }
+ else
+ {
+ swprintf( sText, szPMCWebSite[TEXT_PMC_NODROPOFF] );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+ }
+
+ usPosY += 50;
+
+ // if we hired personnel and they are inbound, show the next deployment
+ if ( !gPMCHiringEvents.empty() )
+ {
+ CHAR16 sectorname[64];
+ GetSectorIDString( SECTORX( gPMCHiringEvents[0].usSectorToArrive ), SECTORY( gPMCHiringEvents[0].usSectorToArrive ), 0, sectorname, TRUE );
+ swprintf( sText, szPMCWebSite[TEXT_PMC_NEXTDEPLOYMENT], gPMCHiringEvents[0].usRegulars, gPMCHiringEvents[0].usVeterans, sectorname, (gPMCHiringEvents[0].usTimeToArrive % 1440) / 60, (gPMCHiringEvents[0].usTimeToArrive % 1440) % 60, 1 + (gPMCHiringEvents[0].usTimeToArrive / 1440) );
+ usPosY += DisplayWrappedString( usPosX, usPosY, LAPTOP_SCREEN_LR_X - LAPTOP_SCREEN_UL_X, 2, CAMPHIS_FONT_MED, MERCOMP_FONT_COLOR, sText, FONT_MCOLOR_BLACK, FALSE, 0 );
+ }
+
+ DropDownTemplate::getInstance( ).Display( );
+
+ MarkButtonsDirty( );
+ RenderWWWProgramTitleBar( );
+ InvalidateRegion( LAPTOP_SCREEN_UL_X, LAPTOP_SCREEN_WEB_UL_Y, LAPTOP_SCREEN_LR_X, LAPTOP_SCREEN_WEB_LR_Y );
+}
+////////////////////////// CONTRACT PAGE ////////////////////////////////
+
+
+void GameInitPMC()
+{
+ gPMCData.usTotalMoneyEarned = 0;
+ gPMCData.usRegularsHired = 0;
+ gPMCData.usVeteransHired = 0;
+ gPMCData.usRegularsAvailable = Random( gGameExternalOptions.usPMCMaxRegulars );
+ gPMCData.usVeteransAvailable = Random( gGameExternalOptions.usPMCMaxVeterans );
+}
+
+// the PMC replenishes personnel
+void HourlyUpdatePMC( )
+{
+ if ( Chance( 50 ) )
+ gPMCData.usRegularsAvailable = min( gPMCData.usRegularsAvailable + 1, gGameExternalOptions.usPMCMaxRegulars );
+
+ if ( Chance( 30 ) )
+ gPMCData.usVeteransAvailable = min( gPMCData.usVeteransAvailable + 1, gGameExternalOptions.usPMCMaxVeterans );
+}
+
+void HandlePMCArrival( UINT8 usId )
+{
+ std::vector::iterator itend = gPMCHiringEvents.end( );
+ for ( std::vector::iterator it = gPMCHiringEvents.begin( ); it != itend; ++it )
+ {
+ if ( (*it).usId == usId )
+ {
+ // the militia we ordered have arrived!
+ StrategicAddMilitiaToSector( SECTORX( (*it).usSectorToArrive ), SECTORY( (*it).usSectorToArrive ), REGULAR_MILITIA, (*it).usRegulars );
+ StrategicAddMilitiaToSector( SECTORX( (*it).usSectorToArrive ), SECTORY( (*it).usSectorToArrive ), ELITE_MILITIA, (*it).usVeterans );
+
+ // if this is in the current sector, militia will be updated
+ ResetMilitia( );
+
+ GetSectorIDString( SECTORX( (*it).usSectorToArrive ), SECTORY( (*it).usSectorToArrive ), 0, gPMCSectorNamesstr[0], TRUE );
+
+ ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPMCWebSite[TEXT_PMC_ARRIVAL], gPMCSectorNamesstr[0] );
+
+ // delete event, we're done here
+ gPMCHiringEvents.erase( it );
+
+ return;
+ }
+ }
+}
+
+// it could happen that we load events incorrectly. To detect that early, we write an extra eyecacher befoer and after the list of events. Should we fail to read it correctly, we will knowm where to look.
+UINT32 gPMCSaveCheck = 0xF123456F;
+BOOLEAN SavePMC( HWFILE hwFile )
+{
+ UINT32 uiNumBytesWritten = 0;
+
+ if ( !FileWrite( hwFile, &gPMCData, sizeof(PMCGlobalData), &uiNumBytesWritten ) )
+ return(FALSE);
+
+ // in order to save a vector, we first save its size and then its content
+ UINT32 size = gPMCHiringEvents.size( );
+ if ( !FileWrite( hwFile, &size, sizeof(UINT32), &uiNumBytesWritten ) )
+ return(FALSE);
+
+ if ( !FileWrite( hwFile, &gPMCSaveCheck, sizeof(UINT32), &uiNumBytesWritten ) )
+ return(FALSE);
+
+ for ( UINT32 i = 0; i < size; ++i )
+ {
+ if ( !FileWrite( hwFile, &gPMCHiringEvents[i], sizeof(PMCReinforcesHireEvent), &uiNumBytesWritten ) )
+ return(FALSE);
+ }
+
+ if ( !FileWrite( hwFile, &gPMCSaveCheck, sizeof(UINT32), &uiNumBytesWritten ) )
+ return(FALSE);
+
+ return(TRUE);
+}
+
+BOOLEAN LoadPMC( HWFILE hwFile )
+{
+ if ( guiCurrentSaveGameVersion >= PMC_WEBSITE )
+ {
+ gPMCHiringEvents.clear();
+
+ UINT32 numBytesRead = 0;
+
+ numBytesRead = ReadFieldByField( hwFile, &gPMCData, sizeof(gPMCData), sizeof(PMCGlobalData), numBytesRead );
+
+ UINT32 size = 0;
+ numBytesRead = ReadFieldByField( hwFile, &size, sizeof(size), sizeof(UINT32), numBytesRead );
+
+ UINT32 safetycheck1 = 0;
+ numBytesRead = ReadFieldByField( hwFile, &safetycheck1, sizeof(safetycheck1), sizeof(UINT32), numBytesRead );
+
+ for ( UINT32 i = 0; i < size; ++i )
+ {
+ PMCReinforcesHireEvent event;
+ numBytesRead = ReadFieldByField( hwFile, &event, sizeof(event), sizeof(PMCReinforcesHireEvent), 0 );
+
+ gPMCHiringEvents.push_back( event );
+ }
+
+ UINT32 safetycheck2 = 0;
+ numBytesRead = ReadFieldByField( hwFile, &safetycheck2, sizeof(safetycheck2), sizeof(UINT32), numBytesRead );
+
+ if ( safetycheck1 != gPMCSaveCheck || safetycheck2 != gPMCSaveCheck )
+ {
+ ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Eyecatcher corruption detected while loading PMC data!" );
+ return FALSE;
+ }
+ }
+ else
+ {
+ // if loading an older savegame, initialise the PMC
+ GameInitPMC();
+ }
+
+ return TRUE;
+}
\ No newline at end of file
diff --git a/Laptop/PMC.h b/Laptop/PMC.h
new file mode 100644
index 00000000..1e9fb46e
--- /dev/null
+++ b/Laptop/PMC.h
@@ -0,0 +1,56 @@
+#ifndef __PMC_H
+#define __PMC_H
+
+/**
+* @file
+* @author Flugente (bears-pit.com)
+*/
+
+// main page (explains what this is all about)
+BOOLEAN EnterPMCMain( );
+void ExitPMCMain( );
+void HandlePMCMain( );
+void RenderPMCMain( );
+
+// on this site you can conclude a contract with the WHO to get strategic data on diseases
+BOOLEAN EnterPMCContract( );
+void ExitPMCContract( );
+void HandlePMCContract( );
+void RenderPMCContract( );
+
+// in case we hire miltia from the PMC, we have to know how many, where and when they should arrive
+typedef struct
+{
+ UINT8 usId; // number of this hiring event
+ UINT8 usSectorToArrive;
+ UINT8 usRegulars;
+ UINT8 usVeterans;
+
+ UINT32 usTimeToArrive;
+} PMCReinforcesHireEvent;
+
+extern std::vector gPMCHiringEvents;
+
+// global data on the PMC
+typedef struct
+{
+ UINT32 usTotalMoneyEarned;
+
+ UINT16 usRegularsHired;
+ UINT16 usVeteransHired;
+
+ UINT8 usRegularsAvailable;
+ UINT8 usVeteransAvailable;
+ UINT8 usUnused[2];
+} PMCGlobalData;
+
+extern PMCGlobalData gPMCData;
+
+void GameInitPMC();
+void HourlyUpdatePMC();
+void HandlePMCArrival( UINT8 usId );
+
+BOOLEAN SavePMC( HWFILE hwFile );
+BOOLEAN LoadPMC( HWFILE hwFile );
+
+#endif //__PMC_H
diff --git a/Laptop/email.cpp b/Laptop/email.cpp
index 1395653b..6db1390e 100644
--- a/Laptop/email.cpp
+++ b/Laptop/email.cpp
@@ -3682,18 +3682,18 @@ BOOLEAN HandleMailSpecialMessages( UINT16 usMessageId, INT32 *iResults, EmailPtr
break;
//Dealtar's Airport Externalization
case BOBBYR_SHIPMENT_ARRIVED:
- wstring wstrMail;
- wstring::size_type index;
- CHAR16 szMail[MAIL_STRING_SIZE];
-
if (!pMessageRecordList)
{
+ wstring wstrMail;
+ wstring::size_type index;
+ CHAR16 szMail[MAIL_STRING_SIZE];
+
// WANNE.MAIL: Fix
gusCurShipmentDestinationID = -1; // Reset
gusCurShipmentDestinationID = pMail->iCurrentShipmentDestinationID;
// Loop through each line of the shipment EDT-file
- for (int i = 0; i < BOBBYR_SHIPMENT_ARRIVED_LENGTH; i++)
+ for (int i = 0; i < BOBBYR_SHIPMENT_ARRIVED_LENGTH; ++i)
{
wstrMail.clear();
LoadEncryptedDataFromFile("BINARYDATA\\Email.edt", szMail, MAIL_STRING_SIZE *usMessageId, MAIL_STRING_SIZE);
@@ -3724,12 +3724,17 @@ BOOLEAN HandleMailSpecialMessages( UINT16 usMessageId, INT32 *iResults, EmailPtr
AddEmailRecordToList((STR16)wstrMail.c_str());
- usMessageId++;
+ ++usMessageId;
}
}
giPrevMessageId = giMessageId;
break;
+ case(PMC_INTRO) :
+ SetBookMark( PMC_BOOKMARK );
+ fReDrawScreenFlag = TRUE;
+ break;
+
#endif
}
diff --git a/Laptop/email.h b/Laptop/email.h
index 3478f204..03f79c1b 100644
--- a/Laptop/email.h
+++ b/Laptop/email.h
@@ -363,6 +363,9 @@
#define JOHN_KULBA_MISSED_FLIGHT_3 ( JOHN_KULBA_MISSED_FLIGHT_2 + JOHN_KULBA_MISSED_FLIGHT_2_LENGTH )
#define JOHN_KULBA_MISSED_FLIGHT_3_LENGTH 3
+ #define PMC_INTRO (JOHN_KULBA_MISSED_FLIGHT_3 + JOHN_KULBA_MISSED_FLIGHT_3_LENGTH)
+ #define PMC_INTRO_LENGTH 3
+
#endif
// WANNE: New 1.13 MERC merc mail text for level up that Speck sends
@@ -507,6 +510,7 @@ enum {
#ifdef JA2UB
MAIL_MIGUEL,
#endif
+ PMC,
};
// the length of the subject in char
diff --git a/Laptop/finances.cpp b/Laptop/finances.cpp
index 4a2fe82d..1273892e 100644
--- a/Laptop/finances.cpp
+++ b/Laptop/finances.cpp
@@ -1455,7 +1455,6 @@ void IncrementCurrentPageFinancialDisplay( void )
void ProcessTransactionString(STR16 pString, FinanceUnitPtr pFinance)
{
-
switch( pFinance->ubCode)
{
case ACCRUED_INTEREST:
@@ -1595,9 +1594,12 @@ void ProcessTransactionString(STR16 pString, FinanceUnitPtr pFinance)
case WHO_SUBSCRIPTION:
swprintf( pString, L"%s", pTransactionText[WHO_SUBSCRIPTION] );
break;
+
+ // Flugente: a contract with a PMC
+ case PMC_CONTRACT:
+ swprintf( pString, L"%s", pTransactionText[PMC_CONTRACT] );
+ break;
}
-
-
}
diff --git a/Laptop/finances.h b/Laptop/finances.h
index 9ee473a4..d77a362a 100644
--- a/Laptop/finances.h
+++ b/Laptop/finances.h
@@ -55,6 +55,7 @@ enum
MILITIA_UPKEEP, // HEADROCK HAM 3.6: Militia Upkeep Costs (daily payment)
PRISONER_RANSOM, // Flugente: ransom for released prisoners
WHO_SUBSCRIPTION, // Flugente: subscription do WHO data
+ PMC_CONTRACT, // Flugente: hired militia from a PMC
TEXT_NUM_FINCANCES
};
diff --git a/Laptop/laptop.cpp b/Laptop/laptop.cpp
index 24a6da9d..d1019d06 100644
--- a/Laptop/laptop.cpp
+++ b/Laptop/laptop.cpp
@@ -89,6 +89,7 @@
#include "CampaignHistory_Summary.h" // added by Flugente
#include "MercCompare.h" // added by Flugente
#include "WHO.h" // added by Flugente
+ #include "PMC.h" // added by Flugente
#endif
#include "connect.h"
@@ -1485,6 +1486,18 @@ void RenderLaptop()
case LAPTOP_MODE_WHO_TIPS:
RenderWHOTips( );
break;
+
+ case LAPTOP_MODE_PMC_MAIN:
+ RenderPMCMain( );
+ break;
+
+ case LAPTOP_MODE_PMC_CONTRACT_MILITIA:
+ RenderPMCContract( );
+ break;
+
+ case LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL:
+ RenderPMCContract( );
+ break;
}
if( guiCurrentLaptopMode >= LAPTOP_MODE_WWW )
@@ -1930,6 +1943,17 @@ void EnterNewLaptopMode()
EnterWHOTips( );
break;
+ case LAPTOP_MODE_PMC_MAIN:
+ EnterPMCMain( );
+ break;
+
+ case LAPTOP_MODE_PMC_CONTRACT_MILITIA:
+ EnterPMCContract( );
+ break;
+
+ case LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL:
+ EnterPMCContract( );
+ break;
}
// first time using webbrowser in this laptop session
@@ -2191,6 +2215,18 @@ void HandleLapTopHandles()
case LAPTOP_MODE_WHO_TIPS:
HandleWHOTips( );
break;
+
+ case LAPTOP_MODE_PMC_MAIN:
+ HandlePMCMain( );
+ break;
+
+ case LAPTOP_MODE_PMC_CONTRACT_MILITIA:
+ HandlePMCContract( );
+ break;
+
+ case LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL:
+ HandlePMCContract( );
+ break;
}
}
@@ -2761,6 +2797,18 @@ UINT32 ExitLaptopMode(UINT32 uiMode)
case LAPTOP_MODE_WHO_TIPS:
ExitWHOTips( );
break;
+
+ case LAPTOP_MODE_PMC_MAIN:
+ ExitPMCMain( );
+ break;
+
+ case LAPTOP_MODE_PMC_CONTRACT_MILITIA:
+ ExitPMCContract( );
+ break;
+
+ case LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL:
+ ExitPMCContract( );
+ break;
}
if( ( uiMode != LAPTOP_MODE_NONE )&&( uiMode < LAPTOP_MODE_WWW ) )
@@ -3748,6 +3796,24 @@ void SetBookMark(INT32 iBookId)
}
}
+BOOLEAN IsBookMarkSet( INT32 iBookId )
+{
+ INT32 iCounter = 0;
+ while ( LaptopSaveInfo.iBookMarkList[iCounter] != -1 )
+ {
+ // move through list until empty
+ if ( LaptopSaveInfo.iBookMarkList[iCounter] == iBookId )
+ {
+ // found it, return
+ return TRUE;
+ }
+
+ ++iCounter;
+ }
+
+ return FALSE;
+}
+
BOOLEAN RemoveBookMark( INT32 iBookId )
{
@@ -4357,6 +4423,27 @@ if( (gubQuest[ QUEST_FIX_LAPTOP ] != QUESTINPROGRESS) || (gGameUBOptions.LaptopQ
}
}
break;
+
+ case PMC_BOOKMARK:
+ {
+ guiCurrentWWWMode = LAPTOP_MODE_PMC_MAIN;
+ guiCurrentLaptopMode = LAPTOP_MODE_PMC_MAIN;
+
+ // do we have to have a World Wide Wait
+ if ( LaptopSaveInfo.fVisitedBookmarkAlready[PMC_BOOKMARK] == FALSE )
+ {
+ // reset flag and set load pending flag
+ LaptopSaveInfo.fVisitedBookmarkAlready[PMC_BOOKMARK] = TRUE;
+ fLoadPendingFlag = TRUE;
+ }
+ else
+ {
+ // fast reload
+ fLoadPendingFlag = TRUE;
+ fFastLoadFlag = TRUE;
+ }
+ }
+ break;
}
#ifdef JA2UB
diff --git a/Laptop/laptop.h b/Laptop/laptop.h
index 09094fab..595e7bb3 100644
--- a/Laptop/laptop.h
+++ b/Laptop/laptop.h
@@ -22,6 +22,7 @@ void DrawButtonText();
void InitBookMarkList();
void SetBookMark(INT32 iBookId);
void RemoveBookmark(INT32 iBookId);
+BOOLEAN IsBookMarkSet( INT32 iBookId );
BOOLEAN LeaveLapTopScreen( );
void SetLaptopExitScreen( UINT32 uiExitScreen );
void SetLaptopNewGameFlag( );
@@ -155,6 +156,11 @@ enum
LAPTOP_MODE_WHO_MAIN,
LAPTOP_MODE_WHO_CONTRACT,
LAPTOP_MODE_WHO_TIPS,
+
+ // Flugente: PMC
+ LAPTOP_MODE_PMC_MAIN,
+ LAPTOP_MODE_PMC_CONTRACT_MILITIA,
+ LAPTOP_MODE_PMC_CONTRACT_INDIVIDUAL,
LAPTOP_MODE_BOBBYR_SHIPMENTS,
@@ -234,6 +240,7 @@ enum{
CAMPAIGNHISTORY_BOOKMARK, // added by Flugente
MERCCOMPARE_BOOKMARK, // added by Flugente
WHO_BOOKMARK, // added by Flugente
+ PMC_BOOKMARK, // added by Flugente
TEXT_NUM_LAPTOP_BOOKMARKS
};
diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp
index 555c26d5..04f1446b 100644
--- a/SaveLoadGame.cpp
+++ b/SaveLoadGame.cpp
@@ -115,6 +115,7 @@
#include "Encyclopedia_new.h"
#include "CampaignStats.h" // added by Flugente
#include "DynamicDialogue.h" // added by Flugente
+ #include "PMC.h" // added by Flugente
#endif
#include "BobbyR.h"
@@ -4305,6 +4306,9 @@ BOOLEAN SaveGame( int ubSaveGameID, STR16 pGameDesc )
{
ScreenMsg( FONT_MCOLOR_WHITE, MSG_ERROR, L"ERROR writing Campaign Stats");
goto FAILED_TO_SAVE;
+#ifdef JA2BETAVERSION
+ SaveGameFilePosition( FileGetPos( hFile ), "Campaign Stats" );
+#endif
}
// Flugente: dynamic dialogue
@@ -4314,9 +4318,12 @@ BOOLEAN SaveGame( int ubSaveGameID, STR16 pGameDesc )
goto FAILED_TO_SAVE;
}
-#ifdef JA2BETAVERSION
- SaveGameFilePosition( FileGetPos( hFile ), "Campaign Stats" );
-#endif
+ // Flugente: PMC
+ if ( !SavePMC( hFile ) )
+ {
+ ScreenMsg( FONT_MCOLOR_WHITE, MSG_ERROR, L"ERROR writing PMC data" );
+ goto FAILED_TO_SAVE;
+ }
//Close the saved game file
FileClose( hFile );
@@ -5996,6 +6003,18 @@ BOOLEAN LoadSavedGame( int ubSavedGameID )
return(FALSE);
}
}
+
+ uiRelEndPerc += 1;
+ SetRelativeStartAndEndPercentage( 0, uiRelStartPerc, uiRelEndPerc, L"Load PMC data ..." );
+ RenderProgressBar( 0, 100 );
+ uiRelStartPerc = uiRelEndPerc;
+
+ if ( !LoadPMC( hFile ) )
+ {
+ DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "PMC data failed" ) );
+ FileClose( hFile );
+ return(FALSE);
+ }
//
//Close the saved game file
diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp
index 9952c9b0..c098fe24 100644
--- a/Strategic/Assignments.cpp
+++ b/Strategic/Assignments.cpp
@@ -66,9 +66,10 @@
#include "Tactical Save.h" // added by Flugente
#include "Campaign Types.h" // added by Flugente
#include "Strategic Town Loyalty.h"
- #include "DynamicDialogue.h" // added by Flugente
+ #include "DynamicDialogue.h" // added by Flugente
#include "Disease.h" // added by Flugente
#include "Queen Command.h" // added by Flugente
+ #include "PMC.h" // added by Flugente
#endif
#include
#include
@@ -2540,6 +2541,9 @@ void UpdateAssignments()
HandleDiseaseDiagnosis(); // this must come after HandleDisease() so we discover fresh infections
HandleDiseaseSectorTreatment();
+ // Flugente: PMC recruits new personnel
+ HourlyUpdatePMC();
+
// check to see if anyone is done healing?
UpdatePatientsWhoAreDoneHealing( );
diff --git a/Strategic/Campaign Types.h b/Strategic/Campaign Types.h
index e48c2b72..a0290ecf 100644
--- a/Strategic/Campaign Types.h
+++ b/Strategic/Campaign Types.h
@@ -281,6 +281,9 @@ typedef struct FACILITYASSIGNMENTTYPE
} FACILITYASSIGNMENTTYPE;
+// Flugente: facilitytype properties
+#define FACILITYTYPE_PMCENTRYPOINT 0x00000001 // militia hired from the PMC can only enter Arulco in sectors with facilites with this property
+
// HEADROCK HAM 3.5: Facility Type
typedef struct FACILITYTYPE
{
@@ -295,6 +298,8 @@ typedef struct FACILITYTYPE
UINT16 usMilitiaTraining; // Percentage effectiveness of Militia training (100 = normal)
UINT16 usMobileMilitiaTraining; // Percentage effectiveness of Mobile Militia training (100 = normal)
+ UINT32 usFacilityFlags; // flagmask for various facility properties
+
FACILITYASSIGNMENTTYPE AssignmentData[ NUM_FACILITY_ASSIGNMENTS ]; // Data about possible assignments that can be done here
} FACILITYTYPE;
diff --git a/Strategic/Game Event Hook.cpp b/Strategic/Game Event Hook.cpp
index 00b90ed8..7c51753a 100644
--- a/Strategic/Game Event Hook.cpp
+++ b/Strategic/Game Event Hook.cpp
@@ -45,6 +45,7 @@
#include "Campaign.h"
#include "PostalService.h"
#include "MilitiaSquads.h"
+ #include "PMC.h" // added by Flugente
#endif
#include "connect.h"
@@ -509,6 +510,16 @@ BOOLEAN ExecuteStrategicEvent( STRATEGICEVENT *pEvent )
case EVENT_MILITIA_MOVEMENT_ORDER:
MilitiaMovementOrder( (UINT8) pEvent->uiParam );
break;
+
+ case EVENT_PMC_EMAIL:
+ // only send the email if we hven't already visited the site, otherwise continue to spam ;-)
+ if ( !IsBookMarkSet(PMC_BOOKMARK) )
+ AddEmail( PMC_INTRO, PMC_INTRO_LENGTH, PMC, GetWorldTotalMin( ), -1, -1, TYPE_EMAIL_EMAIL_EDT );
+ break;
+
+ case EVENT_PMC_REINFORCEMENT_ARRIVAL:
+ HandlePMCArrival( (UINT8)pEvent->uiParam );
+ break;
}
gfPreventDeletionOfAnyEvent = fOrigPreventFlag;
return TRUE;
diff --git a/Strategic/Game Event Hook.h b/Strategic/Game Event Hook.h
index ee920fa4..6f098fe0 100644
--- a/Strategic/Game Event Hook.h
+++ b/Strategic/Game Event Hook.h
@@ -112,7 +112,9 @@ enum
EVENT_HELICOPTER_HOVER_FOR_A_MINUTE,
EVENT_HELICOPTER_REFUEL_FOR_A_MINUTE,
- EVENT_MILITIA_MOVEMENT_ORDER, // Flugente: timed event: militia was ordered to move, at this time they should arrive
+ EVENT_MILITIA_MOVEMENT_ORDER, // Flugente: militia was ordered to move, at this time they should arrive
+ EVENT_PMC_EMAIL, // Flugente: pmc will send us an introduction email
+ EVENT_PMC_REINFORCEMENT_ARRIVAL, // Flugente: pmc hired militia arrives
NUMBER_OF_EVENT_TYPES_PLUS_ONE,
NUMBER_OF_EVENT_TYPES = NUMBER_OF_EVENT_TYPES_PLUS_ONE - 1
diff --git a/Strategic/Game Events.cpp b/Strategic/Game Events.cpp
index 0c8ddc5f..e4eac830 100644
--- a/Strategic/Game Events.cpp
+++ b/Strategic/Game Events.cpp
@@ -109,6 +109,8 @@ CHAR16 gEventName[NUMBER_OF_EVENT_TYPES_PLUS_ONE][40]={
#endif
L"HelicopterHoverForAMinute",
L"HelicopterRefuelForAMinute",
+ L"MilitiaMovementOrder",
+ L"PMCReinforcementArrival",
};
#endif
diff --git a/Strategic/Game Init.cpp b/Strategic/Game Init.cpp
index 49bcf2f0..e0ebe442 100644
--- a/Strategic/Game Init.cpp
+++ b/Strategic/Game Init.cpp
@@ -60,6 +60,7 @@
#include "MilitiaSquads.h"
#include "Map Screen Interface Map Inventory.h"//dnl ch51 081009
#include "CampaignStats.h" // added by Flugente
+ #include "PMC.h" // added by Flugente
#endif
#include "Vehicles.h"
@@ -714,6 +715,9 @@ fFirstTimeInMapScreen = TRUE;
// Flugente campaign stats
gCampaignStats.clear();
+ // Flugente: PMC
+ GameInitPMC();
+
InitStrategicLayer();
// Set new game flag
diff --git a/Strategic/Town Militia.cpp b/Strategic/Town Militia.cpp
index e09e3fc4..0892e4a2 100644
--- a/Strategic/Town Militia.cpp
+++ b/Strategic/Town Militia.cpp
@@ -29,6 +29,8 @@
#include "Map Screen Interface Border.h"
#include "interface control.h"
#include "Map Screen Interface Map.h"
+ #include "laptop.h" // added by Flugente
+ #include "Game Event Hook.h" // added by Flugente
#endif
// HEADROCK HAM 3: include these files so that a militia trainer's Effective Leadership can be determined. Used
@@ -126,6 +128,7 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
UINT8 iTrainingSquadSize = __min(iMaxMilitiaPerSector, CalcNumMilitiaTrained(ubTrainerEffectiveLeadership, FALSE));
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Militia1");
+
// get town index
ubTownId = StrategicMap[ sMapX + sMapY * MAP_WORLD_X ].bNameId;
@@ -134,7 +137,6 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
Assert( IsThisSectorASAMSector( sMapX, sMapY, 0 ) );
}
-
// force tactical to update militia status
gfStrategicMilitiaChangesMade = FALSE;
@@ -221,7 +223,7 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
}
else
{
- if( ubTownId != BLANK_SECTOR )
+ if( ubTownId != BLANK_SECTOR )
{
// dammit! Last chance - try to find other eligible sectors in the same town with a Green guy to be promoted
InitFriendlyTownSectorServer(ubTownId, sMapX, sMapY);
@@ -246,9 +248,9 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
}
}
- // Kaiden: Veteran militia training
- // This is essentially copy/pasted from above
- // But the names have been changed to protect the innocent
+ // Kaiden: Veteran militia training
+ // This is essentially copy/pasted from above
+ // But the names have been changed to protect the innocent
if ((!fFoundOne) && (gGameExternalOptions.gfTrainVeteranMilitia)
&& (GetWorldDay( ) >= gGameExternalOptions.guiTrainVeteranMilitiaDelay))
{
@@ -305,7 +307,7 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
}
// next, please!
- ubMilitiaTrained++;
+ ++ubMilitiaTrained;
}
if (gfStrategicMilitiaChangesMade)
@@ -332,12 +334,16 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
RecordNumMilitiaTrainedForMercs( sMapX, sMapY, pTrainer->bSectorZ, ubMilitiaTrained, FALSE );
}
- // the trainer announces to player that he's finished his assignment. Make his sector flash!
- AssignmentDone( pTrainer, TRUE, FALSE );
+ // the trainer announces to player that he's finished his assignment. Make his sector flash!
+ AssignmentDone( pTrainer, TRUE, FALSE );
- // handle completion of town by training group
+ // handle completion of town by training group
HandleCompletionOfTownTrainingByGroupWithTrainer( pTrainer, TOWN_MILITIA );
}
+
+ // Flugente: if we trained militia, the PMC notices us and offers their services
+ if ( gGameExternalOptions.fPMC )
+ AddStrategicEvent( EVENT_PMC_EMAIL, GetWorldTotalMin() + 60 * (1 + Random(6)), 0 );
}
diff --git a/Strategic/XML_FacilityTypes.cpp b/Strategic/XML_FacilityTypes.cpp
index c3166246..d5134ab6 100644
--- a/Strategic/XML_FacilityTypes.cpp
+++ b/Strategic/XML_FacilityTypes.cpp
@@ -179,7 +179,9 @@ facilitytypeStartElementHandle(void *userData, const XML_Char *name, const XML_C
strcmp(name, "ubMilitiaTrainersAllowed") == 0 ||
strcmp(name, "ubMobileMilitiaTrainersAllowed") == 0 ||
strcmp(name, "usMilitiaTraining") == 0 ||
- strcmp(name, "usMobileMilitiaTraining") == 0 ))
+ strcmp(name, "usMobileMilitiaTraining") == 0 ||
+
+ strcmp( name, "pmcentrypoint" ) == 0 ))
{
pData->curElement = FACILITYTYPE_ELEMENT;
@@ -426,8 +428,10 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
gFacilityTypes[pData->curIndex].usMilitiaTraining = pData->curFacilityTypeData.usMilitiaTraining;
gFacilityTypes[pData->curIndex].usMobileMilitiaTraining = pData->curFacilityTypeData.usMobileMilitiaTraining;
+ gFacilityTypes[pData->curIndex].usFacilityFlags = pData->curFacilityTypeData.usFacilityFlags;
+
// Set assignment-specific data
- for (UINT16 cnt = 0; cnt < NUM_FACILITY_ASSIGNMENTS; cnt++)
+ for (UINT16 cnt = 0; cnt < NUM_FACILITY_ASSIGNMENTS; ++cnt)
{
// Performance and limits
gFacilityTypes[pData->curIndex].AssignmentData[cnt].usPerformance = pData->curFacilityTypeData.AssignmentData[cnt].usPerformance;
@@ -472,7 +476,7 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
gFacilityTypes[pData->curIndex].AssignmentData[cnt].ubMinimumLoyaltyHere = pData->curFacilityTypeData.AssignmentData[cnt].ubMinimumLoyaltyHere;
// Set risks associated with this assignment
- for (UINT16 cntB = 0; cntB < NUM_RISKS; cntB++)
+ for (UINT16 cntB = 0; cntB < NUM_RISKS; ++cntB)
{
gFacilityTypes[pData->curIndex].AssignmentData[cnt].Risk[cntB].usChance = pData->curFacilityTypeData.AssignmentData[cnt].Risk[cntB].usChance;
gFacilityTypes[pData->curIndex].AssignmentData[cnt].Risk[cntB].bBaseEffect = pData->curFacilityTypeData.AssignmentData[cnt].Risk[cntB].bBaseEffect;
@@ -485,7 +489,7 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
wcscpy(gFacilityTypes[pData->curIndex].szFacilityName, pData->curFacilityTypeData.szFacilityName);
wcscpy(gFacilityTypes[pData->curIndex].szFacilityShortName, pData->curFacilityTypeData.szFacilityShortName);
- for (UINT16 cnt = 0; cnt < NUM_FACILITY_ASSIGNMENTS; cnt++)
+ for (UINT16 cnt = 0; cnt < NUM_FACILITY_ASSIGNMENTS; ++cnt)
{
wcscpy(gFacilityTypes[pData->curIndex].AssignmentData[cnt].szTooltipText, pData->curFacilityTypeData.AssignmentData[cnt].szTooltipText);
}
@@ -539,25 +543,29 @@ facilitytypeEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = FACILITYTYPE_TYPE;
pData->curFacilityTypeData.ubMilitiaTrainersAllowed = (UINT8) atol(pData->szCharData);
}
-
else if(strcmp(name, "ubMobileMilitiaTrainersAllowed") == 0 )
{
pData->curElement = FACILITYTYPE_TYPE;
pData->curFacilityTypeData.ubMobileMilitiaTrainersAllowed = (UINT8) atol(pData->szCharData);
}
-
else if(strcmp(name, "usMilitiaTraining") == 0 )
{
pData->curElement = FACILITYTYPE_TYPE;
pData->curFacilityTypeData.usMilitiaTraining = (UINT8) atol(pData->szCharData);
}
-
else if(strcmp(name, "usMobileMilitiaTraining") == 0 )
{
pData->curElement = FACILITYTYPE_TYPE;
pData->curFacilityTypeData.usMobileMilitiaTraining = (UINT8) atol(pData->szCharData);
}
+ else if ( strcmp( name, "pmcentrypoint" ) == 0 )
+ {
+ pData->curElement = FACILITYTYPE_TYPE;
+ if ( (UINT8)atol( pData->szCharData ) )
+ pData->curFacilityTypeData.usFacilityFlags |= FACILITYTYPE_PMCENTRYPOINT;
+ }
+
///////////////////////////////////////////////////////
// Assignments
diff --git a/Tactical/DynamicDialogue.cpp b/Tactical/DynamicDialogue.cpp
index b57a93aa..f8e94e67 100644
--- a/Tactical/DynamicDialogue.cpp
+++ b/Tactical/DynamicDialogue.cpp
@@ -304,7 +304,7 @@ BOOLEAN LoadDynamicDialogue( HWFILE hwFile )
for ( UINT32 i = 0; i < size; ++i )
{
DynamicOpinionSpeechEvent event;
- numBytesRead = ReadFieldByField( hwFile, &event, sizeof(event), sizeof(DynamicOpinionSpeechEvent), numBytesRead );
+ numBytesRead = ReadFieldByField( hwFile, &event, sizeof(event), sizeof(DynamicOpinionSpeechEvent), 0 );
gDynamicOpinionSpeechEventArchiveVector.push_back( event );
}
@@ -312,7 +312,7 @@ BOOLEAN LoadDynamicDialogue( HWFILE hwFile )
UINT32 safetycheck2 = 0;
numBytesRead = ReadFieldByField( hwFile, &safetycheck2, sizeof(safetycheck2), sizeof(UINT32), numBytesRead );
- if ( gDynDiaSaveCheck != gDynDiaSaveCheck || gDynDiaSaveCheck != gDynDiaSaveCheck )
+ if ( safetycheck1 != gDynDiaSaveCheck || safetycheck2 != gDynDiaSaveCheck )
{
ScreenMsg( FONT_MCOLOR_LTGREEN, MSG_INTERFACE, L"Eyecatcher corruption detected while loading dynamic dialogue events!" );
return FALSE;
@@ -383,7 +383,7 @@ void CreateSpeechEventsFromDynamicOpinionEvent( DynamicOpinionSpeechEvent aEvent
// that way, if several opinon events regarding the same thing are set, we will have dialogue over all of that
UINT8 cnt = 0;
- aEvent.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.usDynamicDialogueTimeOffset;
+ aEvent.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.sDynamicDialogueTimeOffset;
UINT8 queuenumber = aEvent.usQueueNumber + 1;
@@ -449,7 +449,7 @@ void CreateSpeechEventsFromDynamicOpinionEvent( DynamicOpinionSpeechEvent aEvent
response.usQueueNumber = queuenumber++;
response.usSide = DOST_POSITION_LEFT;
response.usNumonside = (UINT8)GetSidePosition( response.usSide );
- response.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.usDynamicDialogueTimeOffset;
+ response.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.sDynamicDialogueTimeOffset;
gDynamicOpinionSpeechEventVector.push_back( response );
gDynamicOpinionSpeechInCurrentDialogue.push_back( response );
@@ -464,7 +464,7 @@ void CreateSpeechEventsFromDynamicOpinionEvent( DynamicOpinionSpeechEvent aEvent
response.usQueueNumber = queuenumber++;
response.usSide = DOST_POSITION_RIGHT;
response.usNumonside = (UINT8)GetSidePosition( response.usSide );
- response.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.usDynamicDialogueTimeOffset;
+ response.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.sDynamicDialogueTimeOffset;
gDynamicOpinionSpeechEventVector.push_back( response );
gDynamicOpinionSpeechInCurrentDialogue.push_back( response );
@@ -606,7 +606,7 @@ void CreateSpeechEventsFromDynamicOpinionEvent( DynamicOpinionSpeechEvent aEvent
{
impaction.usQueueNumber = queuenumber++;
impaction.usNumonside = (UINT8)GetSidePosition( impaction.usSide );
- impaction.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.usDynamicDialogueTimeOffset;
+ impaction.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.sDynamicDialogueTimeOffset;
gDynamicOpinionSpeechEventVector.push_back( impaction );
gDynamicOpinionSpeechInCurrentDialogue.push_back( impaction );
@@ -626,7 +626,7 @@ void CreateSpeechEventsFromDynamicOpinionEvent( DynamicOpinionSpeechEvent aEvent
response.usQueueNumber = queuenumber++;
response.usSide = DOST_POSITION_LEFT;
response.usNumonside = (UINT8)GetSidePosition( response.usSide );
- response.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.usDynamicDialogueTimeOffset;
+ response.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.sDynamicDialogueTimeOffset;
gDynamicOpinionSpeechEventVector.push_back( response );
gDynamicOpinionSpeechInCurrentDialogue.push_back( response );
@@ -642,7 +642,7 @@ void CreateSpeechEventsFromDynamicOpinionEvent( DynamicOpinionSpeechEvent aEvent
response.usQueueNumber = queuenumber++;
response.usSide = DOST_POSITION_RIGHT;
response.usNumonside = (UINT8)GetSidePosition( response.usSide );
- response.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.usDynamicDialogueTimeOffset;
+ response.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.sDynamicDialogueTimeOffset;
gDynamicOpinionSpeechEventVector.push_back( response );
gDynamicOpinionSpeechInCurrentDialogue.push_back( response );
@@ -682,7 +682,7 @@ void CreateSpeechEventsFromDynamicOpinionEvent( DynamicOpinionSpeechEvent aEvent
}
impinterference.usNumonside = (UINT8)GetSidePosition( impinterference.usSide );
- impinterference.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.usDynamicDialogueTimeOffset;
+ impinterference.usStarttime = GetJA2Clock( ) + cnt * gGameExternalOptions.sDynamicDialogueTimeOffset;
gDynamicOpinionSpeechEventVector.push_back( impinterference );
gDynamicOpinionSpeechInCurrentDialogue.push_back( impinterference );
@@ -1085,7 +1085,7 @@ BOOLEAN DynamicOpinionTacticalCharacterDialogue( DynamicOpinionSpeechEvent& aEve
pDDBox->SetStartTime( aEvent.usStarttime );
// delay destruction of all current boxes - as long as new dialogue comes in, they will be kept
- DelayBoxDestruction( aEvent.usStarttime + gGameExternalOptions.usDynamicDialogueTimeOffset * 3.5f );
+ DelayBoxDestruction( aEvent.usStarttime + gGameExternalOptions.sDynamicDialogueTimeOffset * 3.5f );
// on certain dialogues, we can choose an answer
if ( aEvent.ubEventType == DOST_INTERJECTOR_DIALOGUESELECTION )
@@ -1115,7 +1115,7 @@ BOOLEAN DynamicOpinionTacticalCharacterDialogue( DynamicOpinionSpeechEvent& aEve
IMPDialogueChooseBox_Static::getInstance( ).SetHelpText( szDynamicDialogueText_DOST_INTERJECTOR_DIALOGUESELECTION[aEvent.data.event.ubEventId] );
IMPDialogueChooseBox_Static::getInstance( ).Create( sX, sY + 60 );
IMPDialogueChooseBox_Static::getInstance( ).SetStartTime( aEvent.usStarttime );
- IMPDialogueChooseBox_Static::getInstance( ).SetEndTime( aEvent.usStarttime + 2 * gGameExternalOptions.usDynamicDialogueTimeOffset );
+ IMPDialogueChooseBox_Static::getInstance( ).SetEndTime( aEvent.usStarttime + 2 * gGameExternalOptions.sDynamicDialogueTimeOffset );
}
return TRUE;
diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp
index f16ee97a..e9d1125e 100644
--- a/Tactical/Handle UI.cpp
+++ b/Tactical/Handle UI.cpp
@@ -1163,7 +1163,7 @@ UINT32 UIHandleNewBadMerc( UI_EVENT *pUIEvent )
else if( usRandom < 8 )
pSoldier = TacticalCreateArmyTroop();
else
- pSoldier = TacticalCreateEliteEnemy();
+ pSoldier = TacticalCreateEliteEnemy( );
//Add soldier strategic info, so it doesn't break the counters!
if( pSoldier )
diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp
index 0f530260..d3f61439 100644
--- a/Tactical/Turn Based Input.cpp
+++ b/Tactical/Turn Based Input.cpp
@@ -1724,7 +1724,7 @@ void GetKeyboardInput( UINT32 *puiNewEvent )
// Flugente: speed up dynamic dialogue boxes
// Note that this will behave oddly on the morning of January 1st 1970 :-)
- DelayBoxDestructionBy( - gGameExternalOptions.usDynamicDialogueTimeOffset );
+ DelayBoxDestructionBy( -gGameExternalOptions.sDynamicDialogueTimeOffset );
}
#endif
diff --git a/Utils/Text.h b/Utils/Text.h
index b28b9ba4..ffd3d46e 100644
--- a/Utils/Text.h
+++ b/Utils/Text.h
@@ -2744,7 +2744,7 @@ enum
extern STR16 szCampaignHistoryWebpageString[];
// Flugente: merc compare website
-#define TEXT_MERCCOMPARE_CUSTOMERSTATEMENTS 6 // number of customer quotes, each with an additional short character name
+#define TEXT_MERCCOMPARE_CUSTOMERSTATEMENTS 7 // number of customer quotes, each with an additional short character name
enum
{
@@ -2805,6 +2805,41 @@ enum
extern STR16 szWHOWebSite[];
+// Flugente: PMC website
+enum
+{
+ // main page
+ TEXT_PMC_WEBSITENAME,
+ TEXT_PMC_SLOGAN,
+
+ // links to other pages
+ TEXT_PMC_SUBSITE1,
+
+ TEXT_PMC_MAIN1 = TEXT_PMC_SUBSITE1 + 3,
+
+ // team contracts
+ TEXT_PMC_CONTRACT_TEAM_INTRO = TEXT_PMC_MAIN1 + 7,
+ TEXT_PMC_CONTRACT_DROPDOWNTEXT,
+ TEXT_PMC_REGULAR,
+ TEXT_PMC_VETERAN,
+
+ TEXT_PMC_DETAIL,
+
+ TEXT_PMC_SELECTAREA = TEXT_PMC_DETAIL + 3,
+ TEXT_PMC_TOTALCOST,
+ TEXT_PMC_ETA,
+ TEXT_PMC_CONTRACTBUTTON,
+
+ TEXT_PMC_CONFIRMATION,
+ TEXT_PMC_ARRIVAL,
+ TEXT_PMC_NEXTDEPLOYMENT,
+ TEXT_PMC_NODROPOFF,
+
+ TEXT_PMC_MAX,
+};
+
+extern STR16 szPMCWebSite[];
+
extern STR16 szTacticalInventoryDialogString[];
extern STR16 szTacticalCoverDialogString[];
extern STR16 szTacticalCoverDialogPrintString[];
diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp
index 785c8a83..f40e623d 100644
--- a/Utils/_ChineseText.cpp
+++ b/Utils/_ChineseText.cpp
@@ -3898,6 +3898,7 @@ STR16 pTransactionText[] =
L"民兵保养", // L"Militia upkeep", // HEADROCK HAM 3.6
L"释放俘虏所需的赎金", //L"Ransom for released prisoners",
L"WHO data subscription", // Flugente: disease TODO.Translate
+ L"Payment to Kerberus", // Flugente: PMC
};
STR16 pTransactionAlternateText[] =
@@ -4342,6 +4343,7 @@ STR16 pBookMarkStrings[] =
L"战役历史",
L"MeLoDY",
L"WHO",
+ L"Kerberus",
};
STR16 pBookmarkTitle[] =
@@ -4461,6 +4463,9 @@ STR16 pWebPagesTitles[] =
L"WHO - About WHO",
L"WHO - Disease in Arulco",
L"WHO - Helpful Tips",
+ L"Kerberus - About Us",
+ L"Kerberus - Hire a Team",
+ L"Kerberus - Individual Contracts",
L"Bobby Ray - 最近的运货",
L"百科全书",
L"百科全书 - 数据",
@@ -6251,6 +6256,7 @@ STR16 gzLaptopHelpText[] =
L"战役历史",
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
+ L"Kerberus - Excellence In Security",
};
@@ -8656,7 +8662,9 @@ STR16 szMercCompareWebSite[] = // TODO.Translate
L"I'll be the first to admit our crew was a rather illustrious assortion of characters, and we ran into some scuffles. But we learned to respect each other, and now complement each other perfectly.",
L"-Michael C., NASA-",
L"I fully recommend this site!",
- L"-Kasper H., H&C logistic incorporated-",
+ L"-Kasper H., H&C logistic Inc-",
+ L"Our training process has to be very quick, so we need to know whom we're dealing with. MeLoDY were the logical choice for this.",
+ L"-Stan Duke, Kerberus Inc-",
// analyze
L"Choose your employee",
@@ -8746,6 +8754,49 @@ STR16 szWHOWebSite[] =
L"If a blade weapon hits an infected person, the blade becomes infected, and can be used to spread the infection further.",
};
+STR16 szPMCWebSite[] =
+{
+ // main page
+ L"Kerberus",
+ L"Experience In Security",
+
+ // links to other pages
+ L"What is Kerberus?",
+ L"Team Contracts",
+ L"Individual Contracts",
+
+ // text on the main page
+ L"Kerberus is a well known international private military contractor. Founded in 1983, we provide security and armed forces training around the world.",
+ L"Our extensively trained personnel provides security for over 30 governments areound the world. This includes several conflict zones.",
+ L"We have several training centres around the globe, including in Indonesia, Colombia, Katar, South Africa and Romania. As a result, we can usually fulfil your contract requirements within 24 hours.",
+ L"Under 'Individual Contracts', we offer individual contracts with experienced veterans in the field of security.",
+ L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.",
+ L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insetion via harbours or border posts is also possible.",
+ L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.",
+
+ // militia contract page
+ L"You can select the type and number of personnel you want to hire here:",
+ L"Initial deployment",
+ L"Regular personnel",
+ L"Veteran personnel",
+
+ L"%d available, %d$ each",
+ L"Hire: %d",
+ L"Cost: %d$",
+
+ L"Select the initial operational area:",
+ L"Total Cost: %d$",
+ L"ETA: %02d:%02d",
+ L"Close Contract",
+
+ L"Thank you! Our personnel will be on site on %02d:%02d tomorrow.",
+ L"Kerberus reinforcements have arrived in %s.",
+ L"Next deployment: %d regulars and %d veterans at %s on %02d:%02d, day %d.",
+ L"You do not control any location through which we could insert troops!",
+
+ // individual contract page
+};
+
STR16 szTacticalInventoryDialogString[]=
{
L"操作背包",
diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp
index e374fdc0..5ba476aa 100644
--- a/Utils/_DutchText.cpp
+++ b/Utils/_DutchText.cpp
@@ -3897,6 +3897,7 @@ STR16 pTransactionText[] =
L"Militia upkeep", // HEADROCK HAM 3.6 // TODO.Translate
L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate
L"WHO data subscription", // Flugente: disease TODO.Translate
+ L"Payment to Kerberus", // Flugente: PMC
};
STR16 pTransactionAlternateText[] =
@@ -4344,6 +4345,7 @@ STR16 pBookMarkStrings[] =
L"Campaign History", // TODO.Translate
L"MeLoDY",
L"WHO",
+ L"Kerberus",
};
STR16 pBookmarkTitle[] =
@@ -6264,6 +6266,7 @@ STR16 gzLaptopHelpText[] =
L"Campaign History", // TODO.Translate
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
+ L"Kerberus - Excellence In Security",
};
@@ -8672,7 +8675,9 @@ STR16 szMercCompareWebSite[] = // TODO.Translate
L"I'll be the first to admit our crew was a rather illustrious assortion of characters, and we ran into some scuffles. But we learned to respect each other, and now complement each other perfectly.",
L"-Michael C., NASA-",
L"I fully recommend this site!",
- L"-Kasper H., H&C logistic incorporated-",
+ L"-Kasper H., H&C logistic Inc-",
+ L"Our training process has to be very quick, so we need to know whom we're dealing with. MeLoDY were the logical choice for this.",
+ L"-Stan Duke, Kerberus Inc-",
// analyze
L"Choose your employee",
@@ -8761,6 +8766,49 @@ STR16 szWHOWebSite[] =
L"If a blade weapon hits an infected person, the blade becomes infected, and can be used to spread the infection further.",
};
+STR16 szPMCWebSite[] =
+{
+ // main page
+ L"Kerberus",
+ L"Experience In Security",
+
+ // links to other pages
+ L"What is Kerberus?",
+ L"Team Contracts",
+ L"Individual Contracts",
+
+ // text on the main page
+ L"Kerberus is a well known international private military contractor. Founded in 1983, we provide security and armed forces training around the world.",
+ L"Our extensively trained personnel provides security for over 30 governments areound the world. This includes several conflict zones.",
+ L"We have several training centres around the globe, including in Indonesia, Colombia, Katar, South Africa and Romania. As a result, we can usually fulfil your contract requirements within 24 hours.",
+ L"Under 'Individual Contracts', we offer individual contracts with experienced veterans in the field of security.",
+ L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.",
+ L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insetion via harbours or border posts is also possible.",
+ L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.",
+
+ // militia contract page
+ L"You can select the type and number of personnel you want to hire here:",
+ L"Initial deployment",
+ L"Regular personnel",
+ L"Veteran personnel",
+
+ L"%d available, %d$ each",
+ L"Hire: %d",
+ L"Cost: %d$",
+
+ L"Select the initial operational area:",
+ L"Total Cost: %d$",
+ L"ETA: %02d:%02d",
+ L"Close Contract",
+
+ L"Thank you! Our personnel will be on site on %02d:%02d tomorrow.",
+ L"Kerberus reinforcements have arrived in %s.",
+ L"Next deployment: %d regulars and %d veterans at %s on %02d:%02d, day %d.",
+ L"You do not control any location through which we could insert troops!",
+
+ // individual contract page
+};
+
STR16 szTacticalInventoryDialogString[]=
{
L"Inventory Manipulations",
diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp
index 07ca2767..6035eaaa 100644
--- a/Utils/_EnglishText.cpp
+++ b/Utils/_EnglishText.cpp
@@ -3897,6 +3897,7 @@ STR16 pTransactionText[] =
L"Militia upkeep", // HEADROCK HAM 3.6
L"Ransom for released prisoners", // Flugente: prisoner system
L"WHO data subscription", // Flugente: disease
+ L"Payment to Kerberus", // Flugente: PMC
};
STR16 pTransactionAlternateText[] =
@@ -4341,6 +4342,7 @@ STR16 pBookMarkStrings[] =
L"Campaign History",
L"MeLoDY",
L"WHO",
+ L"Kerberus",
};
STR16 pBookmarkTitle[] =
@@ -4460,6 +4462,9 @@ STR16 pWebPagesTitles[] =
L"WHO - About WHO",
L"WHO - Disease in Arulco",
L"WHO - Helpful Tips",
+ L"Kerberus - About Us",
+ L"Kerberus - Hire a Team",
+ L"Kerberus - Individual Contracts",
L"Bobby Ray's - Recent Shipments",
L"Encyclopedia",
L"Encyclopedia - Data",
@@ -6252,6 +6257,7 @@ STR16 gzLaptopHelpText[] =
L"Campaign History",
L"Mercenaries Love or Dislike You",
L"World Health Organization",
+ L"Kerberus - Excellence In Security",
};
@@ -8656,7 +8662,9 @@ STR16 szMercCompareWebSite[] =
L"I'll be the first to admit our crew was a rather illustrious assortion of characters, and we ran into some scuffles. But we learned to respect each other, and now complement each other perfectly.",
L"-Michael C., NASA-",
L"I fully recommend this site!",
- L"-Kasper H., H&C logistic incorporated-",
+ L"-Kasper H., H&C logistic Inc-",
+ L"Our training process has to be very quick, so we need to know whom we're dealing with. MeLoDY were the logical choice for this.",
+ L"-Stan Duke, Kerberus Inc-",
// analyze
L"Choose your employee",
@@ -8745,6 +8753,49 @@ STR16 szWHOWebSite[] =
L"If a blade weapon hits an infected person, the blade becomes infected, and can be used to spread the infection further.",
};
+STR16 szPMCWebSite[] =
+{
+ // main page
+ L"Kerberus",
+ L"Experience In Security",
+
+ // links to other pages
+ L"What is Kerberus?",
+ L"Team Contracts",
+ L"Individual Contracts",
+
+ // text on the main page
+ L"Kerberus is a well known international private military contractor. Founded in 1983, we provide security and armed forces training around the world.",
+ L"Our extensively trained personnel provides security for over 30 governments areound the world. This includes several conflict zones.",
+ L"We have several training centres around the globe, including in Indonesia, Colombia, Katar, South Africa and Romania. As a result, we can usually fulfil your contract requirements within 24 hours.",
+ L"Under 'Individual Contracts', we offer individual contracts with experienced veterans in the field of security.",
+ L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.",
+ L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insetion via harbours or border posts is also possible.",
+ L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.",
+
+ // militia contract page
+ L"You can select the type and number of personnel you want to hire here:",
+ L"Initial deployment",
+ L"Regular personnel",
+ L"Veteran personnel",
+
+ L"%d available, %d$ each",
+ L"Hire: %d",
+ L"Cost: %d$",
+
+ L"Select the initial operational area:",
+ L"Total Cost: %d$",
+ L"ETA: %02d:%02d",
+ L"Close Contract",
+
+ L"Thank you! Our personnel will be on site on %02d:%02d tomorrow.",
+ L"Kerberus reinforcements have arrived in %s.",
+ L"Next deployment: %d regulars and %d veterans at %s on %02d:%02d, day %d.",
+ L"You do not control any location through which we could insert troops!",
+
+ // individual contract page
+};
+
STR16 szTacticalInventoryDialogString[]=
{
L"Inventory Manipulations",
diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp
index c722bbfe..ea3ee99b 100644
--- a/Utils/_FrenchText.cpp
+++ b/Utils/_FrenchText.cpp
@@ -3906,6 +3906,7 @@ STR16 pTransactionText[] =
L"Entretien de la milice", // HEADROCK HAM 3.6
L"Argent des prisonniers libérés", // Flugente: prisoner system
L"WHO data subscription", // Flugente: disease TODO.Translate
+ L"Payment to Kerberus", // Flugente: PMC
};
STR16 pTransactionAlternateText[] =
@@ -4354,6 +4355,7 @@ STR16 pBookMarkStrings[] =
L"Comptes rendus",
L"MeLoDY",
L"WHO",
+ L"Kerberus",
};
STR16 pBookmarkTitle[] =
@@ -4473,6 +4475,9 @@ STR16 pWebPagesTitles[] =
L"WHO - About WHO",
L"WHO - Disease in Arulco",
L"WHO - Helpful Tips",
+ L"Kerberus - About Us",
+ L"Kerberus - Hire a Team",
+ L"Kerberus - Individual Contracts",
L"Bobby Ray : Dernières commandes",
L"Encyclopédie",
L"Encyclopédie : Données",
@@ -6266,6 +6271,7 @@ STR16 gzLaptopHelpText[] =
L"Comptes rendus",
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
+ L"Kerberus - Excellence In Security",
};
@@ -8659,7 +8665,9 @@ STR16 szMercCompareWebSite[] = // TODO.Translate
L"I'll be the first to admit our crew was a rather illustrious assortion of characters, and we ran into some scuffles. But we learned to respect each other, and now complement each other perfectly.",
L"-Michael C., NASA-",
L"I fully recommend this site!",
- L"-Kasper H., H&C logistic incorporated-",
+ L"-Kasper H., H&C logistic Inc-",
+ L"Our training process has to be very quick, so we need to know whom we're dealing with. MeLoDY were the logical choice for this.",
+ L"-Stan Duke, Kerberus Inc-",
// analyze
L"Choose your employee",
@@ -8748,6 +8756,49 @@ STR16 szWHOWebSite[] =
L"If a blade weapon hits an infected person, the blade becomes infected, and can be used to spread the infection further.",
};
+STR16 szPMCWebSite[] =
+{
+ // main page
+ L"Kerberus",
+ L"Experience In Security",
+
+ // links to other pages
+ L"What is Kerberus?",
+ L"Team Contracts",
+ L"Individual Contracts",
+
+ // text on the main page
+ L"Kerberus is a well known international private military contractor. Founded in 1983, we provide security and armed forces training around the world.",
+ L"Our extensively trained personnel provides security for over 30 governments areound the world. This includes several conflict zones.",
+ L"We have several training centres around the globe, including in Indonesia, Colombia, Katar, South Africa and Romania. As a result, we can usually fulfil your contract requirements within 24 hours.",
+ L"Under 'Individual Contracts', we offer individual contracts with experienced veterans in the field of security.",
+ L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.",
+ L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insetion via harbours or border posts is also possible.",
+ L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.",
+
+ // militia contract page
+ L"You can select the type and number of personnel you want to hire here:",
+ L"Initial deployment",
+ L"Regular personnel",
+ L"Veteran personnel",
+
+ L"%d available, %d$ each",
+ L"Hire: %d",
+ L"Cost: %d$",
+
+ L"Select the initial operational area:",
+ L"Total Cost: %d$",
+ L"ETA: %02d:%02d",
+ L"Close Contract",
+
+ L"Thank you! Our personnel will be on site on %02d:%02d tomorrow.",
+ L"Kerberus reinforcements have arrived in %s.",
+ L"Next deployment: %d regulars and %d veterans at %s on %02d:%02d, day %d.",
+ L"You do not control any location through which we could insert troops!",
+
+ // individual contract page
+};
+
STR16 szTacticalInventoryDialogString[]=
{
L"Manipulations de l'inventaire",
diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp
index e36748c0..2f4d14c2 100644
--- a/Utils/_GermanText.cpp
+++ b/Utils/_GermanText.cpp
@@ -3874,6 +3874,7 @@ STR16 pTransactionText[] =
L"Unterhaltskosten für Miliz", // HEADROCK HAM 3.6
L"Lösegeld erpresst", // Flugente: prisoner system
L"WHO data subscription", // Flugente: disease TODO.Translate
+ L"Payment to Kerberus", // Flugente: PMC
};
STR16 pTransactionAlternateText[] =
@@ -4295,6 +4296,7 @@ STR16 pBookMarkStrings[] =
L"Geschichte",
L"MeLoDY",
L"WHO",
+ L"Kerberus",
};
STR16 pBookmarkTitle[] =
@@ -4406,6 +4408,9 @@ STR16 pWebPagesTitles[] =
L"WHO - About WHO",
L"WHO - Disease in Arulco",
L"WHO - Helpful Tips",
+ L"Kerberus - About Us",
+ L"Kerberus - Hire a Team",
+ L"Kerberus - Individual Contracts",
L"Bobby Rays - Letzte Lieferungen",
L"Enzyklopädie",
L"Enzyklopädie - Daten",
@@ -6096,6 +6101,7 @@ STR16 gzLaptopHelpText[] =
L"Geschichte",
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
+ L"Kerberus - Excellence In Security",
};
STR16 gzHelpScreenText[] =
@@ -8486,7 +8492,9 @@ STR16 szMercCompareWebSite[] = // TODO.Translate
L"I'll be the first to admit our crew was a rather illustrious assortion of characters, and we ran into some scuffles. But we learned to respect each other, and now complement each other perfectly.",
L"-Michael C., NASA-",
L"I fully recommend this site!",
- L"-Kasper H., H&C logistic incorporated-",
+ L"-Kasper H., H&C logistic Inc-",
+ L"Our training process has to be very quick, so we need to know whom we're dealing with. MeLoDY were the logical choice for this.",
+ L"-Stan Duke, Kerberus Inc-",
// analyze
L"Choose your employee",
@@ -8575,6 +8583,49 @@ STR16 szWHOWebSite[] =
L"If a blade weapon hits an infected person, the blade becomes infected, and can be used to spread the infection further.",
};
+STR16 szPMCWebSite[] =
+{
+ // main page
+ L"Kerberus",
+ L"Experience In Security",
+
+ // links to other pages
+ L"What is Kerberus?",
+ L"Team Contracts",
+ L"Individual Contracts",
+
+ // text on the main page
+ L"Kerberus is a well known international private military contractor. Founded in 1983, we provide security and armed forces training around the world.",
+ L"Our extensively trained personnel provides security for over 30 governments areound the world. This includes several conflict zones.",
+ L"We have several training centres around the globe, including in Indonesia, Colombia, Katar, South Africa and Romania. As a result, we can usually fulfil your contract requirements within 24 hours.",
+ L"Under 'Individual Contracts', we offer individual contracts with experienced veterans in the field of security.",
+ L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.",
+ L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insetion via harbours or border posts is also possible.",
+ L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.",
+
+ // militia contract page
+ L"You can select the type and number of personnel you want to hire here:",
+ L"Initial deployment",
+ L"Regular personnel",
+ L"Veteran personnel",
+
+ L"%d available, %d$ each",
+ L"Hire: %d",
+ L"Cost: %d$",
+
+ L"Select the initial operational area:",
+ L"Total Cost: %d$",
+ L"ETA: %02d:%02d",
+ L"Close Contract",
+
+ L"Thank you! Our personnel will be on site on %02d:%02d tomorrow.",
+ L"Kerberus reinforcements have arrived in %s.",
+ L"Next deployment: %d regulars and %d veterans at %s on %02d:%02d, day %d.",
+ L"You do not control any location through which we could insert troops!",
+
+ // individual contract page
+};
+
STR16 szTacticalInventoryDialogString[]=
{
L"Inventory Manipulations",
diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp
index 0565a111..c0ee2f92 100644
--- a/Utils/_ItalianText.cpp
+++ b/Utils/_ItalianText.cpp
@@ -3893,6 +3893,7 @@ STR16 pTransactionText[] =
L"Militia upkeep", // HEADROCK HAM 3.6 // TODO.Translate
L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate
L"WHO data subscription", // Flugente: disease TODO.Translate
+ L"Payment to Kerberus", // Flugente: PMC
};
STR16 pTransactionAlternateText[] =
@@ -4333,6 +4334,7 @@ STR16 pBookMarkStrings[] =
L"Campaign History", // TODO.Translate
L"MeLoDY",
L"WHO",
+ L"Kerberus",
};
STR16 pBookmarkTitle[] =
@@ -4452,6 +4454,9 @@ STR16 pWebPagesTitles[] =
L"WHO - About WHO",
L"WHO - Disease in Arulco",
L"WHO - Helpful Tips",
+ L"Kerberus - About Us",
+ L"Kerberus - Hire a Team",
+ L"Kerberus - Individual Contracts",
L"Bobby Ray - Spedizioni recenti",
L"Encyclopedia",
L"Encyclopedia - Data",
@@ -6250,6 +6255,7 @@ STR16 gzLaptopHelpText[] =
L"Campaign History", // TODO.Translate
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
+ L"Kerberus - Excellence In Security",
};
@@ -8665,7 +8671,9 @@ STR16 szMercCompareWebSite[] = // TODO.Translate
L"I'll be the first to admit our crew was a rather illustrious assortion of characters, and we ran into some scuffles. But we learned to respect each other, and now complement each other perfectly.",
L"-Michael C., NASA-",
L"I fully recommend this site!",
- L"-Kasper H., H&C logistic incorporated-",
+ L"-Kasper H., H&C logistic Inc-",
+ L"Our training process has to be very quick, so we need to know whom we're dealing with. MeLoDY were the logical choice for this.",
+ L"-Stan Duke, Kerberus Inc-",
// analyze
L"Choose your employee",
@@ -8754,6 +8762,49 @@ STR16 szWHOWebSite[] =
L"If a blade weapon hits an infected person, the blade becomes infected, and can be used to spread the infection further.",
};
+STR16 szPMCWebSite[] =
+{
+ // main page
+ L"Kerberus",
+ L"Experience In Security",
+
+ // links to other pages
+ L"What is Kerberus?",
+ L"Team Contracts",
+ L"Individual Contracts",
+
+ // text on the main page
+ L"Kerberus is a well known international private military contractor. Founded in 1983, we provide security and armed forces training around the world.",
+ L"Our extensively trained personnel provides security for over 30 governments areound the world. This includes several conflict zones.",
+ L"We have several training centres around the globe, including in Indonesia, Colombia, Katar, South Africa and Romania. As a result, we can usually fulfil your contract requirements within 24 hours.",
+ L"Under 'Individual Contracts', we offer individual contracts with experienced veterans in the field of security.",
+ L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.",
+ L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insetion via harbours or border posts is also possible.",
+ L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.",
+
+ // militia contract page
+ L"You can select the type and number of personnel you want to hire here:",
+ L"Initial deployment",
+ L"Regular personnel",
+ L"Veteran personnel",
+
+ L"%d available, %d$ each",
+ L"Hire: %d",
+ L"Cost: %d$",
+
+ L"Select the initial operational area:",
+ L"Total Cost: %d$",
+ L"ETA: %02d:%02d",
+ L"Close Contract",
+
+ L"Thank you! Our personnel will be on site on %02d:%02d tomorrow.",
+ L"Kerberus reinforcements have arrived in %s.",
+ L"Next deployment: %d regulars and %d veterans at %s on %02d:%02d, day %d.",
+ L"You do not control any location through which we could insert troops!",
+
+ // individual contract page
+};
+
STR16 szTacticalInventoryDialogString[]=
{
L"Inventory Manipulations",
diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp
index 5e65d7dd..cff855c1 100644
--- a/Utils/_PolishText.cpp
+++ b/Utils/_PolishText.cpp
@@ -3907,6 +3907,7 @@ STR16 pTransactionText[] =
L"Utrzymanie Samoobr.", // HEADROCK HAM 3.6
L"Ransom for released prisoners", // Flugente: prisoner system TODO.Translate
L"WHO data subscription", // Flugente: disease TODO.Translate
+ L"Payment to Kerberus", // Flugente: PMC
};
STR16 pTransactionAlternateText[] =
@@ -4351,6 +4352,7 @@ STR16 pBookMarkStrings[] =
L"Campaign History", // TODO.Translate
L"MeLoDY",
L"WHO",
+ L"Kerberus",
};
STR16 pBookmarkTitle[] =
@@ -4470,6 +4472,9 @@ STR16 pWebPagesTitles[] =
L"WHO - About WHO",
L"WHO - Disease in Arulco",
L"WHO - Helpful Tips",
+ L"Kerberus - About Us",
+ L"Kerberus - Hire a Team",
+ L"Kerberus - Individual Contracts",
L"Bobby Ray's - Ostatnie dostawy",
L"Encyclopedia",
L"Encyclopedia - Dane",
@@ -6267,6 +6272,7 @@ STR16 gzLaptopHelpText[] =
L"Campaign History", // TODO.Translate
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
+ L"Kerberus - Excellence In Security",
};
@@ -8681,7 +8687,9 @@ STR16 szMercCompareWebSite[] = // TODO.Translate
L"I'll be the first to admit our crew was a rather illustrious assortion of characters, and we ran into some scuffles. But we learned to respect each other, and now complement each other perfectly.",
L"-Michael C., NASA-",
L"I fully recommend this site!",
- L"-Kasper H., H&C logistic incorporated-",
+ L"-Kasper H., H&C logistic Inc-",
+ L"Our training process has to be very quick, so we need to know whom we're dealing with. MeLoDY were the logical choice for this.",
+ L"-Stan Duke, Kerberus Inc-",
// analyze
L"Choose your employee",
@@ -8770,6 +8778,49 @@ STR16 szWHOWebSite[] =
L"If a blade weapon hits an infected person, the blade becomes infected, and can be used to spread the infection further.",
};
+STR16 szPMCWebSite[] =
+{
+ // main page
+ L"Kerberus",
+ L"Experience In Security",
+
+ // links to other pages
+ L"What is Kerberus?",
+ L"Team Contracts",
+ L"Individual Contracts",
+
+ // text on the main page
+ L"Kerberus is a well known international private military contractor. Founded in 1983, we provide security and armed forces training around the world.",
+ L"Our extensively trained personnel provides security for over 30 governments areound the world. This includes several conflict zones.",
+ L"We have several training centres around the globe, including in Indonesia, Colombia, Katar, South Africa and Romania. As a result, we can usually fulfil your contract requirements within 24 hours.",
+ L"Under 'Individual Contracts', we offer individual contracts with experienced veterans in the field of security.",
+ L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.",
+ L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insetion via harbours or border posts is also possible.",
+ L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.",
+
+ // militia contract page
+ L"You can select the type and number of personnel you want to hire here:",
+ L"Initial deployment",
+ L"Regular personnel",
+ L"Veteran personnel",
+
+ L"%d available, %d$ each",
+ L"Hire: %d",
+ L"Cost: %d$",
+
+ L"Select the initial operational area:",
+ L"Total Cost: %d$",
+ L"ETA: %02d:%02d",
+ L"Close Contract",
+
+ L"Thank you! Our personnel will be on site on %02d:%02d tomorrow.",
+ L"Kerberus reinforcements have arrived in %s.",
+ L"Next deployment: %d regulars and %d veterans at %s on %02d:%02d, day %d.",
+ L"You do not control any location through which we could insert troops!",
+
+ // individual contract page
+};
+
STR16 szTacticalInventoryDialogString[]=
{
L"Inventory Manipulations",
diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp
index a96d1e45..eca02ec6 100644
--- a/Utils/_RussianText.cpp
+++ b/Utils/_RussianText.cpp
@@ -3894,6 +3894,7 @@ STR16 pTransactionText[] =
L"Содержание ополчения", // HEADROCK HAM 3.6 //Militia upkeep
L"Выкуп за освобожденных заключенных", // Ransom for released prisoners
L"WHO data subscription", // Flugente: disease // TODO.Translate
+ L"Payment to Kerberus", // Flugente: PMC
};
STR16 pTransactionAlternateText[] =
@@ -4338,6 +4339,7 @@ STR16 pBookMarkStrings[] =
L"Журнал",
L"MeLoDY", // TODO.Translate
L"WHO",
+ L"Kerberus",
};
STR16 pBookmarkTitle[] =
@@ -4457,6 +4459,9 @@ STR16 pWebPagesTitles[] =
L"WHO - About WHO",
L"WHO - Disease in Arulco",
L"WHO - Helpful Tips",
+ L"Kerberus - About Us",
+ L"Kerberus - Hire a Team",
+ L"Kerberus - Individual Contracts",
L"Бобби Рэй - последние поступления",
L"Энциклопедия",
L"Энциклопедия - данные",
@@ -6250,6 +6255,7 @@ STR16 gzLaptopHelpText[] =
L"Журнал кампании",
L"Mercenaries Love or Dislike You", // TODO.Translate
L"World Health Organization",
+ L"Kerberus - Excellence In Security",
};
@@ -8653,7 +8659,9 @@ STR16 szMercCompareWebSite[] = // TODO.Translate
L"I'll be the first to admit our crew was a rather illustrious assortion of characters, and we ran into some scuffles. But we learned to respect each other, and now complement each other perfectly.",
L"-Michael C., NASA-",
L"I fully recommend this site!",
- L"-Kasper H., H&C logistic incorporated-",
+ L"-Kasper H., H&C logistic Inc-",
+ L"Our training process has to be very quick, so we need to know whom we're dealing with. MeLoDY were the logical choice for this.",
+ L"-Stan Duke, Kerberus Inc-",
// analyze
L"Choose your employee",
@@ -8742,6 +8750,49 @@ STR16 szWHOWebSite[] = // TODO.Translate
L"If a blade weapon hits an infected person, the blade becomes infected, and can be used to spread the infection further.",
};
+STR16 szPMCWebSite[] =
+{
+ // main page
+ L"Kerberus",
+ L"Experience In Security",
+
+ // links to other pages
+ L"What is Kerberus?",
+ L"Team Contracts",
+ L"Individual Contracts",
+
+ // text on the main page
+ L"Kerberus is a well known international private military contractor. Founded in 1983, we provide security and armed forces training around the world.",
+ L"Our extensively trained personnel provides security for over 30 governments areound the world. This includes several conflict zones.",
+ L"We have several training centres around the globe, including in Indonesia, Colombia, Katar, South Africa and Romania. As a result, we can usually fulfil your contract requirements within 24 hours.",
+ L"Under 'Individual Contracts', we offer individual contracts with experienced veterans in the field of security.",
+ L"You can also hire an entire security team. In the 'Team Contracts' page, you can select how many of our personnel you want to hire, and where you require their services. Due to regrettable incidents in the past, we have to insist that the landing zone be under your control prior to debarkation.",
+ L"Our team can deploy by air, in which case, of course, an airport is required. Depending on the country our services are required in, insetion via harbours or border posts is also possible.",
+ L"An advance payment is required. After that, the daily fee for our personnel will be deducted from your account.",
+
+ // militia contract page
+ L"You can select the type and number of personnel you want to hire here:",
+ L"Initial deployment",
+ L"Regular personnel",
+ L"Veteran personnel",
+
+ L"%d available, %d$ each",
+ L"Hire: %d",
+ L"Cost: %d$",
+
+ L"Select the initial operational area:",
+ L"Total Cost: %d$",
+ L"ETA: %02d:%02d",
+ L"Close Contract",
+
+ L"Thank you! Our personnel will be on site on %02d:%02d tomorrow.",
+ L"Kerberus reinforcements have arrived in %s.",
+ L"Next deployment: %d regulars and %d veterans at %s on %02d:%02d, day %d.",
+ L"You do not control any location through which we could insert troops!",
+
+ // individual contract page
+};
+
STR16 szTacticalInventoryDialogString[]=
{
L"Команды инвентаря",