Little Alien

- New files for militia 




git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@61 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
lalien
2006-05-10 22:44:00 +00:00
parent 44dea15c67
commit 88d8b484f5
4 changed files with 1142 additions and 0 deletions
+681
View File
@@ -0,0 +1,681 @@
#ifdef PRECOMPILEDHEADERS
#include "Strategic All.h"
#else
#include "Town Militia.h"
#include "Militia Control.h"
#include "Campaign Types.h"
#include "strategic.h"
#include "strategicmap.h"
#include "Overhead.h"
#include "Strategic Town Loyalty.h"
#include "Utilities.h"
#include "random.h"
#include "text.h"
#include "Map Screen Interface.h"
#include "Interface.h"
#include "Laptopsave.h"
#include "finances.h"
#include "Game Clock.h"
#include "Assignments.h"
#include "squads.h"
#include "Soldier Create.h"
#include "Dialogue Control.h"
#endif
#include "MilitiaSquads.h"
#include "Reinforcement.h"
// Debug defines
//#define DEBUG_SHOW_RATINGS
#define DEBUG_RATINGS_CONDITION !fForBattle
// will create a squad each n hours (12 for example). Should divide 24 without remainder
#define CREATE_EACH_N_HOURS 12
// more these values - less the chances
#define CHANCE_TO_MOVE_A_SQUAD 5
#define CHANCE_TO_MOVE_AN_UNFULL_SQUAD 40
#define DIV_OF_ORIGINAL_MILITIA 2
#define BASE_DIR_PRIORITY 5
// little chance to move if below minimum
#define MINIMUM_MILITIA_SQUAD_SIZE 10
// should be 2* Minimum
//#define MAXIMUM_MILITIA_SQUAD_SIZE 30
#define MAXIMUM_MILITIA_SQUAD_SIZE_BATTLE MAXIMUM_MILITIA_SQUAD_SIZE
#define DIR_WITH_UNFULL_SQUAD_RATING_BONUS 100
// rating of battle, when there's equal number of soldiers
//#define DIR_RATING_OF_BATTLE 10
#define DIR_MIN_DIF 0.75
#define DIR_NORTH 0
#define DIR_EAST 1
#define DIR_SOUTH 2
#define DIR_WEST 3
UINT8 gpAttackDirs[5][4]; // 0. Green Militia 1. Regular Militia 2. Elite Militia 3. Insertion code
UINT8 guiDirNumber = 0;
BOOLEAN gfMSBattle = FALSE;
INT16 sMSMapX, sMSMapY;
extern UINT8 GetTraversability( INT16 sStartSector, INT16 sEndSector );
extern void TriggerPrebattleInterface( UINT8 ubResult );
extern BOOLEAN gfEnterAutoResolveMode;
//Counts the number of live mercs in any given sector.
BOOLEAN PlayerMercsInSector_MSE( UINT8 ubSectorX, UINT8 ubSectorY, BOOLEAN fDontConsiderNextSector )
{
GROUP *pGroup;
PLAYERGROUP *pPlayer;
UINT8 ubNumMercs = 0;
pGroup = gpGroupList;
while( pGroup )
{
if( pGroup->fPlayer )// && !pGroup->fBetweenSectors)
{
if ( ( pGroup->ubSectorX == ubSectorX && pGroup->ubSectorY == ubSectorY && pGroup->ubSectorZ == 0 ) ||
( !fDontConsiderNextSector && ( pGroup->ubNextX == ubSectorX && pGroup->ubNextY == ubSectorY && pGroup->ubSectorZ == 0 ) ) )
{
//we have a group, make sure that it isn't a group containing only dead members.
pPlayer = pGroup->pPlayerList;
while( pPlayer )
{
// robots count as mercs here, because they can fight, but vehicles don't
if( ( pPlayer->pSoldier->bLife ) && !( pPlayer->pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) )
{
ubNumMercs++;
}
pPlayer = pPlayer->next;
}
}
}
pGroup = pGroup->next;
}
return ubNumMercs;
}
// get any enemy group id in the sector (if no group, will return 0 )
UINT8 GetEnemyGroupIdInSector( INT16 sMapX, INT16 sMapY )
{
UINT8 ubRes = 0;
GROUP *curr;
curr = gpGroupList;
while( curr )
{
if( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && !curr->fPlayer )
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
void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY )
{
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] / DIV_OF_ORIGINAL_MILITIA);
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] / DIV_OF_ORIGINAL_MILITIA);
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] / DIV_OF_ORIGINAL_MILITIA);
pSectorInfo = &( SectorInfo[ SECTOR( sTMapX, sTMapY ) ] );
while( CountMilitia(pSectorInfo) > MAXIMUM_MILITIA_SQUAD_SIZE )
if(pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA])--pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA];else
if(pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA])--pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA];else
if(pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA])--pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA];
}
// Creates militia at destination sector and removes it from starting sector
void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOLEAN fAlternativeMax )
{
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
SECTORINFO *pTSectorInfo = &( SectorInfo[ SECTOR( sTMapX, sTMapY ) ] );
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, pSectorInfo->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] );
while( !fAlternativeMax && CountMilitia(pTSectorInfo) > MAXIMUM_MILITIA_SQUAD_SIZE ||
fAlternativeMax && CountMilitia(pTSectorInfo) > MAXIMUM_MILITIA_SQUAD_SIZE_BATTLE )
if(pTSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA])
{--pTSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA];++pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA];}else
if(pTSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA])
{--pTSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA];++pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA];}else
if(pTSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA])
{--pTSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA];++pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA];}
}
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 ] )
{
StrategicAddMilitiaToSector( sTMapX, sTMapY, ELITE_MILITIA, 1 );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ELITE_MILITIA, 1 );
return TRUE;
}
if( pSectorInfo->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] )
{
StrategicAddMilitiaToSector( sTMapX, sTMapY, REGULAR_MILITIA, 1 );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, 1 );
return TRUE;
}
if( pSectorInfo->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] )
{
StrategicAddMilitiaToSector( sTMapX, sTMapY, GREEN_MILITIA, 1 );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, 1 );
return TRUE;
}
return FALSE;
}
// Generate rating for a direction
UINT16 CountDirectionEnemyRating( INT16 sMapX, INT16 sMapY, UINT8 uiDir )
{
DOUBLE ddMinAngle, ddMaxAngle;
DOUBLE ddRes = 0;
DOUBLE pix2 = 3.1415926 * 2; // pi * 2
//UINT16 uiSector = 0;
INT16 sLMX, sLMY;
switch(uiDir)
{
case DIR_NORTH:
ddMinAngle = -2.3561944; // -135 degrees
ddMaxAngle = -0.7853981; // -45 degrees
break;
case DIR_EAST:
ddMinAngle = -0.7853981; // -45 degrees
ddMaxAngle = 0.7853981; // 45 degrees
break;
case DIR_SOUTH:
ddMinAngle = 0.7853981; // 45 degrees
ddMaxAngle = 2.3561944; // 135 degrees
break;
case DIR_WEST:
ddMinAngle = 2.3561944; // 135 degrees
ddMaxAngle = -2.3561944 + pix2; // 225 degrees(-135)
break;
default:
return 0;
}
//for( uiSector = 0 ; uiSector < 256 ; ++uiSector )
for( sLMX = 0; sLMX < 16 ; ++sLMX )
for( sLMY = 0; sLMY < 16 ; ++sLMY )
{
// SECTORINFO *pSectorInfo = &( SectorInfo[ uiSector ] );
UINT8 uiSumOfEnemyTroops = NumEnemiesInSector( sLMX, sLMY );
//pSectorInfo->ubNumAdmins + pSectorInfo->ubNumTroops + pSectorInfo->ubNumElites;
// there's an enemy
if( uiSumOfEnemyTroops )
{
DOUBLE ddAngle;
if( sLMX - sMapX == 0 )ddAngle = ( sLMY - sMapY > 0 ) ? 1.57079632 : -1.57079632;
else ddAngle = atan2( (double)(sLMY - sMapY), (double)(sLMX - sMapX) );
if( ddAngle < 0 && uiDir == DIR_WEST )ddAngle += pix2;
// is it in a right direction?
if( ddAngle >= ddMinAngle && ddAngle <= ddMaxAngle )
{
DOUBLE ddDistance = sqrt( pow( sLMY - sMapY, 2 ) + pow( sLMX - sMapX, 2 ) );
ddRes += (DOUBLE)uiSumOfEnemyTroops / pow( ddDistance, 2 );
}
}
}
return (UINT16) ddRes;
}
UINT16 CountDirectionRating( INT16 sMapX, INT16 sMapY, UINT8 uiDir )
{
INT32 iRes = BASE_DIR_PRIORITY + CountDirectionEnemyRating( sMapX, sMapY, uiDir );
INT16 sDMapX, sDMapY;
INT32 iDiff;
switch(uiDir)
{
case DIR_NORTH:
sDMapX = sMapX;
sDMapY = sMapY - 1;
break;
case DIR_EAST:
sDMapX = sMapX + 1;
sDMapY = sMapY;
break;
case DIR_SOUTH:
sDMapX = sMapX;
sDMapY = sMapY + 1;
break;
case DIR_WEST:
sDMapX = sMapX - 1;
sDMapY = sMapY;
break;
default:
return iRes;
}
if( CountAllMilitiaInSector( sDMapX, sDMapY ) &&
CountAllMilitiaInSector( sDMapX, sDMapY ) + CountAllMilitiaInSector( sMapX, sMapY ) <= MAXIMUM_MILITIA_SQUAD_SIZE )
iRes += DIR_WITH_UNFULL_SQUAD_RATING_BONUS;
if( NumEnemiesInSector( sDMapX, sDMapY ) )
{
// if( GetTownIdForSector( sMapX, sMapY ) == BLANK_SECTOR )
iDiff = iRes * ( (FLOAT)CountAllMilitiaInFiveSectors( sDMapX, sDMapY ) / (FLOAT)NumEnemiesInFiveSectors( sDMapX, sDMapY ) );
// else
// iDiff = iRes * ( (FLOAT)CountAllMilitiaInFiveSectors( sMapX, sMapY ) / DIV_OF_ORIGINAL_MILITIA / (FLOAT)NumEnemiesInFiveSectors( sDMapX, sDMapY ) );
if( iDiff > (FLOAT)DIR_MIN_DIF * iRes )
iRes = iDiff;
else
iRes = 0;
}
// There's player's mercs! Go there
if( PlayerMercsInSector_MSE( sDMapX, sDMapY, FALSE ) )
iRes += 15000;// should be enough
// ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"M %ld, E%ld,%ld %ld, Diff %ld", CountAllMilitiaInSector( sMapX, sMapY ), sDMapX, sDMapY, NumEnemiesInSector( sDMapX, sDMapY ), ((INT32)CountAllMilitiaInSector( sMapX, sMapY )) - ((INT32)NumEnemiesInSector( sDMapX, sDMapY )) );
return iRes;
}
// Standard conditions the direction should fit
BOOLEAN CheckStandardConditionsForDirection( INT16 sSMapX, INT16 sSMapY, INT16 sMapX, INT16 sMapY, BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors )
{
UINT8 uiTravab = GetTraversability( SECTOR( sSMapX , sSMapY ) , SECTOR( sMapX, sMapY ) );
if( uiTravab == GROUNDBARRIER || uiTravab == EDGEOFWORLD ) return FALSE;
if( !fForBattle && gfMSBattle && NumEnemiesInSector( sMapX, sMapY ) ) return FALSE;
return (GetTownIdForSector( sMapX, sMapY ) == BLANK_SECTOR || fWithCities) && !IsThisSectorASAMSector( sMapX, sMapY , 0 ) &&
(GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR || !fOnlyCitySectors);// &&
// ( !NumEnemiesInSector( sMapX, sMapY ) || GetEnemyGroupIdInSector(sMapX, sMapY ) || fForBattle ) &&
// ( fForBattle || CountAllMilitiaInSector( sMapX, sMapY ) < MAXIMUM_MILITIA_SQUAD_SIZE || PlayerMercsInSector( sMapX, sMapY, 0 ) )
}
void GenerateDirectionInfos( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3], BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors )
{
*uiDirNumber = 0;
#ifdef DEBUG_SHOW_RATINGS
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%ld,%ld-------------------", sMapX, sMapY );
#endif
if(CheckStandardConditionsForDirection( sMapX, sMapY, sMapX, sMapY - 1, fWithCities, fForBattle, fOnlyCitySectors ) )
{
pMoveDir[ *uiDirNumber ][0] = SECTOR( sMapX, sMapY - 1 );
if( fForBattle )
pMoveDir[ *uiDirNumber ][1] = 0;
else
pMoveDir[ *uiDirNumber ][1] = CountDirectionRating( sMapX, sMapY, DIR_NORTH );
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
++(*uiDirNumber);
}
if(CheckStandardConditionsForDirection( sMapX, sMapY, sMapX - 1, sMapY, fWithCities, fForBattle, fOnlyCitySectors ))
{
pMoveDir[ *uiDirNumber ][0] = SECTOR( sMapX - 1, sMapY );
if( fForBattle )
pMoveDir[ *uiDirNumber ][1] = 0;
else
pMoveDir[ *uiDirNumber ][1] = CountDirectionRating( sMapX, sMapY, DIR_WEST );
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_WEST;
#ifdef DEBUG_SHOW_RATINGS
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of west direction - %ld", pMoveDir[ *uiDirNumber ][1]);
#endif
++(*uiDirNumber);
}
if(CheckStandardConditionsForDirection( sMapX, sMapY, sMapX, sMapY + 1, fWithCities, fForBattle, fOnlyCitySectors ))
{
pMoveDir[ *uiDirNumber ][0] = SECTOR( sMapX, sMapY + 1 );
if( fForBattle )
pMoveDir[ *uiDirNumber ][1] = 0;
else
pMoveDir[ *uiDirNumber ][1] = CountDirectionRating( sMapX, sMapY, DIR_SOUTH );
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_SOUTH;
#ifdef DEBUG_SHOW_RATINGS
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of south direction - %ld", pMoveDir[ *uiDirNumber ][1]);
#endif
++(*uiDirNumber);
}
if(CheckStandardConditionsForDirection( sMapX, sMapY, sMapX + 1, sMapY, fWithCities, fForBattle, fOnlyCitySectors ))
{
pMoveDir[ *uiDirNumber ][0] = SECTOR( sMapX + 1, sMapY );
if( fForBattle )
pMoveDir[ *uiDirNumber ][1] = 0;
else
pMoveDir[ *uiDirNumber ][1] = CountDirectionRating( sMapX, sMapY, DIR_EAST );
pMoveDir[ *uiDirNumber ][2] = INSERTION_CODE_EAST;
#ifdef DEBUG_SHOW_RATINGS
if( DEBUG_RATINGS_CONDITION )ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Priority of east direction - %ld", pMoveDir[ *uiDirNumber ][1]);
#endif
++(*uiDirNumber);
}
}
UINT8 pBlockMoveList[256];
UINT8 uiBlockMoveListPointer;
void AddToBlockMoveList(INT16 sMapX, INT16 sMapY)
{
pBlockMoveList[ uiBlockMoveListPointer++ ] = SECTOR( sMapX, sMapY );
}
void ClearBlockMoveList()
{
uiBlockMoveListPointer = 0;
}
BOOLEAN CheckInBlockMoveList(INT16 sMapX, INT16 sMapY)
{
UINT16 i;
for( i = 0; i < uiBlockMoveListPointer ; ++i)
if( sMapX == SECTORX(pBlockMoveList[i]) && sMapY == SECTORY(pBlockMoveList[i]) )return TRUE;
return FALSE;
}
void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY )
{
UINT16 pMoveDir[4][3];
UINT8 uiDirNumber = 0;
UINT32 iRandomRes = 0, iRandom = 0;
UINT8 x;//,y;
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
UINT8 uiMilitiaCount;
if( !gGameExternalOptions.gfAllowMilitiaGroups )
return;
if( sMapX == 1 && sMapY == 1 )
{
ClearBlockMoveList();
gfMSBattle = FALSE;
}
if( CheckInBlockMoveList( sMapX, sMapY ) )return;
uiMilitiaCount = CountMilitia(pSectorInfo);
if( !uiMilitiaCount )return;
// new squad
if( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR )
{
if( GetWorldHour() % CREATE_EACH_N_HOURS )return;
GenerateDirectionInfos( sMapX, sMapY, &uiDirNumber, pMoveDir, FALSE, FALSE, FALSE );
if(uiDirNumber)// && Random(100) < CHANCE_TO_GENERATE_A_SQUAD)
{
for( x = 1; x < uiDirNumber ; ++x )pMoveDir[x][1] += pMoveDir[x-1][1];
iRandomRes = Random( pMoveDir[ uiDirNumber - 1 ][1] );
for( x = 0; x < uiDirNumber; ++x)
if( iRandomRes < pMoveDir[x][1] )
{
iRandomRes = x;
break;
}
// shouldn't be!
if(iRandomRes >= uiDirNumber)iRandomRes = 0;
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%ld,%ld:Dir count %ld, Rand %ld. Go to %ld,%ld", sMapX, sMapY, uiDirNumber, iRandomRes, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ));
GenerateMilitiaSquad( sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
AddToBlockMoveList( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
if( NumEnemiesInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) && CountAllMilitiaInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) )
{
/* GROUP* pEnemyGroup = GetGroup( GetEnemyGroupIdInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) );
if(pEnemyGroup && pEnemyGroup->ubGroupID)
{
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Attacking from %ld,%ld to %ld,%ld - enemy's group id %ld", sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0], pEnemyGroup->ubGroupID ));
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Arrival 1, Arrival 2");
pEnemyGroup->ubPrevX = sMapX;
pEnemyGroup->ubPrevY = sMapY;
pEnemyGroup->ubNextX = SECTORX( pMoveDir[ iRandomRes ][0] );
pEnemyGroup->ubNextY = SECTORY( pMoveDir[ iRandomRes ][0] );
*/
gfMSBattle = TRUE;
// GroupArrivedAtSector( pEnemyGroup->ubGroupID , TRUE, FALSE );
EnterAutoResolveMode( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
// }
}
}
else return;
}
// moving squad, if it is not a SAM site
else if(!IsThisSectorASAMSector( sMapX, sMapY, 0 ))
if( !PlayerMercsInSector_MSE( sMapX, sMapY, FALSE ) ) // and there's no player's mercs in the sector
{
if( GetWorldHour() % 2 )return;
GenerateDirectionInfos( sMapX, sMapY, &uiDirNumber, pMoveDir, FALSE, FALSE, FALSE );
if( uiDirNumber )
{
for( x = 1; x < uiDirNumber ; ++x )pMoveDir[x][1] += pMoveDir[x-1][1];
// ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%ld,%ld", x, pMoveDir[x][1]);
iRandom = Random( pMoveDir[ uiDirNumber - 1 ][1] +
( uiMilitiaCount >= MINIMUM_MILITIA_SQUAD_SIZE ? CHANCE_TO_MOVE_A_SQUAD : CHANCE_TO_MOVE_AN_UNFULL_SQUAD ) );
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Roll %ld", iRandomRes);
iRandomRes = 256;
for( x = 0; x < uiDirNumber; ++x)
if( iRandom < pMoveDir[x][1] )
{
iRandomRes = x;
break;
}
// "Decided" to stay here
if(iRandomRes >= uiDirNumber)
return;
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%ld,%ld:Dir count %ld, Rand %ld. Go to %ld,%ld. Have %ld militia men", sMapX, sMapY, uiDirNumber, iRandomRes, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ), uiMilitiaCount);
MoveMilitiaSquad( sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ), FALSE );
AddToBlockMoveList( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
if( NumEnemiesInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) )
{
/* GROUP* pEnemyGroup = GetGroup( GetEnemyGroupIdInSector( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) ) );
if(pEnemyGroup && pEnemyGroup->ubGroupID)
{
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Attacking from %ld,%ld to %ld,%ld - enemy's group id %ld", sMapX, sMapY, SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0], pEnemyGroup->ubGroupID ));
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Arrival 1, Arrival 2");
pEnemyGroup->ubPrevX = sMapX;
pEnemyGroup->ubPrevY = sMapY;
pEnemyGroup->ubNextX = SECTORX( pMoveDir[ iRandomRes ][0] );
pEnemyGroup->ubNextY = SECTORY( pMoveDir[ iRandomRes ][0] );
*/
gfMSBattle = TRUE;
// GroupArrivedAtSector( pEnemyGroup->ubGroupID , TRUE, FALSE );
EnterAutoResolveMode( SECTORX( pMoveDir[ iRandomRes ][0] ), SECTORY( pMoveDir[ iRandomRes ][0] ) );
// }
}
}
else return;
}
}
extern BOOLEAN gfMSResetMilitia;
void DoMilitiaHelpFromAdjacentSectors( INT16 sMapX, INT16 sMapY )
{
UINT16 pMoveDir[4][3];
UINT8 uiDirNumber = 0;
UINT8 x;
UINT8 uiNumGreen = 0, uiNumReg = 0, uiNumElite = 0;
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
BOOLEAN fMoreTroopsLeft[4] = {FALSE,FALSE,FALSE,FALSE};
BOOLEAN fFirstLoop = TRUE;
BOOLEAN fMilitiaAlreadyBeen = CountMilitia(pSectorInfo )>0 ? TRUE : FALSE;
guiDirNumber = 0;
GenerateDirectionInfos( sMapX, sMapY, &uiDirNumber, pMoveDir,
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, FALSE );
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;
guiDirNumber = uiDirNumber + 1;
x = 0;
while( CountMilitia(pSectorInfo ) < MAXIMUM_MILITIA_SQUAD_SIZE_BATTLE &&
( fMoreTroopsLeft[0] || fMoreTroopsLeft[1] || fMoreTroopsLeft[2] || fMoreTroopsLeft[3] || fFirstLoop ) )
{
fMoreTroopsLeft[ x ] = MoveOneBestMilitiaMan( SECTORX( pMoveDir[ x ][0] ), SECTORY( pMoveDir[ x ][0] ), sMapX, sMapY );
if( fMilitiaAlreadyBeen )gfMSResetMilitia = TRUE;
if( fMoreTroopsLeft[ x ] )
{
gpAttackDirs[ x + 1 ][0] += pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA] - uiNumGreen;
gpAttackDirs[ x + 1 ][1] += pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA] - uiNumReg;
gpAttackDirs[ x + 1 ][2] += pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA] - uiNumElite;
gpAttackDirs[ x + 1 ][3] = pMoveDir[ x ][2];
uiNumGreen = pSectorInfo->ubNumberOfCivsAtLevel[GREEN_MILITIA];
uiNumReg = pSectorInfo->ubNumberOfCivsAtLevel[REGULAR_MILITIA];
uiNumElite = pSectorInfo->ubNumberOfCivsAtLevel[ELITE_MILITIA];
}
++x;
if( x >= uiDirNumber )
{
x = 0;
fFirstLoop = FALSE;
}
}
}
void MSCallBack( UINT8 ubResult )
{
if( ubResult == MSG_BOX_RETURN_YES )
DoMilitiaHelpFromAdjacentSectors( sMSMapX, sMSMapY );
}
BOOLEAN IsThereMilitiaInAdjacentSector( INT16 sMapX, INT16 sMapY )
{
UINT16 pMoveDir[4][3];
UINT8 uiDirNumber = 0;
UINT8 x;
BOOLEAN fResult = FALSE;
GenerateDirectionInfos( sMapX, sMapY, &uiDirNumber, pMoveDir,
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, FALSE );
for( x = 0; x < uiDirNumber ; ++x )
if( CountAllMilitiaInSector( SECTORX( pMoveDir[ x ][ 0 ] ), SECTORY( pMoveDir[ x ][ 0 ] ) ) )
fResult = TRUE;
return fResult;
}
void MilitiaHelpFromAdjacentSectors( INT16 sMapX, INT16 sMapY )
{
sMSMapX = sMapX;
sMSMapY = sMapY;
if( !gGameExternalOptions.gfAllowMilitiaGroups )
return;
if( CountAllMilitiaInSector( sMapX, sMapY ) ) MSCallBack( MSG_BOX_RETURN_YES );
if( IsThereMilitiaInAdjacentSector( sMapX, sMapY ) && CountAllMilitiaInSector( sMapX, sMapY ) < MAXIMUM_MILITIA_SQUAD_SIZE_BATTLE )
DoScreenIndependantMessageBox( gzCWStrings[0], MSG_BOX_FLAG_YESNO, MSCallBack );
}
void MilitiaFollowPlayer( INT16 sMapX, INT16 sMapY, INT16 sDMapX, INT16 sDMapY )
{
if( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ||
IsThisSectorASAMSector( sMapX, sMapY, 0 ) ||
PlayerMercsInSector_MSE( sMapX, sMapY, TRUE ) )return;
if( GetTownIdForSector( sDMapX, sDMapY ) != BLANK_SECTOR ||
IsThisSectorASAMSector( sDMapX, sDMapY, 0 ) )return;
MoveMilitiaSquad( sMapX, sMapY, sDMapX, sDMapY, FALSE );
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef _MILITIA_SQUADS_H
#define _MILITIA_SQUADS_H
// header for town militia strategic control module
#include "Types.h"
#include "Soldier Control.h"
#define MAXIMUM_MILITIA_SQUAD_SIZE 30
extern UINT8 gpAttackDirs[5][4];
extern UINT8 guiDirNumber;
void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY );
void MilitiaHelpFromAdjacentSectors( INT16 sMapX, INT16 sMapY );
void GenerateDirectionInfos( INT16 sMapX, INT16 sMapY, UINT8* uiDirNumber, UINT16 pMoveDir[4][3], BOOLEAN fWithCities, BOOLEAN fForBattle, BOOLEAN fOnlyCitySectors );
BOOLEAN MoveOneBestMilitiaMan(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY);
void MilitiaFollowPlayer( INT16 sMapX, INT16 sMapY, INT16 sDMapX, INT16 sDMapY );
#endif
+423
View File
@@ -0,0 +1,423 @@
#ifdef PRECOMPILEDHEADERS
#include "Strategic All.h"
#else
#include "Town Militia.h"
#include "Militia Control.h"
#include "Campaign Types.h"
#include "strategic.h"
#include "strategicmap.h"
#include "Overhead.h"
#include "Strategic Town Loyalty.h"
#include "Utilities.h"
#include "random.h"
#include "text.h"
#include "Map Screen Interface.h"
#include "Interface.h"
#include "Laptopsave.h"
#include "finances.h"
#include "Game Clock.h"
#include "Assignments.h"
#include "squads.h"
#include "Soldier Create.h"
#include "Dialogue Control.h"
#endif
#include "Reinforcement.h"
#include "MilitiaSquads.h"
#define IS_ONLY_IN_CITIES ( gGameExternalOptions.gfAllowReinforcmentsOnlyInCity ? TRUE: FALSE )
UINT8 gubReinforcementMinEnemyStaticGroupSize = 12;
void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites )
{
UINT8 ubNumAdmins, ubNumTroops, ubNumElites;
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber, ubIndex;
GetNumberOfStationaryEnemiesInSector( sSectorX, sSectorY, pubNumAdmins, pubNumTroops, pubNumElites );
GetNumberOfMobileEnemiesInSector( sSectorX, sSectorY, &ubNumAdmins, &ubNumTroops, &ubNumElites );
*pubNumAdmins += ubNumAdmins;
*pubNumTroops += ubNumTroops;
*pubNumElites += ubNumElites;
if( !gGameExternalOptions.gfAllowReinforcments )
return;
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sSectorX, sSectorY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
{
GetNumberOfStationaryEnemiesInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), &ubNumAdmins, &ubNumTroops, &ubNumElites );
while( ubNumElites + ubNumTroops + ubNumAdmins > gubReinforcementMinEnemyStaticGroupSize)
{
if( ubNumElites )
{
*pubNumElites += 1;
ubNumElites--;
}else if( ubNumTroops )
{
*pubNumTroops += 1;
ubNumTroops--;
}else if( ubNumAdmins )
{
*pubNumAdmins += 1;
ubNumAdmins--;
}
}
GetNumberOfMobileEnemiesInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), &ubNumAdmins, &ubNumTroops, &ubNumElites );
*pubNumAdmins += ubNumAdmins;
*pubNumTroops += ubNumTroops;
*pubNumElites += ubNumElites;
}
}
UINT8 NumEnemiesInFiveSectors( INT16 sMapX, INT16 sMapY )
{
UINT8 ubNumAdmins, ubNumTroops, ubNumElites;
GetNumberOfEnemiesInFiveSectors( sMapX, sMapY, &ubNumAdmins, &ubNumTroops, &ubNumElites );
return ubNumAdmins + ubNumTroops + ubNumElites;
}
BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 sSectorY )
{
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber = 0, ubIndex;
if( pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY )
return TRUE; //Well, it's in the same sector, so allow to reinforce
if( !gGameExternalOptions.gfAllowReinforcments )
return FALSE;
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sSectorX, sSectorY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
if( pGroup->ubSectorX == SECTORX( pusMoveDir[ ubIndex ][ 0 ] ) && pGroup->ubSectorY == SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) )
return TRUE;
return FALSE;
}
UINT8 GetAdjacentSectors( UINT8 pSectors[4], INT16 sSectorX, INT16 sSectorY )
{
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber = 0, ubIndex;
UINT8 ubCounter = 0;
GenerateDirectionInfos( sSectorX, sSectorY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sSectorX, sSectorY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
pSectors[ ubCounter++ ] = pusMoveDir[ ubIndex ][ 0 ];
return ubCounter;
}
UINT8 CountAllMilitiaInFiveSectors(INT16 sMapX, INT16 sMapY)
{
UINT8 ubResult = 0;
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber, ubIndex;
ubResult = CountAllMilitiaInSector( sMapX, sMapY );
if( !gGameExternalOptions.gfAllowReinforcments )
return ubResult;
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
ubResult += CountAllMilitiaInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) );
return ubResult;
}
UINT8 MilitiaInFiveSectorsOfRank( INT16 sMapX, INT16 sMapY, UINT8 ubRank )
{
UINT8 ubResult = 0;
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber, ubIndex;
ubResult = MilitiaInSectorOfRank( sMapX, sMapY, ubRank );
if( !gGameExternalOptions.gfAllowReinforcments )
return ubResult;
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
ubResult += MilitiaInSectorOfRank( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ), ubRank );
return ubResult;
}
BOOLEAN ARMoveBestMilitiaManFromAdjacentSector(INT16 sMapX, INT16 sMapY)
{
UINT8 ubResult = 0;
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber;
UINT8 ubRandom;
if( !gGameExternalOptions.gfAllowReinforcments )
return FALSE;
if( CountAllMilitiaInSector( sMapX, sMapY ) >= MAXIMUM_MILITIA_SQUAD_SIZE ||
CountAllMilitiaInFiveSectors( sMapX, sMapY ) - CountAllMilitiaInSector( sMapX, sMapY ) == 0 )
return FALSE;
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
ubRandom = Random( ubDirNumber );
while( !MoveOneBestMilitiaMan( SECTORX( pusMoveDir[ ubRandom ][ 0 ] ), SECTORY( pusMoveDir[ ubRandom ][ 0 ] ), sMapX, sMapY ) )
ubRandom = Random( ubDirNumber );
return TRUE;
}
BOOLEAN ARRemoveMilitiaMan( INT16 sMapX, INT16 sMapY, UINT8 ubRank )
{
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber, ubRandom;
if( MilitiaInSectorOfRank( sMapX, sMapY, ubRank ) )
{
StrategicRemoveMilitiaFromSector( sMapX, sMapY, ubRank, 1 );
ARMoveBestMilitiaManFromAdjacentSector( sMapX, sMapY );
return TRUE;
}
if( !gGameExternalOptions.gfAllowReinforcments )
return FALSE;
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
for( ; ; )
{
ubRandom = Random( ubDirNumber );
if( MilitiaInSectorOfRank( SECTORX( pusMoveDir[ ubRandom ][ 0 ] ), SECTORY( pusMoveDir[ ubRandom ][ 0 ] ), ubRank ) )
{
StrategicRemoveMilitiaFromSector( SECTORX( pusMoveDir[ ubRandom ][ 0 ] ), SECTORY( pusMoveDir[ ubRandom ][ 0 ] ), ubRank, 1 );
return TRUE;
}
}
return FALSE;
}
GROUP* GetEnemyGroupInSector( INT16 sMapX, INT16 sMapY )
{
GROUP *curr;
curr = gpGroupList;
while( curr )
{
if( curr->ubSectorX == sMapX && curr->ubSectorY == sMapY && !curr->fPlayer && curr->ubGroupID )
return curr;
curr = curr->next;
}
return NULL;
}
UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY )
{
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber = 0, ubIndex;
GROUP *pGroup;
SECTORINFO *pThisSector, *pSector;
if( !gGameExternalOptions.gfAllowReinforcments )
return 255;
pThisSector = &SectorInfo[ SECTOR( sMapX, sMapY ) ];
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
for( ubIndex = 0; ubIndex < ubDirNumber; ubIndex++ )
if( NumMobileEnemiesInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ) && GetEnemyGroupInSector( SECTORX( pusMoveDir[ ubIndex][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ) )
{
pGroup = GetEnemyGroupInSector( SECTORX( pusMoveDir[ ubIndex][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) );
pGroup->ubPrevX = pGroup->ubSectorX;
pGroup->ubPrevY = pGroup->ubSectorY;
pGroup->ubSectorX = pGroup->ubNextX = sMapX;
pGroup->ubSectorY = pGroup->ubNextY = sMapY;
return pusMoveDir[ ubIndex ][ 2 ];
}
if( NumEnemiesInFiveSectors( sMapX, sMapY ) - NumEnemiesInSector( sMapX, sMapY ) == 0 )
{
return 255;
}else
for(;;)
{
ubIndex = Random(ubDirNumber);
if( NumEnemiesInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ) > gubReinforcementMinEnemyStaticGroupSize )
{
pSector = &SectorInfo[ pusMoveDir[ ubIndex ][ 0 ] ];
if( pSector->ubNumElites )
{
(pThisSector->ubNumElites)++;
(pSector->ubNumElites)--;
}else if( pSector->ubNumTroops )
{
(pThisSector->ubNumTroops)++;
(pSector->ubNumTroops)--;
}else if( pSector->ubNumAdmins )
{
(pThisSector->ubNumAdmins)++;
(pSector->ubNumAdmins)--;
}
return pusMoveDir[ ubIndex ][ 2 ];
}
}
}
UINT8 NumFreeMilitiaSlots()
{
UINT8 ubNumFreeSlots = 0;
INT32 i;
SOLDIERTYPE *pSoldier;
//Count the number of free militia slots. It is possible to have multiple groups exceed the maximum.
for( i = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; i <= gTacticalStatus.Team[ MILITIA_TEAM].bLastID; i++ )
{
pSoldier = &Menptr[ i ];
if( !pSoldier->bActive )
ubNumFreeSlots++;
}
return max( 0 , ubNumFreeSlots - ( 32 - MAXIMUM_MILITIA_SQUAD_SIZE ) );
}
UINT8 DoReinforcementAsPendingMilitia( INT16 sMapX, INT16 sMapY, UINT8 *pubRank )
{
UINT16 pusMoveDir[4][3];
UINT8 ubDirNumber = 0, ubIndex;
SECTORINFO *pSector;//*pThisSector,
if( !gGameExternalOptions.gfAllowReinforcments )
return 255;
// pThisSector = &SectorInfo[ SECTOR( sMapX, sMapY ) ];
GenerateDirectionInfos( sMapX, sMapY, &ubDirNumber, pusMoveDir,
( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR ? TRUE : FALSE ), TRUE, IS_ONLY_IN_CITIES );
if( CountAllMilitiaInFiveSectors( sMapX, sMapY ) - CountAllMilitiaInSector( sMapX, sMapY ) == 0 )
{
*pubRank = 255;
return 255;
}else
for(;;)
{
ubIndex = Random(ubDirNumber);
if( CountAllMilitiaInSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ) ) )
{
pSector = &SectorInfo[ pusMoveDir[ ubIndex ][ 0 ] ];
if( pSector->ubNumberOfCivsAtLevel[ 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 ] )
{
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 ] )
{
StrategicAddMilitiaToSector( sMapX, sMapY,GREEN_MILITIA, 1 );
StrategicRemoveMilitiaFromSector( SECTORX( pusMoveDir[ ubIndex ][ 0 ] ), SECTORY( pusMoveDir[ ubIndex ][ 0 ] ),GREEN_MILITIA, 1 );
*pubRank = GREEN_MILITIA;
}
return pusMoveDir[ ubIndex ][ 2 ];
}
}
}
void AddPossiblePendingMilitiaToBattle()
{
UINT8 ubSlots;
UINT8 ubNumElites, ubNumRegulars, ubNumGreens;
SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
static UINT8 ubPredefinedInsertionCode = 255;
static UINT8 ubPredefinedRank = 255;
if( !PlayerMercsInSector( gWorldSectorX, gWorldSectorY, 0 ) || !CountAllMilitiaInSector( gWorldSectorX, gWorldSectorY )
|| !NumEnemiesInSector( gWorldSectorX, gWorldSectorY ) ) return;
//MAXIMUM_MILITIA_SQUAD_SIZE - CountAllMilitiaInSector( gWorldSectorX, gWorldSectorY );
ubSlots = NumFreeMilitiaSlots();
if( !ubSlots )
{ //no available slots to add militia to. Try again later...
return;
}
if( ubPredefinedInsertionCode != 255 && ubPredefinedRank != 255 &&
CountAllMilitiaInSector( gWorldSectorX, gWorldSectorY ) )
{
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--;
}
if( ubNumGreens || ubNumRegulars || ubNumElites )
AddSoldierInitListMilitiaOnEdge( ubPredefinedInsertionCode, ubNumGreens, ubNumRegulars, ubNumElites );
}
ubPredefinedInsertionCode = 255;
ubPredefinedRank = 255;
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.
ubPredefinedInsertionCode = DoReinforcementAsPendingMilitia( gWorldSectorX, gWorldSectorY, &ubPredefinedRank );
if( ubPredefinedInsertionCode != 255 )
AddPossiblePendingMilitiaToBattle();
}
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef __REINFORCEMENT_H__
#define __REINFORCEMENT_H__
//For Autoresolve (mostly)
void GetNumberOfEnemiesInFiveSectors( INT16 sSectorX, INT16 sSectorY, UINT8 *pubNumAdmins, UINT8 *pubNumTroops, UINT8 *pubNumElites );
BOOLEAN IsGroupInARightSectorToReinforce( GROUP *pGroup, INT16 sSectorX, INT16 sSectorY );
UINT8 GetAdjacentSectors( UINT8 pSectors[4], INT16 sSectorX, INT16 sSectorY );
UINT8 CountAllMilitiaInFiveSectors(INT16 sMapX, INT16 sMapY);
UINT8 MilitiaInFiveSectorsOfRank(INT16 sMapX, INT16 sMapY, UINT8 ubRank);
BOOLEAN ARRemoveMilitiaMan( INT16 sMapX, INT16 sMapY, UINT8 ubRank );
UINT8 NumEnemiesInFiveSectors( INT16 sMapX, INT16 sMapY );
//For Tactical
UINT8 DoReinforcementAsPendingEnemy( INT16 sMapX, INT16 sMapY );
void AddPossiblePendingMilitiaToBattle();
#endif