mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
New Feature: Militia Volunteer Pool limits the number of militia we can train. Turned off by default.
GameDir >= r2210 is recommended. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7746 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -1994,6 +1994,11 @@ void LoadGameExternalOptions()
|
||||
// HEADROCK HAM 3: Define effect of "TEACHER" trait in increasing effective leadership, for purposes of eligibility for training militia. This is a percentage value. HAM Default would be 200 = double effective leadership for each TEACHING level.
|
||||
gGameExternalOptions.usTeacherTraitEffectOnLeadership = iniReader.ReadInteger("Militia Training Settings","TEACHER_TRAIT_EFFECT_ON_LEADERSHIP", 100, 1, 10000);
|
||||
|
||||
//################# Militia Volunteer Pool Settings ###################
|
||||
gGameExternalOptions.fMilitiaVolunteerPool = iniReader.ReadBoolean( "Militia Volunteer Pool Settings", "MILITIA_VOLUNTEER_POOL", FALSE );
|
||||
gGameExternalOptions.dMilitiaVolunteerGainFactorHourly = iniReader.ReadFloat( "Militia Volunteer Pool Settings", "MILITIA_VOLUNTEER_POOL_GAINFACTOR_HOURLY", 0.001f, 0.0f, 1.0f );
|
||||
gGameExternalOptions.dMilitiaVolunteerGainFactorLiberation = iniReader.ReadFloat( "Militia Volunteer Pool Settings", "MILITIA_VOLUNTEER_POOL_GAINFACTOR_LIBERATION", 0.2f, 0.0f, 1.0f );
|
||||
gGameExternalOptions.dMilitiaVolunteerMultiplierFarm = iniReader.ReadFloat( "Militia Volunteer Pool Settings", "MILITIA_VOLUNTEER_POOL_MULTIPLIER_FARM", 0.05f, 0.0f, 1.0f );
|
||||
|
||||
//################# Mobile Militia Training Settings ##################
|
||||
|
||||
|
||||
@@ -287,6 +287,12 @@ typedef struct
|
||||
INT32 iVeteranCostModifier;
|
||||
INT32 iMinLoyaltyToTrain;
|
||||
|
||||
// Flugente: militia volunteer pool
|
||||
BOOLEAN fMilitiaVolunteerPool;
|
||||
FLOAT dMilitiaVolunteerGainFactorHourly;
|
||||
FLOAT dMilitiaVolunteerGainFactorLiberation;
|
||||
FLOAT dMilitiaVolunteerMultiplierFarm;
|
||||
|
||||
INT32 iMaxEnemyGroupSize;
|
||||
|
||||
BOOLEAN fMercDayOne;
|
||||
|
||||
+4
-1
@@ -166,7 +166,10 @@ typedef struct
|
||||
BOOLEAN bJohnEscorted;// and if they were at all
|
||||
UINT8 ubJohnPossibleMissedFlights;// and how many flights he already missed
|
||||
|
||||
UINT8 bPadding[ 77 ]; // Flugente: 86->77
|
||||
// Flugente: militia volunteer pool. No relation to the laptop whatsoever, but I'm not creating a new struct for one variable
|
||||
FLOAT dMilitiaVolunteerPool;
|
||||
|
||||
UINT8 bPadding[ 72 ];
|
||||
|
||||
} LaptopSaveInfoStruct;
|
||||
|
||||
|
||||
@@ -1412,6 +1412,10 @@ BOOLEAN CanCharacterTrainMilitia( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
AssertNotNIL(pSoldier);
|
||||
|
||||
// Flugente: militia volunteer pool
|
||||
if ( !GetVolunteerPool() )
|
||||
return FALSE;
|
||||
|
||||
// Make sure the basic sector/merc variables are still applicable. This is simply a fail-safe.
|
||||
if( !BasicCanCharacterTrainMilitia( pSoldier ) )
|
||||
{
|
||||
@@ -2480,6 +2484,9 @@ void UpdateAssignments()
|
||||
// reset scan flags in all sectors
|
||||
ClearSectorScanResults();
|
||||
|
||||
// update militia volunteer count
|
||||
UpdateVolunteers();
|
||||
|
||||
// run through sectors and handle each type in sector
|
||||
for(sX = 0 ; sX < MAP_WORLD_X; ++sX )
|
||||
{
|
||||
@@ -18375,6 +18382,13 @@ BOOLEAN CanCharacterTrainMilitiaWithErrorReport( SOLDIERTYPE *pSoldier )
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
if ( !GetVolunteerPool() )
|
||||
{
|
||||
swprintf( sString, L"There are no volunteers for militia left!" );
|
||||
DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL );
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if ( 100 <= GetMobileMilitiaQuota( TRUE ) )
|
||||
return ( FALSE );
|
||||
|
||||
|
||||
@@ -7667,6 +7667,25 @@ void MilitiaGroupBoxButtonCallback( GUI_BUTTON *btn, INT32 reason )
|
||||
|
||||
void DisplayMilitiaGroupBox()
|
||||
{
|
||||
// if we play with a limited militia pool, show us how many we have
|
||||
if ( fShowMilitia && gGameExternalOptions.fMilitiaVolunteerPool )
|
||||
{
|
||||
CHAR16 sVolunteerString[200];
|
||||
|
||||
SetFont( FONT12ARIAL );
|
||||
|
||||
if ( GetVolunteerPool() >= 2 * gGameExternalOptions.iTrainingSquadSize )
|
||||
SetFontForeground( FONT_FCOLOR_GREEN );
|
||||
else if ( GetVolunteerPool( ) >= gGameExternalOptions.iTrainingSquadSize )
|
||||
SetFontForeground( FONT_FCOLOR_YELLOW );
|
||||
else
|
||||
SetFontForeground( FONT_FCOLOR_RED );
|
||||
|
||||
// header
|
||||
swprintf( sVolunteerString, szMilitiaStrategicMovementText[8], GetVolunteerPool( ), CalcHourlyVolunteerGain( ) );
|
||||
mprintf( MapScreenRect.iLeft + 20, MapScreenRect.iBottom - 10, sVolunteerString );
|
||||
}
|
||||
|
||||
if ( !gMilitiaGroupBoxCreated )
|
||||
return;
|
||||
|
||||
@@ -7679,6 +7698,8 @@ void DisplayMilitiaGroupBox()
|
||||
return;
|
||||
}
|
||||
|
||||
SetFontForeground( FONT_FCOLOR_WHITE );
|
||||
|
||||
CreateMilitiaGroupBoxVideoObjects();
|
||||
|
||||
// move to defines later
|
||||
@@ -7715,7 +7736,7 @@ void DisplayMilitiaGroupBox()
|
||||
SetFontForeground( FONT_FCOLOR_WHITE );
|
||||
SetFontBackground( FONT_MCOLOR_BLACK );
|
||||
|
||||
//Display the background for the drop down window
|
||||
//Display the background
|
||||
ColorFillVideoSurfaceArea( FRAME_BUFFER, gMilitiaGroupBoxX, gMilitiaGroupBoxY, gMilitiaGroupBoxX + MILITIAGROUPBOX_WIDTH, gMilitiaGroupBoxY + MILITIAGROUPBOX_HEIGHT, Get16BPPColor( FROMRGB( 50, 50, 50 ) ) );
|
||||
|
||||
// mouse region - clicking on a group name selects that group
|
||||
|
||||
@@ -191,6 +191,9 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY,
|
||||
ubMilitiaToTrain = CalcNumMilitiaTrained(ubBestLeadership, TRUE);
|
||||
}
|
||||
|
||||
// Flugente: our pool of volunteers limits how many militia can be created
|
||||
ubMilitiaToTrain = min( ubMilitiaToTrain, GetVolunteerPool( ) );
|
||||
|
||||
// HEADROCK HAM 3.4: Composition of new Mobile Militia groups is now dictated by two INI settings controlling
|
||||
// the percentage of Elites and Regulars within the group. If the percentage for either is above 0, at least
|
||||
// one militia of that type will be created every time. Green militia are created based on whatever remains.
|
||||
@@ -302,6 +305,9 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY,
|
||||
ubTargetGreen--;
|
||||
}
|
||||
|
||||
// Flugente: substract volunteers
|
||||
AddVolunteers( -ubMilitiaToTrain );
|
||||
|
||||
while (ubMilitiaToTrain > 0)
|
||||
{
|
||||
|
||||
@@ -447,7 +453,7 @@ void GenerateMilitiaSquad(INT16 sMapX, INT16 sMapY, INT16 sTMapX, INT16 sTMapY,
|
||||
--pTargetSector->ubNumberOfCivsAtLevel[ELITE_MILITIA];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Update the militia if the current sector is affected
|
||||
if (gfStrategicMilitiaChangesMade)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
// HEADROCK HAM 3.6: Added for facility string printing...
|
||||
#include "PopUpBox.h"
|
||||
#include "CampaignStats.h" // added by Flugente
|
||||
#include "Town Militia.h" // added by Flugente
|
||||
#endif
|
||||
|
||||
#include "postalservice.h"
|
||||
@@ -391,10 +392,18 @@ BOOLEAN SetThisSectorAsPlayerControlled( INT16 sMapX, INT16 sMapY, INT8 bMapZ, B
|
||||
|
||||
//if ( ubTraverseType == )
|
||||
|
||||
if ( GetTownIdForSector( sMapX, sMapY ) != BLANK_SECTOR )
|
||||
UINT8 townid = GetTownIdForSector( sMapX, sMapY );
|
||||
if ( townid != BLANK_SECTOR )
|
||||
{
|
||||
// first liberation of a town sector -> special texts
|
||||
gCurrentIncident.usIncidentFlags |= INCIDENT_FIRST_LIBERATION;
|
||||
|
||||
// liberating a town sector for the first time grants us an initial wave of volunteers
|
||||
UINT16 population = GetSectorPopulation( sMapX, sMapY );
|
||||
|
||||
FLOAT loyalpopulation = gTownLoyalty[townid].ubRating * population / 100;
|
||||
|
||||
AddVolunteers( loyalpopulation * gGameExternalOptions.dMilitiaVolunteerGainFactorLiberation );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,9 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
|
||||
UINT8 ubTrainerEffectiveLeadership = FindBestMilitiaTrainingLeadershipInSector ( sMapX, sMapY, pTrainer->bSectorZ, TOWN_MILITIA );
|
||||
UINT8 iTrainingSquadSize = __min(iMaxMilitiaPerSector, CalcNumMilitiaTrained(ubTrainerEffectiveLeadership, FALSE));
|
||||
|
||||
// Flugente: our pool of volunteers limits how many militia can be created
|
||||
iTrainingSquadSize = min( iTrainingSquadSize, GetVolunteerPool( ) );
|
||||
|
||||
DebugMsg (TOPIC_JA2,DBG_LEVEL_3,"Militia1");
|
||||
|
||||
// get town index
|
||||
@@ -310,6 +313,8 @@ void TownMilitiaTrainingCompleted( SOLDIERTYPE *pTrainer, INT16 sMapX, INT16 sMa
|
||||
++ubMilitiaTrained;
|
||||
}
|
||||
|
||||
AddVolunteers( -ubMilitiaTrained );
|
||||
|
||||
if (gfStrategicMilitiaChangesMade)
|
||||
{
|
||||
ResetMilitia();
|
||||
@@ -2142,7 +2147,7 @@ UINT8 CalcNumMilitiaTrained(UINT8 ubBestLeadership, BOOLEAN fMobile)
|
||||
ubMilitiaToTrain = __max(3, ubMilitiaToTrain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (ubMilitiaToTrain);
|
||||
}
|
||||
|
||||
@@ -2428,4 +2433,66 @@ UINT32 CalcMilitiaUpkeep( void )
|
||||
}
|
||||
|
||||
return (uiTotalPayment);
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: our militia volunteer pool is limited
|
||||
INT32 GetVolunteerPool()
|
||||
{
|
||||
// if this feature is off, we simply assume we have reserves
|
||||
if ( !gGameExternalOptions.fMilitiaVolunteerPool )
|
||||
return 999999;
|
||||
|
||||
// the pool is actually a float number, only return full volunteers though
|
||||
return (INT32)LaptopSaveInfo.dMilitiaVolunteerPool;
|
||||
}
|
||||
|
||||
// add/remove volunteers from pool
|
||||
void AddVolunteers( FLOAT asNum )
|
||||
{
|
||||
LaptopSaveInfo.dMilitiaVolunteerPool = max( 0, LaptopSaveInfo.dMilitiaVolunteerPool + asNum );
|
||||
}
|
||||
|
||||
FLOAT CalcHourlyVolunteerGain()
|
||||
{
|
||||
FLOAT loyalpopulation = 0.0f; // the number of loyal citizens, from which we derive the hourly volunteer gain
|
||||
FLOAT populationmodifier = 1.0f; // certain sectors/facilities under our control increase the volunteer gain
|
||||
|
||||
for ( UINT8 sX = 1; sX < MAP_WORLD_X - 1; ++sX )
|
||||
{
|
||||
for ( UINT8 sY = 1; sY < MAP_WORLD_X - 1; ++sY )
|
||||
{
|
||||
// not if the enemy controls this sector
|
||||
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].fEnemyControlled )
|
||||
continue;
|
||||
|
||||
UINT8 sector = SECTOR( sX, sY );
|
||||
|
||||
SECTORINFO *pSectorInfo = &(SectorInfo[sector]);
|
||||
|
||||
if ( !pSectorInfo )
|
||||
continue;
|
||||
|
||||
// TODO: modifier increase for every farm we control
|
||||
if ( pSectorInfo->ubTraversability[THROUGH_STRATEGIC_MOVE] == FARMLAND || pSectorInfo->ubTraversability[THROUGH_STRATEGIC_MOVE] == FARMLAND_ROAD )
|
||||
populationmodifier += gGameExternalOptions.dMilitiaVolunteerMultiplierFarm;
|
||||
|
||||
UINT8 ubTownID = StrategicMap[CALCULATE_STRATEGIC_INDEX( sX, sY )].bNameId;
|
||||
if ( ubTownID != BLANK_SECTOR )
|
||||
{
|
||||
UINT16 population = GetSectorPopulation( sX, sY );
|
||||
|
||||
loyalpopulation += gTownLoyalty[ubTownID].ubRating * population / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FLOAT hourlygain = loyalpopulation * populationmodifier * gGameExternalOptions.dMilitiaVolunteerGainFactorHourly;
|
||||
|
||||
return hourlygain;
|
||||
}
|
||||
|
||||
// every hour, controlled sectors add to our volunteer pool
|
||||
void UpdateVolunteers()
|
||||
{
|
||||
AddVolunteers( CalcHourlyVolunteerGain() );
|
||||
}
|
||||
|
||||
@@ -112,4 +112,16 @@ typedef struct MILITIA_LIST_TYPE
|
||||
// HEADROCK HAM 3.6: Calculate upkeep costs for militia
|
||||
UINT32 CalcMilitiaUpkeep( void );
|
||||
|
||||
// Flugente: militia volunteer pool
|
||||
// how many volunteers do we currently have?
|
||||
INT32 GetVolunteerPool();
|
||||
|
||||
// add/remove volunteers from pool
|
||||
void AddVolunteers( FLOAT asNum );
|
||||
|
||||
FLOAT CalcHourlyVolunteerGain();
|
||||
|
||||
// every hour, controlled sectors add to our volunteer pool
|
||||
void UpdateVolunteers();
|
||||
|
||||
#endif
|
||||
@@ -10042,6 +10042,8 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
|
||||
L"Militia Volunteers: %d (+%5.3f)",
|
||||
};
|
||||
|
||||
// WANNE: Some Chinese specific strings that needs to be in unicode!
|
||||
|
||||
@@ -10053,6 +10053,8 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
|
||||
L"Militia Volunteers: %d (+%5.3f)",
|
||||
};
|
||||
|
||||
#endif //DUTCH
|
||||
|
||||
@@ -10091,6 +10091,8 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
|
||||
L"Militia Volunteers: %d (+%5.3f)",
|
||||
};
|
||||
|
||||
#endif //ENGLISH
|
||||
|
||||
@@ -10039,6 +10039,8 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
|
||||
L"Militia Volunteers: %d (+%5.3f)",
|
||||
};
|
||||
|
||||
#endif //FRENCH
|
||||
|
||||
@@ -9870,6 +9870,8 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
|
||||
L"Militia Volunteers: %d (+%5.3f)",
|
||||
};
|
||||
|
||||
#endif //GERMAN
|
||||
|
||||
@@ -10049,6 +10049,8 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
|
||||
L"Militia Volunteers: %d (+%5.3f)",
|
||||
};
|
||||
|
||||
#endif //ITALIAN
|
||||
|
||||
@@ -10064,6 +10064,8 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
|
||||
L"Militia Volunteers: %d (+%5.3f)",
|
||||
};
|
||||
|
||||
#endif //POLISH
|
||||
|
||||
@@ -10037,6 +10037,8 @@ STR16 szMilitiaStrategicMovementText[] =
|
||||
L"Group %d (new)",
|
||||
L"Group %d",
|
||||
L"Final",
|
||||
|
||||
L"Militia Volunteers: %d (+%5.3f)",
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user