Mobile Miltia improvements (by Moa)

- ja2_options.ini: MOBILE_MILITIA_MAX_ACTIVE_MODE, MOBILE_MILITIA_MAX_ACTIVE_MODIFIER
- see: http://www.bears-pit.com/board/ubbthreads.php/topics/325103/2.html


git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6544 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Wanne
2013-10-30 19:48:45 +00:00
parent cf06aed52a
commit 923327ca14
15 changed files with 495 additions and 19 deletions
+15 -1
View File
@@ -1881,6 +1881,12 @@ void LoadGameExternalOptions()
gGameExternalOptions.gfmusttrainroaming = iniReader.ReadBoolean("Mobile Militia Training Settings","MUST_TRAIN_MOBILE_MILITIA",FALSE);
//Moa: Mode to determine maximum allowed mobile militia for training / deserting.
gGameExternalOptions.gbMobileMilitiaMaxActiveMode = (UINT8) iniReader.ReadInteger("Mobile Militia Training Settings","MOBILE_MILITIA_MAX_ACTIVE_MODE",0,0,255);
//Moa: modifier for the maximum (make sure this is read after iMaxMilitiaPerSector)
gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier = iniReader.ReadFloat("Mobile Militia Training Settings","MOBILE_MILITIA_MAX_ACTIVE_MODIFIER", 0.5, 0.01, 10.0) * gGameExternalOptions.iMaxMilitiaPerSector;
gGameExternalOptions.guiCreateEachNHours = iniReader.ReadInteger("Mobile Militia Training Settings","CREATE_MOBILE_MILITIA_SQUAD_EACH_N_HOURS",24, 1, 96);
// HEADROCK HAM 3.3: New militia feature, Minimum Leadership required to train Roaming Militia
@@ -1921,7 +1927,15 @@ void LoadGameExternalOptions()
// HEADROCK HAM 3.3: If enabled, Roaming Militia can automatically reinforce city garrisons.
gGameExternalOptions.fAllowMobileReinforceSAM = iniReader.ReadBoolean("Mobile Militia Movement Settings","ALLOW_MOBILE_MILITIA_REINFORCE_SAM_GARRISONS", FALSE);
// Moa: If enabled militia will follow player (default HAM behavier), set to FALSE if they should do what they want.
gGameExternalOptions.gfAllowMilitiaFollowPlayer = iniReader.ReadBoolean("Mobile Militia Movement Settings","ALLOW_MILITIA_FOLLOW_PLAYER", TRUE);
// Moa: If enabled militia will spread (default HAM behavier) or set to FALSE to fill up the destination group to maximum.
gGameExternalOptions.gfAllowMilitiaSpread = iniReader.ReadBoolean("Mobile Militia Movement Settings","ALLOW_MILITIA_SPREAD", TRUE);
// Moa: If enabled militia will spread when following or set to FALSE to fill up the destination group to maximum.
gGameExternalOptions.gfAllowMilitiaSpreadWhenFollowing = iniReader.ReadBoolean("Mobile Militia Movement Settings","ALLOW_MILITIA_SPREAD_WHEN_FOLLOWING", FALSE);
// SANDRO - added several bonuses for militia
//################# Militia Strength Settings ##################
+7 -1
View File
@@ -453,6 +453,12 @@ typedef struct
BOOLEAN gfAllowMilitiaGroups;
BOOLEAN gfmusttrainroaming;
BOOLEAN gflimitedRoaming;
BOOLEAN gfAllowMilitiaFollowPlayer; //Moa: TRUE try to follow, FALSE do what they want
BOOLEAN gfAllowMilitiaSpreadWhenFollowing; //Moa: TRUE spread normal, FALSE dont spread when following
BOOLEAN gfAllowMilitiaSpread; //Moa: TRUE spread normal, FALSE fill up to max
UINT8 gbMobileMilitiaMaxActiveMode; //Moa: Used to check if the maximum of mobile militia is reached (for training/deserting). THIS IS A MODE
FLOAT gfpMobileMilitiaMaxActiveModifier; //Moa: const multiplier for the mode used (precalculated with MOBILE_MILITIA_MAX_ACTIVE_MODIFIER * MAX_MILITIA_PER_SECTOR).
BOOLEAN gfAllowReinforcements;
BOOLEAN gfAllowReinforcementsOnlyInCity;
UINT32 guiBaseQueenPoolIncrement;
@@ -832,7 +838,7 @@ typedef struct
// HEADROCK HAM B1: Allows reducing the chance of scoring a hit fractionally, if CTH = Minimum CTH
UINT16 usMinimumCTHDivisor;
// HEADROCK HAM B1: Allows Restricted Roaming Militia to move through previously visited sectors, even if restricted.
// HEADROCK HAM B1: Allows Restricted Roaming Militia to move through previously visited sectors.
BOOLEAN fUnrestrictVisited;
// HEADROCK HAM B1: Allows the capture of towns to dynamically alter roaming restrictions
+8
View File
@@ -15198,6 +15198,10 @@ BOOLEAN CanCharacterTrainMobileMilitia( SOLDIERTYPE *pSoldier )
// return( FALSE );
//}
if ( 100 <= GetMobileMilitiaQuota( FALSE ) )
return ( FALSE );
// If we've reached this, then all is well.
return( TRUE );
@@ -15217,6 +15221,10 @@ BOOLEAN CanCharacterTrainMilitiaWithErrorReport( SOLDIERTYPE *pSoldier )
return( FALSE );
}
if ( 100 <= GetMobileMilitiaQuota( TRUE ) )
return ( FALSE );
///////////////////////////////
// Test for required Leadership
+379 -17
View File
@@ -25,6 +25,8 @@
#include "Auto Resolve.h"
#include "Vehicles.h"
#include "Tactical Save.h"
#include "Campaign.h"
#include "message.h"
#endif
#include "connect.h"
@@ -514,14 +516,15 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
ubNumEnemiesNearTarget > 0 )
{
// Both sectors threatened.
if (gGameExternalOptions.gfAllowReinforcements && !gGameExternalOptions.gfAllowReinforcementsOnlyInCity)
//Moa: removed below: reinforcement is handled elsewhere, the function below is even better then 50%/50% because it leaves
//a chance to make one sector fully defended instead of possibly two losses. Talking about unfull groups - full groups wont change anyway.
/*if (gGameExternalOptions.gfAllowReinforcements && !gGameExternalOptions.gfAllowReinforcementsOnlyInCity)
{
// Militia will spread out between the two sectors to maximize defensive capability, since they can
// always reinforce one another if either sector is attacked.
ubChanceToSpreadOut = 100;
}
else
else*/
{
// Militia chance to spread out is based on whether the Origin or the Destination are under greater
// threat. If the destination is more threatened, militia are more likely to reinforce it
@@ -531,20 +534,7 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
ubChanceToSpreadOut = __min( 100, (ubNumEnemiesNearOrigin * 100) / usTotalNumEnemies );
}
}
else if (NumEnemiesInFiveSectors( sMapX, sMapY ) > 0 &&
NumEnemiesInFiveSectors( sTMapX, sTMapY ) > 0 )
{
// Both sectors threatened. Militia will spread out between them, to maximize defensive capability.
ubChanceToSpreadOut = 100;
}
else if (NumEnemiesInFiveSectors( sMapX, sMapY ) > 0 &&
NumEnemiesInFiveSectors( sTMapX, sTMapY ) == 0 )
{
// Source sector is threatened, while destination is not. The group does not
// move at all, as it is already in a good position to defend.
return;
}
else
{
///////////////////////////////////////////////////////
@@ -575,6 +565,19 @@ void MoveMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY, BOOL
{
ubChanceToSpreadOut = 0;
}
if (!gGameExternalOptions.gfAllowMilitiaSpread )
{
// Spreading is not allowed by user. Let them fill up the target sector.
ubChanceToSpreadOut = 0;
}
else if ( !gGameExternalOptions.gfAllowMilitiaSpreadWhenFollowing && PlayerMercsInSector_MSE( (UINT8) sTMapX, (UINT8) sTMapY, FALSE ) )
{
// There is a Player in targetsector or about to arrive, but spreading is not allowed by user.
// Let them fill up the target sector
ubChanceToSpreadOut = 0;
}
}
}
@@ -1488,7 +1491,7 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY )
// moving squad, if it is not a SAM site
if( ( fSourceCityAllowsRoaming ) && (!IsThisSectorASAMSector( sMapX, sMapY, 0 )) )
{
if( !PlayerMercsInSector_MSE( (UINT8)sMapX, (UINT8)sMapY, FALSE ) ) // and there's no player's mercs in the sector
if( !gGameExternalOptions.gfAllowMilitiaFollowPlayer || !PlayerMercsInSector_MSE( (UINT8)sMapX, (UINT8)sMapY, FALSE ) ) // and there's no player's mercs in the sector, or they are not forced to follow
{
if( GetWorldHour() % 2 )return;
@@ -1569,6 +1572,9 @@ void UpdateMilitiaSquads(INT16 sMapX, INT16 sMapY )
pEnemyGroup->ubNextX = targetX;
pEnemyGroup->ubNextY = targetY;
*/
//Moa: handle deserters before moving in hostile territory
MobileMilitiaDeserters( targetX, targetY, TRUE, TRUE );
gfMSBattle = TRUE;
// GroupArrivedAtSector( pEnemyGroup->ubGroupID , TRUE, FALSE );
@@ -2251,3 +2257,359 @@ void InitManualMobileRestrictions()
gubManualRestrictMilitia[x] = MANUAL_MOBILE_NO_RESTRICTION;
}
}
extern BOOLEAN IsMercOnTeam(UINT8 ubMercID);
// @brief Calculates the contingent for mobile militia.
// Calculates current active mobile militia and compares to variable maximum limit which can be altered by external data.
// @param printMessage Set to TRUE to get a screenmessage telling the player which maximum is reached. No message is generated when the maximum is not yet reached (<=100).
// @return The current percentage (0% - 255%). If the feature is deactivated allways 0 is returned.
UINT8 GetMobileMilitiaQuota( BOOLEAN printMessage )
{
///////////////////////
// Check for maximum mobiles allowed
//
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode > 1 )
{
//what we need to know
UINT16 iActiveMobiles = 0, iCurrentMax = 0;
UINT16 iTownSectorsUnderPlayerControl = 0, iTownSectorsLiberatedAtLeastOnce = 0;
UINT8 iTownsUnderPlayerControl = 0, iCurrentProgress = 0, iMaxProgress = 0, iNumRebelsInPlayerTeam = 0;
//temp values for sectors we gonna check
INT8 iCurrT_ID, test;
UINT16 iStrategicMapID, iSectorInfoID;
SECTORINFO *pSectorInfo;
// start gathering data
if (gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 8U) // check for TownsLiberated is active
for ( iCurrT_ID = 0; iCurrT_ID < NUM_TOWNS; iCurrT_ID++) // for each town
{
if ( GetTownSectorsUnderControl( iCurrT_ID ) == GetTownSectorSize( iCurrT_ID ) )
iTownsUnderPlayerControl++; // remember player has that town under control
}
for ( iSectorInfoID = 0; iSectorInfoID < 255; iSectorInfoID++) // for each sector ...
{
iStrategicMapID = SECTOR_INFO_TO_STRATEGIC_INDEX(iSectorInfoID);
pSectorInfo = &( SectorInfo[ iSectorInfoID ] );
iCurrT_ID = StrategicMap[ iStrategicMapID ].bNameId;
if ( iCurrT_ID != BLANK_SECTOR )
{
// we have found a town (no sam site)
if ( StrategicMap[ iStrategicMapID ].fEnemyControlled == FALSE )
iTownSectorsUnderPlayerControl++; // remember player currently controls that town sector
if ( pSectorInfo->fSurfaceWasEverPlayerControlled == TRUE )
iTownSectorsLiberatedAtLeastOnce++; // remember player had allready liberated that town sector once
if ( MilitiaTrainingAllowedInTown( iCurrT_ID ) == FALSE ) // considered as mobile only if in that town training is taboo (Tixa, Omerta..)
iActiveMobiles += CountMilitia( pSectorInfo );
//for ( UINT8 militiaLevel = 0; militiaLevel < MAX_MILITIA_LEVELS; militiaLevel++ )
// iActiveMobiles += pSectorInfo->ubNumberOfCivsAtLevel[ militiaLevel ]; // remember number of roaming militia in that town sector (green, regular, elite, ..)
}
//else if ( StrategicMap[ iStrategicMapID ].bSAMCondition > 0 ) //faster then below, but not safe
else if ( MilitiaTrainingAllowedInSector( SECTORX(iSectorInfoID), SECTORY(iSectorInfoID), 0 ) == FALSE )
{
// we are in wilderness
//for ( UINT8 militiaLevel = 0; militiaLevel < MAX_MILITIA_LEVELS; militiaLevel++ )
// iActiveMobiles += pSectorInfo->ubNumberOfCivsAtLevel[ militiaLevel ]; // remember number of roaming militia in that sector (green, regular, elite, ..)
iActiveMobiles += CountMilitia( pSectorInfo );
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 64U ) // check for rebels in player team is active
{
if ( gProfilesRPC != NULL )
{
UINT16 rebelStructSize = sizeof ( gProfilesRPC );
for (UINT16 rebelPC = 0; rebelPC < rebelStructSize; rebelPC++)
{
if ( IsMercOnTeam ( gProfilesRPC[ rebelPC ].ProfilId ) ) iNumRebelsInPlayerTeam++;
}
}
//if ( IsMercOnTeam ( IRA ) ) iNumRebelsInPlayerTeam++;
//if ( IsMercOnTeam ( DIMITRI ) ) iNumRebelsInPlayerTeam++;
//if ( IsMercOnTeam ( CARLOS ) ) iNumRebelsInPlayerTeam++;
//if ( IsMercOnTeam ( MIGUEL ) ) iNumRebelsInPlayerTeam++;
//if ( IsMercOnTeam ( DYNAMO ) ) iNumRebelsInPlayerTeam++;
//if ( IsMercOnTeam ( ENRICO ) ) iNumRebelsInPlayerTeam++;
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 16U ) // check for current progress is active
iCurrentProgress = CurrentPlayerProgressPercentage();
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 32U ) // check for max progress is active
iMaxProgress = HighestPlayerProgressPercentage();
//end gathering data
/////////////////////
// calc maximum (note: the modifier was initilized allready with MOBILE_MILITIA_MAX_ACTIVE_MODIFIER * MAX_MILITIA_PER_SECTOR)
UINT8 iModeMatch = 0; //takes the mode which matches the maximum used in order to build a message later on (0=no match 1..6)
UINT16 iCalc;
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 128U ) // we are using the highest value
{
iCurrentMax = 0;
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 2U ) // check for town sectors under player control is active
{
iCalc = (UINT16) ( iTownSectorsUnderPlayerControl * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier );
if ( iCurrentMax <= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 1;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 4U ) // check for town sectors liberated at least once is active
{
iCalc = (UINT16) (iTownSectorsLiberatedAtLeastOnce * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier );
if ( iCurrentMax <= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 2;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 8U )
{
iCalc = (UINT16) (iTownsUnderPlayerControl * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier * 3 );
if ( iCurrentMax <= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 3;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 16U )
{
iCalc = (UINT16) (iCurrentProgress * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier * 20 / 100 );
if ( iCurrentMax <= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 4;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 32U )
{
iCalc = (UINT16) (iMaxProgress * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier * 20 / 100 );
if ( iCurrentMax <= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 5;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 64U )
{
iCalc = (UINT16) (iNumRebelsInPlayerTeam * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier * 3 );
if ( iCurrentMax <= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 6;
}
}
}
else // we are using lowest value
{
iCurrentMax = (UINT16) -1;
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 2U )
{
iCalc = (UINT16) ( iTownSectorsUnderPlayerControl * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier );
if ( iCurrentMax >= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 1;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 4U )
{
iCalc = (UINT16) (iTownSectorsLiberatedAtLeastOnce * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier );
if ( iCurrentMax >= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 2;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 8U )
{
iCalc = (UINT16) (iTownsUnderPlayerControl * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier * 3 );
if ( iCurrentMax >= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 3;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 16U )
{
iCalc = (UINT16) (iCurrentProgress * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier * 20 / 100 );
if ( iCurrentMax >= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 4;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 32U )
{
iCalc = (UINT16) (iMaxProgress * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier * 20 / 100 );
if ( iCurrentMax >= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 5;
}
}
if ( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 64U )
{
iCalc = (UINT16) (iNumRebelsInPlayerTeam * gGameExternalOptions.gfpMobileMilitiaMaxActiveModifier * 3 );
if ( iCurrentMax >= iCalc )
{
iCurrentMax = iCalc;
iModeMatch = 6;
}
}
}
/////////////////////
//Notify player
if ( iActiveMobiles >= iCurrentMax )
{
if ( printMessage && iModeMatch > 0 )//fail safe to avoid in-buffer == out-buffer
{
// providing feedback why player cant train more.
CHAR16 sString[200];
swprintf( sString, pMilitiaConfirmStrings[15], iActiveMobiles, iCurrentMax, pMilitiaConfirmStrings[15 + iModeMatch] );//We reached maximum (..active../..max..)..make this..to do sth
//ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, sString );
DoScreenIndependantMessageBox(sString, MSG_BOX_FLAG_OK, NULL);
}
}
return ( iCurrentMax == 0 ? 255 : (iActiveMobiles * 100 / iCurrentMax) );
//return ( iCurrentMax == 0 ? 255 : max( 255, (iActiveMobiles * 100 / iCurrentMax) ) );
}//end check for maximum mobile militia allowed
return 0;
}
//@brief Checks for militia quota and removes randomly some of militia if there are too many.
// Deserting works only if the feature is enabled and the sector is threatened by an adjacent enemy presence.
// The chance to generate deserters raises with the quota.
//@param sMapX, sMapY Strategic sector coordinate which will be checked.
//@param fDeleteEquipment If the militia has any equipment it will be deleted when he is a deserter.
//@param fPrintMessage Notifies player that some militia have deserted.
//@auth Moa
void MobileMilitiaDeserters(INT16 sMapX, INT16 sMapY, BOOLEAN fDeleteEquip, BOOLEAN fPrintMessage)
{
// if more then allowed mobiles are active some of them will desert (green and only some regulars, elites will never desert)
UINT8 desertersGreen = 0, desertersRegular = 0;
BOOLEAN enemiesNear = FALSE;
// feature not activated, return
if (!( gGameExternalOptions.gbMobileMilitiaMaxActiveMode & 1U ) )
return;
// Training allowed here therefore not a sector for mobile militia, return
if ( gfMilitiaAllowedInTown [ GetTownIdForSector( sMapX, sMapY ) ] )
return;
// This is a SAM site therefore no mobile militia here, return
if (IsThisSectorASAMSector( sMapX, sMapY, 0 ))
return;
///////////////////////
// check enemy presence to decide if mobiles are threatened and some will desert.
// Note: cant use NumEnemiesInFiveSectors() as it does not work for omerta or when reinforcements are deactivated, also it uses generateDirectionInfo(), which is used for militia movement.
UINT8 eAdmins = 0, eTroops = 0, eElites = 0;
//enemies in current sector
GetNumberOfEnemiesInSector( sMapX, sMapY, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
enemiesNear = TRUE;
if ( ( sMapX > MINIMUM_VALID_X_COORDINATE ) && !enemiesNear )
{
//left side
GetNumberOfEnemiesInSector( sMapX - 1, sMapY, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
enemiesNear = TRUE;
}
if ( ( sMapX < MAXIMUM_VALID_X_COORDINATE ) && !enemiesNear)
{
//right side
GetNumberOfEnemiesInSector( sMapX + 1, sMapY, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
enemiesNear = TRUE;
}
if ( ( sMapY > MINIMUM_VALID_Y_COORDINATE ) && !enemiesNear )
{
//top side
GetNumberOfEnemiesInSector( sMapX, sMapY - 1, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
enemiesNear = TRUE;
}
if ( ( sMapY < MAXIMUM_VALID_Y_COORDINATE ) && !enemiesNear)
{
//bottom side
GetNumberOfEnemiesInSector( sMapX, sMapY + 1, &eAdmins, &eTroops, &eElites );
if ( (eAdmins > 0) || (eTroops > 0) ||(eElites > 0) )
enemiesNear = TRUE;
}
/////////////////////////
//calc number of deserters
if ( enemiesNear ) //if deserting feature is active, this is a sector where mobile militia is allowed and there is a threat at target
{
UINT8 quota = GetMobileMilitiaQuota( FALSE );
if (quota > 100) //more active then allowed
{
UINT8 militiaGreen = SectorInfo[ SECTOR( sMapX, sMapY) ].ubNumberOfCivsAtLevel[ GREEN_MILITIA ];
UINT8 militiaRegular = SectorInfo[ SECTOR( sMapX, sMapY) ].ubNumberOfCivsAtLevel[ REGULAR_MILITIA ];
desertersGreen = (quota - 100) * militiaGreen / 100;
desertersGreen = Random( min( militiaGreen, desertersGreen ) );//cant remove more then actually exist in that group
desertersRegular = (quota - 100) * militiaRegular / 200;
desertersRegular = Random( min ( militiaRegular, desertersRegular ) );
}
}
////////////////////////
//remove militia
if ( desertersRegular + desertersGreen > 0 )
{
StrategicRemoveMilitiaFromSector( sMapX, sMapY, GREEN_MILITIA, desertersGreen );
StrategicRemoveMilitiaFromSector( sMapX, sMapY, REGULAR_MILITIA, desertersRegular );
///////////////////////////
//remove equipment
if ( fDeleteEquip && gGameExternalOptions.fMilitiaUseSectorInventory)
{
SOLDIERCREATE_STRUCT trashIt;
UINT8 cnt = desertersGreen;
while ( cnt > 0 )
{
TakeMilitiaEquipmentfromSector( sMapX, sMapY, 0, &trashIt, SOLDIER_CLASS_GREEN_MILITIA);
cnt--;
}
cnt = desertersRegular;
while ( cnt > 0 )
{
TakeMilitiaEquipmentfromSector( sMapX, sMapY, 0, &trashIt, SOLDIER_CLASS_REG_MILITIA);
cnt--;
}
}
///////////////////////////
//notify player
if ( fPrintMessage )
{
CHAR16 sSector[16];
GetShortSectorString( sMapX, sMapY, sSector );
//using screen message to have it logged. Cant use msgBox as it prevents showing the autoresolve screen.
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMilitiaConfirmStrings[ 22 ], ( desertersRegular + desertersGreen ), sSector );
}
}
//clean up
if (gfStrategicMilitiaChangesMade)
{
ResetMilitia();
}
}
+4
View File
@@ -65,4 +65,8 @@ UINT8 ManualMobileMovementAllowed( UINT8 ubSector );
// HEADROCK HAM 4: Initialize all manual restrictions;
void InitManualMobileRestrictions();
//Moa: for mobile militia: militia deserters and maximum allowed
extern void MobileMilitiaDeserters( INT16 sMapX, INT16 sMapY, BOOLEAN fDeleteEquip, BOOLEAN fPrintMessage );
extern UINT8 GetMobileMilitiaQuota( BOOLEAN printMessage );
#endif
+10
View File
@@ -844,6 +844,16 @@ DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Militia3");
gfYesNoPromptIsForContinue = TRUE;
//Moa: prevent continue training when at/above maximum
if ( ubMilitiaType == MOBILE_MILITIA )
{
if ( 100 <= GetMobileMilitiaQuota( TRUE ) )
{
MilitiaTrainingRejected( MOBILE_MILITIA );
return;
}
}
// is there enough loyalty to continue training
if( DoesSectorMercIsInHaveSufficientLoyaltyToTrainMilitia( pSoldier ) == FALSE )
{
+8
View File
@@ -5099,6 +5099,14 @@ STR16 pMilitiaConfirmStrings[] =
L"继续在%s (%s %d)训练巡逻民兵吗?", // L"Continue training mobile militia in %s (%s %d)?", // HEADROCK HAM 3.6: Mobile Militia
L"在%d地区训练巡逻民兵将花费$%d。%s", // L"Training mobile militia in %d sectors will cost $ %d. %s", // HEADROCK HAM 3.6: Mobile Militia
L"训练一队民兵要花费$", // L"Training a squad of mobile militia will cost $", // HEADROCK HAM 3.6: Mobile Militia
L"You cannot train more mobile militia because the maximum is reached (%d/%d). You have to %s first in order to train more.", // TODO.Translate
L"liberate more town sectors", // TODO.Translate
L"liberate new town sectors", // TODO.Translate
L"liberate more towns", // TODO.Translate
L"regain your lost progress", // TODO.Translate
L"progress further", // TODO.Translate
L"recruit more rebels", // TODO.Translate
L"The militia team leader has to inform you that %d fellow have deserted facing enemy in sector %s.", // TODO.Translate
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel
+8
View File
@@ -5101,6 +5101,14 @@ STR16 pMilitiaConfirmStrings[] =
L"Continue training mobile militia in %s (%s %d)?", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"Training mobile militia in %d sectors will cost $ %d. %s", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"Training a squad of mobile militia will cost $", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"You cannot train more mobile militia because the maximum is reached (%d/%d). You have to %s first in order to train more.", // TODO.Translate
L"liberate more town sectors", // TODO.Translate
L"liberate new town sectors", // TODO.Translate
L"liberate more towns", // TODO.Translate
L"regain your lost progress", // TODO.Translate
L"progress further", // TODO.Translate
L"recruit more rebels", // TODO.Translate
L"The militia team leader has to inform you that %d fellow have deserted facing enemy in sector %s.", // TODO.Translate
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel
+8
View File
@@ -5099,6 +5099,14 @@ STR16 pMilitiaConfirmStrings[] =
L"Continue training mobile militia in %s (%s %d)?", // HEADROCK HAM 3.6: Mobile Militia
L"Training mobile militia in %d sectors will cost $ %d. %s", // HEADROCK HAM 3.6: Mobile Militia
L"Training a squad of mobile militia will cost $", // HEADROCK HAM 3.6: Mobile Militia
L"You cannot train more mobile militia because the maximum is reached (%d/%d). You have to %s first in order to train more.", //Moa: maximum number mobile militia (15)
L"liberate more town sectors",
L"liberate new town sectors",
L"liberate more towns",
L"regain your lost progress",
L"progress further",
L"recruit more rebels",
L"The militia team leader has to inform you that %d fellow have deserted facing enemy in sector %s.", //Moa: mobile deserted (22)
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel
+8
View File
@@ -5106,6 +5106,14 @@ STR16 pMilitiaConfirmStrings[] =
L"Voulez-vous poursuivre l'entraînement de la milice mobile à %s (%s %d)?", // HEADROCK HAM 3.6: Mobile Militia
L"L'entraînement des milices mobiles dans %d secteurs vous coûtera %d $. %s", // HEADROCK HAM 3.6: Mobile Militia
L"L'entraînement de la milice mobile vous coûtera $", // HEADROCK HAM 3.6: Mobile Militia
L"You cannot train more mobile militia because the maximum is reached (%d/%d). You have to %s first in order to train more.", // TODO.Translate
L"liberate more town sectors", // TODO.Translate
L"liberate new town sectors", // TODO.Translate
L"liberate more towns", // TODO.Translate
L"regain your lost progress", // TODO.Translate
L"progress further", // TODO.Translate
L"recruit more rebels", // TODO.Translate
L"The militia team leader has to inform you that %d fellow have deserted facing enemy in sector %s.", // TODO.Translate
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel
+8
View File
@@ -4946,6 +4946,14 @@ STR16 pMilitiaConfirmStrings[] =
L"Mobile Milizen in %s (%s %d) weitertrainieren?", // HEADROCK HAM 3.6: Mobile Militia
L"Mobile Milizen in %d Sektoren zu trainieren kostet $ %d. %s", // HEADROCK HAM 3.6: Mobile Militia
L"Eine mobile Milizeinheit für diese Stadt zu trainieren kostet $", // HEADROCK HAM 3.6: Mobile Militia
L"Sie können keine weiteren mobilen Milizen ausbilden, da das Maximum erreicht wurde (%d/%d). Sie müssen zunächst %s um weitere zu trainieren.",
L"weitere Stadtteile befreien",
L"neue Stadtteile befreien",
L"mehr Städte erobern",
L"den verlorenen Fortschritt wieder aufholen",
L"weiter fortschreiten",
L"mehr Rebellen rekrutieren",
L"Der Miliztruppführer muss Sie leider darüber informieren, dass %d Mitstreiter im Angesicht des Feindes desertierten im Sektor %s.",
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel
+8
View File
@@ -5084,6 +5084,14 @@ STR16 pMilitiaConfirmStrings[] =
L"Continue training mobile militia in %s (%s %d)?", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"Training mobile militia in %d sectors will cost $ %d. %s", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"Training a squad of mobile militia will cost $", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"You cannot train more mobile militia because the maximum is reached (%d/%d). You have to %s first in order to train more.", // TODO.Translate
L"liberate more town sectors", // TODO.Translate
L"liberate new town sectors", // TODO.Translate
L"liberate more towns", // TODO.Translate
L"regain your lost progress", // TODO.Translate
L"progress further", // TODO.Translate
L"recruit more rebels", // TODO.Translate
L"The militia team leader has to inform you that %d fellow have deserted facing enemy in sector %s.", // TODO.Translate
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel
+8
View File
@@ -5108,6 +5108,14 @@ STR16 pMilitiaConfirmStrings[] =
L"Kontynuuj trening ruchomej samoobrony w %s (%s %d)?", // HEADROCK HAM 3.6: Mobile Militia
L"Trenowanie ruchomej samoobrony w %d sektorach będzie kosztować %d$. %s", // HEADROCK HAM 3.6: Mobile Militia
L"Trenowanie ruchomej samoobrony będzie kosztować $", // HEADROCK HAM 3.6: Mobile Militia
L"You cannot train more mobile militia because the maximum is reached (%d/%d). You have to %s first in order to train more.", // TODO.Translate
L"liberate more town sectors", // TODO.Translate
L"liberate new town sectors", // TODO.Translate
L"liberate more towns", // TODO.Translate
L"regain your lost progress", // TODO.Translate
L"progress further", // TODO.Translate
L"recruit more rebels", // TODO.Translate
L"The militia team leader has to inform you that %d fellow have deserted facing enemy in sector %s.", // TODO.Translate
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel
+8
View File
@@ -5098,6 +5098,14 @@ STR16 pMilitiaConfirmStrings[] =
L"Продолжить тренировку мобильного подразделения в %s (%s %d)?",
L"Тренировка мобильного подразделения в секторе %d обойдётся в $ %d. %s",
L"Тренировка мобильного подразделения ополченцев обойдётся в $",
L"You cannot train more mobile militia because the maximum is reached (%d/%d). You have to %s first in order to train more.", // TODO.Translate
L"liberate more town sectors", // TODO.Translate
L"liberate new town sectors", // TODO.Translate
L"liberate more towns", // TODO.Translate
L"regain your lost progress", // TODO.Translate
L"progress further", // TODO.Translate
L"recruit more rebels", // TODO.Translate
L"The militia team leader has to inform you that %d fellow have deserted facing enemy in sector %s.", // TODO.Translate
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel
+8
View File
@@ -5102,6 +5102,14 @@ STR16 pMilitiaConfirmStrings[] =
L"Continue training mobile militia in %s (%s %d)?", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"Training mobile militia in %d sectors will cost $ %d. %s", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"Training a squad of mobile militia will cost $", // HEADROCK HAM 3.6: Mobile Militia // TODO.Translate
L"You cannot train more mobile militia because the maximum is reached (%d/%d). You have to %s first in order to train more.", // TODO.Translate
L"liberate more town sectors", // TODO.Translate
L"liberate new town sectors", // TODO.Translate
L"liberate more towns", // TODO.Translate
L"regain your lost progress", // TODO.Translate
L"progress further", // TODO.Translate
L"recruit more rebels", // TODO.Translate
L"The militia team leader has to inform you that %d fellow have deserted facing enemy in sector %s.", // TODO.Translate
};
//Strings used in the popup box when withdrawing, or depositing money from the $ sign at the bottom of the single merc panel