mirror of
https://github.com/1dot13/source.git
synced 2026-08-12 14:10:23 +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:
+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--;
|
||||
|
||||
Reference in New Issue
Block a user