1 #ifndef __STRATEGIC_MOVEMENT_H 2 #define __STRATEGIC_MOVEMENT_H 3 4 #include "Debug.h" 5 #include "Types.h" 6 7 struct SOLDIERTYPE; 8 9 10 enum //enemy intentions, 11 { 12 NO_INTENTIONS, //enemy intentions are undefined. 13 PURSUIT, //enemy group has spotted a player group and is pursuing them. If they lose the player group, they 14 //will get reassigned. 15 STAGING, //enemy is prepare to assault a town sector, but doesn't have enough troops. 16 PATROL, //enemy is moving around determining safe areas. 17 REINFORCEMENTS, //enemy group has intentions to fortify position at final destination. 18 ASSAULT, //enemy is ready to fight anything they encounter. 19 NUM_ENEMY_INTENTIONS 20 }; 21 22 enum //move types 23 { 24 ONE_WAY, //from first waypoint to last, deleting each waypoint as they are reached. 25 CIRCULAR, //from first to last, recycling forever. 26 ENDTOEND_FORWARDS, //from first to last -- when reaching last, change to backwards. 27 ENDTOEND_BACKWARDS //from last to first -- when reaching first, change to forwards. 28 }; 29 30 enum 31 { 32 NORTH_STRATEGIC_MOVE, 33 EAST_STRATEGIC_MOVE, 34 SOUTH_STRATEGIC_MOVE, 35 WEST_STRATEGIC_MOVE, 36 THROUGH_STRATEGIC_MOVE 37 }; 38 39 //This structure contains all of the information about a group moving in the strategic 40 //layer. This includes all troops, equipment, and waypoints, and location. 41 //NOTE: This is used for groups that are initiating a movement to another sector. 42 struct WAYPOINT 43 { 44 UINT8 x; //sector x position of waypoint 45 UINT8 y; //sector y position of waypoint 46 WAYPOINT* next; //next waypoint in list 47 }; 48 49 50 struct PLAYERGROUP 51 { 52 SOLDIERTYPE *pSoldier; //direct access to the soldier pointer 53 PLAYERGROUP* next; //next player in list 54 }; 55 56 57 struct ENEMYGROUP 58 { 59 UINT8 ubNumTroops; //number of regular troops in the group 60 UINT8 ubNumElites; //number of elite troops in the group 61 UINT8 ubNumAdmins; //number of administrators in the group 62 UINT8 ubPendingReinforcements;//This group is waiting for reinforcements before attacking or attempting to fortify newly aquired sector. 63 UINT8 ubAdminsInBattle; //number of administrators in currently in battle. 64 UINT8 ubIntention; //the type of group this is: patrol, assault, spies, etc. 65 UINT8 ubTroopsInBattle; //number of soldiers currently in battle. 66 UINT8 ubElitesInBattle; //number of elite soldiers currently in battle. 67 }; 68 69 70 //NOTE: ALL FLAGS ARE CLEARED WHENEVER A GROUP ARRIVES IN A SECTOR, OR ITS WAYPOINTS ARE 71 // DELETED!!! 72 #define GROUPFLAG_SIMULTANEOUSARRIVAL_APPROVED 0x00000001 73 #define GROUPFLAG_SIMULTANEOUSARRIVAL_CHECKED 0x00000002 74 //I use this flag when traversing through a list to determine which groups meet whatever conditions, 75 //then add this marker flag. The second time I traverse the list, I simply check for this flag, 76 //apply my modifications to the group, and remove the flag. If you decide to use it, make sure the 77 //flag is cleared. 78 #define GROUPFLAG_MARKER 0x00000004 79 //Set whenever a group retreats from battle. If the group arrives in the next sector and enemies are there 80 //retreat will not be an option. 81 #define GROUPFLAG_JUST_RETREATED_FROM_BATTLE 0x00000008 82 #define GROUPFLAG_HIGH_POTENTIAL_FOR_AMBUSH 0x00000010 83 #define GROUPFLAG_GROUP_ARRIVED_SIMULTANEOUSLY 0x00000020 84 85 86 struct GROUP 87 { 88 BOOLEAN fDebugGroup; //for testing purposes -- handled differently in certain cases. 89 BOOLEAN fPlayer; //set if this is a player controlled group. 90 BOOLEAN fVehicle; //vehicle controlled group? 91 BOOLEAN fPersistant; //This flag when set prevents the group from being automatically deleted when it becomes empty. 92 UINT8 ubGroupID; //the unique ID of the group (used for hooking into events and SOLDIERTYPE) 93 UINT8 ubGroupSize; //total number of individuals in the group. 94 UINT8 ubSectorX, ubSectorY; //last/curr sector occupied 95 UINT8 ubSectorZ; 96 UINT8 ubNextX, ubNextY; //next sector destination 97 UINT8 ubPrevX, ubPrevY; //prev sector occupied (could be same as ubSectorX/Y) 98 UINT8 ubOriginalSector; //sector where group was created. 99 BOOLEAN fBetweenSectors; //set only if a group is between sector. 100 UINT8 ubMoveType; //determines the type of movement (ONE_WAY, CIRCULAR, ENDTOEND, etc.) 101 UINT8 ubNextWaypointID; //the ID of the next waypoint 102 UINT32 uiArrivalTime; //the arrival time in world minutes that the group will arrive at the next sector. This should not be set directly; use setArrivalTime instead 103 UINT32 uiTraverseTime; //the total traversal time from the previous sector to the next sector. 104 WAYPOINT *pWaypoints; //a list of all of the waypoints in the groups movement. 105 UINT8 ubTransportationMask; //the mask combining all of the groups transportation methods. 106 UINT32 uiFlags; //various conditions that apply to the group 107 UINT8 ubCreatedSectorID; //used for debugging strategic AI for keeping track of the sector ID a group was created in. 108 UINT8 ubSectorIDOfLastReassignment; //used for debuggin strategic AI. Records location of any reassignments. 109 110 union 111 { 112 PLAYERGROUP *pPlayerList; //list of players in the group 113 ENEMYGROUP *pEnemyGroup; //a structure containing general enemy info 114 }; 115 GROUP* next; //next group 116 117 // ARM: centralized it so we can do a comprehensive Assert on it. Causing problems with helicopter group! 118 void setArrivalTime(UINT32 time); 119 }; 120 121 122 extern GROUP *gpGroupList; 123 124 125 #define BASE_FOR_EACH_GROUP(type, iter) \ 126 for (type iter = gpGroupList; iter != NULL; iter = iter->next) 127 #define FOR_EACH_GROUP(iter) BASE_FOR_EACH_GROUP( GROUP*, iter) 128 #define CFOR_EACH_GROUP(iter) BASE_FOR_EACH_GROUP(const GROUP*, iter) 129 130 #define BASE_FOR_EACH_ENEMY_GROUP(type, iter) \ 131 BASE_FOR_EACH_GROUP(type, iter) \ 132 if (iter->fPlayer) continue; else 133 #define FOR_EACH_ENEMY_GROUP(iter) BASE_FOR_EACH_ENEMY_GROUP( GROUP*, iter) 134 #define CFOR_EACH_ENEMY_GROUP(iter) BASE_FOR_EACH_ENEMY_GROUP(const GROUP*, iter) 135 136 #define BASE_FOR_EACH_PLAYER_GROUP(type, iter) \ 137 BASE_FOR_EACH_GROUP(type, iter) \ 138 if (!iter->fPlayer) continue; else 139 #define FOR_EACH_PLAYER_GROUP(iter) BASE_FOR_EACH_PLAYER_GROUP( GROUP*, iter) 140 #define CFOR_EACH_PLAYER_GROUP(iter) BASE_FOR_EACH_PLAYER_GROUP(const GROUP*, iter) 141 142 #define FOR_EACH_GROUP_SAFE(iter) \ 143 for (GROUP* iter = gpGroupList, * iter##__next; iter != NULL; iter = iter##__next) \ 144 if (iter##__next = iter->next, FALSE) {} else \ 145 146 147 #define CFOR_EACH_PLAYER_IN_GROUP(iter, group) \ 148 for (PLAYERGROUP const* iter = (Assert((group)->fPlayer), (group)->pPlayerList); iter; iter = iter->next) 149 150 151 //General utility functions 152 void RemoveAllGroups(void); 153 GROUP* GetGroup( UINT8 ubGroupID ); 154 155 /* Remove a group from the list. This removes all of the waypoints as well as 156 * the members of the group. Calling this function doesn't position them in a 157 * sector. It is up to you to do that. The event system will automatically 158 * handle their updating as they arrive in sectors. */ 159 void RemoveGroup(GROUP&); 160 161 /* Clear a group's waypoints. This is necessary when sending new orders such as 162 * different routes. */ 163 void RemoveGroupWaypoints(GROUP&); 164 165 //Player grouping functions 166 167 /* Create a new player group. This is the first step before adding waypoints 168 * and members to the player group. */ 169 GROUP* CreateNewPlayerGroupDepartingFromSector(UINT8 ubSectorX, UINT8 ubSectorY); 170 171 //Allows you to add or remove players from the group. 172 void AddPlayerToGroup(GROUP&, SOLDIERTYPE&); 173 174 void RemovePlayerFromGroup(SOLDIERTYPE&); 175 void RemovePlayerFromPGroup(GROUP&, SOLDIERTYPE&); 176 177 // create a vehicle group, it is by itself, 178 GROUP* CreateNewVehicleGroupDepartingFromSector(UINT8 ubSectorX, UINT8 ubSectorY); 179 180 181 //Appends a waypoint to the end of the list. Waypoint MUST be on the 182 //same horizontal xor vertical level as the last waypoint added. 183 BOOLEAN AddWaypointToPGroup( GROUP *pGroup, UINT8 ubSectorX, UINT8 ubSectorY ); 184 //Same, but uses a plain sectorID (0-255) 185 BOOLEAN AddWaypointIDToPGroup( GROUP *pGroup, UINT8 ubSectorID ); 186 //Same, but uses a strategic sectorID 187 BOOLEAN AddWaypointStrategicIDToPGroup( GROUP *pGroup, UINT32 uiSectorID ); 188 189 //Enemy grouping functions -- private use by the strategic AI. 190 //............................................................ 191 GROUP* CreateNewEnemyGroupDepartingFromSector( UINT32 uiSector, UINT8 ubNumAdmins, UINT8 ubNumTroops, UINT8 ubNumElites ); 192 193 /* Arrival callback -- None of these functions should be called directly. 194 * This is called whenever any group arrives in the next sector (player or 195 * enemy). This function will first check to see if a battle should start, or if 196 * they aren't at the final destination, they will move to the next sector. */ 197 void GroupArrivedAtSector(GROUP&, BOOLEAN check_for_battle, BOOLEAN never_left); 198 void CalculateNextMoveIntention( GROUP *pGroup ); 199 200 201 // Set current sector of the group, used for player controlled mercs 202 void SetGroupSectorValue(INT16 x, INT16 y, INT16 z, GROUP&); 203 204 void SetEnemyGroupSector(GROUP&, UINT8 sector_id); 205 206 207 // calculate the eta time in world total mins of this group 208 INT32 CalculateTravelTimeOfGroup(GROUP const*); 209 210 static UINT32 const TRAVERSE_TIME_IMPOSSIBLE = 0xFFFFFFFF; 211 212 // Get travel time for this group 213 INT32 GetSectorMvtTimeForGroup(UINT8 ubSector, UINT8 ubDirection, GROUP const*); 214 215 UINT8 PlayerMercsInSector( UINT8 ubSectorX, UINT8 ubSectorY, UINT8 ubSectorZ ); 216 UINT8 PlayerGroupsInSector( UINT8 ubSectorX, UINT8 ubSectorY, UINT8 ubSectorZ ); 217 218 // Is this player group in motion? 219 BOOLEAN PlayerGroupInMotion(GROUP const*); 220 221 // Is the player greoup with this id in motion 222 bool PlayerIDGroupInMotion(UINT8 id); 223 224 // get number of mercs between sectors 225 BOOLEAN PlayersBetweenTheseSectors( INT16 sSource, INT16 sDest, INT32 *iCountEnter, INT32 *iCountExit, BOOLEAN *fAboutToArriveEnter ); 226 227 void MoveAllGroupsInCurrentSectorToSector( UINT8 ubSectorX, UINT8 ubSectorY, UINT8 ubSectorZ ); 228 229 //Save the strategic movemnet Group paths to the saved game file 230 void SaveStrategicMovementGroupsToSaveGameFile(HWFILE); 231 232 //Load the strategic movement Group paths from the saved game file 233 void LoadStrategicMovementGroupsFromSavedGameFile(HWFILE); 234 235 void HandleArrivalOfReinforcements(GROUP const*); 236 237 //Called when all checks have been made for the group (if possible to retreat, etc.) This function 238 //blindly determines where to move the group. 239 void RetreatGroupToPreviousSector(GROUP&); 240 241 GROUP* FindEnemyMovementGroupInSector(UINT8 x, UINT8 y); 242 GROUP* FindPlayerMovementGroupInSector(UINT8 x, UINT8 y); 243 244 BOOLEAN GroupAtFinalDestination(const GROUP*); 245 246 // find the travel time between waypts for this group 247 INT32 FindTravelTimeBetweenWaypoints(WAYPOINT const* pSource, WAYPOINT const* pDest, GROUP const*); 248 249 BOOLEAN GroupReversingDirectionsBetweenSectors( GROUP *pGroup, UINT8 ubSectorX, UINT8 ubSectorY, BOOLEAN fBuildingWaypoints ); 250 BOOLEAN GroupBetweenSectorsAndSectorXYIsInDifferentDirection( GROUP *pGroup, UINT8 ubSectorX, UINT8 ubSectorY ); 251 252 WAYPOINT* GetFinalWaypoint(const GROUP*); 253 254 void ResetMovementForEnemyGroupsInLocation( UINT8 ubSectorX, UINT8 ubSectorY ); 255 256 //Determines if any particular group WILL be moving through a given sector given it's current 257 //position in the route and TREATS the pGroup->ubMoveType as ONE_WAY EVEN IF IT ISN'T. If the 258 //group is currently IN the sector, or just left the sector, it will return FALSE. 259 BOOLEAN GroupWillMoveThroughSector( GROUP *pGroup, UINT8 ubSectorX, UINT8 ubSectorY ); 260 261 void RandomizePatrolGroupLocation( GROUP *pGroup ); 262 263 void PlaceGroupInSector(GROUP&, INT16 prev_x, INT16 prev_y, INT16 next_x, INT16 next_y, INT8 z, bool check_for_battle); 264 265 void PlayerGroupArrivedSafelyInSector(GROUP&, BOOLEAN fCheckForNPCs); 266 267 bool DoesPlayerExistInPGroup(GROUP const&, SOLDIERTYPE const&); 268 269 bool GroupHasInTransitDeadOrPOWMercs(GROUP const&); 270 271 void AddFuelToVehicle(SOLDIERTYPE* pSoldier, SOLDIERTYPE* pVehicle); 272 273 void CalculateGroupRetreatSector(GROUP*); 274 275 void UpdatePersistantGroupsFromOldSave(UINT32 uiSavedGameVersion); 276 277 extern BOOLEAN gfUndergroundTacticalTraversal; 278 279 #endif 280