mirror of
https://github.com/1dot13/source.git
synced 2026-09-09 14:46:05 +02:00
- New Feature: Arulco special division controls other features to fight the player. For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=tree&goto=343706&#msg_343706
- New Feature: Enemy helicopters allow the AI to rapidly deploy troops aross the map. For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=tree&goto=343707&#msg_343707. GameDir <= r2279 is required. - Fix: income of mine 0 was not correctly calculated git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8015 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -3322,9 +3322,9 @@ void SayQuoteFromAnyBodyInSector( UINT16 usQuoteNum )
|
||||
void SayQuoteFromAnyBodyInThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usQuoteNum )
|
||||
{
|
||||
// WDS - make number of mercenaries, etc. be configurable
|
||||
std::vector<UINT8> ubMercsInSector (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, 0);
|
||||
UINT8 ubNumMercs = 0;
|
||||
UINT8 ubChosenMerc;
|
||||
std::vector<UINT16> ubMercsInSector (CODE_MAXIMUM_NUMBER_OF_PLAYER_SLOTS, 0);
|
||||
UINT16 ubNumMercs = 0;
|
||||
UINT16 ubChosenMerc;
|
||||
SOLDIERTYPE *pTeamSoldier;
|
||||
INT32 cnt;
|
||||
|
||||
@@ -3342,16 +3342,17 @@ void SayQuoteFromAnyBodyInThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSect
|
||||
if( pTeamSoldier->sSectorX == sSectorX && pTeamSoldier->sSectorY == sSectorY && pTeamSoldier->bSectorZ == bSectorZ && !AM_AN_EPC( pTeamSoldier ) && !( pTeamSoldier->flags.uiStatusFlags & SOLDIER_GASSED ) && !(AM_A_ROBOT( pTeamSoldier )) && !pTeamSoldier->flags.fMercAsleep )
|
||||
{
|
||||
ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
|
||||
ubNumMercs++;
|
||||
++ubNumMercs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SayQuoteFromAnyBodyInThisSector: num mercs = %d",ubNumMercs));
|
||||
|
||||
// If we are > 0
|
||||
if ( ubNumMercs > 0 )
|
||||
{
|
||||
ubChosenMerc = (UINT8)Random( ubNumMercs );
|
||||
ubChosenMerc = (UINT16)Random( ubNumMercs );
|
||||
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("SayQuoteFromAnyBodyInThisSector: chosen merc = %d",ubChosenMerc));
|
||||
|
||||
//// If we are air raid, AND red exists somewhere...
|
||||
@@ -3367,7 +3368,6 @@ void SayQuoteFromAnyBodyInThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSect
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
TacticalCharacterDialogue( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ], usQuoteNum );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,6 +175,7 @@ enum {
|
||||
BG_PERC_HEARING_NIGHT,
|
||||
BG_PERC_HEARING_DAY,
|
||||
BG_PERC_DISARM,
|
||||
BG_PERC_SAM_CTH,
|
||||
|
||||
// approaches
|
||||
BG_PERC_APPROACH_FRIENDLY,
|
||||
|
||||
@@ -731,7 +731,7 @@ extern OBJECTTYPE gTempObject;
|
||||
// flags used for various item properties (easier than adding 32 differently named variables). DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
|
||||
// note that these should not be used to determine what kind of an attachment an item is, that is determined by attachmentclass and the AC_xxx flags above
|
||||
//#define EMPTY_SANDBAG 0x00000001 //1
|
||||
//#define FULL_SANDBAG 0x00000002 //2
|
||||
#define MANPAD 0x00000002 //2 // this item is a MAn-Portable Air-Defense System
|
||||
//#define SHOVEL 0x00000004 //4 // a shovel is used for filling sandbags and other building-related tasks
|
||||
//#define CONCERTINA 0x00000008 //8
|
||||
|
||||
|
||||
+429
-1
@@ -40,6 +40,7 @@
|
||||
#include "Tactical Save.h"
|
||||
// HEADROCK HAM 3.5: Need this to see if enemies present at starting sector
|
||||
#include "Overhead.h"
|
||||
#include "Map Information.h" // added by Flugente
|
||||
#endif
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -386,6 +387,7 @@ BOOLEAN gfIngagedInDrop = FALSE;
|
||||
ANITILE *gpHeli;
|
||||
BOOLEAN gfFirstHeliRun;
|
||||
|
||||
extern BOOLEAN gfTacticalDoHeliRun;
|
||||
|
||||
void HandleFirstHeliDropOfGame( );
|
||||
|
||||
@@ -479,13 +481,16 @@ void StartHelicopterRun()
|
||||
}
|
||||
|
||||
|
||||
void HandleHeliDrop( )
|
||||
void HandleHeliDrop( BOOLEAN fPlayer )
|
||||
{
|
||||
UINT8 ubScriptCode;
|
||||
UINT32 uiClock;
|
||||
INT32 iVol;
|
||||
INT32 cnt;
|
||||
ANITILE_PARAMS AniParams;
|
||||
|
||||
if ( !fPlayer )
|
||||
return HandleEnemyAirdrop();
|
||||
|
||||
if ( gfHandleHeli )
|
||||
{
|
||||
@@ -1021,3 +1026,426 @@ void HandleFirstHeliDropOfGame( )
|
||||
// Send message to turn on ai again....
|
||||
CharacterDialogueWithSpecialEvent( 0, 0, 0, DIALOGUE_TACTICAL_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_ENABLE_AI ,0, 0 );
|
||||
}
|
||||
|
||||
UINT16 SpawnAirDropElite( INT32 sGridNo )
|
||||
{
|
||||
SOLDIERTYPE *pSoldier;
|
||||
|
||||
// not underground!
|
||||
if ( gbWorldSectorZ )
|
||||
return NOBODY;
|
||||
|
||||
// hmm...
|
||||
if ( !IsLocationSittable( sGridNo, 0 ) )
|
||||
return NOBODY;
|
||||
|
||||
// Flugente hack
|
||||
pSoldier = TacticalCreateEliteEnemy( );
|
||||
|
||||
//Add soldier strategic info, so it doesn't break the counters!
|
||||
if ( pSoldier )
|
||||
{
|
||||
if ( !gbWorldSectorZ )
|
||||
{
|
||||
SECTORINFO *pSector = &SectorInfo[SECTOR( gWorldSectorX, gWorldSectorY )];
|
||||
switch ( pSoldier->ubSoldierClass )
|
||||
{
|
||||
case SOLDIER_CLASS_ADMINISTRATOR: pSector->ubNumAdmins++; pSector->ubAdminsInBattle++; break;
|
||||
case SOLDIER_CLASS_ARMY: pSector->ubNumTroops++; pSector->ubTroopsInBattle++; break;
|
||||
case SOLDIER_CLASS_ELITE: pSector->ubNumElites++; pSector->ubElitesInBattle++; break;
|
||||
}
|
||||
}
|
||||
|
||||
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CHOPPER;
|
||||
pSoldier->usStrategicInsertionData = sGridNo; // required, otherwise soldiers will spawn in map before jumping out of the heli
|
||||
UpdateMercInSector( pSoldier, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
//AllTeamsLookForAll( NO_INTERRUPTS );
|
||||
}
|
||||
|
||||
return pSoldier->ubID;
|
||||
}
|
||||
|
||||
void InitiateEnemyAirDropSoldiers( INT32 sGridNo )
|
||||
{
|
||||
gfTacticalDoHeliRun = TRUE;
|
||||
|
||||
ResetHeliSeats( );
|
||||
|
||||
//SetHelicopterDroppoint( gMapInformation.sCenterGridNo );
|
||||
SetHelicopterDroppoint( sGridNo );
|
||||
|
||||
SetHelicopterDropDirection( WEST );
|
||||
|
||||
for ( int i = 0; i < 6; ++i )
|
||||
{
|
||||
UINT8 id = SpawnAirDropElite( gMapInformation.sSouthGridNo + i );
|
||||
|
||||
if ( id == NOBODY )
|
||||
return;
|
||||
|
||||
AddMercToHeli( id );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HandleEnemyAirdrop( )
|
||||
{
|
||||
UINT8 ubScriptCode;
|
||||
UINT32 uiClock;
|
||||
INT32 iVol;
|
||||
ANITILE_PARAMS AniParams;
|
||||
|
||||
if ( gfHandleHeli )
|
||||
{
|
||||
if ( gCurrentUIMode != LOCKUI_MODE )
|
||||
{
|
||||
guiPendingOverrideEvent = LU_BEGINUILOCK;
|
||||
}
|
||||
|
||||
gfIgnoreScrolling = TRUE;
|
||||
|
||||
uiClock = GetJA2Clock( );
|
||||
|
||||
if ( (uiClock - guiHeliLastUpdate) > ME_SCRIPT_DELAY )
|
||||
{
|
||||
guiHeliLastUpdate = uiClock;
|
||||
|
||||
if ( fFadingHeliIn )
|
||||
{
|
||||
if ( uiSoundSample != NO_SAMPLE )
|
||||
{
|
||||
iVol = SoundGetVolume( uiSoundSample );
|
||||
iVol = __min( HIGHVOLUME, iVol + 5 );
|
||||
SoundSetVolume( uiSoundSample, iVol );
|
||||
if ( iVol == HIGHVOLUME )
|
||||
fFadingHeliIn = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fFadingHeliIn = FALSE;
|
||||
}
|
||||
}
|
||||
else if ( fFadingHeliOut )
|
||||
{
|
||||
if ( uiSoundSample != NO_SAMPLE )
|
||||
{
|
||||
iVol = SoundGetVolume( uiSoundSample );
|
||||
|
||||
iVol = __max( 0, iVol - 5 );
|
||||
|
||||
SoundSetVolume( uiSoundSample, iVol );
|
||||
if ( iVol == 0 )
|
||||
{
|
||||
// Stop sound
|
||||
SoundStop( uiSoundSample );
|
||||
fFadingHeliOut = FALSE;
|
||||
gfHandleHeli = FALSE;
|
||||
gfIgnoreScrolling = FALSE;
|
||||
gbNumHeliSeatsOccupied = 0;
|
||||
guiPendingOverrideEvent = LU_ENDUILOCK;
|
||||
UnLockPauseState( );
|
||||
UnPauseGame( );
|
||||
|
||||
RebuildCurrentSquad( );
|
||||
|
||||
HandleFirstHeliDropOfGame( );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fFadingHeliOut = FALSE;
|
||||
gfHandleHeli = FALSE;
|
||||
gfIgnoreScrolling = FALSE;
|
||||
gbNumHeliSeatsOccupied = 0;
|
||||
guiPendingOverrideEvent = LU_ENDUILOCK;
|
||||
UnLockPauseState( );
|
||||
UnPauseGame( );
|
||||
|
||||
RebuildCurrentSquad( );
|
||||
|
||||
HandleFirstHeliDropOfGame( );
|
||||
}
|
||||
}
|
||||
|
||||
if ( gsHeliScript == MAX_HELI_SCRIPT )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ubScriptCode = ubHeliScripts[gubHeliState][gsHeliScript];
|
||||
|
||||
// Switch on mode...
|
||||
if ( gubHeliState == HELI_DROP )
|
||||
{
|
||||
if ( !gfIngagedInDrop )
|
||||
{
|
||||
INT8 bEndVal = (gbHeliRound * NUM_PER_HELI_RUN);
|
||||
|
||||
if ( bEndVal > gbNumHeliSeatsOccupied )
|
||||
{
|
||||
bEndVal = gbNumHeliSeatsOccupied;
|
||||
}
|
||||
|
||||
// Flugente: watching mercs rope down one by one gets boring fast. So we allow up to 3 mercs to rope down at the same time
|
||||
for ( int i = 0; i < 3; ++i )
|
||||
{
|
||||
// OK, Check if we have anybody left to send!
|
||||
if ( gbCurDrop < bEndVal )
|
||||
{
|
||||
// Flugente: it is now possible to use airdrops with soldiers after they have arrived in Arulco. In that case, they might have an animation that breaks EVENT_InitNewSoldierAnim prematurely.
|
||||
// In the worst case, this can cause the game to be unable to finish the airdrop. For that reason, we set all those soldiers to the STANDING aniamtion.
|
||||
//MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->usAnimState = STANDING;
|
||||
MercPtrs[gusHeliSeats[gbCurDrop]]->EVENT_InitNewSoldierAnim( HELIDROP, 0, FALSE );
|
||||
|
||||
// Change insertion code
|
||||
MercPtrs[gusHeliSeats[gbCurDrop]]->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
|
||||
MercPtrs[gusHeliSeats[gbCurDrop]]->usStrategicInsertionData = gsGridNoSweetSpot;
|
||||
|
||||
// HEADROCK HAM 3.5: Externalized!
|
||||
UpdateMercInSector( MercPtrs[gusHeliSeats[gbCurDrop]], gWorldSectorX, gWorldSectorY, startingZ );
|
||||
|
||||
// IF the first guy down, set squad!
|
||||
if ( gfFirstGuyDown )
|
||||
{
|
||||
gfFirstGuyDown = FALSE;
|
||||
//SetCurrentSquad( MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->bAssignment, TRUE );
|
||||
}
|
||||
ScreenMsg( FONT_MCOLOR_WHITE, MSG_INTERFACE, TacticalStr[MERC_HAS_ARRIVED_STR], MercPtrs[gusHeliSeats[gbCurDrop]]->GetName( ) );
|
||||
|
||||
++gbCurDrop;
|
||||
|
||||
gfIngagedInDrop = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( gbExitCount == 0 )
|
||||
{
|
||||
gbExitCount = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
--gbExitCount;
|
||||
|
||||
if ( gbExitCount == 1 )
|
||||
{
|
||||
// Goto leave
|
||||
gsHeliScript = -1;
|
||||
gubHeliState = HELI_ENDDROP;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ( ubScriptCode )
|
||||
{
|
||||
case HELI_REST:
|
||||
|
||||
break;
|
||||
|
||||
case HELI_MOVE_DOWN:
|
||||
|
||||
gdHeliZPos -= 1;
|
||||
gpHeli->pLevelNode->sRelativeZ = (INT16)gdHeliZPos;
|
||||
break;
|
||||
|
||||
case HELI_MOVE_UP:
|
||||
|
||||
gdHeliZPos += 1;
|
||||
gpHeli->pLevelNode->sRelativeZ = (INT16)gdHeliZPos;
|
||||
break;
|
||||
|
||||
case HELI_MOVESMALL_DOWN:
|
||||
|
||||
gdHeliZPos -= 0.25;
|
||||
gpHeli->pLevelNode->sRelativeZ = (INT16)gdHeliZPos;
|
||||
break;
|
||||
|
||||
case HELI_MOVESMALL_UP:
|
||||
|
||||
gdHeliZPos += 0.25;
|
||||
gpHeli->pLevelNode->sRelativeZ = (INT16)gdHeliZPos;
|
||||
break;
|
||||
|
||||
|
||||
case HELI_MOVEY:
|
||||
|
||||
if ( gHeliEnterDirection == SOUTH )
|
||||
{
|
||||
gpHeli->sRelativeY -= 4;
|
||||
}
|
||||
else if ( gHeliEnterDirection == EAST )
|
||||
{
|
||||
gpHeli->sRelativeX -= 4;
|
||||
gpHeli->sRelativeY -= 1;
|
||||
}
|
||||
else if ( gHeliEnterDirection == WEST )
|
||||
{
|
||||
gpHeli->sRelativeX += 4;
|
||||
gpHeli->sRelativeY += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpHeli->sRelativeY += 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case HELI_MOVELARGERY:
|
||||
|
||||
if ( gHeliEnterDirection == SOUTH )
|
||||
{
|
||||
gpHeli->sRelativeY -= 6;
|
||||
}
|
||||
else if ( gHeliEnterDirection == EAST )
|
||||
{
|
||||
gpHeli->sRelativeX -= 6;
|
||||
gpHeli->sRelativeY -= 1;
|
||||
}
|
||||
else if ( gHeliEnterDirection == WEST )
|
||||
{
|
||||
gpHeli->sRelativeX += 6;
|
||||
gpHeli->sRelativeY += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpHeli->sRelativeY += 6;
|
||||
}
|
||||
break;
|
||||
|
||||
case HELI_GOTO_BEGINDROP:
|
||||
|
||||
gsHeliScript = -1;
|
||||
gubHeliState = HELI_BEGINDROP;
|
||||
break;
|
||||
|
||||
case HELI_SHOW_HELI:
|
||||
|
||||
// Start animation
|
||||
memset( &AniParams, 0, sizeof(ANITILE_PARAMS) );
|
||||
AniParams.sGridNo = gsGridNoSweetSpot;
|
||||
AniParams.ubLevelID = ANI_SHADOW_LEVEL;
|
||||
AniParams.sDelay = 90;
|
||||
AniParams.sStartFrame = 0;
|
||||
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_LOOPING;
|
||||
AniParams.sX = gsHeliXPos;
|
||||
AniParams.sY = gsHeliYPos;
|
||||
AniParams.sZ = (INT16)gdHeliZPos;
|
||||
|
||||
if ( gHeliEnterDirection == SOUTH )
|
||||
{
|
||||
strcpy( AniParams.zCachedFile, "TILECACHE\\HELI_SH_SOUTH.STI" );
|
||||
}
|
||||
else if ( gHeliEnterDirection == EAST )
|
||||
{
|
||||
strcpy( AniParams.zCachedFile, "TILECACHE\\HELI_SH_EAST.STI" );
|
||||
}
|
||||
else if ( gHeliEnterDirection == WEST )
|
||||
{
|
||||
strcpy( AniParams.zCachedFile, "TILECACHE\\HELI_SH_WEST.STI" );
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy( AniParams.zCachedFile, "TILECACHE\\HELI_SH.STI" );
|
||||
}
|
||||
|
||||
gpHeli = CreateAnimationTile( &AniParams );
|
||||
break;
|
||||
|
||||
case HELI_GOTO_DROP:
|
||||
|
||||
// Goto drop animation
|
||||
gdHeliZPos -= 0.25;
|
||||
gpHeli->pLevelNode->sRelativeZ = (INT16)gdHeliZPos;
|
||||
gsHeliScript = -1;
|
||||
gubHeliState = HELI_DROP;
|
||||
break;
|
||||
|
||||
case HELI_GOTO_MOVETO:
|
||||
|
||||
// Goto drop animation
|
||||
gsHeliScript = -1;
|
||||
gubHeliState = HELI_MOVETO;
|
||||
break;
|
||||
|
||||
case HELI_GOTO_MOVEAWAY:
|
||||
|
||||
// Goto drop animation
|
||||
gsHeliScript = -1;
|
||||
gubHeliState = HELI_MOVEAWAY;
|
||||
break;
|
||||
|
||||
case HELI_GOTO_EXIT:
|
||||
|
||||
if ( gbCurDrop < gbNumHeliSeatsOccupied )
|
||||
{
|
||||
// Start another run......
|
||||
INT16 sX, sY;
|
||||
|
||||
ConvertGridNoToCenterCellXY( gsGridNoSweetSpot, &sX, &sY );
|
||||
|
||||
if ( gHeliEnterDirection == SOUTH )
|
||||
{
|
||||
gsHeliXPos = sX - (2 * CELL_X_SIZE);
|
||||
gsHeliYPos = sY + (10 * CELL_Y_SIZE);
|
||||
}
|
||||
else if ( gHeliEnterDirection == EAST )
|
||||
{
|
||||
gsHeliXPos = sX + (10 * CELL_X_SIZE);
|
||||
gsHeliYPos = sY + (2 * CELL_Y_SIZE);
|
||||
}
|
||||
else if ( gHeliEnterDirection == WEST )
|
||||
{
|
||||
gsHeliXPos = sX - (10 * CELL_X_SIZE);
|
||||
gsHeliYPos = sY - (2 * CELL_Y_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
gsHeliXPos = sX - (2 * CELL_X_SIZE);
|
||||
gsHeliYPos = sY - (10 * CELL_Y_SIZE);
|
||||
}
|
||||
|
||||
gdHeliZPos = 0;
|
||||
gsHeliScript = 0;
|
||||
gbExitCount = 0;
|
||||
gubHeliState = HELI_APPROACH;
|
||||
++gbHeliRound;
|
||||
|
||||
// Ahh, but still delete the heli!
|
||||
DeleteAniTile( gpHeli );
|
||||
gpHeli = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Goto drop animation
|
||||
gsHeliScript = -1;
|
||||
gubHeliState = HELI_EXIT;
|
||||
|
||||
// Delete helicopter image!
|
||||
DeleteAniTile( gpHeli );
|
||||
gpHeli = NULL;
|
||||
gfIgnoreScrolling = FALSE;
|
||||
|
||||
// Select our first guy
|
||||
SelectSoldier( gusHeliSeats[0], FALSE, TRUE );
|
||||
}
|
||||
break;
|
||||
|
||||
case HELI_DONE:
|
||||
|
||||
// End
|
||||
fFadingHeliOut = TRUE;
|
||||
|
||||
// HEADROCK HAM 3.5: Update now, in case the LZ is still in a "RED" airspace sector. This is only
|
||||
// required if the sector is free of enemies... but still required. Will run immediately after the
|
||||
// helicopter is gone.
|
||||
UpdateAirspaceControl( );
|
||||
break;
|
||||
}
|
||||
|
||||
++gsHeliScript;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ enum
|
||||
UNNAMED_CIV_GROUP_23,
|
||||
VOLUNTEER_CIV_GROUP, // Flugente: civilians that the player recruited
|
||||
BOUNTYHUNTER_CIV_GROUP, // Flugente: hostile bounty hunters
|
||||
UNNAMED_CIV_GROUP_26,
|
||||
DOWNEDPILOT_CIV_GROUP, // Flugente: downed pilots
|
||||
UNNAMED_CIV_GROUP_27,
|
||||
UNNAMED_CIV_GROUP_28,
|
||||
UNNAMED_CIV_GROUP_29,
|
||||
|
||||
@@ -6829,7 +6829,8 @@ void RemoveCapturedEnemiesFromSectorInfo( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
|
||||
// officers and generals are 'special' prisoners...
|
||||
if ( pTeamSoldier->usSoldierFlagMask & SOLDIER_VIP )
|
||||
++sNumPrisoner[PRISONER_GENERAL];
|
||||
else if ( pTeamSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER )
|
||||
// downed pilots count as officers too, even though they are civilians. This makes capturing them more rewarding
|
||||
else if ( (pTeamSoldier->usSoldierFlagMask & SOLDIER_ENEMY_OFFICER) || pTeamSoldier->ubCivilianGroup == DOWNEDPILOT_CIV_GROUP )
|
||||
++sNumPrisoner[PRISONER_OFFICER];
|
||||
else if ( pTeamSoldier->bTeam == ENEMY_TEAM )
|
||||
{
|
||||
|
||||
+10
-12
@@ -2826,28 +2826,27 @@ BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos )
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DeductAmmo( SOLDIERTYPE *pSoldier, INT8 bInvPos )
|
||||
{
|
||||
OBJECTTYPE * pObj;
|
||||
return DeductAmmo( pSoldier, &(pSoldier->inv[bInvPos]) );
|
||||
}
|
||||
|
||||
// tanks never run out of MG ammo!
|
||||
// unlimited cannon ammo is handled in AI
|
||||
if ( TANK( pSoldier ) && !Item[pSoldier->inv[bInvPos].usItem].cannon )
|
||||
void DeductAmmo( SOLDIERTYPE *pSoldier, OBJECTTYPE* pObj )
|
||||
{
|
||||
if ( pSoldier && pObj->exists( ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
// tanks never run out of MG ammo!
|
||||
// unlimited cannon ammo is handled in AI
|
||||
if ( TANK( pSoldier ) && !Item[pObj->usItem].cannon )
|
||||
return;
|
||||
|
||||
pObj = &(pSoldier->inv[ bInvPos ]);
|
||||
if ( pObj->exists() == true )
|
||||
{
|
||||
if ( Item[pObj->usItem].cannon )
|
||||
{
|
||||
}
|
||||
else if ( Item[ pObj->usItem ].usItemClass == IC_GUN && !Item[pObj->usItem].cannon && pSoldier->bWeaponMode != WM_ATTACHED_GL && pSoldier->bWeaponMode != WM_ATTACHED_GL_BURST && pSoldier->bWeaponMode != WM_ATTACHED_GL_AUTO )
|
||||
{
|
||||
// Flugente: check for underbarrel weapons and use that object if necessary
|
||||
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( &(pSoldier->inv[bInvPos]) );
|
||||
OBJECTTYPE* pObjUsed = pSoldier->GetUsedWeapon( pObj );
|
||||
|
||||
// Flugente: external feeding allows us to take ammo from somewhere other than our magazine, like a belt in our inventory our even another mercs
|
||||
if ( gGameExternalOptions.ubExternalFeeding > 0 )
|
||||
@@ -2921,7 +2920,6 @@ void DeductAmmo( SOLDIERTYPE *pSoldier, INT8 bInvPos )
|
||||
|
||||
// Dirty Bars
|
||||
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL1 );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -300,7 +300,7 @@ UINT16 CalculateRaiseGunCost(SOLDIERTYPE *pSoldier, BOOLEAN fAddingRaiseGunCost,
|
||||
INT16 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT32 sGridNo, INT16 bAimTime, UINT8 ubAddTurningCost, UINT8 ubForceRaiseGunCost = 0 );
|
||||
BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos );
|
||||
void DeductAmmo( SOLDIERTYPE *pSoldier, INT8 bInvPos );
|
||||
|
||||
void DeductAmmo( SOLDIERTYPE *pSoldier, OBJECTTYPE* pObj );
|
||||
|
||||
UINT16 GetAPsToPickupItem( SOLDIERTYPE *pSoldier, INT32 usMapPos );
|
||||
INT16 MinAPsToPunch(SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT8 ubAddTurningCost );
|
||||
|
||||
@@ -391,7 +391,7 @@ enum
|
||||
#define SOLDIER_ENEMY_OBSERVEDTHISTURN 0x08000000 //134217728 // enemy soldier was seen by the player this turn
|
||||
|
||||
#define SOLDIER_VIP 0x10000000 //268435456 // soldier is a VIP - the player will likely try to assassinate him
|
||||
#define SOLDIER_BODYGUARD 0x20000000 //536870912 // soldier is a bodyguard for a VIP/*
|
||||
#define SOLDIER_BODYGUARD 0x20000000 //536870912 // soldier is a bodyguard for a VIP
|
||||
#define SOLDIER_COVERT_TEMPORARY_OVERT 0x40000000 //1073741824 // we are covert, but just performed a obviously suspicious task. For a short time, we can be uncovered more easily
|
||||
#define SOLDIER_MOVEITEM_RESTRICTED 0x80000000 //2147483648 // when moving item, this soldier will not pick up equipment the militia might use
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@@ -3609,6 +3609,81 @@ void CreatePrisonerOfWar()
|
||||
}
|
||||
}
|
||||
|
||||
// create a downed pilot in a random location in the current sector
|
||||
void CreateDownedPilot( )
|
||||
{
|
||||
UINT8 tries = 0;
|
||||
INT32 sGridNo = NOWHERE;
|
||||
do
|
||||
{
|
||||
if ( ++tries > 20 )
|
||||
return;
|
||||
|
||||
sGridNo = RandomGridNo( );
|
||||
}
|
||||
// a valid starting gridno must be valid, not in a structure, not in water, and not too near to our mercs
|
||||
while ( TileIsOutOfBounds( sGridNo ) || FindStructure( sGridNo, STRUCTURE_BLOCKSMOVES ) || TERRAIN_IS_WATER( gpWorldLevelData[sGridNo].ubTerrainID ) || GridNoNearPlayerMercs( sGridNo, 25 ) );
|
||||
|
||||
SOLDIERCREATE_STRUCT MercCreateStruct;
|
||||
UINT8 ubID;
|
||||
|
||||
MercCreateStruct.initialize( );
|
||||
MercCreateStruct.bTeam = CIV_TEAM;
|
||||
MercCreateStruct.ubProfile = NO_PROFILE;
|
||||
MercCreateStruct.sSectorX = gWorldSectorX;
|
||||
MercCreateStruct.sSectorY = gWorldSectorY;
|
||||
MercCreateStruct.bSectorZ = gbWorldSectorZ;
|
||||
MercCreateStruct.sInsertionGridNo = sGridNo;
|
||||
MercCreateStruct.ubDirection = Random( NUM_WORLD_DIRECTIONS );
|
||||
MercCreateStruct.ubBodyType = Random( ADULTFEMALEMONSTER );
|
||||
|
||||
RandomizeNewSoldierStats( &MercCreateStruct );
|
||||
|
||||
SOLDIERTYPE* pSoldier = TacticalCreateSoldier( &MercCreateStruct, &ubID );
|
||||
|
||||
if ( pSoldier )
|
||||
{
|
||||
// a downed pilot might be wounded
|
||||
pSoldier->stats.bLife = min( pSoldier->stats.bLifeMax, max( OKLIFE + 20, pSoldier->stats.bLife - 20 ) );
|
||||
pSoldier->bBleeding = pSoldier->stats.bLifeMax - pSoldier->stats.bLife;
|
||||
|
||||
AddSoldierToSector( pSoldier->ubID );
|
||||
|
||||
// set correct civ group
|
||||
pSoldier->ubCivilianGroup = DOWNEDPILOT_CIV_GROUP;
|
||||
|
||||
// make him wear administrator uniform
|
||||
UINT16 usPaletteAnimSurface = LoadSoldierAnimationSurface( pSoldier, pSoldier->usAnimState );
|
||||
|
||||
if ( usPaletteAnimSurface != INVALID_ANIMATION_SURFACE )
|
||||
{
|
||||
SET_PALETTEREP_ID( pSoldier->VestPal, gUniformColors[UNIFORM_ENEMY_ADMIN].vest );
|
||||
SET_PALETTEREP_ID( pSoldier->PantsPal, gUniformColors[UNIFORM_ENEMY_ADMIN].pants );
|
||||
|
||||
// Use palette from HVOBJECT, then use substitution for pants, etc
|
||||
memcpy( pSoldier->p8BPPPalette, gAnimSurfaceDatabase[usPaletteAnimSurface].hVideoObject->pPaletteEntry, sizeof(pSoldier->p8BPPPalette) * 256 );
|
||||
|
||||
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->HeadPal );
|
||||
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->VestPal );
|
||||
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->PantsPal );
|
||||
SetPaletteReplacement( pSoldier->p8BPPPalette, pSoldier->SkinPal );
|
||||
|
||||
pSoldier->CreateSoldierPalettes( );
|
||||
|
||||
// Dirty
|
||||
fInterfacePanelDirty = DIRTYLEVEL2;
|
||||
}
|
||||
|
||||
// So we can see them!
|
||||
AllTeamsLookForAll( NO_INTERRUPTS );
|
||||
|
||||
// downed pilots are hostile, even though they stand no chance against us
|
||||
gTacticalStatus.fCivGroupHostile[POW_PRISON_CIV_GROUP] = CIV_GROUP_HOSTILE;
|
||||
|
||||
pSoldier->aiData.bNeutral = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void RandomizeRelativeLevel( INT8 *pbRelLevel, UINT8 ubSoldierClass )
|
||||
{
|
||||
UINT8 ubLocationModifier = 0;
|
||||
|
||||
@@ -457,6 +457,9 @@ void CreateAssassin(UINT8 disguisetype);
|
||||
// create a prisoner (in a prison cell) in the current sector
|
||||
void CreatePrisonerOfWar();
|
||||
|
||||
// create a downed pilot in a random location in the current sector
|
||||
void CreateDownedPilot();
|
||||
|
||||
// randomly generates a relative level rating (attributes or equipment)
|
||||
void RandomizeRelativeLevel( INT8 *pbRelLevel, UINT8 ubSoldierClass );
|
||||
|
||||
|
||||
@@ -954,6 +954,8 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
|
||||
{
|
||||
SectorAddPrisonersofWar(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
|
||||
|
||||
SectorAddDownedPilot( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
|
||||
LuaHandleSectorTacticalEntry( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
}
|
||||
|
||||
@@ -1009,6 +1011,8 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
|
||||
{
|
||||
SectorAddPrisonersofWar(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
|
||||
|
||||
SectorAddDownedPilot( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
|
||||
LuaHandleSectorTacticalEntry( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
|
||||
}
|
||||
|
||||
@@ -3049,3 +3053,28 @@ void SectorAddPrisonersofWar( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: decide wether to add a downed pilot if a helicopter was shot down here
|
||||
void SectorAddDownedPilot( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
|
||||
{
|
||||
// not in underground sectors
|
||||
if ( sMapZ > 0 )
|
||||
return;
|
||||
|
||||
// get sector
|
||||
SECTORINFO *pSector = &SectorInfo[SECTOR( sMapX, sMapY )];
|
||||
if ( !pSector )
|
||||
return;
|
||||
|
||||
if ( pSector->usSectorInfoFlag & SECTORINFO_ENEMYHELI_SHOTDOWN )
|
||||
{
|
||||
// it is likely that a pilot has survived, but not guaranteed
|
||||
if ( Chance( 75 ) )
|
||||
{
|
||||
CreateDownedPilot();
|
||||
}
|
||||
|
||||
// remove the flag. We can only find the pilot the first time we visit this sector after the heli was shut down
|
||||
pSector->usSectorInfoFlag &= ~SECTORINFO_ENEMYHELI_SHOTDOWN;
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ void SectorAddAssassins( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
|
||||
// Flugente: decide wether to create prisoners of war in a sector. Not to be confused with player POWs
|
||||
void SectorAddPrisonersofWar( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
|
||||
|
||||
// Flugente: add script-defined civilians if Lua functions say so
|
||||
void SectorAddLuaCivilians( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
|
||||
// Flugente: decide wether to add a downed pilot if a helicopter was shot down here
|
||||
void SectorAddDownedPilot( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
|
||||
|
||||
#endif
|
||||
@@ -117,6 +117,7 @@ backgroundStartElementHandle(void *userData, const XML_Char *name, const XML_Cha
|
||||
strcmp(name, "hearing_night") == 0 ||
|
||||
strcmp(name, "hearing_day") == 0 ||
|
||||
strcmp(name, "disarm_trap") == 0 ||
|
||||
strcmp(name, "SAM_cth" ) == 0 ||
|
||||
strcmp(name, "approach_friendly") == 0 ||
|
||||
strcmp(name, "approach_direct") == 0 ||
|
||||
strcmp(name, "approach_threaten") == 0 ||
|
||||
@@ -486,6 +487,11 @@ backgroundEndElementHandle(void *userData, const XML_Char *name)
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curBackground.value[BG_PERC_DISARM] = min( 50, max( -50, (INT16)atol( pData->szCharData ) ) );
|
||||
}
|
||||
else if ( strcmp( name, "SAM_cth" ) == 0 )
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
pData->curBackground.value[BG_PERC_SAM_CTH] = min( 100, max( -50, (INT16)atol( pData->szCharData ) ) );
|
||||
}
|
||||
else if(strcmp(name, "approach_friendly") == 0)
|
||||
{
|
||||
pData->curElement = ELEMENT;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _MERC_ENTRING_H
|
||||
#define _MERC_ENTRING_H
|
||||
|
||||
extern BOOLEAN gfIngagedInDrop;
|
||||
|
||||
void ResetHeliSeats( );
|
||||
void AddMercToHeli( UINT8 ubID );
|
||||
@@ -11,9 +12,12 @@ void SetHelicopterDropDirection( UINT8 usDirection );
|
||||
|
||||
void StartHelicopterRun();
|
||||
|
||||
void HandleHeliDrop( );
|
||||
void HandleHeliDrop( BOOLEAN fPlayer = TRUE );
|
||||
|
||||
extern BOOLEAN gfIngagedInDrop;
|
||||
UINT16 SpawnAirDropElite( INT32 sGridNo );
|
||||
|
||||
void InitiateEnemyAirDropSoldiers( INT32 sGridNo );
|
||||
void HandleEnemyAirdrop( );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user