- New Feature: enemy assassins disguise as militia and can ambush player mercs

- Fix: invalid GridNo for mounting weapons

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5753 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2012-12-30 19:20:36 +00:00
parent 3e859f91a8
commit e193f05865
31 changed files with 600 additions and 139 deletions
+6 -1
View File
@@ -1062,7 +1062,12 @@ void LoadGameExternalOptions()
// Flugente: the assassins are disguised initially, so it is harder for the player to detect them
gGameExternalOptions.fAssassinsAreDisguised = iniReader.ReadBoolean("Tactical Difficulty Settings", "ASSASSINS_DISGUISED", TRUE);
// Flugente: does the queen send out assassins that mix among your militia?
gGameExternalOptions.fEnemyAssassins = iniReader.ReadBoolean("Tactical Difficulty Settings", "ENEMY_ASSASSINS", TRUE);
gGameExternalOptions.usAssassinMinimumProgress = iniReader.ReadInteger("Tactical Difficulty Settings", "ASSASSIN_MINIMUM_PROGRESS", 30, 0, 100);
gGameExternalOptions.usAssassinMinimumMilitia = iniReader.ReadInteger("Tactical Difficulty Settings", "ASSASSIN_MINIMUM_MILITIA", 10, 0, 64);
gGameExternalOptions.usAssassinPropabilityModifier = iniReader.ReadInteger("Tactical Difficulty Settings", "ASSASSIN_PROPABILITY_MODIFIER", 100, 0, 1000);
//################# Tactical Vision Settings #################
// Sight range
+11 -1
View File
@@ -361,7 +361,15 @@ typedef struct
BOOLEAN fEnableChanceOfEnemyAmbushes;
INT8 bChanceModifierEnemyAmbushes;
UINT8 usSpecialNPCStronger;
BOOLEAN fAssassinsAreDisguised; // added by Flugente
// Flugente: should kingpin's hitmen be disguised? This will make them have random clothes among other stuff
BOOLEAN fAssassinsAreDisguised;
// Flugente: does the queen send out assassins that mix among your militia?
BOOLEAN fEnemyAssassins;
UINT8 usAssassinMinimumProgress;
UINT8 usAssassinMinimumMilitia;
UINT32 usAssassinPropabilityModifier;
///////////////////////////////////////
// System settings
@@ -522,6 +530,8 @@ typedef struct
UINT32 ubGameProgressMikeAvailable;
UINT32 ubGameProgressIggyAvaliable;
BOOLEAN ubSendTroopsToDrassen;
// Flugente: new counterattacks and other new AI tactics
UINT8 ubAgressiveStrategicAI;
UINT32 ubGameProgressOffensiveStage1;
UINT32 ubGameProgressOffensiveStage2;
+17
View File
@@ -953,6 +953,23 @@ void StartCivQuote( SOLDIERTYPE *pCiv )
}
// Flugente: if we are an assassin, we speak like the militia we emulate
if ( pCiv->bSoldierFlagMask & SOLDIER_ASSASSIN )
{
switch ( pCiv->GetUniformType() )
{
case UNIFORM_MILITIA_REGULAR:
ubCivQuoteID = CIV_QUOTE_MEDIUM_MILITIA;
break;
case UNIFORM_MILITIA_ELITE:
ubCivQuoteID = CIV_QUOTE_ELITE_MILITIA;
break;
default:
ubCivQuoteID = CIV_QUOTE_GREEN_MILITIA;
break;
}
}
// Determine location...
// Get location of civ on screen.....
GetSoldierScreenPos( pCiv, &sScreenX, &sScreenY );
+1 -1
View File
@@ -2125,7 +2125,7 @@ void HandleNPCDoAction( UINT8 ubTargetNPC, UINT16 usActionCode, UINT8 ubQuoteNum
{
//MakeCivHostile( pSoldier, 2 );
}
if (pSoldier->ubProfile != NO_PROFILE && pSoldier->stats.bLife >= OKLIFE)
if ( ( pSoldier->ubProfile != NO_PROFILE || pSoldier->IsAssassin() ) && pSoldier->stats.bLife >= OKLIFE )
{
// trigger quote!
//TriggerNPCWithIHateYouQuote( pSoldier->ubProfile );
+1 -1
View File
@@ -358,7 +358,7 @@ enum
UNNAMED_CIV_GROUP_17,
UNNAMED_CIV_GROUP_18,
UNNAMED_CIV_GROUP_19,
UNNAMED_CIV_GROUP_20,
ASSASSIN_CIV_GROUP, // Flugente: enemy assassins belong to this group
UNNAMED_CIV_GROUP_21,
UNNAMED_CIV_GROUP_22,
UNNAMED_CIV_GROUP_23,
+12 -26
View File
@@ -3066,35 +3066,21 @@ BOOLEAN HandleAtNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving )
}
}
else if ( pSoldier->bTeam == CIV_TEAM && pSoldier->ubProfile != NO_PROFILE && pSoldier->aiData.bNeutral )
else if ( pSoldier->bTeam == CIV_TEAM && pSoldier->IsAssassin() && pSoldier->aiData.bNeutral )
{
switch( pSoldier->ubProfile )
{
case JIM:
case JACK:
case OLAF:
case RAY:
case OLGA:
case TYRONE:
{
INT32 sDesiredMercDist;
INT32 sDesiredMercDist;
if (!TileIsOutOfBounds(ClosestPC( pSoldier, &sDesiredMercDist )))
{
if ( sDesiredMercDist <= NPC_TALK_RADIUS * 2 )
{
// stop
CancelAIAction( pSoldier, TRUE );
// aaaaaaaaaaaaaaaaaaaaatttaaaack!!!!
AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID );
//MakeCivHostile( pSoldier, 2 );
//TriggerNPCWithIHateYouQuote( pSoldier->ubProfile );
}
}
if (!TileIsOutOfBounds(ClosestPC( pSoldier, &sDesiredMercDist )))
{
if ( sDesiredMercDist <= NPC_TALK_RADIUS * 2 )
{
// stop
CancelAIAction( pSoldier, TRUE );
// aaaaaaaaaaaaaaaaaaaaatttaaaack!!!!
AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID );
//MakeCivHostile( pSoldier, 2 );
//TriggerNPCWithIHateYouQuote( pSoldier->ubProfile );
}
break;
default:
break;
}
}
+1 -1
View File
@@ -2048,7 +2048,7 @@ void TakeCorpse( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel )
else if ( pCorpse->def.ubBodyType == REGFEMALE || pCorpse->def.ubBodyType == MINICIV || pCorpse->def.ubBodyType == DRESSCIV )
gTempObject[0]->data.sObjectFlag |= CORPSE_F;
if ( pCorpse->def.usFlags & ROTTING_CORPSE_HEAD_TAKEN )
if ( pCorpse->def.usFlags & ROTTING_CORPSE_HEAD_TAKEN || pCorpse->def.fHeadTaken )
gTempObject[0]->data.sObjectFlag |= CORPSE_NO_HEAD;
if ( pCorpse->def.usFlags & ROTTING_CORPSE_NO_VEST )
+50 -23
View File
@@ -13828,6 +13828,10 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
if ( this->pathing.bLevel == 1 )
return( FALSE );
// this is odd - invalid GridNo... well, not mounted then
if ( TileIsOutOfBounds(this->sGridNo) )
return( FALSE );
// we determine the height of the next tile in our direction. Because of the way structures are handled, we sometimes have to take the very tile we're occupying right now
INT32 nextGridNoinSight = this->sGridNo;
if ( this->ubDirection == NORTH || this->ubDirection == SOUTHWEST || this->ubDirection == WEST || this->ubDirection == NORTHWEST )
@@ -14718,17 +14722,23 @@ BOOLEAN SOLDIERTYPE::EquipmentTooGood( BOOLEAN fCloselook )
INT8 uniformtype = GetUniformType();
// adjust max coolness depending on uniform
// enemy spies get a small bonus here
switch ( uniformtype )
{
case UNIFORM_ENEMY_ADMIN:
maxcoolnessallowed += 1;
break;
case UNIFORM_ENEMY_TROOP:
case UNIFORM_MILITIA_ROOKIE:
maxcoolnessallowed += 2;
break;
case UNIFORM_ENEMY_ELITE:
case UNIFORM_MILITIA_REGULAR:
maxcoolnessallowed += 3;
break;
case UNIFORM_MILITIA_ELITE:
maxcoolnessallowed += 4;
break;
default:
// we do not wear a proper army uniform, uncover us. Note: This should never happen - if this message shows, somewhere, something is wrong
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_UNIFORM_NOORDER], this->name );
@@ -15108,16 +15118,17 @@ BOOLEAN SOLDIERTYPE::SeemsLegit( UINT8 ubObserverID )
// are we targeting a buddy of our observer?
if ( this->ubTargetID && MercPtrs[this->ubTargetID] && MercPtrs[this->ubTargetID]->bTeam == pSoldier->bTeam )
{
// if we aiming at a soldier, others will notice our intent... not covert!
// if we are aiming at a soldier, others will notice our intent... not covert!
if ( WeaponReady(this) )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_TARGETTING_SOLDIER], this->name );
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_TARGETTING_SOLDIER], this->name, MercPtrs[this->ubTargetID]->name );
return FALSE;
}
}
// even as a soldier, we will be caught around fresh corpses
if (distance < gSkillTraitValues.sCOCloseDetectionRangeSoldierCorpse)
// assassins will not be uncovered around corpses, as the AI cannot willingly evade them... one could 'ward' against assassins by surrounding yourself with fresh corpses
if (distance < gSkillTraitValues.sCOCloseDetectionRangeSoldierCorpse && !(this->bSoldierFlagMask & SOLDIER_ASSASSIN) )
{
// check wether we are around a fresh corpse - this will make us much more suspicious
// I deem this necessary, to avoid cheap exploits by nefarious players :-)
@@ -15208,6 +15219,11 @@ BOOLEAN SOLDIERTYPE::RecognizeAsCombatant(UINT8 ubTargetID)
// we have uncovered a spy! Get alerted, if we aren't already
if ( this->aiData.bAlertStatus < STATUS_BLACK )
this->aiData.bAlertStatus = STATUS_BLACK;
// reset our sight of this guy
this->aiData.bOppList[pSoldier->ubID] = NOT_HEARD_OR_SEEN;
ManSeesMan(this, pSoldier, pSoldier->sGridNo, pSoldier->pathing.bLevel, 0, 0);
}
return TRUE;
@@ -15216,11 +15232,22 @@ BOOLEAN SOLDIERTYPE::RecognizeAsCombatant(UINT8 ubTargetID)
return FALSE;
}
// dress up in our natural state
// loose covert property
void SOLDIERTYPE::LooseDisguise( void )
{
// loose any covert flags
this->bSoldierFlagMask &= ~(SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER);
// rehandle sight for everybody
SOLDIERTYPE* pSoldier;
UINT8 iLoop = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
for (pSoldier = MercPtrs[iLoop]; iLoop <= gTacticalStatus.Team[ LAST_TEAM ].bLastID; ++iLoop, ++pSoldier )
{
if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 )
{
RecalculateOppCntsDueToNoLongerNeutral( pSoldier );
}
}
}
// undisguise or take off any clothes item and switch back to original clothes
@@ -15327,7 +15354,7 @@ BOOLEAN SOLDIERTYPE::CanProcessPrisoners()
if ( !prisonhere )
return FALSE;
// Are there any prisoners in this prison?
// Are there any prisoners in this prison? note that there are no underground prisons
if ( !this->bSectorZ )
{
SECTORINFO *pSectorInfo = &( SectorInfo[ SECTOR( this->sSectorX, this->sSectorY ) ] );
@@ -15335,14 +15362,6 @@ BOOLEAN SOLDIERTYPE::CanProcessPrisoners()
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;
}
@@ -15383,6 +15402,20 @@ BOOLEAN SOLDIERTYPE::UsesScubaGear()
return TRUE;
}
// Flugente: are we an assassin?
BOOLEAN SOLDIERTYPE::IsAssassin()
{
// kingpin's hitmen are assassins
if ( this->ubProfile >= JIM && this->ubProfile <= TYRONE )
return TRUE;
// there can be non-NPC assassins too
if ( this->bSoldierFlagMask & SOLDIER_ASSASSIN )
return TRUE;
return FALSE;
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{
INT8 bBandaged; //,savedOurTurn;
@@ -16731,23 +16764,17 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT8 ubTargetID, BOOLEAN fValid
}
else if (pTSoldier->aiData.bNeutral)
{
switch( pTSoldier->ubProfile )
if ( pTSoldier->IsAssassin() )
{
case JIM:
case JACK:
case OLAF:
case RAY:
case OLGA:
case TYRONE:
// Start combat etc
DeleteTalkingMenu();
CancelAIAction( pTSoldier, TRUE );
AddToShouldBecomeHostileOrSayQuoteList( pTSoldier->ubID );
break;
default:
}
else
{
// Start talking!
return( InitiateConversation( pTSoldier, this, NPC_INITIAL_QUOTE, 0 ) );
break;
}
}
else
+6 -3
View File
@@ -358,9 +358,9 @@ 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 SOLDIER_POW 0x00000400 //1024 // we are a prisoner of war
/*#define ENEMY_NET_4_LVL_3 0x00000800 //2048
#define SOLDIER_ASSASSIN 0x00000800 //2048 // we are an enemy assassin, and thus we will behave very different from normal enemies
#define ENEMY_NET_1_LVL_4 0x00001000 //4096
/*#define ENEMY_NET_1_LVL_4 0x00001000 //4096
#define ENEMY_NET_2_LVL_4 0x00002000 //8192
#define ENEMY_NET_3_LVL_4 0x00004000 //16384
#define ENEMY_NET_4_LVL_4 0x00008000 //32768
@@ -1494,7 +1494,7 @@ public:
// do we recognize someone else as a combatant?
BOOLEAN RecognizeAsCombatant(UINT8 ubTargetID);
// loose disguise, dress up in our natural state
// loose covert property
void LooseDisguise( void );
// lose disguise or take off any clothes item and switch back to original clothes
@@ -1506,6 +1506,9 @@ public:
// Flugente: scuba gear
BOOLEAN UsesScubaGear();
// Flugente: are we an assassin?
BOOLEAN IsAssassin();
//////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE;
+124 -3
View File
@@ -1249,8 +1249,8 @@ BOOLEAN TacticalCopySoldierFromProfile( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STR
//}
}
// Flugente: if playing with the covert trait, the assasins come covert, so they are tougher to find
if ( gGameExternalOptions.fAssassinsAreDisguised && gGameOptions.fNewTraitSystem && pSoldier->ubProfile >= JIM && pSoldier->ubProfile <= TYRONE )
// Flugente: if playing with the covert trait, the assassins come covert, so they are tougher to find
if ( gGameExternalOptions.fAssassinsAreDisguised && gGameOptions.fNewTraitSystem && pSoldier->IsAssassin() )
{
pSoldier->bSoldierFlagMask |= (SOLDIER_COVERT_SOLDIER|SOLDIER_COVERT_NPC_SPECIAL|SOLDIER_NEW_VEST|SOLDIER_NEW_PANTS);
@@ -3015,6 +3015,127 @@ SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType )
return TacticalCreateSoldier( &pp, &ubID );
}
// Flugente: assassins are elite soldiers of the civ team that go hostile on a certain event, otherwsie they jsut blend in
SOLDIERTYPE* TacticalCreateEnemyAssassin(UINT8 disguisetype)
{
BASIC_SOLDIERCREATE_STRUCT bp;
SOLDIERCREATE_STRUCT pp;
UINT8 ubID;
SOLDIERTYPE * pSoldier;
// this needs the covert ops trait, and thus the new trait system
if ( !gGameOptions.fNewTraitSystem )
return NULL;
// not in autoresolve!
if( guiCurrentScreen == AUTORESOLVE_SCREEN )
{
return NULL;
}
memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ELITE );
RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ELITE );
bp.bTeam = CIV_TEAM;
bp.bOrders = SEEKENEMY;
bp.bAttitude = (INT8) Random( MAXATTITUDES );
bp.bBodyType = Random(4);
bp.ubSoldierClass = SOLDIER_CLASS_ELITE;
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
pSoldier = TacticalCreateSoldier( &pp, &ubID );
if ( pSoldier )
{
// set correct stats
pSoldier->stats.bLife = pSoldier->stats.bLifeMax = (INT8)( 70 + Random( 26 ) );
pSoldier->stats.bAgility = (INT8)( 70 + Random( 16 ) );
// add assassin flag
pSoldier->bSoldierFlagMask |= (SOLDIER_COVERT_SOLDIER|SOLDIER_ASSASSIN);
// add spy trait lvl2
pSoldier->stats.ubSkillTraits[0] = COVERT_NT;
pSoldier->stats.ubSkillTraits[1] = COVERT_NT;
// set correct civ group
pSoldier->ubCivilianGroup = ASSASSIN_CIV_GROUP;
// set militia name to further irritate the player
swprintf( pSoldier->name, TacticalStr[ MILITIA_TEAM_MERC_NAME ] );
// wear a militia uniform
UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE )
{
switch( disguisetype )
{
case ELITE_MILITIA:
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_MILITIA_ELITE ].vest );
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_MILITIA_ELITE ].pants );
break;
case REGULAR_MILITIA:
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_MILITIA_REGULAR ].vest );
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_MILITIA_REGULAR ].pants );
break;
default:
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[ UNIFORM_MILITIA_ROOKIE ].vest );
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[ UNIFORM_MILITIA_ROOKIE ].pants );
break;
}
// Use palette from HVOBJECT, then use substitution for pants, etc
memcpy( pSoldier->p8BPPPalette, gAnimSurfaceDatabase[ usPaletteAnimSurface ].hVideoObject->pPaletteEntry, sizeof( pSoldier->p8BPPPalette ) * 256 );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->HeadPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->VestPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->PantsPal );
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal );
pSoldier->CreateSoldierPalettes();
}
// send soldier to centre of map, roughly
pSoldier->aiData.sNoiseGridno = (CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS);
pSoldier->aiData.ubNoiseVolume = MAX_MISC_NOISE_DURATION;
}
return( pSoldier );
}
void CreateAssassin(UINT8 disguisetype)
{
SOLDIERTYPE* pSoldier = TacticalCreateEnemyAssassin( disguisetype );
if ( pSoldier )
{
// find a valid starting gridno
if ( pSoldier->sInsertionGridNo <= 0 )
{
UINT8 tries = 0; // counter for gridno function... if we fail to get a valid starting gridno multiple times, do not place assassin
INT32 sGridNo = NOWHERE;
do
{
if ( ++tries > 20 )
return;
sGridNo = RandomGridNo();
}
// a valid starting gridno must be valid, not in a structure, not in water, and not too near to our mercs
while( TileIsOutOfBounds(sGridNo) || FindStructure( sGridNo, STRUCTURE_BLOCKSMOVES ) || TERRAIN_IS_WATER( gpWorldLevelData[ sGridNo ].ubTerrainID) || GridNoNearPlayerMercs(sGridNo, 12) );
pSoldier->sInsertionGridNo = sGridNo;
}
AddSoldierToSector( pSoldier->ubID );
// So we can see them!
AllTeamsLookForAll(NO_INTERRUPTS);
gTacticalStatus.fCivGroupHostile[ ASSASSIN_CIV_GROUP ] = CIV_GROUP_WILL_BECOME_HOSTILE;
}
}
void RandomizeRelativeLevel( INT8 *pbRelLevel, UINT8 ubSoldierClass )
{
@@ -4794,4 +4915,4 @@ BOOLEAN AssignTraitsToSoldier( SOLDIERTYPE *pSoldier, SOLDIERCREATE_STRUCT *pCre
return( TRUE );
else
return( FALSE );
}
}
+4
View File
@@ -426,6 +426,10 @@ SOLDIERTYPE* TacticalCreateArmyTroop();
SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass );
SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType );
// Flugente: assassins are elite soldiers of the civ team that go hostile on a certain event, otherwise they just blend in
SOLDIERTYPE* TacticalCreateEnemyAssassin(UINT8 disguisetype);
void CreateAssassin(UINT8 disguisetype);
// randomly generates a relative level rating (attributes or equipment)
void RandomizeRelativeLevel( INT8 *pbRelLevel, UINT8 ubSoldierClass );
+92 -1
View File
@@ -54,6 +54,8 @@
#include "Queen Command.h"
#include "Map Edgepoints.h"
#include "Campaign.h" // added by Flugente for HighestPlayerProgressPercentage()
BOOLEAN gfOriginalList = TRUE;
SOLDIERINITNODE *gSoldierInitHead = NULL;
@@ -911,7 +913,12 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
//we now have the number, so compared it to the num we can add, and determine how we will
//randomly determine which nodes to add.
if( !ubSlotsAvailable )
{ //There aren't any basic placements of desired team, so exit.
{
// Flugente: decide wether to spawn enemy assassins in this sector (not kingpin's hitmen, they are handled elsewhere)
if ( bTeam == MILITIA_TEAM )
SectorAddAssassins(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
//There aren't any basic placements of desired team, so exit.
return ubNumAdded;
}
curr = mark;
@@ -953,6 +960,11 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
}
curr = curr->next;
}
// Flugente: decide wether to spawn enemy assassins in this sector (not kingpin's hitmen, they are handled elsewhere)
if ( bTeam == MILITIA_TEAM )
SectorAddAssassins(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
return ubNumAdded;
}
@@ -2676,3 +2688,82 @@ void AddSoldierInitListMilitiaOnEdge( UINT8 ubStrategicInsertionCode, UINT8 ubNu
}
}
}
extern UINT32 GetWorldTotalMin( );
// Flugente: decide wether to spawn enemy assassins in this sector (not kingpin's hitmen, they are handled elsewhere)
void SectorAddAssassins( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
{
// this needs to be turned on on, and new trait system needs to be active
if ( !gGameExternalOptions.fEnemyAssassins || !gGameOptions.fNewTraitSystem )
return;
// only possible if a certain progress has been reached - the queen only sends out assassins after a while
if ( HighestPlayerProgressPercentage() < gGameExternalOptions.usAssassinMinimumProgress )
return;
// not in underground sectors
if ( sMapZ > 0 )
return;
SECTORINFO *pSector = &SectorInfo[ SECTOR( sMapX, sMapY ) ];
if ( !pSector )
return;
// does not work atm, time gets reset too early
// not if we have recently been in this sector
//if ( pSector->uiTimeCurrentSectorWasLastLoaded + 10 > GetWorldTotalMin() )
//return;
// do not spawn if militia size is very small (we will be spotted much easier by the player)
UINT32 totalmilitia = pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ] + pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] + pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
if ( totalmilitia < gGameExternalOptions.usAssassinMinimumMilitia )
return;
// count current number of civilians
UINT16 numberofcivs = 0;
SOLDIERTYPE* pTeamSoldier = NULL;
INT32 cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID;
INT32 lastid = gTacticalStatus.Team[ CIV_TEAM ].bLastID;
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt < lastid; ++cnt, ++pTeamSoldier)
{
// check if teamsoldier exists in this sector
if ( pTeamSoldier && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->sSectorX == sMapX && pTeamSoldier->sSectorY == sMapY && pTeamSoldier->bSectorZ == sMapZ )
++numberofcivs;
}
// we can't spawn if all civilian slots are already taken
if ( numberofcivs >= gGameExternalOptions.ubGameMaximumNumberOfCivilians )
return;
// now count militia, and which type (green, regular, elite) is most numerous - that will be the best type to blend in
UINT8 militiacnt = pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ];
UINT8 militiadisguise = GREEN_MILITIA;
if ( pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ] > militiacnt )
{
militiacnt = pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ];
militiadisguise = REGULAR_MILITIA;
}
if ( pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ] > militiacnt )
{
militiacnt = pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
militiadisguise = ELITE_MILITIA;
}
// the bigger the militia, the more likely infiltration
// if militia is at maximum, there is a 10% chance of infiltration
UINT32 resultrange = gGameExternalOptions.ubGameMaximumNumberOfRebels * 10;
UINT32 modifiedmilitianumber = totalmilitia * gGameExternalOptions.usAssassinPropabilityModifier / 100;
if ( Random(resultrange) >= modifiedmilitianumber )
return;
CreateAssassin( militiadisguise );
++numberofcivs;
// if there is still room for a second assassin, and we are feeling very lucky again, add a second one
if ( numberofcivs < gGameExternalOptions.ubGameMaximumNumberOfCivilians && Random(resultrange) < modifiedmilitianumber )
{
CreateAssassin( militiadisguise );
++numberofcivs;
}
}
+3
View File
@@ -59,4 +59,7 @@ void RemoveDetailedPlacementInfo( UINT8 ubNodeID );
void AddProfilesUsingProfileInsertionData();
void AddProfilesNotUsingProfileInsertionData();
// Flugente: decide wether to spawn enemy assassins in this sector (not kingpin's hitmen, they are handled elsewhere)
void SectorAddAssassins( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
#endif
+64 -3
View File
@@ -770,6 +770,11 @@ void CheckHostileOrSayQuoteList( void )
{
gTacticalStatus.fCivGroupHostile[ pSoldier->ubCivilianGroup ] = CIV_GROUP_HOSTILE;
}
// reevaluate sight - we might already see people that weren't enemies until now
ManLooksForOtherTeams(pSoldier);
pSoldier->aiData.bAlertStatus = STATUS_RED;
}
}
@@ -2370,6 +2375,42 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT32 sOppGridNo,
}
}
}
// Flugente: for assassins without profiles
else if ( pSoldier->IsAssassin() && pSoldier->bTeam == CIV_TEAM )
{
// if we are an assassin and still neutral and undercover, approach target and then become hostile
if ( pSoldier->aiData.bNeutral && pSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) )
{
// only if this guy isn't disguised himself!
if ( (pOpponent->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER)) == 0)
{
if ( pSoldier->ubCivilianGroup != NON_CIV_GROUP && gTacticalStatus.fCivGroupHostile[ pSoldier->ubCivilianGroup ] >= CIV_GROUP_WILL_BECOME_HOSTILE )
{
// measure distance to our opponent, only go hostile if he is close enough
if ( PythSpacesAway( pSoldier->sGridNo, pOpponent->sGridNo ) <= NPC_TALK_RADIUS * 2 )
{
AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID );
fNotAddedToList = FALSE;
}
}
}
}
if ( fNotAddedToList )
{
// change orders, reset action!
if ( pSoldier->aiData.bOrders != SEEKENEMY )
{
pSoldier->aiData.bOrders = SEEKENEMY;
if ( pSoldier->aiData.bOppCnt == 0 )
{
// didn't see anyone before!
CancelAIAction( pSoldier, TRUE );
SetNewSituation( pSoldier );
}
}
}
}
else
{
if ( pSoldier->bTeam == CIV_TEAM )
@@ -2515,9 +2556,29 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT32 sOppGridNo,
*/
}
// if both of us are not neutral, AND
// if this man is actually a true opponent (we're not on the same side)
if (!CONSIDERED_NEUTRAL( pOpponent, pSoldier ) && !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide) && pSoldier->RecognizeAsCombatant(pOpponent->ubID) )
// Flugente: reworked this to account for covert ops and assassin mechanisms
// if we are not neutral against this guy, we are truly opponents (we're not on the same side) and recognize him as an opponent...
BOOLEAN fAddAsOpponent = FALSE;
if ( !CONSIDERED_NEUTRAL( pSoldier, pOpponent ) && (pSoldier->bSide != pOpponent->bSide) && pSoldier->RecognizeAsCombatant(pOpponent->ubID) )
{
// ... check wether he is not neutral against us (account for the fact that we might be covert!)
// if we are an NPC assassin
if ( pSoldier->bSoldierFlagMask & SOLDIER_ASSASSIN && pSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) )
{
// check wether our opponent would see us as an opponent if we weren't covert
if ( !( (pSoldier->aiData.bNeutral || pSoldier->bSoldierFlagMask & SOLDIER_POW) && ( pOpponent->bTeam != CREATURE_TEAM || pOpponent->flags.uiStatusFlags & SOLDIER_VEHICLE ) ) )
fAddAsOpponent = TRUE;
}
else
{
// simply check wether this guy sees us as an opponent too
if ( !CONSIDERED_NEUTRAL( pOpponent, pSoldier ) )
fAddAsOpponent = TRUE;
}
}
if ( fAddAsOpponent )
{
AddOneOpponent(pSoldier);
+53
View File
@@ -1459,6 +1459,59 @@ INT32 ClosestPC( SOLDIERTYPE *pSoldier, INT32 * psDistance )
return( sGridNo );
}
// Flugente: like ClosestPC(...), but does not account for covert or not visible mercs
INT32 ClosestUnDisguisedPC( SOLDIERTYPE *pSoldier, INT32 * psDistance )
{
// used by NPCs... find the closest PC
// NOTE: skips EPCs!
UINT8 ubLoop;
SOLDIERTYPE *pTargetSoldier;
INT32 sMinDist = WORLD_MAX;
INT32 sDist;
INT32 sGridNo = NOWHERE;
// Loop through all mercs on player team
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( ; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++)
{
pTargetSoldier = Menptr + ubLoop;
if (!pTargetSoldier->bActive || !pTargetSoldier->bInSector)
continue;
// if not conscious, skip him
if (pTargetSoldier->stats.bLife < OKLIFE)
continue;
if ( AM_AN_EPC( pTargetSoldier ) )
continue;
if ( pTargetSoldier->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) )
continue;
sDist = PythSpacesAway(pSoldier->sGridNo,pTargetSoldier->sGridNo);
// if this PC is not visible to the soldier, then add a penalty to the distance
// so that we weight in favour of visible mercs
if ( pTargetSoldier->bTeam != pSoldier->bTeam && pSoldier->aiData.bOppList[ ubLoop ] != SEEN_CURRENTLY )
continue;
if (sDist < sMinDist)
{
sMinDist = sDist;
sGridNo = pTargetSoldier->sGridNo;
}
}
if ( psDistance )
{
*psDistance = sMinDist;
}
return( sGridNo );
}
INT32 FindClosestClimbPointAvailableToAI( SOLDIERTYPE * pSoldier, INT32 sStartGridNo, INT32 sDesiredGridNo, BOOLEAN fClimbUp )
{
INT32 sGridNo;
+1 -1
View File
@@ -440,7 +440,7 @@ void CalcBestShot(SOLDIERTYPE *pSoldier, ATTACKTYPE *pBestShot, BOOLEAN shootUns
//NumMessage("SHOT AttackValue = ",iAttackValue / 1000);
// special stuff for assassins to ignore militia more
if ( pSoldier->ubProfile >= JIM && pSoldier->ubProfile <= TYRONE && pOpponent->bTeam == MILITIA_TEAM )
if ( pSoldier->IsAssassin() && pOpponent->bTeam == MILITIA_TEAM )
{
iAttackValue /= 2;
}
+61 -19
View File
@@ -662,14 +662,8 @@ INT8 DecideActionNamedNPC( SOLDIERTYPE * pSoldier )
}
}
switch( pSoldier->ubProfile )
if ( pSoldier->IsAssassin() )
{
case JIM:
case JACK:
case OLAF:
case RAY:
case OLGA:
case TYRONE:
sDesiredMercLoc = ClosestPC( pSoldier, &sDesiredMercDist );
if (!TileIsOutOfBounds(sDesiredMercLoc))
@@ -691,9 +685,6 @@ INT8 DecideActionNamedNPC( SOLDIERTYPE * pSoldier )
}
}
}
break;
default:
break;
}
return( AI_ACTION_NONE );
@@ -838,9 +829,36 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
}
}
if (pSoldier->ubProfile != NO_PROFILE)
if ( pSoldier->ubProfile != NO_PROFILE || pSoldier->IsAssassin() )
{
pSoldier->aiData.bAction = DecideActionNamedNPC( pSoldier );
if ( pSoldier->ubProfile != NO_PROFILE )
pSoldier->aiData.bAction = DecideActionNamedNPC( pSoldier );
else
{
INT32 sDesiredMercDist;
INT32 sDesiredMercLoc = ClosestUnDisguisedPC( pSoldier, &sDesiredMercDist );
if (!TileIsOutOfBounds(sDesiredMercLoc))
{
if ( sDesiredMercDist <= NPC_TALK_RADIUS * 2 )
{
AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID );
// now wait a bit!
pSoldier->aiData.usActionData = 5000;
pSoldier->aiData.bAction = AI_ACTION_WAIT;
}
else
{
pSoldier->aiData.usActionData = GoAsFarAsPossibleTowards( pSoldier, sDesiredMercLoc, AI_ACTION_APPROACH_MERC );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
pSoldier->aiData.bAction = AI_ACTION_APPROACH_MERC;
}
}
}
}
if ( pSoldier->aiData.bAction != AI_ACTION_NONE )
{
return( pSoldier->aiData.bAction );
@@ -852,9 +870,7 @@ INT8 DecideActionGreen(SOLDIERTYPE *pSoldier)
}
// turn off counter so we don't check it again
pSoldier->uiTimeSinceLastSpoke = 0;
}
}
// if not in the way, do nothing most of the time
@@ -1440,18 +1456,44 @@ INT8 DecideActionYellow(SOLDIERTYPE *pSoldier)
// ******************
// REAL TIME NPC CODE
// ******************
if (pSoldier->ubProfile != NO_PROFILE)
if (pSoldier->ubProfile != NO_PROFILE || pSoldier->IsAssassin() )
{
pSoldier->aiData.bAction = DecideActionNamedNPC( pSoldier );
if ( pSoldier->ubProfile != NO_PROFILE )
pSoldier->aiData.bAction = DecideActionNamedNPC( pSoldier );
else
{
INT32 sDesiredMercDist;
INT32 sDesiredMercLoc = ClosestUnDisguisedPC( pSoldier, &sDesiredMercDist );
// Flugente: if this guy is disguised, do not consider him
if (!TileIsOutOfBounds(sDesiredMercLoc))
{
if ( sDesiredMercDist <= NPC_TALK_RADIUS * 2 )
{
AddToShouldBecomeHostileOrSayQuoteList( pSoldier->ubID );
// now wait a bit!
pSoldier->aiData.usActionData = 5000;
pSoldier->aiData.bAction = AI_ACTION_WAIT;
}
else
{
pSoldier->aiData.usActionData = GoAsFarAsPossibleTowards( pSoldier, sDesiredMercLoc, AI_ACTION_APPROACH_MERC );
if (!TileIsOutOfBounds(pSoldier->aiData.usActionData))
{
pSoldier->aiData.bAction = AI_ACTION_APPROACH_MERC;
}
}
}
}
if ( pSoldier->aiData.bAction != AI_ACTION_NONE )
{
return( pSoldier->aiData.bAction );
}
}
}
}
// determine the most important noise heard, and its relative value
+1
View File
@@ -162,6 +162,7 @@ INT8 ClosestPanicTrigger( SOLDIERTYPE * pSoldier );
INT32 ClosestKnownOpponent(SOLDIERTYPE *pSoldier, INT32 * psGridNo, INT8 * pbLevel);
INT32 ClosestPC( SOLDIERTYPE *pSoldier, INT32 * psDistance );
INT32 ClosestUnDisguisedPC( SOLDIERTYPE *pSoldier, INT32 * psDistance ); // Flugente: like ClosestPC(...), but does not account for covert or not visible mercs
BOOLEAN CanAutoBandage( BOOLEAN fDoFullCheck );
void DebugAI( STR szOutput );
+18
View File
@@ -1422,3 +1422,21 @@ INT32 RandomGridNo()
}while( !GridNoOnVisibleWorldTile( iMapIndex ) );
return iMapIndex;
}
// Flugente: is this gridno near a player merc?
BOOLEAN GridNoNearPlayerMercs( INT32 sGridNo, INT16 sRadius )
{
SOLDIERTYPE* pTeamSoldier = NULL;
INT32 cnt = gTacticalStatus.Team[ OUR_TEAM ].bFirstID;
INT32 lastid = gTacticalStatus.Team[ OUR_TEAM ].bLastID;
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt < lastid; ++cnt, ++pTeamSoldier)
{
if ( pTeamSoldier && pTeamSoldier->bActive && pTeamSoldier->bInSector )
{
if ( PythSpacesAway(sGridNo, pTeamSoldier->sGridNo) < sRadius )
return( TRUE );
}
}
return( FALSE );
}
+2
View File
@@ -151,5 +151,7 @@ BOOLEAN FindWallJumpDirection( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bStart
BOOLEAN FindLowerLevelWall( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bStartingDir, INT8 *pbDirection );
BOOLEAN FindWindowJumpDirection( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bStartingDir, INT8 *pbDirection );
// Flugente: is this gridno near a player merc?
BOOLEAN GridNoNearPlayerMercs( INT32 sGridNo, INT16 sRadius );
#endif
+23 -19
View File
@@ -614,26 +614,30 @@ void RenderRadarScreen( )
}
else
{
// If on roof, make darker....
if ( pSoldier->pathing.bLevel > 0 )
{
usLineColor = Get16BPPColor( FROMRGB( 150, 150, 0 ) );
}
else
{
usLineColor = Get16BPPColor( gTacticalStatus.Team[ pSoldier->bTeam ].RadarColor );
}
// If on roof, make darker....
if ( pSoldier->pathing.bLevel > 0 )
{
usLineColor = Get16BPPColor( FROMRGB( 150, 150, 0 ) );
}
else
{
usLineColor = Get16BPPColor( gTacticalStatus.Team[ pSoldier->bTeam ].RadarColor );
}
}
}
else
{
usLineColor = Get16BPPColor( gTacticalStatus.Team[ pSoldier->bTeam ].RadarColor );
// Override civ team with red if hostile...
if ( pSoldier->bTeam == CIV_TEAM && !pSoldier->aiData.bNeutral && ( pSoldier->bSide != gbPlayerNum ) )
{
// Override civ team with red if hostile...
if ( pSoldier->bTeam == CIV_TEAM && !pSoldier->aiData.bNeutral && ( pSoldier->bSide != gbPlayerNum ) )
{
usLineColor = Get16BPPColor( FROMRGB( 255, 0, 0 ) );
}
}
// Flugente: if we are a (still covert) enemy assassin, colour us like militia, so that the player wont notice us
if ( pSoldier->bSoldierFlagMask & SOLDIER_ASSASSIN && pSoldier->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER )
usLineColor = Get16BPPColor( gTacticalStatus.Team[ MILITIA_TEAM ].RadarColor );
// Render different color if an enemy and he's unconscious
if ( pSoldier->bTeam != gbPlayerNum && pSoldier->stats.bLife < OKLIFE )
@@ -641,11 +645,11 @@ void RenderRadarScreen( )
usLineColor = Get16BPPColor( FROMRGB( 128, 128, 128 ) );
}
// If on roof, make darker....
if ( pSoldier->bTeam == gbPlayerNum && pSoldier->pathing.bLevel > 0 )
{
usLineColor = Get16BPPColor( FROMRGB( 150, 150, 0 ) );
}
// If on roof, make darker....
if ( pSoldier->bTeam == gbPlayerNum && pSoldier->pathing.bLevel > 0 )
{
usLineColor = Get16BPPColor( FROMRGB( 150, 150, 0 ) );
}
}
RectangleDraw( TRUE, sXSoldRadar, sYSoldRadar, sXSoldRadar+1, sYSoldRadar+1, usLineColor, pDestBuf );
+19 -6
View File
@@ -1425,16 +1425,22 @@ void RenderOverheadOverlays()
{ //normal
if(is_networked)
{
if(pSoldier->bTeam!=0)
if(pSoldier->bTeam != OUR_TEAM)
{
if(pSoldier->bSide==1)
{
// Civ (white)
if (pSoldier->bTeam == 4)
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, 4 );
if (pSoldier->bTeam == CIV_TEAM)
{
// Flugente: if we are a (still covert) enemy assassin, colour us like militia, so that the player wont notice us
if ( pSoldier->bSoldierFlagMask & SOLDIER_ASSASSIN && pSoldier->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER )
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, MILITIA_TEAM );
else
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, CIV_TEAM );
}
// Enemy (red)
else
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, 1 );
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, ENEMY_TEAM );
}
// Other clients
@@ -1449,8 +1455,15 @@ void RenderOverheadOverlays()
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, pSoldier->bTeam );
}
else
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, pSoldier->bTeam );
RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sX, sY, (INT16)(sX + 3), (INT16)(sY + 9));
{
// Flugente: if we are a (still covert) enemy assassin, colour us like militia, so that the player wont notice us
if ( pSoldier->bSoldierFlagMask & SOLDIER_ASSASSIN && pSoldier->bSoldierFlagMask & SOLDIER_COVERT_SOLDIER )
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, MILITIA_TEAM );
else
Blt8BPPDataTo16BPPBufferTransparent((UINT16*)pDestBuf, uiDestPitchBYTES, hVObject, sX, sY, pSoldier->bTeam );
RegisterBackgroundRect(BGND_FLAG_SINGLE, NULL, sX, sY, (INT16)(sX + 3), (INT16)(sY + 9));
}
}
else if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
{ //vehicle
+6 -6
View File
@@ -7426,11 +7426,11 @@ STR16 szCovertTextStr[]=
L"%s 有迷彩油的痕迹!", //L"%s has camo!",
L"%s 有不合身份的背包!", //L"%s has a backpack!",
L"%s 被发现携带尸体!", //L"%s is seen carrying a corpse!",
L"%s's %s is suspicious!",
L"%s's %s is considered military hardware!",
L"%s's %s is suspicious!",// TODO.Translate
L"%s's %s is considered military hardware!",// TODO.Translate
L"%s 携带了太多的枪支!", //L"%s carries too many guns!",
L"%s's %s is too advanced for an arulcan soldier!",
L"%s's %s has too many attachments!",
L"%s's %s is too advanced for an arulcan soldier!",// TODO.Translate
L"%s's %s has too many attachments!",// TODO.Translate
L"%s 被发现有可疑举动!", //L"%s was seen performing suspicious activities!",
L"%s 被发现不像个平民!", //L"%s does not look like a civilian!",
L"%s 被发现流血不止了!", //L"%s bleeding was discovered!",
@@ -7439,7 +7439,7 @@ STR16 szCovertTextStr[]=
L"%s 不应该出现在这里!", //L"%s isn't supposed to be here!",
L"%s 不应该在这个时候出现在这里!", //L"%s isn't supposed to be here at this time!",
L"%s 被发现在新鲜尸体旁边行踪诡秘!", //L"%s was seen near a fresh corpse!",
L"%s 的装备让人惊疑!", //L"%s equipment raises a few eyebrows!",
L"%s is seen targetting %s!", // TODO.Translate
L"%s 被发现瞄准了其他士兵!", //L"%s is seen targeting a soldier!",
L"%s 被识破了 %s 伪装!", //L"%s has seen through %s disguise!",
L"无法找到对应的衣服信息在 Items.xml 中!", //L"No clothes item found in Items.xml!",
@@ -7450,7 +7450,7 @@ STR16 szCovertTextStr[]=
L"未发现制服!", //L"No uniform found!",
L"%s 已伪装成平民", //L"%s is now disguised as a civilian.",
L"%s 已伪装成士兵", //L"%s is now disguised as a soldier.",
L"%s wears a disorderly uniform!",
L"%s wears a disorderly uniform!",// TODO.Translate
};
STR16 szCorpseTextStr[]=
+3 -3
View File
@@ -7431,14 +7431,14 @@ STR16 szCovertTextStr[]=
L"%s was seen performing suspicious activities!",
L"%s does not look like a civilian!",
L"%s bleeding was discovered!",
L"%s is drunk and doesn't look like a soldier!",
L"%s is drunk and doesn't behave like a soldier!",
L"On closer inspection, %s's disguise does not hold!",
L"%s isn't supposed to be here!",
L"%s isn't supposed to be here at this time!",
L"%s was seen near a fresh corpse!",
L"%s equipment raises a few eyebrows!",
L"%s is seen targeting a soldier!",
L"%s has seen through %s disguise!",
L"%s is seen targetting %s!",
L"%s has seen through %s's disguise!",
L"No clothes item found in Items.xml!",
L"This does not work with the old trait system!",
L"Not enough APs!",
+3 -3
View File
@@ -7419,14 +7419,14 @@ STR16 szCovertTextStr[]=
L"%s was seen performing suspicious activities!",
L"%s does not look like a civilian!",
L"%s bleeding was discovered!",
L"%s is drunk and doesn't look like a soldier!",
L"%s is drunk and doesn't behave like a soldier!",
L"On closer inspection, %s's disguise does not hold!",
L"%s isn't supposed to be here!",
L"%s isn't supposed to be here at this time!",
L"%s was seen near a fresh corpse!",
L"%s equipment raises a few eyebrows!",
L"%s is seen targeting a soldier!",
L"%s has seen through %s disguise!",
L"%s is seen targetting %s!",
L"%s has seen through %s's disguise!",
L"No clothes item found in Items.xml!",
L"This does not work with the old trait system!",
L"Not enough APs!",
+3 -3
View File
@@ -7405,14 +7405,14 @@ STR16 szCovertTextStr[]=
L"%s was seen performing suspicious activities!",
L"%s does not look like a civilian!",
L"%s bleeding was discovered!",
L"%s is drunk and doesn't look like a soldier!",
L"%s is drunk and doesn't behave like a soldier!",
L"On closer inspection, %s's disguise does not hold!",
L"%s isn't supposed to be here!",
L"%s isn't supposed to be here at this time!",
L"%s was seen near a fresh corpse!",
L"%s equipment raises a few eyebrows!",
L"%s is seen targeting a soldier!",
L"%s has seen through %s disguise!",
L"%s is seen targetting %s!",
L"%s has seen through %s's disguise!",
L"No clothes item found in Items.xml!",
L"This does not work with the old trait system!",
L"Not enough APs!",
+3 -3
View File
@@ -7246,14 +7246,14 @@ STR16 szCovertTextStr[]=
L"%s was seen performing suspicious activities!",
L"%s does not look like a civilian!",
L"%s bleeding was discovered!",
L"%s is drunk and doesn't look like a soldier!",
L"%s is drunk and doesn't behave like a soldier!",
L"On closer inspection, %s's disguise does not hold!",
L"%s isn't supposed to be here!",
L"%s isn't supposed to be here at this time!",
L"%s was seen near a fresh corpse!",
L"%s equipment raises a few eyebrows!",
L"%s is seen targeting a soldier!",
L"%s has seen through %s disguise!",
L"%s is seen targetting %s!",
L"%s has seen through %s's disguise!",
L"No clothes item found in Items.xml!",
L"This does not work with the old trait system!",
L"Not enough APs!",
+3 -3
View File
@@ -7418,14 +7418,14 @@ STR16 szCovertTextStr[]=
L"%s was seen performing suspicious activities!",
L"%s does not look like a civilian!",
L"%s bleeding was discovered!",
L"%s is drunk and doesn't look like a soldier!",
L"%s is drunk and doesn't behave like a soldier!",
L"On closer inspection, %s's disguise does not hold!",
L"%s isn't supposed to be here!",
L"%s isn't supposed to be here at this time!",
L"%s was seen near a fresh corpse!",
L"%s equipment raises a few eyebrows!",
L"%s is seen targeting a soldier!",
L"%s has seen through %s disguise!",
L"%s is seen targetting %s!",
L"%s has seen through %s's disguise!",
L"No clothes item found in Items.xml!",
L"This does not work with the old trait system!",
L"Not enough APs!",
+3 -3
View File
@@ -7432,14 +7432,14 @@ STR16 szCovertTextStr[]=
L"%s was seen performing suspicious activities!",
L"%s does not look like a civilian!",
L"%s bleeding was discovered!",
L"%s is drunk and doesn't look like a soldier!",
L"%s is drunk and doesn't behave like a soldier!",
L"On closer inspection, %s's disguise does not hold!",
L"%s isn't supposed to be here!",
L"%s isn't supposed to be here at this time!",
L"%s was seen near a fresh corpse!",
L"%s equipment raises a few eyebrows!",
L"%s is seen targeting a soldier!",
L"%s has seen through %s disguise!",
L"%s is seen targetting %s!",
L"%s has seen through %s's disguise!",
L"No clothes item found in Items.xml!",
L"This does not work with the old trait system!",
L"Not enough APs!",
+3 -3
View File
@@ -7384,14 +7384,14 @@ STR16 szCovertTextStr[]=
L"%s was seen performing suspicious activities!",
L"%s does not look like a civilian!",
L"%s bleeding was discovered!",
L"%s is drunk and doesn't look like a soldier!",
L"%s is drunk and doesn't behave like a soldier!",
L"On closer inspection, %s's disguise does not hold!",
L"%s isn't supposed to be here!",
L"%s isn't supposed to be here at this time!",
L"%s was seen near a fresh corpse!",
L"%s equipment raises a few eyebrows!",
L"%s is seen targeting a soldier!",
L"%s has seen through %s disguise!",
L"%s is seen targetting %s!",
L"%s has seen through %s's disguise!",
L"No clothes item found in Items.xml!",
L"This does not work with the old trait system!",
L"Not enough APs!",
+3 -3
View File
@@ -7435,14 +7435,14 @@ STR16 szCovertTextStr[]=
L"%s was seen performing suspicious activities!",
L"%s does not look like a civilian!",
L"%s bleeding was discovered!",
L"%s is drunk and doesn't look like a soldier!",
L"%s is drunk and doesn't behave like a soldier!",
L"On closer inspection, %s's disguise does not hold!",
L"%s isn't supposed to be here!",
L"%s isn't supposed to be here at this time!",
L"%s was seen near a fresh corpse!",
L"%s equipment raises a few eyebrows!",
L"%s is seen targeting a soldier!",
L"%s has seen through %s disguise!",
L"%s is seen targetting %s!",
L"%s has seen through %s's disguise!",
L"No clothes item found in Items.xml!",
L"This does not work with the old trait system!",
L"Not enough APs!",