mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
New feature: turncoats can be created from enemies and ordered to switch sides
Requires GameDir >= r2535 For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=360191&#msg_360191 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8811 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -2577,6 +2577,10 @@ void LoadSkillTraitsExternalSettings()
|
||||
|
||||
// Flugente: as the 'redisguise after x turns' part is missing the x turns part, this is now permanently set to TRUE until that changes
|
||||
gSkillTraitValues.fCOStripIfUncovered = TRUE;// iniReader.ReadBoolean( "Covert Ops", "COVERT_STRIPIFUNCOVERED", FALSE );
|
||||
|
||||
gSkillTraitValues.fCOTurncoats = iniReader.ReadBoolean( "Covert Ops", "COVERT_TURNCOATS", TRUE );
|
||||
gSkillTraitValues.fCOTurncoats_SectorActivationRequiresRadioOperator = iniReader.ReadBoolean( "Covert Ops", "COVERT_TURNCOATS_SECTOR_ACTIVATION_REQUIRES_RADIOOPERATOR", FALSE );
|
||||
gSkillTraitValues.sCOTurncoats_PlayerConvinctionBonus = iniReader.ReadInteger( "Covert Ops", "COVERT_TURNCOATS_PLAYER_CONVINCTION_BONUS", 0, -100, 100 );
|
||||
|
||||
// Flugente: RADIO OPERATOR
|
||||
gSkillTraitValues.fROAllowArtillery = iniReader.ReadBoolean("Radio Operator","RADIO_OPERATOR_ARTILLERY", TRUE);
|
||||
|
||||
@@ -1927,6 +1927,9 @@ typedef struct
|
||||
UINT16 usCOEliteUncoverRadius;
|
||||
BOOLEAN fCODetectIfBleeding; // will we be discovered if we are bleeding?
|
||||
BOOLEAN fCOStripIfUncovered;
|
||||
BOOLEAN fCOTurncoats; // can we create enemy turncoats that can be ordered to betray their comrades?
|
||||
BOOLEAN fCOTurncoats_SectorActivationRequiresRadioOperator; // activating turncoats sector-wide requires a radio operator
|
||||
INT32 sCOTurncoats_PlayerConvinctionBonus;
|
||||
|
||||
// RADIO OPERATOR
|
||||
BOOLEAN fROAllowArtillery; // artillery can be forbidden for all teams with this setting
|
||||
|
||||
+2
-2
@@ -55,8 +55,8 @@
|
||||
|
||||
#endif
|
||||
|
||||
CHAR8 czVersionNumber[16] = { "Build 20.05.17" }; //YY.MM.DD
|
||||
CHAR8 czVersionNumber[16] = { "Build 20.05.30" }; //YY.MM.DD
|
||||
CHAR16 zTrackingNumber[16] = { L"Z" };
|
||||
CHAR16 zRevisionNumber[16] = { L"Revision 8804" };
|
||||
CHAR16 zRevisionNumber[16] = { L"Revision 8811" };
|
||||
|
||||
// SAVE_GAME_VERSION is defined in header, change it there
|
||||
|
||||
@@ -516,11 +516,13 @@ STR16 OperationText( UINT32 aNum )
|
||||
|
||||
STR16 operationame = GetIncidentName( battlereport.id );
|
||||
|
||||
if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_RECRUITED )
|
||||
if ( battlereport.flagmask & (MILITIA_BATTLEREPORT_FLAG_RECRUITED| MILITIA_BATTLEREPORT_FLAG_RECRUITED_TURNCOAT) )
|
||||
{
|
||||
STR16 originsectorstr = militia.GetOriginSector( );
|
||||
|
||||
if ( militia.origin == MO_PMC )
|
||||
if ( battlereport.flagmask & MILITIA_BATTLEREPORT_FLAG_RECRUITED_TURNCOAT )
|
||||
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[11], day, hours, minutes, originsectorstr );
|
||||
else if ( militia.origin == MO_PMC )
|
||||
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[8], day, hours, minutes, originsectorstr );
|
||||
else if ( militia.origin == MO_DEFECTOR )
|
||||
swprintf( gMilitiaOperationText, szIndividualMilitiaBattleReportText[9], day, hours, minutes, originsectorstr );
|
||||
|
||||
@@ -8223,6 +8223,13 @@ void AssignPersonnelSkillTraitHelpText( UINT8 ubTraitNumber, BOOLEAN fExpertLeve
|
||||
INT16 apreduction = ( gSkillTraitValues.sCODisguiseAPReduction * (fExpertLevel ? 2 : 1));
|
||||
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[6], apreduction, sSpecialCharacters[0]);
|
||||
wcscat( apStr, atStr );
|
||||
|
||||
if ( gSkillTraitValues.fCOTurncoats )
|
||||
{
|
||||
swprintf( atStr, gzIMPMajorTraitsHelpTextsCovertOps[7] );
|
||||
wcscat( apStr, atStr );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -6671,13 +6671,13 @@ void HandleSpyAssignments()
|
||||
if ( Chance( uncoverrisk ) )
|
||||
{
|
||||
// if we are already in hiding, we will be uncovered
|
||||
if ( pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] )
|
||||
if ( pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] > 10 )
|
||||
vector_uncoveredmercs.push_back( uiCnt );
|
||||
|
||||
// we get a penalty, and a chance to be uncovered
|
||||
pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] += 2 + Random( 3 );
|
||||
pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] += 20 + Random( 30 );
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, szIntelText[1], pSoldier->GetName(), (pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] - 1) );
|
||||
ScreenMsg( FONT_MCOLOR_RED, MSG_INTERFACE, szIntelText[1], pSoldier->GetName(), (pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] - 10) / 10 );
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -6688,8 +6688,10 @@ void HandleSpyAssignments()
|
||||
}
|
||||
|
||||
// penalty runs out for every soldier, regardless of whether they are on an intel assignment
|
||||
if ( pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] )
|
||||
pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY]--;
|
||||
if ( pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] > 10)
|
||||
pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] -= 10;
|
||||
else
|
||||
pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -570,7 +570,13 @@ typedef struct SECTORINFO
|
||||
// Flugente: burial assignment
|
||||
FLOAT dBurial_UnappliedProgress; // progress done via assignment work. This way no work gets lost
|
||||
|
||||
INT8 bPadding[ 12 ];
|
||||
// Flugente: number of turncoats
|
||||
UINT8 ubNumAdmins_Turncoat;
|
||||
UINT8 ubNumTroops_Turncoat;
|
||||
UINT8 ubNumElites_Turncoat;
|
||||
UINT8 bPadding_1;
|
||||
|
||||
INT8 bPadding[ 8 ];
|
||||
|
||||
}SECTORINFO;
|
||||
|
||||
|
||||
@@ -6636,6 +6636,15 @@ UINT32 WhatPlayerKnowsAboutEnemiesInSector( INT16 sSectorX, INT16 sSectorY )
|
||||
fCount = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: turncoats allow vision as well
|
||||
if ( gSkillTraitValues.fCOTurncoats
|
||||
&& TurncoatsInSector( sSectorX, sSectorY ) )
|
||||
{
|
||||
fDetection = TRUE;
|
||||
fCount = TRUE;
|
||||
fDirection = TRUE;
|
||||
}
|
||||
|
||||
// Flugente: we can buy info on enemy groups with intel
|
||||
GetInfoFromGroupsInSector( sSectorX, sSectorY, ENEMY_TEAM, fDetection, fCount, fDirection );
|
||||
@@ -8466,6 +8475,27 @@ void DetermineMapIntelData( INT32 asSectorZ )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: turncoats
|
||||
if ( gSkillTraitValues.fCOTurncoats )
|
||||
{
|
||||
for ( UINT16 sector = 0; sector < 256; ++sector )
|
||||
{
|
||||
CorrectTurncoatCount( SECTORX( sector ), SECTORY( sector ) );
|
||||
|
||||
UINT16 numturncoats = NumTurncoatsOfClassInSector( SECTORX( sector ), SECTORY( sector ), SOLDIER_CLASS_ADMINISTRATOR )
|
||||
+ NumTurncoatsOfClassInSector( SECTORX( sector ), SECTORY( sector ), SOLDIER_CLASS_ARMY )
|
||||
+ NumTurncoatsOfClassInSector( SECTORX( sector ), SECTORY( sector ), SOLDIER_CLASS_ELITE );
|
||||
|
||||
if ( numturncoats )
|
||||
{
|
||||
CHAR16 str[128];
|
||||
swprintf( str, szTurncoatText[9], numturncoats );
|
||||
|
||||
AddIntelAndQuestMapDataForSector( SECTORX( sector ), SECTORY( sector ), -1, 23, str, L"" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add lua data
|
||||
|
||||
@@ -580,6 +580,103 @@ UINT32 CreateNewIndividualMilitia( UINT8 aMilitiaRank, UINT8 aOrigin, UINT8 aSec
|
||||
return newmilitia.id;
|
||||
}
|
||||
|
||||
UINT32 CreateNewIndividualMilitiaFromSoldier( SOLDIERTYPE* pSoldier, UINT8 aOrigin )
|
||||
{
|
||||
if ( !gGameExternalOptions.fIndividualMilitia || !pSoldier )
|
||||
return 0;
|
||||
|
||||
MILITIA newmilitia;
|
||||
|
||||
newmilitia.id = GetFreeIndividualMilitiaId();
|
||||
|
||||
switch ( pSoldier->ubSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
case SOLDIER_CLASS_GREEN_MILITIA:
|
||||
case SOLDIER_CLASS_BANDIT:
|
||||
newmilitia.militiarank = GREEN_MILITIA;
|
||||
break;
|
||||
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
case SOLDIER_CLASS_ELITE_MILITIA:
|
||||
newmilitia.militiarank = ELITE_MILITIA;
|
||||
break;
|
||||
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
case SOLDIER_CLASS_REG_MILITIA:
|
||||
newmilitia.militiarank = REGULAR_MILITIA;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// according to origin, we choose bodytype, skin, hair, fore- and surname
|
||||
newmilitia.origin = aOrigin;
|
||||
|
||||
newmilitia.originsector = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY );
|
||||
newmilitia.sector = newmilitia.originsector;
|
||||
|
||||
newmilitia.bodytype = pSoldier->ubBodyType;
|
||||
|
||||
if ( COMPARE_PALETTEREP_ID( pSoldier->SkinPal, "PINKSKIN" ) ) newmilitia.skin = PINKSKIN;
|
||||
else if ( COMPARE_PALETTEREP_ID( pSoldier->SkinPal, "TANSKIN" ) ) newmilitia.skin = TANSKIN;
|
||||
else if ( COMPARE_PALETTEREP_ID( pSoldier->SkinPal, "DARKSKIN" ) ) newmilitia.skin = DARKSKIN;
|
||||
else if ( COMPARE_PALETTEREP_ID( pSoldier->SkinPal, "BLACKSKIN" ) ) newmilitia.skin = BLACKSKIN;
|
||||
|
||||
if ( COMPARE_PALETTEREP_ID( pSoldier->HeadPal, "BROWNHEAD" ) ) newmilitia.hair = BROWNHEAD;
|
||||
if ( COMPARE_PALETTEREP_ID( pSoldier->HeadPal, "BLACKHEAD" ) ) newmilitia.hair = BLACKHEAD;
|
||||
if ( COMPARE_PALETTEREP_ID( pSoldier->HeadPal, "WHITEHEAD" ) ) newmilitia.hair = WHITEHEAD;
|
||||
if ( COMPARE_PALETTEREP_ID( pSoldier->HeadPal, "BLONDHEAD" ) ) newmilitia.hair = BLONDEHEAD;
|
||||
if ( COMPARE_PALETTEREP_ID( pSoldier->HeadPal, "REDHEAD" ) ) newmilitia.hair = REDHEAD;
|
||||
|
||||
// age is random
|
||||
newmilitia.age = 16 + Random( 2 ) * ( 1 + Random( 8 ) )
|
||||
+ Random( 2 ) * ( 1 + Random( 8 ) )
|
||||
+ Random( 2 ) * ( 1 + Random( 8 ) )
|
||||
+ Random( 2 ) * ( 1 + Random( 8 ) )
|
||||
+ Random( 2 ) * ( 1 + Random( 8 ) )
|
||||
+ Random( 2 ) * ( 1 + Random( 8 ) );
|
||||
|
||||
if ( newmilitia.hair == WHITEHEAD )
|
||||
newmilitia.age = max( newmilitia.age, 38 + Random( 2 ) * ( 1 + Random( 8 ) ) );
|
||||
|
||||
// we have to choose a new name, as we cannot take the soldiers name, as those are set in separate arrays
|
||||
if ( newmilitia.bodytype == REGFEMALE )
|
||||
{
|
||||
newmilitia.forename = Random( gMilitiaOriginData[newmilitia.origin].szFemale_Forename.size() );
|
||||
newmilitia.surname = Random( gMilitiaOriginData[newmilitia.origin].szFemale_Surname.size() );
|
||||
}
|
||||
else
|
||||
{
|
||||
newmilitia.forename = Random( gMilitiaOriginData[newmilitia.origin].szMale_Forename.size() );
|
||||
newmilitia.surname = Random( gMilitiaOriginData[newmilitia.origin].szMale_Surname.size() );
|
||||
}
|
||||
|
||||
newmilitia.flagmask = 0;
|
||||
|
||||
newmilitia.healthratio = 100.0f * pSoldier->stats.bLife / pSoldier->stats.bLifeMax;
|
||||
|
||||
newmilitia.kills = 0;
|
||||
newmilitia.assists = 0;
|
||||
newmilitia.promotionpoints = 0.0f;
|
||||
|
||||
// promotion points are based on kills and assists. For proper accounting, award points for current rank
|
||||
newmilitia.AddKills( 0, 0 );
|
||||
|
||||
// make up some history
|
||||
MILITIA_BATTLEREPORT report;
|
||||
report.flagmask |= MILITIA_BATTLEREPORT_FLAG_RECRUITED_TURNCOAT;
|
||||
report.id = GetWorldTotalMin();
|
||||
|
||||
newmilitia.history.push_back( report );
|
||||
|
||||
gIndividualMilitiaVector.push_back( newmilitia );
|
||||
|
||||
return newmilitia.id;
|
||||
}
|
||||
|
||||
// search for a individual militia that is alive and not currently in use in this sector, and return its id
|
||||
// if none is found, create new and return that one
|
||||
UINT32 GetIdOfUnusedIndividualMilitia( UINT8 aSoldierClass, UINT8 aSector )
|
||||
|
||||
@@ -38,6 +38,8 @@ NUM_TOTAL_STATS
|
||||
#define MILITIA_BATTLEREPORT_FLAG_KILLEDENEMY 0x00000040 // killed an enemy
|
||||
#define MILITIA_BATTLEREPORT_FLAG_FIRED 0x00000080 // militia was fired
|
||||
|
||||
#define MILITIA_BATTLEREPORT_FLAG_RECRUITED_TURNCOAT 0x00000100 // defected to our side
|
||||
|
||||
struct MILITIA_BATTLEREPORT
|
||||
{
|
||||
MILITIA_BATTLEREPORT( ) : id( 0 ), flagmask( 0 ) {}
|
||||
@@ -166,6 +168,8 @@ UINT32 CreateRandomIndividualMilitia( UINT8 aMilitiaRank, UINT8 aOrigin, UINT8 a
|
||||
|
||||
UINT32 CreateNewIndividualMilitia( UINT8 aMilitiaRank, UINT8 aOrigin, UINT8 aSector );
|
||||
|
||||
UINT32 CreateNewIndividualMilitiaFromSoldier( SOLDIERTYPE* pSoldier, UINT8 aOrigin );
|
||||
|
||||
UINT32 GetIdOfUnusedIndividualMilitia( UINT8 aSoldierClass, UINT8 aSector );
|
||||
|
||||
BOOLEAN GetIdOfIndividualMilitiaWithClassSector( UINT8 aSoldierClass, UINT8 aSector, UINT32& arId );
|
||||
|
||||
@@ -3039,3 +3039,408 @@ void HandleBloodCatDeaths( SECTORINFO *pSector )
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
UINT16 NumTurncoatsOfClassInSector( INT16 sSectorX, INT16 sSectorY, UINT8 aSoldierClass )
|
||||
{
|
||||
// HEADROCK: This is a TEMPORARY fix to avoid the assertion error. Not sure this is the best solution,
|
||||
// probably isn't. But I need this bit to work.
|
||||
if ( sSectorX < MINIMUM_VALID_X_COORDINATE ||
|
||||
sSectorX > MAXIMUM_VALID_X_COORDINATE ||
|
||||
sSectorY < MINIMUM_VALID_Y_COORDINATE ||
|
||||
sSectorY > MAXIMUM_VALID_Y_COORDINATE )
|
||||
{
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE );
|
||||
AssertLE( sSectorX, MAXIMUM_VALID_X_COORDINATE );
|
||||
AssertGE( sSectorY, MINIMUM_VALID_Y_COORDINATE );
|
||||
AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE );
|
||||
|
||||
SECTORINFO* pSector = &SectorInfo[SECTOR( sSectorX, sSectorY )];
|
||||
|
||||
UINT16 num = 0;
|
||||
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR: num += pSector->ubNumAdmins_Turncoat; break;
|
||||
case SOLDIER_CLASS_ARMY: num += pSector->ubNumTroops_Turncoat; break;
|
||||
case SOLDIER_CLASS_ELITE: num += pSector->ubNumElites_Turncoat; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
GROUP* pGroup = gpGroupList;
|
||||
while ( pGroup )
|
||||
{
|
||||
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY )
|
||||
{
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR: num += pGroup->pEnemyGroup->ubNumAdmins_Turncoat; break;
|
||||
case SOLDIER_CLASS_ARMY: num += pGroup->pEnemyGroup->ubNumTroops_Turncoat; break;
|
||||
case SOLDIER_CLASS_ELITE: num += pGroup->pEnemyGroup->ubNumElites_Turncoat; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
pGroup = pGroup->next;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
BOOLEAN TurncoatsInSector( INT16 sSectorX, INT16 sSectorY )
|
||||
{
|
||||
// HEADROCK: This is a TEMPORARY fix to avoid the assertion error. Not sure this is the best solution,
|
||||
// probably isn't. But I need this bit to work.
|
||||
if ( sSectorX < MINIMUM_VALID_X_COORDINATE ||
|
||||
sSectorX > MAXIMUM_VALID_X_COORDINATE ||
|
||||
sSectorY < MINIMUM_VALID_Y_COORDINATE ||
|
||||
sSectorY > MAXIMUM_VALID_Y_COORDINATE )
|
||||
{
|
||||
return ( 0 );
|
||||
}
|
||||
|
||||
AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE );
|
||||
AssertLE( sSectorX, MAXIMUM_VALID_X_COORDINATE );
|
||||
AssertGE( sSectorY, MINIMUM_VALID_Y_COORDINATE );
|
||||
AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE );
|
||||
|
||||
SECTORINFO* pSector = &SectorInfo[SECTOR( sSectorX, sSectorY )];
|
||||
|
||||
if ( pSector->ubNumAdmins_Turncoat
|
||||
|| pSector->ubNumTroops_Turncoat
|
||||
|| pSector->ubNumElites_Turncoat )
|
||||
return TRUE;
|
||||
|
||||
GROUP* pGroup = gpGroupList;
|
||||
while ( pGroup )
|
||||
{
|
||||
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY )
|
||||
{
|
||||
if ( pGroup->pEnemyGroup->ubNumAdmins_Turncoat
|
||||
|| pGroup->pEnemyGroup->ubNumTroops_Turncoat
|
||||
|| pGroup->pEnemyGroup->ubNumElites_Turncoat )
|
||||
return TRUE;
|
||||
}
|
||||
pGroup = pGroup->next;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool RemoveOneTurncoat( INT16 sSectorX, INT16 sSectorY, UINT8 aSoldierClass )
|
||||
{
|
||||
// HEADROCK: This is a TEMPORARY fix to avoid the assertion error. Not sure this is the best solution,
|
||||
// probably isn't. But I need this bit to work.
|
||||
if ( sSectorX < MINIMUM_VALID_X_COORDINATE ||
|
||||
sSectorX > MAXIMUM_VALID_X_COORDINATE ||
|
||||
sSectorY < MINIMUM_VALID_Y_COORDINATE ||
|
||||
sSectorY > MAXIMUM_VALID_Y_COORDINATE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE );
|
||||
AssertLE( sSectorX, MAXIMUM_VALID_X_COORDINATE );
|
||||
AssertGE( sSectorY, MINIMUM_VALID_Y_COORDINATE );
|
||||
AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE );
|
||||
|
||||
SECTORINFO* pSector = &SectorInfo[SECTOR( sSectorX, sSectorY )];
|
||||
|
||||
// count how many turncoats we have
|
||||
UINT16 num_static = 0;
|
||||
UINT16 num_groups = 0;
|
||||
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
num_static = pSector->ubNumAdmins_Turncoat;
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
num_static = pSector->ubNumTroops_Turncoat;
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
num_static = pSector->ubNumElites_Turncoat;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GROUP* pGroup = gpGroupList;
|
||||
while ( pGroup )
|
||||
{
|
||||
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY )
|
||||
{
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
num_groups += pGroup->pEnemyGroup->ubNumAdmins_Turncoat;
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
num_groups += pGroup->pEnemyGroup->ubNumTroops_Turncoat;
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
num_groups += pGroup->pEnemyGroup->ubNumElites_Turncoat;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pGroup = pGroup->next;
|
||||
}
|
||||
|
||||
if ( num_static + num_groups )
|
||||
{
|
||||
if ( Chance( 100 * num_static / ( num_static + num_groups ) ) )
|
||||
{
|
||||
// add to garrison
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
pSector->ubNumAdmins_Turncoat--;
|
||||
return true;
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
pSector->ubNumTroops_Turncoat--;
|
||||
return true;
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
pSector->ubNumElites_Turncoat--;
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GROUP* pGroup = gpGroupList;
|
||||
while ( pGroup )
|
||||
{
|
||||
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY )
|
||||
{
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
if ( pGroup->pEnemyGroup->ubNumAdmins_Turncoat )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumAdmins_Turncoat--;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
if ( pGroup->pEnemyGroup->ubNumTroops_Turncoat )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumTroops_Turncoat--;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
if ( pGroup->pEnemyGroup->ubNumElites_Turncoat )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumElites_Turncoat--;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pGroup = pGroup->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AddOneTurncoat( INT16 sSectorX, INT16 sSectorY, UINT8 aSoldierClass )
|
||||
{
|
||||
// HEADROCK: This is a TEMPORARY fix to avoid the assertion error. Not sure this is the best solution,
|
||||
// probably isn't. But I need this bit to work.
|
||||
if ( sSectorX < MINIMUM_VALID_X_COORDINATE ||
|
||||
sSectorX > MAXIMUM_VALID_X_COORDINATE ||
|
||||
sSectorY < MINIMUM_VALID_Y_COORDINATE ||
|
||||
sSectorY > MAXIMUM_VALID_Y_COORDINATE )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE );
|
||||
AssertLE( sSectorX, MAXIMUM_VALID_X_COORDINATE );
|
||||
AssertGE( sSectorY, MINIMUM_VALID_Y_COORDINATE );
|
||||
AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE );
|
||||
|
||||
SECTORINFO* pSector = &SectorInfo[SECTOR( sSectorX, sSectorY )];
|
||||
|
||||
// count how many 'slots' we have for more turncoats, then add one at a random position
|
||||
UINT16 freeslots_static = 0;
|
||||
UINT16 freeslots_groups = 0;
|
||||
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
if ( pSector->ubNumAdmins_Turncoat < pSector->ubNumAdmins )
|
||||
freeslots_static = pSector->ubNumAdmins - pSector->ubNumAdmins_Turncoat;
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
if ( pSector->ubNumTroops_Turncoat < pSector->ubNumTroops )
|
||||
freeslots_static = pSector->ubNumTroops - pSector->ubNumTroops_Turncoat;
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
if ( pSector->ubNumElites_Turncoat < pSector->ubNumElites )
|
||||
freeslots_static = pSector->ubNumElites - pSector->ubNumElites_Turncoat;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
GROUP* pGroup = gpGroupList;
|
||||
while ( pGroup )
|
||||
{
|
||||
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY )
|
||||
{
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
if ( pGroup->pEnemyGroup->ubNumAdmins_Turncoat < pGroup->pEnemyGroup->ubNumAdmins )
|
||||
freeslots_groups += pGroup->pEnemyGroup->ubNumAdmins - pGroup->pEnemyGroup->ubNumAdmins_Turncoat;
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
if ( pGroup->pEnemyGroup->ubNumTroops_Turncoat < pGroup->pEnemyGroup->ubNumTroops )
|
||||
freeslots_groups += pGroup->pEnemyGroup->ubNumTroops - pGroup->pEnemyGroup->ubNumTroops_Turncoat;
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
if ( pGroup->pEnemyGroup->ubNumElites_Turncoat < pGroup->pEnemyGroup->ubNumElites )
|
||||
freeslots_groups += pGroup->pEnemyGroup->ubNumElites - pGroup->pEnemyGroup->ubNumElites_Turncoat;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pGroup = pGroup->next;
|
||||
}
|
||||
|
||||
if ( freeslots_static + freeslots_groups )
|
||||
{
|
||||
if ( Chance( 100 * freeslots_static / ( freeslots_static + freeslots_groups ) ) )
|
||||
{
|
||||
// add to garrison
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
pSector->ubNumAdmins_Turncoat++;
|
||||
return true;
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
pSector->ubNumTroops_Turncoat++;
|
||||
return true;
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
pSector->ubNumElites_Turncoat++;
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GROUP* pGroup = gpGroupList;
|
||||
while ( pGroup )
|
||||
{
|
||||
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY )
|
||||
{
|
||||
switch ( aSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
if ( pGroup->pEnemyGroup->ubNumAdmins_Turncoat < pGroup->pEnemyGroup->ubNumAdmins )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumAdmins_Turncoat++;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
if ( pGroup->pEnemyGroup->ubNumTroops_Turncoat < pGroup->pEnemyGroup->ubNumTroops )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumTroops_Turncoat++;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
if ( pGroup->pEnemyGroup->ubNumElites_Turncoat < pGroup->pEnemyGroup->ubNumElites )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumElites_Turncoat++;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
pGroup = pGroup->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CorrectTurncoatCount( INT16 sSectorX, INT16 sSectorY )
|
||||
{
|
||||
// HEADROCK: This is a TEMPORARY fix to avoid the assertion error. Not sure this is the best solution,
|
||||
// probably isn't. But I need this bit to work.
|
||||
if ( sSectorX < MINIMUM_VALID_X_COORDINATE ||
|
||||
sSectorX > MAXIMUM_VALID_X_COORDINATE ||
|
||||
sSectorY < MINIMUM_VALID_Y_COORDINATE ||
|
||||
sSectorY > MAXIMUM_VALID_Y_COORDINATE )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AssertGE( sSectorX, MINIMUM_VALID_X_COORDINATE );
|
||||
AssertLE( sSectorX, MAXIMUM_VALID_X_COORDINATE );
|
||||
AssertGE( sSectorY, MINIMUM_VALID_Y_COORDINATE );
|
||||
AssertLE( sSectorY, MAXIMUM_VALID_Y_COORDINATE );
|
||||
|
||||
SECTORINFO* pSector = &SectorInfo[SECTOR( sSectorX, sSectorY )];
|
||||
|
||||
if ( pSector->ubNumAdmins_Turncoat > pSector->ubNumAdmins )
|
||||
{
|
||||
pSector->ubNumTroops_Turncoat += pSector->ubNumAdmins_Turncoat - pSector->ubNumAdmins;
|
||||
pSector->ubNumAdmins_Turncoat = pSector->ubNumAdmins;
|
||||
}
|
||||
if ( pSector->ubNumTroops_Turncoat > pSector->ubNumTroops )
|
||||
{
|
||||
pSector->ubNumElites_Turncoat += pSector->ubNumTroops_Turncoat - pSector->ubNumTroops;
|
||||
pSector->ubNumTroops_Turncoat = pSector->ubNumTroops;
|
||||
}
|
||||
if ( pSector->ubNumElites_Turncoat > pSector->ubNumElites )
|
||||
{
|
||||
pSector->ubNumElites_Turncoat = pSector->ubNumElites;
|
||||
}
|
||||
|
||||
GROUP* pGroup = gpGroupList;
|
||||
while ( pGroup )
|
||||
{
|
||||
if ( pGroup->usGroupTeam == ENEMY_TEAM && !pGroup->fVehicle && pGroup->ubSectorX == sSectorX && pGroup->ubSectorY == sSectorY )
|
||||
{
|
||||
if ( pGroup->pEnemyGroup->ubNumAdmins_Turncoat > pGroup->pEnemyGroup->ubNumAdmins )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumTroops_Turncoat += pGroup->pEnemyGroup->ubNumAdmins_Turncoat - pGroup->pEnemyGroup->ubNumAdmins;
|
||||
pGroup->pEnemyGroup->ubNumAdmins_Turncoat = pGroup->pEnemyGroup->ubNumAdmins;
|
||||
}
|
||||
if ( pGroup->pEnemyGroup->ubNumTroops_Turncoat > pGroup->pEnemyGroup->ubNumTroops )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumElites_Turncoat += pGroup->pEnemyGroup->ubNumTroops_Turncoat - pGroup->pEnemyGroup->ubNumTroops;
|
||||
pGroup->pEnemyGroup->ubNumTroops_Turncoat = pGroup->pEnemyGroup->ubNumTroops;
|
||||
}
|
||||
if ( pGroup->pEnemyGroup->ubNumElites_Turncoat > pGroup->pEnemyGroup->ubNumElites )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumElites_Turncoat = pGroup->pEnemyGroup->ubNumElites;
|
||||
}
|
||||
}
|
||||
pGroup = pGroup->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,13 @@ extern INT32 gsGridNoForMapEdgePointInfo;
|
||||
// This currently does not exist for MILITIA_TEAM, making such a check relatively useless
|
||||
BOOLEAN CheckPendingNonPlayerTeam(UINT8 usTeam);
|
||||
|
||||
// Flugente: turncoats
|
||||
UINT16 NumTurncoatsOfClassInSector( INT16 sSectorX, INT16 sSectorY, UINT8 aSoldierClass );
|
||||
BOOLEAN TurncoatsInSector( INT16 sSectorX, INT16 sSectorY );
|
||||
bool RemoveOneTurncoat( INT16 sSectorX, INT16 sSectorY, UINT8 aSoldierClass );
|
||||
bool AddOneTurncoat( INT16 sSectorX, INT16 sSectorY, UINT8 aSoldierClass );
|
||||
void CorrectTurncoatCount( INT16 sSectorX, INT16 sSectorY );
|
||||
|
||||
extern UINT32 guiTurnCnt, guiReinforceTurn, guiMilitiaReinforceTurn;//dnl ch68 080913
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5815,6 +5815,13 @@ void InvestigateSector( UINT8 ubSectorID )
|
||||
ubNumToSend--;
|
||||
ubAdmins[i]++;
|
||||
ubTotal++;
|
||||
|
||||
// Flugente: turncoats might move as well
|
||||
if ( pSector->ubNumAdmins_Turncoat > pSector->ubNumAdmins )
|
||||
{
|
||||
SectorInfo[ubSectorID].ubNumAdmins_Turncoat += pSector->ubNumAdmins_Turncoat - pSector->ubNumAdmins;
|
||||
pSector->ubNumAdmins_Turncoat = pSector->ubNumAdmins;
|
||||
}
|
||||
}
|
||||
else if( pSector->ubNumTroops )
|
||||
{
|
||||
@@ -5822,6 +5829,13 @@ void InvestigateSector( UINT8 ubSectorID )
|
||||
ubNumToSend--;
|
||||
ubTroops[i]++;
|
||||
ubTotal++;
|
||||
|
||||
// Flugente: turncoats might move as well
|
||||
if ( pSector->ubNumTroops_Turncoat > pSector->ubNumTroops )
|
||||
{
|
||||
SectorInfo[ubSectorID].ubNumTroops_Turncoat += pSector->ubNumTroops_Turncoat - pSector->ubNumTroops;
|
||||
pSector->ubNumTroops_Turncoat = pSector->ubNumTroops;
|
||||
}
|
||||
}
|
||||
else if( pSector->ubNumElites )
|
||||
{
|
||||
@@ -5829,6 +5843,13 @@ void InvestigateSector( UINT8 ubSectorID )
|
||||
ubNumToSend--;
|
||||
ubElites[i]++;
|
||||
ubTotal++;
|
||||
|
||||
// Flugente: turncoats might move as well
|
||||
if ( pSector->ubNumElites_Turncoat > pSector->ubNumElites )
|
||||
{
|
||||
SectorInfo[ubSectorID].ubNumElites_Turncoat += pSector->ubNumElites_Turncoat - pSector->ubNumElites;
|
||||
pSector->ubNumElites_Turncoat = pSector->ubNumElites;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6571,6 +6592,13 @@ void UpgradeAdminsToTroops()
|
||||
|
||||
--ubAdminsToCheck;
|
||||
}
|
||||
|
||||
// Flugente: make sure turncoat numbers are plausible
|
||||
if ( pSector->ubNumAdmins_Turncoat > pSector->ubNumAdmins )
|
||||
{
|
||||
pSector->ubNumTroops_Turncoat += pSector->ubNumAdmins_Turncoat - pSector->ubNumAdmins;
|
||||
pSector->ubNumAdmins_Turncoat = pSector->ubNumAdmins;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6628,6 +6656,13 @@ void UpgradeAdminsToTroops()
|
||||
|
||||
ubAdminsToCheck--;
|
||||
}
|
||||
|
||||
// Flugente: make sure turncoat numbers are plausible
|
||||
if ( pGroup->pEnemyGroup->ubNumAdmins_Turncoat > pGroup->pEnemyGroup->ubNumAdmins )
|
||||
{
|
||||
pGroup->pEnemyGroup->ubNumTroops_Turncoat += pGroup->pEnemyGroup->ubNumAdmins_Turncoat - pGroup->pEnemyGroup->ubNumAdmins;
|
||||
pGroup->pEnemyGroup->ubNumAdmins_Turncoat = pGroup->pEnemyGroup->ubNumAdmins;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,14 @@ typedef struct ENEMYGROUP
|
||||
UINT8 ubTanksInBattle;
|
||||
UINT8 ubNumJeeps;
|
||||
UINT8 ubJeepsInBattle;
|
||||
INT8 bPadding[16];
|
||||
|
||||
// Flugente: number of turncoats
|
||||
UINT8 ubNumAdmins_Turncoat;
|
||||
UINT8 ubNumTroops_Turncoat;
|
||||
UINT8 ubNumElites_Turncoat;
|
||||
UINT8 bPadding_1;
|
||||
|
||||
INT8 bPadding[12];
|
||||
}ENEMYGROUP;
|
||||
|
||||
//NOTE: ALL FLAGS ARE CLEARED WHENEVER A GROUP ARRIVES IN A SECTOR, OR ITS WAYPOINTS ARE
|
||||
|
||||
@@ -431,12 +431,15 @@ INT8 SoldierClassToMilitiaRank(UINT8 ubSoldierClass)
|
||||
|
||||
switch( ubSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR:
|
||||
case SOLDIER_CLASS_GREEN_MILITIA:
|
||||
bRank = GREEN_MILITIA;
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY:
|
||||
case SOLDIER_CLASS_REG_MILITIA:
|
||||
bRank = REGULAR_MILITIA;
|
||||
break;
|
||||
case SOLDIER_CLASS_ELITE:
|
||||
case SOLDIER_CLASS_ELITE_MILITIA:
|
||||
bRank = ELITE_MILITIA;
|
||||
break;
|
||||
|
||||
+2
-2
@@ -2395,9 +2395,9 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
|
||||
fDoIcon_Assignment = TRUE;
|
||||
fShowCustomText = TRUE;
|
||||
|
||||
if (pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY])
|
||||
if (pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] > 10)
|
||||
{
|
||||
swprintf(sString, L"Hide %dh", pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY]);
|
||||
swprintf(sString, L"Hide %dh", pSoldier->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] / 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+124
-108
@@ -6283,10 +6283,7 @@ BOOLEAN ShowSoldierRoleSymbol(SOLDIERTYPE* pSoldier)
|
||||
// this only works on enemy soldiers
|
||||
if ( pSoldier->bTeam != ENEMY_TEAM && pSoldier->bTeam != CIV_TEAM )
|
||||
return false;
|
||||
|
||||
if ( pSoldier->usSkillCounter[SOLDIER_COUNTER_ROLE_OBSERVED] < gGameExternalOptions.usTurnsToUncover )
|
||||
return false;
|
||||
|
||||
|
||||
INT16 sXPos = 0;
|
||||
INT16 sYPos = 0;
|
||||
INT32 iBack = 0;
|
||||
@@ -6297,113 +6294,29 @@ BOOLEAN ShowSoldierRoleSymbol(SOLDIERTYPE* pSoldier)
|
||||
sXPos += 50;
|
||||
sYPos += 25;
|
||||
|
||||
// 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 ( pSoldier->usSkillCounter[SOLDIER_COUNTER_ROLE_OBSERVED] >= gGameExternalOptions.usTurnsToUncover )
|
||||
{
|
||||
if ( PlayerKnowsAboutVIP( pSoldier->sSectorX, pSoldier->sSectorY ) )
|
||||
// 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 )
|
||||
{
|
||||
// Add bars
|
||||
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20), (INT16)(sYPos + 20) );
|
||||
|
||||
if ( iBack != -1 )
|
||||
if ( PlayerKnowsAboutVIP( pSoldier->sSectorX, pSoldier->sSectorY ) )
|
||||
{
|
||||
SetBackgroundRectFilled( iBack );
|
||||
// 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;
|
||||
}
|
||||
|
||||
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 6, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
}
|
||||
|
||||
// is this guy an officer?
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
|
||||
{
|
||||
// Add bars
|
||||
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)(sXPos + 20 ), (INT16)(sYPos + 20 ) );
|
||||
|
||||
if ( iBack != -1 )
|
||||
{
|
||||
SetBackgroundRectFilled( iBack );
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
// is this guy radio operator with a radio?
|
||||
if ( pSoldier->CanUseRadio(false) )
|
||||
{
|
||||
// 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, 3, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
// is this guy a doctor? we do not check for medical gear, as we would not have that information from a glance
|
||||
if ( HAS_SKILL_TRAIT( pSoldier, DOCTOR_NT) )
|
||||
{
|
||||
// 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, 1, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
// is this guy a sniper? Just check for the gun, trait is not necessary
|
||||
if ( pSoldier->HasSniper() )
|
||||
{
|
||||
// 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, 2, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
// is this guy a mortar guy? Just check for the gun, trait is not necessary
|
||||
if ( pSoldier->HasMortar() )
|
||||
{
|
||||
// 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, 4, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
// do we carry a key?
|
||||
for ( int ubLoop = 0; ubLoop < NUM_KEYS; ++ubLoop )
|
||||
{
|
||||
if ( SoldierHasKey( pSoldier, ubLoop ) )
|
||||
// is this guy an officer?
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
|
||||
{
|
||||
// Add bars
|
||||
iBack = RegisterBackgroundRect( BGND_FLAG_SINGLE, NULL, sXPos, sYPos, (INT16)( sXPos + 20 ), (INT16)( sYPos + 20 ) );
|
||||
@@ -6413,12 +6326,115 @@ BOOLEAN ShowSoldierRoleSymbol(SOLDIERTYPE* pSoldier)
|
||||
SetBackgroundRectFilled( iBack );
|
||||
}
|
||||
|
||||
BltVideoObjectFromIndex( FRAME_BUFFER, guiENEMYROLES, 11, 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;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// is this guy radio operator with a radio?
|
||||
if ( pSoldier->CanUseRadio( false ) )
|
||||
{
|
||||
// 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, 3, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
// is this guy a doctor? we do not check for medical gear, as we would not have that information from a glance
|
||||
if ( HAS_SKILL_TRAIT( pSoldier, DOCTOR_NT ) )
|
||||
{
|
||||
// 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, 1, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
// is this guy a sniper? Just check for the gun, trait is not necessary
|
||||
if ( pSoldier->HasSniper() )
|
||||
{
|
||||
// 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, 2, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
// is this guy a mortar guy? Just check for the gun, trait is not necessary
|
||||
if ( pSoldier->HasMortar() )
|
||||
{
|
||||
// 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, 4, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
// do we carry a key?
|
||||
for ( int ubLoop = 0; ubLoop < NUM_KEYS; ++ubLoop )
|
||||
{
|
||||
if ( SoldierHasKey( pSoldier, ubLoop ) )
|
||||
{
|
||||
// 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, 11, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// turncoats are instantly visible
|
||||
if ( gSkillTraitValues.fCOTurncoats && pSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT )
|
||||
{
|
||||
// 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, 12, sXPos, sYPos, VO_BLT_TRANSSHADOW, NULL );
|
||||
|
||||
sYPos += 20;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
+246
-7
@@ -114,6 +114,8 @@
|
||||
#include "DynamicDialogue.h" // added by Flugente for HandleDynamicOpinions()
|
||||
#include "DropDown.h" // added by Flugente
|
||||
#include "Creature Spreading.h" // added by Flugente forResetCreatureAttackVariables()
|
||||
#include "finances.h" // added by Flugente
|
||||
#include "MilitiaIndividual.h" // added by Flugente
|
||||
#endif
|
||||
#include "connect.h"
|
||||
|
||||
@@ -153,6 +155,10 @@ class OBJECTTYPE;
|
||||
class SOLDIERTYPE;
|
||||
|
||||
extern void HandleBestSightingPositionInRealtime();
|
||||
extern INT32 GetCurrentBalance( void );
|
||||
|
||||
extern CHAR16 gzUserDefinedButton1[128];
|
||||
extern CHAR16 gzUserDefinedButton2[128];
|
||||
|
||||
void UpdateFastForwardMode(SOLDIERTYPE* pSoldier, INT8 bAction); // sevenfm: to call in HandleAtNewGridNo
|
||||
|
||||
@@ -4214,15 +4220,13 @@ void SetSoldierNeutral( SOLDIERTYPE * pSoldier )
|
||||
}
|
||||
void MakeCivHostile(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
INT8 bNewSide;
|
||||
|
||||
if ( pSoldier->ubBodyType == COW )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// default is hostile to player, allied to army
|
||||
bNewSide = 1;
|
||||
INT8 bNewSide = 1;
|
||||
|
||||
switch( pSoldier->ubProfile )
|
||||
{
|
||||
@@ -4267,6 +4271,11 @@ void MakeCivHostile(SOLDIERTYPE *pSoldier)
|
||||
{
|
||||
bNewSide = zCivGroupName[pSoldier->ubCivilianGroup].bSide;
|
||||
}
|
||||
// Flugente: enemies are already hostile, let's assume we want to make them friendly instead
|
||||
else if ( pSoldier->bTeam == ENEMY_TEAM )
|
||||
{
|
||||
bNewSide = 0;
|
||||
}
|
||||
|
||||
if ( !pSoldier->aiData.bNeutral && bNewSide == pSoldier->bSide )
|
||||
{
|
||||
@@ -4302,6 +4311,63 @@ void MakeCivHostile(SOLDIERTYPE *pSoldier)
|
||||
pSoldier->aiData.bOrders = FARPATROL;
|
||||
}
|
||||
|
||||
// Flugente: turncoats
|
||||
if ( pSoldier->bTeam == ENEMY_TEAM )
|
||||
{
|
||||
// change to enemy team
|
||||
SetSoldierNonNeutral( pSoldier );
|
||||
pSoldier->bSide = bNewSide;
|
||||
|
||||
// remember old class and switch to its equivalent
|
||||
UINT8 oldclass = pSoldier->ubSoldierClass;
|
||||
UINT16 sector = SECTOR( pSoldier->sSectorX, pSoldier->sSectorY );
|
||||
|
||||
// extract militia profile from pSoldier, so that a fitting profile is ready to be taken during creation
|
||||
CreateNewIndividualMilitiaFromSoldier( pSoldier, MO_DEFECTOR );
|
||||
|
||||
pSoldier = ChangeSoldierTeam( pSoldier, MILITIA_TEAM );
|
||||
|
||||
// it doesn't make sense to force a militia reset when all changes are in the sector, so set this back to original value afterwards
|
||||
//BOOLEAN tmp = gfStrategicMilitiaChangesMade;
|
||||
|
||||
//gfStrategicMilitiaChangesMade = tmp;
|
||||
|
||||
if ( oldclass == SOLDIER_CLASS_ARMY )
|
||||
{
|
||||
pSoldier->ubSoldierClass = SOLDIER_CLASS_REG_MILITIA;
|
||||
|
||||
SectorInfo[sector].ubNumTroops = max( 0, SectorInfo[sector].ubNumTroops - 1 );
|
||||
SectorInfo[sector].ubTroopsInBattle = max( 0, SectorInfo[sector].ubTroopsInBattle - 1 );
|
||||
}
|
||||
else if ( oldclass == SOLDIER_CLASS_ELITE )
|
||||
{
|
||||
pSoldier->ubSoldierClass = SOLDIER_CLASS_ELITE_MILITIA;
|
||||
|
||||
SectorInfo[sector].ubNumElites = max( 0, SectorInfo[sector].ubNumElites - 1 );
|
||||
SectorInfo[sector].ubElitesInBattle = max( 0, SectorInfo[sector].ubElitesInBattle - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
pSoldier->ubSoldierClass = SOLDIER_CLASS_GREEN_MILITIA;
|
||||
|
||||
SectorInfo[sector].ubNumAdmins = max( 0, SectorInfo[sector].ubNumAdmins - 1 );
|
||||
SectorInfo[sector].ubAdminsInBattle = max( 0, SectorInfo[sector].ubAdminsInBattle - 1 );
|
||||
}
|
||||
|
||||
StrategicAddMilitiaToSector( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->ubSoldierClass - 4, 1 );
|
||||
|
||||
// rehandle sight for everybody
|
||||
SOLDIERTYPE* pTeamSoldier;
|
||||
UINT16 iLoop = gTacticalStatus.Team[OUR_TEAM].bFirstID;
|
||||
for ( pTeamSoldier = MercPtrs[iLoop]; iLoop <= gTacticalStatus.Team[CIV_TEAM].bLastID; ++iLoop, ++pTeamSoldier )
|
||||
{
|
||||
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->stats.bLife > 0 )
|
||||
{
|
||||
RecalculateOppCntsDueToNoLongerNeutral( pTeamSoldier );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pSoldier->bSide = bNewSide;
|
||||
|
||||
if ( pSoldier->aiData.bNeutral )
|
||||
@@ -6903,6 +6969,10 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
if ( pTeamSoldier->usSoldierFlagMask & SOLDIER_VIP )
|
||||
DeleteVIP( pTeamSoldier->sSectorX, pTeamSoldier->sSectorY );
|
||||
|
||||
// Flugente: turncoats
|
||||
if ( pTeamSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT )
|
||||
RemoveOneTurncoat( sMapX, sMapY, pTeamSoldier->ubSoldierClass );
|
||||
|
||||
// Flugente: campaign stats
|
||||
gCurrentIncident.AddStat( pTeamSoldier, CAMPAIGNHISTORY_TYPE_PRISONER );
|
||||
|
||||
@@ -10520,7 +10590,138 @@ void HandleDisplayingOfPlayerLostDialogue( )
|
||||
}
|
||||
#endif
|
||||
|
||||
static UINT8 prisonerdialoguetargetID = 0;
|
||||
static UINT8 prisonerdialoguetargetID = NOBODY;
|
||||
|
||||
void TurnCoatAttemptMessageBoxCallBack( UINT8 ubExitValue )
|
||||
{
|
||||
// check ubExitValue to see whether we actually want to go through (2)
|
||||
if ( ubExitValue != 2
|
||||
|| prisonerdialoguetargetID == NOBODY
|
||||
|| gusSelectedSoldier == NOBODY )
|
||||
return;
|
||||
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[prisonerdialoguetargetID];
|
||||
|
||||
if ( !pSoldier )
|
||||
return;
|
||||
|
||||
INT16 approachselected = DropDownTemplate<DROPDOWNNR_MSGBOX_1>::getInstance().GetSelectedEntryKey();
|
||||
|
||||
UINT8 approachchance = MercPtrs[gusSelectedSoldier]->GetTurncoatConvinctionChance( prisonerdialoguetargetID, approachselected );
|
||||
|
||||
// you can never turn a VIP (though we don't tell the player if someone is a VIP, lest they have an exploit to find out)
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_VIP )
|
||||
approachchance = 0;
|
||||
|
||||
// as using random numbers to pass the check would result in players savescumming, use a number based on the soldier's stats
|
||||
UINT32 soldierconsistentnumber = ( 23 * EffectiveAgility( pSoldier, FALSE ) + 83 * EffectiveExplosive( pSoldier ) + 19 * EffectiveMarksmanship( pSoldier ) + 92 * pSoldier->stats.bLifeMax ) % 100;
|
||||
|
||||
if ( soldierconsistentnumber < approachchance )
|
||||
{
|
||||
pSoldier->usSoldierFlagMask2 |= SOLDIER_TURNCOAT;
|
||||
|
||||
AddOneTurncoat( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->ubSoldierClass );
|
||||
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szTurncoatText[0], pSoldier->GetName() );
|
||||
|
||||
// increase intel penalty. We can only try to convert enemies if the penalty is low, and having a high penalty means we can't mine intel for a few hours but have to hide
|
||||
MercPtrs[gusSelectedSoldier]->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] += 1;
|
||||
|
||||
StatChange( MercPtrs[gusSelectedSoldier], EXPERAMT, 2, FROM_SUCCESS );
|
||||
StatChange( MercPtrs[gusSelectedSoldier], LDRAMT, 4, FROM_SUCCESS );
|
||||
}
|
||||
else
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szTurncoatText[1], pSoldier->GetName() );
|
||||
|
||||
// increase intel penalty. We can only try to convert enemies if the penalty is low, and having a high penalty means we can't mine intel for a few hours but have to hide
|
||||
MercPtrs[gusSelectedSoldier]->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] += 4;
|
||||
|
||||
StatChange( MercPtrs[gusSelectedSoldier], EXPERAMT, 1, FROM_FAILURE );
|
||||
StatChange( MercPtrs[gusSelectedSoldier], LDRAMT, 1, FROM_FAILURE );
|
||||
}
|
||||
|
||||
// explain that suspicion is so high that we have to stop
|
||||
if ( MercPtrs[gusSelectedSoldier]->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] >= 20 )
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szTurncoatText[2] );
|
||||
|
||||
// use up resources spent, regardless of whether or not we were successful
|
||||
if ( approachselected == 3 )
|
||||
{
|
||||
INT32 bribeamount = 10 * min( 10, CurrentPlayerProgressPercentage() );
|
||||
|
||||
// substract money spent
|
||||
AddTransactionToPlayersBook ( TRANSFER_FUNDS_TO_MERC, MercPtrs[gusSelectedSoldier]->ubProfile, GetWorldTotalMin(), -bribeamount );
|
||||
}
|
||||
else if ( approachselected == 4 )
|
||||
{
|
||||
int intelbribeneeded = max( 2, ( CurrentPlayerProgressPercentage() + 5 ) / 10 );
|
||||
|
||||
AddIntel( -intelbribeneeded, TRUE );
|
||||
}
|
||||
|
||||
//ReduceAttackBusyCount();
|
||||
}
|
||||
|
||||
CHAR16 gTurncoatDropdownText[4][256];
|
||||
|
||||
void HandleTurncoatAttempt( SOLDIERTYPE* pSoldier )
|
||||
{
|
||||
// abort if bad pointer, or not an enemy and not a capturable civilian
|
||||
if ( pSoldier
|
||||
&& pSoldier->bTeam == ENEMY_TEAM
|
||||
&& pSoldier->ubProfile == NO_PROFILE
|
||||
&& !( pSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT )
|
||||
&& !gTacticalStatus.Team[ENEMY_TEAM].bAwareOfOpposition
|
||||
&& !pSoldier->RecognizeAsCombatant( gusSelectedSoldier ) )
|
||||
{
|
||||
// remember the target's ID
|
||||
prisonerdialoguetargetID = pSoldier->ubID;
|
||||
|
||||
CHAR16 buf[256];
|
||||
UINT8 ubCurrentProgress = CurrentPlayerProgressPercentage();
|
||||
|
||||
std::vector<std::pair<INT16, STR16> > dropdownvector_1;
|
||||
int cnt = 1;
|
||||
|
||||
UINT8 chance = MercPtrs[gusSelectedSoldier]->GetTurncoatConvinctionChance( prisonerdialoguetargetID, cnt );
|
||||
swprintf( gTurncoatDropdownText[cnt-1], szTurncoatText[3], chance );
|
||||
dropdownvector_1.push_back( std::make_pair( cnt, gTurncoatDropdownText[cnt - 1] ) );
|
||||
|
||||
++cnt;
|
||||
chance = MercPtrs[gusSelectedSoldier]->GetTurncoatConvinctionChance( prisonerdialoguetargetID, cnt );
|
||||
swprintf( gTurncoatDropdownText[cnt - 1], szTurncoatText[4], chance );
|
||||
dropdownvector_1.push_back( std::make_pair( cnt, gTurncoatDropdownText[cnt - 1] ) );
|
||||
|
||||
++cnt;
|
||||
INT32 balance = GetCurrentBalance();
|
||||
INT32 bribeamount = 10 * min( 10, ubCurrentProgress );
|
||||
if ( bribeamount <= balance )
|
||||
{
|
||||
chance = MercPtrs[gusSelectedSoldier]->GetTurncoatConvinctionChance( prisonerdialoguetargetID, cnt );
|
||||
swprintf( gTurncoatDropdownText[cnt - 1], szTurncoatText[5], bribeamount, chance );
|
||||
dropdownvector_1.push_back( std::make_pair( cnt, gTurncoatDropdownText[cnt - 1] ) );
|
||||
}
|
||||
|
||||
++cnt;
|
||||
FLOAT intelreserve = GetIntel();
|
||||
int intelbribeneeded = max( 2, ( ubCurrentProgress + 5 ) / 10 );
|
||||
if ( intelbribeneeded <= intelreserve )
|
||||
{
|
||||
chance = MercPtrs[gusSelectedSoldier]->GetTurncoatConvinctionChance( prisonerdialoguetargetID, cnt );
|
||||
swprintf( gTurncoatDropdownText[cnt - 1], szTurncoatText[6], intelbribeneeded, chance );
|
||||
dropdownvector_1.push_back( std::make_pair( cnt, gTurncoatDropdownText[cnt - 1] ) );
|
||||
}
|
||||
|
||||
DropDownTemplate<DROPDOWNNR_MSGBOX_1>::getInstance().SetEntries( dropdownvector_1 );
|
||||
|
||||
wcscpy( gzUserDefinedButton1, szTurncoatText[8] );
|
||||
wcscpy( gzUserDefinedButton2, pEpcMenuStrings[4] );
|
||||
|
||||
DoMessageBox( MSG_BOX_BASIC_STYLE, szTurncoatText[7], guiCurrentScreen, ( MSG_BOX_FLAG_GENERIC_TWO_BUTTONS | MSG_BOX_FLAG_DROPDOWN_1 ),
|
||||
TurnCoatAttemptMessageBoxCallBack, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
|
||||
{
|
||||
@@ -10679,11 +10880,11 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
|
||||
}
|
||||
}
|
||||
}
|
||||
// we offered to surrender OURSELVES TO the enemy
|
||||
// we offered to surrender OURSELVES TO the enemy, or are attempting to turn a soldier into a turncoat
|
||||
else if ( ubExitValue == 2 )
|
||||
{
|
||||
// we cannot surrender to bandits, talk instead
|
||||
if ( MercPtrs[prisonerdialoguetargetID]->bTeam != CREATURE_TEAM )
|
||||
if ( MercPtrs[prisonerdialoguetargetID]->bTeam == CREATURE_TEAM )
|
||||
{
|
||||
// normal dialog
|
||||
StartCivQuote( MercPtrs[prisonerdialoguetargetID] );
|
||||
@@ -10740,7 +10941,7 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
|
||||
else if ( ubExitValue == 3 )
|
||||
{
|
||||
// Flugente: if we are disguised and talk to a non-profile NPC, we will continue to 'chat' with the enemy as long as we aren't ordered to do something else.
|
||||
// This way we can easily order our spies to 'distract 'enemies'
|
||||
// This way we can easily order our spies to 'distract' enemies
|
||||
if ( GetSoldier( &pSoldier, gusSelectedSoldier ) &&
|
||||
pSoldier->bTeam == gbPlayerNum &&
|
||||
MercPtrs[prisonerdialoguetargetID] &&
|
||||
@@ -11128,6 +11329,27 @@ UINT16 NumSoldiersWithFlagInSector( UINT8 aTeam, UINT32 aFlag )
|
||||
return num;
|
||||
}
|
||||
|
||||
UINT16 NumSoldiersofClassWithFlag2InSector( UINT8 aTeam, UINT8 aSoldierClass, UINT32 aFlag )
|
||||
{
|
||||
SOLDIERTYPE* pSoldier;
|
||||
INT32 cnt = 0;
|
||||
UINT16 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->usSoldierFlagMask2 & aFlag)
|
||||
&& pSoldier->ubSoldierClass == aSoldierClass )
|
||||
{
|
||||
++num;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
INT32 GetClosestSoldierWithFlag( UINT8 aTeam, UINT32 aFlag )
|
||||
{
|
||||
INT32 sBestGridNo = NOWHERE;
|
||||
@@ -11414,3 +11636,20 @@ BOOLEAN IsCivFactionMemberAliveInSector( UINT8 usCivilianGroup )
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN IsFreeSlotAvailable( int aTeam )
|
||||
{
|
||||
SOLDIERTYPE *pSoldier;
|
||||
INT32 cnt = gTacticalStatus.Team[aTeam].bFirstID;
|
||||
|
||||
// run through list
|
||||
for ( pSoldier = MercPtrs[cnt]; cnt <= gTacticalStatus.Team[aTeam].bLastID; ++cnt, ++pSoldier )
|
||||
{
|
||||
if ( !pSoldier->bActive )
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -357,6 +357,9 @@ extern UINT8 NumZombiesInSector();
|
||||
// Flugente: offer the enemy the chance to surrender
|
||||
void HandleSurrenderOffer( SOLDIERTYPE* pSoldier );
|
||||
|
||||
// Flugente: attempt to convince a soldier to become a turncoat
|
||||
void HandleTurncoatAttempt( SOLDIERTYPE* pSoldier );
|
||||
|
||||
// Flugente: disguised mercs can distract enemies by talking to them. In order to display that, we sometimes display excerpts of their 'chats'
|
||||
void CheckChatPartners();
|
||||
|
||||
@@ -401,6 +404,7 @@ UINT8 HighestEnemyOfficersInSector(UINT8& aType);
|
||||
|
||||
// count all soldiers in the current sector that have a specific flag set
|
||||
UINT16 NumSoldiersWithFlagInSector(UINT8 aTeam, UINT32 aFlag);
|
||||
UINT16 NumSoldiersofClassWithFlag2InSector( UINT8 aTeam, UINT8 aSoldierClass, UINT32 aFlag );
|
||||
INT32 GetClosestSoldierWithFlag( UINT8 aTeam, UINT32 aFlag );
|
||||
|
||||
// Flugente: VIP targets
|
||||
@@ -426,5 +430,7 @@ void VIPFleesToMeduna();
|
||||
// Flugente: is any member of a specific civilian faction still alive in the current sector?
|
||||
BOOLEAN IsCivFactionMemberAliveInSector( UINT8 usCivilianGroup );
|
||||
|
||||
BOOLEAN IsFreeSlotAvailable( int aTeam );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -300,6 +300,11 @@ void ReducePointsForFatigue( SOLDIERTYPE *pSoldier, UINT32 *pusPoints )
|
||||
*pusPoints -= (*pusPoints * GetPenaltyForFatigue( pSoldier )) / 100;
|
||||
}
|
||||
|
||||
void ReducePointsForFatigue( SOLDIERTYPE *pSoldier, INT32 *psPoints )
|
||||
{
|
||||
*psPoints -= ( *psPoints * GetPenaltyForFatigue( pSoldier ) ) / 100;
|
||||
}
|
||||
|
||||
INT32 GetSkillCheckPenaltyForFatigue( SOLDIERTYPE *pSoldier, INT32 iSkill )
|
||||
{
|
||||
// use only half the full effect of fatigue for skill checks
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Soldier Control.h"
|
||||
|
||||
void ReducePointsForFatigue( SOLDIERTYPE *pSoldier, UINT32 *pusPoints );
|
||||
void ReducePointsForFatigue( SOLDIERTYPE *pSoldier, INT32 *psPoints );
|
||||
INT32 GetSkillCheckPenaltyForFatigue( SOLDIERTYPE *pSoldier, INT32 iSkill );
|
||||
INT32 SkillCheck( SOLDIERTYPE *pSoldier, INT8 bReason, INT8 bDifficulty );
|
||||
INT16 CalcTrapDetectLevel( SOLDIERTYPE *pSoldier, BOOLEAN fExamining );
|
||||
|
||||
@@ -249,7 +249,7 @@ SkillSelection::Setup( UINT32 aVal )
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_SkillSelection, uiCounter ) );
|
||||
|
||||
// if we cannot perform this skill, grey it out
|
||||
if ( !( pSoldier->CanUseSkill( uiCounter, TRUE ) ) )
|
||||
if ( !( pSoldier->CanUseSkill( uiCounter, TRUE, sTraitsMenuTargetGridNo ) ) )
|
||||
{
|
||||
// Set this option off.
|
||||
pOption->setAvail( new popupCallbackFunction<bool, void*>( &Popup_OptionOff, NULL ) );
|
||||
@@ -309,7 +309,7 @@ SkillSelection::Setup( UINT32 aVal )
|
||||
{
|
||||
for(UINT32 uiCounter = SKILLS_RADIO_FIRST; uiCounter <= SKILLS_RADIO_LAST; ++uiCounter)
|
||||
{
|
||||
SetRegionFastHelpText( &(GetPopup()->MenuRegion[cnt++]), pSoldier->PrintSkillDesc(uiCounter) );
|
||||
SetRegionFastHelpText( &(GetPopup()->MenuRegion[cnt++]), pSoldier->PrintSkillDesc( uiCounter, sTraitsMenuTargetGridNo ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -318,7 +318,7 @@ SkillSelection::Setup( UINT32 aVal )
|
||||
{
|
||||
for ( UINT32 uiCounter = SKILLS_INTEL_FIRST; uiCounter <= SKILLS_INTEL_LAST; ++uiCounter )
|
||||
{
|
||||
SetRegionFastHelpText( &( GetPopup()->MenuRegion[cnt++] ), pSoldier->PrintSkillDesc( uiCounter ) );
|
||||
SetRegionFastHelpText( &( GetPopup()->MenuRegion[cnt++] ), pSoldier->PrintSkillDesc( uiCounter, sTraitsMenuTargetGridNo ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -327,7 +327,7 @@ SkillSelection::Setup( UINT32 aVal )
|
||||
{
|
||||
for(UINT32 uiCounter = SKILLS_VARIOUS_FIRST; uiCounter <= SKILLS_VARIOUS_LAST; ++uiCounter)
|
||||
{
|
||||
SetRegionFastHelpText( &(GetPopup()->MenuRegion[cnt++]), pSoldier->PrintSkillDesc(uiCounter) );
|
||||
SetRegionFastHelpText( &(GetPopup()->MenuRegion[cnt++]), pSoldier->PrintSkillDesc(uiCounter, sTraitsMenuTargetGridNo ) );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -114,6 +114,8 @@ extern UINT8 gubInterruptProvoker;
|
||||
|
||||
extern UINT16 PickSoldierReadyAnimation( SOLDIERTYPE *pSoldier, BOOLEAN fEndReady, BOOLEAN fHipStance );
|
||||
|
||||
extern bool RemoveOneTurncoat( INT16 sSectorX, INT16 sSectorY, UINT8 aSoldierClass );
|
||||
|
||||
// Animation code explanations!
|
||||
//
|
||||
// 0-399: Actual animation frame indices
|
||||
@@ -4131,6 +4133,10 @@ BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse )
|
||||
{
|
||||
DeleteVIP( pSoldier->sSectorX, pSoldier->sSectorY );
|
||||
}
|
||||
|
||||
// Flugente: turncoats
|
||||
if ( pSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT )
|
||||
RemoveOneTurncoat( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->ubSoldierClass );
|
||||
|
||||
// Flugente: additional dialogue
|
||||
if ( pSoldier->ubProfile != NO_PROFILE )
|
||||
|
||||
@@ -10168,6 +10168,14 @@ UINT8 SOLDIERTYPE::SoldierTakeDamage( INT8 bHeight, INT16 sLifeDeduct, INT16 sBr
|
||||
if ( this->ubBodyType != CROW && this->ubBodyType != COW )
|
||||
HandleDynamicOpinionChange( MercPtrs[ubAttacker], OPINIONEVENT_CIV_ATTACKER, TRUE, TRUE );
|
||||
}
|
||||
|
||||
// if we are a turncoat, lose the flag if we were attacked by player forces
|
||||
if ( (this->usSoldierFlagMask2 & SOLDIER_TURNCOAT) && MercPtrs[ubAttacker]->bSide == 0 )
|
||||
{
|
||||
this->usSoldierFlagMask2 &= ~SOLDIER_TURNCOAT;
|
||||
|
||||
RemoveOneTurncoat( this->sSectorX, this->sSectorY, this->ubSoldierClass );
|
||||
}
|
||||
}
|
||||
|
||||
// CJC Jan 21 99: add check to see if we are hurting an enemy in an enemy-controlled
|
||||
@@ -16200,7 +16208,7 @@ void SOLDIERTYPE::LooseDisguise( void )
|
||||
// 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 )
|
||||
for ( pSoldier = MercPtrs[iLoop]; iLoop <= gTacticalStatus.Team[CIV_TEAM].bLastID; ++iLoop, ++pSoldier )
|
||||
{
|
||||
if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->stats.bLife > 0 )
|
||||
{
|
||||
@@ -17794,6 +17802,16 @@ BOOLEAN SOLDIERTYPE::CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck, INT32 sGridNo )
|
||||
canuse = TRUE;
|
||||
break;
|
||||
|
||||
case SKILLS_RADIO_ACTIVATE_TURNCOATS_ALL:
|
||||
if ( ( !fAPCheck || EnoughPoints( this, APBPConstants[AP_RADIO], APBPConstants[BP_RADIO], FALSE ) )
|
||||
&& CanUseRadio()
|
||||
&& gSkillTraitValues.fCOTurncoats
|
||||
&& !gbWorldSectorZ
|
||||
&& gTacticalStatus.ubInterruptPending == DISABLED_INTERRUPT
|
||||
&& IsFreeSlotAvailable( MILITIA_TEAM ) )
|
||||
canuse = TRUE;
|
||||
break;
|
||||
|
||||
case SKILLS_INTEL_CONCEAL:
|
||||
case SKILLS_INTEL_GATHERINTEL:
|
||||
// in order to conceal, we need:
|
||||
@@ -17855,6 +17873,52 @@ BOOLEAN SOLDIERTYPE::CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck, INT32 sGridNo )
|
||||
}
|
||||
break;
|
||||
|
||||
case SKILLS_CREATE_TURNCOAT:
|
||||
// in order to try to create a turncoat, we need:
|
||||
// - a non-profile, not-already-turncoat enemy soldier
|
||||
// - enemy team not aware of us
|
||||
// - valid disguise
|
||||
{
|
||||
SOLDIERTYPE* pSoldier = SimpleFindSoldier( sGridNo, gsInterfaceLevel );
|
||||
if ( pSoldier
|
||||
&& InPositionForTurncoatAttempt( pSoldier->ubID ) )
|
||||
{
|
||||
canuse = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SKILLS_ACTIVATE_TURNCOATS:
|
||||
// not during an interrupt
|
||||
if ( gSkillTraitValues.fCOTurncoats
|
||||
&& !gbWorldSectorZ
|
||||
&& gTacticalStatus.ubInterruptPending == DISABLED_INTERRUPT
|
||||
&& IsFreeSlotAvailable( MILITIA_TEAM ) )
|
||||
{
|
||||
SOLDIERTYPE* pSoldier = SimpleFindSoldier( sGridNo, gsInterfaceLevel );
|
||||
if ( pSoldier
|
||||
&& pSoldier->bTeam == ENEMY_TEAM
|
||||
&& pSoldier->ubProfile == NO_PROFILE
|
||||
&& ( pSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT )
|
||||
&& SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) )
|
||||
{
|
||||
canuse = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SKILLS_ACTIVATE_TURNCOATS_ALL:
|
||||
// not during an interrupt
|
||||
if ( gSkillTraitValues.fCOTurncoats
|
||||
&& !gbWorldSectorZ
|
||||
&& gTacticalStatus.ubInterruptPending == DISABLED_INTERRUPT
|
||||
&& !gSkillTraitValues.fCOTurncoats_SectorActivationRequiresRadioOperator
|
||||
&& IsFreeSlotAvailable( MILITIA_TEAM ) )
|
||||
{
|
||||
canuse = TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case SKILLS_SPOTTER:
|
||||
if ( (!fAPCheck || EnoughPoints( this, APBPConstants[AP_SPOTTER], 0, FALSE )) && CanSpot( ) )
|
||||
canuse = TRUE;
|
||||
@@ -17928,6 +17992,10 @@ BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID )
|
||||
return SwitchOffRadio( );
|
||||
break;
|
||||
|
||||
case SKILLS_RADIO_ACTIVATE_TURNCOATS_ALL:
|
||||
return RadioOrderAllTurnCoatToSwitchSides();
|
||||
break;
|
||||
|
||||
case SKILLS_INTEL_CONCEAL:
|
||||
case SKILLS_INTEL_GATHERINTEL:
|
||||
{
|
||||
@@ -17955,6 +18023,18 @@ BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID )
|
||||
}
|
||||
break;
|
||||
|
||||
case SKILLS_CREATE_TURNCOAT:
|
||||
AttemptToCreateTurncoat ( ID );
|
||||
break;
|
||||
|
||||
case SKILLS_ACTIVATE_TURNCOATS:
|
||||
OrderTurnCoatToSwitchSides( ID );
|
||||
break;
|
||||
|
||||
case SKILLS_ACTIVATE_TURNCOATS_ALL:
|
||||
OrderAllTurnCoatToSwitchSides();
|
||||
break;
|
||||
|
||||
case SKILLS_SPOTTER:
|
||||
return BecomeSpotter( usMapPos );
|
||||
break;
|
||||
@@ -18001,9 +18081,9 @@ BOOLEAN SOLDIERTYPE::IsAIAllowedtoUseSkill( INT8 iSkill )
|
||||
static CHAR16 skilldescarray[500];
|
||||
|
||||
// print a small description of the skill if we can use it, or its requirements if we cannot
|
||||
STR16 SOLDIERTYPE::PrintSkillDesc( INT8 iSkill )
|
||||
STR16 SOLDIERTYPE::PrintSkillDesc( INT8 iSkill, INT32 sGridNo )
|
||||
{
|
||||
if ( CanUseSkill( iSkill, TRUE ) )
|
||||
if ( CanUseSkill( iSkill, TRUE, sGridNo ) )
|
||||
{
|
||||
return pTraitSkillsMenuDescStrings[iSkill];
|
||||
}
|
||||
@@ -18036,6 +18116,25 @@ STR16 SOLDIERTYPE::PrintSkillDesc( INT8 iSkill )
|
||||
|
||||
break;
|
||||
|
||||
case SKILLS_RADIO_ACTIVATE_TURNCOATS_ALL:
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_X_TXT], gzMercSkillTextNew[RADIO_OPERATOR_NT] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_X_TXT], New113Message[MSG113_WORKING_RADIO_SET] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_NOT_DURING_INTERRUPT] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_TURNED_ENEMY] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_SURFACELEVEL] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
break;
|
||||
|
||||
case SKILLS_INTEL_CONCEAL:
|
||||
case SKILLS_INTEL_GATHERINTEL:
|
||||
|
||||
@@ -18056,6 +18155,39 @@ STR16 SOLDIERTYPE::PrintSkillDesc( INT8 iSkill )
|
||||
|
||||
break;
|
||||
|
||||
case SKILLS_CREATE_TURNCOAT:
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_ENEMY] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_NOALARM] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_DISGUISE_CIV_OR_MIL] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_SURFACELEVEL] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_STRATEGIC_SUSPICION] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
break;
|
||||
|
||||
case SKILLS_ACTIVATE_TURNCOATS:
|
||||
case SKILLS_ACTIVATE_TURNCOATS_ALL:
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_NOT_DURING_INTERRUPT] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_TURNED_ENEMY] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_SURFACELEVEL] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
break;
|
||||
|
||||
case SKILLS_SPOTTER:
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_X_AP], APBPConstants[AP_SPOTTER] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
@@ -18836,6 +18968,21 @@ BOOLEAN SOLDIERTYPE::SwitchOffRadio( )
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::RadioOrderAllTurnCoatToSwitchSides()
|
||||
{
|
||||
// not possible if already scanning
|
||||
if ( !gSkillTraitValues.fCOTurncoats )
|
||||
return FALSE;
|
||||
|
||||
// use the radio, this handles animation, batteries etc.
|
||||
if ( !UseRadio() )
|
||||
return FALSE;
|
||||
|
||||
OrderAllTurnCoatToSwitchSides();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// display and error sound used either when the radio set fails or the sector is jammed - the player knows of the error, but cannot be sure of the cause
|
||||
void
|
||||
SOLDIERTYPE::RadioFail( )
|
||||
@@ -20233,7 +20380,7 @@ UINT8 SOLDIERTYPE::GetUncoverRisk()
|
||||
// if we do this disguised as a soldier, risk will be much higer, as we are under much more scrutiny. This makes up for the increased gain in soldier disguise
|
||||
// less risk if we are asleep, just hiding or forced to hide
|
||||
UINT8 typemultiplier = ( this->usSoldierFlagMask & SOLDIER_COVERT_SOLDIER ) ? 5 : 2;
|
||||
if ( ( this->bAssignment == CONCEALED ) || this->flags.fMercAsleep || this->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] )
|
||||
if ( ( this->bAssignment == CONCEALED ) || this->flags.fMercAsleep || this->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] > 10 )
|
||||
typemultiplier = 1;
|
||||
|
||||
// we now take the sector coolness as a measurement of how important the sector is, and thus how intel we gain
|
||||
@@ -20259,7 +20406,7 @@ FLOAT SOLDIERTYPE::GetIntelGain()
|
||||
return 0.0f;
|
||||
|
||||
// if we're asleep, or on a penalty, we accomplish nothing
|
||||
if ( this->flags.fMercAsleep || this->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] )
|
||||
if ( this->flags.fMercAsleep || this->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] > 10 )
|
||||
return 0.0f;
|
||||
|
||||
// the covert trait isn't that important in determining the intel gain. It is much more important in mitigating the risk of exposure, however
|
||||
@@ -20624,6 +20771,243 @@ UINT8 SOLDIERTYPE::GetThiefEvadeDetectionChance()
|
||||
return totalvalue;
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::InPositionForTurncoatAttempt( UINT16 usID )
|
||||
{
|
||||
if ( !gSkillTraitValues.fCOTurncoats
|
||||
|| gbWorldSectorZ
|
||||
|| gTacticalStatus.Team[ENEMY_TEAM].bAwareOfOpposition )
|
||||
return FALSE;
|
||||
|
||||
if ( this->stats.bLife < OKLIFE
|
||||
|| this->flags.fMercAsleep
|
||||
|| this->bCollapsed
|
||||
|| ( this->usSoldierFlagMask & SOLDIER_POW )
|
||||
|| this->usSkillCooldown[SOLDIER_COOLDOWN_INTEL_PENALTY] > 20
|
||||
|| usID == NOBODY )
|
||||
return FALSE;
|
||||
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[usID];
|
||||
|
||||
if ( !pSoldier
|
||||
|| pSoldier->bTeam != ENEMY_TEAM
|
||||
|| pSoldier->ubProfile != NO_PROFILE
|
||||
|| pSoldier->stats.bLife != pSoldier->stats.bLifeMax
|
||||
|| pSoldier->bCollapsed
|
||||
|| ( pSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT )
|
||||
|| !SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass )
|
||||
|| !SeemsLegit( pSoldier->ubID ) )
|
||||
return FALSE;
|
||||
|
||||
// additional checks if we want to know wether we can target a specific location
|
||||
if ( PythSpacesAway( this->sGridNo, pSoldier->sGridNo ) < 10 )
|
||||
{
|
||||
INT32 val = SoldierToVirtualSoldierLineOfSightTest( this, pSoldier->sGridNo, this->pathing.bLevel, gAnimControl[this->usAnimState].ubEndHeight, FALSE, 10 );
|
||||
|
||||
// error if we cannot see the target
|
||||
if ( !val )
|
||||
return FALSE;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
UINT8 SOLDIERTYPE::GetTurncoatConvinctionChance( UINT16 usID, UINT8 usApproach )
|
||||
{
|
||||
if ( usID >= NOBODY )
|
||||
return 0;
|
||||
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[usID];
|
||||
|
||||
if ( !pSoldier
|
||||
|| pSoldier->bTeam != ENEMY_TEAM )
|
||||
return 0;
|
||||
|
||||
if ( this->stats.bLife < OKLIFE )
|
||||
return 0;
|
||||
|
||||
// determine effectiveness of merc
|
||||
// nominally in [0; 1000]
|
||||
INT32 basestatrating = 6 * EffectiveLeadership( this ) + 40 * EffectiveExpLevel( this, FALSE );
|
||||
|
||||
FLOAT recruitmodifier = ( 100 + this->GetBackgroundValue( BG_PERC_APPROACH_RECRUIT ) ) / 100.0f;
|
||||
|
||||
// personality/disability modifiers
|
||||
FLOAT persmodifier = 1.0f;
|
||||
if ( DoesMercHaveDisability( this, NERVOUS ) ) persmodifier -= 0.10f;
|
||||
|
||||
if ( gGameOptions.fNewTraitSystem )
|
||||
{
|
||||
if ( DoesMercHavePersonality( this, CHAR_TRAIT_SOCIABLE ) ) persmodifier += 0.08f;
|
||||
if ( DoesMercHavePersonality( this, CHAR_TRAIT_LONER ) ) persmodifier -= 0.04f;
|
||||
if ( DoesMercHavePersonality( this, CHAR_TRAIT_ASSERTIVE ) ) persmodifier += 0.05f;
|
||||
if ( DoesMercHavePersonality( this, CHAR_TRAIT_AGGRESSIVE ) ) persmodifier -= 0.05f;
|
||||
if ( DoesMercHavePersonality( this, CHAR_TRAIT_PHLEGMATIC ) ) persmodifier -= 0.02f;
|
||||
if ( DoesMercHavePersonality( this, CHAR_TRAIT_DAUNTLESS ) ) persmodifier += 0.03f;
|
||||
if ( DoesMercHavePersonality( this, CHAR_TRAIT_SHOWOFF ) ) persmodifier += 0.04f;
|
||||
if ( DoesMercHavePersonality( this, CHAR_TRAIT_COWARD ) ) persmodifier -= 0.07f;
|
||||
}
|
||||
|
||||
// nominally in [0; 100]
|
||||
INT32 recruitrating = basestatrating * recruitmodifier * persmodifier * gMercProfiles[this->ubProfile].usApproachFactor[3] / 1000;
|
||||
|
||||
// optional ini bonus
|
||||
recruitrating += gSkillTraitValues.sCOTurncoats_PlayerConvinctionBonus;
|
||||
|
||||
ReducePointsForFatigue( this, &recruitrating );
|
||||
|
||||
// determine resistance of soldier to our subversion
|
||||
INT32 ubLocationModifier = 2 * max( 1, min( 20, gCoolnessBySector[SECTOR( this->sSectorX, this->sSectorY )] ) );
|
||||
|
||||
// enemy resistance is dependent on their level, class and the sector rating
|
||||
INT32 enemyresistancerating = ubLocationModifier + 8 * EffectiveExpLevel( pSoldier, FALSE );
|
||||
|
||||
switch ( pSoldier->ubSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR: enemyresistancerating -= 30; break;
|
||||
case SOLDIER_CLASS_ELITE: enemyresistancerating += 30; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if ( pSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
|
||||
enemyresistancerating += 30;
|
||||
|
||||
ReducePointsForFatigue( pSoldier, &enemyresistancerating );
|
||||
|
||||
switch ( usApproach )
|
||||
{
|
||||
// base approach
|
||||
case 1:
|
||||
break;
|
||||
|
||||
// we use our looks for seduction
|
||||
// thus looking attractive lowers enemy resistance, while being ugly can increase it
|
||||
// however this fails if the soldier is not attracted to us
|
||||
case 2:
|
||||
{
|
||||
// determine whether the soldier is attracted to us in the first place (don't display this, otherwise people will want to set sexual orientation and whatnot)
|
||||
INT32 stat_dependant_roll = ( 37 * EffectiveStrength( pSoldier, FALSE ) + 92 * EffectiveMedical( pSoldier ) + 51 * EffectiveDexterity( pSoldier, FALSE ) + 61 * pSoldier->stats.bLife ) % 100;
|
||||
bool samesexattraction = ( stat_dependant_roll < 8 );
|
||||
|
||||
bool female_player = ( this->ubBodyType == REGFEMALE );
|
||||
bool female_soldier = ( pSoldier->ubBodyType == REGFEMALE );
|
||||
|
||||
bool fittingattraction = false;
|
||||
if ( female_player != female_soldier && !samesexattraction )
|
||||
fittingattraction = true;
|
||||
else if ( female_player == female_soldier && samesexattraction )
|
||||
fittingattraction = true;
|
||||
|
||||
if ( gMercProfiles[this->ubProfile].bAppearance == APPEARANCE_UGLY ) enemyresistancerating += 50 - ( fittingattraction ? 5 : 0 );
|
||||
else if ( gMercProfiles[this->ubProfile].bAppearance == APPEARANCE_HOMELY ) enemyresistancerating += 40 - ( fittingattraction ? 15 : 0 );
|
||||
else if ( gMercProfiles[this->ubProfile].bAppearance == APPEARANCE_AVERAGE ) enemyresistancerating += 30 - ( fittingattraction ? 30 : 0 );
|
||||
else if ( gMercProfiles[this->ubProfile].bAppearance == APPEARANCE_ATTRACTIVE ) enemyresistancerating += 20 - ( fittingattraction ? 45 : 0 );
|
||||
else if ( gMercProfiles[this->ubProfile].bAppearance == APPEARANCE_BABE ) enemyresistancerating += 10 - ( fittingattraction ? 60 : 0 );
|
||||
|
||||
// seduction works better in civilian clothing
|
||||
if ( this->usSoldierFlagMask & SOLDIER_COVERT_CIV )
|
||||
enemyresistancerating -= 5;
|
||||
}
|
||||
break;
|
||||
|
||||
// we try to bribe the soldier with money
|
||||
case 3:
|
||||
{
|
||||
// the amount of money depends on progress and unimportant in this case
|
||||
// the worse the location, the poorer the soldier, thus the more effective money is
|
||||
enemyresistancerating -= 30 + (40 - ubLocationModifier);
|
||||
}
|
||||
break;
|
||||
|
||||
// we try to bribe the soldier with intel
|
||||
case 4:
|
||||
{
|
||||
// the amount of intel depends on progress and unimportant in this case
|
||||
enemyresistancerating -= 80;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if ( enemyresistancerating > recruitrating )
|
||||
return 0;
|
||||
|
||||
return max( 0, min( 100, recruitrating - enemyresistancerating ) );
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::AttemptToCreateTurncoat( UINT16 usID )
|
||||
{
|
||||
if ( usID >= NOBODY )
|
||||
return;
|
||||
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[usID];
|
||||
|
||||
if ( !pSoldier
|
||||
|| pSoldier->bTeam != ENEMY_TEAM
|
||||
|| ( pSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT ) )
|
||||
return;
|
||||
|
||||
HandleTurncoatAttempt( pSoldier );
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::OrderTurnCoatToSwitchSides( UINT16 usID )
|
||||
{
|
||||
if ( usID >= NOBODY )
|
||||
return FALSE;
|
||||
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[usID];
|
||||
|
||||
if (!pSoldier
|
||||
|| pSoldier->bTeam != ENEMY_TEAM
|
||||
|| !( pSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT ) )
|
||||
return FALSE;
|
||||
|
||||
if ( IsFreeSlotAvailable( MILITIA_TEAM ) )
|
||||
{
|
||||
// remove turncoat property
|
||||
pSoldier->usSoldierFlagMask2 &= ~SOLDIER_TURNCOAT;
|
||||
RemoveOneTurncoat( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->ubSoldierClass );
|
||||
|
||||
MakeCivHostile( pSoldier );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::OrderAllTurnCoatToSwitchSides()
|
||||
{
|
||||
SOLDIERTYPE *pSoldier;
|
||||
INT32 cnt = gTacticalStatus.Team[ENEMY_TEAM].bFirstID;
|
||||
|
||||
// run through list
|
||||
for ( pSoldier = MercPtrs[cnt]; cnt <= gTacticalStatus.Team[ENEMY_TEAM].bLastID; ++cnt, ++pSoldier )
|
||||
{
|
||||
if ( pSoldier->bActive && pSoldier->bInSector )
|
||||
{
|
||||
if ( pSoldier->usSoldierFlagMask2 & SOLDIER_TURNCOAT )
|
||||
{
|
||||
if ( IsFreeSlotAvailable( MILITIA_TEAM ) )
|
||||
{
|
||||
// remove turncoat property
|
||||
pSoldier->usSoldierFlagMask2 &= ~SOLDIER_TURNCOAT;
|
||||
RemoveOneTurncoat( pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->ubSoldierClass );
|
||||
|
||||
MakeCivHostile( pSoldier );
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
INT8 bBandaged; //,savedOurTurn;
|
||||
|
||||
@@ -426,6 +426,7 @@ enum
|
||||
|
||||
#define SOLDIER_DRAG_SOUND 0x00080000 // played sound when started dragging
|
||||
#define SOLDIER_SPENT_AP 0x00100000 // soldier has spent some AP this turn (including realtime)
|
||||
#define SOLDIER_TURNCOAT 0x00200000 // this enemy soldier will switch to the militia team if ordered to
|
||||
|
||||
#define SOLDIER_INTERROGATE_ALL 0x000001F8 // all interrogation flags
|
||||
// ----------------------------------------------------------------
|
||||
@@ -597,13 +598,17 @@ enum{
|
||||
SKILLS_RADIO_LISTEN,
|
||||
SKILLS_RADIO_CALLREINFORCEMENTS,
|
||||
SKILLS_RADIO_TURNOFF,
|
||||
SKILLS_RADIO_LAST = SKILLS_RADIO_TURNOFF,
|
||||
SKILLS_RADIO_ACTIVATE_TURNCOATS_ALL, // order all enemy turncoats to turn into militia right now (in case this requires a radio)
|
||||
SKILLS_RADIO_LAST = SKILLS_RADIO_ACTIVATE_TURNCOATS_ALL,
|
||||
|
||||
// spy
|
||||
SKILLS_INTEL_FIRST,
|
||||
SKILLS_INTEL_CONCEAL = SKILLS_INTEL_FIRST, // assignment: spy hides among the population
|
||||
SKILLS_INTEL_GATHERINTEL, // assignment: spy gathers information while disguised
|
||||
SKILLS_INTEL_LAST = SKILLS_INTEL_GATHERINTEL,
|
||||
SKILLS_CREATE_TURNCOAT,
|
||||
SKILLS_ACTIVATE_TURNCOATS, // order enemy turncoat to turn into militia right now
|
||||
SKILLS_ACTIVATE_TURNCOATS_ALL, // order all enemy turncoats to turn into militia right now
|
||||
SKILLS_INTEL_LAST = SKILLS_ACTIVATE_TURNCOATS_ALL,
|
||||
|
||||
// various
|
||||
SKILLS_VARIOUS_FIRST,
|
||||
@@ -1915,7 +1920,7 @@ public:
|
||||
BOOLEAN IsAIAllowedtoUseSkill( INT8 iSkill );
|
||||
|
||||
// print a small description of the skill if we can use it, or its requirements if we cannot
|
||||
STR16 PrintSkillDesc( INT8 iSkill);
|
||||
STR16 PrintSkillDesc( INT8 iSkill, INT32 sGridNo = -1 );
|
||||
|
||||
// Flugente: functions for the radio operator trait
|
||||
BOOLEAN CanUseRadio(BOOLEAN fCheckForAP = TRUE); // can we use radio, if we even have one?
|
||||
@@ -1932,6 +1937,7 @@ public:
|
||||
BOOLEAN RadioListen();
|
||||
BOOLEAN RadioCallReinforcements( UINT32 usSector, UINT16 sNumber );
|
||||
BOOLEAN SwitchOffRadio();
|
||||
BOOLEAN RadioOrderAllTurnCoatToSwitchSides();
|
||||
void RadioFail(); // display and error sound used either when the radio set fails or the sector is jammed - the player knows of the error, but cannot be sure of the cause
|
||||
|
||||
// Flugente: spotter
|
||||
@@ -2025,6 +2031,13 @@ public:
|
||||
// Flugente: those with the <scrounging> background occasionally steal money from the locals
|
||||
UINT8 GetThiefStealMoneyChance();
|
||||
UINT8 GetThiefEvadeDetectionChance();
|
||||
|
||||
// Flugente: turncoats
|
||||
BOOLEAN InPositionForTurncoatAttempt( UINT16 usID );
|
||||
UINT8 GetTurncoatConvinctionChance( UINT16 usID, UINT8 usApproach );
|
||||
void AttemptToCreateTurncoat( UINT16 usID );
|
||||
BOOLEAN OrderTurnCoatToSwitchSides( UINT16 usID );
|
||||
void OrderAllTurnCoatToSwitchSides();
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}; // SOLDIERTYPE;
|
||||
|
||||
@@ -1864,6 +1864,15 @@ BOOLEAN TacticalCopySoldierFromCreateStruct( SOLDIERTYPE *pSoldier, SOLDIERCREAT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: turncoats
|
||||
if ( gSkillTraitValues.fCOTurncoats && pCreateStruct->bTeam == ENEMY_TEAM && SOLDIER_CLASS_ENEMY( pSoldier->ubSoldierClass ) )
|
||||
{
|
||||
if ( NumSoldiersofClassWithFlag2InSector( pCreateStruct->bTeam, pSoldier->ubSoldierClass, SOLDIER_TURNCOAT ) < NumTurncoatsOfClassInSector( gWorldSectorX, gWorldSectorY, pSoldier->ubSoldierClass ) )
|
||||
{
|
||||
pSoldier->usSoldierFlagMask2 |= SOLDIER_TURNCOAT;
|
||||
}
|
||||
}
|
||||
|
||||
// SANDRO - If neither of these two options are activated, use the original code
|
||||
// however, "no traits" means no traits at all, so commented out
|
||||
|
||||
@@ -1587,6 +1587,11 @@ SOLDIERTYPE *ChangeSoldierTeam( SOLDIERTYPE *pSoldier, UINT8 ubTeam )
|
||||
MercCreateStruct.fPlayerMerc = TRUE;
|
||||
}
|
||||
|
||||
if ( ubTeam == MILITIA_TEAM )
|
||||
{
|
||||
MercCreateStruct.ubSoldierClass = pSoldier->ubSoldierClass;
|
||||
}
|
||||
|
||||
if ( TacticalCreateSoldier( &MercCreateStruct, &ubID ) )
|
||||
{
|
||||
pNewSoldier = MercPtrs[ ubID ];
|
||||
|
||||
@@ -1147,6 +1147,7 @@ enum
|
||||
IMPROVEGEARPICKUPMAG_STR,
|
||||
|
||||
DISTRACT_STOP_STR,
|
||||
DISTRACT_TRY_TO_TURNCOAT,
|
||||
|
||||
TEXT_NUM_TACTICAL_STR
|
||||
};
|
||||
@@ -2673,6 +2674,11 @@ enum
|
||||
TEXT_SKILL_DENIAL_SINGLEMERC,
|
||||
TEXT_SKILL_DENIAL_NOALARM,
|
||||
TEXT_SKILL_DENIAL_DISGUISE_CIV_OR_MIL,
|
||||
TEXT_SKILL_DENIAL_NOT_DURING_INTERRUPT,
|
||||
TEXT_SKILL_DENIAL_TURNED_ENEMY,
|
||||
TEXT_SKILL_DENIAL_ENEMY,
|
||||
TEXT_SKILL_DENIAL_SURFACELEVEL,
|
||||
TEXT_SKILL_DENIAL_STRATEGIC_SUSPICION,
|
||||
|
||||
TEXT_SKILL_DENIAL_MAX,
|
||||
};
|
||||
@@ -3093,6 +3099,8 @@ extern STR16 szMilitiaText[];
|
||||
|
||||
extern STR16 szFactoryText[];
|
||||
|
||||
extern STR16 szTurncoatText[];
|
||||
|
||||
#define TACTICAL_INVENTORY_DIALOG_NUM 16
|
||||
#define TACTICAL_COVER_DIALOG_NUM 16
|
||||
|
||||
|
||||
@@ -11597,6 +11597,21 @@ STR16 szFactoryText[] = // TODO.Translate
|
||||
L"h/item",
|
||||
};
|
||||
|
||||
STR16 szTurncoatText[] =
|
||||
{
|
||||
L"%s now secretly works for us!",
|
||||
L"%s is not swayed by our offer. Suspicion against us rises...",
|
||||
L"Suspicion against us is high. We should stop trying to turn more soldiers to our side and lay low for a while.",
|
||||
L"Recruit approach (%d)",
|
||||
L"Use seduction (%d)",
|
||||
|
||||
L"Bribe ($%d) (%d)", // 5
|
||||
L"Offer %d intel (%d)",
|
||||
L"How to convince the soldier to join your forces?",
|
||||
L"Do it",
|
||||
L"%d turncoats present",
|
||||
};
|
||||
|
||||
// WANNE: Some Chinese specific strings that needs to be in unicode!
|
||||
STR16 ChineseSpecString1 = L"%%"; //defined in _ChineseText.cpp as this file is already unicode
|
||||
STR16 ChineseSpecString2 = L"*%3d%%%%"; //defined in _ChineseText.cpp as this file is already unicode
|
||||
|
||||
@@ -11613,4 +11613,19 @@ STR16 szFactoryText[] = // TODO.Translate
|
||||
L"h/item",
|
||||
};
|
||||
|
||||
STR16 szTurncoatText[] =
|
||||
{
|
||||
L"%s now secretly works for us!",
|
||||
L"%s is not swayed by our offer. Suspicion against us rises...",
|
||||
L"Suspicion against us is high. We should stop trying to turn more soldiers to our side and lay low for a while.",
|
||||
L"Recruit approach (%d)",
|
||||
L"Use seduction (%d)",
|
||||
|
||||
L"Bribe ($%d) (%d)", // 5
|
||||
L"Offer %d intel (%d)",
|
||||
L"How to convince the soldier to join your forces?",
|
||||
L"Do it",
|
||||
L"%d turncoats present",
|
||||
};
|
||||
|
||||
#endif //DUTCH
|
||||
|
||||
@@ -2814,10 +2814,14 @@ STR16 pTraitSkillsMenuStrings[] =
|
||||
L"Eavesdrop",
|
||||
L"Call reinforcements",
|
||||
L"Switch off radio set",
|
||||
L"Radio: Activate all turncoats",
|
||||
|
||||
// spy
|
||||
L"Hide assignment",
|
||||
L"Get Intel assignment",
|
||||
L"Recruit turncoat",
|
||||
L"Activate turncoat",
|
||||
L"Activate all turncoats",
|
||||
|
||||
// various
|
||||
L"Spotter",
|
||||
@@ -2835,10 +2839,14 @@ STR16 pTraitSkillsMenuDescStrings[] =
|
||||
L"Use your radio equipment to continously listen for enemy movement.",
|
||||
L"Call in reinforcements from neighbouring sectors.",
|
||||
L"Turn off radio set.",
|
||||
L"Order all previously turned soldiers in the sector to betray their comrades and join you.",
|
||||
|
||||
// spy
|
||||
L"Assignment: hide among the population.",
|
||||
L"Assignment: hide among the population and gather intel.",
|
||||
L"Try to turn an enemy into a turncoat.",
|
||||
L"Order previously turned soldier to betray their comrades and join you.",
|
||||
L"Order all previously turned soldiers in the sector to betray their comrades and join you.",
|
||||
|
||||
// various
|
||||
L"Observe an area, granting allied snipers a bonus to cth on anything you see.",
|
||||
@@ -2867,6 +2875,11 @@ STR16 pTraitSkillsDenialStrings[] =
|
||||
L" - single merc\n",
|
||||
L" - no alarm raised\n",
|
||||
L" - civilian or soldier disguise\n",
|
||||
L" - being our turn\n",
|
||||
L" - turned enemy soldier\n",
|
||||
L" - enemy soldier\n",
|
||||
L" - surface sector\n",
|
||||
L" - not being under suspicion\n",
|
||||
};
|
||||
|
||||
STR16 pSkillMenuStrings[] =
|
||||
@@ -4075,6 +4088,7 @@ CHAR16 TacticalStr[][ MED_STRING_LENGTH ] =
|
||||
L"%s picked up %s",
|
||||
|
||||
L"%s has stopped chatting with %s",
|
||||
L"Attempt to turn",
|
||||
};
|
||||
|
||||
//Varying helptext explains (for the "Go to Sector/Map" checkbox) what will happen given different circumstances in the "exiting sector" interface.
|
||||
@@ -11260,6 +11274,7 @@ STR16 szIndividualMilitiaBattleReportText[] =
|
||||
L"Hired from Kerberus on Day %d, %d:%02d in %s",
|
||||
L"Defected to us on Day %d, %d:%02d in %s",
|
||||
L"Contract terminated on Day %d, %d:%02d",
|
||||
L"Defected to us on Day %d, %d:%02d in %s",
|
||||
};
|
||||
|
||||
STR16 szIndividualMilitiaTraitRequirements[] =
|
||||
@@ -11597,4 +11612,19 @@ STR16 szFactoryText[] =
|
||||
L"h/item",
|
||||
};
|
||||
|
||||
STR16 szTurncoatText[] =
|
||||
{
|
||||
L"%s now secretly works for us!",
|
||||
L"%s is not swayed by our offer. Suspicion against us rises...",
|
||||
L"Suspicion against us is high. We should stop trying to turn more soldiers to our side and lay low for a while.",
|
||||
L"Recruit approach (%d)",
|
||||
L"Use seduction (%d)",
|
||||
|
||||
L"Bribe ($%d) (%d)", // 5
|
||||
L"Offer %d intel (%d)",
|
||||
L"How to convince the soldier to join your forces?",
|
||||
L"Do it",
|
||||
L"%d turncoats present",
|
||||
};
|
||||
|
||||
#endif //ENGLISH
|
||||
|
||||
@@ -11595,4 +11595,19 @@ STR16 szFactoryText[] = // TODO.Translate
|
||||
L"h/item",
|
||||
};
|
||||
|
||||
STR16 szTurncoatText[] =
|
||||
{
|
||||
L"%s now secretly works for us!",
|
||||
L"%s is not swayed by our offer. Suspicion against us rises...",
|
||||
L"Suspicion against us is high. We should stop trying to turn more soldiers to our side and lay low for a while.",
|
||||
L"Recruit approach (%d)",
|
||||
L"Use seduction (%d)",
|
||||
|
||||
L"Bribe ($%d) (%d)", // 5
|
||||
L"Offer %d intel (%d)",
|
||||
L"How to convince the soldier to join your forces?",
|
||||
L"Do it",
|
||||
L"%d turncoats present",
|
||||
};
|
||||
|
||||
#endif //FRENCH
|
||||
|
||||
@@ -11425,4 +11425,19 @@ STR16 szFactoryText[] = // TODO.Translate
|
||||
L"h/item",
|
||||
};
|
||||
|
||||
STR16 szTurncoatText[] =
|
||||
{
|
||||
L"%s now secretly works for us!",
|
||||
L"%s is not swayed by our offer. Suspicion against us rises...",
|
||||
L"Suspicion against us is high. We should stop trying to turn more soldiers to our side and lay low for a while.",
|
||||
L"Recruit approach (%d)",
|
||||
L"Use seduction (%d)",
|
||||
|
||||
L"Bribe ($%d) (%d)", // 5
|
||||
L"Offer %d intel (%d)",
|
||||
L"How to convince the soldier to join your forces?",
|
||||
L"Do it",
|
||||
L"%d turncoats present",
|
||||
};
|
||||
|
||||
#endif //GERMAN
|
||||
|
||||
@@ -11604,4 +11604,19 @@ STR16 szFactoryText[] = // TODO.Translate
|
||||
L"h/item",
|
||||
};
|
||||
|
||||
STR16 szTurncoatText[] =
|
||||
{
|
||||
L"%s now secretly works for us!",
|
||||
L"%s is not swayed by our offer. Suspicion against us rises...",
|
||||
L"Suspicion against us is high. We should stop trying to turn more soldiers to our side and lay low for a while.",
|
||||
L"Recruit approach (%d)",
|
||||
L"Use seduction (%d)",
|
||||
|
||||
L"Bribe ($%d) (%d)", // 5
|
||||
L"Offer %d intel (%d)",
|
||||
L"How to convince the soldier to join your forces?",
|
||||
L"Do it",
|
||||
L"%d turncoats present",
|
||||
};
|
||||
|
||||
#endif //ITALIAN
|
||||
|
||||
@@ -259,6 +259,7 @@ STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
|
||||
L"伪装状态下使用近战武器攻击时,命中率增加 +%d%s \n",//L"+%d%s CTH with covert melee weapons\n",
|
||||
L"伪装状态下使用近战武器攻击时,秒杀几率增加 +%d%s \n",//L"+%d%s chance of instakill with covert melee weapons\n",
|
||||
L"伪装动作消耗的行动点 -%d%s \n",//L"Disguise AP cost lowered by %d%s.\n",
|
||||
L"Can convince enemy soldiers to secretly change sides.\n", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 gzIMPMajorTraitsHelpTextsRadioOperator[]=
|
||||
|
||||
@@ -259,6 +259,7 @@ STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
|
||||
L"+%d%s CtH with covert melee weapons\n",
|
||||
L"+%d%s chance of instakill with covert melee weapons\n",
|
||||
L"Disguise AP cost lowered by %d%s.\n",
|
||||
L"Can convince enemy soldiers to secretly change sides.\n", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 gzIMPMajorTraitsHelpTextsRadioOperator[]= // TODO.Translate
|
||||
|
||||
@@ -259,6 +259,7 @@ STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
|
||||
L"+%d%s CtH with covert melee weapons\n",
|
||||
L"+%d%s chance of instakill with covert melee weapons\n",
|
||||
L"Disguise AP cost lowered by %d%s.\n",
|
||||
L"Can convince enemy soldiers to secretly change sides.\n",
|
||||
};
|
||||
|
||||
STR16 gzIMPMajorTraitsHelpTextsRadioOperator[]=
|
||||
|
||||
@@ -259,6 +259,7 @@ STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
|
||||
L"+%d%s de chance de toucher avec une arme d'espion\n",
|
||||
L"+%d%s de chance de tuer un ennemi instantanément avec une arme d'espion\n",
|
||||
L"Le nombre de PA pour se déguiser, est réduit de %d%s\n",
|
||||
L"Can convince enemy soldiers to secretly change sides.\n", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 gzIMPMajorTraitsHelpTextsRadioOperator[]=
|
||||
|
||||
@@ -259,6 +259,7 @@ STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
|
||||
L"+%d%s Trefferwahrscheinlichkeit mit verdeckten Nahkampfwaffen (z.B. Garotte)\n",
|
||||
L"+%d%s Wahrscheinlichkeit für einen tödlichen Angriff mit verdeckten Nahkampfwaffen (z.B. Garotte)\n",
|
||||
L"Um %d%s verringerte AP-Kosten zum Verkleiden\n",
|
||||
L"Kann feindliche Soldaten zum Überlaufen überreden.\n",
|
||||
};
|
||||
|
||||
STR16 gzIMPMajorTraitsHelpTextsRadioOperator[]=
|
||||
|
||||
@@ -257,6 +257,7 @@ STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
|
||||
L"+%d%s CtH with covert melee weapons\n",
|
||||
L"+%d%s chance of instakill with covert melee weapons\n",
|
||||
L"Disguise AP cost lowered by %d%s.\n",
|
||||
L"Can convince enemy soldiers to secretly change sides.\n", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 gzIMPMajorTraitsHelpTextsRadioOperator[]= // TODO.Translate
|
||||
|
||||
@@ -259,6 +259,7 @@ STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
|
||||
L"+%d%s CtH with covert melee weapons\n",
|
||||
L"+%d%s chance of instakill with covert melee weapons\n",
|
||||
L"Disguise AP cost lowered by %d%s.\n",
|
||||
L"Can convince enemy soldiers to secretly change sides.\n", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 gzIMPMajorTraitsHelpTextsRadioOperator[]= // TODO.Translate
|
||||
|
||||
@@ -259,6 +259,7 @@ STR16 gzIMPMajorTraitsHelpTextsCovertOps[]=
|
||||
L"+%d%s к шансу попадания скрытным оружием ближнего боя.\n",
|
||||
L"+%d%s к шансу на смертельный удар скрытным оружием ближнего боя.\n",
|
||||
L"ОД на переодевание снижены на %d%s.\n",
|
||||
L"Can convince enemy soldiers to secretly change sides.\n", // TODO.Translate
|
||||
};
|
||||
|
||||
STR16 gzIMPMajorTraitsHelpTextsRadioOperator[]=
|
||||
|
||||
@@ -11617,4 +11617,19 @@ STR16 szFactoryText[] = // TODO.Translate
|
||||
L"h/item",
|
||||
};
|
||||
|
||||
STR16 szTurncoatText[] =
|
||||
{
|
||||
L"%s now secretly works for us!",
|
||||
L"%s is not swayed by our offer. Suspicion against us rises...",
|
||||
L"Suspicion against us is high. We should stop trying to turn more soldiers to our side and lay low for a while.",
|
||||
L"Recruit approach (%d)",
|
||||
L"Use seduction (%d)",
|
||||
|
||||
L"Bribe ($%d) (%d)", // 5
|
||||
L"Offer %d intel (%d)",
|
||||
L"How to convince the soldier to join your forces?",
|
||||
L"Do it",
|
||||
L"%d turncoats present",
|
||||
};
|
||||
|
||||
#endif //POLISH
|
||||
|
||||
@@ -11597,4 +11597,19 @@ STR16 szFactoryText[] = // TODO.Translate
|
||||
L"h/item",
|
||||
};
|
||||
|
||||
STR16 szTurncoatText[] =
|
||||
{
|
||||
L"%s now secretly works for us!",
|
||||
L"%s is not swayed by our offer. Suspicion against us rises...",
|
||||
L"Suspicion against us is high. We should stop trying to turn more soldiers to our side and lay low for a while.",
|
||||
L"Recruit approach (%d)",
|
||||
L"Use seduction (%d)",
|
||||
|
||||
L"Bribe ($%d) (%d)", // 5
|
||||
L"Offer %d intel (%d)",
|
||||
L"How to convince the soldier to join your forces?",
|
||||
L"Do it",
|
||||
L"%d turncoats present",
|
||||
};
|
||||
|
||||
#endif //RUSSIAN
|
||||
|
||||
Reference in New Issue
Block a user