From c9bcf90966b7aaca8ea5e8b9048c927fa886f85e Mon Sep 17 00:00:00 2001 From: Flugente Date: Sun, 8 Feb 2015 22:11:16 +0000 Subject: [PATCH] Expanded feature: Militia Strategic Movement is turned on with ALLOW_MILITIA_STRATEGIC_COMMAND set to TRUE and allows plotting paths for the militia just like for merc squads. GameDir >= r2204 is recommended. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7727 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 4 + GameSettings.h | 3 + GameVersion.h | 3 +- SaveLoadGame.cpp | 132 ++- Strategic/AI Viewer.cpp | 44 +- Strategic/Assignments.cpp | 15 +- Strategic/Auto Resolve.cpp | 71 +- Strategic/LuaInitNPCs.cpp | 5 +- Strategic/Map Screen Interface Border.cpp | 52 +- Strategic/Map Screen Interface Bottom.cpp | 5 +- Strategic/Map Screen Interface Map.cpp | 1242 +++++++++++++++------ Strategic/Map Screen Interface Map.h | 26 +- Strategic/Map Screen Interface.cpp | 38 +- Strategic/MilitiaSquads.cpp | 472 ++++++-- Strategic/MilitiaSquads.h | 13 +- Strategic/PreBattle Interface.cpp | 71 +- Strategic/Queen Command.cpp | 74 +- Strategic/Queen Command.h | 4 +- Strategic/Reinforcement.cpp | 69 +- Strategic/Strategic AI.cpp | 82 +- Strategic/Strategic Movement.cpp | 238 +++- Strategic/Strategic Movement.h | 3 + Strategic/Strategic Pathing.cpp | 179 +-- Strategic/Town Militia.cpp | 277 +++-- Strategic/Town Militia.h | 4 + Strategic/mapscreen.cpp | 965 ++++++++++++---- Strategic/mapscreen.h | 42 + Strategic/strategic.cpp | 9 +- Strategic/strategicmap.cpp | 139 +-- Strategic/strategicmap.h | 6 +- Tactical/Dialogue Control.cpp | 7 + Tactical/Inventory Choosing.cpp | 3 + Tactical/Militia Control.cpp | 36 +- Tactical/SkillMenu.cpp | 3 +- Tactical/Soldier Control.cpp | 14 +- Tactical/Soldier Init List.cpp | 17 +- Tactical/Strategic Exit GUI.cpp | 9 +- Utils/Text.h | 3 + Utils/Timer Control.cpp | 3 +- Utils/_ChineseText.cpp | 12 + Utils/_DutchText.cpp | 12 + Utils/_EnglishText.cpp | 12 + Utils/_FrenchText.cpp | 12 + Utils/_GermanText.cpp | 12 + Utils/_ItalianText.cpp | 12 + Utils/_PolishText.cpp | 12 + Utils/_RussianText.cpp | 12 + 47 files changed, 3156 insertions(+), 1322 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index e631d56e0..fe0cbb5fb 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -2059,6 +2059,10 @@ void LoadGameExternalOptions() // Moa: If enabled militia will spread when following or set to FALSE to fill up the destination group to maximum. gGameExternalOptions.gfAllowMilitiaSpreadWhenFollowing = iniReader.ReadBoolean("Mobile Militia Movement Settings","ALLOW_MILITIA_SPREAD_WHEN_FOLLOWING", FALSE); + //################# Militia Strategic Movement Settings ################## + gGameExternalOptions.fMilitiaStrategicCommand = iniReader.ReadBoolean("Militia Strategic Movement Settings", "ALLOW_MILITIA_STRATEGIC_COMMAND", FALSE ); + + // SANDRO - added several bonuses for militia //################# Militia Strength Settings ################## diff --git a/GameSettings.h b/GameSettings.h index 159efbbfc..3a07a73af 100644 --- a/GameSettings.h +++ b/GameSettings.h @@ -444,6 +444,9 @@ typedef struct BOOLEAN gfAllowMilitiaSpread; //Moa: TRUE spread normal, FALSE fill up to max UINT8 gbMobileMilitiaMaxActiveMode; //Moa: Used to check if the maximum of mobile militia is reached (for training/deserting). THIS IS A MODE FLOAT gfpMobileMilitiaMaxActiveModifier; //Moa: const multiplier for the mode used (precalculated with MOBILE_MILITIA_MAX_ACTIVE_MODIFIER * MAX_MILITIA_PER_SECTOR). + + // Flugente: militia movement + BOOLEAN fMilitiaStrategicCommand; BOOLEAN gfAllowReinforcements; BOOLEAN gfAllowReinforcementsOnlyInCity; diff --git a/GameVersion.h b/GameVersion.h index c4f8f32d8..dd840c974 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 MILITIA_PATH_PLOTTING 162 // Flugente: the player can plot militia paths in strategic, similar to player or helicopter travel #define STRATEGIC_TEAM_GROUPS 161 // Flugente: a change to the GROUP-structure allows any team to have strategic movement groups #define PMC_WEBSITE 160 // Flugente: a new PMC allows us to hire trained militia #define DISEASE_SYSTEM 159 // Flugente: mercs can get diseases @@ -80,7 +81,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 STRATEGIC_TEAM_GROUPS +#define SAVE_GAME_VERSION MILITIA_PATH_PLOTTING //#define RUSSIANGOLD #ifdef __cplusplus diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 74c8c73ca..8ebac3e05 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -3992,11 +3992,21 @@ BOOLEAN SaveGame( int ubSaveGameID, STR16 pGameDesc ) ScreenMsg( FONT_MCOLOR_WHITE, MSG_ERROR, L"ERROR writing vehicle info"); goto FAILED_TO_SAVE; } - #ifdef JA2BETAVERSION - SaveGameFilePosition( FileGetPos( hFile ), "Vehicle Information" ); - #endif +#ifdef JA2BETAVERSION + SaveGameFilePosition( FileGetPos( hFile ), "Vehicle Information" ); +#endif + // Flugente: militia movement + if ( !SaveMilitiaMovementInformationToSaveGameFile( hFile ) ) + { + ScreenMsg( FONT_MCOLOR_WHITE, MSG_ERROR, L"ERROR writing militia movement" ); + goto FAILED_TO_SAVE; + } + +#ifdef JA2BETAVERSION + SaveGameFilePosition( FileGetPos( hFile ), "Militia Movement" ); +#endif if( !SaveBulletStructureToSaveGameFile( hFile ) ) { @@ -4017,10 +4027,7 @@ BOOLEAN SaveGame( int ubSaveGameID, STR16 pGameDesc ) #ifdef JA2BETAVERSION SaveGameFilePosition( FileGetPos( hFile ), "Physics Table" ); #endif - - - - + if( !SaveAirRaidInfoToSaveGameFile( hFile ) ) { @@ -5268,16 +5275,11 @@ BOOLEAN LoadSavedGame( int ubSavedGameID ) } - - - uiRelEndPerc += 1; SetRelativeStartAndEndPercentage( 0, uiRelStartPerc, uiRelEndPerc, L"Vehicle Information..." ); RenderProgressBar( 0, 100 ); uiRelStartPerc = uiRelEndPerc; - - if( guiCurrentSaveGameVersion >= 22 ) { if( !LoadVehicleInformationFromSavedGameFile( hFile, guiCurrentSaveGameVersion ) ) @@ -5286,20 +5288,33 @@ BOOLEAN LoadSavedGame( int ubSavedGameID ) FileClose( hFile ); return(FALSE); } - #ifdef JA2BETAVERSION - LoadGameFilePosition( FileGetPos( hFile ), "Vehicle Information" ); - #endif + +#ifdef JA2BETAVERSION + LoadGameFilePosition( FileGetPos( hFile ), "Vehicle Information" ); +#endif } + uiRelEndPerc += 1; + SetRelativeStartAndEndPercentage( 0, uiRelStartPerc, uiRelEndPerc, L"Militia Movement..." ); + RenderProgressBar( 0, 100 ); + uiRelStartPerc = uiRelEndPerc; + if ( !LoadMilitiaMovementInformationFromSavedGameFile( hFile, guiCurrentSaveGameVersion ) ) + { + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "LoadMilitiaMovementInformationFromSavedGameFile failed" ) ); + FileClose( hFile ); + return(FALSE); + } + +#ifdef JA2BETAVERSION + LoadGameFilePosition( FileGetPos( hFile ), "Militia Movement" ); +#endif uiRelEndPerc += 1; SetRelativeStartAndEndPercentage( 0, uiRelStartPerc, uiRelEndPerc, L"Bullet Information..." ); RenderProgressBar( 0, 100 ); uiRelStartPerc = uiRelEndPerc; - - if( guiCurrentSaveGameVersion >= 24 ) { if( !LoadBulletStructureFromSavedGameFile( hFile ) ) @@ -6520,9 +6535,8 @@ BOOLEAN SaveSoldierStructure( HWFILE hFile ) UINT8 ubZero = 0; //Loop through all the soldier structs to save - for( cnt=0; cnt< TOTAL_SOLDIERS; cnt++) + for( cnt=0; cnt< TOTAL_SOLDIERS; ++cnt) { - //if the soldier isnt active, dont add them to the saved game file. if( !Menptr[ cnt ].bActive ) { @@ -6533,7 +6547,6 @@ BOOLEAN SaveSoldierStructure( HWFILE hFile ) return(FALSE); } } - else { // Save the byte specifing to load the soldiers @@ -6587,6 +6600,7 @@ BOOLEAN SaveSoldierStructure( HWFILE hFile ) } } } + return( TRUE ); } @@ -6661,8 +6675,7 @@ BOOLEAN LoadSoldierStructure( HWFILE hFile ) // Load the pMercPath if( !LoadMercPathToSoldierStruct( hFile, ubId ) ) return( FALSE ); - - + // //do we have a KEY_ON_RING *pKeyRing; // @@ -6694,7 +6707,6 @@ BOOLEAN LoadSoldierStructure( HWFILE hFile ) return(FALSE); } } - } else { @@ -6869,13 +6881,13 @@ BOOLEAN SaveFilesToSavedGame( STR pSrcFileName, HWFILE hFile ) HWFILE hSrcFile=NULL; UINT8 *pData; UINT32 uiNumBytesRead; - - + if(FileExists(pSrcFileName)) { //open the file hSrcFile = FileOpen( pSrcFileName, FILE_ACCESS_READ | FILE_OPEN_EXISTING, FALSE ); } + if( !hSrcFile ) { // Write the the size of the file to the saved game file @@ -6888,11 +6900,10 @@ BOOLEAN SaveFilesToSavedGame( STR pSrcFileName, HWFILE hFile ) return( TRUE ); } - #ifdef JA2BETAVERSION - guiNumberOfMapTempFiles++; //Increment counter: To determine where the temp files are crashing - #endif - - +#ifdef JA2BETAVERSION + ++guiNumberOfMapTempFiles; //Increment counter: To determine where the temp files are crashing +#endif + //Get the file size of the source data file uiFileSize = FileGetSize( hSrcFile ); if( uiFileSize == 0 ) @@ -6905,8 +6916,6 @@ BOOLEAN SaveFilesToSavedGame( STR pSrcFileName, HWFILE hFile ) return(FALSE); } - - //Allocate a buffer to read the data into pData = (UINT8 *) MemAlloc( uiFileSize ); if( pData == NULL ) @@ -6923,8 +6932,6 @@ BOOLEAN SaveFilesToSavedGame( STR pSrcFileName, HWFILE hFile ) return(FALSE); } - - // Write the buffer to the saved game file FileWrite( hFile, pData, uiFileSize, &uiNumBytesWritten ); if( uiNumBytesWritten != uiFileSize ) @@ -6941,10 +6948,10 @@ BOOLEAN SaveFilesToSavedGame( STR pSrcFileName, HWFILE hFile ) //Clsoe the source data file FileClose( hSrcFile ); - #ifdef JA2BETAVERSION +#ifdef JA2BETAVERSION //Write out the name of the temp file so we can track whcih ones get loaded, and saved - WriteTempFileNameToFile( pSrcFileName, uiFileSize, hFile ); - #endif + WriteTempFileNameToFile( pSrcFileName, uiFileSize, hFile ); +#endif return( TRUE ); } @@ -6957,9 +6964,7 @@ BOOLEAN LoadFilesFromSavedGame( STR pSrcFileName, HWFILE hFile ) HWFILE hSrcFile; UINT8 *pData; UINT32 uiNumBytesRead; - - - + //If the source file exists, delete it if( FileExists( pSrcFileName ) ) { @@ -6970,9 +6975,9 @@ BOOLEAN LoadFilesFromSavedGame( STR pSrcFileName, HWFILE hFile ) } } - #ifdef JA2BETAVERSION - guiNumberOfMapTempFiles++; //Increment counter: To determine where the temp files are crashing - #endif +#ifdef JA2BETAVERSION + ++guiNumberOfMapTempFiles; //Increment counter: To determine where the temp files are crashing +#endif //open the destination file to write to hSrcFile = FileOpen( pSrcFileName, FILE_ACCESS_WRITE | FILE_CREATE_ALWAYS, FALSE ); @@ -6982,7 +6987,6 @@ BOOLEAN LoadFilesFromSavedGame( STR pSrcFileName, HWFILE hFile ) return( FALSE ); } - // Read the size of the data FileRead( hFile, &uiFileSize, sizeof( UINT32 ), &uiNumBytesRead ); if( uiNumBytesRead != sizeof( UINT32 ) ) @@ -6992,7 +6996,6 @@ BOOLEAN LoadFilesFromSavedGame( STR pSrcFileName, HWFILE hFile ) return(FALSE); } - //if there is nothing in the file, return; if( uiFileSize == 0 ) { @@ -7022,8 +7025,6 @@ BOOLEAN LoadFilesFromSavedGame( STR pSrcFileName, HWFILE hFile ) return(FALSE); } - - // Write the buffer to the new file FileWrite( hSrcFile, pData, uiFileSize, &uiNumBytesWritten ); if( uiNumBytesWritten != uiFileSize ) @@ -7042,9 +7043,9 @@ BOOLEAN LoadFilesFromSavedGame( STR pSrcFileName, HWFILE hFile ) //Close the source data file FileClose( hSrcFile ); - #ifdef JA2BETAVERSION - WriteTempFileNameToFile( pSrcFileName, uiFileSize, hFile ); - #endif +#ifdef JA2BETAVERSION + WriteTempFileNameToFile( pSrcFileName, uiFileSize, hFile ); +#endif return( TRUE ); } @@ -7079,10 +7080,9 @@ BOOLEAN SaveEmailToSavedGame( HWFILE hFile ) return(FALSE); } - //loop trhough all the emails, add each one individually pEmail = pEmailList; - for( cnt=0; cntpSubject ) + 1 ) * 2; @@ -7101,7 +7101,6 @@ BOOLEAN SaveEmailToSavedGame( HWFILE hFile ) return(FALSE); } - //Get the current emails data and asign it to the 'Saved email' struct SavedEmail.usOffset = pEmail->usOffset; SavedEmail.usLength = pEmail->usLength; @@ -7891,15 +7890,13 @@ BOOLEAN SaveMercPathFromSoldierStruct( HWFILE hFile, UINT8 ubID ) PathStPtr pTempPath = Menptr[ ubID ].pMercPath; UINT32 uiNumBytesWritten=0; - //loop through to get all the nodes while( pTempPath ) { - uiNumOfNodes++; + ++uiNumOfNodes; pTempPath = pTempPath->pNext; } - //Save the number of the nodes FileWrite( hFile, &uiNumOfNodes, sizeof( UINT32 ), &uiNumBytesWritten ); if( uiNumBytesWritten != sizeof( UINT32 ) ) @@ -7910,8 +7907,7 @@ BOOLEAN SaveMercPathFromSoldierStruct( HWFILE hFile, UINT8 ubID ) //loop through all the nodes and add them pTempPath = Menptr[ ubID ].pMercPath; - - //loop through nodes and save all the nodes + //loop through nodes and save all the nodes while( pTempPath ) { //Save the number of the nodes @@ -7924,8 +7920,6 @@ BOOLEAN SaveMercPathFromSoldierStruct( HWFILE hFile, UINT8 ubID ) pTempPath = pTempPath->pNext; } - - return( TRUE ); } @@ -7938,9 +7932,7 @@ BOOLEAN LoadMercPathToSoldierStruct( HWFILE hFile, UINT8 ubID ) PathStPtr pTemp = NULL; UINT32 uiNumBytesRead=0; UINT32 cnt; - - - + //The list SHOULD be empty at this point /* //if there is nodes, loop through and delete them @@ -7968,7 +7960,7 @@ BOOLEAN LoadMercPathToSoldierStruct( HWFILE hFile, UINT8 ubID ) } //load all the nodes - for( cnt=0; cntubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks > gGameExternalOptions.iMaxEnemyGroupSize ) diff --git a/Strategic/AI Viewer.cpp b/Strategic/AI Viewer.cpp index bd75b5460..be0d3eed8 100644 --- a/Strategic/AI Viewer.cpp +++ b/Strategic/AI Viewer.cpp @@ -37,6 +37,7 @@ #include "Auto Resolve.h" #include "Strategic Status.h" #include "wordwrap.h" + #include "Town Militia.h" // added by Flugente #endif #ifdef JA2BETAVERSION @@ -452,27 +453,29 @@ void RenderStationaryGroups() { HVOBJECT hVObject; SECTORINFO *pSector; - INT32 x, y, xp, yp; + INT32 xp, yp; CHAR16 str[20]; INT32 iSector = 0; UINT8 ubIconColor = 0; UINT8 ubGroupSize = 0; - SetFont( FONT10ARIAL ); SetFontShadow( FONT_NEARBLACK ); GetVideoObject( &hVObject, guiMapIconsID ); - Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ + Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ //Render groups that are stationary... - for( y = 0; y < 16; y++ ) + for ( INT32 y = 0; y < 16; ++y ) { yp = VIEWER_TOP + VIEWER_CELLH * y + 1; - for( x = 0; x < 16; x++ ) + for ( INT32 x = 0; x < 16; ++x ) { SetFontForeground( FONT_YELLOW ); xp = VIEWER_LEFT + VIEWER_CELLW * x + 1; + + iSector = SECTOR(x, y); + pSector = &SectorInfo[ iSector ]; if( pSector->uiFlags & SF_MINING_SITE ) @@ -480,20 +483,21 @@ void RenderStationaryGroups() if( pSector->uiFlags & SF_SAM_SITE ) BltVideoObject( FRAME_BUFFER, hVObject, SAM_ICON, xp + 20, yp + 4, VO_BLT_SRCTRANSPARENCY, NULL ); + + UINT8 nummilitia = NumNonPlayerTeamMembersInSector( x, y, MILITIA_TEAM ); - - if( pSector->ubNumberOfCivsAtLevel[0] + pSector->ubNumberOfCivsAtLevel[1] + pSector->ubNumberOfCivsAtLevel[2] ) + if ( nummilitia ) { // show militia ubIconColor = ICON_COLOR_BLUE; - ubGroupSize = pSector->ubNumberOfCivsAtLevel[0] + pSector->ubNumberOfCivsAtLevel[1] + pSector->ubNumberOfCivsAtLevel[2]; + ubGroupSize = nummilitia; } - else - if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks ) + else if( pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks ) { // show enemies ubIconColor = ChooseEnemyIconColor( pSector->ubNumAdmins, pSector->ubNumTroops, pSector->ubNumElites, pSector->ubNumTanks ); ubGroupSize = pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks; + if( pSector->ubGarrisonID != NO_GARRISON ) { if( gGarrisonGroup[ pSector->ubGarrisonID ].ubPendingGroupID ) @@ -527,7 +531,7 @@ void RenderStationaryGroups() mprintf( xp + 2, yp + 2, str ); } - iSector++; + ++iSector; } } } @@ -753,8 +757,8 @@ void RenderInfoInSector() ubMercs, ubActive, ubUnconcious, ubCollapsed ); yp += 10; SetFontForeground( FONT_LTBLUE ); - mprintf( 280, yp, L"Militia: (%d Green, %d Regular, %d Elite)", - pSector->ubNumberOfCivsAtLevel[0], pSector->ubNumberOfCivsAtLevel[1], pSector->ubNumberOfCivsAtLevel[2] ); + mprintf( 280, yp, L"Militia: (%d Green, %d Regular, %d Elite)", + MilitiaInSectorOfRank( ubSectorX, ubSectorY, GREEN_MILITIA ), MilitiaInSectorOfRank( ubSectorX, ubSectorY, REGULAR_MILITIA ), MilitiaInSectorOfRank( ubSectorX, ubSectorY, ELITE_MILITIA ) ); yp += 10; SetFontForeground( FONT_ORANGE ); mprintf( 280, yp, L"Garrison: (%d:%d Admins, %d:%d Troops, %d:%d Elites, %d:%d Tanks)", @@ -967,19 +971,17 @@ void HandleViewerInput() pSector = NULL; if( gsSelSectorX && gsSelSectorY ) { - pSector = &SectorInfo[ SECTOR( gsSelSectorX, gsSelSectorY ) ]; - pSector->ubNumberOfCivsAtLevel[0] = 15; - pSector->ubNumberOfCivsAtLevel[1] = 4; - pSector->ubNumberOfCivsAtLevel[2] = 1; + StrategicAddMilitiaToSector( gsSelSectorX, gsSelSectorY, GREEN_MILITIA, 15 ); + StrategicAddMilitiaToSector( gsSelSectorX, gsSelSectorY, REGULAR_MILITIA, 4 ); + StrategicAddMilitiaToSector( gsSelSectorX, gsSelSectorY, ELITE_MILITIA, 1 ); gfRenderMap = TRUE; EliminateAllEnemies( (UINT8)gsSelSectorX, (UINT8)gsSelSectorY ); } else if( gsHiSectorX && gsHiSectorY ) { - pSector = &SectorInfo[ SECTOR( gsHiSectorX, gsHiSectorY ) ]; - pSector->ubNumberOfCivsAtLevel[0] = 15; - pSector->ubNumberOfCivsAtLevel[1] = 4; - pSector->ubNumberOfCivsAtLevel[2] = 1; + StrategicAddMilitiaToSector( gsHiSectorX, gsHiSectorY, GREEN_MILITIA, 15 ); + StrategicAddMilitiaToSector( gsHiSectorX, gsHiSectorY, REGULAR_MILITIA, 4 ); + StrategicAddMilitiaToSector( gsHiSectorX, gsHiSectorY, ELITE_MILITIA, 1 ); gfRenderMap = TRUE; EliminateAllEnemies( (UINT8)gsHiSectorX, (UINT8)gsHiSectorY ); } diff --git a/Strategic/Assignments.cpp b/Strategic/Assignments.cpp index b0012dbb4..8ba358f0f 100644 --- a/Strategic/Assignments.cpp +++ b/Strategic/Assignments.cpp @@ -3026,7 +3026,6 @@ UINT32 CalculateSnitchGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts ) UINT32 CalculateAllGuardsValueInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) { - SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); UINT32 prisonguardvalue = 0; // count any mercs found here, and sum up their guard values @@ -3036,7 +3035,7 @@ UINT32 CalculateAllGuardsValueInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) UINT32 lastid = gTacticalStatus.Team[ OUR_TEAM ].bLastID; for ( uiCnt = firstid, pSoldier = MercPtrs[ uiCnt ]; uiCnt <= lastid; ++uiCnt, ++pSoldier) { - if( pSoldier->bActive && ( pSoldier->sSectorX == sMapX ) && ( pSoldier->sSectorY == sMapY ) && ( pSoldier->bSectorZ == bZ) && pSoldier->flags.fMercAsleep == FALSE ) + if( pSoldier->bActive && ( pSoldier->sSectorX == sMapX ) && ( pSoldier->sSectorY == sMapY ) && ( pSoldier->bSectorZ == bZ) && !pSoldier->flags.fMercAsleep ) { UINT16 tmp; prisonguardvalue += CalculatePrisonGuardValue(pSoldier, &tmp ); @@ -3044,14 +3043,13 @@ UINT32 CalculateAllGuardsValueInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) } // add militia strength - prisonguardvalue += 100 * pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + 150 * pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + 200 * pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + prisonguardvalue += 100 * MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) + 150 * MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) + 200 * MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ); return( prisonguardvalue ); } UINT32 CalculateAllSnitchesGuardValueInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) { - SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); UINT32 prisonguardvalue = 0; // count any mercs found here, and sum up their guard values @@ -3069,14 +3067,13 @@ UINT32 CalculateAllSnitchesGuardValueInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ } // add militia strength - prisonguardvalue += 100 * pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + 150 * pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + 200 * pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + prisonguardvalue += 100 * MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) + 150 * MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) + 200 * MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ); return( prisonguardvalue ); } UINT32 CalculateAllGuardsNumberInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) { - SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); UINT8 numprisonguards = 0; // count any mercs found here @@ -3095,7 +3092,7 @@ UINT32 CalculateAllGuardsNumberInPrison( INT16 sMapX, INT16 sMapY, INT8 bZ ) } // add militia strength - numprisonguards += pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + numprisonguards += NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ); return( numprisonguards ); } @@ -18075,6 +18072,10 @@ BOOLEAN BasicCanCharacterTrainMobileMilitia( SOLDIERTYPE *pSoldier ) return ( FALSE ); } + // Flugente: not allowed if we can move militia in strategic, as this then becomes pointless + if ( gGameExternalOptions.fMilitiaStrategicCommand ) + return FALSE; + // Is character dead or unconscious? if( pSoldier->stats.bLife < OKLIFE ) { diff --git a/Strategic/Auto Resolve.cpp b/Strategic/Auto Resolve.cpp index 600fc9e66..fcd6efed3 100644 --- a/Strategic/Auto Resolve.cpp +++ b/Strategic/Auto Resolve.cpp @@ -608,7 +608,7 @@ void EnterAutoResolveMode( UINT8 ubSectorX, UINT8 ubSectorY ) CreateDestroyMapInvButton(); RenderButtons(); -DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve1"); + DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve1"); // WDS - make number of mercenaries, etc. be configurable //Allocate memory for all the globals while we are in this mode. gpAR = (AUTORESOLVE_STRUCT*)MemAlloc( sizeof( AUTORESOLVE_STRUCT ) ); @@ -784,7 +784,7 @@ void AssociateEnemiesWithStrategicGroups() //Now go through our enemies in the autoresolve array, and assign the ubGroupID to the soldier //Stationary groups have a group ID of 0 - for( i = 0; i < gpAR->ubEnemies; i++ ) + for( i = 0; i < gpAR->ubEnemies; ++i ) { if( gpEnemies[ i ].uiFlags & CELL_ELITE && ubNumElites ) { @@ -826,7 +826,7 @@ void AssociateEnemiesWithStrategicGroups() pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && pGroup->ubSectorX == gpAR->ubSectorX && pGroup->ubSectorY == gpAR->ubSectorY ) + if ( pGroup->usGroupTeam == ENEMY_TEAM && pGroup->ubSectorX == gpAR->ubSectorX && pGroup->ubSectorY == gpAR->ubSectorY ) { ubNumElitesInGroup = pGroup->pEnemyGroup->ubNumElites; ubNumTroopsInGroup = pGroup->pEnemyGroup->ubNumTroops; @@ -876,7 +876,7 @@ void AssociateEnemiesWithStrategicGroups() while( pGroup ) { // Don't process road block. It'll be processed as static - if ( pGroup->ubGroupID && pGroup->usGroupTeam != OUR_TEAM && IsGroupInARightSectorToReinforce( pGroup, gpAR->ubSectorX, gpAR->ubSectorY ) ) + if ( pGroup->ubGroupID && pGroup->usGroupTeam == ENEMY_TEAM && IsGroupInARightSectorToReinforce( pGroup, gpAR->ubSectorX, gpAR->ubSectorY ) ) { ubNumElitesInGroup = pGroup->pEnemyGroup->ubNumElites; ubNumTroopsInGroup = pGroup->pEnemyGroup->ubNumTroops; @@ -919,12 +919,11 @@ void AssociateEnemiesWithStrategicGroups() } pGroup = pGroup->next; } - - -// Set GroupID = 0 for the rest + + // Set GroupID = 0 for the rest ubDirAmount = GetAdjacentSectors( pSectors, gpAR->ubSectorX, gpAR->ubSectorY ); - for( ubCurrSI = 0; ubCurrSI < ubDirAmount; ubCurrSI++ ) + for( ubCurrSI = 0; ubCurrSI < ubDirAmount; ++ubCurrSI ) { pSector = &SectorInfo[ pSectors[ ubCurrSI ] ]; @@ -933,7 +932,7 @@ void AssociateEnemiesWithStrategicGroups() ubISNumElites = pSector->ubNumElites; ubISNumTanks = pSector->ubNumTanks; - for( i = 0; i < gpAR->ubEnemies; i++ ) + for( i = 0; i < gpAR->ubEnemies; ++i ) { if( ubISNumAdmins + ubISNumTroops + ubISNumElites + ubISNumTanks <= gubReinforcementMinEnemyStaticGroupSize ) break; @@ -978,7 +977,6 @@ void AssociateEnemiesWithStrategicGroups() } } } - } @@ -2790,11 +2788,11 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2"); gbGreenToRegPromotions = 0; gbRegToElitePromotions = 0; gbMilitiaPromotions = 0; - for( i = 0; i < MAX_AR_TEAM_SIZE; i++ ) + for( i = 0; i < MAX_AR_TEAM_SIZE; ++i ) { if( gpCivs[ i ].pSoldier ) { - ubCurrentRank = MAX_AR_TEAM_SIZE; + ubCurrentRank = GREEN_MILITIA; switch( gpCivs[ i ].pSoldier->ubSoldierClass ) { case SOLDIER_CLASS_GREEN_MILITIA: ubCurrentRank = GREEN_MILITIA; break; @@ -2829,18 +2827,24 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2"); { if( ubPromotions == 2 ) { - gbGreenToElitePromotions++; - gbMilitiaPromotions++; + ++gbGreenToElitePromotions; + ++gbMilitiaPromotions; + + ubCurrentRank = ELITE_MILITIA; } else if( gpCivs[ i ].pSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA ) { - gbGreenToRegPromotions++; - gbMilitiaPromotions++; + ++gbGreenToRegPromotions; + ++gbMilitiaPromotions; + + ubCurrentRank = REGULAR_MILITIA; } else if( gpCivs[ i ].pSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA ) { - gbRegToElitePromotions++; - gbMilitiaPromotions++; + ++gbRegToElitePromotions; + ++gbMilitiaPromotions; + + ubCurrentRank = ELITE_MILITIA; } } } @@ -2850,8 +2854,27 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2"); } } + // Flugente: after we fought, move any militia in groups into the sector garrison - the player will likely want to rethink orders for the survivors + // Flugente: in case militia died we have to lower the group sizes + // loop over all militia groups that are in this sector and alter their size. If a group has size 0 delete it. If any militia are left place them into this sector + { + GROUP* pGroup = gpGroupList; + while ( pGroup ) + { + if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubSectorX == gpAR->ubSectorX && pGroup->ubSectorY == gpAR->ubSectorY ) + { + GROUP* pDeleteGroup = pGroup; + pGroup = pGroup->next; + + DissolveMilitiaGroup( pDeleteGroup->ubGroupID ); + } + else + pGroup = pGroup->next; + } + } + //Record and process all enemy deaths - for( i = 0; i < MAX_AR_TEAM_SIZE; i++ ) + for( i = 0; i < MAX_AR_TEAM_SIZE; ++i ) { if( gpEnemies[ i ].pSoldier ) { @@ -2877,7 +2900,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2"); } } //Physically delete the soldiers now. - for( i = 0; i < MAX_AR_TEAM_SIZE; i++ ) + for( i = 0; i < MAX_AR_TEAM_SIZE; ++i ) { if( gpEnemies[ i ].pSoldier ) { @@ -2886,14 +2909,15 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2"); } } - for( i = 0; i < NUM_AR_BUTTONS; i++ ) + for( i = 0; i < NUM_AR_BUTTONS; ++i ) { UnloadButtonImage( gpAR->iButtonImage[ i ] ); RemoveButton( gpAR->iButton[ i ] ); } - if( fDeleteForGood ) - { //Warp the game time accordingly + if( fDeleteForGood ) + { + //Warp the game time accordingly WarpGameTime( gpAR->uiTotalElapsedBattleTimeInMilliseconds/1000, WARPTIME_NO_PROCESSING_OF_EVENTS ); //Deallocate all of the global memory. @@ -2909,7 +2933,6 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2"); MemFree( gpEnemies ); gpEnemies = NULL; - } //KM : Aug 09, 1999 Patch fix -- Would break future dialog while time compressing diff --git a/Strategic/LuaInitNPCs.cpp b/Strategic/LuaInitNPCs.cpp index 01a83bc20..3219244e7 100644 --- a/Strategic/LuaInitNPCs.cpp +++ b/Strategic/LuaInitNPCs.cpp @@ -2701,9 +2701,8 @@ BOOLEAN LuaInternalQuest( UINT8 ubQuest, INT16 sSectorX, INT16 sSectorY, BOOLEAN if ( Init == 0 ) { LuaFunction(_LS.L, "InternalEndQuest" ).Param(ubQuest).Param(sSectorX).Param(sSectorY).Param(fUpdateHistory).Call(4); - } - - if ( Init == 1 ) + } + else if ( Init == 1 ) { LuaFunction(_LS.L, "InternalStartQuest" ).Param(ubQuest).Param(sSectorX).Param(sSectorY).Param(fUpdateHistory).Call(4); } diff --git a/Strategic/Map Screen Interface Border.cpp b/Strategic/Map Screen Interface Border.cpp index bcaa153ea..2a440675c 100644 --- a/Strategic/Map Screen Interface Border.cpp +++ b/Strategic/Map Screen Interface Border.cpp @@ -32,6 +32,7 @@ // HEADROCK HAM 5: Required for inventory filter popup #include "popup_callback.h" #include "popup_class.h" + #include "Queen Command.h" // added by Flugente #endif #include "connect.h" @@ -167,12 +168,9 @@ void DeleteMapBorderGraphics( void ) // procedure will delete graphics loaded for map border DeleteVideoObjectFromIndex( guiMapBorder ); - - return; } - void RenderMapBorder( void ) { // renders the actual border to the guiSAVEBUFFER @@ -201,7 +199,7 @@ void RenderMapBorder( void ) // get and blt border GetVideoObject(&hHandle, guiMapBorder ); // HEADROCK HAM 4: Load different map border depending on whether we want to display the mobile militia button or not. - if (gGameExternalOptions.gfAllowMilitiaGroups) + if ( gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ) { BltVideoObject( guiSAVEBUFFER , hHandle, 1, xResOffset + MAP_BORDER_X, yResOffset + MAP_BORDER_Y, VO_BLT_SRCTRANSPARENCY,NULL ); } @@ -214,8 +212,6 @@ void RenderMapBorder( void ) // show the level marker DisplayCurrentLevelMarker( ); - - return; } @@ -229,7 +225,7 @@ void RenderMapBorderEtaPopUp( void ) return; } - if( fPlotForHelicopter == TRUE ) + if( fPlotForHelicopter ) { DisplayDistancesForHelicopter( ); return; @@ -250,8 +246,6 @@ void RenderMapBorderEtaPopUp( void ) BltVideoObject( FRAME_BUFFER , hHandle, 2, xVal, yVal, VO_BLT_SRCTRANSPARENCY,NULL ); InvalidateRegion( xVal, yVal, xVal + 100 , yVal + 19); - - return; } BOOLEAN CreateButtonsForMapBorder( void ) @@ -302,7 +296,7 @@ BOOLEAN CreateButtonsForMapBorder( void ) // WANNE: Only display the buton when mobile militia is allowed! // HEADROCK HAM 4: Mobile Restrictions Button - if (gGameExternalOptions.gfAllowMilitiaGroups) + if ( gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ) { giMapBorderButtonsImage[ MAP_BORDER_MOBILE_BTN ] = LoadButtonImage( "INTERFACE\\map_border_buttons.sti" ,-1,20,-1,21,-1 ); giMapBorderButtons[ MAP_BORDER_MOBILE_BTN ] = QuickCreateButton( giMapBorderButtonsImage[ MAP_BORDER_MOBILE_BTN ], MAP_BORDER_MOBILE_BTN_X, MAP_BORDER_MOBILE_BTN_Y, @@ -318,7 +312,7 @@ BOOLEAN CreateButtonsForMapBorder( void ) SetButtonFastHelpText( giMapBorderButtons[ MAP_BORDER_ITEM_BTN ], pMapScreenBorderButtonHelpText[ MAP_BORDER_ITEM_BTN ] ); SetButtonFastHelpText( giMapBorderButtons[ MAP_BORDER_MILITIA_BTN ], pMapScreenBorderButtonHelpText[ MAP_BORDER_MILITIA_BTN ] ); - if (gGameExternalOptions.gfAllowMilitiaGroups) + if ( gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ) SetButtonFastHelpText( giMapBorderButtons[ MAP_BORDER_MOBILE_BTN ], pMapScreenBorderButtonHelpText[ MAP_BORDER_MOBILE_BTN ] ); // HEADROCK HAM 4: Mobile Militia button SetButtonCursor(giMapBorderButtons[ MAP_BORDER_TOWN_BTN ], MSYS_NO_CURSOR ); @@ -328,7 +322,7 @@ BOOLEAN CreateButtonsForMapBorder( void ) SetButtonCursor(giMapBorderButtons[ MAP_BORDER_ITEM_BTN ], MSYS_NO_CURSOR ); SetButtonCursor(giMapBorderButtons[ MAP_BORDER_MILITIA_BTN ], MSYS_NO_CURSOR ); - if (gGameExternalOptions.gfAllowMilitiaGroups) + if ( gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ) SetButtonCursor(giMapBorderButtons[ MAP_BORDER_MOBILE_BTN ], MSYS_NO_CURSOR ); // HEADROCK HAM 4: Mobile Militia button // Flugente: disease @@ -438,7 +432,7 @@ void DeleteMapBorderButtons( void ) RemoveButton( giMapBorderButtons[ MAP_BORDER_MILITIA_BTN ]); // WANNE: Only remove if we added the button - if (gGameExternalOptions.gfAllowMilitiaGroups) + if ( gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ) RemoveButton( giMapBorderButtons[ MAP_BORDER_MOBILE_BTN ]); // HEADROCK HAM 4 if ( giMapBorderButtons[MAP_BORDER_DISEASE_BTN] != -1 ) @@ -454,7 +448,7 @@ void DeleteMapBorderButtons( void ) UnloadButtonImage( giMapBorderButtonsImage[ MAP_BORDER_MILITIA_BTN ] ); // WANNE: Only unload if we added the button - if (gGameExternalOptions.gfAllowMilitiaGroups) + if ( gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ) UnloadButtonImage( giMapBorderButtonsImage[ MAP_BORDER_MOBILE_BTN ] ); // HEADROCK HAM 4 if ( giMapBorderButtonsImage[MAP_BORDER_DISEASE_BTN] != -1 ) @@ -771,7 +765,7 @@ void ToggleAirspaceMode( void ) fShowAircraftFlag = FALSE; MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); - if( fPlotForHelicopter == TRUE ) + if( fPlotForHelicopter ) { AbortMovementPlottingMode( ); } @@ -1121,7 +1115,7 @@ void TurnOnItemFilterMode( void ) MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -1189,7 +1183,7 @@ void TurnOnDiseaseFilterMode( void ) MapBorderButtonOff( MAP_BORDER_AIRSPACE_BTN ); } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -1257,7 +1251,7 @@ void TurnOnMobileFilterMode( void ) MapBorderButtonOff( MAP_BORDER_DISEASE_BTN ); } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -1375,15 +1369,12 @@ void InitializeMapBorderButtonStates( void ) BOOLEAN DoesPlayerHaveAnyMilitia( void ) { - INT16 sX, sY; - // run through list of towns that might have militia..if any return TRUE..else return FALSE - for( sX = 1; sX < MAP_WORLD_X - 1; sX++ ) + for ( INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) { - for( sY = 1; sY < MAP_WORLD_Y - 1; sY++ ) + for ( INT16 sY = 1; sY < MAP_WORLD_Y - 1; ++sY ) { - if( ( SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] - + SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] ) > 0 ) + if ( NumNonPlayerTeamMembersInSector( sX, sY, MILITIA_TEAM ) > 0 ) { // found at least one return( TRUE ); @@ -1398,25 +1389,22 @@ BOOLEAN DoesPlayerHaveAnyMilitia( void ) // HEADROCK HAM 4: Check for Mobile Militia UINT8 DoesPlayerHaveAnyMobileMilitia( void ) { - INT16 sX, sY; - - if (!gGameExternalOptions.gfAllowMilitiaGroups) + if ( !gGameExternalOptions.gfAllowMilitiaGroups || gGameExternalOptions.fMilitiaStrategicCommand ) { // Mobile Militia not allowed at all. return (0); } // run through list of towns that might have militia..if any return TRUE..else return FALSE - for( sX = 1; sX < MAP_WORLD_X - 1; sX++ ) + for ( INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX ) { - for( sY = 1; sY < MAP_WORLD_Y - 1; sY++ ) + for ( INT16 sY = 1; sY < MAP_WORLD_Y - 1; ++sY ) { // Look only in sectors where Militia Training is not allowed at all. If any militia are found there, // it means that they had to MOVE there, hence mobile militia. if (!MilitiaTrainingAllowedInSector( sX, sY, 0 )) { - if( ( SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] - + SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] ) > 0 ) + if ( NumNonPlayerTeamMembersInSector( sX, sY, MILITIA_TEAM ) > 0 ) { // found at least one return( 2 ); @@ -1535,7 +1523,7 @@ void InitMapBorderButtonCoordinates() MAP_LEVEL_MARKER_DELTA = 8; MAP_LEVEL_MARKER_WIDTH = 55; - if (gGameExternalOptions.gfAllowMilitiaGroups) + if ( gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ) { // Mobile button appears next to Militia button. MAP_BORDER_MOBILE_BTN_X = xResOffset + MAP_BORDER_X + ((SCREEN_WIDTH - MAP_BORDER_X - 2 * xResOffset) / 2) + 16; diff --git a/Strategic/Map Screen Interface Bottom.cpp b/Strategic/Map Screen Interface Bottom.cpp index f11df900f..d0d7db202 100644 --- a/Strategic/Map Screen Interface Bottom.cpp +++ b/Strategic/Map Screen Interface Bottom.cpp @@ -1339,7 +1339,7 @@ BOOLEAN AllowedToTimeCompress( void ) } // moving / confirming movement - if( ( bSelectedDestChar != -1 ) || fPlotForHelicopter || gfInConfirmMapMoveMode || fShowMapScreenMovementList ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia || gfInConfirmMapMoveMode || fShowMapScreenMovementList ) { return( FALSE ); } @@ -1680,7 +1680,7 @@ BOOLEAN CommonTimeCompressionChecks( void ) return( TRUE ); } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { // abort plotting movement AbortMovementPlottingMode( ); @@ -1700,7 +1700,6 @@ BOOLEAN AnyUsableRealMercenariesOnTeam( void ) SOLDIERTYPE *pSoldier = NULL; INT32 iCounter = 0, iNumberOnTeam = 0; - // this is for speed, this runs once/frame iNumberOnTeam = gTacticalStatus.Team[ OUR_TEAM ].bLastID; diff --git a/Strategic/Map Screen Interface Map.cpp b/Strategic/Map Screen Interface Map.cpp index 269cb3744..451703571 100644 --- a/Strategic/Map Screen Interface Map.cpp +++ b/Strategic/Map Screen Interface Map.cpp @@ -58,6 +58,10 @@ // added by Flugente extern CHAR16 gzSectorNames[256][4][MAX_SECTOR_NAME_LENGTH]; +extern UINT8 gMilitiaGroupId; +extern UINT8 gNewMilitiaGroupId; +extern PathStPtr gpMilitiaPreviousMercPath; + UINT16 MAP_GRID_X; UINT16 MAP_GRID_Y; @@ -451,6 +455,12 @@ PathStPtr pTempHelicopterPath = NULL; // character temp path PathStPtr pTempCharacterPath = NULL; +// militia temp path +PathStPtr pTempMilitiaPath = NULL; + +// draw temp path? +BOOLEAN fDrawTempMilitiaPath = FALSE; + // draw temp path? BOOLEAN fDrawTempHeliPath = FALSE; @@ -501,6 +511,7 @@ BOOLEAN gfMilitiaPopupCreated = FALSE; INT32 giAnimateRouteBaseTime = 0; INT32 giPotHeliPathBaseTime = 0; +INT32 giPotMilitiaPathBaseTime = 0; INT32 giClickHeliIconBaseTime = 0; // display the level string on the strategic map @@ -550,7 +561,6 @@ void ShowSAMSitesOnStrategicMap( void ); void MilitiaBoxMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ); // display potential path, yes or no? -void DisplayThePotentialPathForHelicopter(INT16 sMapX, INT16 sMapY ); void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies, UINT16 usNumTanks, UINT8 ubIconPosition ); void ShowUncertainNumberEnemiesInSector( INT16 sSectorX, INT16 sSectorY ); void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubIconPosition ); @@ -574,7 +584,7 @@ void AnimateRoute( PathStPtr pPath ); extern void EndConfirmMapMoveMode( void ); extern BOOLEAN CanDrawSectorCursor( void ); -void DrawIconL(INT32 MAP_GRID_X2, INT32 MAP_GRID_Y2, INT32 i, INT32 Sector_X , INT32 Sector_Y ); //Legion +void DrawIconL( INT32 MAP_GRID_X2, INT32 MAP_GRID_Y2, INT32 i ); //Legion UINT32 guiIcon2[256]; ICON_FILE gHiddenIcon[ 256 ]; @@ -587,18 +597,14 @@ BOOLEAN SaveHiddenTownToSaveGameFile( HWFILE hFile ); //--------------Legion 2----Jazz----------- -void DrawIconL(INT32 MAP_GRID_X2, INT32 MAP_GRID_Y2, INT32 i, INT32 Sector_X , INT32 Sector_Y ) +void DrawIconL(INT32 MAP_GRID_X2, INT32 MAP_GRID_Y2, INT32 i ) { - INT16 sX, sY; - HVOBJECT hHandle; - INT8 ubVidObjIndex = 0; - - GetScreenXYFromMapXY( Sector_X, Sector_Y, &sX, &sY ); + HVOBJECT hHandle; + + INT16 sX = (UINT16)(MAP_VIEW_START_X + MAP_GRID_X + (MAP_GRID_X2 * MAP_GRID_X) / 10); + INT16 sY = (UINT16)(MAP_VIEW_START_Y + MAP_GRID_Y + ((MAP_GRID_Y2 * MAP_GRID_Y) / 10) + 1); - sX = (UINT16) (MAP_VIEW_START_X + MAP_GRID_X + (MAP_GRID_X2 * MAP_GRID_X) / 10); - sY = (UINT16) (MAP_VIEW_START_Y + MAP_GRID_Y + ((MAP_GRID_Y2 * MAP_GRID_Y) / 10) + 1); - - ubVidObjIndex = 1; + INT8 ubVidObjIndex = 1; // draw Tixa in its sector GetVideoObject( &hHandle, guiIcon2[i]); @@ -616,38 +622,38 @@ void DrawMapIndexBigMap( BOOLEAN fSelectedCursorIsYellow ) BOOLEAN fDrawCursors; SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); - SetFont(MAP_FONT); - SetFontForeground(MAP_INDEX_COLOR); + SetFont(MAP_FONT); + SetFontForeground(MAP_INDEX_COLOR); // Dk Red is 163 - SetFontBackground(FONT_MCOLOR_BLACK); + SetFontBackground(FONT_MCOLOR_BLACK); fDrawCursors = CanDrawSectorCursor( ); - for(iCount=1; iCount <= MAX_VIEW_SECTORS; iCount++) + for(iCount=1; iCount <= MAX_VIEW_SECTORS; ++iCount) { - if( fDrawCursors && ( iCount == sSelMapX ) && ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) - SetFontForeground( ( UINT8 ) ( fSelectedCursorIsYellow ? FONT_YELLOW : FONT_WHITE ) ); - else if( fDrawCursors && ( iCount == gsHighlightSectorX ) ) - SetFontForeground(FONT_WHITE); - else - SetFontForeground(MAP_INDEX_COLOR); + if ( fDrawCursors && (iCount == sSelMapX) && (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) + SetFontForeground( ( UINT8 ) ( fSelectedCursorIsYellow ? FONT_YELLOW : FONT_WHITE ) ); + else if( fDrawCursors && ( iCount == gsHighlightSectorX ) ) + SetFontForeground(FONT_WHITE); + else + SetFontForeground(MAP_INDEX_COLOR); - FindFontCenterCoordinates(((INT16)(MAP_HORT_INDEX_X+( iCount - 1) *MAP_GRID_X)), MAP_HORT_INDEX_Y, MAP_GRID_X, MAP_HORT_HEIGHT, pMapHortIndex[iCount], MAP_FONT, &usX, &usY); - mprintf(usX,usY,pMapHortIndex[iCount]); + FindFontCenterCoordinates(((INT16)(MAP_HORT_INDEX_X+( iCount - 1) *MAP_GRID_X)), MAP_HORT_INDEX_Y, MAP_GRID_X, MAP_HORT_HEIGHT, pMapHortIndex[iCount], MAP_FONT, &usX, &usY); + mprintf(usX,usY,pMapHortIndex[iCount]); - if( fDrawCursors && ( iCount == sSelMapY) && ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) - SetFontForeground( ( UINT8 ) ( fSelectedCursorIsYellow ? FONT_YELLOW : FONT_WHITE ) ); - else if( fDrawCursors && ( iCount == gsHighlightSectorY ) ) - SetFontForeground(FONT_WHITE); - else - SetFontForeground(MAP_INDEX_COLOR); + if ( fDrawCursors && (iCount == sSelMapY) && (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) + SetFontForeground( ( UINT8 ) ( fSelectedCursorIsYellow ? FONT_YELLOW : FONT_WHITE ) ); + else if( fDrawCursors && ( iCount == gsHighlightSectorY ) ) + SetFontForeground(FONT_WHITE); + else + SetFontForeground(MAP_INDEX_COLOR); - FindFontCenterCoordinates(MAP_VERT_INDEX_X, ((INT16)(MAP_VERT_INDEX_Y+ ( iCount - 1) *MAP_GRID_Y)), MAP_HORT_HEIGHT, MAP_GRID_Y, pMapVertIndex[iCount], MAP_FONT, &usX, &usY); - mprintf(usX,usY,pMapVertIndex[iCount]); + FindFontCenterCoordinates(MAP_VERT_INDEX_X, ((INT16)(MAP_VERT_INDEX_Y+ ( iCount - 1) *MAP_GRID_Y)), MAP_HORT_HEIGHT, MAP_GRID_Y, pMapVertIndex[iCount], MAP_FONT, &usX, &usY); + mprintf(usX,usY,pMapVertIndex[iCount]); } - InvalidateRegion(MAP_VERT_INDEX_X, MAP_VERT_INDEX_Y,MAP_VERT_INDEX_X+MAP_HORT_HEIGHT, MAP_VERT_INDEX_Y+( iCount - 1 ) * MAP_GRID_Y ); - InvalidateRegion(MAP_HORT_INDEX_X, MAP_HORT_INDEX_Y,MAP_HORT_INDEX_X + ( iCount - 1) * MAP_GRID_X, MAP_HORT_INDEX_Y+ MAP_HORT_HEIGHT); + InvalidateRegion(MAP_VERT_INDEX_X, MAP_VERT_INDEX_Y,MAP_VERT_INDEX_X+MAP_HORT_HEIGHT, MAP_VERT_INDEX_Y+( iCount - 1 ) * MAP_GRID_Y ); + InvalidateRegion(MAP_HORT_INDEX_X, MAP_HORT_INDEX_Y,MAP_HORT_INDEX_X + ( iCount - 1) * MAP_GRID_X, MAP_HORT_INDEX_Y+ MAP_HORT_HEIGHT); SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); } @@ -655,7 +661,6 @@ void DrawMapIndexBigMap( BOOLEAN fSelectedCursorIsYellow ) void HandleShowingOfEnemiesWithMilitiaOn( void ) { - INT16 sX = 0, sY = 0; INT32 iNumberOfGreens = 0; INT32 iNumberOfRegulars = 0; INT32 iNumberOfElites = 0; @@ -667,14 +672,14 @@ void HandleShowingOfEnemiesWithMilitiaOn( void ) return; } - for( sX = 1; sX < ( MAP_WORLD_X - 1 ); sX++ ) + for ( INT16 sX = 1; sX < (MAP_WORLD_X - 1); ++sX ) { - for( sY = 1; sY < ( MAP_WORLD_Y - 1); sY++ ) + for ( INT16 sY = 1; sY < (MAP_WORLD_Y - 1); ++sY ) { // get number of each - iNumberOfGreens = SectorInfo[ SECTOR( sX, sY ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; - iNumberOfRegulars = SectorInfo[ SECTOR( sX, sY ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; - iNumberOfElites = SectorInfo[ SECTOR( sX, sY ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + iNumberOfGreens = MilitiaInSectorOfRank( sX, sY, GREEN_MILITIA ); + iNumberOfRegulars = MilitiaInSectorOfRank( sX, sY, REGULAR_MILITIA ); + iNumberOfElites = MilitiaInSectorOfRank( sX, sY, ELITE_MILITIA ); // militia icons drawn iTotalNumberOfIcons = iNumberOfGreens / 10 + iNumberOfGreens % 10 + iNumberOfRegulars / 10 + iNumberOfRegulars % 10 @@ -683,8 +688,6 @@ void HandleShowingOfEnemiesWithMilitiaOn( void ) HandleShowingOfEnemyForcesInSector( sX, sY, ( INT8 )iCurrentMapSectorZ, iTotalNumberOfIcons ); } } - - return; } @@ -698,7 +701,6 @@ UINT32 DrawMap( void ) INT16 cnt, cnt2; INT32 iCounter = 0; INT32 iCounter2 = 0; - INT16 pSectorX = 0, pSectorY = 0; INT16 sBaseSectorValue = 0; //MAP_VIEW_START_X = (SCREEN_WIDTH - 370); @@ -830,20 +832,15 @@ UINT32 DrawMap( void ) for (cnt = 1; cnt < NUM_TOWNS; ++cnt) { - if ( gfHiddenTown[ cnt ] == TRUE ) + if ( gfHiddenTown[cnt] && gfIconTown[cnt] && gfDrawHiddenTown[cnt] ) { - if ( gfIconTown[ cnt ] == TRUE && gfDrawHiddenTown[ cnt ] == TRUE ) - { - sBaseSectorValue = sBaseSectorList[ cnt-1 ]; - pSectorX = SECTORX( sBaseSectorValue ); - pSectorY = SECTORY( sBaseSectorValue ); + sBaseSectorValue = sBaseSectorList[ cnt-1 ]; - INT8 bTownId = GetTownIdForSector( pSectorX, pSectorY ); - if ( /*bTownId != 0 &&*/ bTownId < NUM_TOWNS ) - { - DrawIconL(gHiddenIcon[cnt].IconX, gHiddenIcon[cnt].IconY, cnt, pSectorX, pSectorY); - } - } + INT8 bTownId = GetTownIdForSector( SECTORX( sBaseSectorValue ), SECTORY( sBaseSectorValue ) ); + if ( /*bTownId != 0 &&*/ bTownId < NUM_TOWNS ) + { + DrawIconL( gHiddenIcon[cnt].IconX, gHiddenIcon[cnt].IconY, cnt ); + } } } @@ -871,7 +868,6 @@ UINT32 DrawMap( void ) BlitMineIcon( gMineStatus[ iCounter ].sSectorX, gMineStatus[ iCounter ].sSectorY ); } - // if mine details filter is set if( fShowMineFlag ) { @@ -911,10 +907,11 @@ UINT32 DrawMap( void ) } // show mine outlines even when viewing underground sublevels - they indicate where the mine entrances are - if( fShowMineFlag ) + if ( fShowMineFlag ) + { // draw grey mine sector borders BlitMineGridMarkers( ); - + } // do not show mercs/vehicles when airspace is ON // commented out on a trial basis! @@ -961,9 +958,6 @@ UINT32 DrawMap( void ) void GetScreenXYFromMapXY( INT16 sMapX, INT16 sMapY, INT16 *psX, INT16 *psY ) { - INT16 sXTempOff=1; - INT16 sYTempOff=1; - *psX = ( sMapX * MAP_GRID_X ) + MAP_VIEW_START_X; *psY = ( sMapY * MAP_GRID_Y ) + MAP_VIEW_START_Y; } @@ -983,9 +977,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen1"); // this procedure will display the town names on the screen SetFont(MAP_FONT); - SetFontBackground(FONT_MCOLOR_BLACK); + SetFontBackground(FONT_MCOLOR_BLACK); - for( bTown = FIRST_TOWN; bTown < NUM_TOWNS; bTown++) + for( bTown = FIRST_TOWN; bTown < NUM_TOWNS; ++bTown) { // skip Orta/Tixa until found //if( ( ( fFoundOrta != FALSE ) || ( bTown != ORTA ) ) && ( ( bTown != TIXA ) || ( fFoundTixa != FALSE) ) ) @@ -1051,7 +1045,6 @@ void DrawTownLabels(STR16 pString, STR16 pStringA, UINT16 usFirstX, UINT16 usFir return; } - SetFontDestBuffer( guiSAVEBUFFER, MapScreenRect.iLeft + 2, MapScreenRect.iTop, MapScreenRect.iRight, MapScreenRect.iBottom , FALSE ); // clip blits to mapscreen region @@ -1062,8 +1055,7 @@ void DrawTownLabels(STR16 pString, STR16 pStringA, UINT16 usFirstX, UINT16 usFir // print first string gprintfdirty( usFirstX, usFirstY, pString); - mprintf(usFirstX, usFirstY, pString); - + mprintf(usFirstX, usFirstY, pString); // calculate starting coordinates for the second string VarFindFontCenterCoordinates(( INT16 )( usFirstX ), ( INT16 )usFirstY, StringPixLength( pString, MapTownLabelsFont), 0, MapTownLabelsFont, &sSecondX, &sSecondY, pStringA); @@ -1109,7 +1101,7 @@ INT32 ShowOnDutyTeam( INT16 sMapX, INT16 sMapY ) ( pSoldier->stats.bLife > 0) && ( !PlayerIDGroupInMotion( pSoldier->ubGroupID ) ) ) { - sNumberOnDuty++; + ++sNumberOnDuty; } ++ubCounter; @@ -1119,18 +1111,19 @@ INT32 ShowOnDutyTeam( INT16 sMapX, INT16 sMapY ) ubIcon = sNumberOnDuty % 10; // draw 10x icon - for( i = 0; i < ub10xIcon; i++ ) + for ( i = 0; i < ub10xIcon; ++i ) { DrawMapBoxIcon( hIconHandle, SMALL_YELLOW_10X_BOX, sMapX, sMapY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } // draw 1x icon - for( i = 0; i < ubIcon; i++ ) + for ( i = 0; i < ubIcon; ++i ) { DrawMapBoxIcon( hIconHandle, SMALL_YELLOW_BOX, sMapX, sMapY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } + return ubIconPosition; } @@ -1167,7 +1160,7 @@ INT32 ShowAssignedTeam(INT16 sMapX, INT16 sMapY, INT32 iCount) // skip mercs inside the helicopter if we're showing airspace level - they show up inside chopper icon instead if ( !fShowAircraftFlag || ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iHelicopterVehicleId ) ) { - sNumberOfAssigned++; + ++sNumberOfAssigned; } } @@ -1178,17 +1171,17 @@ INT32 ShowAssignedTeam(INT16 sMapX, INT16 sMapY, INT32 iCount) ubIcon = sNumberOfAssigned % 10; // draw 10x icon - for( i = 0; i < ub10xIcon; i++ ) + for( i = 0; i < ub10xIcon; ++i ) { DrawMapBoxIcon( hIconHandle, SMALL_DULL_YELLOW_10X_BOX, sMapX, sMapY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } // draw 1x icon - for( i = 0; i < ubIcon; i++ ) + for ( i = 0; i < ubIcon; ++i ) { DrawMapBoxIcon( hIconHandle, SMALL_DULL_YELLOW_BOX, sMapX, sMapY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } return ubIconPosition; } @@ -1225,7 +1218,7 @@ INT32 ShowVehicles(INT16 sMapX, INT16 sMapY, INT32 iCount) { if ( pVehicleSoldier->bTeam == gbPlayerNum ) { - sNumberOfVehiclesInSector++; + ++sNumberOfVehiclesInSector; } } } @@ -1238,18 +1231,19 @@ INT32 ShowVehicles(INT16 sMapX, INT16 sMapY, INT32 iCount) ubIcon = sNumberOfVehiclesInSector % 10; // draw 10x icon - for( i = 0; i < ub10xIcon; i++ ) + for( i = 0; i < ub10xIcon; ++i ) { DrawMapBoxIcon( hIconHandle, SMALL_WHITE_10X_BOX, sMapX, sMapY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } // draw 1x icon - for( i = 0; i < ubIcon; i++ ) + for( i = 0; i < ubIcon; ++i ) { DrawMapBoxIcon( hIconHandle, SMALL_WHITE_BOX, sMapX, sMapY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } + return ubIconPosition; } @@ -1301,14 +1295,14 @@ void ShowEnemiesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sNumberOfEnemies else if ( ub10xEnemy > 0 ) { DrawMapBoxIcon( hIconHandle, SMALL_RED_10X_BOX, sSectorX, sSectorY, ubIconPosition ); - ub10xEnemy--; - ubIconPosition++; + --ub10xEnemy; + ++ubIconPosition; } else if ( ubEnemy > 0 ) { DrawMapBoxIcon( hIconHandle, SMALL_RED_BOX, sSectorX, sSectorY, ubIconPosition ); - ubEnemy--; - ubIconPosition++; + --ubEnemy; + ++ubIconPosition; } } } @@ -1403,8 +1397,7 @@ void ShowTeamAndVehicles(INT32 fShowFlags) INT16 sMapY = 0; INT32 iIconOffset = 0; BOOLEAN fContemplatingRetreating = FALSE; - - + if( gfDisplayPotentialRetreatPaths && gpBattleGroup ) { fContemplatingRetreating = TRUE; @@ -1839,8 +1832,59 @@ void CancelPathForGroup( GROUP *pGroup ) CancelPathForVehicle( &( pVehicleList[ iVehicleId ] ), FALSE ); } + else if ( pGroup->usGroupTeam == MILITIA_TEAM ) + { + CancelPathForMilitiaGroup( pGroup->ubGroupID ); + } } +void CancelPathForMilitiaGroup( UINT8 uGroupId ) +{ + // we're clearing everything beyond the *current* sector, that's quite different. Since we're basically cancelling + // his movement completely, we must also make sure his next X,Y are changed and he officially "returns" to his sector + INT16 militiapathslot = GetMilitiaPathSlot( uGroupId ); + + if ( militiapathslot > -1 ) + { + gMilitiaPath[militiapathslot].path = ClearStrategicPathList( gMilitiaPath[militiapathslot].path, uGroupId ); + // NOTE: This automatically calls RemoveGroupWaypoints() internally for valid movement groups + + // if we already reversed one of the passengers, flag will be TRUE, + // don't do it again or we're headed back where we came from! + /*if ( !fAlreadyReversed ) + { + // This causes the group to effectively reverse directions (even if they've never actually left), so handle that. + // They are going to return to their current X,Y sector. + RebuildWayPointsForGroupPath( pVehicle->pMercPath, pVehicle->ubMovementGroup ); + // GroupReversingDirectionsBetweenSectors( GetGroup( pVehicle->ubMovementGroup ), ( UINT8 ) ( pVehicle->sSectorX ), ( UINT8 ) ( pVehicle->sSectorY ), FALSE ); + }*/ + + RebuildWayPointsForGroupPath( gMilitiaPath[militiapathslot].path, uGroupId ); + + // remove group's next and prev to make them stay here + GROUP* pGroup = GetGroup( uGroupId ); + + if ( pGroup ) + { + pGroup->ubNextX = pGroup->ubSectorX; + pGroup->ubNextY = pGroup->ubSectorY; + + pGroup->ubPrevX = 0; + pGroup->ubPrevY = 0; + } + } + + // display "travel route canceled" message + MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[3] ); + + MilitiaplotFinish(); + + fPlotForMilitia = FALSE; + + fTeamPanelDirty = TRUE; + fMapPanelDirty = TRUE; + fCharacterInfoPanelDirty = TRUE; // to update ETA +} void CopyPathToCharactersSquadIfInOne( SOLDIERTYPE *pCharacter ) @@ -1880,8 +1924,6 @@ void DisplaySoldierPath( SOLDIERTYPE *pCharacter ) // trace real route TracePathRoute( FALSE, TRUE, pPath ); AnimateRoute( pPath ); - - return; } @@ -1889,8 +1931,6 @@ void DisplaySoldierTempPath( SOLDIERTYPE *pCharacter ) { // now render temp route TracePathRoute( FALSE, TRUE, pTempCharacterPath ); - - return; } @@ -1901,28 +1941,48 @@ void DisplayHelicopterPath( void ) pVehicleList[ iHelicopterVehicleId ].pMercPath = MoveToBeginningOfPathList( pVehicleList[ iHelicopterVehicleId ].pMercPath ); // clip to map - ClipBlitsToMapViewRegion( ); + ClipBlitsToMapViewRegion( ); // trace both lists..temp is conditional if cursor has sat in same sector grid long enough - TracePathRoute( TRUE, TRUE, pVehicleList[ iHelicopterVehicleId ].pMercPath ); + TracePathRoute( TRUE, TRUE, pVehicleList[ iHelicopterVehicleId ].pMercPath ); AnimateRoute( pVehicleList[ iHelicopterVehicleId ].pMercPath ); // restore RestoreClipRegionToFullScreen( ); - - return; } - void DisplayHelicopterTempPath( void ) { //should we draw temp path? if( fDrawTempHeliPath ) { - TracePathRoute( TRUE, TRUE, pTempHelicopterPath ); + TracePathRoute( TRUE, TRUE, pTempHelicopterPath ); } +} - return; +void DisplayMilitiaPath( void ) +{ + // move to beginning of path list + gMilitiaPath[gMilitiaGroupId].path = MoveToBeginningOfPathList( gMilitiaPath[gMilitiaGroupId].path ); + + // clip to map + ClipBlitsToMapViewRegion( ); + + // trace both lists..temp is conditional if cursor has sat in same sector grid long enough + TracePathRoute( TRUE, TRUE, gMilitiaPath[gMilitiaGroupId].path ); + AnimateRoute( gMilitiaPath[gMilitiaGroupId].path ); + + // restore + RestoreClipRegionToFullScreen( ); +} + +void DisplayMilitiaTempPath( void ) +{ + //should we draw temp path? + if ( fDrawTempMilitiaPath ) + { + TracePathRoute( TRUE, TRUE, pTempMilitiaPath ); + } } extern BOOLEAN HeliCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum ); @@ -1966,8 +2026,6 @@ void PlotPathForHelicopter( INT16 sX, INT16 sY ) pVehicleList[ iHelicopterVehicleId ].pMercPath = MoveToBeginningOfPathList( pVehicleList[ iHelicopterVehicleId ].pMercPath ); fMapPanelDirty = TRUE; - - return; } void PlotATemporaryPathForHelicopter( INT16 sX, INT16 sY ) @@ -1984,8 +2042,69 @@ void PlotATemporaryPathForHelicopter( INT16 sX, INT16 sY ) // build path pTempHelicopterPath = BuildAStrategicPath( NULL, GetLastSectorOfHelicoptersPath( ), ( INT16 )( sX + sY*( MAP_WORLD_X ) ), pVehicleList[ iHelicopterVehicleId ].ubMovementGroup, FALSE /*, TRUE */ ); +} - return; +void PlotPathForMilitia( INT16 sX, INT16 sY ) +{ + //SOLDIERTYPE *pSkyRider = NULL; + + // will plot the path for the helicopter + + // no heli...go back + if ( !fShowMilitia ) + { + return; + } + + // is cursor allowed here?..if not..don't build path + if ( !IsTheCursorAllowedToHighLightThisSector( sX, sY ) ) + { + return; + } + + // preparations for militia path plotting + SetUpMilitiaForMovement( ); + + if ( gMilitiaPath[gMilitiaGroupId].sGroupid < 0 ) + return; + + //CHRISL: If we've plotted a path through enemy controlled airspace, we have a new Skyrider speech we want to hear. + /*if ( GetNumUnSafeSectorsInPath( ) > 0 && !gGameSettings.fOptions[TOPTION_SILENT_SKYRIDER] ) + { + HeliCharacterDialogue( pSkyRider, HELI_PATH_THROUGH_ENEMEY_AIRSPACE ); + }*/ + + // move to beginning of list + //pHelicopterPath = MoveToBeginningOfPathList( pVehicleList[ iHelicopterVehicleId ].pMercPath ); + MoveToBeginningOfPathList( gMilitiaPath[gMilitiaGroupId].path ); + + // will plot a path from current position to sX, sY + // get last sector in helicopters list, build new path, remove tail section, move to beginning of list, and append onto old list + gMilitiaPath[gMilitiaGroupId].path = AppendStrategicPath( MoveToBeginningOfPathList( BuildAStrategicPath( NULL, GetLastSectorOfMilitiaPath( ), (INT16)(sX + sY*(MAP_WORLD_X)), gMilitiaPath[gMilitiaGroupId].sGroupid, TRUE /*, FALSE */ ) ), gMilitiaPath[gMilitiaGroupId].path ); + + // move to beginning of list + gMilitiaPath[gMilitiaGroupId].path = MoveToBeginningOfPathList( gMilitiaPath[gMilitiaGroupId].path ); + + fMapPanelDirty = TRUE; +} + +void PlotATemporaryPathForMilitia( INT16 sX, INT16 sY ) +{ + // clear old temp path + pTempMilitiaPath = MoveToBeginningOfPathList( pTempMilitiaPath ); + pTempMilitiaPath = ClearStrategicPathList( pTempMilitiaPath, 0 ); + + // is cursor allowed here?..if not..don't build temp path + if ( !IsTheCursorAllowedToHighLightThisSector( sX, sY ) ) + { + return; + } + + if ( gMilitiaPath[gMilitiaGroupId].sGroupid < 0 ) + return; + + // build path + pTempMilitiaPath = BuildAStrategicPath( NULL, GetLastSectorOfMilitiaPath( ), (INT16)(sX + sY*(MAP_WORLD_X)), gMilitiaPath[gMilitiaGroupId].sGroupid, TRUE /*, TRUE */ ); } @@ -1995,7 +2114,6 @@ UINT32 ClearPathAfterThisSectorForHelicopter( INT16 sX, INT16 sY ) VEHICLETYPE *pVehicle = NULL; INT32 iOrigLength = 0; - // clear out helicopter path list, after and including this sector if( iHelicopterVehicleId == -1 || !CanHelicopterFly() ) { @@ -2003,10 +2121,8 @@ UINT32 ClearPathAfterThisSectorForHelicopter( INT16 sX, INT16 sY ) return( ABORT_PLOTTING ); } - pVehicle = &( pVehicleList[ iHelicopterVehicleId ] ); - - + iOrigLength = GetLengthOfPath( pVehicle->pMercPath ); if( !iOrigLength ) { @@ -2014,7 +2130,6 @@ UINT32 ClearPathAfterThisSectorForHelicopter( INT16 sX, INT16 sY ) return( ABORT_PLOTTING ); } - // are we clearing everything beyond the helicopter's CURRENT sector? if ( ( sX == pVehicle->sSectorX ) && ( sY == pVehicle->sSectorY ) ) { @@ -2043,6 +2158,60 @@ UINT32 ClearPathAfterThisSectorForHelicopter( INT16 sX, INT16 sY ) } } +// clear out militia path list, after and including this sector +UINT32 ClearPathAfterThisSectorForMilitia( INT16 sX, INT16 sY ) +{ + //VEHICLETYPE *pVehicle = NULL; + INT32 iOrigLength = 0; + + if ( gMilitiaPath[gMilitiaGroupId].sGroupid < 0 ) + return(ABORT_PLOTTING); + + // clear out helicopter path list, after and including this sector + /*if ( iHelicopterVehicleId == -1 || !CanHelicopterFly( ) ) + { + // abort plotting, shouldn't even be here + return(ABORT_PLOTTING); + } + + pVehicle = &(pVehicleList[iHelicopterVehicleId]);*/ + + iOrigLength = GetLengthOfPath( gMilitiaPath[gMilitiaGroupId].path ); + if ( !iOrigLength ) + { + // no previous path, nothing to do, and we didn't shorten it + return(ABORT_PLOTTING); + } + + GROUP* pGroup = GetGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); + + // are we clearing everything beyond the helicopter's CURRENT sector? + if ( pGroup && (sX == pGroup->ubSectorX) && (sY == pGroup->ubSectorY) ) + { + // if we're in confirm map move mode, cancel that (before new UI messages are issued) + EndConfirmMapMoveMode( ); + + CancelPathForGroup( pGroup ); + return(PATH_CLEARED); + } + else // click not in the current sector + { + // if the clicked sector is along current route, this will repath only as far as it. If not, the entire path will + // be canceled. + gMilitiaPath[gMilitiaGroupId].path = ClearStrategicPathListAfterThisSector( gMilitiaPath[gMilitiaGroupId].path, sX, sY, gMilitiaPath[gMilitiaGroupId].sGroupid ); + + if ( GetLengthOfPath( gMilitiaPath[gMilitiaGroupId].path ) < iOrigLength ) + { + // really shortened! + return(PATH_SHORTENED); + } + else + { + // same path as before - it's not any shorter + return (ABORT_PLOTTING); + } + } +} INT16 GetLastSectorOfHelicoptersPath( void ) @@ -2062,6 +2231,23 @@ INT16 GetLastSectorOfHelicoptersPath( void ) return sLastSector; } +INT16 GetLastSectorOfMilitiaPath( void ) +{ + // will return the last sector of the helicopter's current path + INT16 sLastSector = gMilitiaPlotStartSector;//pVehicleList[iHelicopterVehicleId].sSectorX + pVehicleList[iHelicopterVehicleId].sSectorY * MAP_WORLD_X; + PathStPtr pNode = NULL; + + pNode = gMilitiaPath[gMilitiaGroupId].path; + + while ( pNode ) + { + sLastSector = (INT16)(pNode->uiSectorId); + pNode = pNode->pNext; + } + + return sLastSector; +} + BOOLEAN TracePathRoute(BOOLEAN fCheckFlag, BOOLEAN fForceUpDate, PathStPtr pPath ) { @@ -2084,7 +2270,7 @@ BOOLEAN TracePathRoute(BOOLEAN fCheckFlag, BOOLEAN fForceUpDate, PathStPtr pPath while( pPath->pPrev ) { - pPath = pPath->pPrev; + pPath = pPath->pPrev; } pNode = pPath; @@ -2468,16 +2654,17 @@ BOOLEAN TracePathRoute(BOOLEAN fCheckFlag, BOOLEAN fForceUpDate, PathStPtr pPath pPastNode=pNode; pNode=pNode->pNext; + if(!pNode) return( FALSE ); + if (pNode->pNext) - pNextNode=pNode->pNext; + pNextNode=pNode->pNext; else - pNextNode=NULL; + pNextNode=NULL; } return ( TRUE ); - } @@ -2487,11 +2674,11 @@ void AnimateRoute( PathStPtr pPath ) SetFontDestBuffer( FRAME_BUFFER, 0,0,SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); // the animated path - if( TraceCharAnimatedRoute( pPath, FALSE, FALSE )) - { -// ARM? Huh? Why the same thing twice more? - TraceCharAnimatedRoute( pPath, FALSE, TRUE ); - TraceCharAnimatedRoute( pPath, FALSE, TRUE ); + if( TraceCharAnimatedRoute( pPath, FALSE, FALSE )) + { + // ARM? Huh? Why the same thing twice more? + TraceCharAnimatedRoute( pPath, FALSE, TRUE ); + TraceCharAnimatedRoute( pPath, FALSE, TRUE ); } } @@ -2516,9 +2703,8 @@ BOOLEAN TraceCharAnimatedRoute( PathStPtr pPath, BOOLEAN fCheckFlag, BOOLEAN fFo PathStPtr pPastNode=NULL; PathStPtr pNextNode=NULL; - // must be plotting movement - if ( ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) + if ( (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { return FALSE; } @@ -2741,20 +2927,18 @@ void DisplayThePotentialPathForHelicopter(INT16 sMapX, INT16 sMapY ) { // simply check if we want to refresh the screen to display path static BOOLEAN fOldShowAirCraft = FALSE; - static INT16 sOldMapX, sOldMapY; + static INT16 sOldMapX, sOldMapY; INT32 iDifference = 0; - if( fOldShowAirCraft != fShowAircraftFlag ) { fOldShowAirCraft = fShowAircraftFlag; - giPotHeliPathBaseTime = GetJA2Clock( ); + giPotHeliPathBaseTime = GetJA2Clock( ); sOldMapX = sMapX; sOldMapY = sMapY; fTempPathAlreadyDrawn = FALSE; fDrawTempHeliPath = FALSE; - } if( ( sMapX != sOldMapX) || ( sMapY != sOldMapY ) ) @@ -2787,34 +2971,75 @@ void DisplayThePotentialPathForHelicopter(INT16 sMapX, INT16 sMapY ) giPotHeliPathBaseTime = GetJA2Clock( ); fTempPathAlreadyDrawn = TRUE; } +} - return; +void DisplayThePotentialPathForMilitia( INT16 sMapX, INT16 sMapY ) +{ + // simply check if we want to refresh the screen to display path + static BOOLEAN fOldShow = FALSE; + static INT16 sOldMapX, sOldMapY; + INT32 iDifference = 0; + + if ( fOldShow != fShowMilitia ) + { + fOldShow = fShowMilitia; + giPotMilitiaPathBaseTime = GetJA2Clock( ); + + sOldMapX = sMapX; + sOldMapY = sMapY; + fTempPathAlreadyDrawn = FALSE; + fDrawTempMilitiaPath = FALSE; + } + + if ( (sMapX != sOldMapX) || (sMapY != sOldMapY) ) + { + giPotMilitiaPathBaseTime = GetJA2Clock( ); + + sOldMapX = sMapX; + sOldMapY = sMapY; + + // path was plotted and we moved, re draw map..to clean up mess + if ( fTempPathAlreadyDrawn ) + { + fMapPanelDirty = TRUE; + } + + fTempPathAlreadyDrawn = FALSE; + fDrawTempMilitiaPath = FALSE; + } + + iDifference = GetJA2Clock( ) - giPotMilitiaPathBaseTime; + + if ( fTempPathAlreadyDrawn ) + { + return; + } + + //if ( iDifference > MIN_WAIT_TIME_FOR_TEMP_PATH ) + { + fDrawTempMilitiaPath = TRUE; + giPotMilitiaPathBaseTime = GetJA2Clock( ); + fTempPathAlreadyDrawn = TRUE; + } } BOOLEAN IsTheCursorAllowedToHighLightThisSector( INT16 sSectorX, INT16 sSectorY ) { // check to see if this sector is a blocked out sector? - if( sBadSectorsList[ sSectorX ][ sSectorY ] ) - { return ( FALSE ); - } - else - { - // return cursor is allowed to highlight this sector - return ( TRUE ); - } + + // return cursor is allowed to highlight this sector + return (TRUE); } void RestoreBackgroundForMapGrid( INT16 sMapX, INT16 sMapY ) { - INT16 sX, sY; - // screen values - sX=(sMapX * MAP_GRID_X ) + MAP_VIEW_START_X; - sY=(sMapY * MAP_GRID_Y ) + MAP_VIEW_START_Y; + INT16 sX = (sMapX * MAP_GRID_X) + MAP_VIEW_START_X; + INT16 sY = (sMapY * MAP_GRID_Y) + MAP_VIEW_START_Y; // restore background RestoreExternBackgroundRect( sX, sY ,DMAP_GRID_X ,DMAP_GRID_Y ); @@ -2854,8 +3079,6 @@ void ClipBlitsToMapViewRegionForRectangleAndABit( UINT32 uiDestPitchBYTES ) // clip blits to map view region // because MC's map coordinates system is so screwy, these had to be hand-tuned to work right... ARM SetClippingRegionAndImageWidth( uiDestPitchBYTES, MapScreenRect.iLeft - 1, MapScreenRect.iTop - 1, MapScreenRect.iRight - MapScreenRect.iLeft + 3, MapScreenRect.iBottom - MapScreenRect.iTop + 2 ); - - return; } void RestoreClipRegionToFullScreenForRectangle( UINT32 uiDestPitchBYTES ) @@ -2864,8 +3087,6 @@ void RestoreClipRegionToFullScreenForRectangle( UINT32 uiDestPitchBYTES ) //SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, 640, 480 ); SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); - - return; } @@ -3507,7 +3728,7 @@ void ShowNonPlayerGroupsInMotion( INT16 sX, INT16 sY, UINT8 usTeam ) GROUP *curr; curr = gpGroupList; - while( curr->next ) + while( curr ) { if ( curr->usGroupTeam != OUR_TEAM && curr->usGroupTeam == usTeam && curr->ubSectorX == sX && curr->ubSectorY == sY && curr->ubSectorZ == 0 ) { @@ -3625,10 +3846,8 @@ void ShowMilitiaInMotion( INT16 sX, INT16 sY ) if( iCurrentMapSectorZ ) return; - - SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sX, sY ) ] ); - - if ( !CountMilitia(pSectorInfo) ) + + if ( !NumNonPlayerTeamMembersInSector( sX, sY, MILITIA_TEAM ) ) return; if ( ( StrategicMap[ sX + ( sY * MAP_WORLD_X ) ].usFlags & MILITIA_MOVE_ALLDIRS ) == 0 ) @@ -3723,12 +3942,10 @@ void DisplayDistancesForHelicopter( void ) INT16 sMapX, sMapY; INT16 sYPosition = 0; static INT16 sOldYPosition = 0; - INT16 sNumSafeSectors; - INT16 sNumUnSafeSectors; + INT16 sNumSafeSectors; + INT16 sNumUnSafeSectors; UINT32 uiTripCost; - - - + if ( GetMouseMapXY( &sMapX, &sMapY ) && ( sMapY >= 13 ) ) { sYPosition = MAP_HELICOPTER_UPPER_ETA_POPUP_Y; @@ -3767,8 +3984,8 @@ void DisplayDistancesForHelicopter( void ) sTotalCanTravel = ( INT16 )GetTotalDistanceHelicopterCanTravel( ); sDistanceToGo = ( INT16 )DistanceOfIntendedHelicopterPath( ); sTotalOfTrip = sDistanceToGo; // + ( INT16 ) ( DistanceToNearestRefuelPoint( ( INT16 )( LastSectorInHelicoptersPath() % MAP_WORLD_X ), ( INT16 ) ( LastSectorInHelicoptersPath() / MAP_WORLD_X ) ) ); - sNumSafeSectors = GetNumSafeSectorsInPath( ); - sNumUnSafeSectors = GetNumUnSafeSectorsInPath( ); + sNumSafeSectors = GetNumSafeSectorsInPath( ); + sNumUnSafeSectors = GetNumUnSafeSectorsInPath( ); //sDistanceSoFar = ( INT16 )HowFarHelicopterhasTravelledSinceRefueling( ); //sTotalDistanceOfTrip = ( INT16 )DistanceToNearestRefuelPoint( ); @@ -3821,8 +4038,7 @@ void DisplayDistancesForHelicopter( void ) swprintf( sString, L"%s", pHelicopterEtaStrings[ STR_HELI_ETA_TOTAL_COST ] ); mprintf( MAP_HELICOPTER_ETA_POPUP_X + 5, sYPosition + 5 + 3 * GetFontHeight( MAP_FONT ), sString ); - - + // calculate the cost of the trip based on the number of safe and unsafe sectors it will pass through // HEADROCK HAM 3.5: Externalized Base Cost. Also includes hourly-calculated facility modifier. UINT32 uiCostGreen = __max(0,gGameExternalOptions.usHelicopterBaseCostPerGreenTile + gsSkyriderCostModifier); @@ -3882,8 +4098,6 @@ void DisplayDistancesForHelicopter( void ) InvalidateRegion( MAP_HELICOPTER_ETA_POPUP_X, sOldYPosition, MAP_HELICOPTER_ETA_POPUP_X + MAP_HELICOPTER_ETA_POPUP_WIDTH + 20, sOldYPosition + MAP_HELICOPTER_ETA_POPUP_HEIGHT ); else InvalidateRegion( MAP_HELICOPTER_ETA_POPUP_X, sOldYPosition, MAP_HELICOPTER_ETA_POPUP_X + MAP_HELICOPTER_ETA_POPUP_WIDTH + 20, sOldYPosition + MAP_HELICOPTER_ETA_POPUP_ALTERNATE_HEIGHT ); - - return; } @@ -3904,8 +4118,7 @@ void DisplayPositionOfHelicopter( void ) AssertMsg( ( sOldMapX >= 0 ) && ( sOldMapX < SCREEN_WIDTH ), String( "DisplayPositionOfHelicopter: Invalid sOldMapX = %d", sOldMapX ) ); AssertMsg( ( sOldMapY >= 0 ) && ( sOldMapY < SCREEN_HEIGHT ), String( "DisplayPositionOfHelicopter: Invalid sOldMapY = %d", sOldMapY ) ); - - + // HEADROCK HAM 5: Now has to be done here to get the size of the helicopter icon. GetVideoObject( &hHandle, guiHelicopterIcon ); @@ -3921,7 +4134,8 @@ void DisplayPositionOfHelicopter( void ) sOldMapX = 0; } - if( iHelicopterVehicleId != -1 ) { + if( iHelicopterVehicleId != -1 ) + { // draw the destination icon first, so when they overlap, the real one is on top! // HEADROCK HAM 5: No reason to display this anymore: we now do it with a cool new icon displayed // while drawing the path. @@ -4021,8 +4235,6 @@ void DisplayPositionOfHelicopter( void ) sOldMapY = ( INT16 ) y; } } - - return; } @@ -4092,8 +4304,7 @@ BOOLEAN CheckForClickOverHelicopterIcon( INT16 sClickedSectorX, INT16 sClickedSe FLOAT flRatio = 0.0; INT16 sSectorX; INT16 sSectorY; - - + iDeltaTime = GetJA2Clock() - giClickHeliIconBaseTime; giClickHeliIconBaseTime = GetJA2Clock(); @@ -4112,7 +4323,6 @@ BOOLEAN CheckForClickOverHelicopterIcon( INT16 sClickedSectorX, INT16 sClickedSe return( FALSE ); } - // figure out over which sector the helicopter APPEARS to be to the player (because we slide it smoothly across the // map, unlike groups travelling on the ground, it can appear over its next sector while it's not there yet. @@ -4136,7 +4346,6 @@ BOOLEAN CheckForClickOverHelicopterIcon( INT16 sClickedSectorX, INT16 sClickedSe } } - if ( fHelicopterOverNextSector ) { // use the next sector's coordinates @@ -4166,8 +4375,7 @@ void BlitMineIcon( INT16 sMapX, INT16 sMapY ) UINT32 uiDestPitchBYTES; UINT8 *pDestBuf2; INT16 sScreenX, sScreenY; - - + GetVideoObject( &hHandle, guiMINEICON ); pDestBuf2 = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); @@ -4212,7 +4420,6 @@ void BlitMineText( INT16 sMapX, INT16 sMapY ) SetFontForeground( FONT_LTGREEN ); SetFontBackground( FONT_BLACK ); - ubMineIndex = GetMineIndexForSector( sMapX, sMapY ); // display associated town name, followed by "mine" @@ -4220,8 +4427,7 @@ void BlitMineText( INT16 sMapX, INT16 sMapY ) swprintf( wString, L"%s %s", pTownNames[ GetTownAssociatedWithMine( GetMineIndexForSector( sMapX, sMapY ) ) ], MineralsName[gMineStatus[ubMineIndex].ubMineType].sType ); AdjustXForLeftMapEdge(wString, &sScreenX, MapMineLabelsFont); mprintf( ( sScreenX - StringPixLength( wString, MapMineLabelsFont ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MapMineLabelsFont ) , wString ); - ubLineCnt++; - + ++ubLineCnt; // check if mine is empty (abandoned) or running out if (gMineStatus[ ubMineIndex ].fEmpty) @@ -4229,23 +4435,21 @@ void BlitMineText( INT16 sMapX, INT16 sMapY ) swprintf( wString, L"%s", pwMineStrings[ 5 ] ); AdjustXForLeftMapEdge(wString, &sScreenX, MapMineLabelsFont); mprintf( ( sScreenX - StringPixLength( wString, MapMineLabelsFont ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MapMineLabelsFont ) , wString ); - ubLineCnt++; + ++ubLineCnt; } - else - if (gMineStatus[ ubMineIndex ].fShutDown) + else if (gMineStatus[ ubMineIndex ].fShutDown) { swprintf( wString, L"%s", pwMineStrings[ 6 ] ); AdjustXForLeftMapEdge(wString, &sScreenX, MapMineLabelsFont); mprintf( ( sScreenX - StringPixLength( wString, MapMineLabelsFont ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MapMineLabelsFont ) , wString ); - ubLineCnt++; + ++ubLineCnt; } - else - if (gMineStatus[ ubMineIndex ].fRunningOut) + else if (gMineStatus[ ubMineIndex ].fRunningOut) { swprintf( wString, L"%s", pwMineStrings[ 7 ] ); AdjustXForLeftMapEdge(wString, &sScreenX, MapMineLabelsFont); mprintf( ( sScreenX - StringPixLength( wString, MapMineLabelsFont ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MapMineLabelsFont ) , wString ); - ubLineCnt++; + ++ubLineCnt; } @@ -4281,10 +4485,9 @@ void BlitMineText( INT16 sMapX, INT16 sMapY ) AdjustXForLeftMapEdge(wString, &sScreenX, MapMineLabelsFont); mprintf( ( sScreenX - StringPixLengthArg( MapMineLabelsFont, wcslen(wString), wString ) / 2 ) , sScreenY + ubLineCnt * GetFontHeight( MapMineLabelsFont ), wString ); - ubLineCnt++; + ++ubLineCnt; } - SetFontDestBuffer( FRAME_BUFFER, MAP_VIEW_START_X, MAP_VIEW_START_Y, MAP_VIEW_START_X+MAP_VIEW_WIDTH+MAP_GRID_X, MAP_VIEW_START_Y+MAP_VIEW_HEIGHT+7, FALSE ); } @@ -4313,15 +4516,13 @@ void BlitTownGridMarkers( void ) // get 16 bpp color usColor = Get16BPPColor( FROMRGB( 100, 100, 100) ); - - + // blit in the highlighted sector pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); // clip to view region ClipBlitsToMapViewRegionForRectangleAndABit( uiDestPitchBYTES ); - // go through list of towns and place on screen while( pTownNamesList[ iCounter ] != 0 ) { @@ -4357,7 +4558,7 @@ void BlitTownGridMarkers( void ) } } - iCounter++; + ++iCounter; } // restore clips @@ -4365,9 +4566,6 @@ void BlitTownGridMarkers( void ) // unlock surface UnLockVideoSurface( guiSAVEBUFFER ); - - - return; } @@ -4383,14 +4581,13 @@ void BlitMineGridMarkers( void ) // get 16 bpp color usColor = Get16BPPColor( FROMRGB( 100, 100, 100) ); - // blit in the highlighted sector pDestBuf = LockVideoSurface( guiSAVEBUFFER, &uiDestPitchBYTES ); // clip to view region ClipBlitsToMapViewRegionForRectangleAndABit( uiDestPitchBYTES ); - for( iCounter = 0; iCounter < MAX_NUMBER_OF_MINES; iCounter++ ) + for( iCounter = 0; iCounter < MAX_NUMBER_OF_MINES; ++iCounter ) { // get location on screen //GetScreenXYFromMapXY( ( INT16 )( gMineLocation[ iCounter ].sSectorX ), ( INT16 )( gMineLocation[ iCounter ].sSectorY ), &sScreenX, &sScreenY ); @@ -4407,9 +4604,6 @@ void BlitMineGridMarkers( void ) // unlock surface UnLockVideoSurface( guiSAVEBUFFER ); - - - return; } @@ -4478,8 +4672,6 @@ void DisplayLevelString( void ) mprintf( MAP_LEVEL_STRING_X, MAP_LEVEL_STRING_Y, sString ); SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE ); - - return; } @@ -4551,8 +4743,8 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen2"); } // to move a group of militia - INT32 countFreeCivPlace = iMaxMilitiaPerSector - SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] - - SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] - SectorInfo[ SECTOR( sX, sY )].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + // Flugente: we have to account for militia in groups! + INT32 countFreeCivPlace = iMaxMilitiaPerSector - NumNonPlayerTeamMembersInSector( sX, sY, MILITIA_TEAM ); if( countFreeCivPlace <= 0 ) { @@ -4782,25 +4974,21 @@ void CreateDestroyMilitiaPopUPRegions( void ) if( fShowMilitia && sSelectedMilitiaTown && !gfMilitiaPopupCreated ) { - for( iCounter = 0; iCounter < MILITIA_BOXREGIONS; ++iCounter ) { MSYS_DefineRegion( &gMapScreenMilitiaBoxRegions[ iCounter ], ( INT16 ) ( MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( iCounter % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ), ( INT16 )( MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( iCounter / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ), ( INT16 )( MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( ( iCounter ) % MILITIA_BOX_ROWS ) + 1 ) * MILITIA_BOX_BOX_WIDTH ), ( INT16 )( MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( ( iCounter ) / MILITIA_BOX_ROWS ) + 1 ) * MILITIA_BOX_BOX_HEIGHT ), MSYS_PRIORITY_HIGHEST - 3, MSYS_NO_CURSOR, MilitiaRegionMoveCallback, MilitiaRegionClickCallback ); MSYS_SetRegionUserData( &gMapScreenMilitiaBoxRegions[ iCounter ], 0, iCounter ); - } // create militia panel buttons CreateMilitiaPanelBottomButton( ); - - + gfMilitiaPopupCreated = TRUE; } else if( gfMilitiaPopupCreated && ( !fShowMilitia || !sSelectedMilitiaTown ) ) { - for( iCounter = 0; iCounter < MILITIA_BOXREGIONS; ++iCounter ) { // remove region @@ -4814,8 +5002,6 @@ void CreateDestroyMilitiaPopUPRegions( void ) gfMilitiaPopupCreated = FALSE; } - - return; } void RenderIconsPerSectorForSelectedTown( void ) @@ -4899,12 +5085,11 @@ void RenderIconsPerSectorForSelectedTown( void ) iTotalNumberOfIcons = ubGreen; // now display - for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfIcons; iCurrentTroopIcon++ ) + for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfIcons; ++iCurrentTroopIcon ) { sX = ( iCurrentTroopIcon % POPUP_MILITIA_ICONS_PER_ROW ) * MEDIUM_MILITIA_ICON_SPACING + MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + ( ( iCounter % MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_WIDTH ) + 3; sY = ( iCurrentTroopIcon / POPUP_MILITIA_ICONS_PER_ROW ) * ( MEDIUM_MILITIA_ICON_SPACING ) + MAP_MILITIA_BOX_POS_Y + MAP_MILITIA_MAP_Y + ( ( iCounter / MILITIA_BOX_ROWS ) * MILITIA_BOX_BOX_HEIGHT ) + 3; - if( iCurrentTroopIcon < ub10xElite ) { usIconValue = POPUP_BLUE_10X_BOX; @@ -4981,8 +5166,6 @@ void ShowHighLightedSectorOnMilitiaMap( void ) // blt the object BltVideoObject( FRAME_BUFFER, hVObject, 0, sX, sY, VO_BLT_SRCTRANSPARENCY, NULL ); } - - return; } @@ -5148,9 +5331,10 @@ void SetMilitiaMapButtonsText( void ) sBaseSectorValue = GetBaseSectorForCurrentTown( ); sGlobalMapSector = sBaseSectorValue + ( ( sSectorMilitiaMapSector % MILITIA_BOX_ROWS ) + ( sSectorMilitiaMapSector / MILITIA_BOX_ROWS ) * ( 16 ) ); - iNumberOfGreens = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; - iNumberOfRegulars = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; - iNumberOfElites = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + // Flugente: we can only redistribute those militia that are not in any group + iNumberOfGreens = MilitiaInSectorOfRankStationary( SECTORX( sGlobalMapSector ), SECTORY( sGlobalMapSector ), GREEN_MILITIA ); + iNumberOfRegulars = MilitiaInSectorOfRankStationary( SECTORX( sGlobalMapSector ), SECTORY( sGlobalMapSector ), REGULAR_MILITIA ); + iNumberOfElites = MilitiaInSectorOfRankStationary( SECTORX( sGlobalMapSector ), SECTORY( sGlobalMapSector ), ELITE_MILITIA ); // the greens in this sector swprintf( sString, L"%d", iNumberOfGreens ); @@ -5233,7 +5417,7 @@ void DisplayUnallocatedMilitia( void ) iTotalNumberOfIcons = ub10xGreen + ubGreen; // now display green icons - for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfIcons; iCurrentTroopIcon++ ) + for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfIcons; ++iCurrentTroopIcon ) { // get screen x and y coords sX = ( iCurrentTroopIcon % NUMBER_OF_MILITIA_ICONS_PER_LOWER_ROW ) * MEDIUM_MILITIA_ICON_SPACING + MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + 1; @@ -5260,7 +5444,7 @@ void DisplayUnallocatedMilitia( void ) iTotalNumberOfIcons = ub10xRegular + ubRegular; // now display cyan icons - for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfIcons; iCurrentTroopIcon++ ) + for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfIcons; ++iCurrentTroopIcon ) { // get screen x and y coords sX = ( iCurrentTroopIcon % NUMBER_OF_MILITIA_ICONS_PER_LOWER_ROW ) * MEDIUM_MILITIA_ICON_SPACING + MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + 1; @@ -5287,7 +5471,7 @@ void DisplayUnallocatedMilitia( void ) iTotalNumberOfIcons = ub10xElite + ubElite; // now display blue icons - for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfIcons; iCurrentTroopIcon++ ) + for( iCurrentTroopIcon = 0; iCurrentTroopIcon < iTotalNumberOfIcons; ++iCurrentTroopIcon ) { // get screen x and y coords sX = ( iCurrentTroopIcon % NUMBER_OF_MILITIA_ICONS_PER_LOWER_ROW ) * MEDIUM_MILITIA_ICON_SPACING + MAP_MILITIA_BOX_POS_X + MAP_MILITIA_MAP_X + 1; @@ -5365,7 +5549,6 @@ void HandleShutDownOfMilitiaPanelIfPeopleOnTheCursor( INT16 sTownValue ) { INT32 iCounter = 0, iCounterB = 0, iNumberUnderControl = 0, iNumberThatCanFitInSector= 0, iCount = 0; BOOLEAN fLastOne = FALSE; - INT32 iMaxMilitiaPerSector = gGameExternalOptions.iMaxMilitiaPerSector; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen3"); // check if anyone still on the cursor @@ -5382,46 +5565,40 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen3"); { if( pTownNamesList[ iCounter] == sTownValue ) { - if( SectorOursAndPeaceful( ( INT16 )( pTownLocationsList[ iCounter ] % MAP_WORLD_X ) , ( INT16 )( pTownLocationsList[ iCounter ] / MAP_WORLD_X ), 0 ) ) + INT16 sX = GET_X_FROM_STRATEGIC_INDEX( pTownLocationsList[iCounter] ); + INT16 sY = GET_Y_FROM_STRATEGIC_INDEX( pTownLocationsList[iCounter] ); + + if ( SectorOursAndPeaceful( sX, sY, 0 ) ) { iCount = 0; - iNumberThatCanFitInSector = iMaxMilitiaPerSector; - iNumberThatCanFitInSector -= SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; - iNumberThatCanFitInSector -= SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; - iNumberThatCanFitInSector -= SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; - - while( ( iCount < iNumberThatCanFitInSector )&&( ( sGreensOnCursor ) || ( sRegularsOnCursor ) || ( sElitesOnCursor ) ) ) + iNumberThatCanFitInSector = gGameExternalOptions.iMaxMilitiaPerSector - NumNonPlayerTeamMembersInSector( sX, sY, MILITIA_TEAM ); + + while( ( iCount < iNumberThatCanFitInSector ) && ( sGreensOnCursor || sRegularsOnCursor || sElitesOnCursor ) ) { // green - if( ( iCount + 1 <= iNumberThatCanFitInSector )&&( sGreensOnCursor ) ) + if( ( iCount < iNumberThatCanFitInSector ) && sGreensOnCursor ) { - SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]++; - iCount++; - sGreensOnCursor--; + StrategicAddMilitiaToSector( sX, sY, GREEN_MILITIA, 1 ); + ++iCount; + --sGreensOnCursor; } // regular - if( ( iCount + 1 <= iNumberThatCanFitInSector ) && ( sRegularsOnCursor ) ) + if( ( iCount < iNumberThatCanFitInSector ) && sRegularsOnCursor ) { - SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]++; - iCount++; - sRegularsOnCursor--; + StrategicAddMilitiaToSector( sX, sY, REGULAR_MILITIA, 1 ); + ++iCount; + --sRegularsOnCursor; } // elite - if( ( iCount + 1 <= iNumberThatCanFitInSector ) && ( sElitesOnCursor ) ) + if( ( iCount < iNumberThatCanFitInSector ) && sElitesOnCursor ) { - SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]++; - iCount++; - sElitesOnCursor--; + StrategicAddMilitiaToSector( sX, sY, ELITE_MILITIA, 1 ); + ++iCount; + --sElitesOnCursor; } } - - if( STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) == SECTOR( gWorldSectorX, gWorldSectorY ) ) - { - gfStrategicMilitiaChangesMade = TRUE; - } - } fLastOne = TRUE; @@ -5430,31 +5607,29 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen3"); while( pTownNamesList[ iCounterB ] != 0 ) { - if( pTownNamesList[ iCounterB ] == sTownValue ) + if( pTownNamesList[ iCounterB ] == sTownValue ) { fLastOne = FALSE; } - iCounterB++; + ++iCounterB; } if( fLastOne ) { - SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] += ( UINT8 )( sGreensOnCursor % iNumberUnderControl ); - SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] += ( UINT8 )( sRegularsOnCursor % iNumberUnderControl ); - SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] += ( UINT8 )( sElitesOnCursor % iNumberUnderControl ); + StrategicAddMilitiaToSector( sX, sY, GREEN_MILITIA, (UINT8)(sGreensOnCursor % iNumberUnderControl) ); + StrategicAddMilitiaToSector( sX, sY, REGULAR_MILITIA, (UINT8)(sRegularsOnCursor % iNumberUnderControl) ); + StrategicAddMilitiaToSector( sX, sY, ELITE_MILITIA, (UINT8)(sElitesOnCursor % iNumberUnderControl) ); } } - iCounter++; + ++iCounter; } // zero out numbers on the cursor sGreensOnCursor = 0; sRegularsOnCursor = 0; sElitesOnCursor = 0; - - return; } void HandleRemovalOfAllTroopsAmongstSectors( void ) @@ -5464,8 +5639,7 @@ void HandleRemovalOfAllTroopsAmongstSectors( void ) INT32 iNumberLeftOverGreen = 0, iNumberLeftOverRegular = 0, iNumberLeftOverElite = 0; INT16 sBaseSectorValue = 0, sCurrentSectorValue = 0; INT16 sSectorX = 0, sSectorY = 0; - - + // how many sectors in the selected town do we control? iNumberUnderControl = GetTownSectorsUnderControl( ( INT8 ) sSelectedMilitiaTown ); @@ -5495,19 +5669,16 @@ void HandleRemovalOfAllTroopsAmongstSectors( void ) if( !StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled ) { + // Flugente: we no use these handy functions, as this will make altering militia distribution behaviour much easier // get number of each - iNumberOfGreens += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; - iNumberOfRegulars += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; - iNumberOfElites += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; - //zero out all numbers in sectors - SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] = 0; - SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] = 0; - SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] = 0; + iNumberOfGreens += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, GREEN_MILITIA ); + iNumberOfRegulars += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, REGULAR_MILITIA ); + iNumberOfElites += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, ELITE_MILITIA ); - if( sSectorX == gWorldSectorX && sSectorY == gWorldSectorY ) - { - gfStrategicMilitiaChangesMade = TRUE; - } + //zero out all numbers in sectors + StrategicRemoveAllStaticMilitiaFromSector( sSectorX, sSectorY, GREEN_MILITIA ); + StrategicRemoveAllStaticMilitiaFromSector( sSectorX, sSectorY, REGULAR_MILITIA ); + StrategicRemoveAllStaticMilitiaFromSector( sSectorX, sSectorY, ELITE_MILITIA ); } } @@ -5520,6 +5691,7 @@ void HandleRemovalOfAllTroopsAmongstSectors( void ) SpecifyButtonText( giMapMilitiaButton[ 4 ], pMilitiaButtonString[ 2 ] ); } +// Flugente: evening out distributes all militia evenly across town sectors. Note that militia in groups are not affected - they are in a sector, but do not get redistributed void HandleEveningOutOfTroopsAmongstSectors( void ) { INT32 iMaxMilitiaPerSector = gGameExternalOptions.iMaxMilitiaPerSector; @@ -5567,9 +5739,9 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen4"); if( !StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled ) { // get number of each - iNumberOfGreens += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; - iNumberOfRegulars += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; - iNumberOfElites += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + iNumberOfGreens += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, GREEN_MILITIA ); + iNumberOfRegulars += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, REGULAR_MILITIA ); + iNumberOfElites += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, ELITE_MILITIA ); } } @@ -5608,28 +5780,30 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Map Screen4"); SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] = ( UINT8 )( iNumberOfGreens / iNumberUnderControl ); SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] = ( UINT8 )( iNumberOfRegulars / iNumberUnderControl ); SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] = ( UINT8 )( iNumberOfElites / iNumberUnderControl ); - sTotalSoFar = ( INT8 )( ( iNumberOfGreens / iNumberUnderControl ) + ( iNumberOfRegulars / iNumberUnderControl ) + ( iNumberOfElites / iNumberUnderControl ) ); + + // Flugente: as we do not move the group militia, we have to make sure we don't accidentally overfill a sector + sTotalSoFar = NumNonPlayerTeamMembersInSector( sSectorX, sSectorY, MILITIA_TEAM ); // add leftovers that weren't included in the div operation if( ( iNumberLeftOverGreen ) && ( sTotalSoFar < iMaxMilitiaPerSector ) ) { SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]++; - sTotalSoFar++; - iNumberLeftOverGreen--; + ++sTotalSoFar; + --iNumberLeftOverGreen; } if( ( iNumberLeftOverRegular )&&( sTotalSoFar < iMaxMilitiaPerSector ) ) { SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]++; - sTotalSoFar++; - iNumberLeftOverRegular--; + ++sTotalSoFar; + --iNumberLeftOverRegular; } if( ( iNumberLeftOverElite )&&( sTotalSoFar < iMaxMilitiaPerSector ) ) { SectorInfo[ sSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]++; - sTotalSoFar++; - iNumberLeftOverElite--; + ++sTotalSoFar; + --iNumberLeftOverElite; } // if this sector is currently loaded @@ -5891,9 +6065,9 @@ void DrawTownMilitiaForcesOnMap( void ) ubIconPosition = 0; // get number of each - iNumberOfGreens = SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; - iNumberOfRegulars = SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; - iNumberOfElites = SectorInfo[ SECTOR( sSectorX, sSectorY ) ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + iNumberOfGreens = MilitiaInSectorOfRank( sSectorX, sSectorY, GREEN_MILITIA ); + iNumberOfRegulars = MilitiaInSectorOfRank( sSectorX, sSectorY, REGULAR_MILITIA ); + iNumberOfElites = MilitiaInSectorOfRank( sSectorX, sSectorY, ELITE_MILITIA ); // get number of icons of each ub10xGreen = iNumberOfGreens / 10; @@ -5904,42 +6078,42 @@ void DrawTownMilitiaForcesOnMap( void ) ubElite = iNumberOfElites % 10; // first draw elites as they are more important - for( i = 0; i < ub10xElite; i++ ) + for ( i = 0; i < ub10xElite; ++i ) { DrawMapBoxIcon( hVObject, SMALL_BLUE_10X_BOX, sSectorX, sSectorY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } - for( i = 0; i < ubElite; i++ ) + for ( i = 0; i < ubElite; ++i ) { DrawMapBoxIcon( hVObject, SMALL_BLUE_BOX, sSectorX, sSectorY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } // then draw regulars - for( i = 0; i < ub10xRegular; i++ ) + for ( i = 0; i < ub10xRegular; ++i ) { DrawMapBoxIcon( hVObject, SMALL_CYAN_10X_BOX, sSectorX, sSectorY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } - for( i = 0; i < ubRegular; i++ ) + for ( i = 0; i < ubRegular; ++i ) { DrawMapBoxIcon( hVObject, SMALL_CYAN_BOX, sSectorX, sSectorY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } // last draw greens - for( i = 0; i < ub10xGreen; i++ ) + for ( i = 0; i < ub10xGreen; ++i ) { DrawMapBoxIcon( hVObject, SMALL_GREEN_10X_BOX, sSectorX, sSectorY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } - for( i = 0; i < ubGreen; i++ ) + for ( i = 0; i < ubGreen; ++i ) { DrawMapBoxIcon( hVObject, SMALL_GREEN_BOX, sSectorX, sSectorY, ubIconPosition ); - ubIconPosition++; + ++ubIconPosition; } } } @@ -5953,8 +6127,7 @@ void CheckAndUpdateStatesOfSelectedMilitiaSectorButtons( void ) // now set the militia map button text INT32 iNumberOfGreens = 0, iNumberOfRegulars = 0, iNumberOfElites = 0; INT16 sBaseSectorValue = 0, sGlobalMapSector = 0; - - + if( !fMilitiaMapButtonsCreated ) { EnableButton( giMapMilitiaButton[ 4 ] ); @@ -5965,9 +6138,9 @@ void CheckAndUpdateStatesOfSelectedMilitiaSectorButtons( void ) sBaseSectorValue = GetBaseSectorForCurrentTown( ); sGlobalMapSector = sBaseSectorValue + ( ( sSectorMilitiaMapSector % MILITIA_BOX_ROWS ) + ( sSectorMilitiaMapSector / MILITIA_BOX_ROWS ) * ( 16 ) ); - iNumberOfGreens = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + sGreensOnCursor; - iNumberOfRegulars = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + sRegularsOnCursor; - iNumberOfElites = SectorInfo[ sGlobalMapSector ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] + sElitesOnCursor; + iNumberOfGreens = MilitiaInSectorOfRankStationary( SECTORX( sGlobalMapSector ), SECTORY( sGlobalMapSector ), GREEN_MILITIA ) + sGreensOnCursor; + iNumberOfRegulars = MilitiaInSectorOfRankStationary( SECTORX( sGlobalMapSector ), SECTORY( sGlobalMapSector ), REGULAR_MILITIA ) + sRegularsOnCursor; + iNumberOfElites = MilitiaInSectorOfRankStationary( SECTORX( sGlobalMapSector ), SECTORY( sGlobalMapSector ), ELITE_MILITIA ) + sElitesOnCursor; // HEADROCK HAM 3.6: This button is no longer disabled when there are unassigned militia. In fact, // clicking the button when militia are unassigned will prompt the player to authorize disbanding them. @@ -6011,14 +6184,9 @@ void CheckAndUpdateStatesOfSelectedMilitiaSectorButtons( void ) { EnableButton( giMapMilitiaButton[ 2 ] ); } - - - return; } - - BOOLEAN ShadeUndergroundMapElem( INT16 sSectorX, INT16 sSectorY ) { INT16 sScreenX, sScreenY; @@ -6125,30 +6293,13 @@ void MilitiaBoxMaskBtnCallback(MOUSE_REGION * pRegion, INT32 iReason ) } } - -INT32 GetNumberOfMilitiaInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) -{ - INT32 iNumberInSector = 0; - - if( !bSectorZ ) - { - iNumberInSector = SectorInfo[ SECTOR( sSectorX, sSectorY )].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] - + SectorInfo[ SECTOR( sSectorX, sSectorY )].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] - + SectorInfo[ SECTOR( sSectorX, sSectorY )].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; - } - - return( iNumberInSector ); -} - - //There is a special case flag used when players encounter enemies in a sector, then retreat. The number of enemies //will display on mapscreen until time is compressed. When time is compressed, the flag is cleared, and //a question mark is displayed to reflect that the player no longer knows. This is the function that clears that //flag. void ClearAnySectorsFlashingNumberOfEnemies() { - INT32 i; - for( i = 0; i < 256; i++ ) + for ( INT32 i = 0; i < 256; ++i ) { SectorInfo[ i ].uiFlags &= ~SF_PLAYER_KNOWS_ENEMIES_ARE_HERE; } @@ -6396,6 +6547,19 @@ void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bS //ShowNonPlayerGroupsInMotion( sSectorX, sSectorY, MILITIA_TEAM ); } + // Flugente: show moving militia groups + GROUP* pGroup = gpGroupList; + while ( pGroup ) + { + if ( pGroup->usGroupTeam == MILITIA_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) + { + ShowNonPlayerGroupsInMotion( sSectorX, sSectorY, MILITIA_TEAM ); + + break; + } + pGroup = pGroup->next; + } + // get total number of badguys here sNumberOfEnemies = NumNonPlayerTeamMembersInSector( sSectorX, sSectorY, ENEMY_TEAM ); @@ -6415,7 +6579,7 @@ void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bS }*/ // Flugente: tanks get a special icon, so we need to count them separately - UINT16 usNumTanks = NumEnemyTanksInSector( sSectorX, sSectorY ); + UINT16 usNumTanks = NumTanksInSector( sSectorX, sSectorY, ENEMY_TEAM ); switch ( WhatPlayerKnowsAboutEnemiesInSector( sSectorX, sSectorY ) ) { @@ -6729,7 +6893,6 @@ BOOLEAN CanMilitiaAutoDistribute( void ) INT16 sSectorX = 0, sSectorY = 0; INT32 iTotalTroopsInTown = 0; - // can't auto-distribute if we don't have a town selected (this excludes SAM sites) if( sSelectedMilitiaTown == BLANK_SECTOR ) return( FALSE ); @@ -6738,7 +6901,6 @@ BOOLEAN CanMilitiaAutoDistribute( void ) if( !GetTownSectorsUnderControl( ( INT8 ) sSelectedMilitiaTown ) ) return( FALSE ); - // get the sector value for the upper left corner sBaseSectorValue = GetBaseSectorForCurrentTown( ); @@ -6766,13 +6928,12 @@ BOOLEAN CanMilitiaAutoDistribute( void ) if( !StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled ) { // get number of each - iTotalTroopsInTown += SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + - SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + - SectorInfo[ sCurrentSectorValue ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + iTotalTroopsInTown += MilitiaInSectorOfRankStationary( sSectorX, sSectorY, GREEN_MILITIA ) + + MilitiaInSectorOfRankStationary( sSectorX, sSectorY, REGULAR_MILITIA ) + + MilitiaInSectorOfRankStationary( sSectorX, sSectorY, ELITE_MILITIA ); } } - iTotalTroopsOnCursor = sGreensOnCursor + sRegularsOnCursor + sElitesOnCursor; // can't auto-distribute if we don't have any militia in the town @@ -7310,3 +7471,450 @@ BOOLEAN LoadHiddenTownFromLoadGameFile( HWFILE hFile ) return( TRUE ); } +// Flugente: militia pathing +BOOLEAN gMilitiaGroupBoxCreated = FALSE; +UINT16 gMilitiaGroupBoxX = 0; +UINT16 gMilitiaGroupBoxY = 0; + +#define MILITIAGROUPBOX_REGION_MAX 10 + +BOOLEAN gMilitiaGroupBoxRegionDefined[MILITIAGROUPBOX_REGION_MAX]; +MOUSE_REGION gMilitiaGroupBoxRegion[MILITIAGROUPBOX_REGION_MAX]; + +BOOLEAN gMilitiaGroupBoxDummyRegionDefined; +MOUSE_REGION gMilitiaGroupBoxDummyRegion; + +// +/- buttons to add/remove militia from a group +INT32 gMilitiaGroupBoxButtonImage[2] = {-1}; +INT32 gMilitiaGroupBoxButton[2 * MAX_MILITIA_LEVELS] = {-1}; +BOOLEAN gMilitiaGroupBoxButtonCreated[2 * MAX_MILITIA_LEVELS] = {FALSE}; + +UINT32 guiMilitiaGroupBoxTypeSymbols; + +void CreateMilitiaGroupBoxVideoObjects() +{ + gMilitiaGroupBoxButtonImage[0] = LoadButtonImage( "INTERFACE\\plusminusbuttons.sti", -1, 2, -1, 2, -1 ); + gMilitiaGroupBoxButtonImage[1] = LoadButtonImage( "INTERFACE\\plusminusbuttons.sti", -1, 3, -1, 3, -1 ); +} + +void CreateMilitiaGroupBox() +{ + INT16 sMapX, sMapY; + + if ( GetMouseMapXY( &sMapX, &sMapY ) ) + { + // if we are plotting in the upper left corner, get another position for the box + if ( sMapX < 8 && sMapY < 8 ) + { + gMilitiaGroupBoxX = MapScreenRect.iRight - 210; + gMilitiaGroupBoxY = MapScreenRect.iBottom - 200; + } + else + { + gMilitiaGroupBoxX = MapScreenRect.iLeft; + gMilitiaGroupBoxY = MapScreenRect.iTop; + } + + gMilitiaGroupBoxCreated = TRUE; + } +} + +void DestroyMilitiaGroupBox() +{ + for ( int i = 0; i < MILITIAGROUPBOX_REGION_MAX; ++i ) + { + if ( gMilitiaGroupBoxRegionDefined[i] ) + { + MSYS_RemoveRegion( &gMilitiaGroupBoxRegion[i] ); + gMilitiaGroupBoxRegionDefined[i] = FALSE; + } + } + + if ( gMilitiaGroupBoxDummyRegionDefined ) + { + MSYS_RemoveRegion( &gMilitiaGroupBoxDummyRegion ); + gMilitiaGroupBoxDummyRegionDefined = FALSE; + } + + if ( gMilitiaGroupBoxButtonImage[0] > -1 ) + { + UnloadButtonImage( gMilitiaGroupBoxButtonImage[0] ); + gMilitiaGroupBoxButtonImage[0] = -1; + } + + if ( gMilitiaGroupBoxButtonImage[1] > -1 ) + { + UnloadButtonImage( gMilitiaGroupBoxButtonImage[1] ); + gMilitiaGroupBoxButtonImage[1] = -1; + } + + for ( int i = 0; i < 2 * MAX_MILITIA_LEVELS; ++i ) + { + if ( gMilitiaGroupBoxButtonCreated[i] ) + { + // delete militia panel bottom + RemoveButton( gMilitiaGroupBoxButton[i] ); + + gMilitiaGroupBoxButtonCreated[i] = FALSE; + } + } +} + +void MilitiaGroupBoxRegionClickCallback( MOUSE_REGION *pRegion, INT32 iReason ) +{ + if ( (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP) ) + { + UINT8 usValue = (UINT8)MSYS_GetRegionUserData( pRegion, 0 ); + + INT16 slot = GetMilitiaPathSlot( usValue ); + + if ( slot > -1 ) + { + gMilitiaGroupId = (UINT8)slot; + } + } + + if ( (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) ) + { + + } +} + +void MilitiaGroupBoxButtonCallback( 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); + + GROUP* pGroup = GetGroup( gMilitiaPath[gMilitiaGroupId].sGroupid ); + + if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM ) + { + UINT8 id = (UINT8)btn->UserData[0]; + + UINT8 militiatype = id / 2; + + // for now, always alter by 1 + UINT8 howmany = 1; + + // either add or remove a militia from currently selected group + if ( id % 2 ) + { + // remove militia from group + // first, check whether we can reduce the number of militia in the group + switch ( militiatype ) + { + case GREEN_MILITIA: if ( pGroup->pEnemyGroup->ubNumAdmins < howmany ) return; break; + case REGULAR_MILITIA: if ( pGroup->pEnemyGroup->ubNumTroops < howmany ) return; break; + case ELITE_MILITIA: if ( pGroup->pEnemyGroup->ubNumElites < howmany ) return; break; + // this shouldn't happen... + default: return; break; + } + + // add one militia to the sector garrison + StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, militiatype, howmany ); + + // remove one militia from the group + switch ( militiatype ) + { + case GREEN_MILITIA: pGroup->pEnemyGroup->ubNumAdmins -= howmany; break; + case REGULAR_MILITIA: pGroup->pEnemyGroup->ubNumTroops -= howmany; break; + case ELITE_MILITIA: pGroup->pEnemyGroup->ubNumElites -= howmany; break; + } + } + else + { + // add militia to group + // first, check whether we can reduce the number of militia in the sector + INT16 sMapX = GET_X_FROM_STRATEGIC_INDEX( gMilitiaPlotStartSector ); + INT16 sMapY = GET_Y_FROM_STRATEGIC_INDEX( gMilitiaPlotStartSector ); + if ( MilitiaInSectorOfRankStationary( sMapX, sMapY, militiatype ) < howmany ) + { + return; + } + + // remove one militia from the sector garrison + StrategicRemoveMilitiaFromSector( pGroup->ubSectorX, pGroup->ubSectorY, militiatype, howmany ); + + switch ( militiatype ) + { + case GREEN_MILITIA: pGroup->pEnemyGroup->ubNumAdmins += howmany; break; + case REGULAR_MILITIA: pGroup->pEnemyGroup->ubNumTroops += howmany; break; + case ELITE_MILITIA: pGroup->pEnemyGroup->ubNumElites += howmany; break; + } + } + } + } + } +} + +void DisplayMilitiaGroupBox() +{ + if ( !gMilitiaGroupBoxCreated ) + return; + + // destroy the old stuff anyway... + DestroyMilitiaGroupBox(); + + if ( !fPlotForMilitia ) + { + gMilitiaGroupBoxCreated = FALSE; + return; + } + + CreateMilitiaGroupBoxVideoObjects(); + + // move to defines later + UINT16 MILITIAGROUPBOX_WIDTH_NAME = 80; + UINT16 MILITIAGROUPBOX_WIDTH_TYPEBOX = 20; + UINT16 MILITIAGROUPBOX_WIDTH_SECTOR = 30; + UINT16 MILITIAGROUPBOX_WIDTH_ETA = 30; + + UINT16 MILITIAGROUPBOX_HEIGHT_LINE = 14; + + UINT16 MILITIAGROUPBOX_WIDTH = MILITIAGROUPBOX_WIDTH_NAME + 3 * MILITIAGROUPBOX_WIDTH_TYPEBOX + MILITIAGROUPBOX_WIDTH_SECTOR + MILITIAGROUPBOX_WIDTH_ETA; + + // we need a header line, one for the sector, and one for each group present + UINT8 usMapX = GET_X_FROM_STRATEGIC_INDEX( gMilitiaPlotStartSector ); + UINT8 usMapY = GET_Y_FROM_STRATEGIC_INDEX( gMilitiaPlotStartSector ); + + int linecnt = 2; + { + GROUP *pGroup = gpGroupList; + while ( pGroup ) + { + if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubSectorX == usMapX && pGroup->ubSectorY == usMapY ) + ++linecnt; + + pGroup = pGroup->next; + } + } + + // not more groups than allowed though + linecnt = min( linecnt, 2 + MILITIAGROUPBOX_REGION_MAX ); + + UINT16 MILITIAGROUPBOX_HEIGHT = linecnt * MILITIAGROUPBOX_HEIGHT_LINE; + + SetFontForeground( FONT_FCOLOR_WHITE ); + SetFontBackground( FONT_MCOLOR_BLACK ); + + //Display the background for the drop down window + ColorFillVideoSurfaceArea( FRAME_BUFFER, gMilitiaGroupBoxX, gMilitiaGroupBoxY, gMilitiaGroupBoxX + MILITIAGROUPBOX_WIDTH, gMilitiaGroupBoxY + MILITIAGROUPBOX_HEIGHT, Get16BPPColor( FROMRGB( 50, 50, 50 ) ) ); + + // mouse region - clicking on a group name selects that group + if ( !gMilitiaGroupBoxDummyRegionDefined ) + { + MSYS_DefineRegion( &gMilitiaGroupBoxDummyRegion, gMilitiaGroupBoxX, gMilitiaGroupBoxY, gMilitiaGroupBoxX + MILITIAGROUPBOX_WIDTH, gMilitiaGroupBoxY + MILITIAGROUPBOX_HEIGHT, MSYS_PRIORITY_HIGH, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MSYS_NO_CALLBACK ); + MSYS_AddRegion( &gMilitiaGroupBoxDummyRegion ); + gMilitiaGroupBoxDummyRegionDefined = TRUE; + } + + UINT16 dispX = gMilitiaGroupBoxX; + UINT16 dispY = gMilitiaGroupBoxY + 2; + + CHAR16 sString[200]; + + // header + swprintf( sString, szMilitiaStrategicMovementText[2] ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_NAME; + + // display coloured boxes to represent different militia types + ColorFillVideoSurfaceArea( FRAME_BUFFER, dispX, dispY, dispX + 6, dispY + 6, Get16BPPColor( FROMRGB( 0, 231, 0 ) ) ); + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + ColorFillVideoSurfaceArea( FRAME_BUFFER, dispX, dispY, dispX + 6, dispY + 6, Get16BPPColor( FROMRGB( 0, 162, 247 ) ) ); + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + ColorFillVideoSurfaceArea( FRAME_BUFFER, dispX, dispY, dispX + 6, dispY + 6, Get16BPPColor( FROMRGB( 0, 113, 247 ) ) ); + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + + swprintf( sString, szMilitiaStrategicMovementText[3] ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_SECTOR; + + swprintf( sString, szMilitiaStrategicMovementText[4] ); + mprintf( dispX, dispY, sString ); + + dispX = gMilitiaGroupBoxX; + dispY += MILITIAGROUPBOX_HEIGHT_LINE; + + ColorFillVideoSurfaceArea( FRAME_BUFFER, dispX, dispY - 2, dispX + MILITIAGROUPBOX_WIDTH, dispY - 1, Get16BPPColor( FROMRGB( 255, 255, 255 ) ) ); + + // stationary in sector + UINT8 militiastat[MAX_MILITIA_LEVELS]; + for ( int i = 0; i < MAX_MILITIA_LEVELS; ++i ) + militiastat[i] = MilitiaInSectorOfRankStationary( usMapX, usMapY, i ); + + swprintf( sString, szMilitiaStrategicMovementText[1] ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_NAME; + + swprintf( sString, L"%d", militiastat[GREEN_MILITIA] ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + + swprintf( sString, L"%d", militiastat[REGULAR_MILITIA] ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + + swprintf( sString, L"%d", militiastat[ELITE_MILITIA] ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + + swprintf( sString, L"--" ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_SECTOR; + + swprintf( sString, L"--:--" ); + mprintf( dispX, dispY, sString ); + + dispY += MILITIAGROUPBOX_HEIGHT_LINE; + + int groupcnt = 0; + int buttoncnt = 0; + + GROUP *pGroup = gpGroupList; + while ( pGroup && groupcnt < MILITIAGROUPBOX_REGION_MAX ) + { + if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubSectorX == usMapX && pGroup->ubSectorY == usMapY ) + { + dispX = gMilitiaGroupBoxX; + + if ( gMilitiaPath[gMilitiaGroupId].sGroupid == pGroup->ubGroupID ) + { + SetFontForeground( FONT_FCOLOR_YELLOW ); + } + else + { + SetFontForeground( FONT_FCOLOR_WHITE ); + } + + CHAR16 wSectorName[64]; + GetShortSectorString( pGroup->ubNextX, pGroup->ubNextY, wSectorName ); + + // show ETA + CHAR16 timestring[64]; + UINT32 uiArrivalTime = GetWorldTotalMin( ) + CalculateTravelTimeOfGroup( pGroup ); + ConvertMinTimeToDayHourMinString( uiArrivalTime, timestring ); + + // mouse region - clicking on a group name selects that group + if ( !gMilitiaGroupBoxRegionDefined[groupcnt] ) + { + MSYS_DefineRegion( &gMilitiaGroupBoxRegion[groupcnt], dispX, dispY, dispX + MILITIAGROUPBOX_WIDTH_NAME, dispY + MILITIAGROUPBOX_HEIGHT_LINE, MSYS_PRIORITY_HIGH, + MSYS_NO_CURSOR, MSYS_NO_CALLBACK, MilitiaGroupBoxRegionClickCallback ); + MSYS_AddRegion( &gMilitiaGroupBoxRegion[groupcnt] ); + MSYS_SetRegionUserData( &gMilitiaGroupBoxRegion[groupcnt], 0, pGroup->ubGroupID ); + gMilitiaGroupBoxRegionDefined[groupcnt] = TRUE; + } + + if ( pGroup->ubGroupID == gNewMilitiaGroupId ) + swprintf( sString, szMilitiaStrategicMovementText[5], pGroup->ubGroupID ); + else + swprintf( sString, szMilitiaStrategicMovementText[6], pGroup->ubGroupID ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_NAME; + + swprintf( sString, L"%d", pGroup->pEnemyGroup->ubNumAdmins ); + mprintf( dispX, dispY, sString ); + + if ( gMilitiaPath[gMilitiaGroupId].sGroupid == pGroup->ubGroupID ) + { + // '+' button + if ( militiastat[GREEN_MILITIA] && !gMilitiaGroupBoxButtonCreated[buttoncnt] ) + { + gMilitiaGroupBoxButton[buttoncnt] = QuickCreateButton( gMilitiaGroupBoxButtonImage[0], dispX + 14, dispY, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)MilitiaGroupBoxButtonCallback ); + ButtonList[gMilitiaGroupBoxButton[buttoncnt]]->UserData[0] = buttoncnt; + gMilitiaGroupBoxButtonCreated[buttoncnt] = TRUE; + } + ++buttoncnt; + + // '-' button + if ( pGroup->pEnemyGroup->ubNumAdmins && !gMilitiaGroupBoxButtonCreated[buttoncnt] ) + { + gMilitiaGroupBoxButton[buttoncnt] = QuickCreateButton( gMilitiaGroupBoxButtonImage[1], dispX + 14, dispY + 6, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)MilitiaGroupBoxButtonCallback ); + ButtonList[gMilitiaGroupBoxButton[buttoncnt]]->UserData[0] = buttoncnt; + gMilitiaGroupBoxButtonCreated[buttoncnt] = TRUE; + } + ++buttoncnt; + } + + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + + swprintf( sString, L"%d", pGroup->pEnemyGroup->ubNumTroops ); + mprintf( dispX, dispY, sString ); + + if ( gMilitiaPath[gMilitiaGroupId].sGroupid == pGroup->ubGroupID ) + { + // '+' button + if ( militiastat[REGULAR_MILITIA] && !gMilitiaGroupBoxButtonCreated[buttoncnt] ) + { + gMilitiaGroupBoxButton[buttoncnt] = QuickCreateButton( gMilitiaGroupBoxButtonImage[0], dispX + 14, dispY, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)MilitiaGroupBoxButtonCallback ); + ButtonList[gMilitiaGroupBoxButton[buttoncnt]]->UserData[0] = buttoncnt; + gMilitiaGroupBoxButtonCreated[buttoncnt] = TRUE; + } + ++buttoncnt; + + // '-' button + if ( pGroup->pEnemyGroup->ubNumTroops && !gMilitiaGroupBoxButtonCreated[buttoncnt] ) + { + gMilitiaGroupBoxButton[buttoncnt] = QuickCreateButton( gMilitiaGroupBoxButtonImage[1], dispX + 14, dispY + 6, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)MilitiaGroupBoxButtonCallback ); + ButtonList[gMilitiaGroupBoxButton[buttoncnt]]->UserData[0] = buttoncnt; + gMilitiaGroupBoxButtonCreated[buttoncnt] = TRUE; + } + ++buttoncnt; + } + + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + + swprintf( sString, L"%d", pGroup->pEnemyGroup->ubNumElites ); + mprintf( dispX, dispY, sString ); + + if ( gMilitiaPath[gMilitiaGroupId].sGroupid == pGroup->ubGroupID ) + { + // '+' button + if ( militiastat[ELITE_MILITIA] && !gMilitiaGroupBoxButtonCreated[buttoncnt] ) + { + gMilitiaGroupBoxButton[buttoncnt] = QuickCreateButton( gMilitiaGroupBoxButtonImage[0], dispX + 14, dispY, BUTTON_NO_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)MilitiaGroupBoxButtonCallback ); + ButtonList[gMilitiaGroupBoxButton[buttoncnt]]->UserData[0] = buttoncnt; + gMilitiaGroupBoxButtonCreated[buttoncnt] = TRUE; + } + ++buttoncnt; + + // '-' button + if ( pGroup->pEnemyGroup->ubNumElites && !gMilitiaGroupBoxButtonCreated[buttoncnt] ) + { + gMilitiaGroupBoxButton[buttoncnt] = QuickCreateButton( gMilitiaGroupBoxButtonImage[1], dispX + 14, dispY + 6, BUTTON_TOGGLE, MSYS_PRIORITY_HIGHEST - 1, + DEFAULT_MOVE_CALLBACK, (GUI_CALLBACK)MilitiaGroupBoxButtonCallback ); + ButtonList[gMilitiaGroupBoxButton[buttoncnt]]->UserData[0] = buttoncnt; + gMilitiaGroupBoxButtonCreated[buttoncnt] = TRUE; + } + ++buttoncnt; + } + + dispX += MILITIAGROUPBOX_WIDTH_TYPEBOX; + + swprintf( sString, L"%s", wSectorName ); + mprintf( dispX, dispY, sString ); + dispX += MILITIAGROUPBOX_WIDTH_SECTOR; + + swprintf( sString, L"%s", timestring ); + mprintf( dispX, dispY, sString ); + + dispY += MILITIAGROUPBOX_HEIGHT_LINE; + + ++groupcnt; + } + pGroup = pGroup->next; + } +} diff --git a/Strategic/Map Screen Interface Map.h b/Strategic/Map Screen Interface Map.h index 4283877d2..be7ac0ef0 100644 --- a/Strategic/Map Screen Interface Map.h +++ b/Strategic/Map Screen Interface Map.h @@ -87,6 +87,12 @@ void PlotPathForHelicopter( INT16 sX, INT16 sY ); // the temp path, where the helicopter could go void PlotATemporaryPathForHelicopter( INT16 sX, INT16 sY ); +// plot path for helicopter +void PlotPathForMilitia( INT16 sX, INT16 sY ); + +// the temp path, where the helicopter could go +void PlotATemporaryPathForMilitia( INT16 sX, INT16 sY ); + // trace a route for a passed path...doesn't require dest char - most more general BOOLEAN TracePathRoute( BOOLEAN fCheckFlag, BOOLEAN fForceUpDate, PathStPtr pPath ); @@ -108,6 +114,8 @@ void DisplaySoldierPath( SOLDIERTYPE *pCharacter ); void DisplaySoldierTempPath( SOLDIERTYPE *pCharacter ); void DisplayHelicopterPath( void ); void DisplayHelicopterTempPath( void ); +void DisplayMilitiaPath( void ); +void DisplayMilitiaTempPath( void ); // clear path after this sector @@ -118,12 +126,18 @@ void CancelPathForCharacter( SOLDIERTYPE *pCharacter ); void CancelPathForVehicle( VEHICLETYPE *pVehicle, BOOLEAN fAlreadyReversed ); void CancelPathForGroup( GROUP *pGroup ); +void CancelPathForMilitiaGroup( UINT8 uGroupId ); + // check if we have waited long enought object update temp path void DisplayThePotentialPathForHelicopter(INT16 sMapX, INT16 sMapY ); +void DisplayThePotentialPathForMilitia( INT16 sMapX, INT16 sMapY ); + // clear out helicopter list after this sector UINT32 ClearPathAfterThisSectorForHelicopter( INT16 sX, INT16 sY ); +UINT32 ClearPathAfterThisSectorForMilitia( INT16 sX, INT16 sY ); + // check to see if sector is highlightable BOOLEAN IsTheCursorAllowedToHighLightThisSector( INT16 sSectorX, INT16 sSectorY ); @@ -150,6 +164,8 @@ void ShowMilitiaInMotion( INT16 sX, INT16 sY); // added by Flugente // last sector in helicopter's path INT16 GetLastSectorOfHelicoptersPath( void ); +INT16 GetLastSectorOfMilitiaPath( void ); + // display info about helicopter path void DisplayDistancesForHelicopter( void ); @@ -169,10 +185,6 @@ void RemoveMilitiaPopUpBox( void ); // check if anyone left behind, if not, move selected cursor along with movement group //void CheckIfAnyoneLeftInSector( INT16 sX, INT16 sY, INT16 sNewX, INT16 sNewY, INT8 bZ ); -// grab the total number of militia in sector -INT32 GetNumberOfMilitiaInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ); - - // create destroy void CreateDestroyMilitiaPopUPRegions( void ); @@ -332,6 +344,8 @@ extern SGPRect MapScreenRect; // draw temp path extern BOOLEAN fDrawTempHeliPath; +extern BOOLEAN fDrawTempMilitiaPath; + // selected destination char extern INT8 bSelectedDestChar; @@ -384,4 +398,8 @@ extern POINT pTownPoints[ MAX_TOWNS ]; extern void SetUpValidCampaignSectors( void ); #endif +void CreateMilitiaGroupBox( ); +void DestroyMilitiaGroupBox( ); +void DisplayMilitiaGroupBox( ); + #endif diff --git a/Strategic/Map Screen Interface.cpp b/Strategic/Map Screen Interface.cpp index 13d4fa3df..07772ae92 100644 --- a/Strategic/Map Screen Interface.cpp +++ b/Strategic/Map Screen Interface.cpp @@ -1349,7 +1349,7 @@ void JumpToLevel( INT32 iLevel ) return; - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -2640,7 +2640,7 @@ void GoToNextCharacterInList( void ) return; } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if( ( bSelectedDestChar != -1 ) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -2655,7 +2655,7 @@ void GoToNextCharacterInList( void ) iCount = bSelectedInfoChar + 1; } - for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) + for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter ) { if ( ( gCharactersList[ iCount ].fValid ) && ( iCount < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) && ValidSelectableCharForNextOrPrev( iCount ) ) { @@ -2664,7 +2664,7 @@ void GoToNextCharacterInList( void ) } else { - iCount++; + ++iCount; if( iCount >= giMAXIMUM_NUMBER_OF_PLAYER_SLOTS ) { @@ -2684,7 +2684,7 @@ void GoToFirstCharacterInList( void ) return; } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -2710,7 +2710,7 @@ void GoToLastCharacterInList( void ) return; } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -2736,7 +2736,7 @@ void GoToPrevCharacterInList( void ) return; } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -4636,7 +4636,6 @@ void HandleSettingTheSelectedListOfMercs( void ) SOLDIERTYPE *pSoldier = NULL; BOOLEAN fSelected; - // reset the selected character bSelectedDestChar = -1; @@ -6060,16 +6059,13 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber INT16 sSector = 0; BOOLEAN fProblemExists = FALSE; - // valid soldier? Assert( pSoldier ); Assert( pSoldier->bActive); - - + // NOTE: Check for the most permanent conditions first, and the most easily remedied ones last! // In case several cases apply, only the reason found first will be given, so make it a good one! - - + // still in transit? if( IsCharacterInTransit( pSoldier ) == TRUE ) { @@ -6084,7 +6080,6 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber return( FALSE ); } - // underground? (can't move strategically, must use tactical traversal ) if( pSoldier->bSectorZ != 0 ) { @@ -6092,7 +6087,6 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber return( FALSE ); } - // vehicle checks if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { @@ -6135,8 +6129,7 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber return( FALSE ); } } - - + // if merc is in a particular sector, not somewhere in between if ( pSoldier->flags.fBetweenSectors == FALSE ) { @@ -6178,7 +6171,6 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber } } - // if in L12 museum, and the museum alarm went off, and Eldin still around? if ( ( pSoldier->sSectorX == 12 ) && ( pSoldier->sSectorY == MAP_ROW_L ) && ( pSoldier->bSectorZ == 0 ) && ( !pSoldier->flags.fBetweenSectors ) && gMercProfiles[ ELDIN ].bMercStatus != MERC_IS_DEAD ) @@ -6190,7 +6182,6 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber if ( InARoom( pSoldier->sGridNo, &usRoom ) && usRoom >= 22 && usRoom <= 41 ) { - cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; for ( pSoldier2 = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier2++) @@ -6207,7 +6198,6 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber } } - // on assignment, other than just in a VEHICLE? if( ( pSoldier->bAssignment >= ON_DUTY ) && ( pSoldier->bAssignment != VEHICLE ) ) { @@ -6225,7 +6215,6 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber return( FALSE ); } - // a robot? if ( AM_A_ROBOT( pSoldier ) ) { @@ -6259,7 +6248,6 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber } } - // assume there's no problem fProblemExists = FALSE; @@ -6285,7 +6273,6 @@ BOOLEAN CanCharacterMoveInStrategic( SOLDIERTYPE *pSoldier, INT8 *pbErrorNumber return( FALSE ); } - // passed all checks - this character may move strategically! return( TRUE ); } @@ -6298,15 +6285,13 @@ BOOLEAN CanEntireMovementGroupMercIsInMove( SOLDIERTYPE *pSoldier, INT8 *pbError UINT8 ubGroup = 0; UINT8 ubCurrentGroup = 0; - // first check the requested character himself if( CanCharacterMoveInStrategic( pSoldier, pbErrorNumber ) == FALSE ) { // failed no point checking anyone else return( FALSE ); } - - + // now check anybody who would be travelling with him // does character have group? @@ -6376,7 +6361,6 @@ BOOLEAN CanEntireMovementGroupMercIsInMove( SOLDIERTYPE *pSoldier, INT8 *pbError } } - // everybody can move... Yey! :-) return( TRUE ); } diff --git a/Strategic/MilitiaSquads.cpp b/Strategic/MilitiaSquads.cpp index 6ea8ccad6..ffe36c2bd 100644 --- a/Strategic/MilitiaSquads.cpp +++ b/Strategic/MilitiaSquads.cpp @@ -125,34 +125,29 @@ BOOLEAN PlayerMercsInSector_MSE( UINT8 ubSectorX, UINT8 ubSectorY, BOOLEAN fDont return ubNumMercs; } - // get any enemy group id in the sector (if no group, will return 0 ) -UINT8 GetEnemyGroupIdInSector( INT16 sMapX, INT16 sMapY ) +UINT8 GetEnemyGroupIdInSector( INT16 sMapX, INT16 sMapY, UINT8 usTeam ) { UINT8 ubRes = 0; - GROUP *curr; - curr = gpGroupList; + GROUP *curr = gpGroupList; + while( curr ) { - if ( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && curr->usGroupTeam != OUR_TEAM ) + if ( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && curr->usGroupTeam == usTeam ) + { if( !curr->ubGroupID ) return curr->ubGroupID; else ubRes = curr->ubGroupID; + } + curr = curr->next; } + return ubRes; } -// Count all militia in the sector -UINT8 CountMilitia(SECTORINFO *pSectorInfo) -{ - return pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]+ - pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]+ - pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA]; -} - // Creates militia at destination sector. The type and amount of militia depends on current sector's miltia type and amount // HEADROCK HAM 3.4: Added Leadership argument. void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, UINT8 ubBestLeadership ) @@ -169,8 +164,7 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, SECTORINFO *pTargetSector = &( SectorInfo[ SECTOR( sTMapX, sTMapY ) ] ); //HEADROCK HAM B2.7: Track the number of militia at the source. - UINT16 usTotalMilitiaAtSource = pSourceSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + pSourceSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + pSourceSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; - UINT16 usTotalMilitiaAtTarget = pTargetSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + pTargetSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + pTargetSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + UINT16 usTotalMilitiaAtTarget = NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ); // Desired number of Greens, Regulars and Elites to create. UINT8 ubTargetGreen, ubTargetRegular, ubTargetElite; // Upgrade points for replacing militia with better ones. @@ -353,7 +347,6 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, ubMilitiaToTrain = 0; } } - // Full militia group? See if you can upgrade some. else { @@ -437,10 +430,9 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, if( ubActualyAdded > 0 ) RecordNumMilitiaTrainedForMercs( sMapX, sMapY, 0, ubActualyAdded, TRUE ); - // This reduces the group back to "maximum" size. It starts by eliminating extra greens, then regulars, then elites. // That produces a group of max size, with only the best troops remaining. - while( CountMilitia(pTargetSector) > gGameExternalOptions.iMaxMilitiaPerSector ) + while ( NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ) > gGameExternalOptions.iMaxMilitiaPerSector ) { if(pTargetSector->ubNumberOfCivsAtLevel[GREEN_MILITIA]) { @@ -541,14 +533,14 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL // Both sectors not threatened. // Alter spreadout chance based on number of troops in Source and destination sectors. - if ( CountMilitia(pSectorInfo) >= gGameExternalOptions.iMaxMilitiaPerSector && - CountMilitia(pTSectorInfo) == 0 ) + if ( NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ) >= gGameExternalOptions.iMaxMilitiaPerSector && + NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ) == 0 ) { // Source group is full, target sector is empty. The source group gets 30% chance to // spread out to that empty sector. ubChanceToSpreadOut = 30; } - else if ( CountMilitia(pSectorInfo) && CountMilitia(pTSectorInfo) ) + else if ( NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ) && NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ) ) { // Source and destination groups both exist. 50% chance to spread out evenly between them. ubChanceToSpreadOut = 50; @@ -565,7 +557,6 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL { ubChanceToSpreadOut = 0; } - if (!gGameExternalOptions.gfAllowMilitiaSpread ) { @@ -584,7 +575,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL // Should we spread out into the target sector, or move en-masse? if (PreRandom(100) < ubChanceToSpreadOut) { - if ( CountMilitia(pSectorInfo) && CountMilitia(pTSectorInfo) ) + if ( NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ) && NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ) ) { // Source and Target sectors both have groups in them. Source group will attempt to spread out, // averaging the size and composition of both groups. @@ -675,8 +666,8 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL { // Source team moves En-Masse to target sector. - bNewDestGroupSize = __min((CountMilitia(pTSectorInfo) + CountMilitia(pSectorInfo)), (UINT8)gGameExternalOptions.iMaxMilitiaPerSector); - bNewSourceGroupSize = __max(0,(CountMilitia(pTSectorInfo) + CountMilitia(pSectorInfo)) - gGameExternalOptions.iMaxMilitiaPerSector); + bNewDestGroupSize = __min( (NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ) + NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM )), (UINT8)gGameExternalOptions.iMaxMilitiaPerSector ); + bNewSourceGroupSize = __max( 0, (NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ) + NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM )) - gGameExternalOptions.iMaxMilitiaPerSector ); // If there are still going to be two teams after the transfer if ( bNewSourceGroupSize > 0 ) @@ -778,7 +769,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL } } - while( !fAlternativeMax && CountMilitia(pTSectorInfo) > gGameExternalOptions.iMaxMilitiaPerSector ) + while ( !fAlternativeMax && NumNonPlayerTeamMembersInSector( sTMapX, sTMapY, MILITIA_TEAM ) > gGameExternalOptions.iMaxMilitiaPerSector ) { if(pTSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]) { @@ -805,27 +796,27 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL BOOLEAN MoveOneBestMilitiaMan(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY) { - SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); -// SECTORINFO *pTSectorInfo = &( SectorInfo[ SECTOR( sTMapX, sTMapY ) ] ); - - if( pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] ) + if ( MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ) ) { StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, 1 ); StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, 1 ); return TRUE; } - if( pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] ) + + if ( MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) ) { StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, 1 ); StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, 1 ); return TRUE; } - if( pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] ) + + if ( MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) ) { StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, 1 ); StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, 1 ); return TRUE; } + return FALSE; } @@ -1242,8 +1233,8 @@ BOOLEAN CheckStandardConditionsForDirection( INT16 sSMapX, INT16 sSMapY, INT16 s { // Flags to store INI option settings. - BOOLEAN fAllowReinforceCities = ( gGameExternalOptions.fAllowMobileReinforceCities && gGameExternalOptions.gfmusttrainroaming && gGameExternalOptions.gfAllowMilitiaGroups ); - BOOLEAN fAllowReinforceSAM = ( gGameExternalOptions.fAllowMobileReinforceSAM && gGameExternalOptions.gfmusttrainroaming && gGameExternalOptions.gfAllowMilitiaGroups ); + BOOLEAN fAllowReinforceCities = (gGameExternalOptions.fAllowMobileReinforceCities && gGameExternalOptions.gfmusttrainroaming && gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ); + BOOLEAN fAllowReinforceSAM = (gGameExternalOptions.fAllowMobileReinforceSAM && gGameExternalOptions.gfmusttrainroaming && gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ); // Town->Town, Town->SAM, SAM->Town and SAM->SAM are disallowed for peaceful movement. if ( fSourceIsMajorTown || fSourceIsSamSite ) @@ -1255,7 +1246,7 @@ BOOLEAN CheckStandardConditionsForDirection( INT16 sSMapX, INT16 sSMapY, INT16 s { if ( !NumNonPlayerTeamMembersInSector( sMapX, sMapY, ENEMY_TEAM ) && // Is the sector under our control at the moment? pTargetSector->fSurfaceWasEverPlayerControlled && // Has it ever been under control? - CountMilitia(pTargetSector) < gGameExternalOptions.iMaxMilitiaPerSector ) // Is there room here for more militia? + NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ) < gGameExternalOptions.iMaxMilitiaPerSector ) // Is there room here for more militia? { if (fTargetIsSamSite && fAllowReinforceSAM) { @@ -1523,7 +1514,7 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY ) // If we don't want roaming militia // We shouldn't be here. - if( !gGameExternalOptions.gfAllowMilitiaGroups ) + if ( !gGameExternalOptions.gfAllowMilitiaGroups || gGameExternalOptions.fMilitiaStrategicCommand ) return; if( sMapX == 1 && sMapY == 1 ) @@ -1535,7 +1526,7 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY ) if( CheckInBlockMoveList( sMapX, sMapY ) ) return; - uiMilitiaCount = CountMilitia(pSectorInfo); + uiMilitiaCount = NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ); if( !uiMilitiaCount ) return; @@ -1644,7 +1635,7 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY ) if ( NumNonPlayerTeamMembersInSector( targetX, targetY, ENEMY_TEAM ) ) { extern GROUP *gpBattleGroup; - gpBattleGroup = GetGroup( GetEnemyGroupIdInSector( targetX, targetY ) ); + gpBattleGroup = GetGroup( GetEnemyGroupIdInSector( targetX, targetY, ENEMY_TEAM ) ); /* GROUP* pEnemyGroup = GetGroup( GetEnemyGroupIdInSector( targetX, targetY ) ); if(pEnemyGroup && pEnemyGroup->ubGroupID) @@ -1703,7 +1694,7 @@ void CreateMilitiaSquads(INT16 sMapX, INT16 sMapY ) UINT8 ubBestLeadership = FindBestMilitiaTrainingLeadershipInSector ( sMapX, sMapY, 0, MOBILE_MILITIA ); // If we're not allowing roaming groups, then we're not creating them either. - if( !gGameExternalOptions.gfAllowMilitiaGroups ) + if ( !gGameExternalOptions.gfAllowMilitiaGroups || gGameExternalOptions.fMilitiaStrategicCommand ) return; // Reset block move list. Does this cause issues with training in A1? Probably not. @@ -1857,7 +1848,7 @@ void DoMilitiaHelpFromAdjacentSectors( INT16 sMapX, INT16 sMapY ) guiDirNumber = uiDirNumber + 1; x = 0; - while( CountMilitia(pSectorInfo ) < gGameExternalOptions.iMaxMilitiaPerSector && + while ( NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ) < gGameExternalOptions.iMaxMilitiaPerSector && ( fMoreTroopsLeft[0] || fMoreTroopsLeft[1] || fMoreTroopsLeft[2] || fMoreTroopsLeft[3] || fFirstLoop ) ) { fMoreTroopsLeft[ x ] = MoveOneBestMilitiaMan( SECTORX( pMoveDir[ x ][0] ), SECTORY( pMoveDir[ x ][0] ), sMapX, sMapY ); @@ -1946,25 +1937,33 @@ BOOLEAN CallMilitiaReinforcements( INT16 sTargetMapX, INT16 sTargetMapY, INT16 s ZeroMemory( gpAttackDirs, sizeof( gpAttackDirs ) ); - gpAttackDirs[ guiDirNumber ][0] = uiNumGreen = pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]; - gpAttackDirs[ guiDirNumber ][1] = uiNumReg = pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]; - gpAttackDirs[ guiDirNumber ][2] = uiNumElite = pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA]; - gpAttackDirs[ guiDirNumber ][3] = INSERTION_CODE_CENTER; + gpAttackDirs[guiDirNumber][0] = uiNumGreen = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, GREEN_MILITIA ); + gpAttackDirs[guiDirNumber][1] = uiNumReg = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, REGULAR_MILITIA ); + gpAttackDirs[guiDirNumber][2] = uiNumElite = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, ELITE_MILITIA ); + gpAttackDirs[guiDirNumber][3] = INSERTION_CODE_CENTER; guiDirNumber = insertioncode + 1; + + // we can't move more than we are told, and can't add more than would fit into the sector + UINT16 possibletomove = min( sNumber, gGameExternalOptions.iMaxMilitiaPerSector - NumNonPlayerTeamMembersInSector( sTargetMapX, sTargetMapY, MILITIA_TEAM ) ); + UINT16 sMilitiaMoved = 0; - while ( sMilitiaMoved < sNumber && CountMilitia(pSectorInfo ) < gGameExternalOptions.iMaxMilitiaPerSector && MoveOneBestMilitiaMan( sSrcMapX, sSrcMapY, sTargetMapX, sTargetMapY ) ) + while ( sMilitiaMoved < possibletomove && MoveOneBestMilitiaMan( sSrcMapX, sSrcMapY, sTargetMapX, sTargetMapY ) ) { ++sMilitiaMoved; - gpAttackDirs[ guiDirNumber ][0] += pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA] - uiNumGreen; - gpAttackDirs[ guiDirNumber ][1] += pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA] - uiNumReg; - gpAttackDirs[ guiDirNumber ][2] += pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] - uiNumElite; - gpAttackDirs[ guiDirNumber ][3] = insertioncode; + UINT8 militia_green = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, GREEN_MILITIA ); + UINT8 militia_troop = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, REGULAR_MILITIA ); + UINT8 militia_elite = MilitiaInSectorOfRank( sTargetMapX, sTargetMapY, ELITE_MILITIA ); - uiNumGreen = pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]; - uiNumReg = pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]; - uiNumElite = pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA]; + gpAttackDirs[guiDirNumber][0] += militia_green - uiNumGreen; + gpAttackDirs[guiDirNumber][1] += militia_troop - uiNumReg; + gpAttackDirs[guiDirNumber][2] += militia_elite - uiNumElite; + gpAttackDirs[guiDirNumber][3] = insertioncode; + + uiNumGreen = militia_green; + uiNumReg = militia_troop; + uiNumElite = militia_elite; } guiDirNumber = 5; @@ -1972,7 +1971,7 @@ BOOLEAN CallMilitiaReinforcements( INT16 sTargetMapX, INT16 sTargetMapY, INT16 s if ( !sMilitiaMoved ) return FALSE; - // we need to se this falg. If it wasn't set prior to this, we remove it again afterwards, otherwise all militia will join us if we are in combat + // we need to use this flag. If it wasn't set prior to this, we remove it again afterwards, otherwise all militia will join us if we are in combat BOOLEAN wantreinforcements = (gTacticalStatus.uiFlags & WANT_MILITIA_REINFORCEMENTS); gTacticalStatus.uiFlags |= WANT_MILITIA_REINFORCEMENTS; @@ -1996,6 +1995,88 @@ BOOLEAN CallMilitiaReinforcements( INT16 sTargetMapX, INT16 sTargetMapY, INT16 s return TRUE; } +BOOLEAN MilitiaGroupEntersCurrentSector( UINT8 usGroupId, INT16 sMapX, INT16 sMapY ) +{ + GROUP* pGroup = GetGroup( usGroupId ); + + if ( !pGroup || pGroup->usGroupTeam != MILITIA_TEAM ) + return FALSE; + + INT16 sSrcMapX = pGroup->ubPrevX; + INT16 sSrcMapY = pGroup->ubPrevY; + + UINT8 insertioncode = INSERTION_CODE_CENTER; + UINT8 movetype = THROUGH_STRATEGIC_MOVE; + + // determine from which direction militia should enter (and exit if this isn't possible) + if ( sMapX == sSrcMapX + 1 && sMapY == sSrcMapY ) + { + insertioncode = INSERTION_CODE_WEST; + movetype = EAST_STRATEGIC_MOVE; + } + else if ( sMapX == sSrcMapX - 1 && sMapY == sSrcMapY ) + { + insertioncode = INSERTION_CODE_EAST; + movetype = WEST_STRATEGIC_MOVE; + } + else if ( sMapX == sSrcMapX && sMapY == sSrcMapY + 1 ) + { + insertioncode = INSERTION_CODE_NORTH; + movetype = SOUTH_STRATEGIC_MOVE; + } + else if ( sMapX == sSrcMapX && sMapY == sSrcMapY - 1 ) + { + insertioncode = INSERTION_CODE_SOUTH; + movetype = NORTH_STRATEGIC_MOVE; + } + else + { + // no proper direction here... get out + return FALSE; + } + + // test wether travel from src to target is possible ( we cannot open the src map information, we'll rely on the xml data instead + if ( SectorInfo[SECTOR( sSrcMapX, sSrcMapY )].ubTraversability[movetype] == GROUNDBARRIER || SectorInfo[SECTOR( sSrcMapX, sSrcMapY )].ubTraversability[movetype] == EDGEOFWORLD ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Militia cannot traverse to this sector due to the terrain." ); + return FALSE; + } + + ZeroMemory( gpAttackDirs, sizeof(gpAttackDirs) ); + + guiDirNumber = insertioncode + 1; + + gpAttackDirs[guiDirNumber][0] = pGroup->pEnemyGroup->ubNumAdmins; + gpAttackDirs[guiDirNumber][1] = pGroup->pEnemyGroup->ubNumTroops; + gpAttackDirs[guiDirNumber][2] = pGroup->pEnemyGroup->ubNumElites; + gpAttackDirs[guiDirNumber][3] = insertioncode; + + guiDirNumber = 5; + + // we need to use this flag. If it wasn't set prior to this, we remove it again afterwards, otherwise all militia will join us if we are in combat + BOOLEAN wantreinforcements = (gTacticalStatus.uiFlags & WANT_MILITIA_REINFORCEMENTS); + gTacticalStatus.uiFlags |= WANT_MILITIA_REINFORCEMENTS; + + if ( is_networked ) + { + if ( gfStrategicMilitiaChangesMade ) + { + RemoveMilitiaFromTactical( ); + if ( is_server && gMilitiaEnabled == 1 ) + PrepareMilitiaForTactical( FALSE ); + } + } + else + PrepareMilitiaForTactical( FALSE ); + + if ( !wantreinforcements ) + gTacticalStatus.uiFlags &= ~WANT_MILITIA_REINFORCEMENTS; + + gfStrategicMilitiaChangesMade = FALSE; + + return TRUE; +} + void MSCallBack( UINT8 ubResult ) { if( ubResult == MSG_BOX_RETURN_YES ) @@ -2152,15 +2233,13 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu // Check north if( sMapY > MINIMUM_VALID_Y_COORDINATE ) { - pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY - 1 ) ] ); - // Are militia allowed to travel in that direction from the current sector, for training purposes? if ( CheckStandardConditionsForDirection( sMapX, sMapY, sMapX, sMapY - 1, TRUE, FALSE ) ) { // Count free slots. Each slot is worth 3 points. - usMilitiaCapacity = 3 * (ubMaxMilitia - CountMilitia( pSectorInfo )); + usMilitiaCapacity = 3 * (ubMaxMilitia - NumNonPlayerTeamMembersInSector( sMapX, sMapY - 1, MILITIA_TEAM )); // Count militia that can be upgraded. Regular = 1 point, Green = 2 points. - usUpgradeCapacity = MilitiaUpgradeSlotsCheck( pSectorInfo ); + usUpgradeCapacity = MilitiaUpgradeSlotsCheck( sMapX, sMapY - 1 ); // Found at least one slot here? if (usUpgradeCapacity || usMilitiaCapacity) @@ -2170,9 +2249,9 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu pMoveDir[ *uiDirNumber ][1] = usMilitiaCapacity + usUpgradeCapacity; pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_NORTH; - #ifdef DEBUG_SHOW_RATINGS - if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]); - #endif +#ifdef DEBUG_SHOW_RATINGS + if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]); +#endif ++(*uiDirNumber); } @@ -2182,15 +2261,13 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu // Check west if( sMapX > MINIMUM_VALID_X_COORDINATE ) { - pSectorInfo = &( SectorInfo[ SECTOR( sMapX - 1, sMapY ) ] ); - // Are militia allowed to travel in that direction from the current sector, for training purposes? if ( CheckStandardConditionsForDirection( sMapX, sMapY, sMapX - 1, sMapY, TRUE, FALSE ) ) { // Count free slots. Each slot is worth 3 points. - usMilitiaCapacity = 3 * (ubMaxMilitia - CountMilitia( pSectorInfo )); + usMilitiaCapacity = 3 * (ubMaxMilitia - NumNonPlayerTeamMembersInSector( sMapX - 1, sMapY, MILITIA_TEAM )); // Count militia that can be upgraded. Regular = 1 point, Green = 2 points. - usUpgradeCapacity = MilitiaUpgradeSlotsCheck( pSectorInfo ); + usUpgradeCapacity = MilitiaUpgradeSlotsCheck( sMapX - 1, sMapY ); // Found at least one slot here? if (usUpgradeCapacity || usMilitiaCapacity) @@ -2200,9 +2277,9 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu pMoveDir[ *uiDirNumber ][1] = usMilitiaCapacity + usUpgradeCapacity; pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_WEST; - #ifdef DEBUG_SHOW_RATINGS - if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]); - #endif +#ifdef DEBUG_SHOW_RATINGS + if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]); +#endif ++(*uiDirNumber); } @@ -2212,15 +2289,13 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu // Check south if( sMapY < MAXIMUM_VALID_Y_COORDINATE ) { - pSectorInfo = &( SectorInfo[ SECTOR( sMapX , sMapY + 1 ) ] ); - // Are militia allowed to travel in that direction from the current sector, for training purposes? if ( CheckStandardConditionsForDirection( sMapX, sMapY, sMapX, sMapY + 1, TRUE, FALSE ) ) { // Count free slots. Each slot is worth 3 points. - usMilitiaCapacity = 3 * (ubMaxMilitia - CountMilitia( pSectorInfo )); + usMilitiaCapacity = 3 * (ubMaxMilitia - NumNonPlayerTeamMembersInSector( sMapX, sMapY + 1, MILITIA_TEAM )); // Count militia that can be upgraded. Regular = 1 point, Green = 2 points. - usUpgradeCapacity = MilitiaUpgradeSlotsCheck( pSectorInfo ); + usUpgradeCapacity = MilitiaUpgradeSlotsCheck( sMapX, sMapY + 1 ); // Found at least one slot here? if (usUpgradeCapacity || usMilitiaCapacity) @@ -2230,9 +2305,9 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu pMoveDir[ *uiDirNumber ][1] = usMilitiaCapacity + usUpgradeCapacity; pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_SOUTH; - #ifdef DEBUG_SHOW_RATINGS - if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]); - #endif +#ifdef DEBUG_SHOW_RATINGS + if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]); +#endif ++(*uiDirNumber); } @@ -2242,15 +2317,13 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu // Check east if( sMapX < MAXIMUM_VALID_X_COORDINATE ) { - pSectorInfo = &( SectorInfo[ SECTOR( sMapX + 1 , sMapY ) ] ); - // Are militia allowed to travel in that direction from the current sector, for training purposes? if ( CheckStandardConditionsForDirection( sMapX, sMapY, sMapX +1 , sMapY, TRUE, FALSE ) ) { // Count free slots. Each slot is worth 3 points. - usMilitiaCapacity = 3 * (ubMaxMilitia - CountMilitia( pSectorInfo )); + usMilitiaCapacity = 3 * (ubMaxMilitia - NumNonPlayerTeamMembersInSector( sMapX + 1, sMapY, MILITIA_TEAM ) ); // Count militia that can be upgraded. Regular = 1 point, Green = 2 points. - usUpgradeCapacity = MilitiaUpgradeSlotsCheck( pSectorInfo ); + usUpgradeCapacity = MilitiaUpgradeSlotsCheck( sMapX + 1, sMapY ); // Found at least one slot here? if (usUpgradeCapacity || usMilitiaCapacity) @@ -2260,9 +2333,9 @@ void GenerateDirectionInfosForTraining( INT16 sMapX, INT16 sMapY, UINT8* uiDirNu pMoveDir[ *uiDirNumber ][1] = usMilitiaCapacity + usUpgradeCapacity; pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_EAST; - #ifdef DEBUG_SHOW_RATINGS - if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]); - #endif +#ifdef DEBUG_SHOW_RATINGS + if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of north direction - %ld", pMoveDir[ *uiDirNumber ][1]); +#endif ++(*uiDirNumber); } @@ -2325,13 +2398,13 @@ BOOLEAN IsSectorRoamingAllowed( UINT32 uiSector ) // HEADROCK HAM 3.6: Function returns the number of "upgrade slots" available at target sector. Basically, every GREEN // Militia at the target sector counts as 2 upgrade slots, while every regular counts as 1. -UINT16 MilitiaUpgradeSlotsCheck( SECTORINFO * pSectorInfo ) +UINT16 MilitiaUpgradeSlotsCheck( INT16 sMapX, INT16 sMapY ) { // Result variables UINT16 usNumUpgradeSlots = 0; // Target sector full of elites? - if (pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] >= gGameExternalOptions.iMaxMilitiaPerSector) + if ( MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ) >= gGameExternalOptions.iMaxMilitiaPerSector ) { // Militia cannot be placed or moved here at all. return 0; @@ -2342,21 +2415,21 @@ UINT16 MilitiaUpgradeSlotsCheck( SECTORINFO * pSectorInfo ) (GetWorldDay( ) < gGameExternalOptions.guiTrainVeteranMilitiaDelay)) // Not yet allowed. { // If sector full of Regulars and Elites? - if (pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]+pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] >= gGameExternalOptions.iMaxMilitiaPerSector) // Target sector full of regular+elite militia + if ( MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) + MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ) >= gGameExternalOptions.iMaxMilitiaPerSector ) // Target sector full of regular+elite militia { // Can't upgrade Regulars to Elites, so the sector is already full. return 0; } // Each Green we can convert to Regular counts as 2 slots. - usNumUpgradeSlots = pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA] * 2; + usNumUpgradeSlots = MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) * 2; return (usNumUpgradeSlots); } // Allowed to train Green->Regular, and Regular->Elite - usNumUpgradeSlots = pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA] * 2; - usNumUpgradeSlots += pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]; + usNumUpgradeSlots = MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) * 2; + usNumUpgradeSlots += MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ); return (usNumUpgradeSlots); } @@ -2482,26 +2555,20 @@ UINT8 GetMobileMilitiaQuota( BOOLEAN printMessage ) { // we have found a town (no sam site) - if ( StrategicMap[ iStrategicMapID ].fEnemyControlled == FALSE ) - iTownSectorsUnderPlayerControl++; // remember player currently controls that town sector + if ( !StrategicMap[ iStrategicMapID ].fEnemyControlled ) + ++iTownSectorsUnderPlayerControl; // remember player currently controls that town sector - if ( pSectorInfo->fSurfaceWasEverPlayerControlled == TRUE ) - iTownSectorsLiberatedAtLeastOnce++; // remember player had allready liberated that town sector once + if ( pSectorInfo->fSurfaceWasEverPlayerControlled ) + ++iTownSectorsLiberatedAtLeastOnce; // remember player had allready liberated that town sector once if ( MilitiaTrainingAllowedInTown( iCurrT_ID ) == FALSE ) // considered as mobile only if in that town training is taboo (Tixa, Omerta..) - iActiveMobiles += CountMilitia( pSectorInfo ); - //for ( UINT8 militiaLevel = 0; militiaLevel < MAX_MILITIA_LEVELS; militiaLevel++ ) - // iActiveMobiles += pSectorInfo->ubNumberOfCivsAtLevel[ militiaLevel ]; // remember number of roaming militia in that town sector (green, regular, elite, ..) - } - + iActiveMobiles += NumNonPlayerTeamMembersInSector( SECTORX( iSectorInfoID ), SECTORY( iSectorInfoID ), MILITIA_TEAM ); + } //else if ( StrategicMap[ iStrategicMapID ].bSAMCondition > 0 ) //faster then below, but not safe else if ( MilitiaTrainingAllowedInSector( SECTORX(iSectorInfoID), SECTORY(iSectorInfoID), 0 ) == FALSE ) { // we are in wilderness - - //for ( UINT8 militiaLevel = 0; militiaLevel < MAX_MILITIA_LEVELS; militiaLevel++ ) - // iActiveMobiles += pSectorInfo->ubNumberOfCivsAtLevel[ militiaLevel ]; // remember number of roaming militia in that sector (green, regular, elite, ..) - iActiveMobiles += CountMilitia( pSectorInfo ); + iActiveMobiles += NumNonPlayerTeamMembersInSector( SECTORX( iSectorInfoID ), SECTORY( iSectorInfoID ), MILITIA_TEAM ); } } @@ -2698,39 +2765,33 @@ void MobileMilitiaDeserters(INT16 sMapX, INT16 sMapY, BOOLEAN fDeleteEquip, BOOL /////////////////////// // check enemy presence to decide if mobiles are threatened and some will desert. // Note: cant use NumEnemiesInFiveSectors() as it does not work for omerta or when reinforcements are deactivated, also it uses generateDirectionInfo(), which is used for militia movement. - UINT8 eAdmins = 0, eTroops = 0, eElites = 0, eTanks = 0; //enemies in current sector - GetNumberOfEnemiesInSector( sMapX, sMapY, &eAdmins, &eTroops, &eElites, &eTanks ); - if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) ) + if ( NumNonPlayerTeamMembersInSector( sMapX, sMapY, ENEMY_TEAM ) ) enemiesNear = TRUE; if ( ( sMapX > MINIMUM_VALID_X_COORDINATE ) && !enemiesNear ) { //left side - GetNumberOfEnemiesInSector( sMapX - 1, sMapY, &eAdmins, &eTroops, &eElites, &eTanks ); - if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) || (eTanks > 0) ) + if ( NumNonPlayerTeamMembersInSector( sMapX - 1, sMapY, ENEMY_TEAM ) ) enemiesNear = TRUE; } if ( ( sMapX < MAXIMUM_VALID_X_COORDINATE ) && !enemiesNear) { //right side - GetNumberOfEnemiesInSector( sMapX + 1, sMapY, &eAdmins, &eTroops, &eElites, &eTanks ); - if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) || (eTanks > 0) ) + if ( NumNonPlayerTeamMembersInSector( sMapX + 1, sMapY, ENEMY_TEAM ) ) enemiesNear = TRUE; } if ( ( sMapY > MINIMUM_VALID_Y_COORDINATE ) && !enemiesNear ) { //top side - GetNumberOfEnemiesInSector( sMapX, sMapY - 1, &eAdmins, &eTroops, &eElites, &eTanks ); - if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) || (eTanks > 0) ) + if ( NumNonPlayerTeamMembersInSector( sMapX, sMapY - 1, ENEMY_TEAM ) ) enemiesNear = TRUE; } if ( ( sMapY < MAXIMUM_VALID_Y_COORDINATE ) && !enemiesNear) { //bottom side - GetNumberOfEnemiesInSector( sMapX, sMapY + 1, &eAdmins, &eTroops, &eElites, &eTanks ); - if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) || (eTanks > 0) ) + if ( NumNonPlayerTeamMembersInSector( sMapX, sMapY + 1, ENEMY_TEAM ) ) enemiesNear = TRUE; } @@ -2742,8 +2803,8 @@ void MobileMilitiaDeserters(INT16 sMapX, INT16 sMapY, BOOLEAN fDeleteEquip, BOOL if (quota > 100) //more active then allowed { - UINT8 militiaGreen = SectorInfo[ SECTOR( sMapX, sMapY) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; - UINT8 militiaRegular = SectorInfo[ SECTOR( sMapX, sMapY) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; + UINT8 militiaGreen = MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ); + UINT8 militiaRegular = MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ); desertersGreen = (quota - 100) * militiaGreen / 100; desertersGreen = Random( min( militiaGreen, desertersGreen ) );//cant remove more then actually exist in that group @@ -2799,3 +2860,188 @@ void MobileMilitiaDeserters(INT16 sMapX, INT16 sMapY, BOOLEAN fDeleteEquip, BOOL ResetMilitia(); } } + + +#include "mapscreen.h" +#include "Strategic Pathing.h" +#include "GameVersion.h" + +// Flugente: militia movement +BOOLEAN SaveMilitiaMovementInformationToSaveGameFile( HWFILE hFile ) +{ + UINT32 uiNumBytesWritten = 0; + + UINT8 number = MILITIA_PATROLS_MAX; + + //Save the number of elements + FileWrite( hFile, &number, sizeof(UINT8), &uiNumBytesWritten ); + if ( uiNumBytesWritten != sizeof(UINT8) ) + { + return(FALSE); + } + + for ( UINT8 cnt = 0; cnt < MILITIA_PATROLS_MAX; ++cnt ) + { + UINT32 uiNumOfNodes = 0; + PathStPtr pTempPath = gMilitiaPath[cnt].path; + + uiNumBytesWritten = 0; + + //loop through to get all the nodes + while ( pTempPath ) + { + ++uiNumOfNodes; + pTempPath = pTempPath->pNext; + } + + //Save the number of the nodes + FileWrite( hFile, &uiNumOfNodes, sizeof(UINT32), &uiNumBytesWritten ); + if ( uiNumBytesWritten != sizeof(UINT32) ) + { + return(FALSE); + } + + //loop through all the nodes and add them + pTempPath = gMilitiaPath[cnt].path; + + //loop through nodes and save all the nodes + while ( pTempPath ) + { + //Save the number of the nodes + FileWrite( hFile, pTempPath, sizeof(PathSt), &uiNumBytesWritten ); + if ( uiNumBytesWritten != sizeof(PathSt) ) + { + return(FALSE); + } + + pTempPath = pTempPath->pNext; + } + + //Save the group id + FileWrite( hFile, &gMilitiaPath[cnt].sGroupid, sizeof(INT16), &uiNumBytesWritten ); + if ( uiNumBytesWritten != sizeof(INT16) ) + { + return(FALSE); + } + } + + return(TRUE); +} + +BOOLEAN LoadMilitiaMovementInformationFromSavedGameFile( HWFILE hFile, UINT32 uiSavedGameVersion ) +{ + UINT32 uiNumBytesRead; + UINT32 uiTotalNodeCount = 0; + UINT8 cnt; + UINT32 uiNodeCount = 0; + PathSt *pPath = NULL; + UINT8 ubPassengerCnt = 0; + PathSt *pTempPath; + UINT8 numpaths = 0; + + DeleteAllMilitiaPaths( ); + + // if this is an older savegame, nothing to read + if ( uiSavedGameVersion < MILITIA_PATH_PLOTTING ) + return TRUE; + + //Load the number of elements + FileRead( hFile, &numpaths, sizeof(UINT8), &uiNumBytesRead ); + if ( uiNumBytesRead != sizeof(UINT8) ) + { + return(FALSE); + } + + if ( numpaths != MILITIA_PATROLS_MAX ) + return(FALSE); + + for ( UINT32 cnt = 0; cnt < MILITIA_PATROLS_MAX; ++cnt ) + { + UINT32 uiNumOfNodes = 0; + PathStPtr pTempPath = NULL; + PathStPtr pTemp = NULL; + UINT32 uiNumBytesRead = 0; + INT16 groupid = 0; + + //Load the number of the nodes + FileRead( hFile, &uiNumOfNodes, sizeof(UINT32), &uiNumBytesRead ); + if ( uiNumBytesRead != sizeof(UINT32) ) + { + return(FALSE); + } + + //load all the nodes + for ( UINT32 cnt2 = 0; cnt2 < uiNumOfNodes; ++cnt2 ) + { + //Allocate memory for the new node + pTemp = (PathStPtr)MemAlloc( sizeof(PathSt) ); + if ( pTemp == NULL ) + { + pTempPath = MoveToBeginningOfPathList( pTempPath ); + ClearStrategicPathList( pTempPath, -1 ); + return(FALSE); + } + + memset( pTemp, 0, sizeof(PathSt) ); + + //Load the node + FileRead( hFile, pTemp, sizeof(PathSt), &uiNumBytesRead ); + if ( uiNumBytesRead != sizeof(PathSt) ) + { + MemFree( pTemp ); + pTempPath = MoveToBeginningOfPathList( pTempPath ); + ClearStrategicPathList( pTempPath, -1 ); + return(FALSE); + } + + //Put the node into the list + if ( cnt2 == 0 ) + { + pTempPath = pTemp; + pTemp->pPrev = NULL; + } + else + { + pTempPath->pNext = pTemp; + pTemp->pPrev = pTempPath; + + pTempPath = pTempPath->pNext; + } + + pTemp->pNext = NULL; + } + + //move to beginning of list + pTempPath = MoveToBeginningOfPathList( pTempPath ); + + gMilitiaPath[cnt].path = pTempPath; + if ( gMilitiaPath[cnt].path ) + gMilitiaPath[cnt].path->pPrev = NULL; + + //Load the number of the nodes + FileRead( hFile, &groupid, sizeof(INT16), &uiNumBytesRead ); + if ( uiNumBytesRead != sizeof(INT16) ) + { + return(FALSE); + } + + gMilitiaPath[cnt].sGroupid = groupid; + } + + return(TRUE); +} + +// delete a militia group and transfer its militia to the sector they are in +void DissolveMilitiaGroup( UINT8 uGroupId ) +{ + GROUP* pGroup = GetGroup( uGroupId ); + + if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM ) + { + StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, GREEN_MILITIA, pGroup->pEnemyGroup->ubNumAdmins ); + StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, REGULAR_MILITIA, pGroup->pEnemyGroup->ubNumTroops ); + StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, ELITE_MILITIA, pGroup->pEnemyGroup->ubNumElites ); + + RemovePGroup( pGroup ); + } +} diff --git a/Strategic/MilitiaSquads.h b/Strategic/MilitiaSquads.h index 2b67bf924..67a81716b 100644 --- a/Strategic/MilitiaSquads.h +++ b/Strategic/MilitiaSquads.h @@ -56,12 +56,10 @@ BOOLEAN IsSectorRoamingAllowed( UINT32 uiSector ); // HEADROCK HAM 3.6: New upgrade check returns the amount of militia that can be upgraded at target sector, in // "upgrade points" -UINT16 MilitiaUpgradeSlotsCheck( SECTORINFO * pSectorInfo ); +UINT16 MilitiaUpgradeSlotsCheck( INT16 sMapX, INT16 sMapY ); // HEADROCK HAM 3.6: This needs to be accessible. void AddToBlockMoveList(INT16 sMapX, INT16 sMapY); -// And this: -UINT8 CountMilitia(SECTORINFO *pSectorInfo); // HEADROCK HAM 4: Returns whether sector is allowed for militia roaming, taking into account player-set restrictions. UINT8 ManualMobileMovementAllowed( UINT8 ubSector ); @@ -73,4 +71,13 @@ void InitManualMobileRestrictions(); extern void MobileMilitiaDeserters( INT16 sMapX, INT16 sMapY, BOOLEAN fDeleteEquip, BOOLEAN fPrintMessage ); extern UINT8 GetMobileMilitiaQuota( BOOLEAN printMessage ); +// Flugente: militia movement +BOOLEAN SaveMilitiaMovementInformationToSaveGameFile( HWFILE hFile ); +BOOLEAN LoadMilitiaMovementInformationFromSavedGameFile( HWFILE hFile, UINT32 uiSavedGameVersion ); + +// delete a militia group and transfer its militia to the sector they are in +void DissolveMilitiaGroup( UINT8 uGroupId ); + +BOOLEAN MilitiaGroupEntersCurrentSector( UINT8 usGroupId, INT16 sMapX, INT16 sMapY ); + #endif \ No newline at end of file diff --git a/Strategic/PreBattle Interface.cpp b/Strategic/PreBattle Interface.cpp index 9bbe68016..b76b90c94 100644 --- a/Strategic/PreBattle Interface.cpp +++ b/Strategic/PreBattle Interface.cpp @@ -225,7 +225,7 @@ void ValidateAndCorrectInBattleCounters( GROUP *pLocGroup ) { if( pGroup->pEnemyGroup->ubAdminsInBattle || pGroup->pEnemyGroup->ubTroopsInBattle || pGroup->pEnemyGroup->ubElitesInBattle || pGroup->pEnemyGroup->ubTanksInBattle ) { - ubInvalidGroups++; + ++ubInvalidGroups; pGroup->pEnemyGroup->ubAdminsInBattle = 0; pGroup->pEnemyGroup->ubTroopsInBattle = 0; pGroup->pEnemyGroup->ubElitesInBattle = 0; @@ -279,7 +279,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) BOOLEAN fScoutPresent = FALSE; // Added by SANDRO // ARM: Feb01/98 - Cancel out of mapscreen movement plotting if PBI subscreen is coming up - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -305,18 +305,18 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) gfBlitBattleSectorLocator = TRUE; gfBlinkHeader = FALSE; - #ifdef JA2BETAVERSION - if( pBattleGroup ) - { - ValidateAndCorrectInBattleCounters( pBattleGroup ); - } - #endif +#ifdef JA2BETAVERSION + if( pBattleGroup ) + { + ValidateAndCorrectInBattleCounters( pBattleGroup ); + } +#endif // InitializeTacticalStatusAtBattleStart(); // CJC, Oct 5 98: this is all we should need from InitializeTacticalStatusAtBattleStart() if( gubEnemyEncounterCode != BLOODCAT_AMBUSH_CODE && gubEnemyEncounterCode != ENTERING_BLOODCAT_LAIR_CODE ) { - if ( CheckFact( FACT_FIRST_BATTLE_FOUGHT, 0 ) == FALSE ) + if ( !CheckFact( FACT_FIRST_BATTLE_FOUGHT, 0 ) ) { SetFactTrue( FACT_FIRST_BATTLE_BEING_FOUGHT ); } @@ -324,17 +324,17 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) //If we are currently in the AI Viewer development utility, then remove it first. It automatically //returns to the mapscreen upon removal, which is where we want to go. - #ifdef JA2BETAVERSION - if( guiCurrentScreen == AIVIEWER_SCREEN ) - { - gfExitViewer = TRUE; - gpBattleGroup = pBattleGroup; - gfEnteringMapScreen = TRUE; - gfEnteringMapScreenToEnterPreBattleInterface = TRUE; - gfUsePersistantPBI = TRUE; - return; - } - #endif +#ifdef JA2BETAVERSION + if( guiCurrentScreen == AIVIEWER_SCREEN ) + { + gfExitViewer = TRUE; + gpBattleGroup = pBattleGroup; + gfEnteringMapScreen = TRUE; + gfEnteringMapScreenToEnterPreBattleInterface = TRUE; + gfUsePersistantPBI = TRUE; + return; + } +#endif // ATE: Added check for fPersistantPBI = TRUE if pBattleGroup == NULL // Searched code and saw that this condition only happens for creatures @@ -386,19 +386,23 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) pSector = &SectorInfo[ SECTOR( gubPBSectorX, gubPBSectorY ) ]; if( !gfPersistantPBI ) - { //calculate the non-persistant situation + { + //calculate the non-persistant situation gfBlinkHeader = TRUE; if( HostileCiviliansPresent() ) - { //There are hostile civilians, so no autoresolve allowed. + { + //There are hostile civilians, so no autoresolve allowed. gubExplicitEnemyEncounterCode = HOSTILE_CIVILIANS_CODE; } else if( HostileBloodcatsPresent() ) - { //There are bloodcats in the sector, so no autoresolve allowed + { + //There are bloodcats in the sector, so no autoresolve allowed gubExplicitEnemyEncounterCode = HOSTILE_BLOODCATS_CODE; } else if( gbWorldSectorZ > 0 ) - { //We are underground, so no autoresolve allowed + { + //We are underground, so no autoresolve allowed if( pSector->ubCreaturesInBattle ) { gubExplicitEnemyEncounterCode = FIGHTING_CREATURES_CODE; @@ -507,7 +511,6 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) // ARM: this must now be set before any calls utilizing the GetCurrentBattleSectorXYZ() function gfPreBattleInterfaceActive = TRUE; - CheckForRobotAndIfItsControlled(); // wake everyone up @@ -516,7 +519,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) //Count the number of players involved or not involved in this battle guiNumUninvolved = 0; guiNumInvolved = 0; - for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; i++ ) + for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++i ) { if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) { @@ -524,7 +527,8 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) { // involved if( !ubGroupID ) - { //Record the first groupID. If there are more than one group in this battle, we + { + //Record the first groupID. If there are more than one group in this battle, we //can detect it by comparing the first value with future values. If we do, then //we set a flag which determines whether to use the singular help text or plural version //for the retreat button. @@ -546,7 +550,8 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) { fUsePluralVersion = TRUE; } - guiNumInvolved ++; + + ++guiNumInvolved; // SANDRO - added check if we have a scout in group, needed later if( gGameOptions.fNewTraitSystem && HAS_SKILL_TRAIT( MercPtrs[ i ], SCOUTING_NT ) && gSkillTraitValues.fSCPreventsTheEnemyToAmbushMercs ) @@ -554,8 +559,9 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) fScoutPresent = TRUE; } } - else { - guiNumUninvolved++; + else + { + ++guiNumUninvolved; } } } @@ -569,7 +575,8 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) if( gfPersistantPBI ) { if( !pBattleGroup ) - { //creature's attacking! + { + //creature's attacking! gubEnemyEncounterCode = CREATURE_ATTACK_CODE; } else if ( gpBattleGroup->usGroupTeam == OUR_TEAM ) @@ -709,7 +716,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI ) // SANDRO - merc records - ambush experienced if( gubEnemyEncounterCode == ENEMY_AMBUSH_CODE || gubEnemyEncounterCode == BLOODCAT_AMBUSH_CODE || fAmbushPrevented ) { - for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; i++ ) + for( i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++i ) { if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) ) { diff --git a/Strategic/Queen Command.cpp b/Strategic/Queen Command.cpp index 93ac9f067..293c216f3 100644 --- a/Strategic/Queen Command.cpp +++ b/Strategic/Queen Command.cpp @@ -177,7 +177,7 @@ UINT8 NumHostilesInSector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) + if ( pGroup->usGroupTeam != OUR_TEAM && pGroup->usGroupTeam != MILITIA_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) { ubNumHostiles += pGroup->ubGroupSize; } @@ -221,7 +221,7 @@ UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ) pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) + if ( pGroup->usGroupTeam != OUR_TEAM && pGroup->usGroupTeam != MILITIA_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) { ubNumEnemies += pGroup->ubGroupSize; } @@ -281,7 +281,7 @@ UINT8 NumNonPlayerTeamMembersInSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubT return ubNumTroops; } -UINT16 NumEnemyTanksInSector( INT16 sSectorX, INT16 sSectorY ) +UINT16 NumTanksInSector( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam ) { SECTORINFO *pSector; GROUP *pGroup; @@ -303,7 +303,9 @@ UINT16 NumEnemyTanksInSector( INT16 sSectorX, INT16 sSectorY ) AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE ); pSector = &SectorInfo[SECTOR( sSectorX, sSectorY )]; - ubNum = (UINT16)(pSector->ubNumTanks); + + if ( usTeam == ENEMY_TEAM ) + ubNum = (UINT16)(pSector->ubNumTanks); // TODO //if ( is_networked ) @@ -312,7 +314,7 @@ UINT16 NumEnemyTanksInSector( INT16 sSectorX, INT16 sSectorY ) pGroup = gpGroupList; while ( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) + if ( pGroup->usGroupTeam == usTeam && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) { ubNum += pGroup->pEnemyGroup->ubNumTanks; } @@ -363,7 +365,7 @@ UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) + if ( pGroup->usGroupTeam != OUR_TEAM && pGroup->usGroupTeam != MILITIA_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) { ubNumTroops += pGroup->ubGroupSize; } @@ -372,7 +374,8 @@ UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY ) pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; if( pSector->ubGarrisonID == ROADBLOCK ) - { //consider these troops as mobile troops even though they are in a garrison + { + //consider these troops as mobile troops even though they are in a garrison ubNumTroops += (UINT8)(pSector->ubNumAdmins + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumTanks); } @@ -393,7 +396,7 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) + if ( pGroup->usGroupTeam != OUR_TEAM && pGroup->usGroupTeam != MILITIA_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) { *pubNumTroops += pGroup->pEnemyGroup->ubNumTroops; *pubNumElites += pGroup->pEnemyGroup->ubNumElites; @@ -405,16 +408,16 @@ void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pu pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ]; if( pSector->ubGarrisonID == ROADBLOCK ) - { //consider these troops as mobile troops even though they are in a garrison + { + //consider these troops as mobile troops even though they are in a garrison *pubNumAdmins += pSector->ubNumAdmins; *pubNumTroops += pSector->ubNumTroops; *pubNumElites += pSector->ubNumElites; *pubNumTanks += pSector->ubNumTanks; } - } -void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ) +void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ) { GROUP *pGroup; AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE); @@ -427,7 +430,7 @@ void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSe pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) + if ( pGroup->usGroupTeam == usTeam && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY ) { *pubNumTroops += pGroup->pEnemyGroup->ubNumTroops; *pubNumElites += pGroup->pEnemyGroup->ubNumElites; @@ -506,7 +509,7 @@ void EndTacticalBattleForEnemy() pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY ) + if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY ) { pGroup->pEnemyGroup->ubTroopsInBattle = 0; pGroup->pEnemyGroup->ubElitesInBattle = 0; @@ -519,12 +522,12 @@ void EndTacticalBattleForEnemy() //Check to see if any of our mercs have abandoned the militia during a battle. This is cause for a rather //severe loyalty blow. - for( i = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; i <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; i++ ) + for( i = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; i <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; ++i ) { if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->bInSector && MercPtrs[ i ]->stats.bLife >= OKLIFE ) { //found one live militia, so look for any enemies/creatures. // NOTE: this is relying on ENEMY_TEAM being immediately followed by CREATURE_TEAM - for( i = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; i <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; i++ ) + for( i = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID; i <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; ++i ) { if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->bInSector && MercPtrs[ i ]->stats.bLife >= OKLIFE ) { //confirmed at least one enemy here, so do the loyalty penalty. @@ -578,7 +581,7 @@ BOOLEAN PrepareEnemyForSectorBattle() return PrepareEnemyForUndergroundBattle(); // Add the invading group - if ( gpBattleGroup && gpBattleGroup->usGroupTeam != OUR_TEAM ) + if ( gpBattleGroup && gpBattleGroup->usGroupTeam == ENEMY_TEAM ) { //The enemy has instigated the battle which means they are the ones entering the conflict. //The player was actually in the sector first, and the enemy doesn't use reinforced placements @@ -782,11 +785,9 @@ BOOLEAN PrepareEnemyForSectorBattle() //For enemy groups, we fill up the slots until we have none left or all of the groups have been //processed. - for( pGroup = gpGroupList; - pGroup; - pGroup = pGroup->next) + for( pGroup = gpGroupList; pGroup; pGroup = pGroup->next) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && + if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ ) { //Process enemy group in sector. if( sNumSlots > 0 ) @@ -1124,9 +1125,11 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier ) if( pSoldier->aiData.bNeutral || pSoldier->bTeam != ENEMY_TEAM && pSoldier->bTeam != CREATURE_TEAM ) return; + //we are recording an enemy death if( pSoldier->ubGroupID ) - { //The enemy was in a mobile group + { + //The enemy was in a mobile group GROUP *pGroup; pGroup = GetGroup( pSoldier->ubGroupID ); if( !pGroup ) @@ -1138,15 +1141,26 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier ) #endif return; } + if ( pGroup->usGroupTeam == OUR_TEAM ) { - #ifdef JA2BETAVERSION +#ifdef JA2BETAVERSION CHAR16 str[256]; swprintf( str, L"Attempting to process player group thinking it's an enemy group in ProcessQueenCmdImplicationsOfDeath()", pSoldier->ubGroupID ); DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL ); - #endif +#endif return; } + else if ( pGroup->usGroupTeam == MILITIA_TEAM ) + { +#ifdef JA2BETAVERSION + CHAR16 str[256]; + swprintf( str, L"Attempting to process militia group thinking it's an enemy group in ProcessQueenCmdImplicationsOfDeath()", pSoldier->ubGroupID ); + DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL ); +#endif + return; + } + switch( pSoldier->ubSoldierClass ) { case SOLDIER_CLASS_ELITE: @@ -1702,13 +1716,13 @@ void AddPossiblePendingEnemiesToBattle() // Figure out which groups are in the sector, so we can have reinforcements arrive at random for (ubNumGroupsInSector = 0, pGroup = gpGroupList; pGroup; pGroup = pGroup->next) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ ) - ubNumGroupsInSector++; + if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ ) + ++ubNumGroupsInSector; } pGroupInSectorList = (GROUP**) MemAlloc( ubNumGroupsInSector * sizeof( GROUP*)); for (ubNumGroupsInSector = 0, pGroup = gpGroupList; pGroup; pGroup = pGroup->next) { - if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ ) + if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ ) { pGroupInSectorList[ ubNumGroupsInSector++] = pGroup; } @@ -2701,17 +2715,13 @@ void HandleEnemyStatusInCurrentMapBeforeLoadingNewMap() BOOLEAN PlayerSectorDefended( UINT8 ubSectorID ) { - SECTORINFO *pSector; - pSector = &SectorInfo[ ubSectorID ]; - if( pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + - pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + - pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] ) + if ( NumNonPlayerTeamMembersInSector( SECTORX( ubSectorID ), SECTORY( ubSectorID ), MILITIA_TEAM ) ) { //militia in sector return TRUE; } - if ( FindMovementGroupInSector( (UINT8)SECTORX( ubSectorID ), (UINT8)SECTORY( ubSectorID ), OUR_TEAM ) || FindMovementGroupInSector( (UINT8)SECTORX( ubSectorID ), (UINT8)SECTORY( ubSectorID ), MILITIA_TEAM ) ) + if ( FindMovementGroupInSector( SECTORX( ubSectorID ), SECTORY( ubSectorID ), OUR_TEAM ) ) { // player/militia in sector return TRUE; diff --git a/Strategic/Queen Command.h b/Strategic/Queen Command.h index 2f6504128..ea82bdbad 100644 --- a/Strategic/Queen Command.h +++ b/Strategic/Queen Command.h @@ -22,11 +22,11 @@ UINT8 NumEnemiesInAnySector( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ ); // returns how many members of a team are in a sector - not intended for OUR_TEAM! UINT8 NumNonPlayerTeamMembersInSector( INT16 sSectorX, INT16 sSectorY, UINT8 ubTeam ); -UINT16 NumEnemyTanksInSector( INT16 sSectorX, INT16 sSectorY ); +UINT16 NumTanksInSector( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam ); UINT8 NumStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY ); UINT8 NumMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY ); void GetNumberOfMobileEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ); -void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ); +void GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( INT16 sSectorX, INT16 sSectorY, UINT8 usTeam, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ); void GetNumberOfStationaryEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ); void GetNumberOfEnemiesInSector( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites, UINT8 *pubNumTanks ); diff --git a/Strategic/Reinforcement.cpp b/Strategic/Reinforcement.cpp index 1a8fb423a..9c71e1b26 100644 --- a/Strategic/Reinforcement.cpp +++ b/Strategic/Reinforcement.cpp @@ -41,7 +41,7 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites, pubNumTanks ); - GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); + GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( sSectorX, sSectorY, ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); *pubNumAdmins += ubNumAdmins; *pubNumTroops += ubNumTroops; @@ -82,7 +82,7 @@ void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pub } } - GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); + GetNumberOfMobileEnemiesInSectorWithoutRoadBlock( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), ENEMY_TEAM, &ubNumAdmins, &ubNumTroops, &ubNumElites, &ubNumTanks ); *pubNumAdmins += ubNumAdmins; *pubNumTroops += ubNumTroops; @@ -115,9 +115,11 @@ BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 s GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir, FALSE, TRUE ); - for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ ) + for ( ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex ) + { if( pGroup->ubSectorX == SECTORX( pusMoveDir[ ubIndex ][ 0 ] ) && pGroup->ubSectorY == SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ) return TRUE; + } return FALSE; } @@ -130,7 +132,7 @@ UINT8 GetAdjacentSectors( UINT8 pSectors[4], INT16 sSectorX, INT16 sSectorY ) GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir, FALSE, TRUE ); - for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ ) + for( ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex ) pSectors[ ubCounter++ ] = (UINT8)pusMoveDir[ ubIndex ][ 0 ]; return ubCounter; @@ -151,8 +153,7 @@ UINT8 CountAllMilitiaInFiveSectors(INT16 sMapX, INT16 sMapY) for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ ) ubResult += NumNonPlayerTeamMembersInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), MILITIA_TEAM ); - - + return ubResult; } @@ -165,8 +166,9 @@ BOOLEAN ARMoveBestMilitiaManFromAdjacentSector(INT16 sMapX, INT16 sMapY) if( !gGameExternalOptions.gfAllowReinforcements ) return FALSE; - if ( NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ) >= gGameExternalOptions.iMaxMilitiaPerSector || - CountAllMilitiaInFiveSectors( sMapX, sMapY ) - NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ) == 0 ) + UINT8 militiainsector = NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ); + if ( militiainsector >= gGameExternalOptions.iMaxMilitiaPerSector || + CountAllMilitiaInFiveSectors( sMapX, sMapY ) - militiainsector == 0 ) return FALSE; GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir, FALSE, TRUE ); @@ -241,7 +243,10 @@ UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam { ubIndex = Random(ubDirNumber); - if ( usTeam == ENEMY_TEAM && NumNonPlayerTeamMembersInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam ) > gubReinforcementMinEnemyStaticGroupSize ) + INT16 sOtherX = SECTORX( pusMoveDir[ubIndex][0] ); + INT16 sOtherY = SECTORY( pusMoveDir[ubIndex][0] ); + + if ( usTeam == ENEMY_TEAM && NumNonPlayerTeamMembersInSector( sOtherX, sOtherY, usTeam ) > gubReinforcementMinEnemyStaticGroupSize ) { pSector = &SectorInfo[ pusMoveDir[ ubIndex ][ 0 ] ]; @@ -277,26 +282,24 @@ UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam return (UINT8)pusMoveDir[ ubIndex ][ 2 ]; } // no required min size on militia groups - else if ( usTeam == MILITIA_TEAM && NumNonPlayerTeamMembersInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam ) ) + else if ( usTeam == MILITIA_TEAM && NumNonPlayerTeamMembersInSector( sOtherX, sOtherY, usTeam ) ) { - pSector = &SectorInfo[pusMoveDir[ubIndex][0]]; - - if ( pSector->ubNumberOfCivsAtLevel[ELITE_MILITIA] ) + if ( MilitiaInSectorOfRank( sOtherX, sOtherY, ELITE_MILITIA ) ) { - (pThisSector->ubNumberOfCivsAtLevel[ELITE_MILITIA])++; - (pSector->ubNumberOfCivsAtLevel[ELITE_MILITIA])--; + StrategicAddMilitiaToSector( sMapX, sMapY, ELITE_MILITIA, 1 ); + StrategicRemoveMilitiaFromSector( sOtherX, sOtherY, ELITE_MILITIA, 1 ); AddMilitiaToBattle( NULL, (UINT8)pusMoveDir[ubIndex][2], 0, 0, 1, FALSE ); } - else if ( pSector->ubNumberOfCivsAtLevel[REGULAR_MILITIA] ) + else if ( MilitiaInSectorOfRank( sOtherX, sOtherY, REGULAR_MILITIA ) ) { - (pThisSector->ubNumberOfCivsAtLevel[REGULAR_MILITIA])++; - (pSector->ubNumberOfCivsAtLevel[REGULAR_MILITIA])--; + StrategicAddMilitiaToSector( sMapX, sMapY, REGULAR_MILITIA, 1 ); + StrategicRemoveMilitiaFromSector( sOtherX, sOtherY, REGULAR_MILITIA, 1 ); AddMilitiaToBattle( NULL, (UINT8)pusMoveDir[ubIndex][2], 0, 1, 0, FALSE ); } - else if ( pSector->ubNumberOfCivsAtLevel[GREEN_MILITIA] ) + else if ( MilitiaInSectorOfRank( sOtherX, sOtherY, GREEN_MILITIA ) ) { - (pThisSector->ubNumberOfCivsAtLevel[GREEN_MILITIA])++; - (pSector->ubNumberOfCivsAtLevel[GREEN_MILITIA])--; + StrategicAddMilitiaToSector( sMapX, sMapY, GREEN_MILITIA, 1 ); + StrategicRemoveMilitiaFromSector( sOtherX, sOtherY, GREEN_MILITIA, 1 ); AddMilitiaToBattle( NULL, (UINT8)pusMoveDir[ubIndex][2], 1, 0, 0, FALSE ); } @@ -317,7 +320,6 @@ UINT8 DoReinforcementAsPendingMilitia( INT16 sMapX, INT16 sMapY, UINT8 *pubRank { UINT16 pusMoveDir[4][3]; UINT8 ubDirNumber = 0, ubIndex; - SECTORINFO *pSector;//*pThisSector, if( !gGameExternalOptions.gfAllowReinforcements ) return 255; @@ -338,19 +340,19 @@ UINT8 DoReinforcementAsPendingMilitia( INT16 sMapX, INT16 sMapY, UINT8 *pubRank ubIndex = Random(ubDirNumber); if ( NumNonPlayerTeamMembersInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), MILITIA_TEAM ) ) { - pSector = &SectorInfo[ pusMoveDir[ ubIndex ][ 0 ] ]; - - if( pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] ) + if ( MilitiaInSectorOfRank( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ELITE_MILITIA ) ) { StrategicAddMilitiaToSector( sMapX, sMapY,ELITE_MILITIA, 1 ); StrategicRemoveMilitiaFromSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ),ELITE_MILITIA, 1 ); *pubRank = ELITE_MILITIA; - }else if( pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] ) + } + else if ( MilitiaInSectorOfRank( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), REGULAR_MILITIA ) ) { StrategicAddMilitiaToSector( sMapX, sMapY,REGULAR_MILITIA, 1 ); StrategicRemoveMilitiaFromSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ),REGULAR_MILITIA, 1 ); *pubRank = REGULAR_MILITIA; - }else if( pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] ) + } + else if ( MilitiaInSectorOfRank( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), GREEN_MILITIA ) ) { StrategicAddMilitiaToSector( sMapX, sMapY,GREEN_MILITIA, 1 ); StrategicRemoveMilitiaFromSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ),GREEN_MILITIA, 1 ); @@ -391,6 +393,7 @@ void AddPossiblePendingMilitiaToBattle() || (NumNonPlayerTeamMembersInSector( gWorldSectorX, gWorldSectorY, ENEMY_TEAM ) == 0) ) return; + //gGameExternalOptions.guiMaxMilitiaSquadSize - CountAllMilitiaInSector( gWorldSectorX, gWorldSectorY ); ubSlots = NumFreeSlots( MILITIA_TEAM ); if(gGameExternalOptions.sMinDelayMilitiaReinforcements)//dnl ch68 090913 @@ -455,25 +458,23 @@ void AddPossiblePendingMilitiaToBattle() { ubNumElites = ubNumRegulars = ubNumGreens = 0; - // while( ubSlots ) switch( ubPredefinedRank ) { case ELITE_MILITIA: - ubSlots--; ubNumElites++; break; case REGULAR_MILITIA: - ubSlots--; ubNumRegulars++; break; case GREEN_MILITIA: - ubSlots--; ubNumGreens++; break; default: - ubSlots--; + break; } + --ubSlots; + if( ubNumGreens || ubNumRegulars || ubNumElites ) AddSoldierInitListMilitiaOnEdge( ubPredefinedInsertionCode, ubNumGreens, ubNumRegulars, ubNumElites ); } @@ -482,7 +483,8 @@ void AddPossiblePendingMilitiaToBattle() ubPredefinedRank = 255; if( ubSlots ) - { //After going through the process, we have finished with some free slots and no more enemies to add. + { + //After going through the process, we have finished with some free slots and no more enemies to add. //So, we can turn off the flag, as this check is no longer needed. ubPredefinedInsertionCode = DoReinforcementAsPendingMilitia( gWorldSectorX, gWorldSectorY, &ubPredefinedRank ); @@ -500,4 +502,3 @@ void AddPossiblePendingMilitiaToBattle() gfPendingNonPlayerTeam[MILITIA_TEAM] = FALSE; } } - diff --git a/Strategic/Strategic AI.cpp b/Strategic/Strategic AI.cpp index 3ce86a759..4b99229d4 100644 --- a/Strategic/Strategic AI.cpp +++ b/Strategic/Strategic AI.cpp @@ -648,9 +648,9 @@ BOOLEAN PlayerForceTooStrong( UINT8 ubSectorID, UINT16 usOffensePoints, UINT16 * // SANDRO - EVALUATE THE STRENGTH OF MILITIA BASED ON INI SETTING *pusDefencePoints = PlayerMercsInSector( ubSectorX, ubSectorY, 0 ) * 5; - *pusDefencePoints += (pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] * 1 * (100 + gGameExternalOptions.sGreenMilitiaAutoresolveStrength )/100); - *pusDefencePoints += (pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] * 2 * (100 + gGameExternalOptions.sRegularMilitiaAutoresolveStrength)/100); - *pusDefencePoints += (pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] * 3 * (100 + gGameExternalOptions.sVeteranMilitiaAutoresolveStrength)/100); + *pusDefencePoints += (MilitiaInSectorOfRank( ubSectorX, ubSectorY, GREEN_MILITIA ) * 1 * (100 + gGameExternalOptions.sGreenMilitiaAutoresolveStrength) / 100); + *pusDefencePoints += (MilitiaInSectorOfRank( ubSectorX, ubSectorY, REGULAR_MILITIA ) * 2 * (100 + gGameExternalOptions.sRegularMilitiaAutoresolveStrength) / 100); + *pusDefencePoints += (MilitiaInSectorOfRank( ubSectorX, ubSectorY, ELITE_MILITIA ) * 3 * (100 + gGameExternalOptions.sVeteranMilitiaAutoresolveStrength) / 100); if( *pusDefencePoints > usOffensePoints ) { @@ -661,11 +661,9 @@ BOOLEAN PlayerForceTooStrong( UINT8 ubSectorID, UINT16 usOffensePoints, UINT16 * void RequestAttackOnSector( UINT8 ubSectorID, UINT16 usDefencePoints ) { - INT32 i; + Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ - Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ - - for( i = 0; i < giGarrisonArraySize; i++ ) + for ( INT32 i = 0; i < giGarrisonArraySize; ++i ) { if( gGarrisonGroup[ i ].ubSectorID == ubSectorID && !gGarrisonGroup[ i ].ubPendingGroupID ) { @@ -824,7 +822,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic2"); } if( !pGroup->ubNextX || !pGroup->ubNextY ) { - if ( pGroup->usGroupTeam != OUR_TEAM && pGroup->pEnemyGroup->ubIntention != STAGING + if ( pGroup->usGroupTeam == ENEMY_TEAM && pGroup->pEnemyGroup->ubIntention != STAGING && pGroup->pEnemyGroup->ubIntention != REINFORCEMENTS ) { #ifdef JA2BETAVERSION @@ -2147,33 +2145,30 @@ BOOLEAN ReinforcementsApproved( INT32 iGarrisonID, UINT16 *pusDefencePoints ) { SECTORINFO *pSector; UINT16 usOffensePoints; + UINT16 usDefencePoints; UINT8 ubSectorX, ubSectorY; - Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ + Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ pSector = &SectorInfo[ gGarrisonGroup[ iGarrisonID ].ubSectorID ]; ubSectorX = (UINT8)SECTORX( gGarrisonGroup[ iGarrisonID ].ubSectorID ); ubSectorY = (UINT8)SECTORY( gGarrisonGroup[ iGarrisonID ].ubSectorID ); // SANDRO - EVALUATE THE MILITIA STRENGTH REGARDING THE GAME SETTINGS - *pusDefencePoints = PlayerMercsInSector( ubSectorX, ubSectorY, 0 ) * 5; - *pusDefencePoints += (pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] * 1 * (100 + gGameExternalOptions.sGreenMilitiaAutoresolveStrength )/100); - *pusDefencePoints += (pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] * 2 * (100 + gGameExternalOptions.sRegularMilitiaAutoresolveStrength)/100); - *pusDefencePoints += (pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] * 3 * (100 + gGameExternalOptions.sVeteranMilitiaAutoresolveStrength)/100); + usOffensePoints = gArmyComp[gGarrisonGroup[iGarrisonID].ubComposition].bAdminPercentage * 2 + + gArmyComp[gGarrisonGroup[iGarrisonID].ubComposition].bTroopPercentage * 3 + + gArmyComp[gGarrisonGroup[iGarrisonID].ubComposition].bElitePercentage * 4 + + gubGarrisonReinforcementsDenied[iGarrisonID]; + usOffensePoints = usOffensePoints * gArmyComp[gGarrisonGroup[iGarrisonID].ubComposition].bDesiredPopulation / 100; - usOffensePoints = gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bAdminPercentage * 2 + - gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bTroopPercentage * 3 + - gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bElitePercentage * 4 + - gubGarrisonReinforcementsDenied[ iGarrisonID ]; - usOffensePoints = usOffensePoints * gArmyComp[ gGarrisonGroup[ iGarrisonID ].ubComposition ].bDesiredPopulation / 100; - - if( usOffensePoints > *pusDefencePoints ) + if ( PlayerForceTooStrong( gGarrisonGroup[iGarrisonID].ubSectorID, usOffensePoints, &usDefencePoints ) ) { return TRUE; } + //Before returning false, determine if reinforcements have been denied repeatedly. If so, then //we might send an augmented force to take it back. - if( gubGarrisonReinforcementsDenied[ iGarrisonID ] + usOffensePoints > *pusDefencePoints ) + if ( gubGarrisonReinforcementsDenied[iGarrisonID] + usOffensePoints > usDefencePoints ) { #ifdef JA2BETAVERSION LogStrategicEvent( "Sector %c%d will now recieve an %d extra troops due to multiple denials for reinforcements in the past for strong player presence.", @@ -2209,16 +2204,22 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5"); return FALSE; } Assert( pGroup->usGroupTeam != OUR_TEAM ); + + // for now, nothing to do for militia groups + if ( pGroup->usGroupTeam == MILITIA_TEAM ) + return FALSE; + if( pGroup->pEnemyGroup->ubIntention == PURSUIT ) - { //Lost the player group that he was going to attack. Return to original position. + { + //Lost the player group that he was going to attack. Return to original position. SetThisSectorAsEnemyControlled( pGroup->ubSectorX, pGroup->ubSectorY, 0, TRUE ); ReassignAIGroup( &pGroup ); return TRUE; } else if( pGroup->pEnemyGroup->ubIntention == REINFORCEMENTS ) { - Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ - //The group has arrived at the location where he is supposed to reinforce. + Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ + //The group has arrived at the location where he is supposed to reinforce. //Step 1 -- Check for matching garrison location for( i = 0; i < giGarrisonArraySize; i++ ) { @@ -3851,8 +3852,9 @@ BOOLEAN LoadStrategicAI( HWFILE hFile ) pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && pGroup->ubGroupSize >= 16 ) - { //accident in patrol groups being too large + if ( pGroup->usGroupTeam == ENEMY_TEAM && pGroup->ubGroupSize >= 16 ) + { + //accident in patrol groups being too large UINT8 ubGetRidOfXTroops = pGroup->ubGroupSize - 10; if( gbWorldSectorZ || pGroup->ubSectorX != gWorldSectorX || pGroup->ubSectorY != gWorldSectorY ) { //don't modify groups in the currently loaded sector. @@ -3866,6 +3868,7 @@ BOOLEAN LoadStrategicAI( HWFILE hFile ) pGroup = pGroup->next; } } + if( ubSAIVersion < 13 ) { for( i = 0; i < 255; i++ ) @@ -4037,7 +4040,7 @@ BOOLEAN LoadStrategicAI( HWFILE hFile ) if( ubSAIVersion < 26 ) { INT32 i; - for( i = 0; i < 255; i++ ) + for( i = 0; i < 255; ++i ) { if( SectorInfo[ i ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + SectorInfo[ i ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + @@ -6141,7 +6144,7 @@ void EliminateSurplusTroopsForGarrison( GROUP *pGroup, SECTORINFO *pSector ) INT32 iMaxEnemyGroupSize = gGameExternalOptions.iMaxEnemyGroupSize; DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic8"); -iTotal = pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + + iTotal = pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites + pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTanks + pSector->ubNumTroops + pSector->ubNumElites + pSector->ubNumAdmins + pSector->ubNumTanks; if( iTotal <= iMaxEnemyGroupSize ) { @@ -6270,12 +6273,12 @@ void UpgradeAdminsToTroops() GROUP *pGroup; INT16 sPatrolIndex; - Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ + Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */ // on normal, AI evaluates approximately every 10 hrs. There are about 130 administrators seeded on the map. // Some of these will be killed by the player. // check all garrisons for administrators - for( i = 0; i < giGarrisonArraySize; i++ ) + for( i = 0; i < giGarrisonArraySize; ++i ) { // skip sector if it's currently loaded, we'll never upgrade guys in those if ( (gWorldSectorX != 0) && (gWorldSectorY != 0) && @@ -6306,18 +6309,17 @@ void UpgradeAdminsToTroops() pSector->ubNumTroops++; } - ubAdminsToCheck--; + --ubAdminsToCheck; } } } } - - + // check all moving enemy groups for administrators pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->ubGroupSize && pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle ) + if ( pGroup->ubGroupSize && pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle ) { Assert ( pGroup->pEnemyGroup ); @@ -6482,7 +6484,7 @@ void ReassignAIGroup( GROUP **pGroup ) //go through garrisons first and begin considering where the random value dictates. If that garrison doesn't require //reinforcements, it'll continue on considering all subsequent garrisons till the end of the array. If it fails at that //point, it'll restart the loop at zero, and consider all garrisons to the index that was first considered by the random value. - for( i = 0; i < giGarrisonArraySize; i++ ) + for( i = 0; i < giGarrisonArraySize; ++i ) { RecalculateGarrisonWeight( i ); iWeight = gGarrisonGroup[ i ].bWeight; @@ -6710,7 +6712,7 @@ void CalcNumTroopsBasedOnComposition( UINT8 *pubNumTroops, UINT8 *pubNumElites, void ConvertGroupTroopsToComposition( GROUP *pGroup, INT32 iCompositionID ) { Assert( pGroup ); - Assert( pGroup->usGroupTeam != OUR_TEAM ); + Assert( pGroup->usGroupTeam == ENEMY_TEAM ); CalcNumTroopsBasedOnComposition( &pGroup->pEnemyGroup->ubNumTroops, &pGroup->pEnemyGroup->ubNumElites, pGroup->ubGroupSize, iCompositionID ); pGroup->pEnemyGroup->ubNumAdmins = 0; pGroup->ubGroupSize = pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites; @@ -6815,10 +6817,12 @@ void MoveSAIGroupToSector( GROUP **pGroup, UINT8 ubSectorID, UINT32 uiMoveCode, (*pGroup)->ubMoveType = ONE_WAY; if( (*pGroup)->ubSectorX == ubDstSectorX && (*pGroup)->ubSectorY == ubDstSectorY ) - { //The destination sector is the current location. Instead of causing code logic problems, + { + //The destination sector is the current location. Instead of causing code logic problems, //simply process them as if they just arrived. if( EvaluateGroupSituation( *pGroup ) ) - { //The group was deleted. + { + //The group was deleted. *pGroup = NULL; return; } @@ -6852,7 +6856,7 @@ UINT8 RedirectEnemyGroupsMovingThroughSector( UINT8 ubSectorX, UINT8 ubSectorY ) pGroup = gpGroupList; while( pGroup ) { - if ( pGroup->usGroupTeam != OUR_TEAM && pGroup->ubMoveType == ONE_WAY ) + if ( pGroup->usGroupTeam == ENEMY_TEAM && pGroup->ubMoveType == ONE_WAY ) { //check the waypoint list if( GroupWillMoveThroughSector( pGroup, ubSectorX, ubSectorY ) ) diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index 8fa262a3d..92fed1a58 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -49,6 +49,7 @@ #include "Quests.h" #include "Interface.h" // added by Flugente for zBackground #include "Reinforcement.h" // added by Flugente for AddPossiblePendingMilitiaToBattle() + #include "Militia Control.h" // added by Flugente for ResetMilitia() #endif #include "MilitiaSquads.h" @@ -778,6 +779,84 @@ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmin return NULL; } +GROUP* CreateNewMilitiaGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites ) +{ + GROUP *pNew; + AssertMsg( uiSector >= 0 && uiSector <= 255, String( "CreateNewMilitiaGroupDepartingFromSector with out of range value of %d", uiSector ) ); + pNew = (GROUP*)MemAlloc( sizeof(GROUP) ); + AssertMsg( pNew, "MemAlloc failure during CreateNewEnemyGroup." ); + memset( pNew, 0, sizeof(GROUP) ); + pNew->pEnemyGroup = (ENEMYGROUP*)MemAlloc( sizeof(ENEMYGROUP) ); + AssertMsg( pNew->pEnemyGroup, "MemAlloc failure during enemy group creation." ); + memset( pNew->pEnemyGroup, 0, sizeof(ENEMYGROUP) ); + + // Make sure group is not bigger than allowed! + while ( ubNumAdmins + ubNumTroops + ubNumElites > gGameExternalOptions.iMaxEnemyGroupSize ) + { + if ( ubNumTroops ) + { + ubNumTroops--; + } + else if ( ubNumAdmins ) + { + ubNumAdmins--; + } + else if ( ubNumElites ) + { + ubNumElites--; + } + } + + pNew->pWaypoints = NULL; + pNew->ubSectorX = (UINT8)SECTORX( uiSector ); + pNew->ubSectorY = (UINT8)SECTORY( uiSector ); + pNew->ubOriginalSector = (UINT8)uiSector; + pNew->usGroupTeam = MILITIA_TEAM; + pNew->ubMoveType = ONE_WAY; // we don't set up patrols... + pNew->ubNextWaypointID = 0; + pNew->ubFatigueLevel = 100; + pNew->ubRestAtFatigueLevel = 0; + pNew->pEnemyGroup->ubNumAdmins = ubNumAdmins; + pNew->pEnemyGroup->ubNumTroops = ubNumTroops; + pNew->pEnemyGroup->ubNumElites = ubNumElites; + pNew->ubGroupSize = (UINT8)(ubNumAdmins + ubNumTroops + ubNumElites); + pNew->ubTransportationMask = FOOT; + pNew->fVehicle = FALSE; + pNew->ubCreatedSectorID = pNew->ubOriginalSector; + pNew->ubSectorIDOfLastReassignment = 255; + +#ifdef JA2BETAVERSION + { + /*CHAR16 str[512]; + if ( PlayerMercsInSector( pNew->ubSectorX, pNew->ubSectorY, 0 ) || NumNonPlayerTeamMembersInSector( pNew->ubSectorX, pNew->ubSectorY, MILITIA_TEAM ) ) + { + swprintf( str, L"Attempting to send enemy troops from player occupied location. " + L"Please ALT+TAB out of the game before doing anything else and send 'Strategic Decisions.txt' " + L"and this message. You'll likely need to revert to a previous save. If you can reproduce this " + L"with a save close to this event, that would really help me! -- KM:0" ); + DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL ); + }*/ + /* + * Not valid + else if( pNew->ubGroupSize > 25 ) + { + swprintf( str, L"Strategic AI warning: Creating an enemy group containing %d soldiers " + L"(%d admins, %d troops, %d elites) in sector %c%d. This message is a temporary test message " + L"to evaluate a potential problems with very large enemy groups.", + pNew->ubGroupSize, ubNumAdmins, ubNumTroops, ubNumElites, + pNew->ubSectorY + 'A' - 1, pNew->ubSectorX ); + DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL ); + } + */ + } +#endif + + if ( AddGroupToList( pNew ) ) + return pNew; + + return NULL; +} + //INTERNAL LIST MANIPULATION FUNCTIONS //When adding any new group to the list, this is what must be done: @@ -1150,7 +1229,8 @@ BOOLEAN CheckConditionsForBattle( GROUP *pGroup ) } if( pGroup->uiFlags & GROUPFLAG_HIGH_POTENTIAL_FOR_AMBUSH && fBattlePending ) - { //This group has just arrived in a new sector from an adjacent sector that he retreated from + { + //This group has just arrived in a new sector from an adjacent sector that he retreated from //If this battle is an encounter type battle, then there is a 90% chance that the battle will //become an ambush scenario. gfHighPotentialForAmbush = TRUE; @@ -1172,26 +1252,37 @@ BOOLEAN CheckConditionsForBattle( GROUP *pGroup ) } } } - else + else if ( pGroup->usGroupTeam == ENEMY_TEAM ) { if ( NumNonPlayerTeamMembersInSector( pGroup->ubSectorX, pGroup->ubSectorY, MILITIA_TEAM ) ) { fMilitiaPresent = TRUE; fBattlePending = TRUE; } - if( fAliveMerc ) + + if ( fAliveMerc ) { fBattlePending = TRUE; } } + else if ( pGroup->usGroupTeam == MILITIA_TEAM ) + { + if ( NumNonPlayerTeamMembersInSector( pGroup->ubSectorX, pGroup->ubSectorY, ENEMY_TEAM ) ) + { + fMilitiaPresent = TRUE; + fBattlePending = TRUE; + } + } if( !fAliveMerc && !fMilitiaPresent ) - { //empty vehicle, everyone dead, don't care. Enemies don't care. + { + //empty vehicle, everyone dead, don't care. Enemies don't care. return FALSE; } if( fBattlePending ) - { //A battle is pending, but the players could be all unconcious or dead. + { + //A battle is pending, but the players could be all unconcious or dead. //Go through every group until we find at least one concious merc. The looping will determine //if there are any live mercs and/or concious ones. If there are no concious mercs, but alive ones, //then we will go straight to autoresolve, where the enemy will likely annihilate them or capture them. @@ -1206,7 +1297,8 @@ BOOLEAN CheckConditionsForBattle( GROUP *pGroup ) StopTimeCompression(); if( gubNumGroupsArrivedSimultaneously ) - { //Because this is a battle case, clear all the group flags + { + //Because this is a battle case, clear all the group flags curr = gpGroupList; while( curr && gubNumGroupsArrivedSimultaneously ) { @@ -1228,14 +1320,16 @@ BOOLEAN CheckConditionsForBattle( GROUP *pGroup ) } if( !fCombatAbleMerc ) - { //Prepare for instant autoresolve. + { + //Prepare for instant autoresolve. gfDelayAutoResolveStart = TRUE; gfUsePersistantPBI = TRUE; if( fMilitiaPresent ) { NotifyPlayerOfInvasionByEnemyForces( pGroup->ubSectorX, pGroup->ubSectorY, 0, TriggerPrebattleInterface ); - if( GetTownIdForSector( pGroup->ubSectorX, pGroup->ubSectorY ) == BLANK_SECTOR) + // trigger autoresolve if not in city, or this is a militia group + if ( pGroup->usGroupTeam == MILITIA_TEAM || GetTownIdForSector( pGroup->ubSectorX, pGroup->ubSectorY ) == BLANK_SECTOR ) { // CHAR16 str[ 256 ]; // UINT16 uiSectorC = L'A' + pGroup->ubSectorY - 1; @@ -1254,10 +1348,10 @@ BOOLEAN CheckConditionsForBattle( GROUP *pGroup ) } } - #ifdef JA2BETAVERSION - if( guiCurrentScreen == AIVIEWER_SCREEN ) - gfExitViewer = TRUE; - #endif +#ifdef JA2BETAVERSION + if( guiCurrentScreen == AIVIEWER_SCREEN ) + gfExitViewer = TRUE; +#endif if( pPlayerDialogGroup ) { @@ -1679,6 +1773,23 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe return; } + // Flugente: militia groups + if ( pGroup->usGroupTeam == MILITIA_TEAM ) + { + // if the group would move from the current sector... + if ( gWorldSectorX == pGroup->ubSectorX && gWorldSectorY == pGroup->ubSectorY && !gbWorldSectorZ ) + { + // if there is a fight going on in the sector where the group currently is, then we do not move them - erase the group instead + if ( gTacticalStatus.uiFlags & INCOMBAT ) + { + // once militia have arrived, move them from the group to the sector + DissolveMilitiaGroup( pGroup->ubGroupID ); + + return; + } + } + } + if ( pGroup->usGroupTeam == OUR_TEAM ) { //Set the fact we have visited the sector @@ -1765,7 +1876,6 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe pGroup->uiArrivalTime += Random(3) + 3; } - if( !AddStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->uiArrivalTime, pGroup->ubGroupID ) ) AssertMsg( 0, "Failed to add movement event." ); @@ -2080,6 +2190,9 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe fCharacterInfoPanelDirty = TRUE; } + // in case we start a battle, we do not yet destroy militia groups + BOOLEAN fBattlePending = FALSE; + if ( !fGroupDestroyed ) { //Determine if a battle should start. @@ -2107,13 +2220,80 @@ void GroupArrivedAtSector( UINT8 ubGroupID, BOOLEAN fCheckForBattle, BOOLEAN fNe } } else - { //Handle cases for pre battle conditions + { + //Handle cases for pre battle conditions pGroup->uiFlags = 0; + if( gubNumAwareBattles ) - { //When the AI is looking for the players, and a battle is initiated, then + { + //When the AI is looking for the players, and a battle is initiated, then //decrement the value, otherwise the queen will continue searching to infinity. - gubNumAwareBattles--; + --gubNumAwareBattles; } + + fBattlePending = TRUE; + } + } + + // Flugente: if a militia group has reached its final destination, add them to the current sector + if ( pGroup->usGroupTeam == MILITIA_TEAM ) + { + // if they arrive in the sector we have currently loaded, let them join from the edge + // this will always remove them from the group - if you want them to continue moving, issue a new order + if ( pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && pGroup->ubSectorZ == gbWorldSectorZ ) + { + MilitiaGroupEntersCurrentSector( pGroup->ubGroupID, pGroup->ubSectorX, pGroup->ubSectorY ); + + if ( !fBattlePending && GroupAtFinalDestination( pGroup ) ) + { + // once militia have arrived, move them from the group to the sector + DissolveMilitiaGroup( pGroup->ubGroupID ); + } + } + // if we have currently loaded the sector they are moving from, we have to remove them from tactical + else if ( pGroup->ubPrevX == gWorldSectorX && pGroup->ubPrevY == gWorldSectorY && pGroup->ubSectorZ == gbWorldSectorZ ) + { + // first, let them (and all other militia) drop their gear + if ( gGameExternalOptions.fMilitiaUseSectorInventory ) + TeamDropAll( MILITIA_TEAM ); + + // we now force a resetting of militia - they will be removed and recreated + // as the group's coordinates have alreay 'moved' to the next sector, the group militia will now be gone + gfStrategicMilitiaChangesMade = TRUE; + if ( gfStrategicMilitiaChangesMade ) + ResetMilitia( ); + + // now restock the remaining militia + if ( gGameExternalOptions.fMilitiaUseSectorInventory ) + TeamRestock( MILITIA_TEAM ); + + // move the gear along to the next sector + MoveMilitiaEquipment( pGroup->ubPrevX, pGroup->ubPrevY, pGroup->ubSectorX, pGroup->ubSectorY, pGroup->pEnemyGroup->ubNumElites, pGroup->pEnemyGroup->ubNumTroops, pGroup->pEnemyGroup->ubNumAdmins ); + + // if this is the last sector along the path, destroy the group after this and make the militia static + if ( !fBattlePending &&GroupAtFinalDestination( pGroup ) ) + { + // once militia have arrived, move them from the group to the sector + DissolveMilitiaGroup( pGroup->ubGroupID ); + } + + // for safety, reset if necessary + ResetMilitia( ); + } + else + { + // move the gear along to the next sector + MoveMilitiaEquipment( pGroup->ubPrevX, pGroup->ubPrevY, pGroup->ubSectorX, pGroup->ubSectorY, pGroup->pEnemyGroup->ubNumElites, pGroup->pEnemyGroup->ubNumTroops, pGroup->pEnemyGroup->ubNumAdmins ); + + // if this is the last sector along the path, destroy the group after this and make the militia static + if ( !fBattlePending && GroupAtFinalDestination( pGroup ) ) + { + // once militia have arrived, move them from the group to the sector + DissolveMilitiaGroup( pGroup->ubGroupID ); + } + + // for safety, reset if necessary + ResetMilitia( ); } } @@ -2586,7 +2766,7 @@ void InitiateGroupMovementToNextSector( GROUP *pGroup ) if ( !pGroup->ubSectorZ ) { BOOLEAN fCalcRegularTime = TRUE; - if ( pGroup->usGroupTeam != OUR_TEAM ) + if ( pGroup->usGroupTeam == ENEMY_TEAM ) { //Determine if the enemy group is "sleeping". If so, then simply delay their arrival time by the amount of time //they are going to be sleeping for. @@ -2596,17 +2776,21 @@ void InitiateGroupMovementToNextSector( GROUP *pGroup ) if ( Chance( 67 ) ) { //2 in 3 chance of going to sleep. - pGroup->uiTraverseTime = GetSectorMvtTimeForGroup( ubSector, ubDirection, pGroup ); uiSleepMinutes = 360 + Random( 121 ); //6-8 hours sleep - fCalcRegularTime = FALSE; } } } - - if ( fCalcRegularTime ) + else if ( pGroup->usGroupTeam == MILITIA_TEAM ) { - pGroup->uiTraverseTime = GetSectorMvtTimeForGroup( ubSector, ubDirection, pGroup ); + // As the player orders militia to move, a chance-based system is ill-advised - the player would simply cancel and reassign the order, leading to bypassing the mechanci in a tedious way + // so instead, we always add a penalty, but it will be lower + if ( GetWorldHour( ) >= 21 || GetWorldHour( ) <= 4 ) + { + uiSleepMinutes = 280; + } } + + pGroup->uiTraverseTime = GetSectorMvtTimeForGroup( ubSector, ubDirection, pGroup ); } else { @@ -2713,8 +2897,7 @@ void InitiateGroupMovementToNextSector( GROUP *pGroup ) void RemoveGroupWaypoints( UINT8 ubGroupID ) { - GROUP *pGroup; - pGroup = GetGroup( ubGroupID ); + GROUP* pGroup = GetGroup( ubGroupID ); Assert( pGroup ); RemovePGroupWaypoints( pGroup ); } @@ -4861,7 +5044,7 @@ void RandomizePatrolGroupLocation( GROUP *pGroup ) //return; //disabled for now - Assert( pGroup->usGroupTeam != OUR_TEAM ); + Assert( pGroup->usGroupTeam == ENEMY_TEAM ); Assert( pGroup->ubMoveType == ENDTOEND_FORWARDS ); Assert( pGroup->pEnemyGroup->ubIntention == PATROL ); @@ -4874,7 +5057,7 @@ void RandomizePatrolGroupLocation( GROUP *pGroup ) { if( wp->next ) { - ubMaxWaypointID++; + ++ubMaxWaypointID; } wp = wp->next; } @@ -4902,7 +5085,7 @@ void RandomizePatrolGroupLocation( GROUP *pGroup ) wp = pGroup->pWaypoints; while( wp && ubChosen ) { - ubChosen--; + --ubChosen; wp = wp->next; } @@ -4922,7 +5105,6 @@ void RandomizePatrolGroupLocation( GROUP *pGroup ) //Immediately turn off the flag once finished. gfRandomizingPatrolGroup = FALSE; - } //Whenever a player group arrives in a sector, and if bloodcats exist in the sector, diff --git a/Strategic/Strategic Movement.h b/Strategic/Strategic Movement.h index 2ad441c5c..bcb155abc 100644 --- a/Strategic/Strategic Movement.h +++ b/Strategic/Strategic Movement.h @@ -182,6 +182,9 @@ BOOLEAN SetGroupPatrolParameters( UINT8 ubGroupID, UINT8 ubRestAtFL, UINT8 ubRes //Enemy grouping functions -- private use by the strategic AI. //............................................................ GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks ); + +GROUP* CreateNewMilitiaGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites ); + #ifdef JA2UB GROUP* CreateNewEnemyGroupDepartingFromSectorUsingZLevel( UINT32 uiSector, UINT8 ubSectorZ, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks ); #endif diff --git a/Strategic/Strategic Pathing.cpp b/Strategic/Strategic Pathing.cpp index d0db7b29f..822bdf26f 100644 --- a/Strategic/Strategic Pathing.cpp +++ b/Strategic/Strategic Pathing.cpp @@ -24,6 +24,7 @@ #include "Map Screen Interface.h" #include "Game Event Hook.h" #include "Strategic AI.h" + #include "Queen Command.h" // added by Flugente #endif @@ -210,7 +211,7 @@ INT32 FindStratPath(INT16 sStart, INT16 sDestination, INT16 sMvtGroupNumber, BOO // for player groups only! pGroup = GetGroup( ( UINT8 )sMvtGroupNumber ); - if ( pGroup->usGroupTeam == OUR_TEAM ) + if ( pGroup->usGroupTeam == OUR_TEAM || pGroup->usGroupTeam == MILITIA_TEAM ) { // if player is holding down SHIFT key, find the shortest route instead of the quickest route! if ( _KeyDown( SHIFT ) ) @@ -314,7 +315,7 @@ INT32 FindStratPath(INT16 sStart, INT16 sDestination, INT16 sMvtGroupNumber, BOO { continue; } - if( GetNumberOfMilitiaInSector( sSectorX, sSectorY, 0 ) ) + if ( NumNonPlayerTeamMembersInSector( sSectorX, sSectorY, MILITIA_TEAM ) ) { continue; } @@ -478,78 +479,82 @@ INT32 FindStratPath(INT16 sStart, INT16 sDestination, INT16 sMvtGroupNumber, BOO PathStPtr BuildAStrategicPath(PathStPtr pPath , INT16 iStartSectorNum, INT16 iEndSectorNum, INT16 sMvtGroupNumber, BOOLEAN fTacticalTraversal /*, BOOLEAN fTempPath */ ) { + INT32 iCurrentSectorNum; + INT32 iDelta=0; + INT32 iPathLength; + INT32 iCount=0; + PathStPtr pNode=NULL; + PathStPtr pDeleteNode=NULL; + PathStPtr pHeadOfPathList = pPath; + INT32 iOldDelta = 0; + iCurrentSectorNum=iStartSectorNum; - INT32 iCurrentSectorNum; - INT32 iDelta=0; - INT32 iPathLength; - INT32 iCount=0; - PathStPtr pNode=NULL; - PathStPtr pDeleteNode=NULL; - PathStPtr pHeadOfPathList = pPath; - INT32 iOldDelta = 0; - iCurrentSectorNum=iStartSectorNum; + if(iEndSectorNum < MAP_WORLD_X-1) + return NULL; - if(iEndSectorNum < MAP_WORLD_X-1) - return NULL; + if (pNode==NULL) + { + // start new path list + pNode = (PathStPtr) MemAlloc(sizeof(PathSt)); + /* + if ( _KeyDown( CTRL )) + pNode->fSpeed=SLOW_MVT; + else + */ + pNode->fSpeed=NORMAL_MVT; + pNode->uiSectorId=iStartSectorNum; + pNode->pNext=NULL; + pNode->pPrev=NULL; + pNode->uiEta = GetWorldTotalMin( ); + pHeadOfPathList = pNode; + } - if (pNode==NULL) - { - // start new path list - pNode = (PathStPtr) MemAlloc(sizeof(PathSt)); -/* - if ( _KeyDown( CTRL )) - pNode->fSpeed=SLOW_MVT; - else -*/ - pNode->fSpeed=NORMAL_MVT; - pNode->uiSectorId=iStartSectorNum; - pNode->pNext=NULL; - pNode->pPrev=NULL; - pNode->uiEta = GetWorldTotalMin( ); - pHeadOfPathList = pNode; - } - - iPathLength=((INT32)FindStratPath(((INT16)iStartSectorNum),((INT16)iEndSectorNum), sMvtGroupNumber, fTacticalTraversal )); - while(iPathLength > iCount) - { - switch(gusMapPathingData[iCount]) - { + iPathLength=((INT32)FindStratPath(((INT16)iStartSectorNum),((INT16)iEndSectorNum), sMvtGroupNumber, fTacticalTraversal )); + while(iPathLength > iCount) + { + switch(gusMapPathingData[iCount]) + { case(NORTH): iDelta=NORTH_MOVE; - break; + break; case(SOUTH): iDelta=SOUTH_MOVE; - break; + break; case(EAST): iDelta=EAST_MOVE; - break; + break; case(WEST): iDelta=WEST_MOVE; - break; - } - iCount++; - // create new node - iCurrentSectorNum+=iDelta; + break; + } - if(!AddSectorToPathList(pHeadOfPathList, (UINT16)iCurrentSectorNum)) - { - pNode=pHeadOfPathList; - // intersected previous node, delete path to date - if(!pNode) - return NULL; - while(pNode->pNext) + ++iCount; + + // create new node + iCurrentSectorNum+=iDelta; + + if(!AddSectorToPathList(pHeadOfPathList, (UINT16)iCurrentSectorNum)) + { + pNode=pHeadOfPathList; + + // intersected previous node, delete path to date + if(!pNode) + return NULL; + + while(pNode->pNext) pNode=pNode->pNext; + // start backing up while(pNode->uiSectorId!=(UINT32)iStartSectorNum) - { - pDeleteNode=pNode; - pNode=pNode->pPrev; - pNode->pNext=NULL; - MemFree(pDeleteNode); - } - return NULL; - } - + { + pDeleteNode=pNode; + pNode=pNode->pPrev; + pNode->pNext=NULL; + MemFree(pDeleteNode); + } + + return NULL; + } // for strategic mvt events // we are at the new node, check if previous node was a change in deirection, ie change in delta..add waypoint @@ -568,16 +573,16 @@ PathStPtr BuildAStrategicPath(PathStPtr pPath , INT16 iStartSectorNum, INT16 iEn } } */ - iOldDelta = iDelta; + iOldDelta = iDelta; + pHeadOfPathList = pNode; - pHeadOfPathList = pNode; - if(!pNode) - return NULL; - while(pNode->pNext) - pNode=pNode->pNext; + if(!pNode) + return NULL; - } + while(pNode->pNext) + pNode=pNode->pNext; + } pNode=pHeadOfPathList; @@ -591,7 +596,7 @@ PathStPtr BuildAStrategicPath(PathStPtr pPath , INT16 iStartSectorNum, INT16 iEn MemFree(pNode); pHeadOfPathList = NULL; pPath = pHeadOfPathList; - return FALSE; + return FALSE; } /* @@ -604,8 +609,8 @@ PathStPtr BuildAStrategicPath(PathStPtr pPath , INT16 iStartSectorNum, INT16 iEn */ pPath=pHeadOfPathList; - return pPath; + return pPath; } @@ -623,12 +628,12 @@ BOOLEAN AddSectorToPathList( PathStPtr pPath ,UINT16 uiSectorNum ) return FALSE; if (pNode==NULL) - { + { pNode = (PathStPtr) MemAlloc(sizeof(PathSt)); // Implement EtaCost Array as base EtaCosts of sectors // pNode->uiEtaCost=EtaCost[uiSectorNum]; - pNode->uiSectorId=uiSectorNum; + pNode->uiSectorId=uiSectorNum; pNode->uiEta= GetWorldTotalMin( ); pNode->pNext=NULL; pNode->pPrev=NULL; @@ -639,37 +644,37 @@ BOOLEAN AddSectorToPathList( PathStPtr pPath ,UINT16 uiSectorNum ) */ pNode->fSpeed=NORMAL_MVT; - return TRUE; - } + } else - { + { //if (pNode->uiSectorId==uiSectorNum) // return FALSE; - while(pNode->pNext) - { + while(pNode->pNext) + { // if (pNode->uiSectorId==uiSectorNum) // return FALSE; - pNode=pNode->pNext; + pNode=pNode->pNext; + } - } - - pTempNode = (PathStPtr) MemAlloc(sizeof(PathSt)); - pTempNode->uiEta=0; - pNode->pNext=pTempNode; - pTempNode->uiSectorId=uiSectorNum; - pTempNode->pPrev=pNode; - pTempNode->pNext=NULL; + pTempNode = (PathStPtr) MemAlloc(sizeof(PathSt)); + pTempNode->uiEta=0; + pNode->pNext=pTempNode; + pTempNode->uiSectorId=uiSectorNum; + pTempNode->pPrev=pNode; + pTempNode->pNext=NULL; /* if ( _KeyDown( CTRL )) pTempNode->fSpeed=SLOW_MVT; else */ - pTempNode->fSpeed=NORMAL_MVT; + pTempNode->fSpeed=NORMAL_MVT; pNode=pTempNode; } + pPath = pHeadOfList; + return TRUE; } @@ -891,8 +896,8 @@ PathStPtr ClearStrategicPathList( PathStPtr pHeadOfPath, INT16 sMvtGroup ) if( ( sMvtGroup != -1 ) && ( sMvtGroup != 0 ) ) { - // clear this groups mvt pathing - RemoveGroupWaypoints( ( UINT8 )sMvtGroup ); + // clear this groups mvt pathing + RemoveGroupWaypoints( ( UINT8 )sMvtGroup ); } return( pNode ); diff --git a/Strategic/Town Militia.cpp b/Strategic/Town Militia.cpp index f280cd462..93767a7b9 100644 --- a/Strategic/Town Militia.cpp +++ b/Strategic/Town Militia.cpp @@ -414,15 +414,45 @@ void StrategicPromoteMilitiaInSector(INT16 sMapX, INT16 sMapY, UINT8 ubCurrentRa // damn well better have that many around to promote! //Assert(pSectorInfo->ubNumberOfCivsAtLevel[ ubCurrentRank ] >= ubHowMany); + UINT8 stationary = MilitiaInSectorOfRankStationary( sMapX, sMapY, ubCurrentRank ); + UINT8 ingroups = MilitiaInSectorOfRankInGroups( sMapX, sMapY, ubCurrentRank ); + //KM : July 21, 1999 patch fix - if( pSectorInfo->ubNumberOfCivsAtLevel[ ubCurrentRank ] < ubHowMany ) + if ( ubCurrentRank >= ELITE_MILITIA || stationary + ingroups < ubHowMany ) { return; } - pSectorInfo->ubNumberOfCivsAtLevel[ ubCurrentRank ] -= ubHowMany; - pSectorInfo->ubNumberOfCivsAtLevel[ ubCurrentRank + 1 ] += ubHowMany; + // determine how many static and - if necessary - group-based militia we have to remove + UINT8 reducestatic = min( stationary, ubHowMany ); + UINT8 reducegroups = min( ingroups, ubHowMany - reducestatic ); + + pSectorInfo->ubNumberOfCivsAtLevel[ubCurrentRank] -= reducestatic; + pSectorInfo->ubNumberOfCivsAtLevel[ubCurrentRank + 1] += reducestatic; + GROUP *pGroup = gpGroupList; + while ( pGroup && reducegroups ) + { + if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubSectorX == sMapX && pGroup->ubSectorY == sMapY ) + { + if ( ubCurrentRank == GREEN_MILITIA ) + { + UINT8 reduced = min( reducegroups, pGroup->pEnemyGroup->ubNumAdmins ); + pGroup->pEnemyGroup->ubNumAdmins -= reduced; + pGroup->pEnemyGroup->ubNumTroops += reduced; + reducegroups -= reduced; + } + else if ( ubCurrentRank == REGULAR_MILITIA ) + { + UINT8 reduced = min( reducegroups, pGroup->pEnemyGroup->ubNumTroops ); + pGroup->pEnemyGroup->ubNumTroops -= reduced; + pGroup->pEnemyGroup->ubNumElites += reduced; + reducegroups -= reduced; + } + } + pGroup = pGroup->next; + } + if (ubHowMany && sMapX == gWorldSectorX && sMapY == gWorldSectorY ) { gfStrategicMilitiaChangesMade = TRUE; @@ -441,13 +471,50 @@ void StrategicRemoveMilitiaFromSector(INT16 sMapX, INT16 sMapY, UINT8 ubRank, UI // damn well better have that many around to remove! //Assert(pSectorInfo->ubNumberOfCivsAtLevel[ ubRank ] >= ubHowMany); + UINT8 stationary = MilitiaInSectorOfRankStationary( sMapX, sMapY, ubRank ); + UINT8 ingroups = MilitiaInSectorOfRankInGroups( sMapX, sMapY, ubRank ); + //KM : July 21, 1999 patch fix - if( pSectorInfo->ubNumberOfCivsAtLevel[ ubRank ] < ubHowMany ) + if ( stationary + ingroups < ubHowMany ) { return; } - pSectorInfo->ubNumberOfCivsAtLevel[ ubRank ] -= ubHowMany; + // determine how many static and - if necessary - group-based militia we have to remove + UINT8 reducestatic = min( stationary, ubHowMany ); + UINT8 reducegroups = min( ingroups, ubHowMany - reducestatic ); + + pSectorInfo->ubNumberOfCivsAtLevel[ubRank] -= reducestatic; + + GROUP *pGroup = gpGroupList; + while ( pGroup && reducegroups ) + { + if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubSectorX == sMapX && pGroup->ubSectorY == sMapY ) + { + if ( ubRank == GREEN_MILITIA ) + { + UINT8 reduced = min( reducegroups, pGroup->pEnemyGroup->ubNumAdmins ); + pGroup->pEnemyGroup->ubNumAdmins -= reduced; + pGroup->ubGroupSize -= reduced; + reducegroups -= reduced; + } + else if ( ubRank == REGULAR_MILITIA ) + { + UINT8 reduced = min( reducegroups, pGroup->pEnemyGroup->ubNumTroops ); + pGroup->pEnemyGroup->ubNumTroops -= reduced; + pGroup->ubGroupSize -= reduced; + reducegroups -= reduced; + } + else if ( ubRank == ELITE_MILITIA ) + { + UINT8 reduced = min( reducegroups, pGroup->pEnemyGroup->ubNumElites ); + pGroup->pEnemyGroup->ubNumElites -= reduced; + pGroup->ubGroupSize -= reduced; + reducegroups -= reduced; + } + } + pGroup = pGroup->next; + } if (ubHowMany && sMapX == gWorldSectorX && sMapY == gWorldSectorY ) { @@ -458,6 +525,18 @@ void StrategicRemoveMilitiaFromSector(INT16 sMapX, INT16 sMapY, UINT8 ubRank, UI fMapPanelDirty = TRUE; } +void StrategicRemoveAllStaticMilitiaFromSector( INT16 sMapX, INT16 sMapY, UINT8 ubRank ) +{ + if ( ubRank < MAX_MILITIA_LEVELS ) + SectorInfo[SECTOR( sMapX, sMapY )].ubNumberOfCivsAtLevel[ubRank] = 0; + + if ( sMapX == gWorldSectorX && sMapY == gWorldSectorY ) + gfStrategicMilitiaChangesMade = TRUE; + + // update the screen display + fMapPanelDirty = TRUE; +} + // kill pts are (2 * kills) + assists UINT8 CheckOneMilitiaForPromotion(INT16 sMapX, INT16 sMapY, UINT8 ubCurrentRank, UINT8 ubRecentKillPts) @@ -488,21 +567,25 @@ UINT8 CheckOneMilitiaForPromotion(INT16 sMapX, INT16 sMapY, UINT8 ubCurrentRank, } // roll the bones, and see if he makes it - if (Random(100) < uiChanceToLevel) + if ( Chance( uiChanceToLevel ) ) { StrategicPromoteMilitiaInSector(sMapX, sMapY, ubCurrentRank, 1); if( ubCurrentRank == GREEN_MILITIA ) - { //Attempt yet another level up if sufficient points + { + //Attempt yet another level up if sufficient points if( ubRecentKillPts > 2 ) { if( CheckOneMilitiaForPromotion( sMapX, sMapY, REGULAR_MILITIA, (UINT8)(ubRecentKillPts - 2) ) ) - { //success, this militia was promoted twice + { + //success, this militia was promoted twice return 2; } } } + return 1; } + return 0; } @@ -510,39 +593,37 @@ UINT8 CheckOneMilitiaForPromotion(INT16 sMapX, INT16 sMapY, UINT8 ubCurrentRank, // call this if the player attacks his own militia void HandleMilitiaDefections(INT16 sMapX, INT16 sMapY) { - UINT8 ubRank; UINT8 ubMilitiaCnt; - UINT8 ubCount; UINT32 uiChanceToDefect; - for( ubRank = 0; ubRank < MAX_MILITIA_LEVELS; ubRank++ ) + for ( UINT8 ubRank = 0; ubRank < MAX_MILITIA_LEVELS; ++ubRank ) { ubMilitiaCnt = MilitiaInSectorOfRank(sMapX, sMapY, ubRank); - // check each guy at each rank to see if he defects - for (ubCount = 0; ubCount < ubMilitiaCnt; ubCount++) + if ( ubMilitiaCnt ) { - switch( ubRank ) + switch ( ubRank ) { - case GREEN_MILITIA: - uiChanceToDefect = 50; - break; - case REGULAR_MILITIA: - uiChanceToDefect = 75; - break; - case ELITE_MILITIA: - uiChanceToDefect = 90; - break; - default: - Assert( 0 ); - return; + case GREEN_MILITIA: + uiChanceToDefect = 50; + break; + case REGULAR_MILITIA: + uiChanceToDefect = 75; + break; + case ELITE_MILITIA: + uiChanceToDefect = 90; + break; } - // roll the bones; should I stay or should I go now? (for you music fans out there) - if (Random(100) < uiChanceToDefect) + // check each guy at each rank to see if he defects + for ( UINT8 ubCount = 0; ubCount < ubMilitiaCnt; ++ubCount ) { - //B'bye! (for you SNL fans out there) - StrategicRemoveMilitiaFromSector(sMapX, sMapY, ubRank, 1); + // roll the bones; should I stay or should I go now? (for you music fans out there) + if ( Chance( uiChanceToDefect ) ) + { + //B'bye! (for you SNL fans out there) + StrategicRemoveMilitiaFromSector(sMapX, sMapY, ubRank, 1); + } } } } @@ -551,7 +632,36 @@ void HandleMilitiaDefections(INT16 sMapX, INT16 sMapY) UINT8 MilitiaInSectorOfRank(INT16 sMapX, INT16 sMapY, UINT8 ubRank) { - unsigned count = SectorInfo[ SECTOR( sMapX, sMapY ) ].ubNumberOfCivsAtLevel[ ubRank ]; + return MilitiaInSectorOfRankStationary( sMapX, sMapY, ubRank ) + MilitiaInSectorOfRankInGroups( sMapX, sMapY, ubRank ); +} + +UINT8 MilitiaInSectorOfRankStationary( INT16 sMapX, INT16 sMapY, UINT8 ubRank ) +{ + if ( ubRank < MAX_MILITIA_LEVELS ) + return SectorInfo[SECTOR( sMapX, sMapY )].ubNumberOfCivsAtLevel[ubRank]; + + return 0; +} + +UINT8 MilitiaInSectorOfRankInGroups( INT16 sMapX, INT16 sMapY, UINT8 ubRank ) +{ + UINT8 count = 0; + + GROUP *pGroup = gpGroupList; + while ( pGroup ) + { + if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubSectorX == sMapX && pGroup->ubSectorY == sMapY ) + { + if ( ubRank == GREEN_MILITIA ) + count += pGroup->pEnemyGroup->ubNumAdmins; + else if ( ubRank == REGULAR_MILITIA ) + count += pGroup->pEnemyGroup->ubNumTroops; + else if ( ubRank == ELITE_MILITIA ) + count += pGroup->pEnemyGroup->ubNumElites; + } + pGroup = pGroup->next; + } + return count; } @@ -1179,13 +1289,12 @@ BOOLEAN CanSomeoneNearbyScoutThisSector( INT16 sSectorX, INT16 sSectorY, BOOLEAN INT16 sCounterA = 0, sCounterB = 0; UINT8 ubScoutingRange = 1; - // get the sector value sSector = sSectorX + sSectorY * MAP_WORLD_X; - for( sCounterA = sSectorX - ubScoutingRange; sCounterA <= sSectorX + ubScoutingRange; sCounterA++ ) + for( sCounterA = sSectorX - ubScoutingRange; sCounterA <= sSectorX + ubScoutingRange; ++sCounterA ) { - for( sCounterB = sSectorY - ubScoutingRange; sCounterB <= sSectorY + ubScoutingRange; sCounterB++ ) + for( sCounterB = sSectorY - ubScoutingRange; sCounterB <= sSectorY + ubScoutingRange; ++sCounterB ) { // skip out of bounds sectors if ( ( sCounterA < 1 ) || ( sCounterA > 16 ) || ( sCounterB < 1 ) || ( sCounterB > 16 ) ) @@ -1213,15 +1322,7 @@ BOOLEAN CanSomeoneNearbyScoutThisSector( INT16 sSectorX, INT16 sSectorY, BOOLEAN else { // check if any sort of militia here - if( SectorInfo[ sSectorValue ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ] ) - { - return( TRUE ); - } - else if( SectorInfo[ sSectorValue ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] ) - { - return( TRUE ); - } - else if( SectorInfo[ sSectorValue ].ubNumberOfCivsAtLevel[ ELITE_MILITIA ] ) + if ( NumNonPlayerTeamMembersInSector( sCounterA, sCounterB, MILITIA_TEAM ) ) { return( TRUE ); } @@ -1253,7 +1354,6 @@ BOOLEAN IsTownFullMilitia( INT8 bTownId, INT8 iMilitiaType ) // if sector is ours get number of militia here if( SectorOursAndPeaceful( sSectorX, sSectorY, 0 ) ) { - //Kaiden: Checking for Price Hikes. if (iMilitiaType == GREEN_MILITIA) { @@ -1262,7 +1362,7 @@ BOOLEAN IsTownFullMilitia( INT8 bTownId, INT8 iMilitiaType ) iNumberOfMilitia += MilitiaInSectorOfRank( sSectorX, sSectorY, ELITE_MILITIA ); iMaxNumber += iMaxMilitiaPerSector; - if (MilitiaInSectorOfRank( sSectorX, sSectorY, GREEN_MILITIA ) > 0) + if (MilitiaInSectorOfRank( sSectorX, sSectorY, GREEN_MILITIA ) > 0) fIncreaseCost = TRUE; } else if (iMilitiaType == REGULAR_MILITIA) @@ -1297,26 +1397,24 @@ BOOLEAN IsTownFullMilitia( INT8 bTownId, INT8 iMilitiaType ) } } - iCounter++; + ++iCounter; } - if (iMilitiaType == GREEN_MILITIA) - { - if (( iNumberOfMilitia == iMaxNumber ) && (fIncreaseCost)) - return( TRUE ); - else - return( FALSE ); - - } - else if (iMilitiaType == REGULAR_MILITIA) - { - if (( iNumberOfMilitia == iMaxNumber ) && (fIncreaseCost)) - return( TRUE ); - else - return( FALSE ); - } - + if (iMilitiaType == GREEN_MILITIA) + { + if (( iNumberOfMilitia == iMaxNumber ) && fIncreaseCost ) + return( TRUE ); + else + return( FALSE ); + } + else if (iMilitiaType == REGULAR_MILITIA) + { + if (( iNumberOfMilitia == iMaxNumber ) && fIncreaseCost) + return( TRUE ); + else + return( FALSE ); + } // now check the number of militia if ( iMaxNumber > iNumberOfMilitia ) @@ -2122,7 +2220,7 @@ void HandleMilitiaUpkeepPayment( void ) MILITIA_LIST_TYPE MilitiaList[256]; // Go through every sector and count how many militia we've got in total. - for (UINT16 cnt = 0; cnt < 256; cnt++) + for (UINT16 cnt = 0; cnt < 256; ++cnt) { SECTORINFO *pSectorInfo = &( SectorInfo[ cnt ] ); UINT8 sMapX = SECTORX(cnt); @@ -2134,18 +2232,18 @@ void HandleMilitiaUpkeepPayment( void ) if ((ubTownId != BLANK_SECTOR && MilitiaTrainingAllowedInTown(ubTownId)) || // Major Town IsThisSectorASAMSector( sMapX, sMapY, 0 ) ) // SAM Site { - MilitiaList[cnt].ubNumTownGreens = pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]; - MilitiaList[cnt].ubNumTownRegulars = pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]; - MilitiaList[cnt].ubNumTownElites = pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA]; + MilitiaList[cnt].ubNumTownGreens = MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ); + MilitiaList[cnt].ubNumTownRegulars = MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ); + MilitiaList[cnt].ubNumTownElites = MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ); MilitiaList[cnt].ubNumMobileGreens = 0; MilitiaList[cnt].ubNumMobileRegulars = 0; MilitiaList[cnt].ubNumMobileElites = 0; } else { - MilitiaList[cnt].ubNumMobileGreens = pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]; - MilitiaList[cnt].ubNumMobileRegulars = pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]; - MilitiaList[cnt].ubNumMobileElites = pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA]; + MilitiaList[cnt].ubNumMobileGreens = MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ); + MilitiaList[cnt].ubNumMobileRegulars = MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ); + MilitiaList[cnt].ubNumMobileElites = MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ); MilitiaList[cnt].ubNumTownGreens = 0; MilitiaList[cnt].ubNumTownRegulars = 0; MilitiaList[cnt].ubNumTownElites = 0; @@ -2169,53 +2267,54 @@ void HandleMilitiaUpkeepPayment( void ) uiMoneyUnpaid = 0; } - SECTORINFO *pSectorInfo = &( SectorInfo[ MilitiaList[0].ubSectorId ] ); + INT16 sX = SECTORX( MilitiaList[0].ubSectorId ); + INT16 sY = SECTORY( MilitiaList[0].ubSectorId ); if (MilitiaList[0].ubNumMobileElites > 0) { // Remove one militia from sector - pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA]--; + StrategicRemoveMilitiaFromSector( sX, sY, ELITE_MILITIA, 1 ); // Adjust list entry MilitiaList[0].ubNumMobileElites--; // Reduce debt appropriately uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobileElite; // Increase tally of militia removed - uiNumMilitiaDisbanded++; + ++uiNumMilitiaDisbanded; } else if (MilitiaList[0].ubNumMobileRegulars > 0) { - pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]--; + StrategicRemoveMilitiaFromSector( sX, sY, REGULAR_MILITIA, 1 ); MilitiaList[0].ubNumMobileRegulars--; uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobileRegular; - uiNumMilitiaDisbanded++; + ++uiNumMilitiaDisbanded; } else if (MilitiaList[0].ubNumMobileGreens > 0) { - pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]--; + StrategicRemoveMilitiaFromSector( sX, sY, GREEN_MILITIA, 1 ); MilitiaList[0].ubNumMobileGreens--; uiMoneyUnpaid -= gGameExternalOptions.usDailyCostMobileGreen; - uiNumMilitiaDisbanded++; + ++uiNumMilitiaDisbanded; } else if (MilitiaList[0].ubNumTownElites > 0) { - pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA]--; + StrategicRemoveMilitiaFromSector( sX, sY, ELITE_MILITIA, 1 ); MilitiaList[0].ubNumTownElites--; uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTownElite; - uiNumMilitiaDisbanded++; + ++uiNumMilitiaDisbanded; } else if (MilitiaList[0].ubNumTownRegulars > 0) { - pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA]--; + StrategicRemoveMilitiaFromSector( sX, sY, REGULAR_MILITIA, 1 ); MilitiaList[0].ubNumTownRegulars--; uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTownRegular; - uiNumMilitiaDisbanded++; + ++uiNumMilitiaDisbanded; } else if (MilitiaList[0].ubNumTownGreens > 0) { - pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA]--; + StrategicRemoveMilitiaFromSector( sX, sY, GREEN_MILITIA, 1 ); MilitiaList[0].ubNumTownGreens--; uiMoneyUnpaid -= gGameExternalOptions.usDailyCostTownGreen; - uiNumMilitiaDisbanded++; + ++uiNumMilitiaDisbanded; } else { @@ -2306,7 +2405,7 @@ UINT32 CalcMilitiaUpkeep( void ) { UINT32 uiTotalPayment = 0; - for (UINT16 cnt = 0; cnt < 256; cnt++) + for (UINT16 cnt = 0; cnt < 256; ++cnt) { SECTORINFO *pSectorInfo = &( SectorInfo[ cnt ] ); UINT8 sMapX = SECTORX(cnt); @@ -2316,15 +2415,15 @@ UINT32 CalcMilitiaUpkeep( void ) if ((ubTownId != BLANK_SECTOR && MilitiaTrainingAllowedInTown(ubTownId)) || // Major Town IsThisSectorASAMSector( sMapX, sMapY, 0 ) ) // SAM Site { - uiTotalPayment += pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA] * gGameExternalOptions.usDailyCostTownGreen; - uiTotalPayment += pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA] * gGameExternalOptions.usDailyCostTownRegular; - uiTotalPayment += pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] * gGameExternalOptions.usDailyCostTownElite; + uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) * gGameExternalOptions.usDailyCostTownGreen; + uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) * gGameExternalOptions.usDailyCostTownRegular; + uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ) * gGameExternalOptions.usDailyCostTownElite; } else { - uiTotalPayment += pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA] * gGameExternalOptions.usDailyCostMobileGreen; - uiTotalPayment += pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA] * gGameExternalOptions.usDailyCostMobileRegular; - uiTotalPayment += pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] * gGameExternalOptions.usDailyCostMobileElite; + uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ) * gGameExternalOptions.usDailyCostMobileGreen; + uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) * gGameExternalOptions.usDailyCostMobileRegular; + uiTotalPayment += MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ) * gGameExternalOptions.usDailyCostMobileElite; } } diff --git a/Strategic/Town Militia.h b/Strategic/Town Militia.h index c994709f2..76fba4c27 100644 --- a/Strategic/Town Militia.h +++ b/Strategic/Town Militia.h @@ -34,6 +34,8 @@ void StrategicAddMilitiaToSector(INT16 sMapX, INT16 sMapY, UINT8 ubRank, UINT8 u void StrategicPromoteMilitiaInSector(INT16 sMapX, INT16 sMapY, UINT8 ubCurrentRank, UINT8 ubHowMany); void StrategicRemoveMilitiaFromSector(INT16 sMapX, INT16 sMapY, UINT8 ubRank, UINT8 ubHowMany); +void StrategicRemoveAllStaticMilitiaFromSector( INT16 sMapX, INT16 sMapY, UINT8 ubRank ); + // this will check for promotions and handle them for you UINT8 CheckOneMilitiaForPromotion(INT16 sMapX, INT16 sMapY, UINT8 ubCurrentRank, UINT8 ubRecentKillPts); @@ -48,6 +50,8 @@ UINT8 FindBestMilitiaTrainingLeadershipInSector ( INT16 sMapX, INT16 sMapY, INT8 void HandleMilitiaDefections(INT16 sMapX, INT16 sMapY); UINT8 MilitiaInSectorOfRank(INT16 sMapX, INT16 sMapY, UINT8 ubRank); +UINT8 MilitiaInSectorOfRankStationary( INT16 sMapX, INT16 sMapY, UINT8 ubRank ); +UINT8 MilitiaInSectorOfRankInGroups( INT16 sMapX, INT16 sMapY, UINT8 ubRank ); // Returns TRUE if sector is under player control, has no enemies in it, and isn't currently in combat mode BOOLEAN SectorOursAndPeaceful( INT16 sMapX, INT16 sMapY, INT8 bMapZ ); diff --git a/Strategic/mapscreen.cpp b/Strategic/mapscreen.cpp index e0f4a60aa..a9552caca 100644 --- a/Strategic/mapscreen.cpp +++ b/Strategic/mapscreen.cpp @@ -130,6 +130,12 @@ #include "LuaInitNPCs.h" #endif +// Flugente: militia movement + +// plot +BOOLEAN fPlotForMilitia = FALSE; +UINT32 gMilitiaPlotStartSector = 0; + #define MAX_SORT_METHODS 6 // Cursors @@ -613,6 +619,16 @@ SOLDIERTYPE *gpItemPointerSoldier; PathStPtr gpCharacterPreviousMercPath[ CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS ]; PathStPtr gpHelicopterPreviousMercPath = NULL; +// this is not a group id, but the internal militia group id. You can get the currently used group via gMilitiaPath[gMilitiaGroupId].sGroupid +UINT8 gMilitiaGroupId = 0; +PathStPtr gpMilitiaPreviousMercPath = NULL; + +// this is used to note which is the 'new' group created while plotting +UINT8 gNewMilitiaGroupId = 0; + +MILITIA_PATH gMilitiaPath[MILITIA_PATROLS_MAX]; + + // GLOBAL VARIABLES (EXTERNAL) extern BOOLEAN fHoveringHelicopter; extern BOOLEAN fDeletedNode; @@ -650,6 +666,7 @@ extern UINT32 guiUIMessageTimeDelay; extern PathStPtr pTempCharacterPath; extern PathStPtr pTempHelicopterPath; +extern PathStPtr pTempMilitiaPath; extern BOOLEAN gfAutoAIAware; extern void HandlePreBattleInterfaceStates(); @@ -959,7 +976,6 @@ BOOLEAN HandleCtrlOrShiftInTeamPanel( INT8 bCharNumber, BOOLEAN fFromRightClickA INT32 GetContractExpiryTime( SOLDIERTYPE *pSoldier ); -void ConvertMinTimeToETADayHourMinString( UINT32 uiTimeInMin, STR16 sString ); INT32 GetGroundTravelTimeOfCharacter( INT8 bCharNumber ); INT16 CalcLocationValueForChar( INT32 iCounter ); @@ -3277,12 +3293,11 @@ INT32 GetPathTravelTimeDuringPlotting( PathStPtr pPath ) INT32 iTravelTime = 0; WAYPOINT pCurrent; WAYPOINT pNext; - GROUP *pGroup; + GROUP *pGroup = NULL; UINT8 ubGroupId = 0; BOOLEAN fSkipFirstNode = FALSE; - - if( ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) + if ( (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { return( 0 ); } @@ -3299,8 +3314,23 @@ INT32 GetPathTravelTimeDuringPlotting( PathStPtr pPath ) pPath = MoveToBeginningOfPathList( pPath ); + if( fPlotForHelicopter ) + { + ubGroupId = pVehicleList[iHelicopterVehicleId].ubMovementGroup; + pGroup = GetGroup( ubGroupId ); + AssertNotNIL( pGroup ); + } + else if ( fPlotForMilitia ) + { + if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) + { + ubGroupId = (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid; + pGroup = GetGroup( ubGroupId ); + } - if( fPlotForHelicopter == FALSE ) + AssertNotNIL( pGroup ); + } + else { // plotting for a character... if( Menptr[gCharactersList[bSelectedDestChar].usSolID].bAssignment == VEHICLE ) @@ -3340,12 +3370,6 @@ INT32 GetPathTravelTimeDuringPlotting( PathStPtr pPath ) AssertNotNIL(pGroup); } } - else - { - ubGroupId = pVehicleList[ iHelicopterVehicleId ].ubMovementGroup; - pGroup = GetGroup( ubGroupId ); - AssertNotNIL(pGroup); - } // if between sectors if ( pGroup->fBetweenSectors ) @@ -3392,26 +3416,25 @@ INT32 GetPathTravelTimeDuringPlotting( PathStPtr pPath ) void DisplayGroundEta( void ) { UINT32 iTotalTime = 0; - - - if( fPlotForHelicopter == TRUE ) - { + + if( fPlotForHelicopter ) return; - } - if( bSelectedDestChar == -1 ) + if ( fPlotForMilitia ) { - return; + iTotalTime = GetGroundTravelTimeOfMilitia( ); } - - if( !gCharactersList[bSelectedDestChar].fValid ) + else { - return; + if( bSelectedDestChar == -1 ) + return; + + if( !gCharactersList[bSelectedDestChar].fValid ) + return; + + iTotalTime = GetGroundTravelTimeOfCharacter( bSelectedDestChar ); } - - iTotalTime = GetGroundTravelTimeOfCharacter( bSelectedDestChar ); - // now display it SetFont( ETA_FONT ); SetFontForeground( FONT_LTGREEN ); @@ -3779,6 +3802,7 @@ void LoadCharacters( void ) bSelectedAssignChar = -1; bSelectedContractChar = -1; fPlotForHelicopter = FALSE; + fPlotForMilitia = FALSE; } } @@ -5599,9 +5623,8 @@ UINT32 MapScreenHandle(void) MarkAllBoxesAsAltered( ); } - // if plotting path - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { // plot out paths PlotPermanentPaths( ); @@ -5614,7 +5637,6 @@ UINT32 MapScreenHandle(void) //DisplayDestinationOfCurrentDestMerc( ); } - HandleContractRenewalSequence( ); // handle dialog @@ -5741,6 +5763,8 @@ UINT32 MapScreenHandle(void) DrawMilitiaPopUpBox( ); + DisplayMilitiaGroupBox(); + if( fDisableDueToBattleRoster == FALSE ) { CreateDestroyTheUpdateBox( ); @@ -6296,7 +6320,7 @@ void RenderMapCursorsIndexesAnims( ) // handle highlighting of selected sector ( YELLOW ) - don't show it while plotting movement - if ( fDrawCursors && ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) + if ( fDrawCursors && (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { // if mouse cursor is over the currently selected sector if( ( gsHighlightSectorX == sSelMapX ) && ( gsHighlightSectorY == sSelMapY ) ) @@ -6372,11 +6396,9 @@ UINT32 HandleMapUI( ) UINT32 uiNewScreen = MAP_SCREEN; BOOLEAN fWasAlreadySelected; - // Get Input from keyboard GetMapKeyboardInput( &uiNewEvent ); - CreateDestroyMapInvButton(); // Get mouse @@ -6393,12 +6415,11 @@ UINT32 HandleMapUI( ) GetMouseMapXY(&sMapX, &sMapY); // plotting for the chopper? - if( fPlotForHelicopter == TRUE ) + if( fPlotForHelicopter ) { - - if( IsSectorOutOfTheWay( sMapX, sMapY ) == TRUE ) + if( IsSectorOutOfTheWay( sMapX, sMapY ) ) { - if( gfAllowSkyriderTooFarQuote == TRUE ) + if( gfAllowSkyriderTooFarQuote ) { SkyRiderTalk( DESTINATION_TOO_FAR ); } @@ -6406,10 +6427,24 @@ UINT32 HandleMapUI( ) return( MAP_SCREEN ); } - PlotPathForHelicopter( sMapX, sMapY ); fTeamPanelDirty = TRUE; } + else if ( fPlotForMilitia ) + { + /*f ( IsSectorOutOfTheWay( sMapX, sMapY ) ) + { + if ( gfAllowSkyriderTooFarQuote ) + { + SkyRiderTalk( DESTINATION_TOO_FAR ); + } + + return(MAP_SCREEN); + }*/ + + PlotPathForMilitia( sMapX, sMapY ); + fTeamPanelDirty = TRUE; + } else { // plot for character @@ -6646,10 +6681,10 @@ UINT32 HandleMapUI( ) // if we're in airspace mode - if( fShowAircraftFlag == TRUE ) + if( fShowAircraftFlag ) { // if not moving soldiers, and not yet plotting the helicopter - if ( ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) + if ( (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { // if we're on the surface level, and the click is over the helicopter icon // NOTE: The helicopter icon is NOT necessarily directly over the helicopter's current sector!!! @@ -6660,6 +6695,22 @@ UINT32 HandleMapUI( ) } } } + // Flugente: militia movement + else if ( fShowMilitia ) + { + // if not moving soldiers, and not yet plotting the helicopter + if ( (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) + { + if ( !iCurrentMapSectorZ && NumNonPlayerTeamMembersInSector( sMapX, sMapY , MILITIA_TEAM) > 0 ) + { + // move this later on... + //MilitiaPlotInit(); + + if ( RequestGiveMilitiaNewDestination( ) ) + return(MAP_SCREEN); + } + } + } else // not in airspace mode { // sector must be already selected to initiate movement plotting! This is to allow selecting sectors with @@ -6855,7 +6906,7 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) DeleteItemDescriptionBox( ); } // plotting movement? - else if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + else if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -7192,7 +7243,7 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) case F12: #ifdef JA2BETAVERSION - *puiNewEvent = MAP_EVENT_VIEWAI; + //*puiNewEvent = MAP_EVENT_VIEWAI; #endif break; @@ -7449,11 +7500,6 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) //activate autoresolve in prebattle interface. ActivatePreBattleAutoresolveAction(); } - // Flugente: militia orders - else if ( SetMilitiaMovementOrder(sSelMapX, sSelMapY, iCurrentMapSectorZ, MILITIA_MOVE_WEST) ) - { - ; - } else { // only handle border button keyboard equivalents if the button is visible! @@ -7507,11 +7553,6 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) TestDumpStatChanges(); } #endif - // Flugente: militia orders - if ( SetMilitiaMovementOrder(sSelMapX, sSelMapY, iCurrentMapSectorZ, MILITIA_MOVE_EAST) ) - { - ; - } break; case 'D': @@ -7742,7 +7783,7 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) #endif { // ARM: Feb01/98 - Cancel out of mapscreen movement plotting if Help subscreen is coming up - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -7983,7 +8024,7 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) ActivatePreBattleRetreatAction(); } // WANNE: Only allow when mobile militia is allowed! - else if (gGameExternalOptions.gfAllowMilitiaGroups) + else if ( gGameExternalOptions.gfAllowMilitiaGroups && !gGameExternalOptions.fMilitiaStrategicCommand ) { // only handle border button keyboard equivalents if the button is visible! if ( !fShowMapInventoryPool ) @@ -8031,11 +8072,6 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) gfSaveGame = TRUE; RequestTriggerExitFromMapscreen( MAP_EXIT_TO_SAVE ); } - // Flugente: militia orders - else if ( SetMilitiaMovementOrder(sSelMapX, sSelMapY, iCurrentMapSectorZ, MILITIA_MOVE_SOUTH) ) - { - ; - } else if(gGameExternalOptions.fEnableInventoryPoolQ && fShowMapInventoryPool == TRUE)//dnl ch51 081009 { SortInventoryPoolQ(); @@ -8069,7 +8105,7 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) if( ( fCtrl )&&( CHEATER_CHEAT_LEVEL( ) ) ) { // check if selected dest char, - if( ( bSelectedDestChar != -1 ) && ( fPlotForHelicopter == FALSE ) && ( iCurrentMapSectorZ == 0 ) && ( GetMouseMapXY( &sMapX, &sMapY ) ) ) + if ( (bSelectedDestChar != -1) && !fPlotForHelicopter && !fPlotForMilitia && (iCurrentMapSectorZ == 0) && (GetMouseMapXY( &sMapX, &sMapY )) ) { INT16 sDeltaX, sDeltaY; INT16 sPrevX, sPrevY; @@ -8173,7 +8209,7 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) // if not already in sector inventory if ( !fShowMapInventoryPool ) { - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -8278,11 +8314,6 @@ void GetMapKeyboardInput( UINT32 *puiNewEvent ) else if( fCtrl ) { } - // Flugente: militia orders - else if ( SetMilitiaMovementOrder(sSelMapX, sSelMapY, iCurrentMapSectorZ, MILITIA_MOVE_NORTH) ) - { - ; - } else { // only handle border button keyboard equivalents if the button is visible! @@ -8473,7 +8504,7 @@ INT32 iCounter2 = 0; // still plotting movement? - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -8747,7 +8778,6 @@ BOOLEAN GetMouseMapXY( INT16 *psMapWorldX, INT16 *psMapWorldY ) return( FALSE ); } - GetCursorPos(&MousePos); ScreenToClient(ghWindow, &MousePos); // In window coords! @@ -8770,19 +8800,15 @@ BOOLEAN GetMapXY( INT16 sX, INT16 sY, INT16 *psMapWorldX, INT16 *psMapWorldY ) return( FALSE ); } - if ( sMapX < 0 || sMapY < 0 ) + if ( sMapX < 1 || sMapY < 1 ) { - return( FALSE ); + return (FALSE); } if ( sMapX > MAP_VIEW_WIDTH+MAP_GRID_X-1 || sMapY > MAP_VIEW_HEIGHT+7/* +MAP_VIEW_HEIGHT */ ) { return( FALSE ); } - if(sMapX < 1 || sMapY <1) - { - return (FALSE); - } *psMapWorldX = ( sMapX / MAP_GRID_X ); *psMapWorldY = ( sMapY / MAP_GRID_Y ); @@ -8907,7 +8933,7 @@ void PollLeftButtonInMapView( UINT32 *puiNewEvent ) // if in "plot route" mode - if ( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { fEndPlotting = FALSE; @@ -8926,7 +8952,7 @@ void PollLeftButtonInMapView( UINT32 *puiNewEvent ) *puiNewEvent = MAP_EVENT_PLOT_PATH; } } - else // not plotting movement + else // not plotting movement { // if not plotting a path if( ( fEndPlotting == FALSE ) && ( fJustFinishedPlotting == FALSE ) ) @@ -9013,7 +9039,7 @@ void PollRightButtonInMapView( UINT32 *puiNewEvent ) } - if ( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { // cancel/shorten the path *puiNewEvent = MAP_EVENT_CANCEL_PATH; @@ -10088,10 +10114,20 @@ void DisplayThePotentialPathForCurrentDestinationCharacterForMapScreenInterface( void SetUpCursorForStrategicMap( void ) { - if ( gfInChangeArrivalSectorMode == FALSE ) + if ( !gfInChangeArrivalSectorMode ) { // check if character is in destination plotting mode - if( fPlotForHelicopter == FALSE ) + if ( fPlotForHelicopter ) + { + // set cursor to chopper + ChangeMapScreenMaskCursor( CURSOR_CHOPPER ); + } + else if ( fPlotForMilitia ) + { + // set cursor to chopper + ChangeMapScreenMaskCursor( CURSOR_STRATEGIC_FOOT );//CURSOR_MILITIA ); + } + else { if( bSelectedDestChar == -1 ) { @@ -10111,11 +10147,6 @@ void SetUpCursorForStrategicMap( void ) } } } - else // yes - by helicopter - { - // set cursor to chopper - ChangeMapScreenMaskCursor( CURSOR_CHOPPER ); - } } else { @@ -10128,21 +10159,19 @@ void SetUpCursorForStrategicMap( void ) void HandleAnimatedCursorsForMapScreen( ) { - if ( COUNTERDONE( CURSORCOUNTER ) ) { RESETCOUNTER( CURSORCOUNTER ); - UpdateAnimatedCursorFrames( gMapScreenMaskRegion.Cursor ); + UpdateAnimatedCursorFrames( gMapScreenMaskRegion.Cursor ); SetCurrentCursorFromDatabase( gMapScreenMaskRegion.Cursor ); } - } void AbortMovementPlottingMode( void ) { // invalid if we're not plotting movement - Assert( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ); + Assert( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ); // make everybody go back to where they were going before this plotting session started RestorePreviousPaths(); @@ -10166,6 +10195,12 @@ void AbortMovementPlottingMode( void ) pTempHelicopterPath = ClearStrategicPathList( pTempHelicopterPath, 0 ); } + if ( pTempMilitiaPath ) + { + // make sure we're at the beginning + pTempMilitiaPath = MoveToBeginningOfPathList( pTempMilitiaPath ); + pTempMilitiaPath = ClearStrategicPathList( pTempMilitiaPath, 0 ); + } EndConfirmMapMoveMode( ); @@ -10175,11 +10210,24 @@ void AbortMovementPlottingMode( void ) // cancel movement mode bSelectedDestChar = -1; fPlotForHelicopter = FALSE; + + if ( fPlotForMilitia ) + { + if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) + { + DissolveMilitiaGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); + } + + MilitiaplotFinish( ); + + fPlotForMilitia = FALSE; + } + + gMilitiaPath[gMilitiaGroupId].path = NULL; // tell player the route was UNCHANGED MapScreenMessage( FONT_MCOLOR_LTYELLOW, MSG_MAP_UI_POSITION_MIDDLE, pMapPlotStrings[ 2 ] ); - // reset cursors ChangeMapScreenMaskCursor( CURSOR_NORMAL ); SetUpCursorForStrategicMap( ); @@ -10202,16 +10250,16 @@ void CheckToSeeIfMouseHasLeftMapRegionDuringPathPlotting( ) if ( ( gMapViewRegion.uiFlags & MSYS_MOUSE_IN_AREA ) == 0 ) { - - if( fInArea == TRUE ) + if( fInArea ) { fInArea = FALSE; // plotting path, clean up - if( ( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) || ( fDrawTempHeliPath == TRUE ) ) && ( fTempPathAlreadyDrawn == TRUE ) ) + if ( ((bSelectedDestChar != -1) || fPlotForHelicopter || fDrawTempHeliPath || fPlotForMilitia || fDrawTempMilitiaPath ) && fTempPathAlreadyDrawn ) { fDrawTempHeliPath = FALSE; - fMapPanelDirty = TRUE; + fDrawTempMilitiaPath = FALSE; + fMapPanelDirty = TRUE; gfRenderPBInterface = TRUE; // clear the temp path @@ -10220,6 +10268,11 @@ void CheckToSeeIfMouseHasLeftMapRegionDuringPathPlotting( ) pTempCharacterPath = MoveToBeginningOfPathList( pTempCharacterPath); pTempCharacterPath = ClearStrategicPathList( pTempCharacterPath, 0 ); } + else if ( pTempMilitiaPath ) + { + pTempMilitiaPath = MoveToBeginningOfPathList( pTempMilitiaPath ); + pTempMilitiaPath = ClearStrategicPathList( pTempMilitiaPath, 0 ); + } } // reset fact temp path has been drawn @@ -10230,8 +10283,6 @@ void CheckToSeeIfMouseHasLeftMapRegionDuringPathPlotting( ) { fInArea = TRUE; } - - return; } @@ -10529,7 +10580,7 @@ void ContractButtonCallback(GUI_BUTTON *btn,INT32 reason) } /* - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if( ( bSelectedDestChar != -1 ) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); return; @@ -10614,6 +10665,7 @@ void TeamListInfoRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) bSelectedDestChar = -1; bSelectedContractChar = -1; fPlotForHelicopter = FALSE; + fPlotForMilitia = FALSE; // if not dead or POW, select his sector if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) ) @@ -10655,11 +10707,9 @@ void TeamListInfoRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) // select this character ChangeSelectedInfoChar( ( INT8 ) iValue+ FIRSTmercTOdisplay, TRUE ); - - + RequestToggleMercInventoryPanel(); - // highlight giDestHighLine = -1; @@ -10668,6 +10718,7 @@ void TeamListInfoRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) bSelectedDestChar = -1; bSelectedContractChar = -1; fPlotForHelicopter = FALSE; + fPlotForMilitia = FALSE; // if not dead or POW, select his sector if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) ) @@ -10774,6 +10825,7 @@ void TeamListAssignmentRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) // reset dest character bSelectedDestChar = -1; fPlotForHelicopter = FALSE; + fPlotForMilitia = FALSE; // reset contract char bSelectedContractChar = -1; @@ -10835,7 +10887,6 @@ void TeamListAssignmentRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) if( gCharactersList[ iValue + FIRSTmercTOdisplay].fValid == TRUE ) { - ChangeSelectedInfoChar( ( INT8 ) iValue + FIRSTmercTOdisplay, TRUE ); pSoldier = &Menptr[ gCharactersList[ iValue + FIRSTmercTOdisplay].usSolID ]; @@ -10848,6 +10899,7 @@ void TeamListAssignmentRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) bSelectedDestChar = -1; bSelectedContractChar = -1; fPlotForHelicopter = FALSE; + fPlotForMilitia = FALSE; // if not dead or POW, select his sector if( ( pSoldier->stats.bLife > 0 ) && ( pSoldier->bAssignment != ASSIGNMENT_POW ) ) @@ -10966,7 +11018,6 @@ void TeamListDestinationRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) { INT32 iValue = 0; - if( fLockOutMapScreenInterface || gfPreBattleInterfaceActive || fShowMapInventoryPool ) { return; @@ -11067,7 +11118,6 @@ void TeamListDestinationRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) } } - if (iReason & MSYS_CALLBACK_REASON_RBUTTON_UP) { MakeMapModesSuitableForDestPlotting( ( INT8 ) iValue + FIRSTmercTOdisplay ); @@ -11077,6 +11127,9 @@ void TeamListDestinationRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) CancelPathsOfAllSelectedCharacters(); + if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) + CancelPathForMilitiaGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); + // reset selected characters ResetAllSelectedCharacterModes( ); } @@ -11303,6 +11356,7 @@ void TeamListContractRegionBtnCallBack(MOUSE_REGION *pRegion, INT32 iReason ) bSelectedDestChar = -1; bSelectedContractChar = -1; fPlotForHelicopter = FALSE; + fPlotForMilitia = FALSE; fTeamPanelDirty = TRUE; } @@ -11446,20 +11500,24 @@ void HandleHighLightingOfLinesInTeamPanel( void ) // contracts? if( giContractHighLine != -1 ) { - ContractListRegionBoxGlow( ( UINT16 ) giContractHighLine ); + ContractListRegionBoxGlow( ( UINT16 ) giContractHighLine ); } } void PlotPermanentPaths( void ) { - if( fPlotForHelicopter == TRUE ) + if( fPlotForHelicopter ) { DisplayHelicopterPath( ); } + else if ( fPlotForMilitia ) + { + DisplayMilitiaPath(); + } else if( bSelectedDestChar != -1 ) { - DisplaySoldierPath( &Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ] ); + DisplaySoldierPath( &Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ] ); } } @@ -11468,13 +11526,12 @@ void PlotTemporaryPaths( void ) { INT16 sMapX, sMapY; - // check to see if we have in fact moved are are plotting a path? if ( GetMouseMapXY( &sMapX, &sMapY ) ) { - if ( fPlotForHelicopter == TRUE ) + if ( fPlotForHelicopter ) { - Assert( fShowAircraftFlag == TRUE ); + Assert( fShowAircraftFlag ); // plot temp path PlotATemporaryPathForHelicopter( sMapX, sMapY); @@ -11482,7 +11539,7 @@ void PlotTemporaryPaths( void ) // check if potential path is allowed DisplayThePotentialPathForHelicopter( sMapX, sMapY ); - if( fDrawTempHeliPath == TRUE ) + if( fDrawTempHeliPath ) { // clip region ClipBlitsToMapViewRegion( ); @@ -11492,11 +11549,29 @@ void PlotTemporaryPaths( void ) RestoreClipRegionToFullScreen( ); } } - else - // dest char has been selected, - if( bSelectedDestChar != -1 ) + else if ( fPlotForMilitia ) { + Assert( fShowMilitia ); + // plot temp path + PlotATemporaryPathForMilitia( sMapX, sMapY ); + + // check if potential path is allowed + DisplayThePotentialPathForMilitia( sMapX, sMapY ); + + if ( fDrawTempMilitiaPath ) + { + // clip region + ClipBlitsToMapViewRegion( ); + // display heli temp path + DisplayMilitiaTempPath( ); + //restore + RestoreClipRegionToFullScreen( ); + } + } + // dest char has been selected, + else if( bSelectedDestChar != -1 ) + { PlotATemporaryPathForCharacter( &Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ], sMapX, sMapY ); // check to see if we are drawing path @@ -11537,7 +11612,6 @@ void RenderMapRegionBackground( void ) DrawMap( ); } - // blit in border RenderMapBorder( ); @@ -11558,7 +11632,6 @@ void RenderMapRegionBackground( void ) ForceUpDateOfBox( ghTownMineBox ); } - MapscreenMarkButtonsDirty(); RestoreExternBackgroundRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT ); @@ -11578,8 +11651,6 @@ void RenderMapRegionBackground( void ) fMapPanelDirty = FALSE; gfMapPanelWasRedrawn = TRUE; - - return; } @@ -11587,7 +11658,6 @@ void RenderTeamRegionBackground( void ) { HVOBJECT hHandle; - // renders to save buffer when dirty flag set if( fTeamPanelDirty == FALSE ) { @@ -11606,7 +11676,6 @@ void RenderTeamRegionBackground( void ) BltCharInvPanel(); } - if ( !fShowInventoryFlag ) { // if we are not in inventory mode, show character list @@ -11616,13 +11685,11 @@ void RenderTeamRegionBackground( void ) } fDrawCharacterList = FALSE; - - + // display arrows by selected people HandleDisplayOfSelectedMercArrows( ); DisplayIconsForMercsAsleep( ); - // reset dirty flag fTeamPanelDirty = FALSE; gfRenderPBInterface = TRUE; @@ -11649,8 +11716,6 @@ void RenderTeamRegionBackground( void ) } MapscreenMarkButtonsDirty(); - - return; } @@ -11658,7 +11723,6 @@ void RenderCharacterInfoBackground( void ) { HVOBJECT hHandle; - // will render the background for the character info panel if( fCharacterInfoPanelDirty == FALSE ) @@ -11667,7 +11731,6 @@ void RenderCharacterInfoBackground( void ) return; } - // the upleft hand corner character info panel GetVideoObject(&hHandle, guiCHARINFO); BltVideoObject( guiSAVEBUFFER , hHandle, 0,TOWN_INFO_X, TOWN_INFO_Y , VO_BLT_SRCTRANSPARENCY,NULL ); @@ -11705,7 +11768,6 @@ void DetermineIfContractMenuCanBeShown( void ) { if( fShowContractMenu == FALSE ) { - // destroy menus for contract region CreateDestroyMouseRegionsForContractMenu( ); @@ -11717,8 +11779,7 @@ void DetermineIfContractMenuCanBeShown( void ) { HideBox( ghRemoveMercAssignBox ); } - - + return; } @@ -11746,25 +11807,33 @@ void DetermineIfContractMenuCanBeShown( void ) void CheckIfPlottingForCharacterWhileAirCraft( void ) { - // if we are in aircraft mode and plotting for character, reset plotting character + // if the plotting modes are inconsistent, stop plotting + BOOLEAN fAbort = FALSE; - if( fShowAircraftFlag == TRUE ) + if ( fShowAircraftFlag ) { - // if plotting, but not for heli - if ( ( bSelectedDestChar != -1 ) && ( fPlotForHelicopter == FALSE ) ) - { - // abort - AbortMovementPlottingMode(); - } + if ( (bSelectedDestChar != -1 || fPlotForMilitia) && !fPlotForHelicopter ) + fAbort = TRUE; } - else // not in airspace mode + else { - if( fPlotForHelicopter == TRUE ) - { - // abort - AbortMovementPlottingMode(); - } + if ( fPlotForHelicopter ) + fAbort = TRUE; } + + if ( fShowMilitia ) + { + if ( (bSelectedDestChar != -1 || fPlotForHelicopter) && !fPlotForMilitia ) + fAbort = TRUE; + } + else + { + if ( fPlotForMilitia ) + fAbort = TRUE; + } + + if ( fAbort ) + AbortMovementPlottingMode( ); } @@ -11772,7 +11841,6 @@ void ContractRegionBtnCallback( MOUSE_REGION *pRegion, INT32 iReason ) { SOLDIERTYPE *pSoldier = NULL; - // btn callback handler for contract region if( ( iDialogueBox != -1 ) ) @@ -12182,10 +12250,9 @@ void ResetAllSelectedCharacterModes( void ) // unhilight contract line giContractHighLine = -1; - - + // if we were plotting movement - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode(); } @@ -12196,18 +12263,13 @@ void ResetAllSelectedCharacterModes( void ) // reset contract character bSelectedContractChar = -1; - // reset map cursor to normal if ( !gfFadeOutDone && !gfFadeIn ) { - SetUpCursorForStrategicMap( ); + SetUpCursorForStrategicMap( ); } - - return; } - - void UpdatePausedStatesDueToTimeCompression( void ) { // this executes every frame, so keep it optimized for speed! @@ -12327,7 +12389,7 @@ BOOLEAN CheckIfClickOnLastSectorInPath( INT16 sX, INT16 sY ) // see if we have clicked on the last sector in the characters path // check if helicopter - if( fPlotForHelicopter == TRUE ) + if( fPlotForHelicopter ) { // helicopter route confirmed if( sX + ( sY * MAP_WORLD_X ) == GetLastSectorOfHelicoptersPath( ) ) @@ -12352,6 +12414,30 @@ BOOLEAN CheckIfClickOnLastSectorInPath( INT16 sX, INT16 sY ) fLastSectorInPath = TRUE; } } + else if ( fPlotForMilitia ) + { + // helicopter route confirmed + if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 && sX + (sY * MAP_WORLD_X) == GetLastSectorOfMilitiaPath( ) ) + { + // if confirm moving to another sector + //if( ( CheckForClickOverHelicopterIcon( sX, sY ) == FALSE ) ) + { + // take off + //TakeOffHelicopter( ); + } + + // rebuild waypoints - helicopter + ppMovePath = &(gMilitiaPath[gMilitiaGroupId].path); + RebuildWayPointsForGroupPath( *ppMovePath, (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); + + // pointer to previous helicopter path + pPreviousMercPath = gpMilitiaPreviousMercPath; + + fLastSectorInPath = TRUE; + + //gMilitiaPlotStartSector = (INT16)(sX + sY*(MAP_WORLD_X));//SECTOR(sX, sY); + } + } else // not doing helicopter movement { // if not doing a soldier either, we shouldn't be here! @@ -12403,7 +12489,6 @@ BOOLEAN CheckIfClickOnLastSectorInPath( INT16 sX, INT16 sY ) } } - // if the click was over the last sector if ( fLastSectorInPath ) { @@ -12432,7 +12517,6 @@ BOOLEAN CheckIfClickOnLastSectorInPath( INT16 sX, INT16 sY ) } } - return( fLastSectorInPath ); } @@ -12506,38 +12590,21 @@ void UpdateCursorIfInLastSector( void ) INT16 sMapX = 0, sMapY = 0; // check to see if we are plotting a path, if so, see if we are highlighting the last sector int he path, if so, change the cursor - if ( ( bSelectedDestChar != -1) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { GetMouseMapXY(&sMapX, &sMapY); - if( fShowAircraftFlag == FALSE ) - { - if( bSelectedDestChar != -1 ) - { - //c heck if we are in the last sector of the characters path? - if( sMapX + ( sMapY * MAP_WORLD_X ) == GetLastSectorIdInCharactersPath( ( &Menptr[ gCharactersList[ bSelectedDestChar ].usSolID ] ) ) ) - { - // set cursor to checkmark - ChangeMapScreenMaskCursor( CURSOR_CHECKMARK ); - } - else if( fCheckCursorWasSet ) - { - // reset to walking guy/vehicle - SetUpCursorForStrategicMap( ); - } - } - } - else + if ( fShowAircraftFlag ) { // check for helicopter - if( fPlotForHelicopter ) + if ( fPlotForHelicopter ) { - if( sMapX + ( sMapY * MAP_WORLD_X ) == GetLastSectorOfHelicoptersPath( ) ) + if ( sMapX + (sMapY * MAP_WORLD_X) == GetLastSectorOfHelicoptersPath( ) ) { // set cursor to checkmark ChangeMapScreenMaskCursor( CURSOR_CHECKMARK ); } - else if( fCheckCursorWasSet ) + else if ( fCheckCursorWasSet ) { // reset to walking guy/vehicle SetUpCursorForStrategicMap( ); @@ -12549,10 +12616,46 @@ void UpdateCursorIfInLastSector( void ) SetUpCursorForStrategicMap( ); } } + else if ( fShowMilitia ) + { + // check for militia + if ( fPlotForMilitia ) + { + if ( sMapX + (sMapY * MAP_WORLD_X) == GetLastSectorOfMilitiaPath( ) ) + { + // set cursor to checkmark + ChangeMapScreenMaskCursor( CURSOR_CHECKMARK ); + } + else if ( fCheckCursorWasSet ) + { + // reset to walking guy/vehicle + SetUpCursorForStrategicMap( ); + } + } + else + { + // reset to walking guy/vehicle + SetUpCursorForStrategicMap( ); + } + } + else + { + if ( bSelectedDestChar != -1 ) + { + //c heck if we are in the last sector of the characters path? + if ( sMapX + (sMapY * MAP_WORLD_X) == GetLastSectorIdInCharactersPath( (&Menptr[gCharactersList[bSelectedDestChar].usSolID]) ) ) + { + // set cursor to checkmark + ChangeMapScreenMaskCursor( CURSOR_CHECKMARK ); + } + else if ( fCheckCursorWasSet ) + { + // reset to walking guy/vehicle + SetUpCursorForStrategicMap( ); + } + } + } } - - return; - } @@ -12671,7 +12774,7 @@ void HandleChangeOfHighLightedLine( void ) giSleepHighLine = -1; // don't do during plotting, allowing selected character to remain highlighted and their destination column to glow! - if( ( bSelectedDestChar == -1 ) && ( fPlotForHelicopter == FALSE ) ) + if ( (bSelectedDestChar == -1) && !fPlotForHelicopter && !fPlotForMilitia ) { giDestHighLine = -1; } @@ -13259,9 +13362,6 @@ BOOLEAN AnyMercsLeavingRealSoon() void HandleRemovalOfPreLoadedMapGraphics( void ) { - -INT32 iCounter2 = 0; - if( fPreLoadedMapGraphics == TRUE ) { DeleteMapBottomGraphics( ); @@ -13309,7 +13409,7 @@ INT32 iCounter2 = 0; DeleteVideoObjectFromIndex( guiBULLSEYE ); //----------- Legion 2 - for( iCounter2 = 1; iCounter2 < NUM_TOWNS; iCounter2++ ) + for ( INT32 iCounter2 = 1; iCounter2 < NUM_TOWNS; ++iCounter2 ) { //if ( gfDrawHiddenTown[iCounter2] == TRUE ) DeleteVideoObjectFromIndex(guiIcon2[iCounter2]); @@ -13326,8 +13426,6 @@ INT32 iCounter2 = 0; // get rid of border stuff DeleteMapBorderGraphics( ); } - - return; } @@ -14370,14 +14468,12 @@ BOOLEAN CanChangeDestinationForCharSlot( INT8 bCharNumber, BOOLEAN fShowErrorMes if ( gCharactersList[ bCharNumber ].fValid == FALSE ) return (FALSE); - pSoldier = MercPtrs[ gCharactersList[ bCharNumber ].usSolID ]; // valid soldier? Assert( pSoldier ); Assert( pSoldier->bActive ); - if ( CanEntireMovementGroupMercIsInMove( pSoldier, &bErrorNumber ) ) { return( TRUE ); @@ -14492,11 +14588,11 @@ void ChangeMapScreenMaskCursor( UINT16 usCursor ) if ( usCursor == CURSOR_NORMAL ) { - if ( !InItemStackPopup( ) ) - { - // cancel mouse restriction - FreeMouseCursor( FALSE ); - } + if ( !InItemStackPopup( ) ) + { + // cancel mouse restriction + FreeMouseCursor( FALSE ); + } } else { @@ -14516,7 +14612,7 @@ void CancelOrShortenPlottedPath( void ) GetMouseMapXY(&sMapX, &sMapY); // check if we are in aircraft mode - if( fShowAircraftFlag == TRUE ) + if( fShowAircraftFlag ) { // check for helicopter path being plotted if( !fPlotForHelicopter ) @@ -14530,10 +14626,26 @@ void CancelOrShortenPlottedPath( void ) return; } - // try to delete portion of path AFTER the current sector for the helicopter uiReturnValue = ClearPathAfterThisSectorForHelicopter( sMapX, sMapY ); } + else if ( fShowMilitia ) + { + // check for helicopter path being plotted + if ( !fPlotForMilitia ) + return; + + // if player can't redirect it + /*if ( CanHelicopterFly( ) == FALSE ) + { + // explain & ignore + ExplainWhySkyriderCantFly( ); + return; + }*/ + + // try to delete portion of path AFTER the current sector for the helicopter + uiReturnValue = ClearPathAfterThisSectorForMilitia( sMapX, sMapY ); + } else { // check for character path being plotted @@ -14888,9 +15000,8 @@ void CancelPathsOfAllSelectedCharacters() SOLDIERTYPE *pSoldier = NULL; BOOLEAN fSkyriderMsgShown = FALSE; - // cancel destination for the clicked and ALL other valid & selected characters with a route set - for( bCounter = 0; bCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; bCounter++ ) + for( bCounter = 0; bCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++bCounter ) { // if we've clicked on a selected valid character if( ( gCharactersList[ bCounter ].fValid == TRUE ) && IsEntryInSelectedListSet( bCounter ) ) @@ -14914,7 +15025,6 @@ void CancelPathsOfAllSelectedCharacters() continue; } - // cancel the entire path (also clears vehicles for any passengers selected, and handles reversing directions) if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) { @@ -14930,21 +15040,27 @@ void CancelPathsOfAllSelectedCharacters() } - -void ConvertMinTimeToETADayHourMinString( UINT32 uiTimeInMin, STR16 sString ) +void ConvertMinTimeToDayHourMinString( UINT32 uiTimeInMin, STR16 sString ) { UINT32 uiDay, uiHour, uiMin; - uiDay = ( uiTimeInMin / NUM_MIN_IN_DAY ); - uiHour = ( uiTimeInMin - ( uiDay * NUM_MIN_IN_DAY ) ) / NUM_MIN_IN_HOUR; - uiMin = uiTimeInMin - ( ( uiDay * NUM_MIN_IN_DAY ) + ( uiHour * NUM_MIN_IN_HOUR ) ); + uiDay = (uiTimeInMin / NUM_MIN_IN_DAY); + uiHour = (uiTimeInMin - (uiDay * NUM_MIN_IN_DAY)) / NUM_MIN_IN_HOUR; + uiMin = uiTimeInMin - ((uiDay * NUM_MIN_IN_DAY) + (uiHour * NUM_MIN_IN_HOUR)); // there ain't enough room to show both the day and ETA: and without ETA it's confused as the current time -// swprintf( sString, L"%s %s %d, %02d:%02d", pEtaString[ 0 ], pDayStrings[ 0 ], uiDay, uiHour, uiMin ); -// swprintf( sString, L"%s %d, %02d:%02d", pDayStrings[ 0 ], uiDay, uiHour, uiMin ); - swprintf( sString, L"%s %02d:%02d", pEtaString[ 0 ], uiHour, uiMin ); + // swprintf( sString, L"%s %s %d, %02d:%02d", pEtaString[ 0 ], pDayStrings[ 0 ], uiDay, uiHour, uiMin ); + // swprintf( sString, L"%s %d, %02d:%02d", pDayStrings[ 0 ], uiDay, uiHour, uiMin ); + swprintf( sString, L"%02d:%02d", uiHour, uiMin ); } +void ConvertMinTimeToETADayHourMinString( UINT32 uiTimeInMin, STR16 sString ) +{ + CHAR16 timestring[64]; + ConvertMinTimeToDayHourMinString( uiTimeInMin, timestring ); + + swprintf( sString, L"%s %s", pEtaString[0], timestring ); +} INT32 GetGroundTravelTimeOfCharacter( INT8 bCharNumber ) @@ -14966,6 +15082,17 @@ INT32 GetGroundTravelTimeOfCharacter( INT8 bCharNumber ) return( iTravelTime ); } +INT32 GetGroundTravelTimeOfMilitia( ) +{ + // get travel time for the last path segment (stored in pTempMilitiaPath) + INT32 iTravelTime = GetPathTravelTimeDuringPlotting( pTempMilitiaPath ); + + // add travel time for any prior path segments (stored in the selected character's mercpath, but waypoints aren't built) + iTravelTime += GetPathTravelTimeDuringPlotting( gMilitiaPath[gMilitiaGroupId].path ); + + return(iTravelTime); +} + INT16 CalcLocationValueForChar( INT32 iCounter ) @@ -15110,7 +15237,7 @@ BOOLEAN AnyMovableCharsInOrBetweenThisSector( INT16 sSectorX, INT16 sSectorY, IN BOOLEAN RequestGiveSkyriderNewDestination( void ) { // should we allow it? - if( CanHelicopterFly( ) == TRUE ) + if( CanHelicopterFly( ) ) { // if not warned already, and chopper empty, but mercs are in this sector if ( !gfSkyriderEmptyHelpGiven && @@ -15123,7 +15250,8 @@ BOOLEAN RequestGiveSkyriderNewDestination( void ) } // say Yo! - if(gGameSettings.fOptions[ TOPTION_SILENT_SKYRIDER ] == FALSE) SkyRiderTalk( SKYRIDER_SAYS_HI ); + if( !gGameSettings.fOptions[ TOPTION_SILENT_SKYRIDER ]) + SkyRiderTalk( SKYRIDER_SAYS_HI ); // start plotting helicopter movement fPlotForHelicopter = TRUE; @@ -15223,7 +15351,6 @@ void HandleNewDestConfirmation( INT16 sMapX, INT16 sMapY ) { UINT8 ubCurrentProgress; - // if moving the chopper itself, or moving a character aboard the chopper if( fPlotForHelicopter ) { @@ -15267,6 +15394,10 @@ void HandleNewDestConfirmation( INT16 sMapX, INT16 sMapY ) SkyRiderTalk( BELIEVED_ENEMY_SECTOR ); } } + else if ( fPlotForMilitia ) + { + // we could play a generic militia confirmation sound here, if we had such a thing... + } else { RandomAwakeSelectedMercConfirmsStrategicMove( ); @@ -15328,9 +15459,38 @@ void DestinationPlottingCompleted( void ) // clear previous paths for selected characters and helicopter ClearPreviousPaths(); - fPlotForHelicopter = FALSE; + fPlotForHelicopter = FALSE; bSelectedDestChar = - 1; giDestHighLine = -1; + + // Flugente: add militia from the starting sector to the group + if ( fPlotForMilitia ) + { + if ( gbWorldSectorZ <= 0 && gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) + { + GROUP* pGroup = GetGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); + + // If this group has size 0, we assume that we are starting a new path - so pick up militia. + // If it already has members, do not do that + if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM )//&& pGroup->ubGroupSize == 0 ) + { + /*SECTORINFO *pSector = &SectorInfo[SECTOR( pGroup->ubSectorX, pGroup->ubSectorY )]; + + pGroup->pEnemyGroup->ubNumAdmins = pSector->ubNumberOfCivsAtLevel[0]; + pGroup->pEnemyGroup->ubNumTroops = pSector->ubNumberOfCivsAtLevel[1]; + pGroup->pEnemyGroup->ubNumElites = pSector->ubNumberOfCivsAtLevel[2]; + pSector->ubNumberOfCivsAtLevel[0] = 0; + pSector->ubNumberOfCivsAtLevel[1] = 0; + pSector->ubNumberOfCivsAtLevel[2] = 0;*/ + + pGroup->ubGroupSize = pGroup->pEnemyGroup->ubNumAdmins + pGroup->pEnemyGroup->ubNumTroops + pGroup->pEnemyGroup->ubNumElites; + } + } + + MilitiaplotFinish(); + + fPlotForMilitia = FALSE; + } fMapPanelDirty = TRUE; @@ -15775,13 +15935,18 @@ void InitPreviousPaths( void ) INT32 iCounter = 0; // init character previous paths - for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) + for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter ) { gpCharacterPreviousMercPath[ iCounter ] = NULL; } // init helicopter previous path gpHelicopterPreviousMercPath = NULL; + + //for ( iCounter = 0; iCounter < MILITIA_PATROLS_MAX; ++iCounter ) + { + gpMilitiaPreviousMercPath = NULL; + } } @@ -15811,12 +15976,10 @@ void RestorePreviousPaths( void ) UINT8 ubGroupId = 0; BOOLEAN fPathChanged = FALSE; - // invalid if we're not plotting movement - Assert( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ); + Assert( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ); - - if ( fPlotForHelicopter == TRUE ) + if ( fPlotForHelicopter ) { ppMovePath = &( pVehicleList[ iHelicopterVehicleId ].pMercPath ); ubGroupId = pVehicleList[ iHelicopterVehicleId ].ubMovementGroup; @@ -15855,9 +16018,60 @@ void RestorePreviousPaths( void ) CopyPathToAllSelectedCharacters( *ppMovePath ); } } + else if ( fPlotForMilitia ) + { + //for ( iCounter = 0; iCounter < MILITIA_PATROLS_MAX; iCounter++ ) + { + // if selected + //if ( fSelectedListOfMercsForMapScreen[iCounter] == TRUE ) + if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) + { + //pSoldier = MercPtrs[gCharactersList[iCounter].usSolID]; + + //if ( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE ) + { + ppMovePath = &gMilitiaPath[gMilitiaGroupId].path; + ubGroupId = (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid; + } + + fPathChanged = FALSE; + + // if we have the previous path stored for the dest char + if ( gpMilitiaPreviousMercPath ) + { + gpMilitiaPreviousMercPath = MoveToBeginningOfPathList( gpMilitiaPreviousMercPath ); + + // clear current path + *ppMovePath = ClearStrategicPathList( *ppMovePath, ubGroupId ); + // replace it with the previous one + *ppMovePath = CopyPaths( gpMilitiaPreviousMercPath, *ppMovePath ); + // will need to rebuild waypoints + fPathChanged = TRUE; + } + else // no previous path stored + { + // if he has one now, wipe it out + if ( *ppMovePath ) + { + // wipe it out! + *ppMovePath = MoveToBeginningOfPathList( *ppMovePath ); + *ppMovePath = ClearStrategicPathList( *ppMovePath, ubGroupId ); + // will need to rebuild waypoints + fPathChanged = TRUE; + } + } + + if ( fPathChanged ) + { + // rebuild waypoints + RebuildWayPointsForGroupPath( *ppMovePath, ubGroupId ); + } + } + } + } else // character(s) plotting { - for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) + for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter ) { // if selected if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) @@ -15886,7 +16100,6 @@ void RestorePreviousPaths( void ) continue; } - fPathChanged = FALSE; // if we have the previous path stored for the dest char @@ -15914,7 +16127,6 @@ void RestorePreviousPaths( void ) } } - if ( fPathChanged ) { // rebuild waypoints @@ -15930,14 +16142,17 @@ void ClearPreviousPaths( void ) { INT32 iCounter = 0; - for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; iCounter++ ) + for( iCounter = 0; iCounter < giMAXIMUM_NUMBER_OF_PLAYER_SLOTS; ++iCounter ) { if( fSelectedListOfMercsForMapScreen[ iCounter ] == TRUE ) { gpCharacterPreviousMercPath[ iCounter ] = ClearStrategicPathList( gpCharacterPreviousMercPath[ iCounter ], 0 ); } } + gpHelicopterPreviousMercPath = ClearStrategicPathList( gpHelicopterPreviousMercPath, 0 ); + + gpMilitiaPreviousMercPath = ClearStrategicPathList( gpMilitiaPreviousMercPath, 0 ); } @@ -16009,7 +16224,6 @@ void RestoreMapSectorCursor( INT16 sMapX, INT16 sMapY ) { INT16 sScreenX, sScreenY; - Assert( ( sMapX >= 1 ) && ( sMapX <= 16 ) ); Assert( ( sMapY >= 1 ) && ( sMapY <= 16 ) ); @@ -16029,12 +16243,11 @@ void RequestToggleMercInventoryPanel( void ) return; } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } - - + if ( !CanToggleSelectedCharInventory() ) { return; @@ -16083,7 +16296,7 @@ void RequestContractMenu( void ) return; } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -16146,7 +16359,7 @@ void ChangeCharacterListSortMethod( INT32 iValue ) return; } - if( ( bSelectedDestChar != -1 ) || ( fPlotForHelicopter == TRUE ) ) + if ( (bSelectedDestChar != -1) || fPlotForHelicopter || fPlotForMilitia ) { AbortMovementPlottingMode( ); } @@ -16180,6 +16393,7 @@ void MapscreenMarkButtonsDirty() } } } + // HEADROCK HAM 3.6: Get a total of all merc salaries. Used for the new Daily Expenses display. INT32 GetTotalContractExpenses ( void ) { @@ -16245,3 +16459,308 @@ void HandleWhenPlayerHasNoMercsAndNoLaptop() } } #endif + + + + +// Flugente: militia movement +BOOLEAN RequestGiveMilitiaNewDestination( void ) +{ + // are we even allowed to give militia orders in this sector? + if ( !CanGiveStrategicMilitiaMoveOrder( sSelMapX, sSelMapY ) ) + { + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, szMilitiaStrategicMovementText[0] ); + + return FALSE; + } + + // if there is already a travelling group in this sector, pick them up instead + /*UINT8 groupid = 0; + BOOLEAN fGroupAlreadyExists = FALSE; + if ( GetMilitiaGroupInSector( sSelMapX, sSelMapY, groupid ) ) + { + INT16 internalslot = GetMilitiaPathSlot( groupid ); + + if ( internalslot > -1 ) + { + fGroupAlreadyExists = TRUE; + + gMilitiaGroupId = internalslot; + + // yes, we intentionally use a different sector number here + gMilitiaPlotStartSector = (INT16)(sSelMapX + sSelMapY*(MAP_WORLD_X)); + } + }*/ + + // we can actually fail here if there aren't any slots left + if ( !MilitiaPlotStart( ) ) + { + return FALSE; + } + + // start plotting + fPlotForMilitia = TRUE; + + CreateMilitiaGroupBox(); + + // change cursor to the helicopter + SetUpCursorForStrategicMap( ); + + // remember the helicopter's current path so we can restore it if need be + gpMilitiaPreviousMercPath = CopyPaths( gMilitiaPath[gMilitiaGroupId].path, gpMilitiaPreviousMercPath ); + + return TRUE; +} + +void SetUpMilitiaForMovement( ) +{ + // nothing to do atm +} + +// upon starting a game/loading from an old version, set up the data +void MilitiaPlotInit() +{ + static BOOLEAN fCleanOnStart = TRUE; + + if ( fCleanOnStart ) + { + // start new path list + gpMilitiaPreviousMercPath = (PathStPtr)MemAlloc( sizeof(PathSt) ); + memset( gpMilitiaPreviousMercPath, 0, sizeof(PathSt) ); + + gpMilitiaPreviousMercPath->fSpeed = NORMAL_MVT; + gpMilitiaPreviousMercPath->uiSectorId = 0; + gpMilitiaPreviousMercPath->uiEta = GetWorldTotalMin( ); + gpMilitiaPreviousMercPath->pNext = NULL; + gpMilitiaPreviousMercPath->pPrev = NULL; + + for ( int i = 0; i < MILITIA_PATROLS_MAX; ++i ) + { + gMilitiaPath[i].path = (PathStPtr)MemAlloc( sizeof(PathSt) ); + memset( gMilitiaPath[i].path, 0, sizeof(PathSt) ); + + gMilitiaPath[i].path->fSpeed = NORMAL_MVT; + gMilitiaPath[i].path->uiSectorId = 0; + gMilitiaPath[i].path->uiEta = GetWorldTotalMin( ); + gMilitiaPath[i].path->pNext = NULL; + gMilitiaPath[i].path->pPrev = NULL; + + gMilitiaPath[i].sGroupid = -1; + } + + fCleanOnStart = FALSE; + + SetUpMilitiaForMovement( ); + } +} + +// when starting to plot, set up things +BOOLEAN MilitiaPlotStart( ) +{ + // The number of militia groups is limited. Loop over all militia group, eliminate emtpy ones, and then use the first one. If none exists, we have to abort plotting for now + BOOLEAN found = FALSE; + for ( int groupid = 0; groupid < MILITIA_PATROLS_MAX; ++groupid ) + { + if ( gMilitiaPath[groupid].sGroupid > -1 ) + { + GROUP* pGroup = GetGroup( (UINT8)gMilitiaPath[groupid].sGroupid ); + + // if this group exists, is indeed militia but has no members, erase it and its path + if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubGroupSize == 0 ) + { + gMilitiaPath[groupid].path = ClearStrategicPathList( gMilitiaPath[groupid].path, groupid ); + + RemovePGroup( pGroup ); + + gMilitiaPath[groupid].sGroupid = -1; + } + } + + if ( !found && gMilitiaPath[groupid].sGroupid < 0 ) + { + found = TRUE; + gMilitiaGroupId = groupid; + + gMilitiaPath[groupid].path = (PathStPtr)MemAlloc( sizeof(PathSt) ); + memset( gMilitiaPath[groupid].path, 0, sizeof(PathSt) ); + + gMilitiaPath[groupid].path->fSpeed = NORMAL_MVT; + gMilitiaPath[groupid].path->uiSectorId = 0; + gMilitiaPath[groupid].path->uiEta = GetWorldTotalMin( ); + gMilitiaPath[groupid].path->pNext = NULL; + gMilitiaPath[groupid].path->pPrev = NULL; + } + } + + // no free slot - abort + if ( !found ) + return FALSE; + + SECTORINFO *pSector = &SectorInfo[SECTOR( sSelMapX, sSelMapY )]; + + if ( !pSector ) + return FALSE; + + // when we start plotting, the group is still empty - we add militia later + GROUP* pGroup = CreateNewMilitiaGroupDepartingFromSector( SECTOR( sSelMapX, sSelMapY ), pSector->ubNumberOfCivsAtLevel[0], pSector->ubNumberOfCivsAtLevel[1], pSector->ubNumberOfCivsAtLevel[2] ); + + pSector->ubNumberOfCivsAtLevel[0] = 0; + pSector->ubNumberOfCivsAtLevel[1] = 0; + pSector->ubNumberOfCivsAtLevel[2] = 0; + + gMilitiaPath[gMilitiaGroupId].sGroupid = pGroup->ubGroupID; + gNewMilitiaGroupId = pGroup->ubGroupID; + + // yes, we intentionally use a different sector number here + gMilitiaPlotStartSector = (INT16)(sSelMapX + sSelMapY*(MAP_WORLD_X)); + + gMilitiaPath[gMilitiaGroupId].path->uiSectorId = gMilitiaPlotStartSector; + + return TRUE; +} + +// when finished plotting, set up other things +void MilitiaplotFinish() +{ + gMilitiaPlotStartSector = 0; + + // destroy militia group if empty and not moving + if ( gMilitiaPath[gMilitiaGroupId].sGroupid > -1 ) + { + GROUP* pGroup = GetGroup( (UINT8)gMilitiaPath[gMilitiaGroupId].sGroupid ); + + // if the group has no members, or if it is not given any movement orders, destroy it + if ( pGroup && pGroup->usGroupTeam == MILITIA_TEAM + && (!pGroup->ubGroupSize || (pGroup->ubNextX == pGroup->ubSectorX && pGroup->ubNextY == pGroup->ubSectorY) || (pGroup->ubNextX == 0 && pGroup->ubNextY == 0) ) ) + { + StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, GREEN_MILITIA, pGroup->pEnemyGroup->ubNumAdmins ); + StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, REGULAR_MILITIA, pGroup->pEnemyGroup->ubNumTroops ); + StrategicAddMilitiaToSector( pGroup->ubSectorX, pGroup->ubSectorY, ELITE_MILITIA, pGroup->pEnemyGroup->ubNumElites ); + + RemovePGroup( pGroup ); + + gMilitiaPath[gMilitiaGroupId].sGroupid = -1; + + gMilitiaGroupId = 0; + gNewMilitiaGroupId = 0; + } + } +} + +// if this group is a militia travel group, return its slot, othewise return -1 +INT16 GetMilitiaPathSlot( UINT8 uGroupId ) +{ + for ( INT32 iCounter = 0; iCounter < MILITIA_PATROLS_MAX; ++iCounter ) + { + if ( gMilitiaPath[iCounter].sGroupid == uGroupId ) + return iCounter; + } + + return -1; +} + +void DeleteAllMilitiaPaths() +{ + // empty out the vehicle list + if ( gMilitiaPath ) + { + for ( INT32 iCounter = 0; iCounter < MILITIA_PATROLS_MAX; ++iCounter ) + { + if ( gMilitiaPath[iCounter].path ) + { + // toast the path + gMilitiaPath[iCounter].path = ClearStrategicPathList( gMilitiaPath[iCounter].path, 0 ); + + MemFree( gMilitiaPath[iCounter].path ); + } + + gMilitiaPath[iCounter].sGroupid = -1; + } + } +} + +// if a militia group is in this sector, return TRUE, group id will be stored in arId +BOOLEAN GetMilitiaGroupInSector( INT16 sMapX, INT16 sMapY, UINT8& arId ) +{ + GROUP *pGroup = gpGroupList; + while ( pGroup ) + { + if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubSectorX == sMapX && pGroup->ubSectorY == sMapY ) + { + arId = pGroup->ubGroupID; + return TRUE; + } + pGroup = pGroup->next; + } + + return FALSE; +} + +// are we allowed to give militia in this sector a strategic move order? +BOOLEAN CanGiveStrategicMilitiaMoveOrder( INT16 sMapX, INT16 sMapY ) +{ + // not allowed if setting says so + if ( !gGameExternalOptions.fMilitiaStrategicCommand ) + return FALSE; + + // if we posess and staff the militia HQ, we can command militia everywhere + if ( MercStaffsMilitaryHQ( ) ) + return TRUE; + + // town this sector is a part of + UINT8 townid = GetTownIdForSector( sMapX, sMapY ); + + // we require mercs to 'give' the orders to militia. + // For simplicity, we require the mercs simply to not be in a coma, asleep is okay (otherwsie we have to wake them up, give the order, set them asleep again - tedious!). + // Mercs can give these orders if one of these is true + // 1. they are in the same sector + // 2. they are in the same town (otherwise we'd have to do tedious town-internal travel) + // 3. they are a radio operator in an adjacent sector + // 4. they are a radio operator in a sector adjacent to the militia's town + // 5. they are a radio operator in a town adjacent to the militia's sector + SOLDIERTYPE *pSoldier = NULL; + UINT32 uiCnt = 0; + UINT32 firstid = gTacticalStatus.Team[OUR_TEAM].bFirstID; + UINT32 lastid = gTacticalStatus.Team[OUR_TEAM].bLastID; + for ( uiCnt = firstid, pSoldier = MercPtrs[uiCnt]; uiCnt <= lastid; ++uiCnt, ++pSoldier ) + { + if ( pSoldier && pSoldier->bActive && pSoldier->stats.bLife >= OKLIFE ) + { + BOOLEAN fRadioOperator = pSoldier->CanUseRadio( FALSE ); + + INT16 sectordist = abs( sMapX - pSoldier->sSectorX ) + abs( sMapY - pSoldier->sSectorY ); + + // 1. + 3. + if ( fRadioOperator >= sectordist ) + return TRUE; + + UINT8 soldiertownid = GetTownIdForSector( pSoldier->sSectorX, pSoldier->sSectorY ); + + // 2. + if ( townid != BLANK_SECTOR && townid == soldiertownid ) + return TRUE; + + // 4. + if ( fRadioOperator && soldiertownid == BLANK_SECTOR && townid != BLANK_SECTOR ) + { + // check whether adjacent sectors belong to the town we search for + if ( GetTownIdForSector( min( pSoldier->sSectorX + 1, MAP_WORLD_X - 2), pSoldier->sSectorY ) == townid ) return TRUE; + if ( GetTownIdForSector( max( pSoldier->sSectorX - 1, 1 ), pSoldier->sSectorY ) == townid ) return TRUE; + if ( GetTownIdForSector( pSoldier->sSectorX, min( pSoldier->sSectorY + 1, MAP_WORLD_Y - 2 ) ) == townid ) return TRUE; + if ( GetTownIdForSector( pSoldier->sSectorX, max( pSoldier->sSectorY - 1, 1 ) ) == townid ) return TRUE; + } + + // 5. + if ( fRadioOperator && townid == BLANK_SECTOR && soldiertownid != BLANK_SECTOR ) + { + // check whether adjacent sectors belong to the town we search for + if ( GetTownIdForSector( min( sMapX + 1, MAP_WORLD_X - 2 ), sMapY ) == townid ) return TRUE; + if ( GetTownIdForSector( max( sMapX - 1, 1 ), sMapY ) == townid ) return TRUE; + if ( GetTownIdForSector( sMapX, min( sMapY + 1, MAP_WORLD_Y - 2 ) ) == townid ) return TRUE; + if ( GetTownIdForSector( sMapX, max( sMapY - 1, 1 ) ) == townid ) return TRUE; + } + } + } + + return FALSE; +} diff --git a/Strategic/mapscreen.h b/Strategic/mapscreen.h index d0c666564..2f59d0849 100644 --- a/Strategic/mapscreen.h +++ b/Strategic/mapscreen.h @@ -119,4 +119,46 @@ enum NUM_MANUAL_MOBILE_STATES, }; +// Flugente: militia movement +extern BOOLEAN fPlotForMilitia; +extern UINT32 gMilitiaPlotStartSector; + +BOOLEAN RequestGiveMilitiaNewDestination( void ); + +void SetUpMilitiaForMovement(); + +INT32 GetGroundTravelTimeOfMilitia( ); + +typedef struct +{ + INT16 sGroupid; // group ids are normally UINT8 - we use -1 to indicate that it hasn't been used + PathStPtr path; // the path of a militia group that travels +} MILITIA_PATH; + +#define MILITIA_PATROLS_MAX 30 + +extern MILITIA_PATH gMilitiaPath[MILITIA_PATROLS_MAX]; + +// upon starting a game/loading from an old version, set up the data +void MilitiaPlotInit(); + +// when starting to plot, set up things +BOOLEAN MilitiaPlotStart(); + +// when finished plotting, set up other things +void MilitiaplotFinish(); + +// if this group is a militia travel group, return its slot, othewise return -1 +INT16 GetMilitiaPathSlot(UINT8 uGroupId); + +void DeleteAllMilitiaPaths(); + +// if a militia group is in this sector, return TRUE, group id will be stored in arId +BOOLEAN GetMilitiaGroupInSector( INT16 sMapX, INT16 sMapY, UINT8& arId ); + +BOOLEAN CanGiveStrategicMilitiaMoveOrder( INT16 sMapX, INT16 sMapY ); + +void ConvertMinTimeToDayHourMinString( UINT32 uiTimeInMin, STR16 sString ); +void ConvertMinTimeToETADayHourMinString( UINT32 uiTimeInMin, STR16 sString ); + #endif \ No newline at end of file diff --git a/Strategic/strategic.cpp b/Strategic/strategic.cpp index 41870e134..fcc5a16e2 100644 --- a/Strategic/strategic.cpp +++ b/Strategic/strategic.cpp @@ -19,7 +19,8 @@ #include "militiasquads.h" // added by Flugente #include "Game Event Hook.h" // added by Flugente #include "message.h" // added by Flugente - #include "Text.h" // added by Flugente + #include "Text.h" // added by Flugente + #include "Queen Command.h" // added by Flugente #endif #ifdef JA2UB @@ -171,11 +172,9 @@ BOOLEAN SetMilitiaMovementOrder(INT16 sX, INT16 sY, INT8 sZ, UINT32 dir) // militia can only move on the surface if ( sZ ) return FALSE; - - SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sX, sY ) ] ); - + // militia needs to be here... - if ( !CountMilitia(pSectorInfo) ) + if ( !NumNonPlayerTeamMembersInSector( sX, sY, MILITIA_TEAM ) ) return FALSE; // in order to give movement orders, we need a merc to staff a military headquarter diff --git a/Strategic/strategicmap.cpp b/Strategic/strategicmap.cpp index 0d67aa5fe..b718cc387 100644 --- a/Strategic/strategicmap.cpp +++ b/Strategic/strategicmap.cpp @@ -1857,24 +1857,6 @@ UINT8 GetTownSectorSize( INT8 bTownId ) return( ubSectorSize ); } -UINT8 GetMilitiaCountAtLevelAnywhereInTown( UINT8 ubTownValue, UINT8 ubLevelValue ) -{ - INT32 iCounter = 0; - UINT8 ubCount =0; - - while( pTownNamesList[ iCounter ] != 0 ) - { - if( StrategicMap[ pTownLocationsList[ iCounter ] ].bNameId == ubTownValue ) - { - // match. Add the number of civs at this level - ubCount += SectorInfo[ STRATEGIC_INDEX_TO_SECTOR_INFO( pTownLocationsList[ iCounter ] ) ].ubNumberOfCivsAtLevel[ ubLevelValue ]; - } - - iCounter++; - } - return( ubCount ); -} - // return number of sectors under player control for this town UINT8 GetTownSectorsUnderControl( INT8 bTownId ) @@ -1882,14 +1864,13 @@ UINT8 GetTownSectorsUnderControl( INT8 bTownId ) INT8 ubSectorsControlled = 0; UINT16 usSector = 0; - for ( INT32 iCounterA = 0; iCounterA < (INT32)(MAP_WORLD_X - 1); iCounterA++ ) + for ( INT32 iCounterA = 0; iCounterA < (INT32)(MAP_WORLD_X - 1); ++iCounterA ) { - for ( INT32 iCounterB = 0; iCounterB < (INT32)(MAP_WORLD_Y - 1); iCounterB++ ) + for ( INT32 iCounterB = 0; iCounterB < (INT32)(MAP_WORLD_Y - 1); ++iCounterB ) { usSector = (UINT16)CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB ); - if( ( StrategicMap[ usSector ].bNameId == bTownId ) && - ( StrategicMap[ usSector ].fEnemyControlled == FALSE ) && + if( ( StrategicMap[ usSector ].bNameId == bTownId ) && !StrategicMap[ usSector ].fEnemyControlled && (NumNonPlayerTeamMembersInSector( (INT16)iCounterA, (INT16)iCounterB, ENEMY_TEAM ) == 0) ) { ++ubSectorsControlled; @@ -1902,14 +1883,13 @@ UINT8 GetTownSectorsUnderControl( INT8 bTownId ) void InitializeSAMSites( void ) { - UINT32 cnt; // move the landing zone over to Omerta // HEADROCK HAM 3.5: Externalized coordinates gsMercArriveSectorX = gGameExternalOptions.ubDefaultArrivalSectorX; gsMercArriveSectorY = gGameExternalOptions.ubDefaultArrivalSectorY; // all SAM sites start game in perfect working condition - for ( cnt = 0; cnt < NUMBER_OF_SAMS; cnt++ ) + for ( UINT32 cnt = 0; cnt < NUMBER_OF_SAMS; ++cnt ) { StrategicMap[ gpSamSectorX[cnt] + ( MAP_WORLD_X * gpSamSectorY[cnt] ) ].bSAMCondition = 100; }; @@ -1927,8 +1907,6 @@ void GetShortSectorString( INT16 sMapX,INT16 sMapY, STR16 sString ) { // OK, build string id like J11 swprintf( sString, L"%S%S",pVertStrings[ sMapY ], pHortStrings[ sMapX ] ); - - return; } @@ -2140,7 +2118,7 @@ BOOLEAN SetCurrentWorldSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ ) } } - for (int i=0; ibActive ) { @@ -2791,7 +2769,7 @@ void HandleQuestCodeOnSectorEntry( INT16 sNewSectorX, INT16 sNewSectorY, INT8 bN } } - if ( (gubQuest[ QUEST_KINGPIN_MONEY ] == QUESTINPROGRESS) && CheckFact( FACT_KINGPIN_CAN_SEND_ASSASSINS, 0 ) && (GetTownIdForSector( sNewSectorX, sNewSectorY ) != BLANK_SECTOR) && Random( 10 + GetNumberOfMilitiaInSector( sNewSectorX, sNewSectorY, bNewSectorZ ) ) < 3 ) + if ( (gubQuest[QUEST_KINGPIN_MONEY] == QUESTINPROGRESS) && CheckFact( FACT_KINGPIN_CAN_SEND_ASSASSINS, 0 ) && (GetTownIdForSector( sNewSectorX, sNewSectorY ) != BLANK_SECTOR) && !bNewSectorZ && Random( 10 + NumNonPlayerTeamMembersInSector( sNewSectorX, sNewSectorY, MILITIA_TEAM ) ) < 3 ) { DecideOnAssassin(); } @@ -2998,8 +2976,7 @@ BOOLEAN EnterSector( INT16 sSectorX, INT16 sSectorY , INT8 bSectorZ ) { SetSectorFlag( sSectorX, sSectorY, bSectorZ, SF_ALREADY_VISITED ); } - - + GetMapFileName( sSectorX, sSectorY, bSectorZ, bFilename, TRUE, TRUE ); //Load the placeholder map if the real map doesn't exist. @@ -3086,8 +3063,7 @@ BOOLEAN EnterSector( INT16 sSectorX, INT16 sSectorY , INT8 bSectorZ ) //Save to tempfile SaveWorldItemsToTempItemFile( sSectorX, sSectorY, (INT8)bSectorZ, guiNumWorldItems, gWorldItems ); - - + return TRUE; //because the map was loaded. } @@ -3124,7 +3100,7 @@ void UpdateMercsInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) //if( !(gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) ) { - for ( cnt = 0, pSoldier = MercPtrs[ cnt ]; cnt < MAX_NUM_SOLDIERS; cnt++, pSoldier++) + for ( cnt = 0, pSoldier = MercPtrs[ cnt ]; cnt < MAX_NUM_SOLDIERS; ++cnt, ++pSoldier) { if ( gfRestoringEnemySoldiersFromTempFile && cnt >= gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID && @@ -3198,9 +3174,7 @@ void UpdateMercsInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) // Do action HandleNPCDoAction( 0, NPC_ACTION_GRANT_EXPERIENCE_3, 0 ); - } - } } } @@ -3219,7 +3193,6 @@ void UpdateMercsInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) // Set to false fUsingEdgePointsForStrategicEntry = FALSE; } - } void UpdateMercInSector( SOLDIERTYPE *pSoldier, INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) @@ -3809,7 +3782,6 @@ UINT8 SetInsertionDataFromAdjacentMoveDirection( SOLDIERTYPE *pSoldier, UINT8 ub UINT8 ubDirection; EXITGRID ExitGrid; - // Set insertion code switch( ubTacticalDirection ) { @@ -3853,24 +3825,20 @@ UINT8 SetInsertionDataFromAdjacentMoveDirection( SOLDIERTYPE *pSoldier, UINT8 ub } return( ubDirection ); - } UINT8 GetInsertionDataFromAdjacentMoveDirection( UINT8 ubTacticalDirection, INT32 sAdditionalData )//dnl ch56 151009 { UINT8 ubDirection; - - + // Set insertion code switch( ubTacticalDirection ) { // OK, we are using an exit grid - set insertion values... case 255: - ubDirection = 255; break; - case NORTH: ubDirection = NORTH_STRATEGIC_MOVE; break; @@ -3893,24 +3861,20 @@ UINT8 GetInsertionDataFromAdjacentMoveDirection( UINT8 ubTacticalDirection, INT3 } return( ubDirection ); - } UINT8 GetStrategicInsertionDataFromAdjacentMoveDirection( UINT8 ubTacticalDirection, INT32 sAdditionalData )//dnl ch56 151009 { UINT8 ubDirection; - // Set insertion code switch( ubTacticalDirection ) { // OK, we are using an exit grid - set insertion values... case 255: - ubDirection = 255; break; - case NORTH: ubDirection = INSERTION_CODE_SOUTH; break; @@ -3925,15 +3889,14 @@ UINT8 GetStrategicInsertionDataFromAdjacentMoveDirection( UINT8 ubTacticalDirect break; default: // Wrong direction given! - #ifdef JA2BETAVERSION - DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Improper insertion direction %d given to SetInsertionDataFromAdjacentMoveDirection", ubTacticalDirection ) ); - ScreenMsg( FONT_RED, MSG_ERROR, L"Improper insertion direction %d given to GetStrategicInsertionDataFromAdjacentMoveDirection", ubTacticalDirection ); - #endif +#ifdef JA2BETAVERSION + DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Improper insertion direction %d given to SetInsertionDataFromAdjacentMoveDirection", ubTacticalDirection ) ); + ScreenMsg( FONT_RED, MSG_ERROR, L"Improper insertion direction %d given to GetStrategicInsertionDataFromAdjacentMoveDirection", ubTacticalDirection ); +#endif ubDirection = EAST_STRATEGIC_MOVE; } return( ubDirection ); - } @@ -4177,8 +4140,7 @@ BEGINNING_LOOP: } curr = curr->next; } - - + // OK, setup TacticalOverhead polling system that will notify us once everybody // has made it to our destination. if ( ubTacticalDirection != 255 ) @@ -4202,7 +4164,6 @@ void HandleSoldierLeavingSectorByThemSelf( SOLDIERTYPE *pSoldier ) { // soldier leaving thier squad behind, will rejoin later // if soldier in a squad, set the fact they want to return here - UINT8 ubGroupId; if( pSoldier->bAssignment < ON_DUTY ) { @@ -4233,11 +4194,9 @@ void HandleSoldierLeavingSectorByThemSelf( SOLDIERTYPE *pSoldier ) if( pSoldier->ubGroupID == 0 ) { // create independant group - ubGroupId = CreateNewPlayerGroupDepartingFromSector( ( UINT8 )pSoldier->sSectorX, ( UINT8 )pSoldier->sSectorY ); + UINT8 ubGroupId = CreateNewPlayerGroupDepartingFromSector( (UINT8)pSoldier->sSectorX, (UINT8)pSoldier->sSectorY ); AddPlayerToGroup( ubGroupId , pSoldier ); } - - return; } void AllMercsWalkedToExitGrid() @@ -4826,7 +4785,7 @@ BOOLEAN OKForSectorExit( INT8 bExitDirection, INT32 usAdditionalData, UINT32 *pu cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; // look for all mercs on the same team, - for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++) + for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ++cnt, ++pSoldier) { // If we are controllable //if ( OK_CONTROLLABLE_MERC( pSoldier) && pSoldier->bAssignment == CurrentSquad( ) ) @@ -4990,12 +4949,10 @@ BOOLEAN OKForSectorExit( INT8 bExitDirection, INT32 usAdditionalData, UINT32 *pu void SetupNewStrategicGame( ) { - INT16 sSectorX, sSectorY; - // Set all sectors as enemy controlled - for ( sSectorX = 0; sSectorX < MAP_WORLD_X; sSectorX++ ) + for ( INT16 sSectorX = 0; sSectorX < MAP_WORLD_X; ++sSectorX ) { - for ( sSectorY = 0; sSectorY < MAP_WORLD_Y; sSectorY++ ) + for ( INT16 sSectorY = 0; sSectorY < MAP_WORLD_Y; ++sSectorY ) { StrategicMap[ CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].fEnemyControlled = TRUE; } @@ -5041,8 +4998,7 @@ void SetupNewStrategicGame( ) // Daily checks for E-mail from Enrico AddEveryDayStrategicEvent( EVENT_ENRICO_MAIL, ENRICO_MAIL_TIME , 0 ); #endif - - + // if ( gGameOptions.fAirStrikes ) // { // //Daily check for an air raid @@ -5055,10 +5011,7 @@ void SetupNewStrategicGame( ) //Clear any possible battle locator gfBlitBattleSectorLocator = FALSE; - - - - + StrategicTurnsNewGame( ); } @@ -5066,9 +5019,6 @@ void SetupNewStrategicGame( ) // a -1 will be returned upon failure INT8 GetSAMIdFromSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) { - INT8 bCounter = 0; - INT16 sSectorValue = 0; - // check if valid sector if( bSectorZ != 0 ) { @@ -5076,10 +5026,10 @@ INT8 GetSAMIdFromSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) } // get the sector value - sSectorValue = SECTOR( sSectorX, sSectorY ); + INT16 sSectorValue = SECTOR( sSectorX, sSectorY ); // run through list of sam sites - for( bCounter = 0; bCounter < NUMBER_OF_SAMS; bCounter++ ) + for ( INT8 bCounter = 0; bCounter < NUMBER_OF_SAMS; ++bCounter ) { if( pSamList[ bCounter ] == sSectorValue ) { @@ -5087,7 +5037,6 @@ INT8 GetSAMIdFromSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ ) } } - return( -1 ); } @@ -5131,14 +5080,14 @@ BOOLEAN CanGoToTacticalInSector( INT16 sX, INT16 sY, UINT8 ubZ ) INT32 GetNumberOfSAMSitesUnderPlayerControl( void ) { - INT32 iNumber = 0, iCounter = 0; + INT32 iNumber = 0; // if the sam site is under player control, up the number - for( iCounter = 0; iCounter < NUMBER_OF_SAMS; iCounter++ ) + for ( INT32 iCounter = 0; iCounter < NUMBER_OF_SAMS; ++iCounter ) { if( StrategicMap[ SECTOR_INFO_TO_STRATEGIC_INDEX( pSamList[ iCounter ] ) ].fEnemyControlled == FALSE ) { - iNumber++; + ++iNumber; } } @@ -5148,8 +5097,7 @@ INT32 GetNumberOfSAMSitesUnderPlayerControl( void ) INT32 SAMSitesUnderPlayerControl( INT16 sX, INT16 sY ) { BOOLEAN fSamSiteUnderControl = FALSE; - - + // is this sector a SAM sector? if( IsThisSectorASAMSector( sX, sY, 0 ) == TRUE ) { @@ -5167,15 +5115,13 @@ INT32 SAMSitesUnderPlayerControl( INT16 sX, INT16 sY ) void UpdateAirspaceControl( void ) { - INT32 iCounterA = 0, iCounterB = 0; UINT8 ubControllingSAM; StrategicMapElement *pSAMStrategicMap = NULL; BOOLEAN fEnemyControlsAir; - - for( iCounterA = 1; iCounterA < ( INT32 )( MAP_WORLD_X - 1 ); iCounterA++ ) + for ( INT32 iCounterA = 1; iCounterA < (INT32)(MAP_WORLD_X - 1); ++iCounterA ) { - for( iCounterB = 1; iCounterB < ( INT32 )( MAP_WORLD_Y - 1 ); iCounterB++ ) + for ( INT32 iCounterB = 1; iCounterB < (INT32)(MAP_WORLD_Y - 1); ++iCounterB ) { // IMPORTANT: B and A are reverse here, since the table is stored transposed ubControllingSAM = ubSAMControlledSectors[ iCounterB ][ iCounterA ]; @@ -5211,7 +5157,6 @@ void UpdateAirspaceControl( void ) } } - // check if currently selected arrival sector still has secure airspace // if it's not enemy air controlled @@ -5232,9 +5177,9 @@ void UpdateAirspaceControl( void ) } else { - for (UINT8 ubSectorX = 1; ubSectorX <= 16; ubSectorX++) + for (UINT8 ubSectorX = 1; ubSectorX <= 16; ++ubSectorX) { - for (UINT8 ubSectorY = 1; ubSectorY <=16; ubSectorY++) + for (UINT8 ubSectorY = 1; ubSectorY <=16; ++ubSectorY) { if ( StrategicMap[ CALCULATE_STRATEGIC_INDEX( ubSectorX, ubSectorY ) ].fEnemyAirControlled == FALSE && !sBadSectorsList[ ubSectorX ][ ubSectorY ] ) { @@ -5264,8 +5209,7 @@ void UpdateAirspaceControl( void ) // update destination column for any mercs in transit fTeamPanelDirty = TRUE; } - - + // ARM: airspace control now affects refueling site availability, so update that too with every change! UpdateRefuelSiteAvailability( ); } @@ -7574,3 +7518,20 @@ BOOLEAN MoveEnemyFromGridNoToRoofGridNo( UINT32 sSourceGridNo, UINT32 sDestGridN return( FALSE ); } #endif + +// Flugente: militia movement: can we order militia reinforcements from( sSrcMapX, sSrcMapY ) to( sMapX, sMapY ) ? +BOOLEAN CanRequestMilitiaReinforcements( INT16 sMapX, INT16 sMapY, INT16 sSrcMapX, INT16 sSrcMapY ) +{ + if ( !gGameExternalOptions.gfAllowReinforcements ) + return FALSE; + + // we can request reinforcements only inside towns + if ( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR && GetTownIdForSector( sMapX, sMapY ) != GetTownIdForSector( sSrcMapX, sSrcMapY ) ) + return FALSE; + + // not possible of nobody is there + if ( !NumNonPlayerTeamMembersInSector( sSrcMapX, sSrcMapY, MILITIA_TEAM ) ) + return FALSE; + + return TRUE; +} diff --git a/Strategic/strategicmap.h b/Strategic/strategicmap.h index 5f9c140c6..46646a62d 100644 --- a/Strategic/strategicmap.h +++ b/Strategic/strategicmap.h @@ -150,7 +150,6 @@ void AllMercsHaveWalkedOffSector( ); void AdjustSoldierPathToGoOffEdge( SOLDIERTYPE *pSoldier, INT32 sEndGridNo, UINT8 ubTacticalDirection ); void AllMercsWalkedToExitGrid(); -UINT8 GetMilitiaCountAtLevelAnywhereInTown( UINT8 ubTownValue, UINT8 ubLevelValue ); void PrepareLoadedSector(); @@ -213,4 +212,7 @@ void HandleSectorSpecificModificatioToMap( INT16 sMapX, INT16 sMapY, INT8 bMapZ, void HandleEmailBeingSentWhenEnteringSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ, BOOLEAN fLaptopJustGotFixed ); #endif -#endif +// Flugente: militia movement: can we order militia reinforcements from( sSrcMapX, sSrcMapY ) to( sMapX, sMapY ) ? +BOOLEAN CanRequestMilitiaReinforcements( INT16 sMapX, INT16 sMapY, INT16 sSrcMapX, INT16 sSrcMapY ); + +#endif \ No newline at end of file diff --git a/Tactical/Dialogue Control.cpp b/Tactical/Dialogue Control.cpp index 20e506742..0875af606 100644 --- a/Tactical/Dialogue Control.cpp +++ b/Tactical/Dialogue Control.cpp @@ -1074,7 +1074,14 @@ void HandleDialogue( ) if( QItem->uiSpecialEventFlag & DIALOGUE_SPECIAL_EVENT_TRIGGERPREBATTLEINTERFACE ) { UnLockPauseState(); + + // Flugente: what hideous idiocy is this? We cast a UINT32 as GROUP*? This is likely to return garbage. + // Why the hell not use the id instead? InitPreBattleInterface( (GROUP*)QItem->uiSpecialEventData, TRUE ); + + /*GROUP* pGroup = GetGroup( (UINT8)QItem->uiSpecialEventData ); + if ( pGroup ) + InitPreBattleInterface( pGroup, TRUE );*/ } if( QItem->uiSpecialEventFlag & DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX ) { diff --git a/Tactical/Inventory Choosing.cpp b/Tactical/Inventory Choosing.cpp index 3c014c610..e7262e3d5 100644 --- a/Tactical/Inventory Choosing.cpp +++ b/Tactical/Inventory Choosing.cpp @@ -4010,6 +4010,9 @@ void MoveOneMilitiaEquipmentSet(INT16 sSourceX, INT16 sSourceY, INT16 sTargetX, void MoveMilitiaEquipment(INT16 sSourceX, INT16 sSourceY, INT16 sTargetX, INT16 sTargetY, UINT8 usElites, UINT8 usRegulars, UINT8 usGreens) { + if ( !gGameExternalOptions.fMilitiaUseSectorInventory ) + return; + // atm there is no class-specific selection, but that might change in the future for (UINT8 i = 0; i < usElites; ++i) { diff --git a/Tactical/Militia Control.cpp b/Tactical/Militia Control.cpp index fc2b44a69..4ae337006 100644 --- a/Tactical/Militia Control.cpp +++ b/Tactical/Militia Control.cpp @@ -206,23 +206,24 @@ void PrepareMilitiaForTactical( BOOLEAN fPrepareAll) SECTORINFO *pSector; INT32 x; UINT8 ubGreen, ubRegs, ubElites; + if( gbWorldSectorZ > 0 ) return; // Do we have a loaded sector? - if ( gWorldSectorX ==0 && gWorldSectorY == 0 ) + if ( gWorldSectorX == 0 && gWorldSectorY == 0 ) return; - for (int i=0; ibActive || !MercPtrs[i]->bInSector || !TileIsOutOfBounds(MercPtrs[i]->sGridNo)); } pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ]; - ubGreen = pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; - ubRegs = pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; - ubElites = pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + ubGreen = MilitiaInSectorOfRank( gWorldSectorX, gWorldSectorY, GREEN_MILITIA ); + ubRegs = MilitiaInSectorOfRank( gWorldSectorX, gWorldSectorY, REGULAR_MILITIA ); + ubElites = MilitiaInSectorOfRank( gWorldSectorX, gWorldSectorY, ELITE_MILITIA ); // Prevent militia from just waiting on the border gTacticalStatus.Team[MILITIA_TEAM].bAwareOfOpposition = (pSector->uiFlags & SF_PLAYER_KNOWS_ENEMIES_ARE_HERE) != 0; @@ -270,7 +271,7 @@ void PrepareMilitiaForTactical( BOOLEAN fPrepareAll) // } // } - for (int i=0; ibActive || !MercPtrs[i]->bInSector || !TileIsOutOfBounds(MercPtrs[i]->sGridNo)); @@ -279,10 +280,10 @@ void PrepareMilitiaForTactical( BOOLEAN fPrepareAll) void HandleMilitiaPromotions( void ) { - UINT8 cnt; - UINT8 ubMilitiaRank; - SOLDIERTYPE * pTeamSoldier; - UINT8 ubPromotions; + UINT8 cnt; + UINT8 ubMilitiaRank; + SOLDIERTYPE* pTeamSoldier; + UINT8 ubPromotions; gbGreenToElitePromotions = 0; gbGreenToRegPromotions = 0; @@ -291,7 +292,7 @@ void HandleMilitiaPromotions( void ) cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; - for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++, pTeamSoldier++) + for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; ++cnt, ++pTeamSoldier) { if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 ) { @@ -303,18 +304,18 @@ void HandleMilitiaPromotions( void ) { if( ubPromotions == 2 ) { - gbGreenToElitePromotions++; - gbMilitiaPromotions++; + ++gbGreenToElitePromotions; + ++gbMilitiaPromotions; } else if( pTeamSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA ) { - gbGreenToRegPromotions++; - gbMilitiaPromotions++; + ++gbGreenToRegPromotions; + ++gbMilitiaPromotions; } else if( pTeamSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA ) { - gbRegToElitePromotions++; - gbMilitiaPromotions++; + ++gbRegToElitePromotions; + ++gbMilitiaPromotions; } } @@ -322,6 +323,7 @@ void HandleMilitiaPromotions( void ) } } } + if( gbMilitiaPromotions ) { // ATE: Problems here with bringing up message box... diff --git a/Tactical/SkillMenu.cpp b/Tactical/SkillMenu.cpp index 8ce224c37..a992092e6 100644 --- a/Tactical/SkillMenu.cpp +++ b/Tactical/SkillMenu.cpp @@ -11,6 +11,7 @@ #include "DisplayCover.h" #include "worldman.h" #include "Queen Command.h" +#include "strategicmap.h" // sevenfm: need this for correct calculation of traits menu position extern INT16 gsInterfaceLevel; @@ -501,7 +502,7 @@ ReinforcementSector::Setup( UINT32 aVal ) pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction( &Wrapper_Setup_ReinforcementNumber, sectornr ) ); // grey out if no reinforcements can be called from this sector - if ( !NumNonPlayerTeamMembersInSector( loopX, loopY, MILITIA_TEAM ) ) + if ( !CanRequestMilitiaReinforcements( pSoldier->sSectorX, pSoldier->sSectorY, loopX, loopY ) ) { // Set this option off. pOption->setAvail(new popupCallbackFunction( &Popup_OptionOff, NULL )); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index 1a1cbcdb2..b82c1b1b8 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -93,6 +93,8 @@ #include "LOS.h" // added by SANDRO #include "CampaignStats.h" // added by Flugente #include "Interface Panels.h" +#include "Queen Command.h" // added by Flugente +#include "Town Militia.h" // added by Flugente #endif #include "ub_config.h" @@ -17874,8 +17876,12 @@ BOOLEAN SOLDIERTYPE::OrderArtilleryStrike( UINT32 usSectorNr, INT32 sTargetGridN } else if ( bTeam == MILITIA_TEAM ) { - nummortars = (SectorInfo[usSectorNr].ubNumberOfCivsAtLevel[GREEN_MILITIA] + SectorInfo[usSectorNr].ubNumberOfCivsAtLevel[REGULAR_MILITIA] + SectorInfo[usSectorNr].ubNumberOfCivsAtLevel[ELITE_MILITIA]) / gSkillTraitValues.usVOMortarCountDivisor; - numshells = gSkillTraitValues.usVOMortarPointsAdmin * SectorInfo[usSectorNr].ubNumberOfCivsAtLevel[GREEN_MILITIA] + gSkillTraitValues.usVOMortarPointsTroop * SectorInfo[usSectorNr].ubNumberOfCivsAtLevel[REGULAR_MILITIA] + gSkillTraitValues.usVOMortarPointsElite * SectorInfo[usSectorNr].ubNumberOfCivsAtLevel[ELITE_MILITIA]; + UINT8 militia_green = MilitiaInSectorOfRank( sSectorX, sSectorY, GREEN_MILITIA ); + UINT8 militia_troop = MilitiaInSectorOfRank( sSectorX, sSectorY, REGULAR_MILITIA ); + UINT8 militia_elite = MilitiaInSectorOfRank( sSectorX, sSectorY, ELITE_MILITIA ); + + nummortars = (militia_green + militia_troop + militia_elite) / gSkillTraitValues.usVOMortarCountDivisor; + numshells = gSkillTraitValues.usVOMortarPointsAdmin * militia_green + gSkillTraitValues.usVOMortarPointsTroop * militia_troop + gSkillTraitValues.usVOMortarPointsElite * militia_elite; } if ( gSkillTraitValues.usVOMortarShellDivisor * nummortars < 1 ) @@ -22110,8 +22116,8 @@ BOOLEAN IsValidArtilleryOrderSector( INT16 sSectorX, INT16 sSectorY, INT8 bSecto if ( bSectorZ > 0 || sSectorX < 1 || sSectorX >= MAP_WORLD_X - 1 || sSectorY < 1 || sSectorY >= MAP_WORLD_Y - 1 ) return FALSE; - UINT16 usEnemies = (UINT16)NumEnemiesInAnySector( sSectorX, sSectorY, bSectorZ ); - UINT16 usMilitia = (UINT16)GetNumberOfMilitiaInSector( sSectorX, sSectorY, (INT16)bSectorZ ); + UINT16 usEnemies = (UINT16)NumNonPlayerTeamMembersInSector( sSectorX, sSectorY, ENEMY_TEAM ); + UINT16 usMilitia = (UINT16)NumNonPlayerTeamMembersInSector( sSectorX, sSectorY, MILITIA_TEAM ); UINT16 usMercs = (UINT16)PlayerMercsInSector( (UINT8)sSectorX, (UINT8)sSectorY, (UINT8)bSectorZ ); SECTORINFO *pSectorInfo = &(SectorInfo[SECTOR( sSectorX, sSectorY )]); diff --git a/Tactical/Soldier Init List.cpp b/Tactical/Soldier Init List.cpp index a38913b41..58a6161a3 100644 --- a/Tactical/Soldier Init List.cpp +++ b/Tactical/Soldier Init List.cpp @@ -55,6 +55,7 @@ #include "Map Edgepoints.h" #include "Campaign.h" // added by Flugente for HighestPlayerProgressPercentage() #include "CampaignStats.h" // added by Flugente +#include "Town Militia.h" // added by Flugente BOOLEAN gfOriginalList = TRUE; @@ -2825,17 +2826,13 @@ void SectorAddAssassins( INT16 sMapX, INT16 sMapY, INT16 sMapZ ) if ( sMapZ > 0 ) return; - SECTORINFO *pSector = &SectorInfo[ SECTOR( sMapX, sMapY ) ]; - if ( !pSector ) - return; - // does not work atm, time gets reset too early // not if we have recently been in this sector //if ( pSector->uiTimeCurrentSectorWasLastLoaded + 10 > GetWorldTotalMin() ) //return; // do not spawn if militia size is very small (we will be spotted much easier by the player) - UINT32 totalmilitia = pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; + UINT32 totalmilitia = NumNonPlayerTeamMembersInSector( sMapX, sMapY, MILITIA_TEAM ); if ( totalmilitia < gGameExternalOptions.usAssassinMinimumMilitia ) return; @@ -2856,16 +2853,16 @@ void SectorAddAssassins( INT16 sMapX, INT16 sMapY, INT16 sMapZ ) return; // now count militia, and which type (green, regular, elite) is most numerous - that will be the best type to blend in - UINT8 militiacnt = pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ]; + UINT8 militiacnt = MilitiaInSectorOfRank( sMapX, sMapY, GREEN_MILITIA ); UINT8 militiadisguise = GREEN_MILITIA; - if ( pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] > militiacnt ) + if ( MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ) > militiacnt ) { - militiacnt = pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ]; + militiacnt = MilitiaInSectorOfRank( sMapX, sMapY, REGULAR_MILITIA ); militiadisguise = REGULAR_MILITIA; } - if ( pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] > militiacnt ) + + if ( MilitiaInSectorOfRank( sMapX, sMapY, ELITE_MILITIA ) > militiacnt ) { - militiacnt = pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ]; militiadisguise = ELITE_MILITIA; } diff --git a/Tactical/Strategic Exit GUI.cpp b/Tactical/Strategic Exit GUI.cpp index 368383ed5..9f731787a 100644 --- a/Tactical/Strategic Exit GUI.cpp +++ b/Tactical/Strategic Exit GUI.cpp @@ -34,6 +34,7 @@ #include "MessageBoxScreen.h" #include "Quests.h" #include "Creature Spreading.h" + #include "Queen Command.h" // added by Flugente #endif #ifdef JA2UB @@ -307,12 +308,14 @@ BOOLEAN InternalInitSectorExitMenu( UINT8 ubDirection, INT32 sAdditionalData )// if( gTacticalStatus.fEnemyInSector ) { if( gExitDialog.fMultipleSquadsInSector ) - { //We have multiple squads in a hostile sector. That means that we can't load the adjacent sector. + { + //We have multiple squads in a hostile sector. That means that we can't load the adjacent sector. gExitDialog.fGotoSectorDisabled = TRUE; gExitDialog.fGotoSector = FALSE; } - else if( GetNumberOfMilitiaInSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ) ) - { //Leaving this sector will result in militia being forced to fight the battle, can't load adjacent sector. + else if ( gbWorldSectorZ <= 0 && NumNonPlayerTeamMembersInSector( gWorldSectorX, gWorldSectorY, MILITIA_TEAM ) ) + { + //Leaving this sector will result in militia being forced to fight the battle, can't load adjacent sector. gExitDialog.fGotoSectorDisabled = TRUE; gExitDialog.fGotoSector = FALSE; } diff --git a/Utils/Text.h b/Utils/Text.h index fe904ab0e..f4e36f34d 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -2902,6 +2902,9 @@ extern STR16 szIMPGearWebSiteText[]; extern STR16 szIMPGearDropDownText[]; extern STR16 szIMPGearDropDownNoneText[]; +// Flugente: militia movement +extern STR16 szMilitiaStrategicMovementText[]; + #define TACTICAL_INVENTORY_DIALOG_NUM 16 #define TACTICAL_COVER_DIALOG_NUM 16 diff --git a/Utils/Timer Control.cpp b/Utils/Timer Control.cpp index 3e904c37e..46e1b707f 100644 --- a/Utils/Timer Control.cpp +++ b/Utils/Timer Control.cpp @@ -124,6 +124,7 @@ extern INT32 giFlashHighlightedItemBaseTime; //extern INT32 giCompatibleItemBaseTime;//Moa:removed (see HandleMouseInCompatableItemForMapSectorInventory) extern INT32 giAnimateRouteBaseTime; extern INT32 giPotHeliPathBaseTime; +extern INT32 giPotMilitiaPathBaseTime; extern INT32 giClickHeliIconBaseTime; extern INT32 giExitToTactBaseTime; extern UINT32 guiSectorLocatorBaseTime; @@ -540,12 +541,12 @@ void ResetJA2ClockGlobalTimers( void ) { UINT32 uiCurrentTime = GetJA2Clock(); - guiCompressionStringBaseTime = uiCurrentTime; giFlashHighlightedItemBaseTime = uiCurrentTime; //giCompatibleItemBaseTime = uiCurrentTime;//Moa: removed (see HandleMouseInCompatableItemForMapSectorInventory) giAnimateRouteBaseTime = uiCurrentTime; giPotHeliPathBaseTime = uiCurrentTime; + giPotMilitiaPathBaseTime = uiCurrentTime; giClickHeliIconBaseTime = uiCurrentTime; giExitToTactBaseTime = uiCurrentTime; guiSectorLocatorBaseTime = uiCurrentTime; diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 6d108dd91..5bff7697c 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -10029,6 +10029,18 @@ STR16 szIMPGearDropDownNoneText[] = L"No additional items", }; +STR16 szMilitiaStrategicMovementText[] = +{ + L"We cannot relay orders to this sector, militia command not possible.", + L"Unassigned", + L"Group No.", + L"Next", + + L"ETA", + L"Group %d (new)", + L"Group %d", +}; + // WANNE: Some Chinese specific strings that needs to be in unicode! STR16 ChineseSpecString1 = L"%%"; //defined in _ChineseText.cpp as this file is already unicode STR16 ChineseSpecString2 = L"*%3d%%%%"; //defined in _ChineseText.cpp as this file is already unicode diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 0346b6b9a..028edbf37 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -10040,4 +10040,16 @@ STR16 szIMPGearDropDownNoneText[] = L"No additional items", }; +STR16 szMilitiaStrategicMovementText[] = +{ + L"We cannot relay orders to this sector, militia command not possible.", + L"Unassigned", + L"Group No.", + L"Next", + + L"ETA", + L"Group %d (new)", + L"Group %d", +}; + #endif //DUTCH diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 5c209f653..c3cd7436a 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -10078,4 +10078,16 @@ STR16 szIMPGearDropDownNoneText[] = L"No additional items", }; +STR16 szMilitiaStrategicMovementText[] = +{ + L"We cannot relay orders to this sector, militia command not possible.", + L"Unassigned", + L"Group No.", + L"Next", + + L"ETA", + L"Group %d (new)", + L"Group %d", +}; + #endif //ENGLISH diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 4c4a1d4d3..b7531643c 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -10026,4 +10026,16 @@ STR16 szIMPGearDropDownNoneText[] = L"No additional items", }; +STR16 szMilitiaStrategicMovementText[] = +{ + L"We cannot relay orders to this sector, militia command not possible.", + L"Unassigned", + L"Group No.", + L"Next", + + L"ETA", + L"Group %d (new)", + L"Group %d", +}; + #endif //FRENCH diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 2738d9592..7b820d59e 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -9857,4 +9857,16 @@ STR16 szIMPGearDropDownNoneText[] = L"No additional items", }; +STR16 szMilitiaStrategicMovementText[] = +{ + L"We cannot relay orders to this sector, militia command not possible.", + L"Unassigned", + L"Group No.", + L"Next", + + L"ETA", + L"Group %d (new)", + L"Group %d", +}; + #endif //GERMAN diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index b7f8a9db4..fe8440ac3 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -10036,4 +10036,16 @@ STR16 szIMPGearDropDownNoneText[] = L"No additional items", }; +STR16 szMilitiaStrategicMovementText[] = +{ + L"We cannot relay orders to this sector, militia command not possible.", + L"Unassigned", + L"Group No.", + L"Next", + + L"ETA", + L"Group %d (new)", + L"Group %d", +}; + #endif //ITALIAN diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index c931a0b6c..07ad8ee38 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -10051,4 +10051,16 @@ STR16 szIMPGearDropDownNoneText[] = L"No additional items", }; +STR16 szMilitiaStrategicMovementText[] = +{ + L"We cannot relay orders to this sector, militia command not possible.", + L"Unassigned", + L"Group No.", + L"Next", + + L"ETA", + L"Group %d (new)", + L"Group %d", +}; + #endif //POLISH diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index e2c5547b0..ce726a195 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -10024,5 +10024,17 @@ STR16 szIMPGearDropDownNoneText[] = L"No additional items", }; +STR16 szMilitiaStrategicMovementText[] = +{ + L"We cannot relay orders to this sector, militia command not possible.", + L"Unassigned", + L"Group No.", + L"Next", + + L"ETA", + L"Group %d (new)", + L"Group %d", +}; + #endif //RUSSIAN