New feature: transport groups (#172)

https://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=365395
This commit is contained in:
rftrdev
2023-07-04 20:58:56 -07:00
committed by GitHub
parent 8d3e6fce40
commit fb03cba2fa
37 changed files with 1471 additions and 102 deletions
+3 -2
View File
@@ -633,6 +633,7 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve1");
switch( GetEnemyEncounterCode() )
{
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
gpAR->ubPlayerDefenceAdvantage = 21; //Skewed to the player's advantage for convenience purposes.
break;
case ENEMY_INVASION_CODE:
@@ -1745,6 +1746,7 @@ void RenderAutoResolve()
swprintf( str, gpStrategicString[STR_AR_ATTACK_HEADER] );
break;
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
swprintf( str, gpStrategicString[STR_AR_ENCOUNTER_HEADER] );
break;
case ENEMY_INVASION_CODE:
@@ -6058,6 +6060,5 @@ BOOLEAN IndividualMilitiaInUse_AutoResolve( UINT32 aMilitiaId )
}
}
}
return FALSE;
}
}
+1
View File
@@ -47,6 +47,7 @@ set(StrategicSrc
"${CMAKE_CURRENT_SOURCE_DIR}/Strategic Status.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Strategic Town Loyalty.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/strategic town reputation.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Strategic Transport Groups.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/Strategic Turns.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/strategic.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/strategicmap.cpp"
+6
View File
@@ -48,6 +48,7 @@
#include "LuaInitNPCs.h" // added by Flugente
#include "MiniEvents.h"
#include "Rebel Command.h"
#include "interface Dialogue.h"
#include "connect.h"
@@ -668,6 +669,11 @@ BOOLEAN ExecuteStrategicEvent( STRATEGICEVENT *pEvent )
case EVENT_REBELCOMMAND:
RebelCommand::HandleStrategicEvent(pEvent->uiParam);
break;
case EVENT_RETURN_TRANSPORT_GROUP:
// for this action, we only care about the groupid, which is in the event param
ExecuteStrategicAIAction(NPC_ACTION_RETURN_TRANSPORT_GROUP, 0, 0, pEvent->uiParam);
break;
}
gfPreventDeletionOfAnyEvent = fOrigPreventFlag;
return TRUE;
+4 -1
View File
@@ -154,6 +154,9 @@ enum
EVENT_REBELCOMMAND,
EVENT_RETURN_TRANSPORT_GROUP,
EVENT_TRANSPORT_GROUP_DEFEATED,
NUMBER_OF_EVENT_TYPES_PLUS_ONE,
NUMBER_OF_EVENT_TYPES = NUMBER_OF_EVENT_TYPES_PLUS_ONE - 1
};
@@ -217,4 +220,4 @@ void DeleteAllStrategicEvents();
// Flugente: return vector of all events of type ubCallbackID with time and param
std::vector< std::pair<UINT32, UINT32> > GetAllStrategicEventsOfType( UINT8 ubCallbackID );
#endif
#endif
+1
View File
@@ -137,6 +137,7 @@ CHAR16 gEventName[NUMBER_OF_EVENT_TYPES_PLUS_ONE][40]={
L"ArmyFinishTraining",
L"MiniEvent",
L"ARC_Event",
L"ReturnTransportGroup",
};
#endif
+22
View File
@@ -46,6 +46,7 @@
#include "LuaInitNPCs.h" // added by Flugente
#include "Game Event Hook.h" // added by Flugente
#include "Rebel Command.h"
#include "Strategic Transport Groups.h"
#include "Quests.h"
#include "connect.h"
@@ -841,6 +842,8 @@ void fillMapColoursForVisitedSectors(INT32(&colorMap)[ MAXIMUM_VALID_Y_COORDINAT
}
}
FillMapColoursForTransportGroups(colorMap);
if (RebelCommand::ShowEnemyMovementTargets())
{
const auto targetColor = MAP_SHADE_LT_RED;
@@ -8584,6 +8587,25 @@ void DetermineMapIntelData( INT32 asSectorZ )
}
}
// transport groups
std::map<UINT8, TransportGroupSectorInfo> map = GetTransportGroupSectorInfo();
for (const auto iter : map)
{
CHAR16 str[128];
switch (iter.second)
{
case TransportGroupSectorInfo::TransportGroupSectorInfo_LocatedGroup:
swprintf( str, gpStrategicString[STR_PB_TRANSPORT_GROUP]);
break;
case TransportGroupSectorInfo::TransportGroupSectorInfo_LocatedDestination:
swprintf( str, gpStrategicString[STR_PB_TRANSPORT_GROUP_EN_ROUTE]);
break;
}
AddIntelAndQuestMapDataForSector( SECTORX(iter.first), SECTORY(iter.first), MAP_SHADE_LT_YELLOW, -1, str, L"" );
}
// uncovered terrorists we know of
for ( int cnt = 0; cnt < 6; ++cnt )
{
+33 -5
View File
@@ -47,6 +47,7 @@
#include "CampaignStats.h" // added by Flugente
#include "militiasquads.h" // added by Flugente
#include "SkillCheck.h" // added by Flugente
#include "Strategic Transport Groups.h"
#ifdef JA2UB
#include "ub_config.h"
@@ -438,7 +439,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
}
else if ( pBattleGroup && pBattleGroup->usGroupTeam != OUR_TEAM && NumNonPlayerTeamMembersInSector( pBattleGroup->ubSectorX, pBattleGroup->ubSectorY, MILITIA_TEAM ) > 0 )
{
SetEnemyEncounterCode( ENEMY_ENCOUNTER_CODE );
SetEnemyEncounterCode( pBattleGroup->usGroupTeam == ENEMY_TEAM && pBattleGroup->pEnemyGroup->ubIntention == TRANSPORT ? TRANSPORT_INTERCEPT_CODE : ENEMY_ENCOUNTER_CODE );
}
else if( GetEnemyEncounterCode() == ENTERING_ENEMY_SECTOR_CODE ||
GetEnemyEncounterCode() == ENEMY_ENCOUNTER_CODE ||
@@ -452,7 +453,8 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
GetEnemyEncounterCode() == CONCEALINSERTION_CODE ||
GetEnemyEncounterCode() == BLOODCAT_ATTACK_CODE ||
GetEnemyEncounterCode() == ZOMBIE_ATTACK_CODE ||
GetEnemyEncounterCode() == BANDIT_ATTACK_CODE )
GetEnemyEncounterCode() == BANDIT_ATTACK_CODE ||
GetEnemyEncounterCode() == TRANSPORT_INTERCEPT_CODE )
{
//use same code
SetExplicitEnemyEncounterCode( GetEnemyEncounterCode() );
@@ -679,8 +681,24 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
{
SetEnemyEncounterCode( ENEMY_ENCOUNTER_CODE );
GROUP* pGroup = gpGroupList;
BOOLEAN encounteredTransportGroup = FALSE;
while (pGroup)
{
if (pGroup->usGroupTeam == ENEMY_TEAM && pGroup->pEnemyGroup->ubIntention == TRANSPORT && pGroup->ubSectorX == gpBattleGroup->ubSectorX && pGroup->ubSectorY == gpBattleGroup->ubSectorY && pGroup->ubSectorZ == gpBattleGroup->ubSectorZ)
{
encounteredTransportGroup = TRUE;
break;
}
pGroup = pGroup->next;
}
if (encounteredTransportGroup)
{
SetEnemyEncounterCode( TRANSPORT_INTERCEPT_CODE );
}
// Flugente: no ambushes on an airdrop
if ( !fAirDrop )
else if ( !fAirDrop )
{
//Don't consider ambushes until the player has reached 25% (normal) progress
if( gfHighPotentialForAmbush )
@@ -798,7 +816,9 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
}
else
{ //Are enemies invading a town, or just encountered the player.
if( GetTownIdForSector( gubPBSectorX, gubPBSectorY ) )
if (pBattleGroup && pBattleGroup->usGroupTeam == ENEMY_TEAM && pBattleGroup->pEnemyGroup->ubIntention == TRANSPORT)
SetEnemyEncounterCode( TRANSPORT_INTERCEPT_CODE );
else if( GetTownIdForSector( gubPBSectorX, gubPBSectorY ) )
SetEnemyEncounterCode( ENEMY_INVASION_CODE );
//SAM sites not in towns will also be considered to be important
else if( pSector->uiFlags & SF_SAM_SITE )
@@ -866,7 +886,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
}
HideButton( giMapContractButton );
if( GetEnemyEncounterCode() == ENEMY_ENCOUNTER_CODE )
if( GetEnemyEncounterCode() == ENEMY_ENCOUNTER_CODE || GetEnemyEncounterCode() == TRANSPORT_INTERCEPT_CODE )
{ //we know how many enemies are here, so until we leave the sector, we will continue to display the value.
//the flag will get cleared when time advances after the fEnemyInSector flag is clear.
@@ -955,6 +975,7 @@ void InitPreBattleInterface( GROUP *pBattleGroup, BOOLEAN fPersistantPBI )
{
case CREATURE_ATTACK_CODE:
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
case ENEMY_INVASION_CODE:
case ENEMY_INVASION_AIRDROP_CODE:
case BLOODCAT_ATTACK_CODE:
@@ -1213,6 +1234,7 @@ void RenderPBHeader( INT32 *piX, INT32 *piWidth)
swprintf( str, gpStrategicString[ STR_PB_ENEMYINVASION_HEADER ] );
break;
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
swprintf( str, gpStrategicString[ STR_PB_ENEMYENCOUNTER_HEADER ] );
break;
case ENEMY_AMBUSH_CODE:
@@ -2520,6 +2542,10 @@ void LogBattleResults( UINT8 ubVictoryCode)
break;
case CONCEALINSERTION_CODE:
break;
case TRANSPORT_INTERCEPT_CODE:
AddHistoryToPlayersLog( HISTORY_INTERCEPTED_TRANSPORT_GROUP, 0, GetWorldTotalMin(), sSectorX, sSectorY );
NotifyTransportGroupDefeated();
break;
}
// Flugente: campaign stats
@@ -2534,6 +2560,7 @@ void LogBattleResults( UINT8 ubVictoryCode)
AddHistoryToPlayersLog( HISTORY_LOSTTOWNSECTOR, 0, GetWorldTotalMin(), sSectorX, sSectorY );
break;
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
AddHistoryToPlayersLog( HISTORY_LOSTBATTLE, 0, GetWorldTotalMin(), sSectorX, sSectorY );
break;
case ENEMY_AMBUSH_CODE:
@@ -2567,6 +2594,7 @@ void LogBattleResults( UINT8 ubVictoryCode)
gCurrentIncident.usIncidentFlags |= INCIDENT_ATTACK_ENEMY;
break;
case ENEMY_ENCOUNTER_CODE:
case TRANSPORT_INTERCEPT_CODE:
case ENTERING_ENEMY_SECTOR_CODE:
case CREATURE_ATTACK_CODE:
case ENTERING_BLOODCAT_LAIR_CODE:
+3 -1
View File
@@ -47,6 +47,8 @@ enum
BLOODCAT_ATTACK_CODE, // Flugente: like CREATURE_ATTACK_CODE, but with cats
ZOMBIE_ATTACK_CODE, // Flugente: like CREATURE_ATTACK_CODE, but with zombies
BANDIT_ATTACK_CODE, // Flugente: like CREATURE_ATTACK_CODE, but with bandits
TRANSPORT_INTERCEPT_CODE, // rftr: like ENEMY_ENCOUNTER_CODE
};
extern BOOLEAN gfAutoAmbush;
@@ -112,4 +114,4 @@ enum
};
void LogBattleResults( UINT8 ubVictoryCode);
#endif
#endif
+54 -3
View File
@@ -42,6 +42,7 @@
#include "CampaignStats.h" // added by Flugente
#include "ASD.h" // added by Flugente
#include "Interface Panels.h"
#include "Strategic Transport Groups.h"
#ifdef JA2BETAVERSION
extern BOOLEAN gfClearCreatureQuest;
@@ -98,7 +99,6 @@ void HandleBloodCatDeaths( SECTORINFO *pSector );
extern void Ensure_RepairedGarrisonGroup( GARRISON_GROUP **ppGarrison, INT32 *pGarraySize );
void ValidateEnemiesHaveWeapons()
{
#ifdef JA2BETAVERSION
@@ -613,6 +613,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
gfPendingNonPlayerTeam[ENEMY_TEAM] = FALSE;
// rftr: clear cached transport groups
ClearTransportGroupMap();
if( gbWorldSectorZ > 0 )
return PrepareEnemyForUndergroundBattle();
@@ -640,9 +643,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
for( unsigned ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex )
{
while ( NumMobileEnemiesInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ) ) && GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM ) )
while ( NumMobileEnemiesInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ) ) && GetNonPlayerGroupInSectorForReinforcement( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM ) )
{
pGroup = GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM );
pGroup = GetNonPlayerGroupInSectorForReinforcement( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), ENEMY_TEAM );
pGroup->ubPrevX = pGroup->ubSectorX;
pGroup->ubPrevY = pGroup->ubSectorY;
@@ -669,10 +672,23 @@ BOOLEAN PrepareEnemyForSectorBattle()
HandleArrivalOfReinforcements( pGroup );
}
// for transport groups, track how many enemies of each type we're adding so we can update drops for them
if (pGroup->usGroupTeam == ENEMY_TEAM && pGroup->pEnemyGroup->ubIntention == TRANSPORT && pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ)
{
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ADMINISTRATOR, pGroup->pEnemyGroup->ubNumAdmins);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ARMY, pGroup->pEnemyGroup->ubNumTroops);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ELITE, pGroup->pEnemyGroup->ubNumElites);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ROBOT, pGroup->pEnemyGroup->ubNumRobots);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_JEEP, pGroup->pEnemyGroup->ubNumJeeps);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_TANK, pGroup->pEnemyGroup->ubNumTanks);
}
pGroup = pGroup->next;
}
}
UpdateTransportGroupInventory();
ValidateEnemiesHaveWeapons();
UnPauseGame();
return ( ( BOOLEAN) ( gpBattleGroup->ubGroupSize > 0 ) );
@@ -852,6 +868,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle &&
pGroup->ubSectorX == gWorldSectorX && pGroup->ubSectorY == gWorldSectorY && !gbWorldSectorZ )
{ //Process enemy group in sector.
const BOOLEAN isTransportGroup = pGroup->pEnemyGroup->ubIntention == TRANSPORT;
if( sNumSlots > 0 )
{
AssertGE(pGroup->pEnemyGroup->ubNumAdmins, pGroup->pEnemyGroup->ubAdminsInBattle);
@@ -865,6 +882,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubAdminsInBattle += ubNumAdmins;
ubTotalAdmins += ubNumAdmins;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ADMINISTRATOR, ubNumAdmins);
}
if( sNumSlots > 0 )
{ //Add regular army forces.
@@ -879,6 +899,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubTroopsInBattle += ubNumTroops;
ubTotalTroops += ubNumTroops;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ARMY, ubNumTroops);
}
if( sNumSlots > 0 )
{ //Add elite troops
@@ -893,6 +916,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubElitesInBattle += ubNumElites;
ubTotalElites += ubNumElites;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ELITE, ubNumElites);
}
if( sNumSlots > 0 )
{ //Add robots
@@ -907,6 +933,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubRobotsInBattle += ubNumRobots;
ubTotalRobots += ubNumRobots;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ROBOT, ubNumRobots);
}
if( sNumSlots > 0 )
{ //Add tanks
@@ -921,6 +950,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubTanksInBattle += ubNumTanks;
ubTotalTanks += ubNumTanks;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_TANK, ubNumTanks);
}
if ( sNumSlots > 0 )
{
@@ -936,6 +968,9 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
pGroup->pEnemyGroup->ubJeepsInBattle += ubNumJeeps;
ubTotalJeeps += ubNumJeeps;
if (isTransportGroup)
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_JEEP, ubNumJeeps);
}
//NOTE:
//no provisions for profile troop leader or retreat groups yet.
@@ -976,6 +1011,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
unsigned firstSlot = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
unsigned lastSlot = gTacticalStatus.Team[ ENEMY_TEAM ].bLastID;
unsigned slotsAvailable = lastSlot-firstSlot+1;
while( pGroup && sNumSlots > 0 )
{
if ( pGroup->usGroupTeam != OUR_TEAM && !pGroup->fVehicle &&
@@ -1088,6 +1124,7 @@ BOOLEAN PrepareEnemyForSectorBattle()
}
break;
}
}
// Flugente: instead of just crashing the game without any explanation to the user, ignore this issue if it still exists.
@@ -1103,6 +1140,8 @@ BOOLEAN PrepareEnemyForSectorBattle()
pGroup = pGroup->next;
}
UpdateTransportGroupInventory();
ValidateEnemiesHaveWeapons();
UnPauseGame();
@@ -2145,6 +2184,16 @@ void AddEnemiesToBattle( GROUP *pGroup, UINT8 ubStrategicInsertionCode, UINT8 ub
UINT8 ubTotalSoldiers;
UINT8 bDesiredDirection=0;
// while transport groups can't normally reinforce, this covers the case where a transport group enters a sector (via normal movement)
// where a battle is in progress.
if (pGroup && pGroup->pEnemyGroup->ubIntention == TRANSPORT)
{
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ADMINISTRATOR, ubNumAdmins);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ARMY, ubNumTroops);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_ELITE, ubNumElites);
AddToTransportGroupMap(pGroup->ubGroupID, SOLDIER_CLASS_JEEP, ubNumJeeps);
}
switch( ubStrategicInsertionCode )
{
case INSERTION_CODE_NORTH: bDesiredDirection = SOUTHEAST; break;
@@ -3594,3 +3643,5 @@ void CorrectTurncoatCount( INT16 sSectorX, INT16 sSectorY )
pGroup = pGroup->next;
}
}
+57 -5
View File
@@ -41,8 +41,10 @@ How to add a new admin action:
- if effect applies outside of towns, add help text range band as appropriate to SetupAdminActionBox
How to add a new mission:
- add to the RebelCommandAgentMissions enum in the header
- add strings to text files (szRebelCommandAgentMissionsText)
- add strings to text files (szRebelCommandText (trait bonuses), szRebelCommandAgentMissionsText (title/description))
- add to the RebelCommandText and RebelCommandAgentMissions enums in the header
- add to the RebelCommandAgentMissionsText enums in the cpp
- add mission variables to GameSettings
- add values to MissionHelpers::missionInfo table in SetupInfo()
- add to valid check in HandleStrategicEvent() (allows advance from first event/prepare to second event/active effect)
- add to SetupMissionAgentBox() (mission description and merc bonus text)
@@ -91,6 +93,7 @@ Points of interest:
#include "Strategic Mines.h"
#include "Strategic Movement.h"
#include "Strategic Town Loyalty.h"
#include "Strategic Transport Groups.h"
#include "Structure Wrap.h"
#include "Tactical Save.h"
#include "Text.h"
@@ -405,6 +408,7 @@ enum RebelCommandAgentMissionsText // keep this synced with szRebelCommandAgentM
{
MISSION_TEXT(DEEP_DEPLOYMENT)
MISSION_TEXT(DISRUPT_ASD)
MISSION_TEXT(FORGE_TRANSPORT_ORDERS)
MISSION_TEXT(GET_ENEMY_MOVEMENT_TARGETS)
MISSION_TEXT(IMPROVE_LOCAL_SHOPS)
MISSION_TEXT(REDUCE_STRATEGIC_DECISION_SPEED)
@@ -2221,6 +2225,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
{
case RCAM_DEEP_DEPLOYMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DEEP_DEPLOYMENT_TITLE]); break;
case RCAM_DISRUPT_ASD: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DISRUPT_ASD_TITLE]); break;
case RCAM_FORGE_TRANSPORT_ORDERS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_FORGE_TRANSPORT_ORDERS_TITLE]); break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_GET_ENEMY_MOVEMENT_TARGETS_TITLE]); break;
case RCAM_IMPROVE_LOCAL_SHOPS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_IMPROVE_LOCAL_SHOPS_TITLE]); break;
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_TITLE]); break;
@@ -2241,6 +2246,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
{
case RCAM_DEEP_DEPLOYMENT: missionDurationBase = gRebelCommandSettings.iDeepDeploymentDuration; break;
case RCAM_DISRUPT_ASD: missionDurationBase = gRebelCommandSettings.iDisruptAsdDuration; break;
case RCAM_FORGE_TRANSPORT_ORDERS: missionDurationBase = 1; break; // instant effect
case RCAM_GET_ENEMY_MOVEMENT_TARGETS: missionDurationBase = gRebelCommandSettings.iGetEnemyMovementTargetsDuration; break;
case RCAM_IMPROVE_LOCAL_SHOPS: missionDurationBase = gRebelCommandSettings.iImproveLocalShopsDuration; break;
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: missionDurationBase = gRebelCommandSettings.iReduceStrategicDecisionSpeedDuration; break;
@@ -2264,6 +2270,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
{
case RCAM_DEEP_DEPLOYMENT: missionSuccessChanceBase = gRebelCommandSettings.iDeepDeploymentSuccessChance; break;
case RCAM_DISRUPT_ASD: missionSuccessChanceBase = gRebelCommandSettings.iDisruptAsdSuccessChance; break;
case RCAM_FORGE_TRANSPORT_ORDERS: missionSuccessChanceBase = gRebelCommandSettings.iForgeTransportOrdersSuccessChance; break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS: missionSuccessChanceBase = gRebelCommandSettings.iGetEnemyMovementTargetsSuccessChance; break;
case RCAM_IMPROVE_LOCAL_SHOPS: missionSuccessChanceBase = gRebelCommandSettings.iImproveLocalShopsSuccessChance; break;
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: missionSuccessChanceBase = gRebelCommandSettings.iReduceStrategicDecisionSpeedSuccessChance; break;
@@ -2284,6 +2291,7 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
{
case RCAM_DEEP_DEPLOYMENT: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DEEP_DEPLOYMENT_DESC]); break;
case RCAM_DISRUPT_ASD: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_DISRUPT_ASD_DESC]); break;
case RCAM_FORGE_TRANSPORT_ORDERS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_FORGE_TRANSPORT_ORDERS_DESC]); break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_GET_ENEMY_MOVEMENT_TARGETS_DESC]); break;
case RCAM_IMPROVE_LOCAL_SHOPS: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_IMPROVE_LOCAL_SHOPS_DESC]); break;
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED: swprintf(sText, szRebelCommandAgentMissionsText[RCAMT_REDUCE_STRATEGIC_DECISION_SPEED_DESC]); break;
@@ -2454,6 +2462,12 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
}
}
case RCAM_FORGE_TRANSPORT_ORDERS:
{
// no special modifiers. included for completeness.
}
break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS:
{
// no special modifiers. included for completeness.
@@ -2610,7 +2624,13 @@ BOOLEAN SetupMissionAgentBox(UINT16 x, UINT16 y, INT8 index)
swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_START_CONTRACT_EXPIRING]);
}
}
else if (agentIndex[index] == mercs.size() && rebelCommandSaveInfo.availableMissions[index] == RCAM_SEND_SUPPLIES_TO_TOWN)
else if (agentIndex[index] == mercs.size() &&
(
rebelCommandSaveInfo.availableMissions[index] == RCAM_SEND_SUPPLIES_TO_TOWN ||
rebelCommandSaveInfo.availableMissions[index] == RCAM_FORGE_TRANSPORT_ORDERS
)
)
{
canStartMission = FALSE;
swprintf(sText, szRebelCommandText[RCT_MISSION_CANT_USE_REBEL_AGENT]);
@@ -2847,6 +2867,14 @@ void PrepareMission(INT8 index)
}
break;
case RCAM_FORGE_TRANSPORT_ORDERS:
{
missionTitle = RCAMT_FORGE_TRANSPORT_ORDERS_TITLE;
missionSuccessChance = gRebelCommandSettings.iForgeTransportOrdersSuccessChance;
missionDuration = 12;
}
break;
case RCAM_GET_ENEMY_MOVEMENT_TARGETS:
{
missionTitle = RCAMT_GET_ENEMY_MOVEMENT_TARGETS_TITLE;
@@ -3897,6 +3925,7 @@ void DailyUpdate()
{
if (i == RCAM_SOLDIER_BOUNTIES_KINGPIN && !(CheckFact(FACT_KINGPIN_INTRODUCED_SELF, 0) == TRUE && CheckFact(FACT_KINGPIN_DEAD, 0) == FALSE && CheckFact(FACT_KINGPIN_IS_ENEMY, 0) == FALSE && CurrentPlayerProgressPercentage() >= 30)) continue;
else if (i == RCAM_DISRUPT_ASD && gGameExternalOptions.fASDActive == FALSE) continue;
else if (i == RCAM_FORGE_TRANSPORT_ORDERS && gGameExternalOptions.fStrategicTransportGroupsEnabled == FALSE) continue;
validMissions.insert(static_cast<RebelCommandAgentMissions>(i));
}
@@ -4299,6 +4328,16 @@ void SetupInfo()
{0, 0, 0, 0},
{0, MissionHelpers::DISRUPT_ASD_STEAL_FUEL, MissionHelpers::DISRUPT_ASD_DESTROY_RESERVES, 0}
});
//RCAM_FORGE_TRANSPORT_ORDERS
MissionHelpers::missionInfo.push_back(
{
{COVERT_NT },
{-1},
{0},
{0.f},
{0},
{0}
});
//RCAM_GET_ENEMY_MOVEMENT_TARGETS
MissionHelpers::missionInfo.push_back(
{
@@ -4902,6 +4941,7 @@ void HandleStrategicEvent(const UINT32 eventParam)
{
case RCAM_DEEP_DEPLOYMENT:
case RCAM_DISRUPT_ASD:
case RCAM_FORGE_TRANSPORT_ORDERS:
case RCAM_GET_ENEMY_MOVEMENT_TARGETS:
case RCAM_IMPROVE_LOCAL_SHOPS:
case RCAM_REDUCE_STRATEGIC_DECISION_SPEED:
@@ -4926,7 +4966,15 @@ void HandleStrategicEvent(const UINT32 eventParam)
if (validMission)
{
const UINT32 activatedMissionParam = SerialiseMissionSecondEvent(evt1.sentGenericRebelAgent, evt1.mercProfileId, mission, extraBits);
AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * evt1.missionDurationInHours, activatedMissionParam);
if (mission == RCAM_FORGE_TRANSPORT_ORDERS)
{
// don't send a follow-up event for instant-result missions
}
else
{
AddStrategicEvent(EVENT_REBELCOMMAND, GetWorldTotalMin() + 60 * evt1.missionDurationInHours, activatedMissionParam);
missionMap.insert(std::make_pair(mission, activatedMissionParam));
}
if (!evt1.sentGenericRebelAgent)
{
@@ -4935,6 +4983,11 @@ void HandleStrategicEvent(const UINT32 eventParam)
SOLDIERTYPE* pSoldier = MercPtrs[i];
if (pSoldier->ubProfile == evt1.mercProfileId)
{
if (mission == RCAM_FORGE_TRANSPORT_ORDERS)
{
ForceDeployTransportGroup(SECTOR(pSoldier->sSectorX, pSoldier->sSectorY));
}
// mission successful! give some experience pts
StatChange(pSoldier, LDRAMT, 20, FROM_SUCCESS);
StatChange(pSoldier, WISDOMAMT, 15, FROM_SUCCESS);
@@ -4943,7 +4996,6 @@ void HandleStrategicEvent(const UINT32 eventParam)
}
}
missionMap.insert(std::make_pair(mission, activatedMissionParam));
swprintf(msgBoxText, szRebelCommandText[RCT_MISSION_SUCCESS], szRebelCommandAgentMissionsText[evt1.missionId * 2]);
swprintf(screenMsgText, szRebelCommandText[RCT_MISSION_SUCCESS], szRebelCommandAgentMissionsText[evt1.missionId * 2]);
ScreenMsg(FONT_MCOLOR_LTGREEN, MSG_INTERFACE, screenMsgText);
+1
View File
@@ -78,6 +78,7 @@ enum RebelCommandAgentMissions
RCAM_NONE = -1,
RCAM_DEEP_DEPLOYMENT = 0,
RCAM_DISRUPT_ASD, // only available if ASD enabled
RCAM_FORGE_TRANSPORT_ORDERS,
RCAM_GET_ENEMY_MOVEMENT_TARGETS, // aka Strategic Intel
RCAM_IMPROVE_LOCAL_SHOPS,
RCAM_REDUCE_STRATEGIC_DECISION_SPEED, // aka Slower Strategic Decisions
+3 -3
View File
@@ -246,13 +246,13 @@ BOOLEAN ARMoveBestMilitiaManFromAdjacentSector(INT16 sMapX, INT16 sMapY)
return TRUE;
}
GROUP* GetNonPlayerGroupInSector( INT16 sMapX, INT16 sMapY, UINT8 usTeam )
GROUP* GetNonPlayerGroupInSectorForReinforcement( INT16 sMapX, INT16 sMapY, UINT8 usTeam )
{
GROUP *curr;
curr = gpGroupList;
while( curr )
{
if ( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && curr->usGroupTeam == usTeam && curr->ubGroupID )
if ( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && curr->usGroupTeam == usTeam && curr->ubGroupID && (curr->usGroupTeam != ENEMY_TEAM || curr->pEnemyGroup->ubIntention != TRANSPORT) )
return curr;
curr = curr->next;
}
@@ -280,7 +280,7 @@ UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam
for( ubIndex = 0; ubIndex < ubDirNumber; ++ubIndex )
{
while ( (pGroup = GetNonPlayerGroupInSector( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam )) != NULL )
while ( (pGroup = GetNonPlayerGroupInSectorForReinforcement( SECTORX( pusMoveDir[ubIndex][0] ), SECTORY( pusMoveDir[ubIndex][0] ), usTeam )) != NULL )
{
pGroup->ubPrevX = pGroup->ubSectorX;
pGroup->ubPrevY = pGroup->ubSectorY;
+1 -1
View File
@@ -12,6 +12,6 @@ UINT8 NumEnemiesInFiveSectors( INT16 sMapX, INT16 sMapY );
//For Tactical
UINT8 DoReinforcementAsPendingNonPlayer( INT16 sMapX, INT16 sMapY, UINT8 usTeam );
void AddPossiblePendingMilitiaToBattle();
GROUP* GetNonPlayerGroupInSector( INT16 sMapX, INT16 sMapY, UINT8 usTeam );
GROUP* GetNonPlayerGroupInSectorForReinforcement( INT16 sMapX, INT16 sMapY, UINT8 usTeam );
#endif
+102 -73
View File
@@ -33,6 +33,9 @@
#include "interface dialogue.h"
#include "ASD.h" // added by Flugente
#include "Rebel Command.h"
#include "Game Event Hook.h"
#include "Strategic Town Loyalty.h"
#include "Strategic Transport Groups.h"
#include "GameInitOptionsScreen.h"
@@ -488,7 +491,6 @@ extern INT16 sWorldSectorLocationOfFirstBattle;
void ReassignAIGroup( GROUP **pGroup );
void TransferGroupToPool( GROUP **pGroup );
void SendGroupToPool( GROUP **pGroup );
//Simply orders all garrisons to take troops from the patrol groups and send the closest troops from them. Any garrison,
//whom there request isn't fulfilled (due to lack of troops), will recieve their reinforcements from the queen (P3).
@@ -2418,6 +2420,11 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Strategic5");
}
}
}
else if (pGroup->pEnemyGroup->ubIntention == TRANSPORT)
{
ProcessTransportGroupReachedDestination(pGroup);
return TRUE;
}
else
{ //This is a floating group at his final destination...
if( pGroup->pEnemyGroup->ubIntention != STAGING && pGroup->pEnemyGroup->ubIntention != REINFORCEMENTS )
@@ -3458,7 +3465,7 @@ void EvaluateQueenSituation()
dEnemyGeneralsSpeedupFactor *= RebelCommand::GetStrategicDecisionSpeedModifier();
uiOffset += dEnemyGeneralsSpeedupFactor * (zDiffSetting[gGameOptions.ubDifficultyLevel].iBaseDelayInMinutesBetweenEvaluations + Random( zDiffSetting[gGameOptions.ubDifficultyLevel].iEvaluationDelayVariance ));
// Check/update reinforcements pool if old behavior is enabled
if ( !gfUnlimitedTroops && zDiffSetting[gGameOptions.ubDifficultyLevel].iQueenPoolIncrementDaysPerDifficultyLevel == 0 )
{
@@ -3488,88 +3495,88 @@ void EvaluateQueenSituation()
// Gradually promote any remaining admins into troops
UpgradeAdminsToTroops();
if( ( giRequestPoints <= 0 ) || ( ( giReinforcementPoints <= 0 ) && ( giReinforcementPool <= 0 ) ) )
{ //we either have no reinforcements or request for reinforcements.
return;
}
// consider deploying a transport group
ExecuteStrategicAIAction( NPC_ACTION_DEPLOY_TRANSPORT_GROUP, 0, 0 );
// anv: only consider garrisons and patrols that can be reinforced
// otherwise unreinforcable groups will stall the rest, effectively breaking entire system
Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */
for( i = 0; i < giGarrisonArraySize; i++ )
// we either have reinforcements or a request for reinforcements
if (giRequestPoints > 0 && (giReinforcementPoints > 0 || giReinforcementPool > 0))
{
RecalculateGarrisonWeight( i );
iWeight = gGarrisonGroup[ i ].bWeight;
if( iWeight > 0 )
// anv: only consider garrisons and patrols that can be reinforced
// otherwise unreinforcable groups will stall the rest, effectively breaking entire system
Ensure_RepairedGarrisonGroup( &gGarrisonGroup, &giGarrisonArraySize ); /* added NULL fix, 2007-03-03, Sgt. Kolja */
for( i = 0; i < giGarrisonArraySize; i++ )
{
if( !gGarrisonGroup[ i ].ubPendingGroupID &&
EnemyPermittedToAttackSector( NULL, gGarrisonGroup[ i ].ubSectorID ) &&
GarrisonRequestingMinimumReinforcements( i ) )
RecalculateGarrisonWeight( i );
iWeight = gGarrisonGroup[ i ].bWeight;
if( iWeight > 0 )
{
if( ReinforcementsApproved( i, &usDefencePoints ) )
if( !gGarrisonGroup[ i ].ubPendingGroupID &&
EnemyPermittedToAttackSector( NULL, gGarrisonGroup[ i ].ubSectorID ) &&
GarrisonRequestingMinimumReinforcements( i ) )
{
iApplicableGarrisonIds[iApplicableGarrisons] = i;
iApplicableGarrisons++;
iApplicableRequestPoints += gGarrisonGroup[ i ].bWeight;
if( ReinforcementsApproved( i, &usDefencePoints ) )
{
iApplicableGarrisonIds[iApplicableGarrisons] = i;
iApplicableGarrisons++;
iApplicableRequestPoints += gGarrisonGroup[ i ].bWeight;
}
}
}
}
}
for( i = 0; i < giPatrolArraySize; i++ )
{
RecalculatePatrolWeight( i );
iWeight = gPatrolGroup[ i ].bWeight;
if( iWeight > 0 )
for( i = 0; i < giPatrolArraySize; i++ )
{
if( !gPatrolGroup[ i ].ubPendingGroupID && PatrolRequestingMinimumReinforcements( i ) )
RecalculatePatrolWeight( i );
iWeight = gPatrolGroup[ i ].bWeight;
if( iWeight > 0 )
{
iApplicablePatrolIds[iApplicablePatrols] = i;
iApplicablePatrols++;
iApplicableRequestPoints += gPatrolGroup[ i ].bWeight;
if( !gPatrolGroup[ i ].ubPendingGroupID && PatrolRequestingMinimumReinforcements( i ) )
{
iApplicablePatrolIds[iApplicablePatrols] = i;
iApplicablePatrols++;
iApplicableRequestPoints += gPatrolGroup[ i ].bWeight;
}
}
}
}
if( !iApplicableRequestPoints )
{
return;
}
//now randomly choose who gets the reinforcements.
// giRequestPoints is the combined sum of all the individual weights of all garrisons and patrols requesting reinforcements
//iRandom = Random( giRequestPoints );
iRandom = Random( iApplicableRequestPoints );
iOrigRequestPoints = giRequestPoints; // debug only!
//go through garrisons first
for( i = 0; i < iApplicableGarrisons; i++ )
{
iSumOfAllWeights += iWeight; // debug only!
iWeight = gGarrisonGroup[ iApplicableGarrisonIds[i] ].bWeight;
if( iRandom < iWeight )
if( iApplicableRequestPoints )
{
//This is the group that gets the reinforcements!
if ( SendReinforcementsForGarrison( iApplicableGarrisonIds[i] , usDefencePoints, NULL ) )
return;
}
iRandom -= iWeight;
}
//now randomly choose who gets the reinforcements.
// giRequestPoints is the combined sum of all the individual weights of all garrisons and patrols requesting reinforcements
//iRandom = Random( giRequestPoints );
iRandom = Random( iApplicableRequestPoints );
//go through the patrol groups
for( i = 0; i < iApplicablePatrols; i++ )
{
iSumOfAllWeights += iWeight; // debug only!
iWeight = gPatrolGroup[ iApplicablePatrolIds[i] ].bWeight;
if( iRandom < iWeight )
{
//This is the group that gets the reinforcements!
if ( SendReinforcementsForPatrol( iApplicablePatrolIds[i], NULL ) )
return;
iOrigRequestPoints = giRequestPoints; // debug only!
//go through garrisons first
for( i = 0; i < iApplicableGarrisons; i++ )
{
iSumOfAllWeights += iWeight; // debug only!
iWeight = gGarrisonGroup[ iApplicableGarrisonIds[i] ].bWeight;
if( iRandom < iWeight )
{
//This is the group that gets the reinforcements!
if ( SendReinforcementsForGarrison( iApplicableGarrisonIds[i] , usDefencePoints, NULL ) )
return;
}
iRandom -= iWeight;
}
//go through the patrol groups
for( i = 0; i < iApplicablePatrols; i++ )
{
iSumOfAllWeights += iWeight; // debug only!
iWeight = gPatrolGroup[ iApplicablePatrolIds[i] ].bWeight;
if( iRandom < iWeight )
{
//This is the group that gets the reinforcements!
if ( SendReinforcementsForPatrol( iApplicablePatrolIds[i], NULL ) )
return;
}
iRandom -= iWeight;
}
}
iRandom -= iWeight;
}
ValidateWeights( 27 );
@@ -5125,7 +5132,7 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
if ( ubNumSoldiers )
{
InitializeGroup(GROUP_TYPE_ATTACK, ubNumSoldiers, grouptroops[0], groupelites[0], grouprobots[0], groupjeeps[0], grouptanks[0], Random(10) < difficultyMod);
totalusedsoldiers += grouptroops[0] + groupelites[0] + grouprobots[0], grouptanks[0] + groupjeeps[0];
totalusedsoldiers += grouptroops[0] + groupelites[0] + grouprobots[0] + grouptanks[0] + groupjeeps[0];
}
pGroup = CreateNewEnemyGroupDepartingFromSector( SECTOR( gModSettings.ubSAISpawnSectorX, gModSettings.ubSAISpawnSectorY ), 0, grouptroops[0], groupelites[0], grouprobots[0], grouptanks[0], groupjeeps[0] );
@@ -5386,6 +5393,14 @@ void ExecuteStrategicAIAction( UINT16 usActionCode, INT16 sSectorX, INT16 sSecto
gubNumAwareBattles = zDiffSetting[gGameOptions.ubDifficultyLevel].iNumAwareBattles;
break;
case NPC_ACTION_DEPLOY_TRANSPORT_GROUP:
DeployTransportGroup();
break;
case NPC_ACTION_RETURN_TRANSPORT_GROUP:
ReturnTransportGroup(option1);
break;
default:
ScreenMsg( FONT_RED, MSG_DEBUG, L"QueenAI failed to handle action code %d.", usActionCode );
break;
@@ -6403,8 +6418,14 @@ void UpgradeAdminsToTroops()
// if there are any admins currently in this group
if ( pGroup->pEnemyGroup->ubNumAdmins > 0 )
{
// skip transport groups
if (pGroup->pEnemyGroup->ubIntention == TRANSPORT)
{
pGroup = pGroup->next;
continue;
}
// if it's a patrol group
if ( pGroup->pEnemyGroup->ubIntention == PATROL )
else if ( pGroup->pEnemyGroup->ubIntention == PATROL )
{
sPatrolIndex = FindPatrolGroupIndexForGroupID( pGroup->ubGroupID );
Assert( sPatrolIndex != -1 );
@@ -6508,9 +6529,17 @@ INT16 FindGarrisonIndexForGroupIDPending( UINT8 ubGroupID )
void TransferGroupToPool( GROUP **pGroup )
{
//Madd: unlimited reinforcements?
if ( !gfUnlimitedTroops )
giReinforcementPool += (*pGroup)->ubGroupSize;
if ((*pGroup)->usGroupTeam == ENEMY_TEAM)
{
//Madd: unlimited reinforcements?
if ( !gfUnlimitedTroops )
giReinforcementPool += (*pGroup)->ubGroupSize;
AddStrategicAIResources(ASD_ROBOT, (*pGroup)->pEnemyGroup->ubNumRobots);
AddStrategicAIResources(ASD_JEEP, (*pGroup)->pEnemyGroup->ubNumJeeps);
AddStrategicAIResources(ASD_TANK, (*pGroup)->pEnemyGroup->ubNumTanks);
}
RemovePGroup( *pGroup );
*pGroup = NULL;
+3 -1
View File
@@ -38,6 +38,7 @@ BOOLEAN StrategicAILookForAdjacentGroups( GROUP *pGroup );
void RemoveGroupFromStrategicAILists( UINT8 ubGroupID );
void RecalculateSectorWeight( UINT8 ubSectorID );
void RecalculateGroupWeight( GROUP *pGroup );
void SendGroupToPool( GROUP **pGroup );
BOOLEAN OkayForEnemyToMoveThroughSector( UINT8 ubSectorID );
BOOLEAN EnemyPermittedToAttackSector( GROUP **pGroup, UINT8 ubSectorID );
@@ -78,7 +79,8 @@ BOOLEAN PermittedToFillPatrolGroup( INT32 iPatrolID );
enum GROUP_TYPE
{
GROUP_TYPE_ATTACK,
GROUP_TYPE_PATROL
GROUP_TYPE_PATROL,
GROUP_TYPE_TRANSPORT
};
void ASDInitializePatrolGroup(GROUP *pGroup);
+12 -1
View File
@@ -50,6 +50,7 @@
#include "Creature Spreading.h" // added by Flugente
#include "MilitiaIndividual.h" // added by Flugente
#include "Rebel Command.h"
#include "Strategic Transport Groups.h"
#include "MilitiaSquads.h"
#include "Vehicles.h"
@@ -3635,7 +3636,10 @@ INT32 GetSectorMvtTimeForGroup( UINT8 ubSector, UINT8 ubDirection, GROUP *pGroup
dEnemyGeneralsSpeedupFactor = max( 0.75f, dEnemyGeneralsSpeedupFactor - gStrategicStatus.usVIPsLeft * gGameExternalOptions.fEnemyGeneralStrategicMovementSpeedBonus );
}
iBestTraverseTime = dEnemyGeneralsSpeedupFactor * iBestTraverseTime;
// rftr: transport groups move slower than normal
const FLOAT transportSpeedFactor = pGroup->pEnemyGroup->ubIntention == TRANSPORT ? 2.0f : 1.0f;
iBestTraverseTime = dEnemyGeneralsSpeedupFactor * transportSpeedFactor * iBestTraverseTime;
iBestTraverseTime = iBestTraverseTime * (100 + RebelCommand::GetHarriersSpeedPenalty(ubSector)) / 100;
}
@@ -3816,6 +3820,13 @@ void HandleArrivalOfReinforcements( GROUP *pGroup )
ResetMortarsOnTeamCount();
ResetNumSquadleadersInArmyGroup(); // added by SANDRO
AddPossiblePendingEnemiesToBattle();
if (pGroup->pEnemyGroup->ubIntention == TRANSPORT)
{
// normally, transport groups can't reinforce, but this can be hit normally if a battle is occuring in a sector
// where a transport group is moving into.
UpdateTransportGroupInventory();
}
}
else if ( pGroup->usGroupTeam == MILITIA_TEAM )
{
+4
View File
@@ -15,6 +15,7 @@ enum //enemy intentions,
PATROL, //enemy is moving around determining safe areas.
REINFORCEMENTS, //enemy group has intentions to fortify position at final destination.
ASSAULT, //enemy is ready to fight anything they encounter.
TRANSPORT, //rftr: enemy is carrying out non-combat tasks, but still has an escort
NUM_ENEMY_INTENTIONS
};
@@ -109,6 +110,9 @@ typedef struct ENEMYGROUP
#define GROUPFLAG_KNOWN_DIRECTION 0x00000080
#define GROUPFLAG_KNOWN_NUMBER 0x00000100
// rftr: strategic transport group direction flag
#define GROUPFLAG_TRANSPORT_ENROUTE 0x00000200
typedef struct GROUP
{
BOOLEAN fDebugGroup; //for testing purposes -- handled differently in certain cases.
File diff suppressed because it is too large Load Diff
+31
View File
@@ -0,0 +1,31 @@
#ifndef _STRATEGIC_TRANSPORT_GROUPS_H
#define _STRATEGIC_TRANSPORT_GROUPS_H
#include "Campaign Types.h"
#include "Types.h"
#include <map>
enum TransportGroupSectorInfo
{
TransportGroupSectorInfo_LocatedGroup = 0,
TransportGroupSectorInfo_LocatedDestination,
};
struct GROUP;
BOOLEAN DeployTransportGroup();
BOOLEAN ForceDeployTransportGroup(UINT8 sectorId);
BOOLEAN ReturnTransportGroup(INT32 groupId);
void FillMapColoursForTransportGroups(INT32(&colorMap)[MAXIMUM_VALID_Y_COORDINATE][MAXIMUM_VALID_X_COORDINATE]);
void ProcessTransportGroupReachedDestination(GROUP* pGroup);
void UpdateTransportGroupInventory();
const std::map<UINT8, TransportGroupSectorInfo> GetTransportGroupSectorInfo();
void AddToTransportGroupMap(UINT8 groupId, int soldierClass, UINT8 amount);
void ClearTransportGroupMap();
void NotifyTransportGroupDefeated();
#endif