- New prisoner class: Civilians can be interrogated. Does not work for profile-based charcters.

- Capturing civilians is possible if their faction has <fCanBeCaptured> set to 1.

Requires GameDir >= r2215.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7762 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2015-02-28 22:35:30 +00:00
parent 4b70b1e400
commit 9d8e5a4c3a
22 changed files with 321 additions and 99 deletions
+1 -1
View File
@@ -1248,7 +1248,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
}
// Flugente: handcuffing people
if ( gGameExternalOptions.fAllowPrisonerSystem && HasItemFlag( usHandItem, HANDCUFFS ) && pTargetSoldier && pTargetSoldier->CanBeHandcuffed( ) )
if ( gGameExternalOptions.fAllowPrisonerSystem && HasItemFlag( usHandItem, HANDCUFFS ) && pTargetSoldier && pTargetSoldier->CanBeCaptured( ) )
{
// ATE: AI CANNOT GO THROUGH HERE!
INT32 usMapPos;
+1
View File
@@ -82,6 +82,7 @@ typedef struct
BOOLEAN Enabled; //add
BOOLEAN Loyalty;
BOOLEAN AddToBattle;
BOOLEAN fCanBeCaptured; // Flugente: if TRUE, members of this faction can be captured
CHAR16 szCurGroup[MAX_ENEMY_NAMES_CHARS];
} CIV_NAMES_VALUES;
+57 -10
View File
@@ -6789,7 +6789,7 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt )
{
// Kill those not already dead.,...
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == ENEMY_TEAM )
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector )
{
// Only pows that are not dead yet
if ( (pTeamSoldier->usSoldierFlagMask & SOLDIER_POW) && !(pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD) )
@@ -6802,7 +6802,7 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
++sNumPrisoner[PRISONER_GENERAL];
else if ( pTeamSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
++sNumPrisoner[PRISONER_OFFICER];
else
else if ( pTeamSoldier->bTeam == ENEMY_TEAM )
{
switch ( pTeamSoldier->ubSoldierClass )
{
@@ -6815,6 +6815,10 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
break;
}
}
else //if ( pTeamSoldier->bTeam == CIV_TEAM )
{
++sNumPrisoner[PRISONER_CIVILIAN];
}
// Flugente: VIPs
if ( pTeamSoldier->usSoldierFlagMask & SOLDIER_VIP )
@@ -10427,6 +10431,12 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
// if the merc asking for surrender is experienced in capitulation negotiations, we get a bonus to our strength
if ( pSoldier )
playersidestrength = (playersidestrength * (100 + pSoldier->GetBackgroundValue(BG_PERC_CAPITULATION))) / 100;
// Capturing profile-based NPCs would be desirable, but is a good way to break quests. Due to this, we don't allow capturing them.
// As it would be odd if the entire enemy team surrenders apart from one guy, we don't allow surrender, no matter the surrender strength, if a hostile profile-based NPC is around.
// We also don't allow surrender if the enemy has a tank.
// We justify this storywise by these soldiers being very determined leaders who don't allow surrender categorically.
BOOLEAN fNoSurrender = FALSE;
// enemy team
firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
@@ -10436,6 +10446,9 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) )
{
enemysidestrength += pSoldier->GetSurrenderStrength();
if ( pSoldier->ubProfile != NO_PROFILE || pSoldier->ubSoldierClass == SOLDIER_CLASS_TANK )
fNoSurrender = TRUE;
}
}
@@ -10447,8 +10460,14 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) )
{
// if a civilian is not neutral and on the enemy side, add his strength to the team
if ( !pSoldier->aiData.bNeutral && pSoldier->bSide == 1 )
enemysidestrength += pSoldier->GetSurrenderStrength();
if ( !pSoldier->aiData.bNeutral && pSoldier->bSide == 1 && zCivGroupName[pSoldier->ubCivilianGroup].fCanBeCaptured && pSoldier->ubProfile != NO_PROFILE )
fNoSurrender = TRUE;
// a civilian can only be captured if his faction is allowed to. This should prevent the player from exploiting a huge numerical superiority against small enemy groups, like lone assassins.
if ( !pSoldier->CanBeCaptured() )
continue;
enemysidestrength += pSoldier->GetSurrenderStrength( );
}
}
@@ -10464,7 +10483,7 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, New113Message[MSG113_SURRENDER_VALUES], playersidestrength, gGameExternalOptions.fSurrenderMultiplier * enemysidestrength );
// perhaps this can be fleshed out more, for now, let's see if this is acceptable behaviour
if ( playersidestrength >= gGameExternalOptions.fSurrenderMultiplier * enemysidestrength )
if ( !fNoSurrender && playersidestrength >= gGameExternalOptions.fSurrenderMultiplier * enemysidestrength )
{
// it is enough to simply set all soldiers to captured
firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
@@ -10473,8 +10492,12 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
{
if( pSoldier->bActive && ( pSoldier->sSectorX == gWorldSectorX ) && ( pSoldier->sSectorY == gWorldSectorY ) && ( pSoldier->bSectorZ == gbWorldSectorZ) )
{
// only if not dying, and if not a NPC (Mike...)
if( pSoldier->stats.bLife >= OKLIFE && pSoldier->ubProfile == NO_PROFILE )
// can this guy be captured?
if ( !pSoldier->CanBeCaptured( ) )
continue;
// only if not dying
if( pSoldier->stats.bLife >= OKLIFE )
{
pSoldier->usSoldierFlagMask |= SOLDIER_POW;
@@ -10483,10 +10506,34 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
}
}
}
firstid = gTacticalStatus.Team[CIV_TEAM].bFirstID;
lastid = gTacticalStatus.Team[CIV_TEAM].bLastID;
for ( uiCnt = firstid, pSoldier = MercPtrs[uiCnt]; uiCnt <= lastid; ++uiCnt, ++pSoldier )
{
if ( pSoldier->bActive && (pSoldier->sSectorX == gWorldSectorX) && (pSoldier->sSectorY == gWorldSectorY) && (pSoldier->bSectorZ == gbWorldSectorZ) )
{
// can this guy be captured?
if ( !pSoldier->CanBeCaptured() )
continue;
// only if not dying
if ( pSoldier->stats.bLife >= OKLIFE )
{
pSoldier->usSoldierFlagMask |= SOLDIER_POW;
// Remove as target
RemoveManAsTarget( pSoldier );
}
}
}
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_REFUSE_SURRENDER] );
if ( fNoSurrender )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_REFUSE_SURRENDER_LEADER] );
else
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szPrisonerTextStr[STR_PRISONER_REFUSE_SURRENDER] );
// if asking for surrender while undercover and the enemy refuses, he learns who you are, so he uncovers you
if ( gusSelectedSoldier != NOBODY && MercPtrs[ gusSelectedSoldier ]->usSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) )
@@ -10561,8 +10608,8 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
// Flugente: offer the enemy the chance to surrender
void HandleSurrenderOffer( SOLDIERTYPE* pSoldier )
{
// only against enemies...
if ( !pSoldier || pSoldier->bTeam != ENEMY_TEAM )
// abort if bad pointer, or not an enemy and not a capturable civilian
if ( !pSoldier || !pSoldier->CanBeCaptured( ) )
return;
// remember the target's ID
+24 -8
View File
@@ -16176,13 +16176,28 @@ BOOLEAN SOLDIERTYPE::FreePrisoner( )
return FALSE;
}
// can this guy be handcuffed?
BOOLEAN SOLDIERTYPE::CanBeHandcuffed( )
// can this guy be captured (by handcuffing or asking him to surrender)?
BOOLEAN SOLDIERTYPE::CanBeCaptured( )
{
// if this is an enemy that has not already been captured, and is not a NPC, we can handcuff and thus capture him
if ( this->bTeam == ENEMY_TEAM && !(this->usSoldierFlagMask & SOLDIER_POW) && this->ubProfile == NO_PROFILE )
return TRUE;
// if this guy is not already handcuffed, and is not an NPC
if ( !(this->usSoldierFlagMask & SOLDIER_POW) && this->ubProfile == NO_PROFILE )
{
// tanks cannot be captured
if ( this->ubSoldierClass == SOLDIER_CLASS_TANK )
return FALSE;
// enemies can be captured
if ( this->bTeam == ENEMY_TEAM )
return TRUE;
// civilians can be captured if their faction can, and if they are hostile
if ( this->bTeam == CIV_TEAM && zCivGroupName[this->ubCivilianGroup].fCanBeCaptured )
{
if ( !this->aiData.bNeutral && this->bSide == 1 )
return TRUE;
}
}
return FALSE;
}
@@ -19795,7 +19810,7 @@ void SOLDIERTYPE::EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection
UINT8 ubPerson = WhoIsThere2( sGridNo, this->pathing.bLevel );
if ( ubPerson != NOBODY && MercPtrs[ubPerson]->CanBeHandcuffed( ) )
if ( ubPerson != NOBODY && MercPtrs[ubPerson]->CanBeCaptured( ) )
{
// we found someone we can handcuff
SOLDIERTYPE* pSoldier = MercPtrs[ubPerson];
@@ -20390,8 +20405,9 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT8 ubTargetID, BOOLEAN fValid
DeductPoints( this, sAPCost, 0, UNTRIGGERED_INTERRUPT );
apsDeducted = TRUE;
// Flugente: if we are talking to an enemy, we have the option to offer them surrendering... but not on y levels >= 16 (no surrendering in the palace, as we have to kill, not capture, the queen)
if ( pTSoldier->bTeam == ENEMY_TEAM && (gGameExternalOptions.fEnemyCanSurrender || gGameExternalOptions.fPlayerCanAsktoSurrender) && gWorldSectorY < WORLD_MAP_X - 2 )
// Flugente: if we are talking to an enemy, we have the option to offer them surrender...
if ( (pTSoldier->bTeam == ENEMY_TEAM || (pTSoldier->bTeam == CIV_TEAM && zCivGroupName[pTSoldier->ubCivilianGroup].fCanBeCaptured) )
&& (gGameExternalOptions.fEnemyCanSurrender || gGameExternalOptions.fPlayerCanAsktoSurrender) )
{
HandleSurrenderOffer( pTSoldier );
return(FALSE);
+4 -2
View File
@@ -407,7 +407,9 @@ enum
#define SOLDIER_INTERROGATE_OFFICER 0x00000040 //64 // interrogate officers
#define SOLDIER_INTERROGATE_GENERAL 0x00000080 //128 // interrogate generals
#define SOLDIER_INTERROGATE_ALL 0x000000F8 // all interrogation flags
#define SOLDIER_INTERROGATE_CIVILIAN 0x00000100 //256 // interrogate civilian
#define SOLDIER_INTERROGATE_ALL 0x000001F8 // all interrogation flags
// ----------------------------------------------------------------
// -------- added by Flugente: disease property flags --------
@@ -1769,7 +1771,7 @@ public:
BOOLEAN CanProcessPrisoners();
UINT32 GetSurrenderStrength();
BOOLEAN FreePrisoner(); // used for an enemy liberating fellow prisoners
BOOLEAN CanBeHandcuffed(); // can this guy be handcuffed?
BOOLEAN CanBeCaptured(); // can this guy be captured (by handcuffing or asking him to surrender)?
// Flugente: scuba gear
BOOLEAN UsesScubaGear();
+1 -1
View File
@@ -2253,7 +2253,7 @@ UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCurso
{
// is there a person here?
UINT8 usSoldierIndex = WhoIsThere2( sGridNo, pSoldier->pathing.bLevel );
if ( usSoldierIndex != NOBODY && MercPtrs[usSoldierIndex]->CanBeHandcuffed( ) )
if ( usSoldierIndex != NOBODY && MercPtrs[usSoldierIndex]->CanBeCaptured( ) )
{
return( HANDCUFF_GREY_UICURSOR );
}
+7
View File
@@ -49,6 +49,7 @@ civGroupNamesStartElementHandle(void *userData, const XML_Char *name, const XML_
strcmp(name, "Enabled") == 0 ||
strcmp(name, "Loyalty") == 0 ||
strcmp(name, "AddToBattle") == 0 ||
strcmp(name, "fCanBeCaptured" ) == 0 ||
strcmp(name, "szGroup") == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
@@ -98,6 +99,7 @@ civGroupNamesEndElementHandle(void *userData, const XML_Char *name)
zCivGroupName[pData->curCivGroupNames.uiIndex].AddToBattle = pData->curCivGroupNames.AddToBattle;
zCivGroupName[pData->curCivGroupNames.uiIndex].Loyalty = pData->curCivGroupNames.Loyalty;
zCivGroupName[pData->curCivGroupNames.uiIndex].fCanBeCaptured = pData->curCivGroupNames.fCanBeCaptured;
}
else
{
@@ -125,6 +127,11 @@ civGroupNamesEndElementHandle(void *userData, const XML_Char *name)
pData->curElement = ELEMENT;
pData->curCivGroupNames.AddToBattle = (BOOLEAN) atol(pData->szCharData);
}
else if ( strcmp( name, "fCanBeCaptured" ) == 0 )
{
pData->curElement = ELEMENT;
pData->curCivGroupNames.fCanBeCaptured = (BOOLEAN)atol( pData->szCharData );
}
else if(strcmp(name, "szGroup") == 0 )
{
pData->curElement = ELEMENT;