mirror of
https://github.com/1dot13/source.git
synced 2026-09-02 14:36:06 +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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user