Files
source/Strategic/Campaign Init.cpp
T

374 lines
12 KiB
C++

#ifdef PRECOMPILEDHEADERS
#include "Strategic All.h"
#else
#include "types.h"
#include "Campaign Init.h"
#include "Random.h"
#include "Campaign Types.h"
#include "Queen Command.h"
#include "overhead.h"
#include "Strategic Movement.h"
#include "Strategic Status.h"
#include "GameSettings.h"
#include "Creature Spreading.h"
#include "Strategic AI.h"
#endif
extern void InitStrategicMovementCosts();
void InitKnowFacilitiesFlags( );
UNDERGROUND_SECTORINFO* gpUndergroundSectorInfoTail = NULL;
UNDERGROUND_SECTORINFO* NewUndergroundNode( UINT8 ubSectorX, UINT8 ubSectorY, UINT8 ubSectorZ )
{
UNDERGROUND_SECTORINFO *curr;
curr = (UNDERGROUND_SECTORINFO*)MemAlloc( sizeof( UNDERGROUND_SECTORINFO ) );
AssertMsg( curr, "Failed to create an underground sector info node." );
memset( curr, 0, sizeof( UNDERGROUND_SECTORINFO ) );
curr->ubSectorX = ubSectorX;
curr->ubSectorY = ubSectorY;
curr->ubSectorZ = ubSectorZ;
if( gpUndergroundSectorInfoTail )
{
gpUndergroundSectorInfoTail->next = curr;
gpUndergroundSectorInfoTail = gpUndergroundSectorInfoTail->next;
}
else
{
gpUndergroundSectorInfoHead = curr;
gpUndergroundSectorInfoTail = gpUndergroundSectorInfoHead;
}
return curr;
}
// setup which know facilities are in which cities
void InitKnowFacilitiesFlags( )
{
SECTORINFO *pSector;
// Cambria hospital
pSector = &SectorInfo[SEC_G8];
pSector->uiFacilitiesFlags |= SFCF_HOSPITAL;
pSector = &SectorInfo[SEC_F8];
pSector->uiFacilitiesFlags |= SFCF_HOSPITAL;
pSector = &SectorInfo[SEC_G9];
pSector->uiFacilitiesFlags |= SFCF_HOSPITAL;
pSector = &SectorInfo[SEC_F9];
pSector->uiFacilitiesFlags |= SFCF_HOSPITAL;
// Drassen airport
pSector = &SectorInfo[SEC_B13];
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
pSector = &SectorInfo[SEC_C13];
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
pSector = &SectorInfo[SEC_D13];
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
// Meduna airport & military complex
pSector = &SectorInfo[SEC_N3];
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
pSector = &SectorInfo[SEC_N4];
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
pSector = &SectorInfo[SEC_N5];
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
pSector = &SectorInfo[SEC_O3];
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
pSector = &SectorInfo[SEC_O4];
pSector->uiFacilitiesFlags |= SFCF_AIRPORT;
return;
}
void InitMiningLocations()
{
SECTORINFO *pSector;
//Set up mining sites
pSector = &SectorInfo[SEC_D4];
pSector->uiFlags |= SF_MINING_SITE;
// pSector->ubIncomeValue = 33;
pSector = &SectorInfo[SEC_D13];
pSector->uiFlags |= SF_MINING_SITE;
// pSector->ubIncomeValue = 41;
pSector = &SectorInfo[SEC_B2];
pSector->uiFlags |= SF_MINING_SITE;
// pSector->ubIncomeValue = 20;
pSector = &SectorInfo[SEC_H8];
pSector->uiFlags |= SF_MINING_SITE;
// pSector->ubIncomeValue = 64;
pSector = &SectorInfo[SEC_I14];
pSector->uiFlags |= SF_MINING_SITE;
// pSector->ubIncomeValue = 80;
//Grumm
pSector = &SectorInfo[SEC_H3];
pSector->uiFlags |= SF_MINING_SITE;
// pSector->ubIncomeValue = 100;
}
//Mobile groups are handled separately from sectors, because they are on the move.
void GeneratePatrolGroups()
{
GROUP *pGroup;
UINT8 ubNumTroops;
ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_C7, 0, ubNumTroops, 0 );
pGroup->ubTransportationMask = CAR;
AddWaypointToPGroup( pGroup, 8, 3 ); //C8
AddWaypointToPGroup( pGroup, 7, 3 ); //C7
ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_D9, 0, ubNumTroops, 0 );
AddWaypointToPGroup( pGroup, 9, 5 ); //E9
AddWaypointToPGroup( pGroup, 9, 4 ); //D9
pGroup->ubTransportationMask = TRUCK;
ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_B9, 0, ubNumTroops, 0 );
AddWaypointToPGroup( pGroup, 12, 2 ); //B12
AddWaypointToPGroup( pGroup, 9, 2 ); //B9
pGroup->ubTransportationMask = FOOT;
ubNumTroops = (UINT8)(3 + gGameOptions.ubDifficultyLevel + Random( 3 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_A14, 0, ubNumTroops, 0 );
pGroup->ubMoveType = ENDTOEND_FORWARDS;
AddWaypointToPGroup( pGroup, 13, 1 ); //A13
AddWaypointToPGroup( pGroup, 15, 1 ); //A15
AddWaypointToPGroup( pGroup, 15, 5 ); //E15
AddWaypointToPGroup( pGroup, 13, 5 ); //E13
AddWaypointToPGroup( pGroup, 12, 5 ); //E12
AddWaypointToPGroup( pGroup, 12, 3 ); //C12
pGroup->ubTransportationMask = TRACKED;
ubNumTroops = (UINT8)(5 + gGameOptions.ubDifficultyLevel * 2 + Random( 4 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N6, 0, ubNumTroops, 0 );
AddWaypointToPGroup( pGroup, 9, 14 ); //N9
AddWaypointToPGroup( pGroup, 6, 14 ); //N6
pGroup->ubTransportationMask = CAR;
ubNumTroops = (UINT8)(5 + gGameOptions.ubDifficultyLevel * 2 + Random( 4 ));
pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_N10, 0, ubNumTroops, 0 );
AddWaypointToPGroup( pGroup, 10, 11 ); //K10
AddWaypointToPGroup( pGroup, 10, 14 ); //N10
pGroup->ubTransportationMask = CAR;
}
void TrashUndergroundSectorInfo()
{
UNDERGROUND_SECTORINFO *curr;
while( gpUndergroundSectorInfoHead )
{
curr = gpUndergroundSectorInfoHead;
gpUndergroundSectorInfoHead = gpUndergroundSectorInfoHead->next;
MemFree( curr );
}
gpUndergroundSectorInfoHead = NULL;
gpUndergroundSectorInfoTail = NULL;
}
//Defines the sectors that can be occupied by enemies, creatures, etc. It also
//contains the network of cave connections critical for strategic creature spreading, as we can't
//know how the levels connect without loading the maps. This is completely hardcoded, and any
//changes to the maps, require changes accordingly.
void BuildUndergroundSectorInfoList()
{
UNDERGROUND_SECTORINFO *curr;
SECTORINFO *pSector = NULL;
TrashUndergroundSectorInfo();
//********************
//* BASEMENT LEVEL 1 *
//********************
//Miguel's basement. Nothing here.
curr = NewUndergroundNode( 10, 1, 1 );
//Chitzena mine. Nothing here.
curr = NewUndergroundNode( 2, 2, 1 );
//San mona mine. Nothing here.
curr = NewUndergroundNode( 4, 4, 1 );
curr = NewUndergroundNode( 5, 4, 1 );
//J9
curr = NewUndergroundNode( 9, 10, 1 );
switch( gGameOptions.ubDifficultyLevel )
{
case DIF_LEVEL_EASY:
curr->ubNumTroops = 8;
break;
case DIF_LEVEL_MEDIUM:
curr->ubNumTroops = 11;
break;
case DIF_LEVEL_HARD:
curr->ubNumTroops = 15;
break;
case DIF_LEVEL_INSANE:
curr->ubNumTroops = 20;
break;
}
//J9 feeding zone
curr = NewUndergroundNode( 9, 10, 2 );
curr->ubNumCreatures = (UINT8)(2 + gGameOptions.ubDifficultyLevel*2 + Random( 2 ));
//K4
curr = NewUndergroundNode( 4, 11, 1 );
curr->ubNumTroops = (UINT8)(6 + gGameOptions.ubDifficultyLevel*2 + Random( 3 ));
curr->ubNumElites = (UINT8)(4 + gGameOptions.ubDifficultyLevel + Random( 2 ));
//O3
curr = NewUndergroundNode( 3, 15, 1 );
curr->ubNumTroops = (UINT8)(6 + gGameOptions.ubDifficultyLevel*2 + Random( 3 ));
curr->ubNumElites = (UINT8)(4 + gGameOptions.ubDifficultyLevel + Random( 2 ));
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
//P3
curr = NewUndergroundNode( 3, 16, 1 );
switch( gGameOptions.ubDifficultyLevel )
{
case DIF_LEVEL_EASY:
curr->ubNumElites = (UINT8)(8 + Random( 3 ));
break;
case DIF_LEVEL_MEDIUM:
curr->ubNumElites = (UINT8)(10 + Random( 5 ));
break;
case DIF_LEVEL_HARD:
curr->ubNumElites = (UINT8)(14 + Random( 6 ));
break;
case DIF_LEVEL_INSANE:
curr->ubNumElites = 20;
break;
}
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//Do all of the mandatory underground mine sectors
//Drassen's mine
//D13_B1
curr = NewUndergroundNode( 13, 4, 1 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
//E13_B1
curr = NewUndergroundNode( 13, 5, 1 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//E13_B2
curr = NewUndergroundNode( 13, 5, 2 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
//F13_B2
curr = NewUndergroundNode( 13, 6, 2 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR | SOUTH_ADJACENT_SECTOR;
//G13_B2
curr = NewUndergroundNode( 13, 7, 2 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//G13_B3
curr = NewUndergroundNode( 13, 7, 3 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//F13_B3
curr = NewUndergroundNode( 13, 6, 3 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
//Cambria's mine
//H8_B1
curr = NewUndergroundNode( 8, 8, 1 );
curr->ubAdjacentSectors |= EAST_ADJACENT_SECTOR;
//H9_B1
curr = NewUndergroundNode( 9, 8, 1 );
curr->ubAdjacentSectors |= WEST_ADJACENT_SECTOR;
//H9_B2
curr = NewUndergroundNode( 9, 8, 2 );
curr->ubAdjacentSectors |= WEST_ADJACENT_SECTOR;
//H8_B2
curr = NewUndergroundNode( 8, 8, 2 );
curr->ubAdjacentSectors |= EAST_ADJACENT_SECTOR;
//H8_B3
curr = NewUndergroundNode( 8, 8, 3 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
//I8_B3
curr = NewUndergroundNode( 8, 9, 3 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR | SOUTH_ADJACENT_SECTOR;
//J8_B3
curr = NewUndergroundNode( 8, 10, 3 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//Alma's mine
//I14_B1
curr = NewUndergroundNode( 14, 9, 1 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
//J14_B1
curr = NewUndergroundNode( 14, 10, 1 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//J14_B2
curr = NewUndergroundNode( 14, 10, 2 );
curr->ubAdjacentSectors |= WEST_ADJACENT_SECTOR;
//J13_B2
curr = NewUndergroundNode( 13, 10, 2 );
curr->ubAdjacentSectors |= EAST_ADJACENT_SECTOR;
//J13_B3
curr = NewUndergroundNode( 13, 10, 3 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
//K13_B3
curr = NewUndergroundNode( 13, 11, 3 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//Grumm's mine
//H3_B1
curr = NewUndergroundNode( 3, 8, 1 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
//I3_B1
curr = NewUndergroundNode( 3, 9, 1 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//I3_B2
curr = NewUndergroundNode( 3, 9, 2 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//H3_B2
curr = NewUndergroundNode( 3, 8, 2 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR | EAST_ADJACENT_SECTOR;
//H4_B2
curr = NewUndergroundNode( 4, 8, 2 );
curr->ubAdjacentSectors |= WEST_ADJACENT_SECTOR;
curr->uiFlags |= SF_PENDING_ALTERNATE_MAP;
//H4_B3
curr = NewUndergroundNode( 4, 8, 3 );
curr->ubAdjacentSectors |= NORTH_ADJACENT_SECTOR;
//G4_B3
curr = NewUndergroundNode( 4, 7, 3 );
curr->ubAdjacentSectors |= SOUTH_ADJACENT_SECTOR;
}
//This is the function that is called only once, when the player begins a new game. This will calculate
//starting numbers of the queen's army in various parts of the map, which will vary from campaign to campaign.
//This is also highly effected by the game's difficulty setting.
void InitNewCampaign()
{
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"InitNewCampaign");
//First clear all the sector information of all enemy existance. Conveniently, the
//ubGroupType is also cleared, which is perceived to be an empty group.
memset( &SectorInfo, 0, sizeof( SECTORINFO ) * 256 );
InitStrategicMovementCosts();
RemoveAllGroups();
InitMiningLocations();
InitKnowFacilitiesFlags( );
BuildUndergroundSectorInfoList();
// allow overhead view of omerta A9 on game onset
SetSectorFlag( 9, 1, 0, SF_ALREADY_VISITED );
//Generates the initial forces in a new campaign. The idea is to randomize numbers and sectors
//so that no two games are the same.
InitStrategicAI();
InitStrategicStatus();
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"InitNewCampaign done");
}