diff --git a/SaveLoadGame.cpp b/SaveLoadGame.cpp index 212bf952..74c8c73c 100644 --- a/SaveLoadGame.cpp +++ b/SaveLoadGame.cpp @@ -6256,7 +6256,8 @@ BOOLEAN LoadSavedGame( int ubSavedGameID ) OutputDebugString( "Resetting attack busy due to load game.\n"); #endif gTacticalStatus.ubAttackBusyCount = 0; - gfPendingEnemies = CheckPendingEnemies(); + gfPendingNonPlayerTeam[ENEMY_TEAM] = CheckPendingNonPlayerTeam( ENEMY_TEAM ); + gfPendingNonPlayerTeam[MILITIA_TEAM] = CheckPendingNonPlayerTeam( MILITIA_TEAM ); } // ATE: if we are within this window where skyridder was foobared, fix! diff --git a/Strategic/Queen Command.cpp b/Strategic/Queen Command.cpp index 650fe237..93ac9f06 100644 --- a/Strategic/Queen Command.cpp +++ b/Strategic/Queen Command.cpp @@ -75,7 +75,7 @@ std::vector SectorInfo (256); UNDERGROUND_SECTORINFO *gpUndergroundSectorInfoHead = NULL; extern UNDERGROUND_SECTORINFO* gpUndergroundSectorInfoTail; -BOOLEAN gfPendingEnemies = FALSE; +BOOLEAN gfPendingNonPlayerTeam[PLAYER_PLAN] = {FALSE, FALSE, FALSE, FALSE, FALSE}; UINT32 guiTurnCnt = 0, guiReinforceTurn = 0, guiArrived = 0;//dnl ch68 080913 extern void BuildUndergroundSectorInfoList(); @@ -572,7 +572,7 @@ BOOLEAN PrepareEnemyForSectorBattle() unsigned totalCountOfMobileEnemies = 0; int sNumSlots; - gfPendingEnemies = FALSE; + gfPendingNonPlayerTeam[ENEMY_TEAM] = FALSE; if( gbWorldSectorZ > 0 ) return PrepareEnemyForUndergroundBattle(); @@ -601,9 +601,9 @@ BOOLEAN PrepareEnemyForSectorBattle() for( unsigned ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex ) { - while ( NumMobileEnemiesInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ) && GetEnemyGroupInSector( SECTORX( pusMoveDir[ ubIndex][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ) ) + while ( NumMobileEnemiesInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ) ) && GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM ) ) { - pGroup = GetEnemyGroupInSector( SECTORX( pusMoveDir[ ubIndex][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ); + pGroup = GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM ); pGroup->ubPrevX = pGroup->ubSectorX; pGroup->ubPrevY = pGroup->ubSectorY; @@ -653,7 +653,7 @@ BOOLEAN PrepareEnemyForSectorBattle() if (mapMaximumNumberOfEnemies > gGameExternalOptions.ubGameMaximumNumberOfEnemies) mapMaximumNumberOfEnemies = gGameExternalOptions.ubGameMaximumNumberOfEnemies; - gfPendingEnemies = (NumNonPlayerTeamMembersInSector( gWorldSectorX, gWorldSectorY, ENEMY_TEAM ) > mapMaximumNumberOfEnemies); + gfPendingNonPlayerTeam[ENEMY_TEAM] = (NumNonPlayerTeamMembersInSector( gWorldSectorX, gWorldSectorY, ENEMY_TEAM ) > mapMaximumNumberOfEnemies); pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ]; @@ -798,7 +798,7 @@ BOOLEAN PrepareEnemyForSectorBattle() { //adjust the value to zero ubNumAdmins += sNumSlots; sNumSlots = 0; - gfPendingEnemies = TRUE; + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; } pGroup->pEnemyGroup->ubAdminsInBattle += ubNumAdmins; ubTotalAdmins += ubNumAdmins; @@ -812,7 +812,7 @@ BOOLEAN PrepareEnemyForSectorBattle() { //adjust the value to zero ubNumTroops += sNumSlots; sNumSlots = 0; - gfPendingEnemies = TRUE; + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; } pGroup->pEnemyGroup->ubTroopsInBattle += ubNumTroops; ubTotalTroops += ubNumTroops; @@ -826,7 +826,7 @@ BOOLEAN PrepareEnemyForSectorBattle() { //adjust the value to zero ubNumElites += sNumSlots; sNumSlots = 0; - gfPendingEnemies = TRUE; + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; } pGroup->pEnemyGroup->ubElitesInBattle += ubNumElites; ubTotalElites += ubNumElites; @@ -840,7 +840,7 @@ BOOLEAN PrepareEnemyForSectorBattle() { //adjust the value to zero ubNumTanks += sNumSlots; sNumSlots = 0; - gfPendingEnemies = TRUE; + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; } pGroup->pEnemyGroup->ubTanksInBattle += ubNumTanks; ubTotalTanks += ubNumTanks; @@ -1159,7 +1159,7 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier ) } if( guiCurrentScreen == GAME_SCREEN ) { - if( pGroup->ubGroupSize <= iMaxEnemyGroupSize && pGroup->pEnemyGroup->ubNumElites != pGroup->pEnemyGroup->ubElitesInBattle && !gfPendingEnemies || + if ( pGroup->ubGroupSize <= iMaxEnemyGroupSize && pGroup->pEnemyGroup->ubNumElites != pGroup->pEnemyGroup->ubElitesInBattle && !gfPendingNonPlayerTeam[ENEMY_TEAM] || pGroup->ubGroupSize > iMaxEnemyGroupSize /* || pGroup->pEnemyGroup->ubNumElites > 50 || pGroup->pEnemyGroup->ubElitesInBattle > 50*/ ) { DoScreenIndependantMessageBox( L"Group elite counters are bad. What were the last 2-3 things to die, and how? Save game and send to KM with info!!!", MSG_BOX_FLAG_OK, NULL ); @@ -1185,7 +1185,7 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier ) } if( guiCurrentScreen == GAME_SCREEN ) { - if( pGroup->ubGroupSize <= iMaxEnemyGroupSize && pGroup->pEnemyGroup->ubNumTroops != pGroup->pEnemyGroup->ubTroopsInBattle && !gfPendingEnemies || + if ( pGroup->ubGroupSize <= iMaxEnemyGroupSize && pGroup->pEnemyGroup->ubNumTroops != pGroup->pEnemyGroup->ubTroopsInBattle && !gfPendingNonPlayerTeam[ENEMY_TEAM] || pGroup->ubGroupSize > iMaxEnemyGroupSize /*|| pGroup->pEnemyGroup->ubNumTroops > 50 || pGroup->pEnemyGroup->ubTroopsInBattle > 50*/ ) { // haydent @@ -1216,7 +1216,7 @@ void ProcessQueenCmdImplicationsOfDeath( SOLDIERTYPE *pSoldier ) } if( guiCurrentScreen == GAME_SCREEN ) { - if( pGroup->ubGroupSize <= iMaxEnemyGroupSize && pGroup->pEnemyGroup->ubNumAdmins != pGroup->pEnemyGroup->ubAdminsInBattle && !gfPendingEnemies || + if ( pGroup->ubGroupSize <= iMaxEnemyGroupSize && pGroup->pEnemyGroup->ubNumAdmins != pGroup->pEnemyGroup->ubAdminsInBattle && !gfPendingNonPlayerTeam[ENEMY_TEAM] || pGroup->ubGroupSize > iMaxEnemyGroupSize /*|| pGroup->pEnemyGroup->ubNumAdmins > 50 || pGroup->pEnemyGroup->ubAdminsInBattle > 50*/ ) { DoScreenIndependantMessageBox( L"Group admin counters are bad. What were the last 2-3 things to die, and how? Save game and send to KM with info!!!", MSG_BOX_FLAG_OK, NULL ); @@ -1580,7 +1580,7 @@ void AddPossiblePendingEnemiesToBattle() return; } - if( !gfPendingEnemies ) + if ( !gfPendingNonPlayerTeam[ENEMY_TEAM] ) { //Optimization. No point in checking for group reinforcements if we know that there aren't any more enemies that can //be added to this battle. This changes whenever a new enemy group arrives at the scene. @@ -1590,7 +1590,7 @@ void AddPossiblePendingEnemiesToBattle() UINT8 ubInsertionCode = 255; if( gTacticalStatus.Team[ ENEMY_TEAM ].bAwareOfOpposition == TRUE ) - ubInsertionCode = DoReinforcementAsPendingEnemy( gWorldSectorX, gWorldSectorY ); + ubInsertionCode = DoReinforcementAsPendingNonPlayer( gWorldSectorX, gWorldSectorY, ENEMY_TEAM ); if (ubInsertionCode == 255) { @@ -1693,7 +1693,7 @@ void AddPossiblePendingEnemiesToBattle() ubStrategicInsertionCode = INSERTION_CODE_NORTH + Random( 4 ); AddEnemiesToBattle( 0, ubStrategicInsertionCode, ubNumAdmins, ubNumTroops, ubNumElites, ubNumTanks, FALSE ); - gfPendingEnemies = TRUE; + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; } } @@ -1817,9 +1817,10 @@ void AddPossiblePendingEnemiesToBattle() MemFree( pGroupInSectorList); if( ubSlots ) - { //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. - gfPendingEnemies = FALSE; + { + //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. + gfPendingNonPlayerTeam[ENEMY_TEAM] = FALSE; } } @@ -1886,11 +1887,7 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub UINT8 ubCurrSlot; UINT8 ubTotalSoldiers; UINT8 bDesiredDirection=0; - -#ifdef JA2UB - UINT8 ubCnt; -#endif - + switch( ubStrategicInsertionCode ) { case INSERTION_CODE_NORTH: bDesiredDirection = SOUTHEAST; break; @@ -1899,9 +1896,9 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub case INSERTION_CODE_WEST: bDesiredDirection = NORTHEAST; break; default: AssertMsg( 0, "Illegal direction passed to AddEnemiesToBattle()" ); break; } - #ifdef JA2TESTVERSION - ScreenMsg( FONT_RED, MSG_INTERFACE, L"Enemy reinforcements have arrived! (%d admins, %d troops, %d elite)", ubNumAdmins, ubNumTroops, ubNumElites ); - #endif +#ifdef JA2TESTVERSION + ScreenMsg( FONT_RED, MSG_INTERFACE, L"Enemy reinforcements have arrived! (%d admins, %d troops, %d elite)", ubNumAdmins, ubNumTroops, ubNumElites ); +#endif if( fMagicallyAppeared ) { //update the strategic counters @@ -1938,14 +1935,12 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub ubTotalSoldiers = ubNumAdmins + ubNumTroops + ubNumElites + ubNumTanks; - #ifdef JA2UB +#ifdef JA2UB if( gsGridNoForMapEdgePointInfo != -1 ) { ubStrategicInsertionCode = INSERTION_CODE_GRIDNO; } - #endif - - #ifdef JA2UB + if( ubStrategicInsertionCode == INSERTION_CODE_GRIDNO ) { if( gsGridNoForMapEdgePointInfo == -1 ) @@ -1954,7 +1949,7 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub gsGridNoForMapEdgePointInfo=0; } - for( ubCnt=0; ubCnt<32;ubCnt++) + for( UINT8 ubCnt=0; ubCnt<32; ++ubCnt) { MapEdgepointInfo.sGridNo[ ubCnt ] = gsGridNoForMapEdgePointInfo; } @@ -1964,12 +1959,11 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub } else { - ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, (UINT8)(ubNumAdmins+ubNumElites+ubNumTroops+ubNumTanks) ); + ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, ubTotalSoldiers ); } - #else - ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, (UINT8)(ubNumAdmins+ubNumElites+ubNumTroops+ubNumTanks) ); - #endif - +#else + ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, ubTotalSoldiers ); +#endif ubCurrSlot = 0; while( ubTotalSoldiers ) @@ -2082,12 +2076,173 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub } } - #ifdef JA2UB - gsGridNoForMapEdgePointInfo = -1; - #endif +#ifdef JA2UB + gsGridNoForMapEdgePointInfo = -1; +#endif } +void AddMilitiaToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumGreens, UINT8 ubNumRegulars, UINT8 ubNumElites, BOOLEAN fMagicallyAppeared ) +{ + SOLDIERTYPE *pSoldier; + MAPEDGEPOINTINFO MapEdgepointInfo; + UINT8 ubCurrSlot; + UINT8 ubTotalSoldiers; + UINT8 bDesiredDirection = 0; + switch ( ubStrategicInsertionCode ) + { + case INSERTION_CODE_NORTH: bDesiredDirection = SOUTHEAST; break; + case INSERTION_CODE_EAST: bDesiredDirection = SOUTHWEST; break; + case INSERTION_CODE_SOUTH: bDesiredDirection = NORTHWEST; break; + case INSERTION_CODE_WEST: bDesiredDirection = NORTHEAST; break; + default: AssertMsg( 0, "Illegal direction passed to AddEnemiesToBattle()" ); break; + } +#ifdef JA2TESTVERSION + ScreenMsg( FONT_RED, MSG_INTERFACE, L"Militia reinforcements have arrived! (%d greens, %d regulars, %d elite)", ubNumGreens, ubNumRegulars, ubNumElites ); +#endif + + if ( fMagicallyAppeared ) + { + //update the strategic counters + if ( !gbWorldSectorZ ) + { + SECTORINFO *pSector = &SectorInfo[SECTOR( gWorldSectorX, gWorldSectorY )]; + pSector->ubNumberOfCivsAtLevel[GREEN_MILITIA] += ubNumGreens; + pSector->ubNumberOfCivsAtLevel[REGULAR_MILITIA] += ubNumRegulars; + pSector->ubNumberOfCivsAtLevel[ELITE_MILITIA] += ubNumElites; + } + else + { + // there are no underground militia... error if this ever happens + AssertMsg( 0, "Tried to add militia to an underground sector" ); + } + } + + ubTotalSoldiers = ubNumGreens + ubNumRegulars + ubNumElites; + +#ifdef JA2UB + if ( gsGridNoForMapEdgePointInfo != -1 ) + { + ubStrategicInsertionCode = INSERTION_CODE_GRIDNO; + } + + if ( ubStrategicInsertionCode == INSERTION_CODE_GRIDNO ) + { + if ( gsGridNoForMapEdgePointInfo == -1 ) + { + Assert( 0 ); + gsGridNoForMapEdgePointInfo = 0; + } + + for ( UINT8 ubCnt = 0; ubCnt<32; ++ubCnt ) + { + MapEdgepointInfo.sGridNo[ubCnt] = gsGridNoForMapEdgePointInfo; + } + + MapEdgepointInfo.ubNumPoints = 32; + MapEdgepointInfo.ubStrategicInsertionCode = INSERTION_CODE_GRIDNO; + } + else + { + ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, ubTotalSoldiers ); + } +#else + ChooseMapEdgepoints( &MapEdgepointInfo, ubStrategicInsertionCode, (ubTotalSoldiers) ); +#endif + + ubCurrSlot = 0; + while ( ubTotalSoldiers ) + { + if ( ubNumElites && Random( ubTotalSoldiers ) < ubNumElites ) + { + ubNumElites--; + ubTotalSoldiers--; + Assert( pSoldier = TacticalCreateMilitia( SOLDIER_CLASS_ELITE_MILITIA, gWorldSectorX, gWorldSectorY ) ); + if ( pGroup ) + { + pSoldier->ubGroupID = pGroup->ubGroupID; + } + + pSoldier->ubInsertionDirection = bDesiredDirection; + //Setup the position + if ( ubCurrSlot < MapEdgepointInfo.ubNumPoints ) + { //using an edgepoint + pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO; + pSoldier->usStrategicInsertionData = MapEdgepointInfo.sGridNo[ubCurrSlot++]; + } + else + { //no edgepoints left, so put him at the entrypoint. + pSoldier->ubStrategicInsertionCode = ubStrategicInsertionCode; + } + UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 ); + } + else if ( ubNumRegulars && (UINT8)Random( ubTotalSoldiers ) < (UINT8)(ubNumElites + ubNumRegulars) ) + { + ubNumRegulars--; + ubTotalSoldiers--; + Assert( pSoldier = TacticalCreateMilitia( SOLDIER_CLASS_REG_MILITIA, gWorldSectorX, gWorldSectorY ) ); + if ( pGroup ) + { + pSoldier->ubGroupID = pGroup->ubGroupID; + } + + pSoldier->ubInsertionDirection = bDesiredDirection; + //Setup the position + if ( ubCurrSlot < MapEdgepointInfo.ubNumPoints ) + { //using an edgepoint + pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO; + pSoldier->usStrategicInsertionData = MapEdgepointInfo.sGridNo[ubCurrSlot++]; + } + else + { //no edgepoints left, so put him at the entrypoint. + pSoldier->ubStrategicInsertionCode = ubStrategicInsertionCode; + } + UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 ); + } + else if ( ubNumGreens && (UINT8)Random( ubTotalSoldiers ) < (UINT8)(ubNumElites + ubNumRegulars + ubNumGreens) ) + { + ubNumGreens--; + ubTotalSoldiers--; + Assert( pSoldier = TacticalCreateMilitia( SOLDIER_CLASS_GREEN_MILITIA, gWorldSectorX, gWorldSectorY ) ); + if ( pGroup ) + { + pSoldier->ubGroupID = pGroup->ubGroupID; + } + + pSoldier->ubInsertionDirection = bDesiredDirection; + //Setup the position + if ( ubCurrSlot < MapEdgepointInfo.ubNumPoints ) + { //using an edgepoint + pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO; + pSoldier->usStrategicInsertionData = MapEdgepointInfo.sGridNo[ubCurrSlot++]; + } + else + { //no edgepoints left, so put him at the entrypoint. + pSoldier->ubStrategicInsertionCode = ubStrategicInsertionCode; + } + UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, 0 ); + } + + // HEADROCK HAM 3.2: enemy reinforcements arrive with 0 APs. + if ( gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 1 || gGameExternalOptions.ubReinforcementsFirstTurnFreeze == 2 ) + { + pSoldier->bActionPoints = 0; + + // Flugente: due to a fix, also note here that the reinforcements get no APs. + pSoldier->usSoldierFlagMask |= SOLDIER_NO_AP; + + // Flugente: campaign stats + if ( IsOurSoldier( pSoldier ) ) + gCurrentIncident.usIncidentFlags |= INCIDENT_REINFORCEMENTS_PLAYERSIDE; + else + gCurrentIncident.usIncidentFlags |= INCIDENT_REINFORCEMENTS_ENEMY; + } + } + +#ifdef JA2UB + gsGridNoForMapEdgePointInfo = -1; +#endif +} BOOLEAN SaveUnderGroundSectorInfoToSaveGame( HWFILE hFile ) @@ -2627,21 +2782,42 @@ BOOLEAN OnlyHostileCivsInSector() return TRUE; } -BOOLEAN CheckPendingEnemies() +// Flugente check whether a team has nearby members that can be added to the current battle +// Note that this requires separate counts of teammembers in the sector and those that are actually fighting +// This currently does not exist for MILITIA_TEAM, making such a check relatively useless +BOOLEAN CheckPendingNonPlayerTeam( UINT8 usTeam ) { - if( gbWorldSectorZ ) return FALSE; - SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ]; - if( (pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks) > ( pSector->ubElitesInBattle + pSector->ubTroopsInBattle + pSector->ubAdminsInBattle + pSector->ubTanksInBattle) ) - return TRUE; - for (GROUP *pGroup = gpGroupList; pGroup; pGroup = pGroup->next) + if( gbWorldSectorZ ) + return FALSE; + + SECTORINFO *pSector = &SectorInfo[SECTOR( gWorldSectorX, gWorldSectorY )]; + + if ( usTeam == ENEMY_TEAM ) { - if ( pGroup->usGroupTeam != OUR_TEAM - && !pGroup->fVehicle - && pGroup->ubSectorX == gWorldSectorX - && pGroup->ubSectorY == gWorldSectorY - && pGroup->ubGroupSize > pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle + pGroup->pEnemyGroup->ubTanksInBattle) + if( (pSector->ubNumElites + pSector->ubNumTroops + pSector->ubNumAdmins + pSector->ubNumTanks) > ( pSector->ubElitesInBattle + pSector->ubTroopsInBattle + pSector->ubAdminsInBattle + pSector->ubTanksInBattle) ) return TRUE; } + + for (GROUP *pGroup = gpGroupList; pGroup; pGroup = pGroup->next) + { + if ( pGroup->usGroupTeam == usTeam + && !pGroup->fVehicle + && pGroup->ubSectorX == gWorldSectorX + && pGroup->ubSectorY == gWorldSectorY ) + { + if ( usTeam == ENEMY_TEAM ) + { + if ( pGroup->ubGroupSize > pGroup->pEnemyGroup->ubElitesInBattle + pGroup->pEnemyGroup->ubTroopsInBattle + pGroup->pEnemyGroup->ubAdminsInBattle + pGroup->pEnemyGroup->ubTanksInBattle ) + return TRUE; + } + else if ( usTeam == MILITIA_TEAM ) + { + if ( pGroup->ubGroupSize > pSector->ubNumberOfCivsAtLevel[GREEN_MILITIA] + pSector->ubNumberOfCivsAtLevel[REGULAR_MILITIA] + pSector->ubNumberOfCivsAtLevel[ELITE_MILITIA] ) + return TRUE; + } + } + } + return FALSE; } diff --git a/Strategic/Queen Command.h b/Strategic/Queen Command.h index d6080e94..2f650412 100644 --- a/Strategic/Queen Command.h +++ b/Strategic/Queen Command.h @@ -9,7 +9,7 @@ -extern BOOLEAN gfPendingEnemies; +extern BOOLEAN gfPendingNonPlayerTeam[PLAYER_PLAN]; UINT8 NumFreeSlots( UINT8 ubTeam ); @@ -37,6 +37,7 @@ BOOLEAN PrepareEnemyForSectorBattle(); BOOLEAN PrepareEnemyForUndergroundBattle(); void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites, UINT8 ubNumTanks, BOOLEAN fMagicallyAppeared ); +void AddMilitiaToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ubNumGreens, UINT8 ubNumRegulars, UINT8 ubNumElites, BOOLEAN fMagicallyAppeared ); void AddPossiblePendingEnemiesToBattle(); void EndTacticalBattleForEnemy(); @@ -64,7 +65,10 @@ BOOLEAN OnlyHostileCivsInSector(); extern INT32 gsGridNoForMapEdgePointInfo; #endif -BOOLEAN CheckPendingEnemies(); +// Flugente check whether a team has nearby members that can be added to the current battle +// Note that this requires separate counts of teammembers in the sector and those that are actually fighting +// This currently does not exist for MILITIA_TEAM, making such a check relatively useless +BOOLEAN CheckPendingNonPlayerTeam(UINT8 usTeam); extern UINT32 guiTurnCnt, guiReinforceTurn, guiMilitiaReinforceTurn;//dnl ch68 080913 diff --git a/Strategic/Reinforcement.cpp b/Strategic/Reinforcement.cpp index e8012dd0..1a8fb423 100644 --- a/Strategic/Reinforcement.cpp +++ b/Strategic/Reinforcement.cpp @@ -179,13 +179,13 @@ BOOLEAN ARMoveBestMilitiaManFromAdjacentSector(INT16 sMapX, INT16 sMapY) return TRUE; } -GROUP* GetEnemyGroupInSector( INT16 sMapX, INT16 sMapY ) +GROUP* GetNonPlayerGroupInSector( INT16 sMapX, INT16 sMapY, UINT8 usTeam ) { GROUP *curr; curr = gpGroupList; while( curr ) { - if ( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && curr->usGroupTeam != OUR_TEAM && curr->ubGroupID ) + if ( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && curr->usGroupTeam == usTeam && curr->ubGroupID ) return curr; curr = curr->next; } @@ -193,7 +193,7 @@ GROUP* GetEnemyGroupInSector( INT16 sMapX, INT16 sMapY ) } -UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY ) +UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam ) { UINT16 pusMoveDir[4][3]; UINT8 ubDirNumber = 0, ubIndex; @@ -204,16 +204,16 @@ UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY ) if( !gGameExternalOptions.gfAllowReinforcements ) return 255; - if ( ( GetTownIdForSector( sMapX, sMapY ) == OMERTA )&&( gGameOptions.ubDifficultyLevel != DIF_LEVEL_INSANE ) ) //Madd: skip Omerta //Lal: but not on insane ;-) + if ( usTeam == ENEMY_TEAM && ( GetTownIdForSector( sMapX, sMapY ) == OMERTA ) && (gGameOptions.ubDifficultyLevel != DIF_LEVEL_INSANE) ) //Madd: skip Omerta //Lal: but not on insane ;-) return 255; pThisSector = &SectorInfo[ SECTOR( sMapX, sMapY ) ]; GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir, FALSE, TRUE ); - for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ ) + for( ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex ) { - while ((pGroup = GetEnemyGroupInSector( SECTORX( pusMoveDir[ ubIndex][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ) ) != NULL) + while ( (pGroup = GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam )) != NULL ) { // Flugente: disease PopulationMove( pGroup->ubSectorX, pGroup->ubSectorY, sMapX, sMapY, pGroup->ubGroupSize ); @@ -224,9 +224,16 @@ UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY ) pGroup->ubSectorX = pGroup->ubNextX = (UINT8)sMapX; pGroup->ubSectorY = pGroup->ubNextY = (UINT8)sMapY; - gfPendingEnemies = TRUE; - ResetMortarsOnTeamCount(); - ResetNumSquadleadersInArmyGroup(); // added by SANDRO + if ( usTeam == ENEMY_TEAM ) + { + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; + ResetMortarsOnTeamCount(); + ResetNumSquadleadersInArmyGroup(); // added by SANDRO + } + else if ( usTeam == MILITIA_TEAM ) + { + gfPendingNonPlayerTeam[MILITIA_TEAM] = TRUE; + } } } @@ -234,7 +241,7 @@ UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY ) { ubIndex = Random(ubDirNumber); - if ( NumNonPlayerTeamMembersInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM ) > gubReinforcementMinEnemyStaticGroupSize ) + if ( usTeam == ENEMY_TEAM && NumNonPlayerTeamMembersInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam ) > gubReinforcementMinEnemyStaticGroupSize ) { pSector = &SectorInfo[ pusMoveDir[ ubIndex ][ 0 ] ]; @@ -244,19 +251,22 @@ UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY ) (pSector->ubNumElites)--; (pThisSector->ubElitesInBattle)++; AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 0, 1, 0, FALSE ); - }else if( pSector->ubNumTroops ) + } + else if( pSector->ubNumTroops ) { (pThisSector->ubNumTroops)++; (pSector->ubNumTroops)--; (pThisSector->ubTroopsInBattle)++; AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 0, 1, 0, 0, FALSE ); - }else if( pSector->ubNumAdmins ) + } + else if( pSector->ubNumAdmins ) { (pThisSector->ubNumAdmins)++; (pSector->ubNumAdmins)--; (pThisSector->ubAdminsInBattle)++; AddEnemiesToBattle( NULL, (UINT8)pusMoveDir[ ubIndex ][ 2 ], 1, 0, 0, 0, FALSE ); - }else if( pSector->ubNumTanks ) + } + else if( pSector->ubNumTanks ) { (pThisSector->ubNumTanks)++; (pSector->ubNumTanks)--; @@ -266,6 +276,32 @@ UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY ) 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 ) ) + { + pSector = &SectorInfo[pusMoveDir[ubIndex][0]]; + + if ( pSector->ubNumberOfCivsAtLevel[ELITE_MILITIA] ) + { + (pThisSector->ubNumberOfCivsAtLevel[ELITE_MILITIA])++; + (pSector->ubNumberOfCivsAtLevel[ELITE_MILITIA])--; + AddMilitiaToBattle( NULL, (UINT8)pusMoveDir[ubIndex][2], 0, 0, 1, FALSE ); + } + else if ( pSector->ubNumberOfCivsAtLevel[REGULAR_MILITIA] ) + { + (pThisSector->ubNumberOfCivsAtLevel[REGULAR_MILITIA])++; + (pSector->ubNumberOfCivsAtLevel[REGULAR_MILITIA])--; + AddMilitiaToBattle( NULL, (UINT8)pusMoveDir[ubIndex][2], 0, 1, 0, FALSE ); + } + else if ( pSector->ubNumberOfCivsAtLevel[GREEN_MILITIA] ) + { + (pThisSector->ubNumberOfCivsAtLevel[GREEN_MILITIA])++; + (pSector->ubNumberOfCivsAtLevel[GREEN_MILITIA])--; + AddMilitiaToBattle( NULL, (UINT8)pusMoveDir[ubIndex][2], 1, 0, 0, FALSE ); + } + + return (UINT8)pusMoveDir[ubIndex][2]; + } else { // If there are no reinforcements from this direction, remove this as a direction @@ -391,11 +427,29 @@ void AddPossiblePendingMilitiaToBattle() guiMilitiaReinforceTurn = guiMilitiaArrived = 0; //SendFmtMsg("Militia reinforcements: guiTurnCnt=%d guiReinforceTurn=%d guiArrived=%d", guiTurnCnt, guiMilitiaReinforceTurn, guiMilitiaArrived); } + if( !ubSlots ) - { //no available slots to add militia to. Try again later... + { + //no available slots to add militia to. Try again later... return; } + if ( !gfPendingNonPlayerTeam[MILITIA_TEAM] ) + { + //Optimization. No point in checking for group reinforcements if we know that there aren't any more enemies that can + //be added to this battle. This changes whenever a new enemy group arrives at the scene. + while ( ubSlots ) + { + UINT8 ubInsertionCode = DoReinforcementAsPendingNonPlayer( gWorldSectorX, gWorldSectorY, MILITIA_TEAM ); + + if ( ubInsertionCode == 255 ) + break; + + // Assume we added one since there are supposedly more available and room for them + --ubSlots; + } + } + if( ubPredefinedInsertionCode != 255 && ubPredefinedRank != 255 && NumNonPlayerTeamMembersInSector( gWorldSectorX, gWorldSectorY, MILITIA_TEAM ) ) { @@ -438,5 +492,12 @@ void AddPossiblePendingMilitiaToBattle() gfStrategicMilitiaChangesMade = FALSE; // Handled them here } } + + if ( ubSlots ) + { + //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. + gfPendingNonPlayerTeam[MILITIA_TEAM] = FALSE; + } } diff --git a/Strategic/Reinforcement.h b/Strategic/Reinforcement.h index 013461bb..2ea84467 100644 --- a/Strategic/Reinforcement.h +++ b/Strategic/Reinforcement.h @@ -9,8 +9,8 @@ UINT8 CountAllMilitiaInFiveSectors(INT16 sMapX, INT16 sMapY); UINT8 NumEnemiesInFiveSectors( INT16 sMapX, INT16 sMapY ); //For Tactical -UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY ); +UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam ); void AddPossiblePendingMilitiaToBattle(); -GROUP* GetEnemyGroupInSector( INT16 sMapX, INT16 sMapY ); +GROUP* GetNonPlayerGroupInSector( INT16 sMapX, INT16 sMapY, UINT8 usTeam ); #endif \ No newline at end of file diff --git a/Strategic/Strategic Movement.cpp b/Strategic/Strategic Movement.cpp index d6ea9c08..8fa262a3 100644 --- a/Strategic/Strategic Movement.cpp +++ b/Strategic/Strategic Movement.cpp @@ -3489,12 +3489,16 @@ void HandleArrivalOfReinforcements( GROUP *pGroup ) ScreenMsg( FONT_YELLOW, MSG_INTERFACE, Message[ STR_PLAYER_REINFORCEMENTS ] ); } - else + else if ( pGroup->usGroupTeam == ENEMY_TEAM ) { - gfPendingEnemies = TRUE; + gfPendingNonPlayerTeam[ENEMY_TEAM] = TRUE; ResetMortarsOnTeamCount(); ResetNumSquadleadersInArmyGroup(); // added by SANDRO AddPossiblePendingEnemiesToBattle(); + } + else if ( pGroup->usGroupTeam == MILITIA_TEAM ) + { + gfPendingNonPlayerTeam[MILITIA_TEAM] = TRUE; AddPossiblePendingMilitiaToBattle( ); } diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index b7cc0723..f7d717e8 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -7055,12 +7055,13 @@ BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated ) //NEW (Nov 24, 98) by Kris if( !gbWorldSectorZ && fBattleWon ) - { //Check to see if more enemy soldiers exist in the strategic layer + { + //Check to see if more enemy soldiers exist in the strategic layer //It is possible to have more than 20 enemies in a sector. By failing here, //it gives the engine a chance to add these soldiers as reinforcements. This //is naturally handled. AddPossiblePendingEnemiesToBattle(); - if( gfPendingEnemies ) + if ( gfPendingNonPlayerTeam[ENEMY_TEAM] ) { fBattleWon = FALSE; }