Feature improvement: the prisoner system now distinguishes between different types of prisoners (admin, regular, elite). Advanced troops are harder to interrogate, but have a high chance of retaining their rank, should they join yor militia.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6219 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2013-07-12 23:54:50 +00:00
parent 957e8cc76c
commit a1f49b3ca3
18 changed files with 228 additions and 101 deletions
+5
View File
@@ -1630,6 +1630,11 @@ void LoadGameExternalOptions()
gGameExternalOptions.ubPrisonerProcessInfoDirectionChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INFO_DIRECTION_CHANCE", 40, 0, 100); gGameExternalOptions.ubPrisonerProcessInfoDirectionChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_INFO_DIRECTION_CHANCE", 40, 0, 100);
gGameExternalOptions.ubPrisonerProcessRansomBaseChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_RANSOM_CHANCE", 25, 0, 100); gGameExternalOptions.ubPrisonerProcessRansomBaseChance = iniReader.ReadInteger("Strategic Gameplay Settings","PRISONER_RANSOM_CHANCE", 25, 0, 100);
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);
// CHRISL: Determine how Skyrider should handle landing in enemy occupied sectors // CHRISL: Determine how Skyrider should handle landing in enemy occupied sectors
gGameExternalOptions.ubSkyriderHotLZ = iniReader.ReadInteger("Strategic Gameplay Settings", "ALLOW_SKYRIDER_HOT_LZ", 0); gGameExternalOptions.ubSkyriderHotLZ = iniReader.ReadInteger("Strategic Gameplay Settings", "ALLOW_SKYRIDER_HOT_LZ", 0);
+1
View File
@@ -1227,6 +1227,7 @@ typedef struct
UINT8 ubPrisonerProcessInfoNumberChance; UINT8 ubPrisonerProcessInfoNumberChance;
UINT8 ubPrisonerProcessInfoDirectionChance; UINT8 ubPrisonerProcessInfoDirectionChance;
UINT8 ubPrisonerProcessRansomBaseChance; UINT8 ubPrisonerProcessRansomBaseChance;
UINT16 ubPrisonerInterrogationPoints[4]; // points needed to interrogate a prisoner of a specific type
// Sandro: Alternative weapon holding (rifles fired from hip / pistols fired one-handed) // Sandro: Alternative weapon holding (rifles fired from hip / pistols fired one-handed)
UINT8 ubAllowAlternativeWeaponHolding; UINT8 ubAllowAlternativeWeaponHolding;
+64 -47
View File
@@ -2627,7 +2627,8 @@ UINT32 CalculateInterrogationValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts )
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ] ); SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ] );
*pusMaxPts = (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar); UINT8 prisonersspecial = 0, prisonerselite = 0, prisonersregular = 0, prisonersadmin = 0;
*pusMaxPts = GetNumberOrPrisoners( pSectorInfo, &prisonersspecial, &prisonerselite, &prisonersregular, &prisonersadmin );
// no prisoners -> no interrogation (this should not happen) // no prisoners -> no interrogation (this should not happen)
if ( !*pusMaxPts ) if ( !*pusMaxPts )
@@ -2659,8 +2660,6 @@ UINT32 CalculateInterrogationValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts )
usInterrogationPoints = (usInterrogationPoints * performancemodifier) / (650000); usInterrogationPoints = (usInterrogationPoints * performancemodifier) / (650000);
// TODO: adjust for cop background
// adjust for fatigue // adjust for fatigue
ReducePointsForFatigue( pSoldier, &usInterrogationPoints ); ReducePointsForFatigue( pSoldier, &usInterrogationPoints );
@@ -2676,16 +2675,6 @@ UINT32 CalculatePrisonGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts )
// for max points we display the maximum amount of prisoners instead // for max points we display the maximum amount of prisoners instead
*pusMaxPts = 0; *pusMaxPts = 0;
/*if ( !pSoldier || !pSoldier->bSectorZ )
{
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( pSoldier->sSectorX, pSoldier->sSectorY ) ] );
*pusMaxPts = (UINT16)(pSectorInfo->uiNumberOfPrisonersOfWar);
}
// no prisoners -> no interrogation (this should not happen)
if ( !*pusMaxPts )
return .0f;*/
if ( pSoldier->flags.fMercAsleep ) if ( pSoldier->flags.fMercAsleep )
return 0; return 0;
@@ -2704,8 +2693,6 @@ UINT32 CalculatePrisonGuardValue(SOLDIERTYPE *pSoldier, UINT16 *pusMaxPts )
// adjust for fatigue // adjust for fatigue
ReducePointsForFatigue( pSoldier, &usValue ); ReducePointsForFatigue( pSoldier, &usValue );
// TODO: adjust for prison guard background
// return current repair pts // return current repair pts
return( usValue ); return( usValue );
} }
@@ -5531,7 +5518,8 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
// Are there any prisoners in this prison? // Are there any prisoners in this prison?
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
UINT32 numprisoners = pSectorInfo->uiNumberOfPrisonersOfWar; UINT8 prisoners[PRISONER_MAX] = {0};
UINT16 numprisoners = GetNumberOrPrisoners( pSectorInfo, &prisoners[PRISONER_SPECIAL], &prisoners[PRISONER_ELITE], &prisoners[PRISONER_REGULAR], &prisoners[PRISONER_ADMIN] );
// add interrogation progress from last hour and erase it in data // add interrogation progress from last hour and erase it in data
UINT32 interrogationpoints = pSectorInfo->uiInterrogationHundredsLeft; UINT32 interrogationpoints = pSectorInfo->uiInterrogationHundredsLeft;
@@ -5568,22 +5556,32 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
if ( !numinterrogators ) if ( !numinterrogators )
return; return;
// for every x points, we can interrogate 1 prisoner // we first interrogate admins, then troops, then elites, then specials (once we figure out who those are :-) )
// TODO: for now, we lose the remaining points // higher quality prisoners require more effort, but yield better rewards
UINT32 prisonersinterrogated = interrogationpoints / 100; UINT8 interrogatedprisoners[PRISONER_MAX] = {0};
for (int i = PRISONER_ADMIN; i < PRISONER_MAX; ++i)
{
while ( prisoners[i] && interrogationpoints >= gGameExternalOptions.ubPrisonerInterrogationPoints[i] )
{
interrogationpoints -= gGameExternalOptions.ubPrisonerInterrogationPoints[i];
--prisoners[i];
++interrogatedprisoners[i];
}
}
UINT16 prisonersinterrogated = interrogatedprisoners[PRISONER_ADMIN] + interrogatedprisoners[PRISONER_REGULAR] + interrogatedprisoners[PRISONER_ELITE] + interrogatedprisoners[PRISONER_SPECIAL];
// 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) // 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)
pSectorInfo->uiInterrogationHundredsLeft = (UINT8)(interrogationpoints - prisonersinterrogated * 100); UINT32 losthundreds = interrogationpoints / 100;
pSectorInfo->uiInterrogationHundredsLeft = (UINT8)(interrogationpoints - losthundreds * 100);
if ( prisonersinterrogated > numprisoners )
prisonersinterrogated = numprisoners;
if ( !prisonersinterrogated ) if ( !prisonersinterrogated )
return; return;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_PROCESSED], prisonersinterrogated ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_PROCESSED], interrogatedprisoners[PRISONER_ELITE], interrogatedprisoners[PRISONER_REGULAR], interrogatedprisoners[PRISONER_ADMIN] );
UINT32 turnedmilitia = 0; UINT8 turnedmilitia_elite = 0, turnedmilitia_regular= 0, turnedmilitia_admin = 0;
UINT32 revealedpositions = 0; UINT32 revealedpositions = 0;
UINT32 ransomscollected = 0; UINT32 ransomscollected = 0;
UINT32 ransommoney = 0; UINT32 ransommoney = 0;
@@ -5595,9 +5593,15 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
// chance that prisoner will work on our side as militia // chance that prisoner will work on our side as militia
if ( result < gGameExternalOptions.ubPrisonerProcessDefectChance ) if ( result < gGameExternalOptions.ubPrisonerProcessDefectChance )
{ {
++turnedmilitia; // troops are converted to militia, but there is a chance that they will be demoted in the process
if ( i < interrogatedprisoners[PRISONER_ELITE] && Chance(80) )
++turnedmilitia_elite;
else if ( i < interrogatedprisoners[PRISONER_ELITE] + interrogatedprisoners[PRISONER_REGULAR] && Chance(80) )
++turnedmilitia_regular;
else
++turnedmilitia_admin;
// we continue so that this guy can not also run back to the queen // we continue so that this guy cannot also run back to the queen
continue; continue;
} }
// chance that prisoner will give us random info about enemy positions // chance that prisoner will give us random info about enemy positions
@@ -5656,12 +5660,14 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
++giReinforcementPool; ++giReinforcementPool;
} }
if ( turnedmilitia ) if ( turnedmilitia_elite + turnedmilitia_regular + turnedmilitia_admin )
{ {
// add these guys to the local garrison as green militias // add these guys to the local garrison as green militias
StrategicAddMilitiaToSector(sMapX, sMapY, GREEN_MILITIA, turnedmilitia); StrategicAddMilitiaToSector(sMapX, sMapY, GREEN_MILITIA, turnedmilitia_admin);
StrategicAddMilitiaToSector(sMapX, sMapY, REGULAR_MILITIA, turnedmilitia_regular);
StrategicAddMilitiaToSector(sMapX, sMapY, ELITE_MILITIA, turnedmilitia_elite);
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_TURN_MILITIA], turnedmilitia ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_TURN_MILITIA], turnedmilitia_elite, turnedmilitia_regular, turnedmilitia_admin );
} }
if ( revealedpositions ) if ( revealedpositions )
@@ -5698,11 +5704,7 @@ void HandlePrisonerProcessingInSector( INT16 sMapX, INT16 sMapY, INT8 bZ )
} }
// remove interrogated prisoners... // remove interrogated prisoners...
// safety first... ChangeNumberOfPrisoners( pSectorInfo, -interrogatedprisoners[PRISONER_SPECIAL], -interrogatedprisoners[PRISONER_ELITE], -interrogatedprisoners[PRISONER_REGULAR], -interrogatedprisoners[PRISONER_ADMIN] );
if ( prisonersinterrogated > pSectorInfo->uiNumberOfPrisonersOfWar )
pSectorInfo->uiNumberOfPrisonersOfWar = 0;
else
pSectorInfo->uiNumberOfPrisonersOfWar -= prisonersinterrogated;
} }
// Flugente: prisons can riot if there aren't enough guards around // Flugente: prisons can riot if there aren't enough guards around
@@ -5739,7 +5741,13 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ )
// Are there any prisoners in this prison? // Are there any prisoners in this prison?
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
UINT32 numprisoners = pSectorInfo->uiNumberOfPrisonersOfWar; UINT8 prisonersspecial = 0, prisonerselite = 0, prisonersregular = 0, prisonersadmin = 0;
UINT16 numprisoners = GetNumberOrPrisoners( pSectorInfo, &prisonersspecial, &prisonerselite, &prisonersregular, &prisonersadmin );
// for now, simply count specials as elites
ChangeNumberOfPrisoners( pSectorInfo, -prisonersspecial, prisonersspecial, 0, 0 );
prisonerselite += prisonersspecial;
prisonersspecial = 0;
if ( !numprisoners ) if ( !numprisoners )
return; return;
@@ -5751,10 +5759,12 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ )
if( StrategicMap[ sMapX + sMapY * MAP_WORLD_X ].fEnemyControlled == TRUE ) if( StrategicMap[ sMapX + sMapY * MAP_WORLD_X ].fEnemyControlled == TRUE )
{ {
// add enemies // add enemies
pSectorInfo->ubNumTroops += numprisoners; pSectorInfo->ubNumTroops = min(255, pSectorInfo->ubNumTroops + prisonersregular);
pSectorInfo->ubNumElites = min(255, pSectorInfo->ubNumElites + prisonerselite);
pSectorInfo->ubNumAdmins = min(255, pSectorInfo->ubNumAdmins + prisonersadmin);
// all prisoners are free, reduce count! // all prisoners are free, reduce count!
pSectorInfo->uiNumberOfPrisonersOfWar = 0; DeleteAllPrisoners(pSectorInfo);
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_ARMY_FREED_PRISON], wSectorName ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_ARMY_FREED_PRISON], wSectorName );
@@ -5793,11 +5803,7 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ )
fBeginRiot = TRUE; fBeginRiot = TRUE;
// we now have to determine the combined strength of the prisoners // we now have to determine the combined strength of the prisoners
UINT32 prisonerriotvalue = 0; UINT32 prisonerriotvalue = 125 * prisonerselite + 100 * prisonersregular + 75 * prisonersadmin;
for ( UINT32 i = 0; i < numprisoners; ++i )
{
prisonerriotvalue += 100;
}
if ( prisonerriotvalue > prisonguardvalue ) if ( prisonerriotvalue > prisonguardvalue )
{ {
@@ -5807,11 +5813,22 @@ void HandlePrison( INT16 sMapX, INT16 sMapY, INT8 bZ )
if ( fBeginRiot ) if ( fBeginRiot )
{ {
// add enemies FLOAT prisonertoguardratio = 1.0f;
pSectorInfo->ubNumTroops += numprisoners; if ( prisonguardvalue )
prisonertoguardratio = (FLOAT)(prisonerriotvalue / prisonguardvalue);
// all prisoners are free, reduce count! // in a riot, prisoners escape and are added to the sector as enemies. Not all might escape - the worse the prisoner/guard ratio, the more escape
pSectorInfo->uiNumberOfPrisonersOfWar = 0; UINT8 escapedadmins = min( Random(prisonersadmin + prisonersadmin * prisonertoguardratio) , prisonersadmin);
UINT8 escapedregulars = min( Random(prisonersregular + prisonersregular * prisonertoguardratio) , prisonersregular);
UINT8 escapedelites = min( Random(prisonerselite + prisonerselite * prisonertoguardratio) , prisonerselite);
// add enemies
pSectorInfo->ubNumTroops = min(255, pSectorInfo->ubNumTroops + escapedregulars);
pSectorInfo->ubNumElites = min(255, pSectorInfo->ubNumElites + escapedelites);
pSectorInfo->ubNumAdmins = min(255, pSectorInfo->ubNumAdmins + escapedadmins);
// reduce prisoner count!
ChangeNumberOfPrisoners( pSectorInfo, -prisonersspecial, -escapedelites, -escapedregulars, -escapedadmins );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RIOT], wSectorName ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RIOT], wSectorName );
} }
+12 -2
View File
@@ -412,6 +412,16 @@ extern UINT8 gszTerrain[NUM_TRAVTERRAIN_TYPES][15];
//Used by ubGarrisonID when a sector doesn't point to a garrison. Used by strategic AI only. //Used by ubGarrisonID when a sector doesn't point to a garrison. Used by strategic AI only.
#define NO_GARRISON 255 #define NO_GARRISON 255
// Flugente: types of prisoners
typedef enum
{
PRISONER_ADMIN = 0,
PRISONER_REGULAR,
PRISONER_ELITE,
PRISONER_SPECIAL,
PRISONER_MAX,
} PrisonerType;
typedef struct SECTORINFO typedef struct SECTORINFO
{ {
//information pertaining to this sector //information pertaining to this sector
@@ -479,7 +489,7 @@ typedef struct SECTORINFO
BOOLEAN fCampaignSector; BOOLEAN fCampaignSector;
#endif #endif
UINT32 uiNumberOfPrisonersOfWar; UINT8 uiNumberOfPrisonersOfWar[PRISONER_MAX];
UINT8 uiInterrogationHundredsLeft; UINT8 uiInterrogationHundredsLeft;
INT8 bPadding[ 36 ]; INT8 bPadding[ 36 ];
@@ -519,7 +529,7 @@ typedef struct UNDERGROUND_SECTORINFO
BOOLEAN fCampaignSector; BOOLEAN fCampaignSector;
#endif #endif
UINT32 uiNumberOfPrisonersOfWar; UINT8 uiNumberOfPrisonersOfWar[PRISONER_MAX];
INT8 bPadding[32]; INT8 bPadding[32];
//no padding left! //no padding left!
+5 -5
View File
@@ -2416,8 +2416,8 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
case FACILITY_INTERROGATE_PRISONERS: case FACILITY_INTERROGATE_PRISONERS:
sIconIndex = 23; sIconIndex = 23;
fDoIcon = TRUE; fDoIcon = TRUE;
//sPtsAvailable = (INT16)( CalculateInterrogationValue(pSoldier, &usMaximumPts )/100 ); sPtsAvailable = (INT16)( CalculateInterrogationValue(pSoldier, &usMaximumPts ) );
bPtsAvailable = (FLOAT)( CalculateInterrogationValue(pSoldier, &usMaximumPts )/100.0 ); //bPtsAvailable = (FLOAT)( CalculateInterrogationValue(pSoldier, &usMaximumPts )/100.0 );
fShowNumber = TRUE; fShowNumber = TRUE;
fShowMaximum = TRUE; fShowMaximum = TRUE;
break; break;
@@ -2452,10 +2452,10 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
if ( fShowMaximum ) if ( fShowMaximum )
{ {
if ( pSoldier->bAssignment == FACILITY_INTERROGATE_PRISONERS ) /*if ( pSoldier->bAssignment == FACILITY_INTERROGATE_PRISONERS )
swprintf( sString, L"%2.2f/%d", bPtsAvailable, usMaximumPts ); swprintf( sString, L"%2.2f/%d", bPtsAvailable, usMaximumPts );
else else*/
swprintf( sString, L"%d/%d", sPtsAvailable, usMaximumPts ); swprintf( sString, L"%d/%d", sPtsAvailable, usMaximumPts );
} }
else else
{ {
+96 -18
View File
@@ -3665,12 +3665,7 @@ void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldierOld )
// Flugente: if this was a prisoner of war, reduce their sector count by 1 // Flugente: if this was a prisoner of war, reduce their sector count by 1
if ( pSoldierOld->bSoldierFlagMask & SOLDIER_POW_PRISON ) if ( pSoldierOld->bSoldierFlagMask & SOLDIER_POW_PRISON )
{ KillOnePrisoner( &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] );
// get sector
SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
if ( pSector )
pSector->uiNumberOfPrisonersOfWar = max(0, pSector->uiNumberOfPrisonersOfWar - 1);
}
} }
else if ( pSoldierOld->bTeam == MILITIA_TEAM ) else if ( pSoldierOld->bTeam == MILITIA_TEAM )
{ {
@@ -6548,15 +6543,16 @@ void PrisonerMessageBoxCallBack( UINT8 ubExitValue )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RELEASED] ); ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_RELEASED] );
} }
UINT32 prisonerstobemoved = 0; UINT16 prisonerstobemoved = 0;
UINT8 prisonersspecial = 0, prisonerselite = 0, prisonersregular = 0, prisonersadmin = 0;
BOOLEAN success = FALSE; BOOLEAN success = FALSE;
if ( !gbWorldSectorZ ) if ( !gbWorldSectorZ )
{ {
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] ); SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] );
prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar; prisonerstobemoved = GetNumberOrPrisoners( pSectorInfo, &prisonersspecial, &prisonerselite, &prisonersregular, &prisonersadmin );
pSectorInfo->uiNumberOfPrisonersOfWar = 0; DeleteAllPrisoners( pSectorInfo );
if ( usSectorID > 0) if ( usSectorID > 0)
{ {
@@ -6566,7 +6562,7 @@ void PrisonerMessageBoxCallBack( UINT8 ubExitValue )
{ {
success = TRUE; success = TRUE;
pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved; ChangeNumberOfPrisoners( pPrisonSectorInfo, prisonersspecial, prisonerselite, prisonersregular, prisonersadmin );
CHAR16 wString[ 64 ]; CHAR16 wString[ 64 ];
GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), wString ); GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), wString );
@@ -6578,9 +6574,9 @@ void PrisonerMessageBoxCallBack( UINT8 ubExitValue )
{ {
UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ ); UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar; prisonerstobemoved = GetNumberOrPrisoners( pSectorInfo, &prisonersspecial, &prisonerselite, &prisonersregular, &prisonersadmin );
pSectorInfo->uiNumberOfPrisonersOfWar = 0; DeleteAllPrisoners( pSectorInfo );
if ( usSectorID > 0) if ( usSectorID > 0)
{ {
@@ -6590,7 +6586,7 @@ void PrisonerMessageBoxCallBack( UINT8 ubExitValue )
{ {
success = TRUE; success = TRUE;
pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved; ChangeNumberOfPrisoners( pPrisonSectorInfo, prisonersspecial, prisonerselite, prisonersregular, prisonersadmin );
CHAR16 wString[ 64 ]; CHAR16 wString[ 64 ];
GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), wString ); GetShortSectorString( SECTORX(usSectorID), SECTORY(usSectorID), wString );
@@ -6633,9 +6629,9 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
case SOLDIER_CLASS_ARMY: ubNumPrisonerTroop++; break; case SOLDIER_CLASS_ARMY: ubNumPrisonerTroop++; break;
case SOLDIER_CLASS_ELITE: ubNumPrisonerElite++; break; case SOLDIER_CLASS_ELITE: ubNumPrisonerElite++; break;
default: default:
// if none of the above classes, ignore this one // if none of the above classes, ignore this one
continue; continue;
break; break;
} }
++ubNumPrisoners; ++ubNumPrisoners;
@@ -6716,13 +6712,13 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
{ {
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] ); SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners; ChangeNumberOfPrisoners(pSectorInfo, 0, ubNumPrisonerElite, ubNumPrisonerTroop, ubNumPrisonerAdmin);
} }
else else
{ {
UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ ); UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ );
pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners; ChangeNumberOfPrisoners(pSectorInfo, 0, ubNumPrisonerElite, ubNumPrisonerTroop, ubNumPrisonerAdmin);
} }
if ( ubNumPrisoners ) if ( ubNumPrisoners )
@@ -10195,3 +10191,85 @@ BOOLEAN IsProfileInUse(UINT8 usTeam, INT8 aType, UINT16 aNr)
return FALSE; return FALSE;
} }
UINT16 GetNumberOrPrisoners( SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin )
{
if ( !pSectorInfo )
return 0;
*apSpecial = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL];
*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]);
}
UINT16 GetNumberOrPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin )
{
if ( !pSectorInfo )
return 0;
*apSpecial = pSectorInfo->uiNumberOfPrisonersOfWar[PRISONER_SPECIAL];
*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]);
}
void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, 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_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) );
}
void ChangeNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, INT16 aSpecial, 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_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) );
}
void DeleteAllPrisoners( SECTORINFO *pSectorInfo )
{
if ( !pSectorInfo )
return;
for (int i = PRISONER_ADMIN; i < PRISONER_MAX; ++i)
pSectorInfo->uiNumberOfPrisonersOfWar[i] = 0;
}
void DeleteAllPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo )
{
if ( !pSectorInfo )
return;
for (int i = PRISONER_ADMIN; i < PRISONER_MAX; ++i)
pSectorInfo->uiNumberOfPrisonersOfWar[i] = 0;
}
// used when the player kills a prisoner. We kill of high-value prisoners first, to punish this kind of behaviour
void KillOnePrisoner( SECTORINFO *pSectorInfo )
{
if ( !pSectorInfo )
return;
for (int i = PRISONER_SPECIAL; i >= PRISONER_ADMIN; --i)
{
if ( pSectorInfo->uiNumberOfPrisonersOfWar[i] )
{
pSectorInfo->uiNumberOfPrisonersOfWar[i] -= 1;
break;
}
}
}
+14
View File
@@ -6,6 +6,7 @@
#include "Soldier Control.h" #include "Soldier Control.h"
#include "overhead types.h" #include "overhead types.h"
#include "soldier find.h" #include "soldier find.h"
#include "Campaign Types.h" // added by Flugente for SECTORINFO and UNDERGROUND_SECTORINFO
#define ADD_SOLDIER_NO_PROFILE_ID 200 #define ADD_SOLDIER_NO_PROFILE_ID 200
#define MAX_REALTIME_SPEED_VAL 10 #define MAX_REALTIME_SPEED_VAL 10
@@ -364,5 +365,18 @@ BOOLEAN AllowedToStealFromTeamMate( UINT8 aAccessorID, UINT8 aTargetID );
// Flugente: is an soldier profile already used? // Flugente: is an soldier profile already used?
BOOLEAN IsProfileInUse(UINT8 usTeam, INT8 aType, UINT16 aNr); BOOLEAN IsProfileInUse(UINT8 usTeam, INT8 aType, UINT16 aNr);
// Flugente: functions altering a sector's prisoners
UINT16 GetNumberOrPrisoners( SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin );
UINT16 GetNumberOrPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, UINT8* apSpecial, UINT8* apElite, UINT8* apRegular, UINT8* apAdmin );
void ChangeNumberOfPrisoners( SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin );
void ChangeNumberOfPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo, INT16 aSpecial, INT16 aElite, INT16 aRegular, INT16 aAdmin );
void DeleteAllPrisoners( SECTORINFO *pSectorInfo );
void DeleteAllPrisoners( UNDERGROUND_SECTORINFO *pSectorInfo );
// used when the player kills a prisoner. We kill of high-value prisoners first, to punish this kind of behaviour
void KillOnePrisoner( SECTORINFO *pSectorInfo );
#endif #endif
+2 -1
View File
@@ -15520,7 +15520,8 @@ BOOLEAN SOLDIERTYPE::CanProcessPrisoners()
{ {
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( this->sSectorX, this->sSectorY ) ] ); SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( this->sSectorX, this->sSectorY ) ] );
if ( pSectorInfo->uiNumberOfPrisonersOfWar > 0 ) UINT8 tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0;
if ( GetNumberOrPrisoners(pSectorInfo, &tmp1, &tmp2, &tmp3, &tmp4) > 0 )
return TRUE; return TRUE;
} }
+3 -2
View File
@@ -2818,7 +2818,8 @@ void SectorAddPrisonersofWar( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
return; return;
// only continue if there are prisoners in this sector that need to be placed // only continue if there are prisoners in this sector that need to be placed
UINT32 numprisoners = pSector->uiNumberOfPrisonersOfWar; UINT8 tmp1 = 0, tmp2 = 0, tmp3 = 0, tmp4 = 0;
UINT16 numprisoners = GetNumberOrPrisoners(pSector, &tmp1, &tmp2, &tmp3, &tmp4);
if ( !numprisoners ) if ( !numprisoners )
return; return;
@@ -2842,7 +2843,7 @@ void SectorAddPrisonersofWar( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
// we can't spawn if all civilian slots are already taken (we leave a bit of reserve for more important civs) // we can't spawn if all civilian slots are already taken (we leave a bit of reserve for more important civs)
UINT8 maxcivs = max(0, gGameExternalOptions.ubGameMaximumNumberOfCivilians - 3); UINT8 maxcivs = max(0, gGameExternalOptions.ubGameMaximumNumberOfCivilians - 3);
for (UINT8 i = numberofpows; i < numprisoners; ++i) for (UINT16 i = numberofpows; i < numprisoners; ++i)
{ {
if ( numberofcivs < maxcivs ) if ( numberofcivs < maxcivs )
{ {
+3 -3
View File
@@ -7557,12 +7557,12 @@ STR16 szFoodTextStr[]=
L"区域供水不可行,食物和生存系统已被关闭"//L"Sectorwide canteen filling not possible, Food System is off!" L"区域供水不可行,食物和生存系统已被关闭"//L"Sectorwide canteen filling not possible, Food System is off!"
}; };
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]= // TODO.Translate
{ {
L"%d 名俘虏已被审讯", //L"%d prisoners were interrogated.", L"%d elites, %d regulars and %d amins were interrogated.",
L"%d 名俘虏已支付赎金", //L"%d prisoners paid ransom money.", L"%d 名俘虏已支付赎金", //L"%d prisoners paid ransom money.",
L"%d 名俘虏已供出同伙位置", //L"%d prisoners revealed enemy positions.", L"%d 名俘虏已供出同伙位置", //L"%d prisoners revealed enemy positions.",
L"%d 名俘虏已加入我方阵营", //L"%d prisoners joined our cause.", L"%d elites, %d regulars and %d amins joined our cause.",
L"俘虏掀起大规模暴动!在 %s 监狱!", //L"Prisoners start a massive riot in %s!", L"俘虏掀起大规模暴动!在 %s 监狱!", //L"Prisoners start a massive riot in %s!",
L"俘虏被押送前往 %s 监狱", //L"The army now occupies the prison in %s, the prisoners were freed!", L"俘虏被押送前往 %s 监狱", //L"The army now occupies the prison in %s, the prisoners were freed!",
L"俘虏已被释放!", //L"Prisoners have been released!", L"俘虏已被释放!", //L"Prisoners have been released!",
+2 -2
View File
@@ -7555,10 +7555,10 @@ STR16 szFoodTextStr[]=
// TODO.Translate // TODO.Translate
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]=
{ {
L"%d prisoners were interrogated.", L"%d elites, %d regulars and %d amins were interrogated.",
L"%d prisoners paid ransom money.", L"%d prisoners paid ransom money.",
L"%d prisoners revealed enemy positions.", L"%d prisoners revealed enemy positions.",
L"%d prisoners joined our cause.", L"%d elites, %d regulars and %d amins joined our cause.",
L"Prisoners start a massive riot in %s!", L"Prisoners start a massive riot in %s!",
L"%d prisoners were sent to %s!", L"%d prisoners were sent to %s!",
L"Prisoners have been released!", L"Prisoners have been released!",
+2 -2
View File
@@ -7543,10 +7543,10 @@ STR16 szFoodTextStr[]=
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]=
{ {
L"%d prisoners were interrogated.", L"%d elites, %d regulars and %d amins were interrogated.",
L"%d prisoners paid ransom money.", L"%d prisoners paid ransom money.",
L"%d prisoners revealed enemy positions.", L"%d prisoners revealed enemy positions.",
L"%d prisoners joined our cause.", L"%d elites, %d regulars and %d amins joined our cause.",
L"Prisoners start a massive riot in %s!", L"Prisoners start a massive riot in %s!",
L"%d prisoners were sent to %s!", L"%d prisoners were sent to %s!",
L"Prisoners have been released!", L"Prisoners have been released!",
+2 -2
View File
@@ -7539,10 +7539,10 @@ STR16 szFoodTextStr[]=
// TODO.Translate // TODO.Translate
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]=
{ {
L"%d prisoners were interrogated.", L"%d elites, %d regulars and %d amins were interrogated.",
L"%d prisoners paid ransom money.", L"%d prisoners paid ransom money.",
L"%d prisoners revealed enemy positions.", L"%d prisoners revealed enemy positions.",
L"%d prisoners joined our cause.", L"%d elites, %d regulars and %d amins joined our cause.",
L"Prisoners start a massive riot in %s!", L"Prisoners start a massive riot in %s!",
L"%d prisoners were sent to %s!", L"%d prisoners were sent to %s!",
L"Prisoners have been released!", L"Prisoners have been released!",
+2 -2
View File
@@ -7365,10 +7365,10 @@ STR16 szFoodTextStr[]=
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]=
{ {
L"%d Gefangenge wurden verhört.", L"%d Elite-, %d Reguläre und %d Hilfssoldaten wurden verhört.",
L"%d Gefangene wurden gegen Lösegeld freigelassen.", L"%d Gefangene wurden gegen Lösegeld freigelassen.",
L"%d Gefangene haben uns Truppenstandorte verraten.", L"%d Gefangene haben uns Truppenstandorte verraten.",
L"%d Gefangene schliessen sich uns an.", L"%d Elite-, %d Reguläre und %d Hilfssoldaten laufen zu uns über.",
L"Gefangenenaufstand in %s!", L"Gefangenenaufstand in %s!",
L"%d Gefangene wurden nach %s geschickt!", L"%d Gefangene wurden nach %s geschickt!",
L"Gefangene freigelassen!", L"Gefangene freigelassen!",
+2 -2
View File
@@ -7541,10 +7541,10 @@ STR16 szFoodTextStr[]=
// TODO.Translate // TODO.Translate
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]=
{ {
L"%d prisoners were interrogated.", L"%d elites, %d regulars and %d amins were interrogated.",
L"%d prisoners paid ransom money.", L"%d prisoners paid ransom money.",
L"%d prisoners revealed enemy positions.", L"%d prisoners revealed enemy positions.",
L"%d prisoners joined our cause.", L"%d elites, %d regulars and %d amins joined our cause.",
L"Prisoners start a massive riot in %s!", L"Prisoners start a massive riot in %s!",
L"%d prisoners were sent to %s!", L"%d prisoners were sent to %s!",
L"Prisoners have been released!", L"Prisoners have been released!",
+2 -2
View File
@@ -7561,10 +7561,10 @@ STR16 szFoodTextStr[]=
// TODO.Translate // TODO.Translate
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]=
{ {
L"%d prisoners were interrogated.", L"%d elites, %d regulars and %d amins were interrogated.",
L"%d prisoners paid ransom money.", L"%d prisoners paid ransom money.",
L"%d prisoners revealed enemy positions.", L"%d prisoners revealed enemy positions.",
L"%d prisoners joined our cause.", L"%d elites, %d regulars and %d amins joined our cause.",
L"Prisoners start a massive riot in %s!", L"Prisoners start a massive riot in %s!",
L"%d prisoners were sent to %s!", L"%d prisoners were sent to %s!",
L"Prisoners have been released!", L"Prisoners have been released!",
+4 -4
View File
@@ -7539,18 +7539,18 @@ STR16 szFoodTextStr[]=
L"Sectorwide canteen filling not possible, Food System is off!" L"Sectorwide canteen filling not possible, Food System is off!"
}; };
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]= // TODO.Translate
{ {
L"%d prisoners were interrogated.", // TODO.Translate L"%d elites, %d regulars and %d amins were interrogated.",
L"%d prisoners paid ransom money.", L"%d prisoners paid ransom money.",
L"%d prisoners revealed enemy positions.", L"%d prisoners revealed enemy positions.",
L"%d prisoners joined our cause.", L"%d elites, %d regulars and %d amins joined our cause.",
L"Prisoners start a massive riot in %s!", L"Prisoners start a massive riot in %s!",
L"%d prisoners were sent to %s!", L"%d prisoners were sent to %s!",
L"Prisoners have been released!", L"Prisoners have been released!",
L"The army now occupies the prison in %s, the prisoners were freed!", L"The army now occupies the prison in %s, the prisoners were freed!",
L"The enemy refuses to surrender!", L"The enemy refuses to surrender!",
L"The enemy refuses to take you as prisoners - they prefer you dead!", // TODO.Translate L"The enemy refuses to take you as prisoners - they prefer you dead!",
L"This behaviour is set OFF in your ini settings.", L"This behaviour is set OFF in your ini settings.",
}; };
+2 -2
View File
@@ -7559,10 +7559,10 @@ STR16 szFoodTextStr[]=
// TODO.Translate // TODO.Translate
STR16 szPrisonerTextStr[]= STR16 szPrisonerTextStr[]=
{ {
L"%d prisoners were interrogated.", L"%d elites, %d regulars and %d amins were interrogated.",
L"%d prisoners paid ransom money.", L"%d prisoners paid ransom money.",
L"%d prisoners revealed enemy positions.", L"%d prisoners revealed enemy positions.",
L"%d prisoners joined our cause.", L"%d elites, %d regulars and %d amins joined our cause.",
L"Prisoners start a massive riot in %s!", L"Prisoners start a massive riot in %s!",
L"%d prisoners were sent to %s!", L"%d prisoners were sent to %s!",
L"Prisoners have been released!", L"Prisoners have been released!",