mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- New Feature: Enemy Generals are unique enemies whose location randomized and unknwon to the player. As long as they are alive, the enemy gets signifiant strategic boni. The player must learn of their location and take take them out, preferrably without alerting them prior.
- Covert Ops: Bleeding is deemed suspicious only if COVERT_DETECTEDIFBLEEDING is set to TRUE. - renamed special prisoners to officers. - lowered the priority of enemy troops becoming medics - prisoners in player-controlled prisons now use the prioner-colour scheme used by Shank and Dynamo Requires GameDir >= r2028. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7179 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+15
-2
@@ -1509,6 +1509,13 @@ void LoadGameExternalOptions()
|
||||
gGameExternalOptions.sEnemyOfficerSuppressionResistanceBonus = iniReader.ReadInteger("Tactical Enemy Role Settings", "ENEMY_OFFICERS_SUPPRESSION_RESISTANCE_BONUS", 10, 0, 50);
|
||||
gGameExternalOptions.dEnemyOfficerMoraleModifier = iniReader.ReadFloat ("Tactical Enemy Role Settings", "ENEMY_OFFICERS_MORALE_MODIFIER", 0.1f, 0.00f, 1.0f);
|
||||
gGameExternalOptions.dEnemyOfficerSurrenderStrengthBonus = iniReader.ReadFloat ("Tactical Enemy Role Settings", "ENEMY_OFFICERS_SURRENDERSTRENGTHBONUS", 0.1f, 0.00f, 1.0f);
|
||||
|
||||
gGameExternalOptions.fEnemyGenerals = iniReader.ReadBoolean( "Tactical Enemy Role Settings", "ENEMY_GENERALS", TRUE );
|
||||
gGameExternalOptions.usEnemyGeneralsNumber = iniReader.ReadInteger( "Tactical Enemy Role Settings", "ENEMY_GENERALS_NUMBER", 5, 1, 10 );
|
||||
gGameExternalOptions.usEnemyGeneralsBodyGuardsNumber = iniReader.ReadInteger( "Tactical Enemy Role Settings", "ENEMY_GENERALS_BODYGUARDS_NUMBER", 4, 0, 10 );
|
||||
gGameExternalOptions.fEnemyGeneralStrategicDecisionSpeedBonus = iniReader.ReadFloat( "Tactical Enemy Role Settings", "ENEMY_GENERALS_STRATEGIC_DECISION_SPEEDBONUS", 0.05f, 0.00f, 0.1f );
|
||||
gGameExternalOptions.fEnemyGeneralStrategicMovementSpeedBonus = iniReader.ReadFloat( "Tactical Enemy Role Settings", "ENEMY_GENERALS_STRATEGIC_MOVEMENT_SPEEDBONUS", 0.03f, 0.00f, 0.1f );
|
||||
|
||||
|
||||
//################# Tactical Cover System Settings ##################
|
||||
|
||||
@@ -1812,8 +1819,13 @@ void LoadGameExternalOptions()
|
||||
gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_ADMIN] = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INTERROGATION_POINTS_ADMIN", 80, 30, 1000);
|
||||
gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_REGULAR] = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INTERROGATION_POINTS_REGULAR", 100, gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_ADMIN], 1000);
|
||||
gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_ELITE] = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INTERROGATION_POINTS_ELITE", 100, gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_REGULAR], 1000);
|
||||
gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_SPECIAL] = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INTERROGATION_POINTS_SPECIAL", 100, gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_ELITE], 1000);
|
||||
|
||||
gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_OFFICER] = iniReader.ReadInteger( "Strategic Gameplay Settings", "PRISONER_INTERROGATION_POINTS_OFFICER", 100, gGameExternalOptions.ubPrisonerInterrogationPoints[PRISONER_ELITE], 1000 );
|
||||
|
||||
gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_ADMIN] = iniReader.ReadInteger( "Strategic Gameplay Settings", "PRISONER_INTERROGATION_ENEMY_GENERAL_CHANCE_ADMIN", 0, 0, 100 );
|
||||
gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_REGULAR] = iniReader.ReadInteger( "Strategic Gameplay Settings", "PRISONER_INTERROGATION_ENEMY_GENERAL_CHANCE_REGULAR", 1, gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_ADMIN], 100 );
|
||||
gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_ELITE] = iniReader.ReadInteger( "Strategic Gameplay Settings", "PRISONER_INTERROGATION_ENEMY_GENERAL_CHANCE_ELITE", 10, gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_REGULAR], 100 );
|
||||
gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_OFFICER] = iniReader.ReadInteger( "Strategic Gameplay Settings", "PRISONER_INTERROGATION_ENEMY_GENERAL_CHANCE_OFFICER", 60, gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_ELITE], 100 );
|
||||
|
||||
// CHRISL: Determine how Skyrider should handle landing in enemy occupied sectors
|
||||
gGameExternalOptions.ubSkyriderHotLZ = iniReader.ReadInteger("Strategic Gameplay Settings", "ALLOW_SKYRIDER_HOT_LZ", 0, 0, 3);
|
||||
|
||||
@@ -2509,6 +2521,7 @@ void LoadSkillTraitsExternalSettings()
|
||||
gSkillTraitValues.sCOCloseDetectionRange = iniReader.ReadInteger("Covert Ops","COVERT_CLOSE_DETECTION_RANGE", 10, 0, 100);
|
||||
gSkillTraitValues.sCOCloseDetectionRangeSoldierCorpse = iniReader.ReadInteger("Covert Ops","COVERT_CLOSE_DETECTION_RANGE_SOLDIER_CORPSE", 5, 0, 100);
|
||||
gSkillTraitValues.fCOElitesDetectNextTile = iniReader.ReadBoolean("Covert Ops","COVERT_ELITES_DETECT_NEXTTILE", TRUE);
|
||||
gSkillTraitValues.fCODetectIfBleeding = iniReader.ReadBoolean("Covert Ops","COVERT_DETECTEDIFBLEEDING", FALSE );
|
||||
|
||||
// Flugente: RADIO OPERATOR
|
||||
gSkillTraitValues.fROAllowArtillery = iniReader.ReadBoolean("Radio Operator","RADIO_OPERATOR_ARTILLERY", TRUE);
|
||||
|
||||
@@ -1358,6 +1358,7 @@ typedef struct
|
||||
UINT8 ubPrisonerProcessInfoDirectionChance;
|
||||
UINT8 ubPrisonerProcessRansomBaseChance;
|
||||
UINT16 ubPrisonerInterrogationPoints[4]; // points needed to interrogate a prisoner of a specific type
|
||||
UINT8 ubPrisonerInterrogationEnemyGeneralInfoChance[4]; // chance that when getting info from interrogation, this prisoner will tell us about general we do not yet know about
|
||||
|
||||
// Flugente: sexism/racism/etc.
|
||||
INT8 sMoraleModAppearance;
|
||||
@@ -1381,6 +1382,11 @@ typedef struct
|
||||
INT8 sEnemyOfficerSuppressionResistanceBonus;
|
||||
FLOAT dEnemyOfficerMoraleModifier;
|
||||
FLOAT dEnemyOfficerSurrenderStrengthBonus;
|
||||
BOOLEAN fEnemyGenerals;
|
||||
UINT16 usEnemyGeneralsNumber;
|
||||
UINT16 usEnemyGeneralsBodyGuardsNumber;
|
||||
FLOAT fEnemyGeneralStrategicDecisionSpeedBonus;
|
||||
FLOAT fEnemyGeneralStrategicMovementSpeedBonus;
|
||||
|
||||
|
||||
// Sandro: Alternative weapon holding (rifles fired from hip / pistols fired one-handed)
|
||||
@@ -1838,6 +1844,7 @@ typedef struct
|
||||
INT16 sCOCloseDetectionRange;
|
||||
INT16 sCOCloseDetectionRangeSoldierCorpse;
|
||||
BOOLEAN fCOElitesDetectNextTile;
|
||||
BOOLEAN fCODetectIfBleeding; // will we be discovered if we are bleeding?
|
||||
|
||||
// RADIO OPERATOR
|
||||
BOOLEAN fROAllowArtillery; // artillery can be forbidden for all teams with this setting
|
||||
|
||||
+2
-1
@@ -21,6 +21,7 @@ extern CHAR16 zTrackingNumber[16];
|
||||
// Keeps track of the saved game version. Increment the saved game version whenever
|
||||
// you will invalidate the saved game file
|
||||
|
||||
#define ENEMY_VIPS 154 // Flugente: enemy generals are placed randomly in the map
|
||||
#define MORE_LOCKS_AND_KEYS 153 // anv: externalized locks and keys to xml
|
||||
#define MILITIA_MOVEMENT 152 // Flugente: allow control of strategic militia movement
|
||||
#define SNITCH_TRAIT_EXTENDED 151 // anv: more soldier flags, remembering exposition of snitch
|
||||
@@ -72,7 +73,7 @@ extern CHAR16 zTrackingNumber[16];
|
||||
#define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes
|
||||
#define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system
|
||||
|
||||
#define SAVE_GAME_VERSION MORE_LOCKS_AND_KEYS
|
||||
#define SAVE_GAME_VERSION ENEMY_VIPS
|
||||
|
||||
//#define RUSSIANGOLD
|
||||
#ifdef __cplusplus
|
||||
|
||||
+51
-10
@@ -6581,7 +6581,7 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
|
||||
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
|
||||
|
||||
UINT8 prisoners[PRISONER_MAX] = {0};
|
||||
UINT16 numprisoners = GetNumberOfPrisoners( pSectorInfo, &prisoners[PRISONER_SPECIAL], &prisoners[PRISONER_ELITE], &prisoners[PRISONER_REGULAR], &prisoners[PRISONER_ADMIN] );
|
||||
UINT16 numprisoners = GetNumberOfPrisoners( pSectorInfo, &prisoners[PRISONER_OFFICER], &prisoners[PRISONER_ELITE], &prisoners[PRISONER_REGULAR], &prisoners[PRISONER_ADMIN] );
|
||||
|
||||
// add interrogation progress from last hour and erase it in data
|
||||
UINT32 interrogationpoints = pSectorInfo->uiInterrogationHundredsLeft;
|
||||
@@ -6650,7 +6650,7 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
|
||||
}
|
||||
}
|
||||
|
||||
UINT16 prisonersinterrogated = interrogatedprisoners[PRISONER_ADMIN] + interrogatedprisoners[PRISONER_REGULAR] + interrogatedprisoners[PRISONER_ELITE] + interrogatedprisoners[PRISONER_SPECIAL];
|
||||
UINT16 prisonersinterrogated = interrogatedprisoners[PRISONER_ADMIN] + interrogatedprisoners[PRISONER_REGULAR] + interrogatedprisoners[PRISONER_ELITE] + interrogatedprisoners[PRISONER_OFFICER];
|
||||
|
||||
// the part that gets left behind is saved to the map (but not the part that gets lost due to there not being enough prisoners)
|
||||
UINT32 losthundreds = interrogationpoints / 100;
|
||||
@@ -6687,6 +6687,47 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
|
||||
// chance that prisoner will give us random info about enemy positions
|
||||
else if ( result < gGameExternalOptions.ubPrisonerProcessDefectChance + gGameExternalOptions.ubPrisonerProcessInfoBaseChance )
|
||||
{
|
||||
// if this guy is an elite or a special prisoner, there is a chance he might tell us about high-value targets!
|
||||
BOOLEAN fGetInfoOnHiddenVIPs = FALSE;
|
||||
if ( i < interrogatedprisoners[PRISONER_ADMIN] )
|
||||
{
|
||||
if ( Chance( gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_ADMIN] ) )
|
||||
fGetInfoOnHiddenVIPs = TRUE;
|
||||
}
|
||||
else if ( i < interrogatedprisoners[PRISONER_REGULAR] )
|
||||
{
|
||||
if ( Chance( gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_REGULAR] ) )
|
||||
fGetInfoOnHiddenVIPs = TRUE;
|
||||
}
|
||||
else if ( i < interrogatedprisoners[PRISONER_ELITE] )
|
||||
{
|
||||
if ( Chance( gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_ELITE] ) )
|
||||
fGetInfoOnHiddenVIPs = TRUE;
|
||||
}
|
||||
else if ( i < interrogatedprisoners[PRISONER_OFFICER] )
|
||||
{
|
||||
if ( Chance( gGameExternalOptions.ubPrisonerInterrogationEnemyGeneralInfoChance[PRISONER_OFFICER] ) )
|
||||
fGetInfoOnHiddenVIPs = TRUE;
|
||||
}
|
||||
|
||||
if ( fGetInfoOnHiddenVIPs )
|
||||
{
|
||||
UINT16 unknownvipector = 0;
|
||||
if ( GetRandomUnknownVIPSector( unknownvipector ) )
|
||||
{
|
||||
// make this guy known to the player
|
||||
StrategicMap[unknownvipector].usFlags |= ENEMY_VIP_PRESENT_KNOWN;
|
||||
|
||||
CHAR16 str[128];
|
||||
GetSectorIDString( SECTORX( unknownvipector ), SECTORY( unknownvipector ), 0, str, TRUE );
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_DETECTION_VIP], str );
|
||||
|
||||
// enough info from this guy
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN found = FALSE;
|
||||
UINT8 maxtries = 20;
|
||||
for(UINT8 infotry = 0; infotry < maxtries; ++infotry)
|
||||
@@ -6761,7 +6802,7 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
|
||||
}
|
||||
|
||||
// remove interrogated prisoners...
|
||||
ChangeNumberOfPrisoners( pSectorInfo, -interrogatedprisoners[PRISONER_SPECIAL], -interrogatedprisoners[PRISONER_ELITE], -interrogatedprisoners[PRISONER_REGULAR], -interrogatedprisoners[PRISONER_ADMIN], sMapX, sMapY );
|
||||
ChangeNumberOfPrisoners( pSectorInfo, -interrogatedprisoners[PRISONER_OFFICER], -interrogatedprisoners[PRISONER_ELITE], -interrogatedprisoners[PRISONER_REGULAR], -interrogatedprisoners[PRISONER_ADMIN], sMapX, sMapY );
|
||||
|
||||
// give experience rewards to the interrogators
|
||||
// total experience to share
|
||||
@@ -6824,13 +6865,13 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ )
|
||||
// Are there any prisoners in this prison?
|
||||
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
|
||||
|
||||
UINT8 prisonersspecial = 0, prisonerselite = 0, prisonersregular = 0, prisonersadmin = 0;
|
||||
UINT16 numprisoners = GetNumberOfPrisoners( pSectorInfo, &prisonersspecial, &prisonerselite, &prisonersregular, &prisonersadmin );
|
||||
UINT8 prisonersofficer = 0, prisonerselite = 0, prisonersregular = 0, prisonersadmin = 0;
|
||||
UINT16 numprisoners = GetNumberOfPrisoners( pSectorInfo, &prisonersofficer, &prisonerselite, &prisonersregular, &prisonersadmin );
|
||||
|
||||
// for now, simply count specials as elites
|
||||
ChangeNumberOfPrisoners( pSectorInfo, -prisonersspecial, prisonersspecial, 0, 0 );
|
||||
prisonerselite += prisonersspecial;
|
||||
prisonersspecial = 0;
|
||||
// for now, simply count officers as elites
|
||||
ChangeNumberOfPrisoners( pSectorInfo, -prisonersofficer, prisonersofficer, 0, 0 );
|
||||
prisonerselite += prisonersofficer;
|
||||
prisonersofficer = 0;
|
||||
|
||||
if ( !numprisoners )
|
||||
return;
|
||||
@@ -6901,7 +6942,7 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ )
|
||||
pSectorInfo->ubNumAdmins = min(255, pSectorInfo->ubNumAdmins + escapedadmins);
|
||||
|
||||
// reduce prisoner count!
|
||||
ChangeNumberOfPrisoners( pSectorInfo, -prisonersspecial, -escapedelites, -escapedregulars, -escapedadmins, sMapX, sMapY );
|
||||
ChangeNumberOfPrisoners( pSectorInfo, -prisonersofficer, -escapedelites, -escapedregulars, -escapedadmins, sMapX, sMapY );
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RIOT], wSectorName );
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ typedef enum
|
||||
PRISONER_ADMIN = 0,
|
||||
PRISONER_REGULAR,
|
||||
PRISONER_ELITE,
|
||||
PRISONER_SPECIAL,
|
||||
PRISONER_OFFICER,
|
||||
PRISONER_MAX,
|
||||
} PrisonerType;
|
||||
|
||||
|
||||
+60
-1
@@ -492,6 +492,10 @@ void InitStrategicLayer( void )
|
||||
// re-set up leave list arrays for dismissed mercs
|
||||
InitLeaveList( );
|
||||
|
||||
// Flugente: se up VIP locations
|
||||
void InitVIPSectors( );
|
||||
|
||||
|
||||
#ifdef JA2UB
|
||||
LuaInitStrategicLayer(0); //JA25 UB InitStrategicLayer.lua
|
||||
#endif
|
||||
@@ -1219,7 +1223,7 @@ void ReStartingGame()
|
||||
if ( InAirRaid( ) )
|
||||
{
|
||||
EndAirRaid( );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JA2TESTVERSION
|
||||
//Reset so we can use the 'cheat key' to start with mercs
|
||||
@@ -1248,3 +1252,58 @@ void ReStartingGame()
|
||||
gubCheatLevel = 0;
|
||||
|
||||
}
|
||||
|
||||
// Flugente: set up VIP locations
|
||||
void InitVIPSectors()
|
||||
{
|
||||
if ( !gGameExternalOptions.fEnemyGenerals )
|
||||
return;
|
||||
|
||||
gStrategicStatus.usVIPsTotal = gGameExternalOptions.usEnemyGeneralsNumber;
|
||||
gStrategicStatus.usVIPsLeft = 0;
|
||||
|
||||
// first VIP is the general, if he is still alive
|
||||
if ( gMercProfiles[GENERAL].bLife > 0 )
|
||||
{
|
||||
UINT16 generalsector = SECTOR( gMercProfiles[GENERAL].sSectorX, gMercProfiles[GENERAL].sSectorY );
|
||||
|
||||
// place new VIP in sector
|
||||
StrategicMap[generalsector].usFlags |= ENEMY_VIP_PRESENT;
|
||||
|
||||
// no extra troops here. The player might have already taken the barracks but left the general alive
|
||||
//SectorInfo[generalsector].ubNumElites += 5;
|
||||
|
||||
++gStrategicStatus.usVIPsLeft;
|
||||
}
|
||||
|
||||
for ( UINT8 i = gStrategicStatus.usVIPsLeft; i < gStrategicStatus.usVIPsTotal; ++i )
|
||||
{
|
||||
UINT16 vipspawnsector = 0;
|
||||
if ( GetPossibleVIPSector( vipspawnsector ) )
|
||||
{
|
||||
// place new VIP in sector
|
||||
StrategicMap[vipspawnsector].usFlags |= ENEMY_VIP_PRESENT;
|
||||
|
||||
// increase troop count - VIP plus bodyguards
|
||||
SectorInfo[vipspawnsector].ubNumElites += 5;
|
||||
|
||||
// VIP placed
|
||||
++gStrategicStatus.usVIPsLeft;
|
||||
}
|
||||
// spawn the remaining generals in Meduna
|
||||
else
|
||||
{
|
||||
if ( GetRandomEnemyTownSector( MEDUNA, vipspawnsector ) )
|
||||
{
|
||||
// place new VIP in sector
|
||||
StrategicMap[vipspawnsector].usFlags |= ENEMY_VIP_PRESENT;
|
||||
|
||||
// increase troop count - VIP plus bodyguards
|
||||
SectorInfo[vipspawnsector].ubNumElites += 5;
|
||||
|
||||
// VIP placed
|
||||
++gStrategicStatus.usVIPsLeft;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,5 +14,8 @@ void ReStartingGame();
|
||||
|
||||
void InitBloodCatSectors();
|
||||
|
||||
// Flugente: se up VIP locations
|
||||
void InitVIPSectors();
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1289,6 +1289,47 @@ void ShowUncertainNumberEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
|
||||
InvalidateRegion( sXPosition ,sYPosition, sXPosition + DMAP_GRID_X, sYPosition + DMAP_GRID_Y );
|
||||
}
|
||||
|
||||
void ShowVIPSymbol( INT16 sSectorX, INT16 sSectorY )
|
||||
{
|
||||
INT16 sXPosition = 0, sYPosition = 0;
|
||||
HVOBJECT hIconHandle;
|
||||
|
||||
UINT8 iconOffsetX = 0;
|
||||
UINT8 iconOffsetY = 0;
|
||||
|
||||
if ( iResolution >= _640x480 && iResolution < _800x600 )
|
||||
{
|
||||
iconOffsetX = 2;
|
||||
iconOffsetY = 9;
|
||||
}
|
||||
else if ( iResolution < _1024x768 )
|
||||
{
|
||||
iconOffsetX = 8;
|
||||
iconOffsetY = 12;
|
||||
}
|
||||
else
|
||||
{
|
||||
iconOffsetX = 12;
|
||||
iconOffsetY = 13;
|
||||
}
|
||||
|
||||
// grab the x and y postions
|
||||
sXPosition = sSectorX;
|
||||
sYPosition = sSectorY;
|
||||
|
||||
// get the video object
|
||||
GetVideoObject( &hIconHandle, guiCHARICONS );
|
||||
|
||||
// check if we are zoomed in...need to offset in case for scrolling purposes
|
||||
sXPosition = (INT16)(iconOffsetX + (MAP_VIEW_START_X + (sSectorX * MAP_GRID_X + 1)) - 1);
|
||||
sYPosition = (INT16)(((iconOffsetY + (sSectorY * MAP_GRID_Y) + 1)));
|
||||
sYPosition -= 2;
|
||||
|
||||
// small question mark
|
||||
BltVideoObject( guiSAVEBUFFER, hIconHandle, 10, sXPosition, sYPosition, VO_BLT_SRCTRANSPARENCY, NULL );
|
||||
InvalidateRegion( sXPosition, sYPosition, sXPosition + DMAP_GRID_X, sYPosition + DMAP_GRID_Y );
|
||||
}
|
||||
|
||||
|
||||
void ShowTeamAndVehicles(INT32 fShowFlags)
|
||||
{
|
||||
@@ -6493,6 +6534,10 @@ void HandleShowingOfEnemyForcesInSector( INT16 sSectorX, INT16 sSectorY, INT8 bS
|
||||
// get total number of badguys here
|
||||
sNumberOfEnemies = NumEnemiesInSector( sSectorX, sSectorY );
|
||||
|
||||
// Flugente: note if we have detected a VIP here
|
||||
if ( SectorHasVIP( sSectorX, sSectorY ) )//PlayerKnowsAboutVIP( sSectorX, sSectorY ) )
|
||||
ShowVIPSymbol( sSectorX, sSectorY );
|
||||
|
||||
// Flugente: snitch reports can be false - we assume an enemy patrol where there is none. Unfortunately, that would always be the case if fNoEnemyDetectionWithoutReconis false - we detect something everywhere,
|
||||
// so every sector gets a red question mark. In that case, get out of here
|
||||
// anv: probability of false enemy reports!
|
||||
|
||||
@@ -1155,6 +1155,14 @@ void InitStrategicAI()
|
||||
#ifdef JA2BETAVERSION
|
||||
ClearStrategicLog();
|
||||
#endif
|
||||
|
||||
// Flugente: enemy generals can speed up the AI decision process (justification: the generals are the ones planning the military operations, so if theay are around, the army is more efficient)
|
||||
FLOAT dEnemyGeneralsSpeedupFactor = 1.0f;
|
||||
if ( gGameExternalOptions.fEnemyRoles && gGameExternalOptions.fEnemyGenerals )
|
||||
{
|
||||
dEnemyGeneralsSpeedupFactor = max( 0.5f, dEnemyGeneralsSpeedupFactor - gStrategicStatus.usVIPsLeft * gGameExternalOptions.fEnemyGeneralStrategicDecisionSpeedBonus );
|
||||
}
|
||||
|
||||
switch( gGameOptions.ubDifficultyLevel )
|
||||
{
|
||||
case DIF_LEVEL_EASY:
|
||||
@@ -1167,7 +1175,7 @@ void InitStrategicAI()
|
||||
gfUnlimitedTroops = gGameExternalOptions.gfEasyUnlimitedTroops;
|
||||
gfAggressiveQueen = gGameExternalOptions.gfEasyAggressiveQueen;
|
||||
// 475 is 7:55am in minutes since midnight, the time the game starts on day 1
|
||||
AddStrategicEvent( EVENT_EVALUATE_QUEEN_SITUATION, 475 + gGameExternalOptions.ubEasyTimeEvaluateInMinutes + Random( gGameExternalOptions.ubEasyTimeEvaluateVariance ), 0 );
|
||||
AddStrategicEvent( EVENT_EVALUATE_QUEEN_SITUATION, 475 + dEnemyGeneralsSpeedupFactor * (gGameExternalOptions.ubEasyTimeEvaluateInMinutes + Random( gGameExternalOptions.ubEasyTimeEvaluateVariance )), 0 );
|
||||
break;
|
||||
case DIF_LEVEL_MEDIUM:
|
||||
giReinforcementPool = gGameExternalOptions.iReinforcementPoolExperienced;
|
||||
@@ -1178,7 +1186,7 @@ void InitStrategicAI()
|
||||
gubHoursGracePeriod = gGameExternalOptions.ubNormalGracePeriodInHours;
|
||||
gfUnlimitedTroops = gGameExternalOptions.gfNormalUnlimitedTroops;
|
||||
gfAggressiveQueen = gGameExternalOptions.gfNormalAggressiveQueen;
|
||||
AddStrategicEvent( EVENT_EVALUATE_QUEEN_SITUATION, 475 + gGameExternalOptions.ubNormalTimeEvaluateInMinutes + Random( gGameExternalOptions.ubNormalTimeEvaluateVariance ), 0 );
|
||||
AddStrategicEvent( EVENT_EVALUATE_QUEEN_SITUATION, 475 + dEnemyGeneralsSpeedupFactor * (gGameExternalOptions.ubNormalTimeEvaluateInMinutes + Random( gGameExternalOptions.ubNormalTimeEvaluateVariance )), 0);
|
||||
break;
|
||||
case DIF_LEVEL_HARD:
|
||||
giReinforcementPool = gGameExternalOptions.iReinforcementPoolExpert;
|
||||
@@ -1189,7 +1197,7 @@ void InitStrategicAI()
|
||||
gubHoursGracePeriod = gGameExternalOptions.ubHardGracePeriodInHours;
|
||||
gfUnlimitedTroops = gGameExternalOptions.gfHardUnlimitedTroops;
|
||||
gfAggressiveQueen = gGameExternalOptions.gfHardAggressiveQueen;
|
||||
AddStrategicEvent( EVENT_EVALUATE_QUEEN_SITUATION, 475 + gGameExternalOptions.ubHardTimeEvaluateInMinutes + Random( gGameExternalOptions.ubHardTimeEvaluateVariance ), 0 );
|
||||
AddStrategicEvent( EVENT_EVALUATE_QUEEN_SITUATION, 475 + dEnemyGeneralsSpeedupFactor * (gGameExternalOptions.ubHardTimeEvaluateInMinutes + Random( gGameExternalOptions.ubHardTimeEvaluateVariance )), 0);
|
||||
break;
|
||||
case DIF_LEVEL_INSANE:
|
||||
giReinforcementPool = gGameExternalOptions.iReinforcementPoolInsane;
|
||||
@@ -1200,7 +1208,7 @@ void InitStrategicAI()
|
||||
gubHoursGracePeriod = gGameExternalOptions.ubInsaneGracePeriodInHours;
|
||||
gfUnlimitedTroops = gGameExternalOptions.gfInsaneUnlimitedTroops;
|
||||
gfAggressiveQueen = gGameExternalOptions.gfInsaneAggressiveQueen;
|
||||
AddStrategicEvent( EVENT_EVALUATE_QUEEN_SITUATION, 475 + gGameExternalOptions.ubInsaneTimeEvaluateInMinutes + Random( gGameExternalOptions.ubInsaneTimeEvaluateVariance ), 0 );
|
||||
AddStrategicEvent( EVENT_EVALUATE_QUEEN_SITUATION, 475 + dEnemyGeneralsSpeedupFactor * (gGameExternalOptions.ubInsaneTimeEvaluateInMinutes + Random( gGameExternalOptions.ubInsaneTimeEvaluateVariance )), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3257,19 +3265,27 @@ void EvaluateQueenSituation()
|
||||
// This can increase the decision intervals by up to 500 extra minutes (> 8 hrs)
|
||||
uiOffset = max( 100 - giRequestPoints, 0);
|
||||
uiOffset = uiOffset + Random( uiOffset * 4 );
|
||||
|
||||
// Flugente: enemy generals can speed up the AI decision process (justification: the generals are the ones planning the military operations, so if theay are around, the army is more efficient)
|
||||
FLOAT dEnemyGeneralsSpeedupFactor = 1.0f;
|
||||
if ( gGameExternalOptions.fEnemyRoles && gGameExternalOptions.fEnemyGenerals )
|
||||
{
|
||||
dEnemyGeneralsSpeedupFactor = max( 0.5f, dEnemyGeneralsSpeedupFactor - gStrategicStatus.usVIPsLeft * gGameExternalOptions.fEnemyGeneralStrategicDecisionSpeedBonus );
|
||||
}
|
||||
|
||||
switch( gGameOptions.ubDifficultyLevel )
|
||||
{
|
||||
case DIF_LEVEL_EASY:
|
||||
uiOffset += gGameExternalOptions.ubEasyTimeEvaluateInMinutes + Random( gGameExternalOptions.ubEasyTimeEvaluateVariance );
|
||||
uiOffset += dEnemyGeneralsSpeedupFactor * (gGameExternalOptions.ubEasyTimeEvaluateInMinutes + Random( gGameExternalOptions.ubEasyTimeEvaluateVariance ));
|
||||
break;
|
||||
case DIF_LEVEL_MEDIUM:
|
||||
uiOffset += gGameExternalOptions.ubNormalTimeEvaluateInMinutes + Random( gGameExternalOptions.ubNormalTimeEvaluateVariance );
|
||||
uiOffset += dEnemyGeneralsSpeedupFactor * (gGameExternalOptions.ubNormalTimeEvaluateInMinutes + Random( gGameExternalOptions.ubNormalTimeEvaluateVariance ));
|
||||
break;
|
||||
case DIF_LEVEL_HARD:
|
||||
uiOffset += gGameExternalOptions.ubHardTimeEvaluateInMinutes + Random( gGameExternalOptions.ubHardTimeEvaluateVariance );
|
||||
uiOffset += dEnemyGeneralsSpeedupFactor * (gGameExternalOptions.ubHardTimeEvaluateInMinutes + Random( gGameExternalOptions.ubHardTimeEvaluateVariance ));
|
||||
break;
|
||||
case DIF_LEVEL_INSANE:
|
||||
uiOffset += gGameExternalOptions.ubInsaneTimeEvaluateInMinutes + Random( gGameExternalOptions.ubInsaneTimeEvaluateVariance );
|
||||
uiOffset += dEnemyGeneralsSpeedupFactor * (gGameExternalOptions.ubInsaneTimeEvaluateInMinutes + Random( gGameExternalOptions.ubInsaneTimeEvaluateVariance ));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -3260,6 +3260,17 @@ INT32 GetSectorMvtTimeForGroup( UINT8 ubSector, UINT8 ubDirection, GROUP *pGroup
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( !pGroup->fPlayer )
|
||||
{
|
||||
// Flugente: enemy generals can speed up the AI decision process (justification: the generals are the ones planning the military operations, so if theay are around, the army is more efficient)
|
||||
FLOAT dEnemyGeneralsSpeedupFactor = 1.0f;
|
||||
if ( gGameExternalOptions.fEnemyRoles && gGameExternalOptions.fEnemyGenerals )
|
||||
{
|
||||
dEnemyGeneralsSpeedupFactor = max( 0.75f, dEnemyGeneralsSpeedupFactor - gStrategicStatus.usVIPsLeft * gGameExternalOptions.fEnemyGeneralStrategicMovementSpeedBonus );
|
||||
}
|
||||
|
||||
iBestTraverseTime = dEnemyGeneralsSpeedupFactor * iBestTraverseTime;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
return iBestTraverseTime;
|
||||
@@ -5119,7 +5130,7 @@ void SetGroupArrivalTime( GROUP *pGroup, UINT32 uiArrivalTime )
|
||||
|
||||
// Also note that non-chopper groups can currently be delayed such that this assetion would fail - enemy groups by
|
||||
// DelayEnemyGroupsIfPathsCross(), and player groups via PrepareGroupsForSimultaneousArrival(). So we skip the assert.
|
||||
|
||||
|
||||
if ( IsGroupTheHelicopterGroup( pGroup ) )
|
||||
{
|
||||
// make sure it's valid (NOTE: the correct traverse time must be set first!)
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include "GameSettings.h"
|
||||
#include "history.h"
|
||||
#include "Strategic Town Loyalty.h"
|
||||
#include "Game Init.h" // added by Flugente
|
||||
#include "GameVersion.h" // added by Flugente
|
||||
#include "SaveLoadGame.h" // added by Flugente
|
||||
#endif
|
||||
|
||||
|
||||
@@ -42,8 +45,6 @@ BOOLEAN SaveStrategicStatusToSaveGameFile( HWFILE hFile )
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOLEAN LoadStrategicStatusFromSaveGameFile( HWFILE hFile )
|
||||
{
|
||||
UINT32 uiNumBytesRead;
|
||||
@@ -55,6 +56,13 @@ BOOLEAN LoadStrategicStatusFromSaveGameFile( HWFILE hFile )
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Flugente: enemy generals: if loading an old savegame that did not have this feature, or it was turned off and is now turned on, initialise generals
|
||||
if ( guiCurrentSaveGameVersion < ENEMY_VIPS || !gStrategicStatus.usVIPsTotal )
|
||||
{
|
||||
// Flugente: set up VIP locations
|
||||
InitVIPSectors();
|
||||
}
|
||||
|
||||
return( TRUE );
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,11 @@ typedef struct STRATEGIC_STATUS
|
||||
UINT8 ubNumNewSectorsVisitedToday;
|
||||
UINT8 ubNumberOfDaysOfInactivity;
|
||||
|
||||
INT8 bPadding[70];
|
||||
// Flugente: VIPs
|
||||
UINT8 usVIPsTotal;
|
||||
UINT8 usVIPsLeft;
|
||||
|
||||
INT8 bPadding[68];
|
||||
|
||||
} STRATEGIC_STATUS;
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ enum
|
||||
#define MILITIA_MOVE_EAST 0x00000004 //4
|
||||
#define MILITIA_MOVE_SOUTH 0x00000008 //8
|
||||
|
||||
#define ENEMY_VIP_PRESENT 0x00000010 //16 // an enemy VIP is present in this sector
|
||||
#define ENEMY_VIP_PRESENT_KNOWN 0x00000020 //16 // player thinks a VIP is here
|
||||
|
||||
#define MILITIA_MOVE_ALLDIRS 0x0000000F // 15
|
||||
// -------------------------------------------------------
|
||||
|
||||
|
||||
+27
-5
@@ -1848,7 +1848,7 @@ void DrawSelectedUIAboveGuy( UINT16 usSoldierID )
|
||||
}
|
||||
}
|
||||
|
||||
if ( gDisplayEnemyRoles && pSoldier->bTeam == ENEMY_TEAM )
|
||||
if ( gDisplayEnemyRoles && pSoldier->bTeam == ENEMY_TEAM || pSoldier->bTeam == CIV_TEAM )
|
||||
{
|
||||
ShowSoldierRoleSymbol(pSoldier);
|
||||
}
|
||||
@@ -6564,7 +6564,7 @@ void DrawEnemyHealthBar( SOLDIERTYPE* pSoldier, INT32 sX, INT32 sY, UINT8 ubLine
|
||||
BOOLEAN ShowSoldierRoleSymbol(SOLDIERTYPE* pSoldier)
|
||||
{
|
||||
// this only works on enemy soldiers
|
||||
if ( pSoldier->bTeam != ENEMY_TEAM )
|
||||
if ( pSoldier->bTeam != ENEMY_TEAM && pSoldier->bTeam != CIV_TEAM )
|
||||
return false;
|
||||
|
||||
if ( pSoldier->usSkillCounter[SOLDIER_COUNTER_ROLE_OBSERVED] < gGameExternalOptions.usTurnsToUncover )
|
||||
@@ -6580,8 +6580,26 @@ BOOLEAN ShowSoldierRoleSymbol(SOLDIERTYPE* pSoldier)
|
||||
sXPos += 50;
|
||||
sYPos += 25;
|
||||
|
||||
// is this guy an officer?
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
|
||||
// are we a VIP? show that only when the player knows a VIP is in this sector. otherwise, don't even show our officer property
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_VIP && !pSoldier->bSectorZ )
|
||||
{
|
||||
if ( SectorHasVIP( pSoldier->sSectorX, pSoldier->sSectorY ) )//PlayerKnowsAboutVIP( pSoldier->sSectorX, pSoldier->sSectorY ) )
|
||||
{
|
||||
// Add bars
|
||||
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20), (INT16)(sYPos + 20) );
|
||||
|
||||
if ( iBack != -1 )
|
||||
{
|
||||
SetBackgroundRectFilled( iBack );
|
||||
}
|
||||
|
||||
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 6, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
}
|
||||
// is this guy an (non-vip) officer?
|
||||
else if ( pSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
|
||||
{
|
||||
// Add bars
|
||||
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20 ), (INT16)(sYPos + 20 ) );
|
||||
@@ -6591,7 +6609,11 @@ BOOLEAN ShowSoldierRoleSymbol(SOLDIERTYPE* pSoldier)
|
||||
SetBackgroundRectFilled( iBack );
|
||||
}
|
||||
|
||||
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 0, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
// if we look at this guy long enough, we might even learn that he is an advanced officer
|
||||
if ( pSoldier->usSkillCounter[SOLDIER_COUNTER_ROLE_OBSERVED] > 1.5 * gGameExternalOptions.usTurnsToUncover && NUM_SKILL_TRAITS( pSoldier, SQUADLEADER_NT ) > 1 )
|
||||
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 5, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
else
|
||||
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 0, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
+261
-28
@@ -3859,6 +3859,11 @@ void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldierOld )
|
||||
#endif
|
||||
}
|
||||
|
||||
// Flugente: backgrounds
|
||||
if ( pSoldierOld->HasBackgroundFlag( BACKGROUND_GLOBALOYALITYLOSSONDEATH ) )
|
||||
{
|
||||
DecrementTownLoyaltyEverywhere( 20000 );
|
||||
}
|
||||
|
||||
// killing crows/cows is not worth any experience!
|
||||
if ( ( pSoldierOld->ubBodyType != CROW ) && ( pSoldierOld->ubBodyType != COW ) ) //&& pSoldierOld->ubLastDamageReason != TAKE_DAMAGE_BLOODLOSS ) // SANDRO - why not give exp for bleeding out?
|
||||
@@ -6618,7 +6623,7 @@ BOOLEAN GetPlayerControlledPrisonList( std::vector<UINT32>& arSectorIDVector )
|
||||
extern INT32 giReinforcementPool;
|
||||
|
||||
// we cannot simply move all prisoners of a sector. It might be a prison we are already using, so we would move all inmates, not just the new ones
|
||||
UINT16 gusPrisonersSpecial = 0;
|
||||
UINT16 gusPrisonersOfficer = 0;
|
||||
UINT16 gusPrisonersElite = 0;
|
||||
UINT16 gusPrisonersRegular = 0;
|
||||
UINT16 gusPrisonersAdmin = 0;
|
||||
@@ -6652,7 +6657,7 @@ void PrisonerMessageBoxCallBack( UINT8 ubExitValue )
|
||||
}
|
||||
|
||||
BOOLEAN success = FALSE;
|
||||
UINT16 prisonerstobemoved = gusPrisonersSpecial + gusPrisonersElite + gusPrisonersRegular + gusPrisonersAdmin;
|
||||
UINT16 prisonerstobemoved = gusPrisonersOfficer + gusPrisonersElite + gusPrisonersRegular + gusPrisonersAdmin;
|
||||
|
||||
if ( usSectorID > 0 )
|
||||
{
|
||||
@@ -6662,7 +6667,7 @@ void PrisonerMessageBoxCallBack( UINT8 ubExitValue )
|
||||
{
|
||||
success = TRUE;
|
||||
|
||||
ChangeNumberOfPrisoners( pPrisonSectorInfo, gusPrisonersSpecial, gusPrisonersElite, gusPrisonersRegular, gusPrisonersAdmin );
|
||||
ChangeNumberOfPrisoners( pPrisonSectorInfo, gusPrisonersOfficer, gusPrisonersElite, gusPrisonersRegular, gusPrisonersAdmin );
|
||||
|
||||
CHAR16 wString[64];
|
||||
GetShortSectorString( SECTORX( usSectorID ), SECTORY( usSectorID ), wString );
|
||||
@@ -6670,7 +6675,7 @@ void PrisonerMessageBoxCallBack( UINT8 ubExitValue )
|
||||
}
|
||||
}
|
||||
|
||||
gusPrisonersSpecial = 0;
|
||||
gusPrisonersOfficer = 0;
|
||||
gusPrisonersElite = 0;
|
||||
gusPrisonersRegular = 0;
|
||||
gusPrisonersAdmin = 0;
|
||||
@@ -6691,7 +6696,7 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
UINT16 ubNumPrisonerAdmin = 0;
|
||||
UINT16 ubNumPrisonerTroop = 0;
|
||||
UINT16 ubNumPrisonerElite = 0;
|
||||
UINT16 ubNumPrisonerSpecial = 0;
|
||||
UINT16 ubNumPrisonerOfficer = 0;
|
||||
|
||||
// Check if the battle is won!
|
||||
// Loop through all mercs and make go
|
||||
@@ -6706,15 +6711,29 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
// if we arrive here and the guy has lifepoints < OKLIFE, something is very odd... better take him prisoner and remove him anyway
|
||||
//if ( pTeamSoldier->stats.bLife > OKLIFE && pTeamSoldier->stats.bLife != 0 )
|
||||
{
|
||||
switch ( pTeamSoldier->ubSoldierClass )
|
||||
// officers are 'special' prisoners...
|
||||
if ( pTeamSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR: ++ubNumPrisonerAdmin; break;
|
||||
case SOLDIER_CLASS_ARMY: ++ubNumPrisonerTroop; break;
|
||||
case SOLDIER_CLASS_ELITE: ++ubNumPrisonerElite; break;
|
||||
default:
|
||||
// if none of the above classes, ignore this one
|
||||
continue;
|
||||
break;
|
||||
++ubNumPrisonerOfficer;
|
||||
|
||||
// Flugente: VIPs
|
||||
if ( pTeamSoldier->usSoldierFlagMask & SOLDIER_VIP )
|
||||
{
|
||||
DeleteVIP( pTeamSoldier->sSectorX, pTeamSoldier->sSectorY );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( pTeamSoldier->ubSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR: ++ubNumPrisonerAdmin; break;
|
||||
case SOLDIER_CLASS_ARMY: ++ubNumPrisonerTroop; break;
|
||||
case SOLDIER_CLASS_ELITE: ++ubNumPrisonerElite; break;
|
||||
default:
|
||||
// if none of the above classes, ignore this one
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: campaign stats
|
||||
@@ -6822,15 +6841,13 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
}
|
||||
|
||||
// remember all prisoners...
|
||||
gusPrisonersSpecial = ubNumPrisonerSpecial;
|
||||
gusPrisonersOfficer = ubNumPrisonerOfficer;
|
||||
gusPrisonersElite = ubNumPrisonerElite;
|
||||
gusPrisonersRegular = ubNumPrisonerTroop;
|
||||
gusPrisonersAdmin = ubNumPrisonerAdmin;
|
||||
|
||||
DoMessageBox( MSG_BOX_BASIC_MEDIUM_BUTTONS, TacticalStr[PRISONER_DECIDE_STR], GAME_SCREEN, MSG_BOX_FLAG_GENERIC_EIGHT_BUTTONS, PrisonerMessageBoxCallBack, NULL );
|
||||
DoMessageBox( MSG_BOX_BASIC_MEDIUM_BUTTONS, TacticalStr[ PRISONER_DECIDE_STR ], GAME_SCREEN, MSG_BOX_FLAG_GENERIC_EIGHT_BUTTONS, PrisonerMessageBoxCallBack, NULL );
|
||||
}
|
||||
else
|
||||
DoMessageBox( MSG_BOX_BASIC_STYLE, TacticalStr[PRISONER_NO_PRISONS_STR], GAME_SCREEN, (UINT8)MSG_BOX_FLAG_OK, NULL, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10550,38 +10567,38 @@ BOOLEAN IsProfileInUse(UINT8 usTeam, INT8 aType, UINT16 aNr)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UINT16 GetNumberOfPrisoners( SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin )
|
||||
UINT16 GetNumberOfPrisoners( SECTORINFO *pSectorInfo, UINT8* aOfficer, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin )
|
||||
{
|
||||
if ( !pSectorInfo )
|
||||
return 0;
|
||||
|
||||
*apSpecial = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL];
|
||||
*aOfficer = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_OFFICER];
|
||||
*apElite = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE];
|
||||
*apRegular = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR];
|
||||
*apAdmin = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN];
|
||||
|
||||
return (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN]);
|
||||
return (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_OFFICER] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN]);
|
||||
}
|
||||
|
||||
UINT16 GetNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin )
|
||||
UINT16 GetNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, UINT8* aOfficer, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin )
|
||||
{
|
||||
if ( !pSectorInfo )
|
||||
return 0;
|
||||
|
||||
*apSpecial = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL];
|
||||
*aOfficer = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_OFFICER];
|
||||
*apElite = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE];
|
||||
*apRegular = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR];
|
||||
*apAdmin = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN];
|
||||
|
||||
return (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN]);
|
||||
return (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_OFFICER] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] + pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN]);
|
||||
}
|
||||
|
||||
void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin, INT16 sX, INT16 sY )
|
||||
void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aOfficer, INT16 aElite, INT16 aRegular, INT16 aAdmin, INT16 sX, INT16 sY )
|
||||
{
|
||||
if ( !pSectorInfo )
|
||||
return;
|
||||
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL] + aSpecial) );
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_OFFICER] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_OFFICER] + aOfficer ) );
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] + aElite) );
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] + aRegular) );
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN] + aAdmin) );
|
||||
@@ -10600,12 +10617,12 @@ void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aEl
|
||||
|
||||
}
|
||||
|
||||
void ChangeNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin )
|
||||
void ChangeNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, INT16 aOfficer, INT16 aElite, INT16 aRegular, INT16 aAdmin )
|
||||
{
|
||||
if ( !pSectorInfo )
|
||||
return;
|
||||
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL] + aSpecial) );
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_OFFICER] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_OFFICER] + aOfficer ) );
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ELITE] + aElite) );
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_REGULAR] + aRegular) );
|
||||
pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN] = max(0, min(255, pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_ADMIN] + aAdmin) );
|
||||
@@ -10635,7 +10652,7 @@ void KillOnePrisoner( SECTORINFO *pSectorInfo )
|
||||
if ( !pSectorInfo )
|
||||
return;
|
||||
|
||||
for (int i = PRISONER_SPECIAL; i >= PRISONER_ADMIN; --i)
|
||||
for ( int i = PRISONER_OFFICER; i >= PRISONER_ADMIN; --i )
|
||||
{
|
||||
if ( pSectorInfo->uiNumberOfPrisonersOfWar[i] )
|
||||
{
|
||||
@@ -10694,4 +10711,220 @@ UINT8 HighestEnemyOfficersInSector( BOOL& aType )
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
// count all soldiers in the current sector that have a specific flag set
|
||||
UINT16 NumSoldiersWithFlagInSector( UINT8 aTeam, UINT32 aFlag )
|
||||
{
|
||||
SOLDIERTYPE* pSoldier;
|
||||
INT32 cnt = 0;
|
||||
UINT8 num = 0;
|
||||
|
||||
for ( cnt = gTacticalStatus.Team[aTeam].bFirstID, pSoldier = MercPtrs[cnt]; cnt < gTacticalStatus.Team[aTeam].bLastID; pSoldier++, ++cnt )
|
||||
{
|
||||
if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 )
|
||||
{
|
||||
if ( pSoldier->usSoldierFlagMask & aFlag )
|
||||
{
|
||||
++num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
INT32 GetClosestSoldierWithFlag( UINT8 aTeam, UINT32 aFlag )
|
||||
{
|
||||
INT32 sBestGridNo = NOWHERE;
|
||||
|
||||
|
||||
|
||||
return sBestGridNo;
|
||||
}
|
||||
|
||||
// Flugente: VIP targets
|
||||
// can a new VIP be created?
|
||||
BOOLEAN VIPSlotFree()
|
||||
{
|
||||
// TODO: somehow keep track of all VIPs so far, including the dead ones
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN SectorHasVIP( INT16 sMapX, INT16 sMapY )
|
||||
{
|
||||
return (StrategicMap[SECTOR(sMapX, sMapY)].usFlags & ENEMY_VIP_PRESENT);
|
||||
}
|
||||
|
||||
BOOLEAN PlayerKnowsAboutVIP( INT16 sMapX, INT16 sMapY )
|
||||
{
|
||||
return (StrategicMap[SECTOR( sMapX, sMapY )].usFlags & ENEMY_VIP_PRESENT_KNOWN);
|
||||
}
|
||||
|
||||
BOOLEAN TownHasVIP( INT8 bTownId )
|
||||
{
|
||||
for ( INT32 iCounterA = 1; iCounterA < (INT32)(MAP_WORLD_X - 1); ++iCounterA )
|
||||
{
|
||||
for ( INT32 iCounterB = 1; iCounterB < (INT32)(MAP_WORLD_Y - 1); ++iCounterB )
|
||||
{
|
||||
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB )].bNameId == bTownId && SectorHasVIP( iCounterA, iCounterB ) )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN GetRandomEnemyTownSector(INT8 bTownId, UINT16& aSector)
|
||||
{
|
||||
UINT16 usSector = 0;
|
||||
std::vector<UINT16> possiblesectors;
|
||||
|
||||
for ( INT16 iCounterA = 1; iCounterA < (INT32)(MAP_WORLD_X - 1); ++iCounterA )
|
||||
{
|
||||
for ( INT16 iCounterB = 1; iCounterB < (INT32)(MAP_WORLD_Y - 1); ++iCounterB )
|
||||
{
|
||||
usSector = CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB );
|
||||
|
||||
if ( StrategicMap[usSector].bNameId == bTownId && NumEnemiesInSector( iCounterA, iCounterB ) > 0 && !SectorHasVIP( iCounterA, iCounterB ) )
|
||||
{
|
||||
possiblesectors.push_back( usSector );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !possiblesectors.empty( ) )
|
||||
{
|
||||
// select a random town
|
||||
UINT16 tmpSector = possiblesectors[Random( possiblesectors.size( ) )];
|
||||
|
||||
// as the game decides to be a dick, CALCULATE_STRATEGIC_INDEX(x, y) and SECTOR(x, y) are INCOMPATIBLE. Which is obscene, considering their liberate use throughout the code
|
||||
aSector = STRATEGIC_INDEX_TO_SECTOR_INFO( tmpSector );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get a possible sector for a VIP to spawn in. Note: we do not spawn new VIPs in Meduna - VIPs that escape move there instead
|
||||
BOOLEAN GetPossibleVIPSector( UINT16& aSector)
|
||||
{
|
||||
std::vector<INT8> possibletowns;
|
||||
|
||||
for ( INT8 town = FIRST_TOWN; town <= NUM_TOWNS; ++town )
|
||||
{
|
||||
// VIPs don't spawn in Meduna on first try
|
||||
if ( town == MEDUNA )
|
||||
continue;
|
||||
|
||||
// San Mona is also out, as the army has no permanent presence there
|
||||
if ( town == SAN_MONA )
|
||||
continue;
|
||||
|
||||
// no tiny towns
|
||||
if ( GetTownSectorSize( town ) < 2 )
|
||||
continue;
|
||||
|
||||
// if this town already has a VIP, skip it
|
||||
if ( TownHasVIP( town ) )
|
||||
continue;
|
||||
|
||||
// VIPs only spawn in sectors that are completely under enemy control. This makes hunting them down much more challenging ;-)
|
||||
if ( GetTownSectorsUnderControl( town ) == 0 )
|
||||
possibletowns.push_back(town);
|
||||
}
|
||||
|
||||
if ( !possibletowns.empty() )
|
||||
{
|
||||
// select a random town
|
||||
INT8 spawntown = possibletowns[Random( possibletowns.size() )];
|
||||
|
||||
if ( GetRandomEnemyTownSector( spawntown, aSector ) )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get the location of a VIP we do not yet know about
|
||||
BOOLEAN GetRandomUnknownVIPSector( UINT16& aSector )
|
||||
{
|
||||
UINT16 usSector = 0;
|
||||
std::vector<UINT16> possiblesectors;
|
||||
|
||||
for ( INT32 iCounterA = 1; iCounterA < (INT32)(MAP_WORLD_X - 1); ++iCounterA )
|
||||
{
|
||||
for ( INT32 iCounterB = 1; iCounterB < (INT32)(MAP_WORLD_Y - 1); ++iCounterB )
|
||||
{
|
||||
usSector = CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB );
|
||||
|
||||
if ( SectorHasVIP( iCounterA, iCounterB ) && !PlayerKnowsAboutVIP( iCounterA, iCounterB ) )
|
||||
{
|
||||
usSector = CALCULATE_STRATEGIC_INDEX( iCounterA, iCounterB );
|
||||
|
||||
possiblesectors.push_back( usSector );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !possiblesectors.empty( ) )
|
||||
{
|
||||
// select a random sector
|
||||
UINT16 tmpSector = possiblesectors[Random( possiblesectors.size( ) )];
|
||||
|
||||
// as the game decides to be a dick, CALCULATE_STRATEGIC_INDEX(x, y) and SECTOR(x, y) are INCOMPATIBLE. Which is obscene, considering their liberate use throughout the code
|
||||
aSector = STRATEGIC_INDEX_TO_SECTOR_INFO( tmpSector );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void DeleteVIP( INT16 sMapX, INT16 sMapY )
|
||||
{
|
||||
if ( StrategicMap[SECTOR( sMapX, sMapY )].usFlags & ENEMY_VIP_PRESENT_KNOWN )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"An important enemy VIP has been removed!" );
|
||||
}
|
||||
|
||||
// if no other VIPs are here, delete flags
|
||||
if ( NumSoldiersWithFlagInSector( ENEMY_TEAM, SOLDIER_VIP ) + NumSoldiersWithFlagInSector( CIV_TEAM, SOLDIER_VIP ) < 2 )
|
||||
{
|
||||
StrategicMap[SECTOR( sMapX, sMapY )].usFlags &= ~(ENEMY_VIP_PRESENT | ENEMY_VIP_PRESENT_KNOWN);
|
||||
}
|
||||
|
||||
gStrategicStatus.usVIPsLeft = max( 0, gStrategicStatus.usVIPsLeft - 1 );
|
||||
}
|
||||
|
||||
void VIPFleesToMeduna()
|
||||
{
|
||||
// not if we are already in Meduna
|
||||
if ( StrategicMap[CALCULATE_STRATEGIC_INDEX( gWorldSectorX, gWorldSectorY )].bNameId != MEDUNA )
|
||||
{
|
||||
if ( StrategicMap[SECTOR( gWorldSectorX, gWorldSectorY )].usFlags & ENEMY_VIP_PRESENT_KNOWN )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"An enemy VIP has evaded your forces. You have no clue about his whereabouts" );
|
||||
}
|
||||
|
||||
// if no other VIPs are here, delete flags
|
||||
if ( NumSoldiersWithFlagInSector( ENEMY_TEAM, SOLDIER_VIP ) + NumSoldiersWithFlagInSector( CIV_TEAM, SOLDIER_VIP ) == 1 )
|
||||
{
|
||||
StrategicMap[SECTOR( gWorldSectorX, gWorldSectorY )].usFlags &= ~(ENEMY_VIP_PRESENT | ENEMY_VIP_PRESENT_KNOWN);
|
||||
}
|
||||
|
||||
UINT16 usSector = 0;
|
||||
if ( GetRandomEnemyTownSector( MEDUNA, usSector ) )
|
||||
{
|
||||
// place new VIP in sector
|
||||
StrategicMap[usSector].usFlags |= ENEMY_VIP_PRESENT;
|
||||
|
||||
// increase troop count - VIP plus bodyguards
|
||||
SectorInfo[usSector].ubNumElites += 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
-4
@@ -373,11 +373,11 @@ BOOLEAN AllowedToStealFromTeamMate( UINT8 aAccessorID, UINT8 aTargetID );
|
||||
BOOLEAN IsProfileInUse(UINT8 usTeam, INT8 aType, UINT16 aNr);
|
||||
|
||||
// Flugente: functions altering a sector's prisoners
|
||||
UINT16 GetNumberOfPrisoners( SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin );
|
||||
UINT16 GetNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin );
|
||||
UINT16 GetNumberOfPrisoners( SECTORINFO *pSectorInfo, UINT8* aOfficer, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin );
|
||||
UINT16 GetNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, UINT8* aOfficer, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin );
|
||||
|
||||
void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin, INT16 sX = 0, INT16 sY = 0 );
|
||||
void ChangeNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin );
|
||||
void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aOfficer, INT16 aElite, INT16 aRegular, INT16 aAdmin, INT16 sX = 0, INT16 sY = 0 );
|
||||
void ChangeNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, INT16 aOfficer, INT16 aElite, INT16 aRegular, INT16 aAdmin );
|
||||
|
||||
void DeleteAllPrisoners( SECTORINFO *pSectorInfo );
|
||||
void DeleteAllPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo );
|
||||
@@ -400,5 +400,29 @@ enum {
|
||||
// Flugente: return number of enemy officers and highest rank found
|
||||
UINT8 HighestEnemyOfficersInSector(BOOL& aType);
|
||||
|
||||
// count all soldiers in the current sector that have a specific flag set
|
||||
UINT16 NumSoldiersWithFlagInSector(UINT8 aTeam, UINT32 aFlag);
|
||||
INT32 GetClosestSoldierWithFlag( UINT8 aTeam, UINT32 aFlag );
|
||||
|
||||
// Flugente: VIP targets
|
||||
// can a new VIP be created?
|
||||
BOOLEAN VIPSlotFree();
|
||||
|
||||
BOOLEAN SectorHasVIP( INT16 sMapX, INT16 sMapY );
|
||||
BOOLEAN PlayerKnowsAboutVIP( INT16 sMapX, INT16 sMapY );
|
||||
|
||||
BOOLEAN TownHasVIP( INT8 bTownId );
|
||||
|
||||
BOOLEAN GetRandomEnemyTownSector( INT8 bTownId, UINT16& aSector );
|
||||
|
||||
// Get a possible sector for a VIP to spawn in. Note: we do not spawn new VIPs in Meduna - VIPs that escape move there instead
|
||||
BOOLEAN GetPossibleVIPSector( UINT16& aSector );
|
||||
|
||||
// Get the location of a VIP we do not yet know about
|
||||
BOOLEAN GetRandomUnknownVIPSector( UINT16& aSector );
|
||||
|
||||
void DeleteVIP( INT16 sMapX, INT16 sMapY );
|
||||
void VIPFleesToMeduna();
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -674,7 +674,6 @@ BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier )
|
||||
pSoldier->sZLevelOverride = -1;
|
||||
pSoldier->EVENT_SetSoldierDesiredDirection( pSoldier->ubDirection );
|
||||
|
||||
|
||||
if ( gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER || gTacticalStatus.bBoxingState == PRE_BOXING || gTacticalStatus.bBoxingState == BOXING )
|
||||
{
|
||||
BoxingMovementCheck( pSoldier );
|
||||
@@ -4005,6 +4004,12 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
|
||||
*pfMadeCorpse = TRUE;
|
||||
}
|
||||
|
||||
// Flugente: VIPs
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_VIP )
|
||||
{
|
||||
DeleteVIP( pSoldier->sSectorX, pSoldier->sSectorY );
|
||||
}
|
||||
|
||||
// Remove mad as target, one he has died!
|
||||
RemoveManAsTarget( pSoldier );
|
||||
|
||||
|
||||
@@ -15430,7 +15430,7 @@ BOOLEAN SOLDIERTYPE::SeemsLegit( UINT8 ubObserverID )
|
||||
// exceptions: we are discovered if we are close and bleeding, or if we are drunk while dressed as a soldier
|
||||
{
|
||||
// if we are openly bleeding: not covert
|
||||
if ( this->bBleeding > 0 )
|
||||
if ( gSkillTraitValues.fCODetectIfBleeding && this->bBleeding > 0 )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_BLEEDING], this->GetName() );
|
||||
return FALSE;
|
||||
@@ -15448,7 +15448,7 @@ BOOLEAN SOLDIERTYPE::SeemsLegit( UINT8 ubObserverID )
|
||||
// however, if we are dressed up as a civilian, we can get as close as we like, we won't be discovered
|
||||
{
|
||||
// if we are openly bleeding: not covert
|
||||
if ( this->bBleeding > 0 )
|
||||
if ( gSkillTraitValues.fCODetectIfBleeding && this->bBleeding > 0 )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_BLEEDING], this->GetName() );
|
||||
return FALSE;
|
||||
|
||||
@@ -387,9 +387,9 @@ enum
|
||||
#define SOLDIER_ENEMY_OFFICER 0x04000000 //67108864 // soldier is an enemy officer
|
||||
#define SOLDIER_ENEMY_OBSERVEDTHISTURN 0x08000000 //134217728 // enemy soldier was seen by the player this turn
|
||||
|
||||
/*#define PLAYER_NET_1_LVL_4 0x10000000 //268435456
|
||||
#define PLAYER_NET_2_LVL_4 0x20000000 //536870912
|
||||
#define WH40K_SOLDIER_ILLUSION 0x40000000 //1073741824 // Soldier is an Illusion
|
||||
#define SOLDIER_VIP 0x10000000 //268435456 // soldier is a VIP - the player will likely try to assassinate him
|
||||
#define SOLDIER_BODYGUARD 0x20000000 //536870912 // soldier is a bodyguard for a VIP
|
||||
/*#define WH40K_SOLDIER_ILLUSION 0x40000000 //1073741824 // Soldier is an Illusion
|
||||
#define WH40K_SOLDIER_KILLTHISTURN 0x80000000 //2147483648 // Soldier is on a kill streak*/
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@@ -412,7 +412,9 @@ enum
|
||||
#define BACKGROUND_NO_MALE 0x0000000000000040 //64 // background cannot be selected by males (IMP creation)
|
||||
#define BACKGROUND_NO_FEMALE 0x0000000000000080 //128 // background cannot be selected by females (IMP creation)
|
||||
|
||||
#define BACKGROUND_FLAG_MAX 8 // number of flagged backgrounds - keep this updated, or properties will get lost!
|
||||
#define BACKGROUND_GLOBALOYALITYLOSSONDEATH 0x0000000000000100 //256 // if character dies, huge loyalty loss in entire country
|
||||
|
||||
#define BACKGROUND_FLAG_MAX 9 // number of flagged backgrounds - keep this updated, or properties will get lost!
|
||||
|
||||
// some properties are hidden (forbid background in MP creation)
|
||||
// corruption property is not relevant in 1.13
|
||||
|
||||
+336
-261
File diff suppressed because it is too large
Load Diff
@@ -132,7 +132,9 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha
|
||||
strcmp(name, "scrounging") == 0 ||
|
||||
strcmp(name, "traplevel") == 0 ||
|
||||
strcmp(name, "no_male") == 0 ||
|
||||
strcmp(name, "no_female") == 0 ))
|
||||
strcmp(name, "no_female") == 0 ||
|
||||
strcmp( name, "loyalitylossondeath" ) == 0 ))
|
||||
|
||||
{
|
||||
pData->curElement = ELEMENT_PROPERTY;
|
||||
|
||||
@@ -557,7 +559,12 @@ backgroundEndElementHandle(void *userData, const XML_Char *name)
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curBackground.uiFlags |= (UINT16) atol(pData->szCharData) ? BACKGROUND_NO_FEMALE : 0;
|
||||
}
|
||||
|
||||
else if ( strcmp( name, "loyalitylossondeath" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curBackground.uiFlags |= (UINT16)atol( pData->szCharData ) ? BACKGROUND_GLOBALOYALITYLOSSONDEATH : 0;
|
||||
}
|
||||
|
||||
pData->maxReadDepth--;
|
||||
}
|
||||
pData->currentDepth--;
|
||||
|
||||
@@ -2562,6 +2562,12 @@ void HandleAITacticalTraversal( SOLDIERTYPE * pSoldier )
|
||||
}
|
||||
#endif
|
||||
|
||||
// Flugente: VIPs: if a VIP flees, he flees to Meduna (in fact te sodleir doesn't, we simply move the flag to another sector)
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_VIP )
|
||||
{
|
||||
VIPFleesToMeduna();
|
||||
}
|
||||
|
||||
EndAIGuysTurn( pSoldier );
|
||||
RemoveManAsTarget( pSoldier );
|
||||
if (pSoldier->bTeam == CIV_TEAM && pSoldier->aiData.fAIFlags & AI_CHECK_SCHEDULE)
|
||||
|
||||
+102
-2
@@ -35,6 +35,7 @@
|
||||
#endif
|
||||
#include "connect.h"
|
||||
#include "Text.h"
|
||||
#include "Exit Grids.h" // added by Flugente
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// SANDRO - In this file, all APBPConstants[AP_CROUCH] and APBPConstants[AP_PRONE] were changed to GetAPsCrouch() and GetAPsProne()
|
||||
@@ -1002,6 +1003,27 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// are we a bodyguard?
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_BODYGUARD )
|
||||
{
|
||||
// is VIP still alive?
|
||||
UINT16 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
{
|
||||
// we want to stay close to him, but still be able to function properly... stay withing a 7-tile radius
|
||||
if ( SpacesAway( pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo ) > 7 )
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
|
||||
|
||||
if ( !TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//ddd}
|
||||
|
||||
@@ -1716,6 +1738,27 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// are we a bodyguard?
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_BODYGUARD )
|
||||
{
|
||||
// is VIP still alive?
|
||||
UINT16 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
{
|
||||
// we want to stay close to him, but still be able to function properly... stay withing a 7-tile radius
|
||||
if ( SpacesAway( pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo ) > 7 )
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
|
||||
|
||||
if ( !TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -3071,6 +3114,46 @@ INT8 DecideActionRed(SOLDIERTYPE *pSoldier, UINT8 ubUnconsciousOK)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// VIPs run away (but not the GENERAL)
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_VIP && pSoldier->ubProfile != GENERAL )
|
||||
{
|
||||
// this is in red AI state - a firefight is going on, we try to escape
|
||||
pSoldier->aiData.usActionData = FindSpotMaxDistFromOpponents( pSoldier );
|
||||
|
||||
// if we don't know where our opponents are, we cannot run away from them...
|
||||
if ( TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
|
||||
{
|
||||
// search for the closest map edge
|
||||
pSoldier->aiData.usActionData = FindClosestExitGrid( pSoldier, pSoldier->sGridNo, 200 );
|
||||
}
|
||||
|
||||
if ( !TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
|
||||
{
|
||||
return AI_ACTION_RUN_AWAY;
|
||||
}
|
||||
}
|
||||
|
||||
// are we a bodyguard?
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_BODYGUARD )
|
||||
{
|
||||
// is VIP still alive?
|
||||
UINT16 ubPerson = GetClosestFlaggedSoldierID( pSoldier, 100, pSoldier->bTeam, SOLDIER_VIP, FALSE );
|
||||
|
||||
if ( ubPerson != NOBODY )
|
||||
{
|
||||
// we want to stay close to him, but still be able to function properly... stay withing a 7-tile radius
|
||||
if ( SpacesAway( pSoldier->sGridNo, MercPtrs[ubPerson]->sGridNo ) > 7 )
|
||||
{
|
||||
pSoldier->aiData.usActionData = InternalGoAsFarAsPossibleTowards( pSoldier, MercPtrs[ubPerson]->sGridNo, 20, AI_ACTION_SEEK_FRIEND, 0 );
|
||||
|
||||
if ( !TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
|
||||
{
|
||||
return(AI_ACTION_SEEK_FRIEND);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -4345,7 +4428,6 @@ INT16 ubMinAPCost;
|
||||
}
|
||||
else if ( gTacticalStatus.bBoxingState == BOXING )
|
||||
{
|
||||
|
||||
bInWater = FALSE;
|
||||
bInDeepWater = FALSE;
|
||||
bInGas = FALSE;
|
||||
@@ -4361,7 +4443,6 @@ INT16 ubMinAPCost;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// determine if we happen to be in water (in which case we're in BIG trouble!)
|
||||
bInWater = Water( pSoldier->sGridNo );
|
||||
bInDeepWater = WaterTooDeepForAttacks( pSoldier->sGridNo );
|
||||
@@ -4679,6 +4760,25 @@ INT16 ubMinAPCost;
|
||||
}
|
||||
}
|
||||
|
||||
// VIPs run away (but not the GENERAL)
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_VIP && pSoldier->ubProfile != GENERAL )
|
||||
{
|
||||
// this is in red AI state - a firefight is going on, we try to escape
|
||||
pSoldier->aiData.usActionData = FindSpotMaxDistFromOpponents( pSoldier );
|
||||
|
||||
// if we don't know where our opponents are, we cannot run away from them...
|
||||
if ( TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
|
||||
{
|
||||
// search for the closest map edge
|
||||
pSoldier->aiData.usActionData = FindClosestExitGrid( pSoldier, pSoldier->sGridNo, 200 );
|
||||
}
|
||||
|
||||
if ( !TileIsOutOfBounds( pSoldier->aiData.usActionData ) )
|
||||
{
|
||||
return AI_ACTION_RUN_AWAY;
|
||||
}
|
||||
}
|
||||
|
||||
BestShot.ubPossible = FALSE; // by default, assume Shooting isn't possible
|
||||
BestThrow.ubPossible = FALSE; // by default, assume Throwing isn't possible
|
||||
BestStab.ubPossible = FALSE; // by default, assume Stabbing isn't possible
|
||||
|
||||
@@ -842,6 +842,7 @@ enum
|
||||
STR_PRISONER_REFUSE_TAKE_PRISONERS,
|
||||
SRT_PRISONER_INI_SETTING_OFF,
|
||||
STR_PRISONER_X_FREES_Y,
|
||||
STR_PRISONER_DETECTION_VIP,
|
||||
|
||||
TEXT_NUM_PRISONER_STR
|
||||
};
|
||||
|
||||
@@ -8060,6 +8060,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"敌人不肯拿你当囚犯 - 他们宁愿你死!", //L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"这些可以在 INI 设置关闭。", // L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s释放了%s!", //L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]=
|
||||
@@ -8093,6 +8094,8 @@ STR16 szBackgroundText_Flags[]=
|
||||
L" 会导致附近的佣兵腐败\n", //L" spreads corruption to nearby mercs\n",
|
||||
L" female only", // won't show up, text exists for compatibility reasons
|
||||
L" male only", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szBackgroundText_Value[]=
|
||||
|
||||
@@ -8072,6 +8072,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]= // TODO.Translate
|
||||
@@ -8106,6 +8107,8 @@ STR16 szBackgroundText_Flags[]=
|
||||
L" spreads corruption to nearby mercs\n",
|
||||
L" female only", // won't show up, text exists for compatibility reasons
|
||||
L" male only", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n", // TODO.Translate
|
||||
};
|
||||
|
||||
// TODO.Translate
|
||||
|
||||
@@ -8057,6 +8057,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!",
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]=
|
||||
@@ -8083,13 +8084,15 @@ STR16 szBackgroundText_Flags[]=
|
||||
{
|
||||
L" might consume drugs in inventory\n",
|
||||
L" disregard for other backgrounds\n",
|
||||
L" +1 level in underground sectors\n",
|
||||
L" +1 level in underground sectors\n",
|
||||
L" might steal items\n",
|
||||
|
||||
L" +1 traplevel to planted bombs\n",
|
||||
L" spreads corruption to nearby mercs\n",
|
||||
L" female only", // won't show up, text exists for compatibility reasons
|
||||
L" male only", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n",
|
||||
};
|
||||
|
||||
STR16 szBackgroundText_Value[]=
|
||||
|
||||
@@ -8058,6 +8058,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"L'ennemi refuse votre reddition... Ils veulent vos têtes !",
|
||||
L"Ce comportement est désactivé dans vos fichiers ini.",
|
||||
L"%s a libéré %s !",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]=
|
||||
@@ -8092,6 +8093,8 @@ STR16 szBackgroundText_Flags[]=
|
||||
L" répand la corruption aux mercenaires proches\n",
|
||||
L" femme seulement", // won't show up, text exists for compatibility reasons
|
||||
L" homme seulement", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n", // TODO.Translate
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -7885,6 +7885,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"Der Feind weigert sich, Sie als Gefangenen zu nehmen - Er möchte Sie tod sehen!",
|
||||
L"Dieses Verhalten ist ausgeschaltet in der ja2_options.ini Datei.",
|
||||
L"%s hat %s befreit!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]=
|
||||
@@ -7919,6 +7920,8 @@ STR16 szBackgroundText_Flags[]=
|
||||
L" spreads corruption to nearby mercs\n",
|
||||
L" female only", // won't show up, text exists for compatibility reasons
|
||||
L" male only", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n", // TODO.Translate
|
||||
};
|
||||
|
||||
// TODO.Translate
|
||||
|
||||
@@ -8063,6 +8063,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]= // TODO.Translate
|
||||
@@ -8098,6 +8099,8 @@ STR16 szBackgroundText_Flags[]=
|
||||
L" spreads corruption to nearby mercs\n",
|
||||
L" female only", // won't show up, text exists for compatibility reasons
|
||||
L" male only", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n", // TODO.Translate
|
||||
};
|
||||
|
||||
// TODO.Translate
|
||||
|
||||
@@ -8081,6 +8081,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]= // TODO.Translate
|
||||
@@ -8115,6 +8116,8 @@ STR16 szBackgroundText_Flags[]=
|
||||
L" spreads corruption to nearby mercs\n",
|
||||
L" female only", // won't show up, text exists for compatibility reasons
|
||||
L" male only", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n", // TODO.Translate
|
||||
};
|
||||
|
||||
// TODO.Translate
|
||||
|
||||
@@ -8061,6 +8061,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]= // TODO.Translate
|
||||
@@ -8095,6 +8096,8 @@ STR16 szBackgroundText_Flags[]=
|
||||
L" spreads corruption to nearby mercs\n",
|
||||
L" female only", // won't show up, text exists for compatibility reasons
|
||||
L" male only", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n", // TODO.Translate
|
||||
};
|
||||
|
||||
// TODO.Translate
|
||||
|
||||
@@ -8072,6 +8072,7 @@ STR16 szPrisonerTextStr[]=
|
||||
L"The enemy refuses to take you as prisoners - they prefer you dead!",
|
||||
L"This behaviour is set OFF in your ini settings.",
|
||||
L"%s has freed %s!",
|
||||
L"A prisoner revealed the location of a high-ranking army officer in %s!", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 szMTATextStr[]= // TODO.Translate
|
||||
@@ -8106,6 +8107,8 @@ STR16 szBackgroundText_Flags[]=
|
||||
L" spreads corruption to nearby mercs\n",
|
||||
L" female only", // won't show up, text exists for compatibility reasons
|
||||
L" male only", // won't show up, text exists for compatibility reasons
|
||||
|
||||
L" huge loyality penalty in all towns if we die\n", // TODO.Translate
|
||||
};
|
||||
|
||||
// TODO.Translate
|
||||
|
||||
Reference in New Issue
Block a user