mirror of
https://github.com/1dot13/source.git
synced 2026-08-05 14:00:23 +02:00
Prisoner feature bugfix (#110)
* Allow game to continue after offering to surrender to enemies * Fix issues related to surrender and POW quests - Quests were ended prematurely if one had prisoners in both alma and tixa - Strategic status flags for rescue/escape were not set properly - Only the maximum amount a prison can hold will be taken as POWs, rest of the mercs will either escape or have to fight to the death, to prevent a player having unrescuable POWs - Capturing a mercenary had a lot of functions called that should not have been, IF the merc is not going to be captured after all * Switch all tactical surrender calls to use one unified function * Only mercs that are capable can escape Incapacitated mercs left behind will die. Should probably prioritize incapacitated mercs to be captured by the enemy to prevent needless deaths * Combine pow quest state changes into one function * Add JumpIntoEscapedSector to header file * Allow enemy to demand surrender even if they already have POWs in Tixa and Alma * Remove surrender from UB * Address review feedback
This commit is contained in:
+110
-41
@@ -2215,7 +2215,7 @@ BOOLEAN SetCurrentWorldSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
// GridNo = NOWHERE, which causes this assertion to fail
|
||||
//CHRISL: There's also an issue with vehicles. Soldiers in any vehicle are considered to be in sGridNo = NOWHERE
|
||||
// This will result in an assertion error, so let's skip the assertion if the merc is assigned to a vehicle
|
||||
if ( !(MercPtrs[i]->flags.uiStatusFlags & SOLDIER_DEAD) && MercPtrs[i]->bAssignment != VEHICLE && !SPY_LOCATION( MercPtrs[i]->bAssignment ) )
|
||||
if (!(MercPtrs[i]->flags.uiStatusFlags & SOLDIER_DEAD) && MercPtrs[i]->bAssignment != VEHICLE && !SPY_LOCATION(MercPtrs[i]->bAssignment) && MercPtrs[i]->bAssignment != ASSIGNMENT_POW)
|
||||
{
|
||||
//Assert( !MercPtrs[i]->bActive || !MercPtrs[i]->bInSector || MercPtrs[i]->sGridNo != NOWHERE || MercPtrs[i]->bVehicleID == iHelicopterVehicleId );
|
||||
Assert( !MercPtrs[i]->bActive || !MercPtrs[i]->bInSector || !TileIsOutOfBounds( MercPtrs[i]->sGridNo ) || MercPtrs[i]->bVehicleID == iHelicopterVehicleId );
|
||||
@@ -2265,7 +2265,7 @@ BOOLEAN SetCurrentWorldSector( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
// GridNo = NOWHERE, which causes this assertion to fail
|
||||
//CHRISL: There's also an issue with vehicles. Soldiers in any vehicle are considered to be in sGridNo = NOWHERE
|
||||
// This will result in an assertion error, so let's skip the assertion if the merc is assigned to a vehicle
|
||||
if ( !(MercPtrs[i]->flags.uiStatusFlags & SOLDIER_DEAD) && MercPtrs[i]->bAssignment != VEHICLE )
|
||||
if (!(MercPtrs[i]->flags.uiStatusFlags & SOLDIER_DEAD) && MercPtrs[i]->bAssignment != VEHICLE && MercPtrs[i]->bAssignment != ASSIGNMENT_POW)
|
||||
{
|
||||
//Assert( !MercPtrs[i]->bActive || !MercPtrs[i]->bInSector || MercPtrs[i]->sGridNo != NOWHERE || MercPtrs[i]->bVehicleID == iHelicopterVehicleId );
|
||||
Assert( !MercPtrs[i]->bActive || !MercPtrs[i]->bInSector || !TileIsOutOfBounds( MercPtrs[i]->sGridNo ) || MercPtrs[i]->bVehicleID == iHelicopterVehicleId );
|
||||
@@ -3290,23 +3290,9 @@ void UpdateMercsInSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ )
|
||||
}
|
||||
|
||||
// ATE: Call actions based on what POW we are on...
|
||||
if ( gubQuest[QUEST_HELD_IN_ALMA] == QUESTINPROGRESS )
|
||||
{
|
||||
// Complete quest
|
||||
EndQuest( QUEST_HELD_IN_ALMA, sSectorX, sSectorY );
|
||||
|
||||
// Do action
|
||||
HandleNPCDoAction( 0, NPC_ACTION_GRANT_EXPERIENCE_3, 0 );
|
||||
}
|
||||
#ifndef JA2UB
|
||||
else if (gubQuest[QUEST_HELD_IN_TIXA] == QUESTINPROGRESS)
|
||||
{
|
||||
// Complete quest
|
||||
EndQuest(QUEST_HELD_IN_TIXA, sSectorX, sSectorY);
|
||||
|
||||
// Do action
|
||||
HandleNPCDoAction(0, NPC_ACTION_GRANT_EXPERIENCE_3, 0);
|
||||
}
|
||||
HandlePOWQuestState(Q_END, QUEST_HELD_IN_ALMA, sSectorX, sSectorY, bSectorZ);
|
||||
HandlePOWQuestState(Q_END, QUEST_HELD_IN_TIXA, sSectorX, sSectorY, bSectorZ);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -4301,6 +4287,68 @@ void JumpIntoAdjacentSector( UINT8 ubTacticalDirection, UINT8 ubJumpCode, INT32
|
||||
}
|
||||
}
|
||||
|
||||
void JumpIntoEscapedSector(UINT8 ubTacticalDirection)
|
||||
{
|
||||
// Remove any incapacitated mercs from current squads and assign them to new squad
|
||||
UINT32 i = gTacticalStatus.Team[gbPlayerNum].bFirstID;
|
||||
UINT32 const lastID = gTacticalStatus.Team[gbPlayerNum].bLastID;
|
||||
INT8 currentSquad = -1;
|
||||
|
||||
for (SOLDIERTYPE* pSoldier = MercPtrs[i]; i <= lastID; ++i, ++pSoldier)
|
||||
{
|
||||
// Are we not active in sector
|
||||
if (!pSoldier->bActive || !pSoldier->bInSector || pSoldier->stats.bLife >= OKLIFE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (currentSquad == -1)
|
||||
{
|
||||
currentSquad = AddCharacterToUniqueSquad(pSoldier);
|
||||
continue;
|
||||
}
|
||||
if (!AddCharacterToSquad(pSoldier, currentSquad))
|
||||
{
|
||||
currentSquad = AddCharacterToUniqueSquad(pSoldier);
|
||||
}
|
||||
}
|
||||
|
||||
// Retreat squads that are capable of it
|
||||
for (size_t i = 0; i < NUMBER_OF_SQUADS; i++)
|
||||
{
|
||||
for (size_t j = 0; j < NUMBER_OF_SOLDIERS_PER_SQUAD; j++)
|
||||
{
|
||||
SOLDIERTYPE* pSoldier = Squad[i][j];
|
||||
if (pSoldier && OK_CONTROLLABLE_MERC(pSoldier))
|
||||
{
|
||||
GROUP* pGroup = GetGroup(pSoldier->ubGroupID);
|
||||
switch (ubTacticalDirection)
|
||||
{
|
||||
case NORTH:
|
||||
pGroup->ubPrevX = pGroup->ubSectorX;
|
||||
pGroup->ubPrevY = pGroup->ubSectorY - 1;
|
||||
break;
|
||||
case EAST:
|
||||
pGroup->ubPrevX = pGroup->ubSectorX + 1;
|
||||
pGroup->ubPrevY = pGroup->ubSectorY;
|
||||
break;
|
||||
case SOUTH:
|
||||
pGroup->ubPrevX = pGroup->ubSectorX;
|
||||
pGroup->ubPrevY = pGroup->ubSectorY + 1;
|
||||
break;
|
||||
case WEST:
|
||||
pGroup->ubPrevX = pGroup->ubSectorX - 1;
|
||||
pGroup->ubPrevY = pGroup->ubSectorY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
RetreatGroupToPreviousSector(pGroup);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleSoldierLeavingSectorByThemSelf( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
@@ -4361,17 +4409,7 @@ void AllMercsWalkedToExitGrid( )
|
||||
(gubAdjacentJumpCode == JUMP_ALL_LOAD_NEW || gubAdjacentJumpCode == JUMP_SINGLE_LOAD_NEW) )
|
||||
{
|
||||
HandleLoyaltyImplicationsOfMercRetreat( RETREAT_TACTICAL_TRAVERSAL, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
|
||||
// End inetrrogation quest if we left the sector, but haven't killed all enemies
|
||||
if ( gWorldSectorX == 7 && gWorldSectorY == 14 && gbWorldSectorZ == 0 && gubQuest[QUEST_INTERROGATION] == QUESTINPROGRESS )
|
||||
{
|
||||
// Finish quest, although not give points here...
|
||||
InternalEndQuest( QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY, FALSE );
|
||||
// ... give them manually, but halved
|
||||
GiveQuestRewardPoint( gWorldSectorX, gWorldSectorY, 4, NO_PROFILE );
|
||||
// Also get us know, we finished the quest
|
||||
ResetHistoryFact( QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY );
|
||||
}
|
||||
HandlePOWQuestState(Q_END, QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -4539,17 +4577,7 @@ void AllMercsHaveWalkedOffSector( )
|
||||
(gubAdjacentJumpCode == JUMP_ALL_LOAD_NEW || gubAdjacentJumpCode == JUMP_SINGLE_LOAD_NEW) )
|
||||
{
|
||||
HandleLoyaltyImplicationsOfMercRetreat( RETREAT_TACTICAL_TRAVERSAL, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
|
||||
// End inetrrogation quest if we left the sector, but haven't killed all enemies
|
||||
if ( gWorldSectorX == 7 && gWorldSectorY == 14 && gbWorldSectorZ == 0 && gubQuest[QUEST_INTERROGATION] == QUESTINPROGRESS )
|
||||
{
|
||||
// Finish quest, although not give points here...
|
||||
InternalEndQuest( QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY, FALSE );
|
||||
// ... give them manually, but halved
|
||||
GiveQuestRewardPoint( gWorldSectorX, gWorldSectorY, 4, NO_PROFILE );
|
||||
// Also get us know, we finished the quest
|
||||
ResetHistoryFact( QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY );
|
||||
}
|
||||
HandlePOWQuestState(Q_END, QUEST_INTERROGATION, gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
@@ -6921,6 +6949,47 @@ BOOLEAN EscapeDirectionIsValid( INT8 * pbDirection )
|
||||
}
|
||||
return(*pbDirection != -1);
|
||||
}
|
||||
|
||||
bool IsEscapeDirectionValid(WorldDirections pbDirection)
|
||||
{
|
||||
bool isValid = false;
|
||||
UINT8 const ubSectorID = SECTOR(gWorldSectorX, gWorldSectorY);
|
||||
|
||||
switch (pbDirection)
|
||||
{
|
||||
case NORTH:
|
||||
if (!(gWorldSectorY - 1 < MINIMUM_VALID_Y_COORDINATE || gMapInformation.sNorthGridNo == NOWHERE ||
|
||||
SectorInfo[ubSectorID].ubTraversability[NORTH_STRATEGIC_MOVE] == GROUNDBARRIER || SectorInfo[ubSectorID].ubTraversability[NORTH_STRATEGIC_MOVE] == EDGEOFWORLD))
|
||||
{
|
||||
isValid = true;
|
||||
}
|
||||
break;
|
||||
case EAST:
|
||||
if (!(gWorldSectorX + 1 > MAXIMUM_VALID_X_COORDINATE || gMapInformation.sEastGridNo == NOWHERE ||
|
||||
SectorInfo[ubSectorID].ubTraversability[EAST_STRATEGIC_MOVE] == GROUNDBARRIER || SectorInfo[ubSectorID].ubTraversability[EAST_STRATEGIC_MOVE] == EDGEOFWORLD))
|
||||
{
|
||||
isValid = true;
|
||||
}
|
||||
break;
|
||||
case SOUTH:
|
||||
if (!(gWorldSectorY + 1 > MAXIMUM_VALID_Y_COORDINATE || gMapInformation.sSouthGridNo == NOWHERE ||
|
||||
SectorInfo[ubSectorID].ubTraversability[SOUTH_STRATEGIC_MOVE] == GROUNDBARRIER || SectorInfo[ubSectorID].ubTraversability[SOUTH_STRATEGIC_MOVE] == EDGEOFWORLD))
|
||||
{
|
||||
isValid = true;
|
||||
}
|
||||
break;
|
||||
case WEST:
|
||||
if (!(gWorldSectorX - 1 < MINIMUM_VALID_X_COORDINATE || gMapInformation.sWestGridNo == NOWHERE ||
|
||||
SectorInfo[ubSectorID].ubTraversability[WEST_STRATEGIC_MOVE] == GROUNDBARRIER || SectorInfo[ubSectorID].ubTraversability[WEST_STRATEGIC_MOVE] == EDGEOFWORLD))
|
||||
{
|
||||
isValid = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
#ifdef JA2UB
|
||||
|
||||
|
||||
@@ -7968,4 +8037,4 @@ UINT8 tryToRecoverSquadsAndMovementGroups(SOLDIERTYPE* pCharacter) {
|
||||
}
|
||||
CheckSquadMovementGroups();
|
||||
return GetSoldierGroupId(pCharacter);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user