mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
- If ALLOW_MILITIA_STRATEGIC_COMMAND is TRUE and militia can be commanded, oen can order them to retreat from autoresolve
- Final sector in a militia group's path is shown while plotting in the strategic map. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7743 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+186
-36
@@ -2637,10 +2637,13 @@ void CreateAutoResolveInterface()
|
||||
gpAR->iButton[ RETREAT_BUTTON ] =
|
||||
QuickCreateButton( gpAR->iButtonImage[ RETREAT_BUTTON ], (INT16)(gpAR->sCenterStartX+51), (INT16)(iScreenHeightOffset + 274+gpAR->bVerticalOffset), BUTTON_TOGGLE, MSYS_PRIORITY_HIGH,
|
||||
DEFAULT_MOVE_CALLBACK, RetreatButtonCallback );
|
||||
if( !gpAR->ubMercs )
|
||||
|
||||
// no retreat possible if no mercs are present and militia isn't present or cannot be commanded
|
||||
if ( !gpAR->ubMercs && (!gpAR->ubCivs || !CanGiveStrategicMilitiaMoveOrder( gpAR->ubSectorX, gpAR->ubSectorY )) )
|
||||
{
|
||||
DisableButton( gpAR->iButton[ RETREAT_BUTTON ] );
|
||||
}
|
||||
|
||||
SpecifyGeneralButtonTextAttributes( gpAR->iButton[ RETREAT_BUTTON ], gpStrategicString[STR_AR_RETREAT_BUTTON], BLOCKFONT2, 169, FONT_NEARBLACK );
|
||||
|
||||
gpAR->iButton[ BANDAGE_BUTTON ] =
|
||||
@@ -2841,11 +2844,10 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Autoresolve2");
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT8 ubPromotions;
|
||||
// this will check for promotions and handle them for you
|
||||
if( fDeleteForGood && ( gpCivs[ i ].pSoldier->ubMilitiaKills > 0) && ( ubCurrentRank < ELITE_MILITIA ) )
|
||||
{
|
||||
ubPromotions = CheckOneMilitiaForPromotion( gpCivs[ i ].pSoldier->sSectorX, gpCivs[ i ].pSoldier->sSectorY, ubCurrentRank, gpCivs[ i ].pSoldier->ubMilitiaKills );
|
||||
UINT8 ubPromotions = CheckOneMilitiaForPromotion( gpCivs[i].pSoldier->sSectorX, gpCivs[i].pSoldier->sSectorY, ubCurrentRank, gpCivs[i].pSoldier->ubMilitiaKills );
|
||||
if( ubPromotions )
|
||||
{
|
||||
if( ubPromotions == 2 )
|
||||
@@ -3025,7 +3027,7 @@ void RetreatButtonCallback( GUI_BUTTON *btn, INT32 reason )
|
||||
if( reason & MSYS_CALLBACK_REASON_LBUTTON_UP )
|
||||
{
|
||||
INT32 i;
|
||||
for( i = 0; i < gpAR->ubMercs; i++ )
|
||||
for ( i = 0; i < gpAR->ubMercs; ++i )
|
||||
{
|
||||
if( !(gpMercs[ i ].uiFlags & (CELL_RETREATING|CELL_RETREATED)) )
|
||||
{
|
||||
@@ -3036,8 +3038,26 @@ void RetreatButtonCallback( GUI_BUTTON *btn, INT32 reason )
|
||||
gpMercs[ i ].usAttack = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: militia can be ordered to retreat
|
||||
if ( gGameExternalOptions.fMilitiaStrategicCommand )
|
||||
{
|
||||
for ( INT32 i = 0; i < gpAR->ubCivs; ++i )
|
||||
{
|
||||
if ( !(gpCivs[i].uiFlags & (CELL_RETREATING | CELL_RETREATED)) )
|
||||
{
|
||||
gpCivs[i].uiFlags |= CELL_RETREATING | CELL_DIRTY;
|
||||
//Gets to retreat after a total of 2 attacks.
|
||||
gpCivs[i].usNextAttack = (UINT16)((1000 + gpCivs[i].usNextAttack * 2 + PreRandom( 2000 - gpCivs[i].usAttack )) * 2);
|
||||
gpAR->usPlayerAttack -= gpCivs[i].usAttack;
|
||||
gpCivs[i].usAttack = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( gpAR->pRobotCell )
|
||||
{ //if robot is retreating, set the retreat time to be the same as the robot's controller.
|
||||
{
|
||||
//if robot is retreating, set the retreat time to be the same as the robot's controller.
|
||||
UINT8 ubRobotControllerID;
|
||||
|
||||
ubRobotControllerID = gpAR->pRobotCell->pSoldier->ubRobotRemoteHolderID;
|
||||
@@ -3049,10 +3069,12 @@ void RetreatButtonCallback( GUI_BUTTON *btn, INT32 reason )
|
||||
gpAR->pRobotCell->usNextAttack = 0xffff;
|
||||
return;
|
||||
}
|
||||
for( i = 0; i < gpAR->ubMercs; i++ )
|
||||
|
||||
for( i = 0; i < gpAR->ubMercs; ++i )
|
||||
{
|
||||
if( ubRobotControllerID == gpMercs[ i ].pSoldier->ubID )
|
||||
{ //Found the controller, make the robot's retreat time match the contollers.
|
||||
{
|
||||
//Found the controller, make the robot's retreat time match the contollers.
|
||||
gpAR->pRobotCell->usNextAttack = gpMercs[ i ].usNextAttack;
|
||||
return;
|
||||
}
|
||||
@@ -4560,11 +4582,14 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
|
||||
usAttack = (UINT16)(pAttacker->usAttack + PreRandom((INT16)(gGameExternalOptions.iAutoResolveLuckFactor*1000.0) - pAttacker->usAttack ));
|
||||
else
|
||||
usAttack = (UINT16)(950 + PreRandom( 50 ));
|
||||
|
||||
if( pTarget->uiFlags & CELL_RETREATING && !(pAttacker->uiFlags & CELL_FEMALECREATURE) )
|
||||
{ //Attacking a retreating merc is harder. Modify the attack value to 70% of it's value.
|
||||
{
|
||||
//Attacking a retreating merc is harder. Modify the attack value to 70% of it's value.
|
||||
//This allows retreaters to have a better chance of escaping.
|
||||
usAttack = usAttack * 7 / 10;
|
||||
}
|
||||
|
||||
if( pTarget->usDefence < 950 )
|
||||
usDefence = (UINT16)(pTarget->usDefence + PreRandom((INT16)(gGameExternalOptions.iAutoResolveLuckFactor*1000.0) - pTarget->usDefence ));
|
||||
else
|
||||
@@ -4739,11 +4764,11 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
|
||||
// SANDRO - increased mercs' offense/deffense rating
|
||||
if ( pAttacker->uiFlags & CELL_MERC && gGameExternalOptions.sMercsAutoresolveOffenseBonus != 0 )
|
||||
{
|
||||
ubImpact += (iImpact * gGameExternalOptions.sMercsAutoresolveOffenseBonus / 150);
|
||||
ubImpact += (ubImpact * gGameExternalOptions.sMercsAutoresolveOffenseBonus / 150);
|
||||
}
|
||||
else if ( pTarget->uiFlags & CELL_MERC && gGameExternalOptions.sMercsAutoresolveDeffenseBonus != 0 && (iImpact > 3) )
|
||||
else if ( pTarget->uiFlags & CELL_MERC && gGameExternalOptions.sMercsAutoresolveDeffenseBonus != 0 && (ubImpact > 3) )
|
||||
{
|
||||
ubImpact = max( 3, ((iImpact * (100 - (gGameExternalOptions.sMercsAutoresolveDeffenseBonus / 2))) / 100) );
|
||||
ubImpact = max( 3, ((ubImpact * (100 - (gGameExternalOptions.sMercsAutoresolveDeffenseBonus / 2))) / 100) );
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -4816,11 +4841,11 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
|
||||
// SANDRO - increased mercs' offense/deffense rating
|
||||
if ( pAttacker->uiFlags & CELL_MERC && gGameExternalOptions.sMercsAutoresolveOffenseBonus != 0 )
|
||||
{
|
||||
iImpact += (iImpact * gGameExternalOptions.sMercsAutoresolveOffenseBonus / 150);
|
||||
ubImpact += (ubImpact * gGameExternalOptions.sMercsAutoresolveOffenseBonus / 150);
|
||||
}
|
||||
else if ( pTarget->uiFlags & CELL_MERC && gGameExternalOptions.sMercsAutoresolveDeffenseBonus != 0 && (iImpact > 3) )
|
||||
else if ( pTarget->uiFlags & CELL_MERC && gGameExternalOptions.sMercsAutoresolveDeffenseBonus != 0 && (ubImpact > 3) )
|
||||
{
|
||||
iImpact = max( 3, ((iImpact * (100 - (gGameExternalOptions.sMercsAutoresolveDeffenseBonus / 2))) / 100) );
|
||||
ubImpact = max( 3, ((ubImpact * (100 - (gGameExternalOptions.sMercsAutoresolveDeffenseBonus / 2))) / 100) );
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -4950,12 +4975,14 @@ void AttackTarget( SOLDIERCELL *pAttacker, SOLDIERCELL *pTarget )
|
||||
pTarget->pSoldier->DoMercBattleSound( (INT8)( BATTLE_SOUND_HIT1 + PreRandom( 2 ) ) );
|
||||
}
|
||||
if( !(pTarget->uiFlags & CELL_CREATURE) && iNewLife < OKLIFE && pTarget->pSoldier->stats.bLife >= OKLIFE )
|
||||
{ //the hit caused the merc to fall. Play the falling sound
|
||||
{
|
||||
//the hit caused the merc to fall. Play the falling sound
|
||||
PlayAutoResolveSample( (UINT8)FALL_1, RATE_11025, 50, 1, MIDDLEPAN );
|
||||
pTarget->uiFlags &= ~CELL_RETREATING;
|
||||
}
|
||||
if( iNewLife <= 0 )
|
||||
{ //soldier has been killed
|
||||
{
|
||||
//soldier has been killed
|
||||
|
||||
// Flugente: campaign stats
|
||||
gCurrentIncident.AddStat( pTarget->pSoldier, CAMPAIGNHISTORY_TYPE_KILL );
|
||||
@@ -5368,34 +5395,56 @@ BOOLEAN IsBattleOver()
|
||||
INT32 i;
|
||||
INT32 iNumInvolvedMercs = 0;
|
||||
INT32 iNumMercsRetreated = 0;
|
||||
INT32 iNumInvolvedMilitia = 0;
|
||||
INT32 iNumMilitiaRetreated = 0;
|
||||
BOOLEAN fOnlyEPCsLeft = TRUE;
|
||||
|
||||
if( gpAR->ubBattleStatus != BATTLE_IN_PROGRESS )
|
||||
return TRUE;
|
||||
for( i = 0; i < gpAR->ubMercs; i++ )
|
||||
|
||||
for( i = 0; i < gpAR->ubMercs; ++i )
|
||||
{
|
||||
if( !(gpMercs[ i ].uiFlags & CELL_RETREATED) && gpMercs[ i ].pSoldier->stats.bLife )
|
||||
{
|
||||
if( !(gpMercs[ i ].uiFlags & CELL_EPC) )
|
||||
{
|
||||
fOnlyEPCsLeft = FALSE;
|
||||
iNumInvolvedMercs++;
|
||||
++iNumInvolvedMercs;
|
||||
}
|
||||
}
|
||||
|
||||
if( gpMercs[ i ].uiFlags & CELL_RETREATED )
|
||||
{
|
||||
iNumMercsRetreated++;
|
||||
++iNumMercsRetreated;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 0; i < gpAR->ubCivs; ++i )
|
||||
{
|
||||
if ( !(gpCivs[i].uiFlags & CELL_RETREATED) && gpCivs[i].pSoldier->stats.bLife )
|
||||
{
|
||||
++iNumInvolvedMilitia;
|
||||
}
|
||||
else if ( gpCivs[i].uiFlags & CELL_RETREATED )
|
||||
{
|
||||
++iNumMilitiaRetreated;
|
||||
}
|
||||
}
|
||||
|
||||
if( gpAR->pRobotCell )
|
||||
{ //Do special robot checks
|
||||
{
|
||||
//Do special robot checks
|
||||
SOLDIERTYPE *pRobot;
|
||||
pRobot = gpAR->pRobotCell->pSoldier;
|
||||
if( pRobot->ubRobotRemoteHolderID == NOBODY )
|
||||
{ //Robot can't fight anymore.
|
||||
{
|
||||
//Robot can't fight anymore.
|
||||
gpAR->usPlayerAttack -= gpAR->pRobotCell->usAttack;
|
||||
gpAR->pRobotCell->usAttack = 0;
|
||||
|
||||
if( iNumInvolvedMercs == 1 && !gpAR->ubAliveCivs )
|
||||
{ //Robot is the only one left in battle, so instantly kill him.
|
||||
{
|
||||
//Robot is the only one left in battle, so instantly kill him.
|
||||
pRobot->DoMercBattleSound( BATTLE_SOUND_DIE1 );
|
||||
pRobot->stats.bLife = 0;
|
||||
gpAR->ubAliveMercs--;
|
||||
@@ -5403,8 +5452,10 @@ BOOLEAN IsBattleOver()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !gpAR->ubAliveCivs && !iNumInvolvedMercs && iNumMercsRetreated )
|
||||
{ //RETREATED
|
||||
{
|
||||
//RETREATED
|
||||
gpAR->ubBattleStatus = BATTLE_RETREAT;
|
||||
|
||||
// wake everyone up
|
||||
@@ -5412,22 +5463,36 @@ BOOLEAN IsBattleOver()
|
||||
|
||||
RetreatAllInvolvedPlayerGroups( );
|
||||
}
|
||||
else if ( !iNumInvolvedMercs && !iNumInvolvedMilitia && iNumMilitiaRetreated && gGameExternalOptions.fMilitiaStrategicCommand )
|
||||
{
|
||||
//RETREATED
|
||||
gpAR->ubBattleStatus = BATTLE_RETREAT;
|
||||
|
||||
// wake everyone up
|
||||
WakeUpAllMercsInSectorUnderAttack( );
|
||||
|
||||
RetreatAllInvolvedMilitiaGroups( );
|
||||
}
|
||||
else if( !gpAR->ubAliveCivs && !iNumInvolvedMercs )
|
||||
{ //DEFEAT
|
||||
{
|
||||
//DEFEAT
|
||||
|
||||
if( fOnlyEPCsLeft )
|
||||
{ //Kill the EPCs.
|
||||
for( i = 0; i < gpAR->ubMercs; i++ )
|
||||
{
|
||||
//Kill the EPCs.
|
||||
for( i = 0; i < gpAR->ubMercs; ++i )
|
||||
{
|
||||
if( gpMercs[ i ].uiFlags & CELL_EPC )
|
||||
{
|
||||
gpMercs[ i ].pSoldier->DoMercBattleSound( BATTLE_SOUND_DIE1 );
|
||||
gpMercs[ i ].pSoldier->stats.bLife = 0;
|
||||
gpMercs[ i ].pSoldier->iHealableInjury = 0; // added by SANDRO
|
||||
gpAR->ubAliveMercs--;
|
||||
--gpAR->ubAliveMercs;
|
||||
}
|
||||
}
|
||||
}
|
||||
for( i = 0; i < gpAR->ubEnemies; i++ )
|
||||
|
||||
for( i = 0; i < gpAR->ubEnemies; ++i )
|
||||
{
|
||||
if( gpEnemies[ i ].pSoldier->stats.bLife )
|
||||
{
|
||||
@@ -5445,14 +5510,17 @@ BOOLEAN IsBattleOver()
|
||||
gpAR->ubBattleStatus = BATTLE_DEFEAT;
|
||||
}
|
||||
else if( !gpAR->ubAliveEnemies )
|
||||
{ //VICTORY
|
||||
{
|
||||
//VICTORY
|
||||
gpAR->ubBattleStatus = BATTLE_VICTORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SetupDoneInterface();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -5953,26 +6021,108 @@ BOOLEAN ProcessLoyalty()
|
||||
|
||||
void CheckForSoldiersWhoRetreatedIntoMilitiaHeldSectors()
|
||||
{
|
||||
for(int sX = 1; sX < ( MAP_WORLD_X - 1 ); sX++ ) {
|
||||
for(int sY = 1; sY < ( MAP_WORLD_Y - 1); sY++ ) {
|
||||
for( int sX = 1; sX < ( MAP_WORLD_X - 1 ); ++sX )
|
||||
{
|
||||
for( int sY = 1; sY < ( MAP_WORLD_Y - 1); ++sY )
|
||||
{
|
||||
// Check if there is a sector where enemies retreated to and there are also militia present
|
||||
if ( (NumNonPlayerTeamMembersInSector( sX, sY, ENEMY_TEAM ) > 0) &&
|
||||
(NumNonPlayerTeamMembersInSector( sX, sY, MILITIA_TEAM ) > 0) &&
|
||||
(!gTacticalStatus.fEnemyInSector)) {
|
||||
(!gTacticalStatus.fEnemyInSector))
|
||||
{
|
||||
unsigned mercCnt = 0;
|
||||
for( int i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; i++ ) {
|
||||
for( int i = gTacticalStatus.Team[ OUR_TEAM ].bFirstID; i <= gTacticalStatus.Team[ OUR_TEAM ].bLastID; ++i )
|
||||
{
|
||||
if( MercPtrs[ i ]->bActive && MercPtrs[ i ]->stats.bLife && !(MercPtrs[ i ]->flags.uiStatusFlags & SOLDIER_VEHICLE) && !AM_A_ROBOT( MercPtrs[ i ] ) )
|
||||
{ //Merc is active and alive, and not a vehicle or robot
|
||||
if ((MercPtrs[ i ]->sSectorX == sX) &&(MercPtrs[ i ]->sSectorY == sY) && (MercPtrs[ i ]->bSectorZ == 0)) {
|
||||
{
|
||||
//Merc is active and alive, and not a vehicle or robot
|
||||
if ((MercPtrs[ i ]->sSectorX == sX) &&(MercPtrs[ i ]->sSectorY == sY) && (MercPtrs[ i ]->bSectorZ == 0))
|
||||
{
|
||||
++mercCnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there are PC mercs here the player will have to handle the battle
|
||||
if (mercCnt == 0) {
|
||||
if (mercCnt == 0)
|
||||
{
|
||||
// EnterAutoResolveMode ((UINT8)sX, (UINT8)sY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: have all militia in autoresolve drop their gear and be promoted in necessary
|
||||
void AutoResolveMilitiaDropAndPromote()
|
||||
{
|
||||
gbGreenToElitePromotions = 0;
|
||||
gbGreenToRegPromotions = 0;
|
||||
gbRegToElitePromotions = 0;
|
||||
gbMilitiaPromotions = 0;
|
||||
for ( INT32 i = 0; i < MAX_AR_TEAM_SIZE; ++i )
|
||||
{
|
||||
if ( gpCivs[i].pSoldier )
|
||||
{
|
||||
UINT8 ubCurrentRank = GREEN_MILITIA;
|
||||
switch ( gpCivs[i].pSoldier->ubSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_GREEN_MILITIA: ubCurrentRank = GREEN_MILITIA; break;
|
||||
case SOLDIER_CLASS_REG_MILITIA: ubCurrentRank = REGULAR_MILITIA; break;
|
||||
case SOLDIER_CLASS_ELITE_MILITIA: ubCurrentRank = ELITE_MILITIA; break;
|
||||
default:
|
||||
#ifdef JA2BETAVERSION
|
||||
ScreenMsg( FONT_RED, MSG_ERROR, L"Removing autoresolve militia with invalid ubSoldierClass %d.", gpCivs[i].pSoldier->ubSoldierClass );
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
// Flugente: drop sector equipment
|
||||
gpCivs[i].pSoldier->DropSectorEquipment( );
|
||||
|
||||
if ( gpCivs[i].pSoldier->stats.bLife < OKLIFE / 2 )
|
||||
{
|
||||
StrategicRemoveMilitiaFromSector( gpCivs[i].pSoldier->sSectorX, gpCivs[i].pSoldier->sSectorY, ubCurrentRank, 1 );
|
||||
}
|
||||
else if ( gpCivs[i].pSoldier->stats.bLife >= OKLIFE / 2 )
|
||||
{
|
||||
// this will check for promotions and handle them for you
|
||||
if ( gpCivs[i].pSoldier->ubMilitiaKills && ubCurrentRank < ELITE_MILITIA )
|
||||
{
|
||||
UINT8 ubPromotions = CheckOneMilitiaForPromotion( gpCivs[i].pSoldier->sSectorX, gpCivs[i].pSoldier->sSectorY, ubCurrentRank, gpCivs[i].pSoldier->ubMilitiaKills );
|
||||
if ( ubPromotions )
|
||||
{
|
||||
if ( ubPromotions == 2 )
|
||||
{
|
||||
++gbGreenToElitePromotions;
|
||||
++gbMilitiaPromotions;
|
||||
|
||||
ubCurrentRank = ELITE_MILITIA;
|
||||
}
|
||||
else if ( gpCivs[i].pSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
|
||||
{
|
||||
++gbGreenToRegPromotions;
|
||||
++gbMilitiaPromotions;
|
||||
|
||||
ubCurrentRank = REGULAR_MILITIA;
|
||||
}
|
||||
else if ( gpCivs[i].pSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
|
||||
{
|
||||
++gbRegToElitePromotions;
|
||||
++gbMilitiaPromotions;
|
||||
|
||||
ubCurrentRank = ELITE_MILITIA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// in any case, we had our chance to be promoted, clear the counter
|
||||
gpCivs[i].pSoldier->ubMilitiaKills = 0;
|
||||
}
|
||||
|
||||
// DO NOT DELETE HERE!!!!
|
||||
//TacticalRemoveSoldierPointer( gpCivs[i].pSoldier, FALSE );
|
||||
//memset( &gpCivs[i], 0, sizeof(SOLDIERCELL) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,4 +21,7 @@ BOOLEAN GetCurrentBattleSectorXYZ( INT16 *psSectorX, INT16 *psSectorY, INT16 *ps
|
||||
|
||||
void CheckForSoldiersWhoRetreatedIntoMilitiaHeldSectors();
|
||||
|
||||
// Flugente: have all militia in autoresolve drop their gear and be promoted in necessary
|
||||
void AutoResolveMilitiaDropAndPromote();
|
||||
|
||||
#endif
|
||||
@@ -960,7 +960,8 @@ UINT32 DrawMap( void )
|
||||
|
||||
RestoreClipRegionToFullScreen( );
|
||||
|
||||
CheckForSoldiersWhoRetreatedIntoMilitiaHeldSectors();
|
||||
// Flugente: this function does not do anything... so I'm commenting its use out
|
||||
//CheckForSoldiersWhoRetreatedIntoMilitiaHeldSectors();
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
@@ -7688,7 +7689,7 @@ void DisplayMilitiaGroupBox()
|
||||
|
||||
UINT16 MILITIAGROUPBOX_HEIGHT_LINE = 14;
|
||||
|
||||
UINT16 MILITIAGROUPBOX_WIDTH = MILITIAGROUPBOX_WIDTH_NAME + 3 * MILITIAGROUPBOX_WIDTH_TYPEBOX + MILITIAGROUPBOX_WIDTH_SECTOR + MILITIAGROUPBOX_WIDTH_ETA;
|
||||
UINT16 MILITIAGROUPBOX_WIDTH = MILITIAGROUPBOX_WIDTH_NAME + 3 * MILITIAGROUPBOX_WIDTH_TYPEBOX + 2 * MILITIAGROUPBOX_WIDTH_SECTOR + MILITIAGROUPBOX_WIDTH_ETA;
|
||||
|
||||
// we need a header line, one for the sector, and one for each group present
|
||||
UINT8 usMapX = GET_X_FROM_STRATEGIC_INDEX( gMilitiaPlotStartSector );
|
||||
@@ -7750,6 +7751,11 @@ void DisplayMilitiaGroupBox()
|
||||
|
||||
swprintf( sString, szMilitiaStrategicMovementText[4] );
|
||||
mprintf( dispX, dispY, sString );
|
||||
dispX += MILITIAGROUPBOX_WIDTH_ETA;
|
||||
|
||||
swprintf( sString, szMilitiaStrategicMovementText[7] );
|
||||
mprintf( dispX, dispY, sString );
|
||||
dispX += MILITIAGROUPBOX_WIDTH_SECTOR;
|
||||
|
||||
dispX = gMilitiaGroupBoxX;
|
||||
dispY += MILITIAGROUPBOX_HEIGHT_LINE;
|
||||
@@ -7783,6 +7789,11 @@ void DisplayMilitiaGroupBox()
|
||||
|
||||
swprintf( sString, L"--:--" );
|
||||
mprintf( dispX, dispY, sString );
|
||||
dispX += MILITIAGROUPBOX_WIDTH_ETA;
|
||||
|
||||
swprintf( sString, L"--" );
|
||||
mprintf( dispX, dispY, sString );
|
||||
dispX += MILITIAGROUPBOX_WIDTH_SECTOR;
|
||||
|
||||
dispY += MILITIAGROUPBOX_HEIGHT_LINE;
|
||||
|
||||
@@ -7808,6 +7819,22 @@ void DisplayMilitiaGroupBox()
|
||||
CHAR16 wSectorName[64];
|
||||
GetShortSectorString( pGroup->ubNextX, pGroup->ubNextY, wSectorName );
|
||||
|
||||
CHAR16 wFinalSectorName[64];
|
||||
swprintf( sString, L"--" );
|
||||
|
||||
// determine the final destination of this group
|
||||
{
|
||||
INT16 finalsector = GetLastSectorIdInMilitiaGroupPath( pGroup->ubGroupID );
|
||||
if ( finalsector > -1 )
|
||||
{
|
||||
GetShortSectorString( SECTORX( finalsector ), SECTORY( finalsector ), wFinalSectorName );
|
||||
}
|
||||
else
|
||||
{
|
||||
GetShortSectorString( pGroup->ubNextX, pGroup->ubNextY, wFinalSectorName );
|
||||
}
|
||||
}
|
||||
|
||||
// show ETA
|
||||
CHAR16 timestring[64];
|
||||
UINT32 uiArrivalTime = GetWorldTotalMin( ) + CalculateTravelTimeOfGroup( pGroup );
|
||||
@@ -7920,6 +7947,11 @@ void DisplayMilitiaGroupBox()
|
||||
|
||||
swprintf( sString, L"%s", timestring );
|
||||
mprintf( dispX, dispY, sString );
|
||||
dispX += MILITIAGROUPBOX_WIDTH_ETA;
|
||||
|
||||
swprintf( sString, L"%s", wFinalSectorName );
|
||||
mprintf( dispX, dispY, sString );
|
||||
dispX += MILITIAGROUPBOX_WIDTH_SECTOR;
|
||||
|
||||
dispY += MILITIAGROUPBOX_HEIGHT_LINE;
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "Tactical Save.h"
|
||||
#include "message.h"
|
||||
#include "CampaignStats.h" // added by Flugente
|
||||
#include "militiasquads.h" // added by Flugente
|
||||
#endif
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -2011,7 +2012,6 @@ void RetreatAllInvolvedPlayerGroups( void )
|
||||
{
|
||||
GROUP *pGroup;
|
||||
|
||||
|
||||
// make sure guys stop their off duty assignments, like militia training!
|
||||
// but don't exit vehicles - drive off in them!
|
||||
PutNonSquadMercsInBattleSectorOnSquads( FALSE );
|
||||
@@ -2032,6 +2032,123 @@ void RetreatAllInvolvedPlayerGroups( void )
|
||||
}
|
||||
}
|
||||
|
||||
void RetreatAllInvolvedMilitiaGroups()
|
||||
{
|
||||
// first, determine in which sector we are
|
||||
// pick the non-hostile-occupied, reachable adjacent sector with the shortest travel time
|
||||
INT16 sBattleSectorX, sBattleSectorY, sBattleSectorZ;
|
||||
if ( !GetCurrentBattleSectorXYZ( &sBattleSectorX, &sBattleSectorY, &sBattleSectorZ ) )
|
||||
{
|
||||
// well... this sucks. We are in retreat code, but no battle is on... abort this
|
||||
return;
|
||||
}
|
||||
|
||||
// as we move the militia to another sector, anything that modifies them has to be done now - RemoveAutoResolveInterface is too late
|
||||
// as we don't want to make the location of that dependend on some state, we use a trick:
|
||||
// we drop their gear here, and promote them right now. They can then be properly deleted later on.
|
||||
AutoResolveMilitiaDropAndPromote();
|
||||
|
||||
// dissolve all militia groups here
|
||||
INT16 newX = 0;
|
||||
INT16 newY = 0;
|
||||
BOOLEAN found = FALSE;
|
||||
GROUP* pGroup = gpGroupList;
|
||||
while ( pGroup )
|
||||
{
|
||||
if ( MilitiaGroupInvolvedInThisCombat( pGroup ) )
|
||||
{
|
||||
// if a group's previous sector was different, pick it
|
||||
if ( pGroup->ubPrevX != 0 && pGroup->ubPrevY != 0 && ( pGroup->ubPrevX != pGroup->ubSectorX || pGroup->ubPrevY != pGroup->ubSectorY ) )
|
||||
{
|
||||
newX = pGroup->ubPrevX;
|
||||
newY = pGroup->ubPrevY;
|
||||
found = TRUE;
|
||||
}
|
||||
|
||||
GROUP* pDeleteGroup = pGroup;
|
||||
pGroup = pGroup->next;
|
||||
|
||||
ClearMercPathsAndWaypointsForAllInGroup( pDeleteGroup );
|
||||
DissolveMilitiaGroup( pDeleteGroup->ubGroupID );
|
||||
}
|
||||
else
|
||||
pGroup = pGroup->next;
|
||||
}
|
||||
|
||||
// create new group and instantly place it in new sector
|
||||
SECTORINFO *pSector = &SectorInfo[SECTOR( sBattleSectorX, sBattleSectorY )];
|
||||
|
||||
if ( !pSector )
|
||||
return;
|
||||
|
||||
pGroup = CreateNewMilitiaGroupDepartingFromSector( SECTOR( sBattleSectorX, sBattleSectorY ), pSector->ubNumberOfCivsAtLevel[0], pSector->ubNumberOfCivsAtLevel[1], pSector->ubNumberOfCivsAtLevel[2] );
|
||||
|
||||
pSector->ubNumberOfCivsAtLevel[0] = 0;
|
||||
pSector->ubNumberOfCivsAtLevel[1] = 0;
|
||||
pSector->ubNumberOfCivsAtLevel[2] = 0;
|
||||
|
||||
// if we haven't found a good direction yet, we have to pick the best adjacent sector we can find
|
||||
if ( !found )
|
||||
{
|
||||
INT32 besttime = 1000000;
|
||||
UINT8 usDirection = NORTH_STRATEGIC_MOVE;
|
||||
for ( UINT8 i = 0; i < 4; ++i )
|
||||
{
|
||||
INT16 loopX = sBattleSectorX;
|
||||
INT16 loopY = sBattleSectorY;
|
||||
|
||||
if ( i == 0 )
|
||||
{
|
||||
++loopY;
|
||||
usDirection = SOUTH_STRATEGIC_MOVE;
|
||||
}
|
||||
else if ( i == 1 )
|
||||
{
|
||||
++loopX;
|
||||
usDirection = EAST_STRATEGIC_MOVE;
|
||||
}
|
||||
else if ( i == 2 )
|
||||
{
|
||||
--loopY;
|
||||
usDirection = NORTH_STRATEGIC_MOVE;
|
||||
}
|
||||
else if ( i == 3 )
|
||||
{
|
||||
--loopX;
|
||||
usDirection = WEST_STRATEGIC_MOVE;
|
||||
}
|
||||
|
||||
if ( loopX < 1 || loopX >= MAP_WORLD_X - 1 || loopY < 1 || loopY >= MAP_WORLD_Y - 1 )
|
||||
continue;
|
||||
|
||||
// don't retreat into an occupied sector!
|
||||
if ( NumNonPlayerTeamMembersInSector( loopX, loopY, ENEMY_TEAM ) > 0 )
|
||||
continue;
|
||||
|
||||
INT32 uiTraverseTime = GetSectorMvtTimeForGroup( (UINT8)SECTOR( pGroup->ubSectorX, pGroup->ubSectorY ), usDirection, pGroup );
|
||||
if ( uiTraverseTime < besttime )
|
||||
{
|
||||
besttime = uiTraverseTime;
|
||||
newX = loopX;
|
||||
newY = loopY;
|
||||
found = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we found a good direction, move the group
|
||||
if ( found )
|
||||
{
|
||||
// while militia groups travel, they are not between sectors. As a result, when we retreat a militia group, we have to move them to the next sector immediately
|
||||
// do NOT check for a new battle - when calling this function, we are likely still in autoresolve, so this would cause hiccups
|
||||
PlaceGroupInSector( pGroup->ubGroupID, pGroup->ubSectorX, pGroup->ubSectorY, newX, newY, 0, FALSE );
|
||||
}
|
||||
|
||||
// delete group afterwards, if it hasn't been deleted already - the militia will become static
|
||||
if ( pGroup )
|
||||
DissolveMilitiaGroup( pGroup->ubGroupID );
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN PlayerMercInvolvedInThisCombat( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
@@ -2081,6 +2198,26 @@ BOOLEAN PlayerGroupInvolvedInThisCombat( GROUP *pGroup )
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
BOOLEAN MilitiaGroupInvolvedInThisCombat( GROUP *pGroup )
|
||||
{
|
||||
Assert( pGroup );
|
||||
|
||||
// player group, non-empty, not between sectors, in the right sector, isn't a group of in transit, dead, or POW mercs,
|
||||
// and either not the helicopter group, or the heli is on the ground
|
||||
if ( pGroup->usGroupTeam == MILITIA_TEAM && pGroup->ubGroupSize &&
|
||||
!pGroup->fBetweenSectors )
|
||||
{
|
||||
if ( CurrentBattleSectorIs( pGroup->ubSectorX, pGroup->ubSectorY, pGroup->ubSectorZ ) )
|
||||
{
|
||||
// involved
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// not involved
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN CurrentBattleSectorIs( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ )
|
||||
{
|
||||
|
||||
@@ -85,8 +85,10 @@ void WakeUpAllMercsInSectorUnderAttack( void );
|
||||
|
||||
void ClearMovementForAllInvolvedPlayerGroups( void );
|
||||
void RetreatAllInvolvedPlayerGroups( void );
|
||||
void RetreatAllInvolvedMilitiaGroups( void );
|
||||
|
||||
BOOLEAN PlayerGroupInvolvedInThisCombat( GROUP *pGroup );
|
||||
BOOLEAN MilitiaGroupInvolvedInThisCombat( GROUP *pGroup );
|
||||
BOOLEAN PlayerMercInvolvedInThisCombat( SOLDIERTYPE *pSoldier );
|
||||
|
||||
BOOLEAN CurrentBattleSectorIs( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ );
|
||||
|
||||
@@ -3091,16 +3091,19 @@ void SetGroupSectorValue( INT16 sSectorX, INT16 sSectorY, INT16 sSectorZ, UINT8
|
||||
pGroup->ubOriginalSector = (UINT8)SECTOR( pGroup->ubSectorX, pGroup->ubSectorY );
|
||||
DeleteStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->ubGroupID );
|
||||
|
||||
// set all of the mercs in the group so that they are in the new sector too.
|
||||
pPlayer = pGroup->pPlayerList;
|
||||
while( pPlayer )
|
||||
if ( pGroup->usGroupTeam == OUR_TEAM )
|
||||
{
|
||||
pPlayer->pSoldier->sSectorX = sSectorX;
|
||||
pPlayer->pSoldier->sSectorY = sSectorY;
|
||||
pPlayer->pSoldier->bSectorZ = (UINT8)sSectorZ;
|
||||
pPlayer->pSoldier->flags.fBetweenSectors = FALSE;
|
||||
pPlayer->pSoldier->flags.uiStatusFlags &= ~SOLDIER_SHOULD_BE_TACTICALLY_VALID;
|
||||
pPlayer = pPlayer->next;
|
||||
// set all of the mercs in the group so that they are in the new sector too.
|
||||
pPlayer = pGroup->pPlayerList;
|
||||
while( pPlayer )
|
||||
{
|
||||
pPlayer->pSoldier->sSectorX = sSectorX;
|
||||
pPlayer->pSoldier->sSectorY = sSectorY;
|
||||
pPlayer->pSoldier->bSectorZ = (UINT8)sSectorZ;
|
||||
pPlayer->pSoldier->flags.fBetweenSectors = FALSE;
|
||||
pPlayer->pSoldier->flags.uiStatusFlags &= ~SOLDIER_SHOULD_BE_TACTICALLY_VALID;
|
||||
pPlayer = pPlayer->next;
|
||||
}
|
||||
}
|
||||
|
||||
CheckAndHandleUnloadingOfCurrentWorld();
|
||||
|
||||
@@ -1221,10 +1221,28 @@ INT16 GetLastSectorIdInVehiclePath( INT32 iId )
|
||||
}
|
||||
|
||||
return sLastSector;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// get id of last sector in group'S path list
|
||||
INT16 GetLastSectorIdInMilitiaGroupPath( UINT8 uGroupId )
|
||||
{
|
||||
INT16 sLastSector = -1;
|
||||
|
||||
INT16 militiapathslot = GetMilitiaPathSlot( uGroupId );
|
||||
|
||||
if ( militiapathslot > -1 )
|
||||
{
|
||||
PathStPtr pNode = gMilitiaPath[militiapathslot].path;
|
||||
|
||||
while ( pNode )
|
||||
{
|
||||
sLastSector = (INT16)(pNode->uiSectorId);
|
||||
pNode = pNode->pNext;
|
||||
}
|
||||
}
|
||||
|
||||
return sLastSector;
|
||||
}
|
||||
|
||||
|
||||
PathStPtr CopyPaths( PathStPtr pSourcePath, PathStPtr pDestPath )
|
||||
@@ -1974,32 +1992,44 @@ void ClearMercPathsAndWaypointsForAllInGroup( GROUP *pGroup )
|
||||
PLAYERGROUP *pPlayer = NULL;
|
||||
SOLDIERTYPE *pSoldier = NULL;
|
||||
|
||||
pPlayer = pGroup->pPlayerList;
|
||||
while( pPlayer )
|
||||
if ( pGroup->usGroupTeam == OUR_TEAM )
|
||||
{
|
||||
pSoldier = pPlayer->pSoldier;
|
||||
|
||||
if ( pSoldier != NULL )
|
||||
pPlayer = pGroup->pPlayerList;
|
||||
while( pPlayer )
|
||||
{
|
||||
ClearPathForSoldier( pSoldier );
|
||||
pSoldier = pPlayer->pSoldier;
|
||||
|
||||
if ( pSoldier != NULL )
|
||||
{
|
||||
ClearPathForSoldier( pSoldier );
|
||||
}
|
||||
|
||||
pPlayer = pPlayer->next;
|
||||
}
|
||||
|
||||
pPlayer = pPlayer->next;
|
||||
// if it's a vehicle
|
||||
if ( pGroup->fVehicle )
|
||||
{
|
||||
INT32 iVehicleId = -1;
|
||||
VEHICLETYPE *pVehicle = NULL;
|
||||
|
||||
iVehicleId = GivenMvtGroupIdFindVehicleId( pGroup->ubGroupID );
|
||||
Assert ( iVehicleId != -1 );
|
||||
|
||||
pVehicle = &( pVehicleList[ iVehicleId ] );
|
||||
|
||||
// clear the path for that vehicle
|
||||
pVehicle->pMercPath = ClearStrategicPathList( pVehicle->pMercPath, pVehicle->ubMovementGroup );
|
||||
}
|
||||
}
|
||||
|
||||
// if it's a vehicle
|
||||
if ( pGroup->fVehicle )
|
||||
else if ( pGroup->usGroupTeam == MILITIA_TEAM )
|
||||
{
|
||||
INT32 iVehicleId = -1;
|
||||
VEHICLETYPE *pVehicle = NULL;
|
||||
INT16 militiapathslot = GetMilitiaPathSlot( pGroup->ubGroupID );
|
||||
|
||||
iVehicleId = GivenMvtGroupIdFindVehicleId( pGroup->ubGroupID );
|
||||
Assert ( iVehicleId != -1 );
|
||||
|
||||
pVehicle = &( pVehicleList[ iVehicleId ] );
|
||||
|
||||
// clear the path for that vehicle
|
||||
pVehicle->pMercPath = ClearStrategicPathList( pVehicle->pMercPath, pVehicle->ubMovementGroup );
|
||||
if ( militiapathslot > -1 )
|
||||
{
|
||||
gMilitiaPath[militiapathslot].path = ClearStrategicPathList( gMilitiaPath[militiapathslot].path, pGroup->ubGroupID );
|
||||
}
|
||||
}
|
||||
|
||||
// clear the waypoints for this group too - no mercpath = no waypoints!
|
||||
|
||||
@@ -73,6 +73,9 @@ INT16 GetLastSectorIdInCharactersPath( SOLDIERTYPE *pCharacter );
|
||||
// get id of last sector in mercs path list
|
||||
INT16 GetLastSectorIdInVehiclePath( INT32 iId );
|
||||
|
||||
// get id of last sector in group'S path list
|
||||
INT16 GetLastSectorIdInMilitiaGroupPath( UINT8 uGroupId );
|
||||
|
||||
// copy paths
|
||||
PathStPtr CopyPaths( PathStPtr pSourcePath, PathStPtr pDestPath );
|
||||
|
||||
|
||||
@@ -10041,6 +10041,7 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"ETA",
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
};
|
||||
|
||||
// WANNE: Some Chinese specific strings that needs to be in unicode!
|
||||
|
||||
@@ -10052,6 +10052,7 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"ETA",
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
};
|
||||
|
||||
#endif //DUTCH
|
||||
|
||||
@@ -10090,6 +10090,7 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"ETA",
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
};
|
||||
|
||||
#endif //ENGLISH
|
||||
|
||||
@@ -10038,6 +10038,7 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"ETA",
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
};
|
||||
|
||||
#endif //FRENCH
|
||||
|
||||
@@ -9869,6 +9869,7 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"ETA",
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
};
|
||||
|
||||
#endif //GERMAN
|
||||
|
||||
@@ -10048,6 +10048,7 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"ETA",
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
};
|
||||
|
||||
#endif //ITALIAN
|
||||
|
||||
@@ -10063,6 +10063,7 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"ETA",
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
};
|
||||
|
||||
#endif //POLISH
|
||||
|
||||
@@ -10036,6 +10036,7 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"ETA",
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user