mirror of
https://github.com/1dot13/source.git
synced 2026-08-26 14:30:26 +02:00
Moving Tanks Feature (by anv)
- feature: tanks can move around in tactical. Set with Tactical Gameplay Settings > ENEMY_TANKS_CAN_MOVE. - feature: tanks can ignore chance to get through and destroy enemy cover even if it probably won't hit anyone behind it. Set with Tactical Gameplay Settings > ENEMY_TANKS_BLOW_OBSTACLES_UP. - feature: tanks can use cannon even against single mercs and in perfect health. Set with Tactical Gameplay Settings > ENEMY_TANKS_DONT_SPARE_SHELLS. - feature: tanks can noticed as soon as any part of it is visible. Set with Tactical Gameplay Settings > ENEMY_TANKS_ANY_PART_VISIBLE. - feature: depending on game difficulty enemy patrols at game start can be randomly reinforced with tank. Set with Strategic Gameplay Settings > ARMY_USES_TANKS_IN_PATROLS. - feature: depending on game difficulty enemy groups created during offensives can include tanks. Set with trategic Gameplay Settings > ARMY_USES_TANKS_IN_ATTACKS. - feature: mercs in vehicles automatically rest their guns, - fix: guns can be rested on vehicles, - rewritten code to allow putting enemies inside vehicles, - added missing descriptions for all vehicle options to INIEditorJA2Options.xml. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7277 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -316,9 +316,11 @@ void DoneFadeOutKilledQueen( void )
|
||||
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubNumAdmins = 0;
|
||||
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubNumTroops = 0;
|
||||
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubNumElites = 0;
|
||||
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubNumTanks = 0;
|
||||
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubAdminsInBattle = 0;
|
||||
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubTroopsInBattle = 0;
|
||||
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubElitesInBattle = 0;
|
||||
SectorInfo[ SECTOR( VICTORY_X, VICTORY_Y ) ].ubTanksInBattle = 0;
|
||||
|
||||
// ATE: banish elliot... dead or alive
|
||||
gMercProfiles[ ELLIOT ].sSectorX = 0;
|
||||
|
||||
@@ -43,7 +43,7 @@ int gCivPreservedTempFileVersion[256];
|
||||
|
||||
BOOLEAN AddPlacementToWorld( SOLDIERINITNODE *pNode, GROUP *pGroup = NULL );
|
||||
|
||||
BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures );
|
||||
BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks );
|
||||
|
||||
BOOLEAN gfRestoringEnemySoldiersFromTempFile = FALSE;
|
||||
BOOLEAN gfRestoringCiviliansFromTempFile = FALSE;
|
||||
@@ -104,8 +104,8 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
|
||||
#endif
|
||||
INT8 bSectorZ;
|
||||
UINT8 ubSectorID;
|
||||
UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0;
|
||||
UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures;
|
||||
UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0;
|
||||
UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks;
|
||||
|
||||
gfRestoringEnemySoldiersFromTempFile = TRUE;
|
||||
|
||||
@@ -253,6 +253,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
|
||||
ubStrategicElites = pSector->ubNumElites;
|
||||
ubStrategicTroops = pSector->ubNumTroops;
|
||||
ubStrategicAdmins = pSector->ubNumAdmins;
|
||||
ubStrategicTanks = pSector->ubNumTanks;
|
||||
ubStrategicCreatures = pSector->ubNumCreatures;
|
||||
}
|
||||
else
|
||||
@@ -260,7 +261,7 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
|
||||
SECTORINFO *pSector;
|
||||
pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ];
|
||||
ubStrategicCreatures = pSector->ubNumCreatures;
|
||||
GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites );
|
||||
GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks );
|
||||
}
|
||||
|
||||
for( i = 0; i < slots; i++ )
|
||||
@@ -347,6 +348,16 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
|
||||
AddPlacementToWorld( curr );
|
||||
}
|
||||
break;
|
||||
case SOLDIER_CLASS_TANK:
|
||||
if( curr->pBasicPlacement->bBodyType == TANK_NE || curr->pBasicPlacement->bBodyType == TANK_NW )
|
||||
{
|
||||
ubNumTanks++;
|
||||
if( ubNumTanks < ubStrategicTanks )
|
||||
{
|
||||
AddPlacementToWorld( curr );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -374,12 +385,13 @@ BOOLEAN LoadEnemySoldiersFromTempFile()
|
||||
}
|
||||
|
||||
//now add any extra enemies that have arrived since the temp file was made.
|
||||
if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins )
|
||||
if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicTanks > ubNumTanks )
|
||||
{
|
||||
ubStrategicTroops = ( ubStrategicTroops > ubNumTroops ) ? ubStrategicTroops - ubNumTroops : 0;
|
||||
ubStrategicElites = ( ubStrategicElites > ubNumElites ) ? ubStrategicElites - ubNumElites : 0;
|
||||
ubStrategicAdmins = ( ubStrategicAdmins > ubNumAdmins ) ? ubStrategicAdmins - ubNumAdmins : 0;
|
||||
AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites );
|
||||
ubStrategicTanks = ( ubStrategicTanks > ubNumTanks ) ? ubStrategicTanks - ubNumTanks : 0;
|
||||
AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks );
|
||||
}
|
||||
if( ubStrategicCreatures > ubNumCreatures )
|
||||
{
|
||||
@@ -662,8 +674,8 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
|
||||
#endif
|
||||
INT8 bSectorZ;
|
||||
UINT8 ubSectorID;
|
||||
UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0;
|
||||
UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures;
|
||||
UINT8 ubNumElites = 0, ubNumTroops = 0, ubNumAdmins = 0, ubNumCreatures = 0, ubNumTanks = 0;
|
||||
UINT8 ubStrategicElites, ubStrategicTroops, ubStrategicAdmins, ubStrategicCreatures, ubStrategicTanks;
|
||||
|
||||
gfRestoringEnemySoldiersFromTempFile = TRUE;
|
||||
|
||||
@@ -702,16 +714,17 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
|
||||
ubNumElites = pSector->ubNumElites;
|
||||
ubNumTroops = pSector->ubNumTroops;
|
||||
ubNumAdmins = pSector->ubNumAdmins;
|
||||
ubNumTanks = pSector->ubNumTanks;
|
||||
ubNumCreatures = pSector->ubNumCreatures;
|
||||
}
|
||||
|
||||
if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
|
||||
{
|
||||
// Get the number of enemies form the temp file
|
||||
CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( &ubStrategicElites, &ubStrategicTroops, &ubStrategicAdmins, &ubStrategicCreatures );
|
||||
CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( &ubStrategicElites, &ubStrategicTroops, &ubStrategicAdmins, &ubStrategicCreatures, &ubStrategicTanks );
|
||||
|
||||
//If any of the counts differ from what is in memory
|
||||
if( ubStrategicElites != ubNumElites || ubStrategicTroops != ubNumTroops || ubStrategicAdmins != ubNumAdmins || ubStrategicCreatures != ubNumCreatures )
|
||||
if( ubStrategicElites != ubNumElites || ubStrategicTroops != ubNumTroops || ubStrategicAdmins != ubNumAdmins || ubStrategicCreatures != ubNumCreatures || ubStrategicTanks != ubNumTanks )
|
||||
{
|
||||
//remove the file
|
||||
RemoveEnemySoldierTempFile( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
@@ -720,7 +733,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
|
||||
}
|
||||
|
||||
//reset
|
||||
ubNumElites = ubNumTroops = ubNumAdmins = ubNumCreatures = 0;
|
||||
ubNumElites = ubNumTroops = ubNumAdmins = ubNumCreatures = ubNumTanks = 0;
|
||||
|
||||
|
||||
//Open the file for reading
|
||||
@@ -860,6 +873,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
|
||||
ubStrategicElites = pSector->ubNumElites;
|
||||
ubStrategicTroops = pSector->ubNumTroops;
|
||||
ubStrategicAdmins = pSector->ubNumAdmins;
|
||||
ubStrategicTanks = pSector->ubNumTanks;
|
||||
ubStrategicCreatures = pSector->ubNumCreatures;
|
||||
}
|
||||
else
|
||||
@@ -867,7 +881,7 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
|
||||
SECTORINFO *pSector;
|
||||
pSector = &SectorInfo[ SECTOR( sSectorX, sSectorY ) ];
|
||||
ubStrategicCreatures = pSector->ubNumCreatures;
|
||||
GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites );
|
||||
GetNumberOfEnemiesInSector( sSectorX, sSectorY, &ubStrategicAdmins, &ubStrategicTroops, &ubStrategicElites, &ubStrategicTanks );
|
||||
}
|
||||
|
||||
for( i = 0; i < slots; i++ )
|
||||
@@ -944,6 +958,16 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
|
||||
//def: AddPlacementToWorld( curr );
|
||||
}
|
||||
break;
|
||||
case SOLDIER_CLASS_TANK:
|
||||
if( curr->pBasicPlacement->bBodyType == TANK_NE || curr->pBasicPlacement->bBodyType == TANK_NW )
|
||||
{
|
||||
ubNumTanks++;
|
||||
if( ubNumTanks <= ubStrategicTanks )
|
||||
{
|
||||
//def: AddPlacementToWorld( curr );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -969,12 +993,13 @@ BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile()
|
||||
}
|
||||
|
||||
//now add any extra enemies that have arrived since the temp file was made.
|
||||
if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins )
|
||||
if( ubStrategicTroops > ubNumTroops || ubStrategicElites > ubNumElites || ubStrategicAdmins > ubNumAdmins || ubStrategicTanks > ubNumTanks )
|
||||
{
|
||||
ubStrategicTroops = ( ubStrategicTroops > ubNumTroops ) ? ubStrategicTroops - ubNumTroops : 0;
|
||||
ubStrategicElites = ( ubStrategicElites > ubNumElites ) ? ubStrategicElites - ubNumElites : 0;
|
||||
ubStrategicAdmins = ( ubStrategicAdmins > ubNumAdmins ) ? ubStrategicAdmins - ubNumAdmins : 0;
|
||||
AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites );
|
||||
ubStrategicTanks = ( ubStrategicTanks > ubNumTanks ) ? ubStrategicTanks - ubNumTanks : 0;
|
||||
AddSoldierInitListEnemyDefenceSoldiers( ubStrategicAdmins, ubStrategicTroops, ubStrategicElites, ubStrategicTanks );
|
||||
}
|
||||
if( ubStrategicCreatures > ubNumCreatures )
|
||||
{
|
||||
@@ -1567,7 +1592,7 @@ BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY
|
||||
|
||||
|
||||
|
||||
BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures )
|
||||
BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile( UINT8 *pubNumElites, UINT8 *pubNumRegulars, UINT8 *pubNumAdmins, UINT8 *pubNumCreatures, UINT8 *pubNumTanks )
|
||||
{
|
||||
// SOLDIERINITNODE *curr;
|
||||
SOLDIERCREATE_STRUCT tempDetailedPlacement;
|
||||
@@ -1592,6 +1617,7 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile(
|
||||
*pubNumElites = 0;
|
||||
*pubNumRegulars = 0;
|
||||
*pubNumAdmins = 0;
|
||||
*pubNumTanks = 0;
|
||||
*pubNumCreatures = 0;
|
||||
|
||||
|
||||
@@ -1758,6 +1784,12 @@ BOOLEAN CountNumberOfElitesRegularsAdminsAndCreaturesFromEnemySoldiersTempFile(
|
||||
case SOLDIER_CLASS_CREATURE:
|
||||
(*pubNumCreatures)++;
|
||||
break;
|
||||
case SOLDIER_CLASS_TANK:
|
||||
if( tempDetailedPlacement.bBodyType == TANK_NE || tempDetailedPlacement.bBodyType == TANK_NW )
|
||||
{
|
||||
(*pubNumTanks)++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
while( curr )
|
||||
|
||||
@@ -259,7 +259,7 @@ void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8
|
||||
}
|
||||
|
||||
|
||||
Assert( ( bSoldierClass >= SOLDIER_CLASS_NONE ) && ( bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA ) );
|
||||
Assert( ( bSoldierClass >= SOLDIER_CLASS_NONE ) && ( bSoldierClass <= SOLDIER_CLASS_ELITE_MILITIA ) || bSoldierClass == SOLDIER_CLASS_TANK );
|
||||
Assert( ( bEquipmentRating >= 0 ) && ( bEquipmentRating <= 4 ) );
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -2329,7 +2329,7 @@ INT32 SoldierToSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE
|
||||
|
||||
// anv: special check for vehicles - since they're no longer transparent, we need to check for visibility
|
||||
// of all substructures, also vehicle will be noticed even if just part of it is sticking around the corner
|
||||
if( pEndSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && !TANK( pEndSoldier ) )
|
||||
if( pEndSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE && ( !TANK( pEndSoldier ) || gGameExternalOptions.fEnemyTanksAnyPartVisible ) )
|
||||
{
|
||||
STRUCTURE *pBase = pEndSoldier->pLevelNode->pStructureData;
|
||||
if( pBase == NULL )
|
||||
|
||||
@@ -6950,16 +6950,16 @@ void RemoveStaticEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
{
|
||||
SECTORINFO *pSectorInfo = &(SectorInfo[SECTOR( sMapX, sMapY )]);
|
||||
|
||||
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0;
|
||||
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0;
|
||||
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = 0;
|
||||
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
UNDERGROUND_SECTORINFO *pSectorInfo;
|
||||
|
||||
pSectorInfo = FindUnderGroundSector( sMapX, sMapY, bMapZ );
|
||||
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = 0;
|
||||
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = 0;
|
||||
pSectorInfo->ubNumAdmins = pSectorInfo->ubNumTroops = pSectorInfo->ubNumElites = pSectorInfo->ubNumTanks = 0;
|
||||
pSectorInfo->ubAdminsInBattle = pSectorInfo->ubTroopsInBattle = pSectorInfo->ubElitesInBattle = pSectorInfo->ubTanksInBattle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -2610,7 +2610,7 @@ INT16 MinPtsToMove(SOLDIERTYPE *pSoldier)
|
||||
INT16 sCost;
|
||||
INT32 sGridNo;
|
||||
|
||||
if ( TANK( pSoldier ) )
|
||||
if ( TANK( pSoldier ) && !gGameExternalOptions.fEnemyTanksCanMoveInTactical )
|
||||
{
|
||||
return(sLowest);//dnl ch64 290813 100AP made INT8 return obsolete
|
||||
}
|
||||
|
||||
@@ -14228,6 +14228,15 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
|
||||
if ( TileIsOutOfBounds(this->sGridNo) )
|
||||
return( FALSE );
|
||||
|
||||
// anv: passengers who can shoot can rest their guns
|
||||
if ( this->flags.uiStatusFlags & ( SOLDIER_DRIVER | SOLDIER_PASSENGER ) )
|
||||
{
|
||||
if( !gNewVehicle[pVehicleList[this->iVehicleId].ubVehicleType].VehicleSeats[GetSeatIndexFromSoldier(this)].fBlockedShots )
|
||||
return( TRUE );
|
||||
else
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// we determine the height of the next tile in our direction. Because of the way structures are handled, we sometimes have to take the very tile we're occupying right now
|
||||
INT32 nextGridNoinSight = this->sGridNo;
|
||||
if ( this->ubDirection == NORTH || this->ubDirection == SOUTHWEST || this->ubDirection == WEST || this->ubDirection == NORTHWEST )
|
||||
@@ -14258,8 +14267,13 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
|
||||
{
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[ usPersonID ];
|
||||
|
||||
// anv: vehicles don't mind
|
||||
if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
||||
{
|
||||
applybipod = TRUE;
|
||||
}
|
||||
// if the other person is an ally and prone
|
||||
if ( this->bSide == pSoldier->bSide && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE )
|
||||
else if ( this->bSide == pSoldier->bSide && gAnimControl[ pSoldier->usAnimState ].ubEndHeight == ANIM_PRONE )
|
||||
{
|
||||
// if we are facing the other guy in a 90 degree angle, we can mount our gun on his back
|
||||
// Once merc's relationship allows angering mercs through actions of others, add a penalty here
|
||||
@@ -14324,8 +14338,13 @@ BOOLEAN SOLDIERTYPE::IsWeaponMounted( void )
|
||||
{
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[usPersonID];
|
||||
|
||||
// anv: vehicles don't mind
|
||||
if( pSoldier->flags.uiStatusFlags & SOLDIER_VEHICLE )
|
||||
{
|
||||
applybipod = TRUE;
|
||||
}
|
||||
// if the other person is an ally and prone
|
||||
if ( this->bSide == pSoldier->bSide && gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_CROUCH )
|
||||
else if ( this->bSide == pSoldier->bSide && gAnimControl[pSoldier->usAnimState].ubEndHeight == ANIM_CROUCH )
|
||||
{
|
||||
applybipod = TRUE;
|
||||
|
||||
|
||||
@@ -329,6 +329,7 @@ enum
|
||||
SOLDIER_CLASS_CREATURE,
|
||||
SOLDIER_CLASS_MINER,
|
||||
SOLDIER_CLASS_ZOMBIE,
|
||||
SOLDIER_CLASS_TANK,
|
||||
SOLDIER_CLASS_MAX,
|
||||
};
|
||||
|
||||
|
||||
@@ -2430,6 +2430,10 @@ void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, B
|
||||
}
|
||||
break;
|
||||
|
||||
case SOLDIER_CLASS_TANK:
|
||||
pp->bExpLevel = bp->bRelativeAttributeLevel;
|
||||
break;
|
||||
|
||||
default:
|
||||
pp->bExpLevel = bp->bRelativeAttributeLevel; //avg 2 (1-4)
|
||||
ubSoldierClass = SOLDIER_CLASS_NONE;
|
||||
@@ -3033,6 +3037,86 @@ SOLDIERTYPE* TacticalCreateEliteEnemy()
|
||||
return( pSoldier );
|
||||
}
|
||||
|
||||
//USED BY STRATEGIC AI and AUTORESOLVE
|
||||
SOLDIERTYPE* TacticalCreateEnemyTank()
|
||||
{
|
||||
BASIC_SOLDIERCREATE_STRUCT bp;
|
||||
SOLDIERCREATE_STRUCT pp;
|
||||
UINT8 ubID;
|
||||
SOLDIERTYPE * pSoldier;
|
||||
|
||||
if( guiCurrentScreen == AUTORESOLVE_SCREEN && !gfPersistantPBI )
|
||||
{
|
||||
pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_ELITE );
|
||||
if( pSoldier ) return pSoldier;
|
||||
}
|
||||
|
||||
memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
|
||||
RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ELITE );
|
||||
RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ELITE );
|
||||
bp.bTeam = ENEMY_TEAM;
|
||||
bp.bOrders = SEEKENEMY;
|
||||
bp.bAttitude = (INT8) Random( MAXATTITUDES );
|
||||
bp.bBodyType = TANK_NW;
|
||||
bp.ubSoldierClass = SOLDIER_CLASS_TANK;
|
||||
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
|
||||
|
||||
//SPECIAL! Certain events in the game can cause profiled NPCs to become enemies. The two cases are
|
||||
//adding Mike and Iggy. We will only add one NPC in any given combat and the conditions for setting
|
||||
//the associated facts are done elsewhere. There is also another place where NPCs can get added, which
|
||||
//is in AddPlacementToWorld() used for inserting defensive enemies.
|
||||
//NOTE: We don't want to add Mike or Iggy if this is being called from autoresolve!
|
||||
OkayToUpgradeEliteToSpecialProfiledEnemy( &pp );
|
||||
|
||||
pSoldier = TacticalCreateSoldier( &pp, &ubID );
|
||||
if ( pSoldier )
|
||||
{
|
||||
// send soldier to centre of map, roughly
|
||||
pSoldier->aiData.sNoiseGridno = (CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS);
|
||||
pSoldier->aiData.ubNoiseVolume = MAX_MISC_NOISE_DURATION;
|
||||
}
|
||||
|
||||
return( pSoldier );
|
||||
}
|
||||
|
||||
//USED BY STRATEGIC AI and AUTORESOLVE
|
||||
// should to be succeeded by TacticalCreateArmyTroop/EliteEnemy and AddSoldierToVehicle
|
||||
SOLDIERTYPE* TacticalCreateJeep()
|
||||
{
|
||||
BASIC_SOLDIERCREATE_STRUCT bp;
|
||||
SOLDIERCREATE_STRUCT pp;
|
||||
UINT8 ubID;
|
||||
SOLDIERTYPE * pSoldier;
|
||||
SOLDIERTYPE * pDriver;
|
||||
|
||||
if( guiCurrentScreen == AUTORESOLVE_SCREEN && !gfPersistantPBI )
|
||||
{
|
||||
pSoldier = ReserveTacticalSoldierForAutoresolve( SOLDIER_CLASS_ELITE );
|
||||
if( pSoldier ) return pSoldier;
|
||||
}
|
||||
|
||||
memset( &bp, 0, sizeof( BASIC_SOLDIERCREATE_STRUCT ) );
|
||||
RandomizeRelativeLevel( &( bp.bRelativeAttributeLevel ), SOLDIER_CLASS_ELITE );
|
||||
RandomizeRelativeLevel( &( bp.bRelativeEquipmentLevel ), SOLDIER_CLASS_ELITE );
|
||||
bp.bTeam = CIV_TEAM;
|
||||
bp.bOrders = STATIONARY;
|
||||
bp.bAttitude = (INT8) Random( MAXATTITUDES );
|
||||
bp.bBodyType = JEEP;
|
||||
bp.ubSoldierClass = SOLDIER_CLASS_NONE;
|
||||
CreateDetailedPlacementGivenBasicPlacementInfo( &pp, &bp );
|
||||
pp.ubProfile = 199;
|
||||
|
||||
pSoldier = TacticalCreateSoldier( &pp, &ubID );
|
||||
if ( pSoldier )
|
||||
{
|
||||
// send soldier to centre of map, roughly
|
||||
pSoldier->aiData.sNoiseGridno = (CENTRAL_GRIDNO + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) + ( Random( CENTRAL_RADIUS * 2 + 1 ) - CENTRAL_RADIUS ) * WORLD_COLS);
|
||||
pSoldier->aiData.ubNoiseVolume = MAX_MISC_NOISE_DURATION;
|
||||
}
|
||||
|
||||
return( pSoldier );
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ZOMBIES
|
||||
//USED BY STRATEGIC AI and AUTORESOLVE
|
||||
SOLDIERTYPE* TacticalCreateZombie()
|
||||
|
||||
@@ -425,6 +425,8 @@ SOLDIERTYPE* TacticalCreateArmyTroop();
|
||||
#endif
|
||||
SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass, INT16 sX, INT16 sY ); // Flugente: added sector coordinates
|
||||
SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType );
|
||||
SOLDIERTYPE* TacticalCreateEnemyTank();
|
||||
SOLDIERTYPE* TacticalCreateJeep();
|
||||
|
||||
// Flugente: assassins are elite soldiers of the civ team that go hostile on a certain event, otherwise they just blend in
|
||||
SOLDIERTYPE* TacticalCreateEnemyAssassin(UINT8 disguisetype);
|
||||
|
||||
@@ -976,7 +976,7 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
|
||||
return ubNumAdded;
|
||||
}
|
||||
|
||||
void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite )
|
||||
void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalTanks )
|
||||
{
|
||||
SOLDIERINITNODE *mark;
|
||||
SOLDIERINITNODE *curr;
|
||||
@@ -985,6 +985,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
|
||||
UINT8 ubElitePDSlots = 0, ubEliteDSlots = 0, ubElitePSlots = 0, ubEliteBSlots = 0;
|
||||
UINT8 ubTroopPDSlots = 0, ubTroopDSlots = 0, ubTroopPSlots = 0, ubTroopBSlots = 0;
|
||||
UINT8 ubAdminPDSlots = 0, ubAdminDSlots = 0, ubAdminPSlots = 0, ubAdminBSlots = 0;
|
||||
UINT8 ubTankPDSlots = 0, ubTankDSlots = 0, ubTankPSlots = 0, ubTankBSlots = 0;
|
||||
UINT8 ubFreeSlots;
|
||||
UINT8 *pCurrSlots=NULL;
|
||||
UINT8 *pCurrTotal=NULL;
|
||||
@@ -1002,7 +1003,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
|
||||
//of each type of enemy may not be the same. Elites will choose the best placements, then army, then
|
||||
//administrators.
|
||||
|
||||
ubMaxNum = ubTotalAdmin + ubTotalTroops + ubTotalElite;
|
||||
ubMaxNum = ubTotalAdmin + ubTotalTroops + ubTotalElite + ubTotalTanks;
|
||||
|
||||
AssertLE (ubMaxNum, gGameExternalOptions.ubGameMaximumNumberOfEnemies);
|
||||
|
||||
@@ -1052,6 +1053,19 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
|
||||
else
|
||||
ubTroopBSlots++;
|
||||
break;
|
||||
case SOLDIER_CLASS_TANK:
|
||||
if( curr->pDetailedPlacement->bBodyType == TANK_NW ||curr->pDetailedPlacement->bBodyType == TANK_NE )
|
||||
{
|
||||
if( curr->pBasicPlacement->fPriorityExistance && curr->pDetailedPlacement )
|
||||
ubTankPDSlots++;
|
||||
else if( curr->pBasicPlacement->fPriorityExistance )
|
||||
ubTankPSlots++;
|
||||
else if( curr->pDetailedPlacement )
|
||||
ubTankDSlots++;
|
||||
else
|
||||
ubTankBSlots++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
curr = curr->next;
|
||||
@@ -1060,7 +1074,7 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
|
||||
//ADD PLACEMENTS WITH PRIORITY EXISTANCE WITH DETAILED PLACEMENT INFORMATION FIRST
|
||||
//we now have the numbers of available slots for each soldier class, so loop through three times
|
||||
//and randomly choose some (or all) of the matching slots to fill. This is done randomly.
|
||||
for( ubCurrClass = SOLDIER_CLASS_ADMINISTRATOR; ubCurrClass <= SOLDIER_CLASS_ARMY; ubCurrClass++ )
|
||||
for( ubCurrClass = SOLDIER_CLASS_ADMINISTRATOR; ubCurrClass <= SOLDIER_CLASS_ARMY + 1; ubCurrClass++ )
|
||||
{
|
||||
//First, prepare the counters.
|
||||
switch( ubCurrClass )
|
||||
@@ -1077,6 +1091,11 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
|
||||
pCurrSlots = &ubTroopPDSlots;
|
||||
pCurrTotal = &ubTotalTroops;
|
||||
break;
|
||||
case SOLDIER_CLASS_ARMY + 1:// SOLDIER_CLASS_TANK
|
||||
ubCurrClass = SOLDIER_CLASS_TANK;
|
||||
pCurrSlots = &ubTankPDSlots;
|
||||
pCurrTotal = &ubTotalTanks;
|
||||
break;
|
||||
}
|
||||
//Now, loop through the priority existance and detailed placement section of the list.
|
||||
curr = gSoldierInitHead;
|
||||
@@ -1253,6 +1272,12 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
|
||||
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ADMINISTRATOR;
|
||||
ubTotalAdmin--;
|
||||
}
|
||||
else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks )
|
||||
{
|
||||
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK;
|
||||
curr->pBasicPlacement->bBodyType = TANK_NW;
|
||||
ubTotalTanks--;
|
||||
}
|
||||
else
|
||||
Assert(0);
|
||||
if( AddPlacementToWorld( curr ) )
|
||||
@@ -1334,6 +1359,26 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
// anv: try to place tanks outdoors
|
||||
curr = gSoldierInitHead;
|
||||
while( curr && ubFreeSlots && ubMaxNum )
|
||||
{
|
||||
if( !curr->pSoldier && curr->pBasicPlacement->bTeam == ENEMY_TEAM && ubTotalTanks && !GridNoIndoors( curr->pBasicPlacement->usStartingGridNo ))
|
||||
{
|
||||
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK;
|
||||
curr->pBasicPlacement->bBodyType = TANK_NW;
|
||||
ubTotalTanks--;
|
||||
if( AddPlacementToWorld( curr ) )
|
||||
{
|
||||
ubMaxNum--;
|
||||
}
|
||||
else
|
||||
return;
|
||||
ubFreeSlots--;
|
||||
}
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
//Now, loop through the entire list again, but for the last time. All enemies will be inserted now ignoring
|
||||
//detailed placements and classes.
|
||||
curr = gSoldierInitHead;
|
||||
@@ -1362,6 +1407,12 @@ void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTr
|
||||
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ADMINISTRATOR;
|
||||
ubTotalAdmin--;
|
||||
}
|
||||
else if( iRandom < ubTotalElite + ubTotalTroops + ubTotalAdmin + ubTotalTanks )
|
||||
{
|
||||
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_TANK;
|
||||
curr->pBasicPlacement->bBodyType = TANK_NW;
|
||||
ubTotalTanks--;
|
||||
}
|
||||
else
|
||||
Assert(0);
|
||||
/* DISABLE THE OVERRIDE FOR NOW...
|
||||
|
||||
@@ -40,7 +40,7 @@ void RemoveSoldierNodeFromInitList( SOLDIERINITNODE *pNode );
|
||||
SOLDIERINITNODE* FindSoldierInitNodeWithID( UINT16 usID );
|
||||
|
||||
UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum );
|
||||
void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite );
|
||||
void AddSoldierInitListEnemyDefenceSoldiers( UINT8 ubTotalAdmin, UINT8 ubTotalTroops, UINT8 ubTotalElite, UINT8 ubTotalTanks );
|
||||
void AddSoldierInitListCreatures( BOOLEAN fQueen, UINT8 ubNumLarvae, UINT8 ubNumInfants,
|
||||
UINT8 ubNumYoungMales, UINT8 ubNumYoungFemales, UINT8 ubNumAdultMales,
|
||||
UINT8 ubNumAdultFemales );
|
||||
|
||||
+36
-32
@@ -510,24 +510,24 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
|
||||
|
||||
if( pVehicleSoldier )
|
||||
{
|
||||
if ( pVehicleSoldier->bTeam != gbPlayerNum )
|
||||
if ( pVehicleSoldier->bTeam != pSoldier->bTeam )
|
||||
{
|
||||
// Can we add a new vehicle
|
||||
if( vCount >= gGameExternalOptions.ubGameMaximumNumberOfPlayerVehicles )
|
||||
if( vCount >= gGameExternalOptions.ubGameMaximumNumberOfPlayerVehicles && pSoldier->bTeam == gbPlayerNum )
|
||||
{
|
||||
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, TacticalStr[VEHICLE_CAN_NOT_BE_ADDED] );
|
||||
return( FALSE );
|
||||
}
|
||||
|
||||
// Change sides...
|
||||
pVehicleSoldier = ChangeSoldierTeam( pVehicleSoldier, gbPlayerNum );
|
||||
pVehicleSoldier = ChangeSoldierTeam( pVehicleSoldier, pSoldier->bTeam );
|
||||
// add it to mapscreen list
|
||||
fReBuildCharacterList = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// If vehicle is empty, add to unique squad now that it has somebody in it!
|
||||
if ( GetNumberInVehicle( iId ) == 0 && pVehicleSoldier )
|
||||
if ( GetNumberInVehicle( iId ) == 0 && pVehicleSoldier && pSoldier->bTeam == gbPlayerNum )
|
||||
{
|
||||
// 2 ) Add to unique squad...
|
||||
AddCharacterToUniqueSquad( pVehicleSoldier );
|
||||
@@ -536,17 +536,17 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
|
||||
// We have now a guy on a squad group, remove him!
|
||||
RemovePlayerFromGroup( SquadMovementGroups[ pVehicleSoldier->bAssignment ], pVehicleSoldier );
|
||||
|
||||
// I really have vehicles.\
|
||||
// ONLY add to vehicle group once!
|
||||
if ( !DoesPlayerExistInPGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier ) )
|
||||
{
|
||||
//NOW.. add guy to vehicle group....
|
||||
AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier );
|
||||
}
|
||||
else
|
||||
{
|
||||
pVehicleSoldier->ubGroupID = pVehicleList[ iId ].ubMovementGroup;
|
||||
}
|
||||
// I really have vehicles.\
|
||||
// ONLY add to vehicle group once!
|
||||
if ( !DoesPlayerExistInPGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier ) )
|
||||
{
|
||||
//NOW.. add guy to vehicle group....
|
||||
AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pVehicleSoldier );
|
||||
}
|
||||
else
|
||||
{
|
||||
pVehicleSoldier->ubGroupID = pVehicleList[ iId ].ubMovementGroup;
|
||||
}
|
||||
}
|
||||
|
||||
// check if the grunt is already here
|
||||
@@ -565,7 +565,7 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
|
||||
UnSetUIBusy( pSoldier->ubID );
|
||||
|
||||
// can't call SelectSoldier in mapscreen, that will initialize interface panels!!!
|
||||
if ( guiCurrentScreen == GAME_SCREEN )
|
||||
if ( guiCurrentScreen == GAME_SCREEN && pSoldier->bTeam == gbPlayerNum )
|
||||
{
|
||||
SelectSoldier( pVehicleSoldier->ubID, FALSE, TRUE );
|
||||
}
|
||||
@@ -611,11 +611,11 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
|
||||
}
|
||||
|
||||
// if in a squad, remove from squad, if not, check if in vehicle, if so remove, if not, then check if in mvt group..if so, move and destroy group
|
||||
if( pSoldier->bAssignment < ON_DUTY )
|
||||
if( pSoldier->bTeam == gbPlayerNum && pSoldier->bAssignment < ON_DUTY )
|
||||
{
|
||||
RemoveCharacterFromSquads( pSoldier );
|
||||
}
|
||||
else if( pSoldier->ubGroupID != 0 )
|
||||
else if( pSoldier->bTeam == gbPlayerNum && pSoldier->ubGroupID != 0 )
|
||||
{
|
||||
// Flugente 2012-08-15: had very weird behaviour here. The outcommented code below failed, because the group size wasn't 0, which then threw an Assert()-error.
|
||||
// This happened in r5468 when assinging a merc on repair duty to the truck, switching back and forth between the two
|
||||
@@ -628,22 +628,26 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
|
||||
//pSoldier->ubGroupID = 0;
|
||||
}
|
||||
|
||||
if( ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iId ) )
|
||||
{
|
||||
SetTimeOfAssignmentChangeForMerc( pSoldier );
|
||||
}
|
||||
|
||||
// set thier assignment
|
||||
ChangeSoldiersAssignment( pSoldier, VEHICLE );
|
||||
|
||||
// set vehicle id
|
||||
pSoldier->iVehicleId = iId;
|
||||
|
||||
// if vehicle is part of mvt group, then add character to mvt group
|
||||
if( pVehicleList[ iId ].ubMovementGroup != 0 )
|
||||
if( pSoldier->bTeam == gbPlayerNum )
|
||||
{
|
||||
// add character
|
||||
AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pSoldier );
|
||||
|
||||
if( ( pSoldier->bAssignment != VEHICLE ) || ( pSoldier->iVehicleId != iId ) )
|
||||
{
|
||||
SetTimeOfAssignmentChangeForMerc( pSoldier );
|
||||
}
|
||||
|
||||
// set thier assignment
|
||||
ChangeSoldiersAssignment( pSoldier, VEHICLE );
|
||||
|
||||
// if vehicle is part of mvt group, then add character to mvt group
|
||||
if( pVehicleList[ iId ].ubMovementGroup != 0 )
|
||||
{
|
||||
// add character
|
||||
AddPlayerToGroup( pVehicleList[ iId ].ubMovementGroup, pSoldier );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -692,7 +696,7 @@ BOOLEAN AddSoldierToVehicle( SOLDIERTYPE *pSoldier, INT32 iId, UINT8 ubSeatIndex
|
||||
pSoldier->EVENT_StopMerc( pSoldier->sGridNo, pSoldier->ubDirection );
|
||||
|
||||
// can't call SetCurrentSquad OR SelectSoldier in mapscreen, that will initialize interface panels!!!
|
||||
if ( guiCurrentScreen == GAME_SCREEN )
|
||||
if ( pSoldier->bTeam == gbPlayerNum && guiCurrentScreen == GAME_SCREEN )
|
||||
{
|
||||
SetCurrentSquad( pVehicleSoldier->bAssignment, TRUE );
|
||||
}
|
||||
@@ -1592,7 +1596,7 @@ SOLDIERTYPE *GetDriver( INT32 iID )
|
||||
void SetDriver( INT32 iID, UINT8 ubID )
|
||||
{
|
||||
// anv: first make sure previous driver won't be driver anymore
|
||||
if( pVehicleList[ iID ].ubDriver != NOBODY )
|
||||
if( pVehicleList[ iID ].ubDriver != NOBODY && MercPtrs[ pVehicleList[ iID ].ubDriver ]->iVehicleId == iID )
|
||||
{
|
||||
if( MercPtrs[ pVehicleList[ iID ].ubDriver ] )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user