- New Feature: The rosine system now allows to capture enemy soldeirs via using handcuffs on them. They can e transferred to a prison the player controls, and be interrogated there.

- GameDir revision 1568 is required for this feature.
- Savegame compatibility is maintained.

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5709 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2012-12-03 00:50:48 +00:00
parent 33f3fefc3b
commit cb9c217bb1
46 changed files with 1472 additions and 57 deletions
+8
View File
@@ -2404,6 +2404,14 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
}
break;
case FACILITY_INTERROGATE_PRISONERS:
sIconIndex = 23;
fDoIcon = TRUE;
sPtsAvailable = (INT16)( CalculateInterrogationValue(pSoldier, &usMaximumPts ) ) / 100;
fShowNumber = TRUE;
fShowMaximum = TRUE;
break;
}
// Check for being serviced...
+82 -1
View File
@@ -1215,6 +1215,87 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa
}
}
// Flugente: handcuffing people
if ( HasItemFlag(usHandItem, HANDCUFFS ) )
{
// ATE: AI CANNOT GO THROUGH HERE!
INT32 usMapPos;
BOOLEAN fHadToUseCursorPos = FALSE;
GetMouseMapPos( &usMapPos );
// See if we can get there to stab
sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
if ( sActionGridNo == -1 )
{
// Try another location...
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE );
if ( sActionGridNo == -1 )
{
return( ITEM_HANDLE_CANNOT_GETTO_LOCATION );
}
/*if ( !gTacticalStatus.fAutoBandageMode )
{
fHadToUseCursorPos = TRUE;
}*/
}
// Calculate AP costs...
sAPCost = GetAPsToHandcuff( pSoldier, sActionGridNo );
sAPCost += PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if ( EnoughPoints( pSoldier, sAPCost, 0, fFromUI ) )
{
// OK, set UI
SetUIBusy( pSoldier->ubID );
// CHECK IF WE ARE AT THIS GRIDNO NOW
if ( pSoldier->sGridNo != sActionGridNo )
{
// SEND PENDING ACTION
pSoldier->aiData.ubPendingAction = MERC_HANDCUFF_PERSON;
if ( fHadToUseCursorPos )
{
pSoldier->aiData.sPendingActionData2 = usMapPos;
}
else
{
if ( pTargetSoldier != NULL )
{
pSoldier->aiData.sPendingActionData2 = pTargetSoldier->sGridNo;
}
else
{
pSoldier->aiData.sPendingActionData2 = sGridNo;
}
}
pSoldier->aiData.bPendingActionData3 = ubDirection;
pSoldier->aiData.ubPendingActionAnimCount = 0;
// WALK UP TO DEST FIRST
pSoldier->EVENT_InternalGetNewSoldierPath( sActionGridNo, pSoldier->usUIMovementMode, FALSE, TRUE );
}
else
{
pSoldier->EVENT_SoldierHandcuffPerson( sAdjustedGridNo, ubDirection );
}
if ( fFromUI )
{
guiPendingOverrideEvent = A_CHANGE_TO_MOVE;
}
return( ITEM_HANDLE_OK );
}
else
{
return( ITEM_HANDLE_NOAPS );
}
}
if ( Item[usHandItem].canandstring )
{
STRUCTURE *pStructure;
@@ -4574,7 +4655,7 @@ void CleanWeapons( BOOLEAN fCleanAll )
if ( pSoldier->bActive )
pSoldier->CleanWeapon(fCleanAll);
}
else // peform action for every merc in this sector
else // perform action for every merc in this sector
{
UINT8 bMercID, bLastTeamID;
SOLDIERTYPE* pSoldier = NULL;
+33
View File
@@ -4142,6 +4142,24 @@ INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT32 usMapPos, UINT32 uiFlags )
gsUIHandleShowMoveGridLocation = sActionGridNo;
}
}
else if ( uiFlags == MOVEUI_TARGET_HANDCUFF )
{
sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE );
if ( sActionGridNo == -1 )
{
sActionGridNo = usMapPos;
}
sAPCost = GetAPsToHandcuff( pSoldier, sActionGridNo );
sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints);
if ( sActionGridNo != pSoldier->sGridNo )
{
gfUIHandleShowMoveGrid = TRUE;
gsUIHandleShowMoveGridLocation = sActionGridNo;
}
}
else if ( uiFlags == MOVEUI_TARGET_MERCS )
{
INT32 sGotLocation = NOWHERE;
@@ -4494,6 +4512,21 @@ BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier )
return( FALSE );
}
if ( ubItemCursor == HANDCUFFCURS )
{
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, HANDCUFFS ) )
{
if ( gfUIFullTargetFound )
{
usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
return( TRUE );
}
}
return( FALSE );
}
if ( ubItemCursor == BOMBCURS )
{
if ( usMapPos == pSoldier->sGridNo )
+1
View File
@@ -30,6 +30,7 @@
#define MOVEUI_TARGET_CAN 11
#define MOVEUI_TARGET_REFUEL 12
#define MOVEUI_TARGET_FORTIFICATION 13
#define MOVEUI_TARGET_HANDCUFF 14
#define MOVEUI_RETURN_ON_TARGET_MERC 1
+3
View File
@@ -215,6 +215,9 @@ UICursor gUICursors[ NUM_UI_CURSORS ] =
FORTIFICATION_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FORTIFICATION, 0,
FORTIFICATION_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FORTIFICATION_RED, 0,
HANDCUFF_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HANDCUFF, 0,
HANDCUFF_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HANDCUFF_RED, 0,
};
+3
View File
@@ -189,6 +189,9 @@ typedef enum
FORTIFICATION_GREY_UICURSOR,
FORTIFICATION_RED_UICURSOR,
HANDCUFF_GREY_UICURSOR,
HANDCUFF_RED_UICURSOR,
NUM_UI_CURSORS
} UICursorDefines;
+4
View File
@@ -5043,6 +5043,10 @@ STR16 GetSoldierHealthString( SOLDIERTYPE *pSoldier )
}
else
{
// Flugente: display if we are a prisoner of war
if ( pSoldier->bSoldierFlagMask & SOLDIER_POW )
return zHealthStr[ 7 ];
INT32 cnt, cntStart;
if( pSoldier->stats.bLife == pSoldier->stats.bLifeMax )
{
+5 -4
View File
@@ -174,6 +174,7 @@ typedef enum ATTACHMENT_SLOT{
#define TINCANCURS 22
#define REFUELCURS 23
#define FORTICURS 24
#define HANDCUFFCURS 25
#define CAMERARANGE 10
@@ -728,7 +729,7 @@ extern OBJECTTYPE gTempObject;
// note that these should not be used to determine what kind of an attachment an item is, that is determined by attachmentclass and the AC_xxx flags above
#define EMPTY_SANDBAG 0x00000001 //1
#define FULL_SANDBAG 0x00000002 //2
#define SHOVEL 0x00000004 //4
#define SHOVEL 0x00000004 //4 // a shovel is used for filling sandbags and other building-related tasks
#define CONCERTINA 0x00000008 //8
#define WATER_DRUM 0x00000010 //16 // water drums allow to refill canteens in the sector they are in
@@ -743,15 +744,15 @@ extern OBJECTTYPE gTempObject;
#define ATTENTION_ITEM 0x00001000 //4096 // this item is 'interesting' to the AI. Dumb soldiers may try to pick it up
#define GAROTTE 0x00002000 //8192 // this item is a garotte
#define COVERT 0x00004000 //16384 // if LBE, any gun inside will be covert. On a gun, it will covert in any LBE, even if the LBE does not have that tag itself
#define COVERT 0x00004000 //16384 // if LBE, any gun inside will be covert. On a gun, it will be covert in any LBE, even if the LBE does not have that tag itself
#define CORPSE 0x00008000 //32768 // a dead body
#define SKIN_BLOODCAT 0x00010000 //65536 // retrieve this by skinning (=decapitating) a bloodcat
#define NO_METAL_DETECTION 0x00020000 //131072 // a planted bomb with this flag can NOT be detected via metal detector. Use sparingly!
#define JUMP_GRENADE 0x00040000 //262144 // add +25 heigth to explosion, used for bouncing grenades and jumping mines
/*#define PLAYER_NET_4_LVL_1 0x00080000 //524288
#define HANDCUFFS 0x00080000 //524288 // item can be used to capture soldiers
#define PLAYER_NET_1_LVL_2 0x00100000 //1048576
/*#define PLAYER_NET_1_LVL_2 0x00100000 //1048576
#define PLAYER_NET_2_LVL_2 0x00200000 //2097152
#define PLAYER_NET_3_LVL_2 0x00400000 //4194304
#define PLAYER_NET_4_LVL_2 0x00800000 //8388608
+1 -1
View File
@@ -711,7 +711,7 @@ void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, I
if ( gGameOptions.fNewTraitSystem )
{
// Flugente: if we have the covert trait and are covert, we might simply be returning from a reconnaissance mission in enemy territory. No need for a morale drop in this case
if ( !HAS_SKILL_TRAIT( pTeamSoldier, COVERT_NT ) || ( pTeamSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) == 0) )
if ( !HAS_SKILL_TRAIT( pTeamSoldier, COVERT_NT ) || ( (pTeamSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) == 0) )
{
// SANDRO - no penalty for pacifists to run away
if ( gMercProfiles[pTeamSoldier->ubProfile].bCharacterTrait != CHAR_TRAIT_PACIFIST )
+247 -1
View File
@@ -1660,6 +1660,11 @@ BOOLEAN ExecuteOverhead( )
pSoldier->EVENT_SoldierBuildStructure( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 );
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
}
else if ( pSoldier->aiData.ubPendingAction == MERC_HANDCUFF_PERSON )
{
pSoldier->EVENT_SoldierHandcuffPerson( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 );
pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION;
}
else if ( pSoldier->aiData.ubPendingAction == MERC_GIVEITEM )
{
pSoldier->EVENT_SoldierBeginGiveItem( );
@@ -4040,7 +4045,7 @@ UINT8 LastActiveTeamMember( UINT8 ubTeam )
void CheckForPotentialAddToBattleIncrement( SOLDIERTYPE *pSoldier )
{
UINT16 iCounter2;
//UINT16 iCounter2;
// Check if we are a threat!
if ( !pSoldier->aiData.bNeutral && (pSoldier->bSide != gbPlayerNum ) )
{
@@ -6632,6 +6637,240 @@ void DeathNoMessageTimerCallback( void )
}
}
BOOLEAN GetPlayerControlledPrisonSectorId(UINT32& auSectorID)
{
auSectorID = 0;
UINT16 highestprisonsize = 0;
for(INT16 sX = 1; sX < MAP_WORLD_X - 1; ++sX )
{
for(INT16 sY = 1; sY < MAP_WORLD_X - 1; ++sY )
{
if ( !SectorOursAndPeaceful( sX, sY, 0 ) )
continue;
// Is there a prison in this sector?
for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt)
{
// Is this facility here?
if (gFacilityLocations[SECTOR(sX, sY)][cnt].fFacilityHere)
{
// we determine wether this is a prison by checking for usPrisonBaseLimit
if ( gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > highestprisonsize )
{
highestprisonsize = gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit;
auSectorID = SECTOR(sX, sY);
break;
}
}
}
}
}
return (highestprisonsize > 0);
}
extern INT32 giReinforcementPool;
void PrisonerMessageBoxCallBack( UINT8 ubExitValue )
{
if ( !gbWorldSectorZ )
{
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] );
UINT32 prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar;
pSectorInfo->uiNumberOfPrisonersOfWar = 0;
if (ubExitValue == MSG_BOX_RETURN_YES)
{
UINT32 uSectorID = 0;
if ( GetPlayerControlledPrisonSectorId(uSectorID) )
{
SECTORINFO *pPrisonSectorInfo = &( SectorInfo[ uSectorID ] );
if ( pPrisonSectorInfo )
pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved;
}
}
else
{
// send some prisoners back to queen's pool
// there is a chance that escaped prisoners may return to the queen...
giReinforcementPool += (prisonerstobemoved * gGameExternalOptions.ubPrisonerReturntoQueenChance) / 100;
}
}
else
{
UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
UINT32 prisonerstobemoved = pSectorInfo->uiNumberOfPrisonersOfWar;
pSectorInfo->uiNumberOfPrisonersOfWar = 0;
if (ubExitValue == MSG_BOX_RETURN_YES)
{
UINT32 uSectorID = 0;
if ( GetPlayerControlledPrisonSectorId(uSectorID) )
{
SECTORINFO *pPrisonSectorInfo = &( SectorInfo[ uSectorID ] );
if ( pPrisonSectorInfo )
pPrisonSectorInfo->uiNumberOfPrisonersOfWar += prisonerstobemoved;
}
}
else
{
// send some prisoners back to queen's pool
// there is a chance that escaped prisoners may return to the queen...
giReinforcementPool += (prisonerstobemoved * gGameExternalOptions.ubPrisonerReturntoQueenChance) / 100;
}
}
}
void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt = 0;
UINT8 ubNumPrisoners = 0;
UINT8 ubNumPrisonerAdmin = 0;
UINT8 ubNumPrisonerTroop = 0;
UINT8 ubNumPrisonerElite = 0;
// Check if the battle is won!
// Loop through all mercs and make go
for ( pTeamSoldier = Menptr, cnt = 0; cnt < TOTAL_SOLDIERS; ++pTeamSoldier, ++cnt )
{
// Kill those not already dead.,...
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bTeam == ENEMY_TEAM )
{
// For sure for flag thet they are dead is not set
if ( ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_DEAD ) )
{
if ( pTeamSoldier->stats.bLife > OKLIFE && pTeamSoldier->stats.bLife != 0 )
{
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;
}
++ubNumPrisoners;
// place items on the floor
INT8 bVisible = 0;
UINT16 usItemFlags = 0;
UINT8 size = pTeamSoldier->inv.size();
for ( UINT8 cnt = 0; cnt < size; ++cnt )
{
OBJECTTYPE* pObj = &( pTeamSoldier->inv[ cnt ] );
if ( pObj->exists() == true )
{
// Check if it's supposed to be dropped
if ( !( (*pObj).fFlags & OBJECT_UNDROPPABLE ) || pTeamSoldier->bTeam == gbPlayerNum )
{
if ( !(Item[ pObj->usItem ].defaultundroppable ) )
{
//ReduceAmmoDroppedByNonPlayerSoldiers( pTeamSoldier, cnt );
//if this soldier was an enemy
// Kaiden: Added from UB's reveal all items after combat feature!
// HEADROCK HAM B2.8: Now also reveals equipment dropped by militia, if requirement is met.
if( pTeamSoldier->bTeam == ENEMY_TEAM ||
( gGameExternalOptions.ubMilitiaDropEquipment == 2 && pTeamSoldier->bTeam == MILITIA_TEAM ) ||
( gGameExternalOptions.ubMilitiaDropEquipment == 1 && pTeamSoldier->bTeam == MILITIA_TEAM && Menptr[ pTeamSoldier->ubAttackerID ].bTeam != OUR_TEAM ))
{
//add a flag to the item so when all enemies are killed, we can run through and reveal all the enemies items
usItemFlags |= WORLD_ITEM_DROPPED_FROM_ENEMY;
if ( Item[pObj->usItem].damageable && Item[pObj->usItem].usItemClass != IC_THROWING_KNIFE ) // Madd: drop crappier items from enemies on higher difficulty levels - note the quick fix for throwing knives
{
(*pObj)[0]->data.objectStatus -= (gGameOptions.ubDifficultyLevel - 1) * Random(20);
(*pObj)[0]->data.objectStatus = min(max((*pObj)[0]->data.objectStatus,1),100); // never below 1% or above 100%
(*pObj)[0]->data.sRepairThreshold = max(1, min(100, ((*pObj)[0]->data.objectStatus + 200)/3 ));
}
}
//if(UsingNewAttachmentSystem()==true)
//ReduceAttachmentsOnGunForNonPlayerChars(pTeamSoldier, pObj);
// HEADROCK HAM B2.8: Militia will drop items only if allowed.
if (!(gGameExternalOptions.ubMilitiaDropEquipment == 0 && pTeamSoldier->bTeam == MILITIA_TEAM ) &&
!(gGameExternalOptions.ubMilitiaDropEquipment == 1 && pTeamSoldier->bTeam == MILITIA_TEAM && Menptr[ pTeamSoldier->ubAttackerID ].bTeam == OUR_TEAM ))
{
AddItemToPool( pTeamSoldier->sGridNo, pObj, bVisible , pTeamSoldier->pathing.bLevel, usItemFlags, -1 );
}
}
}
}
}
DropKeysInKeyRing( pTeamSoldier, pTeamSoldier->sGridNo, pTeamSoldier->pathing.bLevel, bVisible, FALSE, 0, FALSE );
// Make team look for items
AllSoldiersLookforItems( TRUE );
if ( pTeamSoldier->bTeam != gbPlayerNum )
// Remove merc!
// ATE: Remove merc slot first - will disappear if no corpse data found!
TacticalRemoveSoldier( pTeamSoldier->ubID );
else
pTeamSoldier->RemoveSoldierFromGridNo( );
// Remove as target
RemoveManAsTarget( pTeamSoldier );
}
}
}
}
if (!bMapZ) // Battle ended Above-ground
{
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( sMapX, sMapY ) ] );
pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners;
pSectorInfo->ubNumAdmins -= ubNumPrisonerAdmin;
pSectorInfo->ubNumTroops -= ubNumPrisonerTroop;
pSectorInfo->ubNumElites -= ubNumPrisonerElite;
pSectorInfo->ubAdminsInBattle -= ubNumPrisonerAdmin;
pSectorInfo->ubTroopsInBattle -= ubNumPrisonerTroop;
pSectorInfo->ubElitesInBattle -= ubNumPrisonerElite;
}
else
{
UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ );
pSectorInfo->uiNumberOfPrisonersOfWar += ubNumPrisoners;
pSectorInfo->ubNumAdmins -= ubNumPrisonerAdmin;
pSectorInfo->ubNumTroops -= ubNumPrisonerTroop;
pSectorInfo->ubNumElites -= ubNumPrisonerElite;
pSectorInfo->ubAdminsInBattle -= ubNumPrisonerAdmin;
pSectorInfo->ubTroopsInBattle -= ubNumPrisonerTroop;
pSectorInfo->ubElitesInBattle -= ubNumPrisonerElite;
}
if ( ubNumPrisoners )
{
//if ( guiCurrentScreen == GAME_SCREEN )
UINT32 uSectorID = 0;
if ( GetPlayerControlledPrisonSectorId(uSectorID) )
DoMessageBox( MSG_BOX_BASIC_STYLE, TacticalStr[ PRISONER_DECIDE_STR ], guiCurrentScreen, ( UINT8 )MSG_BOX_FLAG_YESNO, PrisonerMessageBoxCallBack, NULL );
else
DoMessageBox( MSG_BOX_BASIC_STYLE, TacticalStr[ PRISONER_NO_PRISONS_STR ], guiCurrentScreen, ( UINT8 )MSG_BOX_FLAG_OK, NULL, NULL );
}
}
void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
{
if (!bMapZ) // Battle ended Above-ground
@@ -6829,6 +7068,9 @@ BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated )
}
}
// Flugente: remove those enemies that are captured and add them to the prisoner pool
RemoveCapturedEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
// Kill all enemies. Sometime even after killing all the enemies, there appeares "in battle" enemies in sector info
RemoveStaticEnemiesFromSectorInfo( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
@@ -7431,6 +7673,10 @@ UINT8 NumCapableEnemyInSector( )
}
else
{
// Flugente: captured soldiers also do not count
if ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW )
continue;
// Check for any more badguys
if ( !pTeamSoldier->aiData.bNeutral && (pTeamSoldier->bSide != 0 ) )
{
+10 -1
View File
@@ -3663,9 +3663,18 @@ INT16 GetAPsToBuildFortification( SOLDIERTYPE *pSoldier, INT32 usMapPos )
sAPCost += APBPConstants[AP_FORTIFICATION];
return sAPCost;
}
INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos )
{
INT16 sAPCost = 0;
sAPCost = PlotPath( pSoldier, usMapPos, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints );
sAPCost += APBPConstants[AP_HANDCUFF];
return sAPCost;
}
INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier )
{
+1
View File
@@ -357,6 +357,7 @@ INT16 GetAPsToUseCan( SOLDIERTYPE *pSoldier, INT32 usMapPos );
INT16 GetBPsTouseJar( SOLDIERTYPE *pSoldier );
INT16 GetAPsToBuildFortification( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente
INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente
INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier );
+142
View File
@@ -15217,6 +15217,51 @@ void SOLDIERTYPE::Strip()
}
}
// can we process prisoners in this sector?
BOOLEAN SOLDIERTYPE::CanProcessPrisoners()
{
if ( !bInSector || stats.bLife < OKLIFE )
return FALSE;
// Is there a prison in this sector?
BOOLEAN prisonhere = FALSE;
for (UINT16 cnt = 0; cnt < NUM_FACILITY_TYPES; ++cnt)
{
// Is this facility here?
if (gFacilityLocations[SECTOR(this->sSectorX, this->sSectorY)][cnt].fFacilityHere)
{
// we determine wether this is a prison by checking for usPrisonBaseLimit
if (gFacilityTypes[cnt].AssignmentData[FAC_INTERROGATE_PRISONERS].usPrisonBaseLimit > 0)
{
prisonhere = TRUE;
break;
}
}
}
if ( !prisonhere )
return FALSE;
// Are there any prisoners in this prison?
if ( !this->bSectorZ )
{
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] );
if ( pSectorInfo->uiNumberOfPrisonersOfWar > 0 )
return TRUE;
}
// no underground prisons anyway
/*else
{
UNDERGROUND_SECTORINFO *pSectorInfo = FindUnderGroundSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
if ( pSectorInfo->uiNumberOfPrisonersOfWar > 0 )
return TRUE;
}*/
return FALSE;
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
INT8 bBandaged; //,savedOurTurn;
@@ -16115,6 +16160,103 @@ void SOLDIERTYPE::EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection
}
}
void SOLDIERTYPE::EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection )
{
UINT8 ubPerson = WhoIsThere2( sGridNo, this->pathing.bLevel );
if ( ubPerson != NOBODY && MercPtrs[ ubPerson ]->bTeam == ENEMY_TEAM && !(MercPtrs[ ubPerson ]->bSoldierFlagMask & SOLDIER_POW) )
{
// we found someone we can handcuff
SOLDIERTYPE* pSoldier = MercPtrs[ ubPerson ];
// check wether we will be successful
BOOLEAN success = FALSE;
if ( pSoldier->flags.fMercAsleep || pSoldier->bCollapsed )
success = TRUE;
else
{
// check wether we can forcefully handcuff the other soldier, but this will be hard
UINT32 attackrating = 10 * EffectiveExpLevel( this ) + EffectiveStrength( this, FALSE ) + 2 * EffectiveDexterity( this, FALSE ) + EffectiveAgility( this, FALSE );
UINT32 defenserating = 10 * EffectiveExpLevel( pSoldier ) + 2 * EffectiveStrength( pSoldier, FALSE ) + EffectiveDexterity( pSoldier, FALSE ) + 2 * EffectiveAgility( pSoldier, FALSE );
ReducePointsForFatigue( this, &attackrating );
ReducePointsForFatigue( pSoldier, &defenserating );
if ( Random(attackrating) > Random(defenserating) + 50 )
success = TRUE;
}
if ( success )
{
// arrest this guy
pSoldier->bSoldierFlagMask |= SOLDIER_POW;
// move the items in his hands to the floor and move our handcuff into his hands
if ( pSoldier->inv[ HANDPOS ].exists() == true && !( pSoldier->inv[ HANDPOS ].fFlags & OBJECT_UNDROPPABLE ))
{
// ATE: if our guy, make visible....
INT8 bVisible = (pSoldier->bTeam == gbPlayerNum) ? 1 : 0;
UINT16 itemflags = ( pSoldier->bTeam == ENEMY_TEAM ) ? 0 : WORLD_ITEM_DROPPED_FROM_ENEMY;
if(UsingNewAttachmentSystem()==true)
ReduceAttachmentsOnGunForNonPlayerChars(pSoldier, &(pSoldier->inv[ HANDPOS ]));
AddItemToPool( pSoldier->sGridNo, &(pSoldier->inv[ HANDPOS ]), bVisible, pSoldier->pathing.bLevel, itemflags, -1 ); //Madd: added usItemFlags to function arguments
DeleteObj( &(pSoldier->inv[HANDPOS]) );
}
if ( pSoldier->inv[ SECONDHANDPOS ].exists() == true && !( pSoldier->inv[ SECONDHANDPOS ].fFlags & OBJECT_UNDROPPABLE ))
{
// ATE: if our guy, make visible....
INT8 bVisible = (pSoldier->bTeam == gbPlayerNum) ? 1 : 0;
UINT16 itemflags = ( pSoldier->bTeam == ENEMY_TEAM ) ? 0 : WORLD_ITEM_DROPPED_FROM_ENEMY;
if(UsingNewAttachmentSystem()==true)
ReduceAttachmentsOnGunForNonPlayerChars(pSoldier, &(pSoldier->inv[ SECONDHANDPOS ]));
AddItemToPool( pSoldier->sGridNo, &(pSoldier->inv[ SECONDHANDPOS ]), bVisible, pSoldier->pathing.bLevel, itemflags, -1 ); //Madd: added usItemFlags to function arguments
DeleteObj( &(pSoldier->inv[SECONDHANDPOS]) );
}
// move handcuffs to his hands
if ( HasItemFlag( (&(this->inv[HANDPOS]))->usItem, HANDCUFFS ) )
{
AutoPlaceObject( pSoldier, &(this->inv[HANDPOS]), FALSE );
DeleteObj( &(this->inv[HANDPOS]) );
}
// CHANGE DIRECTION AND GOTO ANIMATION NOW
this->EVENT_SetSoldierDesiredDirection( ubDirection );
this->EVENT_SetSoldierDirection( ubDirection );
// CHANGE TO ANIMATION
this->EVENT_InitNewSoldierAnim( RELOAD_ROBOT, 0 , FALSE );
// we gain a bit of experience...
StatChange( this, STRAMT, 2, TRUE );
StatChange( this, DEXTAMT, 3, TRUE );
StatChange( this, EXPERAMT, 2, TRUE );
DeductPoints( this, GetAPsToHandcuff( this, sGridNo ), 0, AFTERACTION_INTERRUPT );
}
else
{
// we gain a bit of experience...
StatChange( this, DEXTAMT, 2, TRUE );
DeductPoints( this, GetAPsToHandcuff( this, sGridNo ), 0, AFTERACTION_INTERRUPT );
// curses!
this->DoMercBattleSound( BATTLE_SOUND_CURSE1 );
}
}
else
{
// Say NOTHING quote...
this->DoMercBattleSound( BATTLE_SOUND_NOTHING );
}
}
void SOLDIERTYPE::EVENT_SoldierBeginReloadRobot( INT32 sGridNo, UINT8 ubDirection, UINT8 ubMercSlot )
{
+8 -3
View File
@@ -223,6 +223,7 @@ enum
MERC_ATTACH_CAN,
MERC_FUEL_VEHICLE,
MERC_BUILD_FORTIFICATION,
MERC_HANDCUFF_PERSON,
};
// ENUMERATIONS FOR THROW ACTIONS
@@ -356,8 +357,8 @@ enum
#define SOLDIER_DAMAGED_PANTS 0x00000100 //256 // Soldier's vest is damaged (and thus can't be taken off)
#define SOLDIER_HEADSHOT 0x00000200 //512 // last hit received was a headshot (attack to the head, so knifes/punches also work)
/*#define WH40K_POWER_WEAPON 0x00000400 //1024
#define ENEMY_NET_4_LVL_3 0x00000800 //2048
#define SOLDIER_POW 0x00000400 //1024 // we are a prisoner of war
/*#define ENEMY_NET_4_LVL_3 0x00000800 //2048
#define ENEMY_NET_1_LVL_4 0x00001000 //4096
#define ENEMY_NET_2_LVL_4 0x00002000 //8192
@@ -411,7 +412,7 @@ extern CLOTHES_STRUCT Clothes[CLOTHES_MAX];
// This macro should be used whenever we want to see if someone is neutral
// IF WE ARE CONSIDERING ATTACKING THEM. Creatures & bloodcats will attack neutrals
// but they can't attack empty vehicles!!
#define CONSIDERED_NEUTRAL( me, them ) ( (them->aiData.bNeutral || them->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) && ( me->bTeam != CREATURE_TEAM || (them->flags.uiStatusFlags & SOLDIER_VEHICLE) ) )
#define CONSIDERED_NEUTRAL( me, them ) ( (them->aiData.bNeutral || them->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER|SOLDIER_POW)) && ( me->bTeam != CREATURE_TEAM || (them->flags.uiStatusFlags & SOLDIER_VEHICLE) ) )
typedef struct
{
@@ -1322,6 +1323,7 @@ public:
void EVENT_BeginMercTurn( BOOLEAN fFromRealTime, INT32 iRealTimeCounter );
void EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente
void EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente
BOOLEAN EVENT_InternalGetNewSoldierPath( INT32 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestart );
void EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BOOLEAN fFromMove, UINT16 usAnimState );
@@ -1494,6 +1496,9 @@ public:
// lose disguise or take off any clothes item and switch back to original clothes
void Strip();
// Flugente: prisoner system
BOOLEAN CanProcessPrisoners();
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
+29
View File
@@ -54,6 +54,7 @@ UINT8 HandleBombCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN fActivated
UINT8 HandleJarCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags );
UINT8 HandleTinCanCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags );
UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente
UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente
extern BOOLEAN HandleCheckForBadChangeToGetThrough( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, INT32 sTargetGridNo , INT8 bLevel );
@@ -304,6 +305,11 @@ UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, INT32 usMapPos
ubCursorID = HandleFortificationCursor( pSoldier, sTargetGridNo, uiCursorFlags );
break;
case HANDCUFFCURS:
ubCursorID = HandleHandcuffCursor( pSoldier, sTargetGridNo, uiCursorFlags );
break;
case INVALIDCURS:
ubCursorID = INVALID_ACTION_UICURSOR;
@@ -2208,7 +2214,26 @@ UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 ui
return( FORTIFICATION_RED_UICURSOR );
}
UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags )
{
// DRAW PATH TO GUY
HandleUIMovementCursor( pSoldier, uiCursorFlags, sGridNo, MOVEUI_TARGET_HANDCUFF );
// do we have handcuffs in our hand?
if ( HasItemFlag( (&(pSoldier->inv[HANDPOS]))->usItem, HANDCUFFS ) )
{
// is there a person here?
UINT8 usSoldierIndex = WhoIsThere2( sGridNo, pSoldier->pathing.bLevel );
if ( usSoldierIndex != NOBODY )
{
// no handcuffing if the guy is already caught...
if ( !(MercPtrs[usSoldierIndex]->bSoldierFlagMask & SOLDIER_POW) )
return( HANDCUFF_GREY_UICURSOR );
}
}
return( HANDCUFF_RED_UICURSOR );
}
void HandleEndConfirmCursor( SOLDIERTYPE *pSoldier )
{
@@ -2685,6 +2710,10 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier )
if ( HasItemFlag(usInHand, (EMPTY_SANDBAG|FULL_SANDBAG|SHOVEL|CONCERTINA)) )
ubCursor = FORTICURS;
// Flugente: cursor for handcuffs
if ( HasItemFlag(usInHand, HANDCUFFS) )
ubCursor = HANDCUFFCURS;
// Now check our terrain to see if we cannot do the action now...
if ( WaterTooDeepForAttacks( pSoldier->sGridNo) )
{
+5 -2
View File
@@ -3012,9 +3012,12 @@ IAN COMMENTED THIS OUT MAY 1997 - DO WE NEED THIS?
if (pOpponent)
{
// check to see if OPPONENT considers US neutral
if ( (pOpponent->aiData.bOppList[ubTarget] == SEEN_CURRENTLY) && !pOpponent->aiData.bNeutral && !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && (pSoldier->bSide != pOpponent->bSide) && pOpponent->RecognizeAsCombatant(pSoldier->ubID) )
if ( (pOpponent->aiData.bOppList[ubTarget] == SEEN_CURRENTLY) && !pOpponent->aiData.bNeutral && (pSoldier->bSide != pOpponent->bSide) )
{
RemoveOneOpponent(pOpponent);
// Flugente: we consider enemies to be neutral if they are prisoners of war (otherwise the AI would kill prisoners). Bu as we want to remove them, we have to account for that
// we also move RecognizeAsCombatant to be the last condition checked, because it is the most computationally expensive one
if ( ( !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) || pSoldier->bSoldierFlagMask & SOLDIER_POW ) && pOpponent->RecognizeAsCombatant(pSoldier->ubID) )
RemoveOneOpponent(pOpponent);
}
UpdatePersonal(pOpponent,ubTarget,NOT_HEARD_OR_SEEN,NOWHERE,0);
gbSeenOpponents[ubLoop][ubTarget] = FALSE;