mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
Added missing #includes Added LUA scripting and console Changed the way tracers are visualized, so they work more like real tracers instead of a light fountain Fixed signedness of many grid variables used in GetMouseMapPos calls Fixed enemy weapon choosing: Sometimes a mortar is chosen but later rejected, but the grenade class was not reset. Caused assertion failure Added checks so enemies don't try to chuck RPG grenades with their hands Now possible to shoot a someone in the head if he's in water Fixed InitSightArrays to also clear soldier interrupt duel points. This was causing an assertion failure elsewhere in the code because the interrupt list still had soldiers on it sometimes when this function was called. Soldiers are much less willing to forfeit their turn over an attempt to use more APs than they have Removed early setting of muzzle flash. This would allow enemies to get an interrupt before you even fired. Fixed item dropping by AI. If AI tried to drop something while standing it would cause deadlock Change to greatly speed up closing the sector inventory window in an unloaded sector Added conditional compile flag to always give robot weapon ready advantage, even for 360 degree sighting Check builddefines.h for the conditional flags. Of greatest interest might be LUA_CONSOLE. This will cause the game to bring up a command console when run. However this console is severely lacking in many areas. If anybody knows of an open-source terminal/console that could be used instead, it would be appreciated. The existing console does bad things when you try to close it, and since it counts as a separate app, it pauses the game while it has focus. LUA scripting is very limited, basically just proof of concept. There is one global variable, the Soldiers array. An array index gives you the soldier in that slot in the currently loaded sector. The soldier has a few things that can be accessed: name (short name); fullname (long name); grid (current grid #, can be changed); walkto(grid) (function to walk to another grid); runto(grid) (function to run to another grid) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@924 3b4a5df2-a311-0410-b5c6-a8a6f20db521
1602 lines
45 KiB
C++
1602 lines
45 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Tactical All.h"
|
|
#include "PreBattle Interface.h"
|
|
#else
|
|
#include "sgp.h"
|
|
#include "air raid.h"
|
|
#include "game event hook.h"
|
|
#include "game clock.h"
|
|
#include "auto bandage.h"
|
|
#include "strategicmap.h"
|
|
#include "PreBattle Interface.h"
|
|
#include "screenids.h"
|
|
#include "jascreens.h"
|
|
#include "random.h"
|
|
#include "overhead types.h"
|
|
#include "sound control.h"
|
|
#include "timer control.h"
|
|
#include "dialogue control.h"
|
|
#include "overhead.h"
|
|
#include "message.h"
|
|
#include "isometric utils.h"
|
|
#include "soldier macros.h"
|
|
#include "worldman.h"
|
|
#include "los.h"
|
|
#include "math.h"
|
|
#include "explosion control.h"
|
|
#include "interface.h"
|
|
#include "music control.h"
|
|
#include "Campaign Types.h"
|
|
#include "GameSettings.h"
|
|
#include "text.h"
|
|
#include "Morale.h"
|
|
#include "Map screen helicopter.h"
|
|
#include "structure wrap.h"
|
|
#include "meanwhile.h"
|
|
#endif
|
|
|
|
#define SCRIPT_DELAY 10
|
|
#define AIR_RAID_SAY_QUOTE_TIME 3000
|
|
#define AIR_RAID_DIVE_INTERVAL 10000
|
|
#define RAID_DELAY 40
|
|
#define TIME_FROM_DIVE_SOUND_TO_ATTACK_DELAY 8000
|
|
#define TIME_FROM_BOMB_SOUND_TO_ATTACK_DELAY 3000
|
|
#define MOVE_X 5
|
|
#define MOVE_Y 5
|
|
#define STRAFE_DIST 80
|
|
#define BOMB_DIST 150
|
|
|
|
|
|
|
|
// BEGIN SERALIZATION
|
|
extern INT32 giTimerAirRaidQuote;
|
|
extern INT32 giTimerAirRaidDiveStarted;
|
|
extern INT32 giTimerAirRaidUpdate;
|
|
|
|
BOOLEAN gfInAirRaid = FALSE;
|
|
BOOLEAN gfAirRaidScheduled = FALSE;
|
|
UINT8 gubAirRaidMode;
|
|
UINT32 guiSoundSample;
|
|
UINT32 guiRaidLastUpdate;
|
|
BOOLEAN gfFadingRaidIn = FALSE;
|
|
BOOLEAN gfQuoteSaid = FALSE;
|
|
INT8 gbNumDives = 0;
|
|
INT8 gbMaxDives = 0;
|
|
BOOLEAN gfFadingRaidOut = FALSE;
|
|
INT16 gsDiveX;
|
|
INT16 gsDiveY;
|
|
INT16 gsDiveTargetLocation;
|
|
UINT8 gubDiveDirection;
|
|
INT16 gsNumGridNosMoved;
|
|
INT32 giNumTurnsSinceLastDive;
|
|
INT32 giNumTurnsSinceDiveStarted;
|
|
INT32 giNumGridNosMovedThisTurn;
|
|
BOOLEAN gfAirRaidHasHadTurn = FALSE;
|
|
UINT8 gubBeginTeamTurn = 0;
|
|
BOOLEAN gfHaveTBBatton = FALSE;
|
|
INT16 gsNotLocatedYet = FALSE;
|
|
extern INT32 giNumFrames; // symbol already defined in video.cpp (jonathanl)
|
|
|
|
AIR_RAID_DEFINITION gAirRaidDef;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
BOOLEAN fInAirRaid;
|
|
BOOLEAN fAirRaidScheduled;
|
|
UINT8 ubAirRaidMode;
|
|
UINT32 uiSoundSample;
|
|
UINT32 uiRaidLastUpdate;
|
|
BOOLEAN fFadingRaidIn;
|
|
BOOLEAN fQuoteSaid;
|
|
INT8 bNumDives;
|
|
INT8 bMaxDives;
|
|
BOOLEAN fFadingRaidOut;
|
|
INT16 sDiveX;
|
|
INT16 sDiveY;
|
|
INT16 sDiveTargetLocation;
|
|
UINT8 ubDiveDirection;
|
|
INT16 sNumGridNosMoved;
|
|
INT32 iNumTurnsSinceLastDive;
|
|
INT32 iNumTurnsSinceDiveStarted;
|
|
INT32 iNumGridNosMovedThisTurn;
|
|
BOOLEAN fAirRaidHasHadTurn;
|
|
UINT8 ubBeginTeamTurn;
|
|
BOOLEAN fHaveTBBatton;
|
|
AIR_RAID_DEFINITION AirRaidDef;
|
|
INT16 sRaidSoldierID;
|
|
|
|
INT16 sNotLocatedYet;
|
|
INT32 iNumFrames;
|
|
|
|
INT8 bLevel;
|
|
INT8 bTeam;
|
|
INT8 bSide;
|
|
UINT8 ubAttackerID;
|
|
UINT16 usAttackingWeapon;
|
|
FLOAT dXPos;
|
|
FLOAT dYPos;
|
|
INT16 sX;
|
|
INT16 sY;
|
|
INT16 sGridNo;
|
|
|
|
|
|
UINT8 ubFiller[ 32 ];
|
|
|
|
} AIR_RAID_SAVE_STRUCT;
|
|
|
|
|
|
// END SERIALIZATION
|
|
SOLDIERTYPE *gpRaidSoldier;
|
|
|
|
|
|
typedef struct
|
|
{
|
|
INT8 bDir1;
|
|
INT8 bDir2;
|
|
|
|
} AIR_RAID_DIR;
|
|
|
|
typedef struct
|
|
{
|
|
INT8 bX;
|
|
INT8 bY;
|
|
|
|
} AIR_RAID_POS;
|
|
|
|
|
|
AIR_RAID_DIR ubPerpDirections[ ] =
|
|
{
|
|
2, 6,
|
|
3, 7,
|
|
0, 4,
|
|
1, 5,
|
|
2, 6,
|
|
3, 7,
|
|
0, 4,
|
|
1, 5
|
|
};
|
|
|
|
AIR_RAID_POS ubXYTragetInvFromDirection[ ] =
|
|
{
|
|
0, -1,
|
|
1, -1,
|
|
1, 0,
|
|
1, 1,
|
|
0, 1,
|
|
-1, 1,
|
|
-1, 0,
|
|
-1, -1
|
|
};
|
|
|
|
|
|
|
|
void ScheduleAirRaid( AIR_RAID_DEFINITION *pAirRaidDef )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"ScheduleAirRaid");
|
|
// Make sure only one is cheduled...
|
|
//if ( gfAirRaidScheduled )
|
|
//{
|
|
// return;
|
|
//}
|
|
|
|
// Copy definiaiotn structure into global struct....
|
|
memcpy( &gAirRaidDef, pAirRaidDef, sizeof( AIR_RAID_DEFINITION ) );
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("ScheduleAirRaid: raid scheduled for %d",GetWorldMinutesInDay() + pAirRaidDef->ubNumMinsFromCurrentTime ));
|
|
AddSameDayStrategicEvent( EVENT_BEGIN_AIR_RAID, ( GetWorldMinutesInDay() + pAirRaidDef->ubNumMinsFromCurrentTime ), 0 );
|
|
|
|
gfAirRaidScheduled = TRUE;
|
|
}
|
|
|
|
|
|
BOOLEAN BeginAirRaid( )
|
|
{
|
|
INT32 cnt=0;
|
|
BOOLEAN fOK = FALSE;
|
|
SOLDIERTYPE *pSoldier;
|
|
gfQuoteSaid = FALSE;
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"BeginAirRaid");
|
|
|
|
// OK, we have been told to start.....
|
|
|
|
// First remove scheduled flag...
|
|
gfAirRaidScheduled = FALSE;
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"BeginAirRaid: UpdateAirspaceControl");
|
|
UpdateAirspaceControl ();
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"BeginAirRaid: WillAirRaidBeStopped");
|
|
if( WillAirRaidBeStopped( gAirRaidDef.sSectorX, gAirRaidDef.sSectorY ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
// CHECK IF WE CURRENTLY HAVE THIS SECTOR OPEN....
|
|
/*if ( gAirRaidDef.sSectorX == gWorldSectorX &&
|
|
gAirRaidDef.sSectorY == gWorldSectorY &&
|
|
gAirRaidDef.sSectorZ == gbWorldSectorZ )
|
|
*/
|
|
// Do we have any guys in here...
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginAirRaid: check for mercs: first id = %d, last id = %d ",gTacticalStatus.Team[ gbPlayerNum ].bFirstID, gTacticalStatus.Team[ gbPlayerNum ].bLastID));
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( cnt = 0, pSoldier = MercPtrs[ cnt ]; cnt < gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++)
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginAirRaid: soldier id = %d, active = %d",pSoldier->ubID,pSoldier->bActive));
|
|
if ( pSoldier->bActive )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginAirRaid: soldier sectors: x = %d, y = %d, z = %d",pSoldier->sSectorX,pSoldier->sSectorY,pSoldier->bSectorZ ));
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginAirRaid: air raid sectors: x = %d, y = %d, z = %d",gAirRaidDef.sSectorX,gAirRaidDef.sSectorY,gAirRaidDef.sSectorZ ));
|
|
if( pSoldier->sSectorX == gAirRaidDef.sSectorX && pSoldier->sSectorY == gAirRaidDef.sSectorY && pSoldier->bSectorZ == gAirRaidDef.sSectorZ && !pSoldier->fBetweenSectors && pSoldier->bLife && pSoldier->bAssignment != IN_TRANSIT )
|
|
{
|
|
fOK = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"BeginAirRaid: do we have some guys in this sector?");
|
|
if ( !fOK )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"BeginAirRaid: no we don't");
|
|
return( FALSE );
|
|
}
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"BeginAirRaid: in pre-battle interface?");
|
|
// ( unless we are in prebattle interface, then ignore... )
|
|
if ( gfPreBattleInterfaceActive )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"BeginAirRaid: change to the right sector");
|
|
ChangeSelectedMapSector( gAirRaidDef.sSectorX, gAirRaidDef.sSectorY, ( INT8 )gAirRaidDef.sSectorZ );
|
|
gfQuoteSaid = FALSE;
|
|
|
|
if ( gAirRaidDef.sSectorX != gWorldSectorX ||
|
|
gAirRaidDef.sSectorY != gWorldSectorY ||
|
|
gAirRaidDef.sSectorZ != gbWorldSectorZ || guiCurrentScreen == MAP_SCREEN )
|
|
{
|
|
// sector not loaded
|
|
// Set flag for handling raid....
|
|
gubAirRaidMode = AIR_RAID_TRYING_TO_START;
|
|
gfQuoteSaid = TRUE;
|
|
SayQuoteFromAnyBodyInThisSector( gAirRaidDef.sSectorX, gAirRaidDef.sSectorY, ( INT8 )gAirRaidDef.sSectorZ, QUOTE_AIR_RAID );
|
|
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_EXIT_MAP_SCREEN, gAirRaidDef.sSectorX, gAirRaidDef.sSectorY, gAirRaidDef.sSectorZ, 0,0 );
|
|
}
|
|
else
|
|
{
|
|
gubAirRaidMode = AIR_RAID_TRYING_TO_START;
|
|
gfQuoteSaid = FALSE;
|
|
}
|
|
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Incoming Air Strike!" );
|
|
LockPauseState ( 22 );
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginAirRaid: setting flags, quote said = %d",gfQuoteSaid));
|
|
// Set flag for handling raid....
|
|
gfInAirRaid = TRUE;
|
|
giNumFrames = 0;
|
|
|
|
|
|
|
|
guiRaidLastUpdate = GetJA2Clock( );
|
|
|
|
|
|
gbNumDives = 0;
|
|
gfAirRaidHasHadTurn = FALSE;
|
|
|
|
gpRaidSoldier = MercPtrs[ MAX_NUM_SOLDIERS - 1 ];
|
|
memset( gpRaidSoldier, 0, sizeof( SOLDIERTYPE ) );
|
|
gpRaidSoldier->bLevel = 0;
|
|
gpRaidSoldier->bTeam = 1;
|
|
gpRaidSoldier->bSide = 1;
|
|
gpRaidSoldier->ubID = MAX_NUM_SOLDIERS - 1;
|
|
gpRaidSoldier->ubAttackerID = NOBODY;
|
|
gpRaidSoldier->usAttackingWeapon = HK21E;
|
|
gpRaidSoldier->inv[HANDPOS].usItem = HK21E;
|
|
|
|
// Determine how many dives this one will be....
|
|
gbMaxDives = (INT8)( gAirRaidDef.bIntensity + Random( gAirRaidDef.bIntensity - 1 ) );
|
|
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Begin Air Raid." );
|
|
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"BeginAirRaid: done");
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
INT16 PickLocationNearAnyMercInSector( )
|
|
{
|
|
UINT8 ubMercsInSector[ 20 ] = { 0 };
|
|
UINT8 ubNumMercs = 0;
|
|
UINT8 ubChosenMerc;
|
|
SOLDIERTYPE *pTeamSoldier;
|
|
INT32 cnt=0;
|
|
|
|
// Loop through all our guys and randomly say one from someone in our sector
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"PickLocationNearAnyMercInSector");
|
|
|
|
// set up soldier ptr as first element in mercptrs list
|
|
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
|
|
// run through list
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("PickLocationNearAnyMercInSector: total guys = %d", gTacticalStatus.Team[ gbPlayerNum ].bLastID));
|
|
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
|
|
{
|
|
// Add guy if he's a candidate...
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("PickLocationNearAnyMercInSector: looping %d",cnt));
|
|
if ( OK_INSECTOR_MERC( pTeamSoldier ) )
|
|
{
|
|
ubMercsInSector[ ubNumMercs ] = (UINT8)cnt;
|
|
ubNumMercs++;
|
|
}
|
|
}
|
|
|
|
// If we are > 0
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("PickLocationNearAnyMercInSector: number of guys %d",ubNumMercs));
|
|
if ( ubNumMercs > 0 )
|
|
{
|
|
ubChosenMerc = (UINT8)Random( ubNumMercs );
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("PickLocationNearAnyMercInSector: chosen guy = %d",ubChosenMerc));
|
|
return( MercPtrs[ ubMercsInSector[ ubChosenMerc ] ]->sGridNo );
|
|
}
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("PickLocationNearAnyMercInSector: no target"));
|
|
return( NOWHERE );
|
|
}
|
|
|
|
INT16 PickRandomLocationAtMinSpacesAway( INT16 sGridNo, INT16 sMinValue, INT16 sRandomVar )
|
|
{
|
|
INT16 sNewGridNo = NOWHERE;
|
|
INT16 sX, sY, sNewX, sNewY;
|
|
INT16 cnt = 0;
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"PickRandomLocationAtMinSpacesAway");
|
|
|
|
sX = CenterX( sGridNo );
|
|
sY = CenterY( sGridNo );
|
|
|
|
while( sNewGridNo == NOWHERE )
|
|
{
|
|
sNewX = sX + sMinValue + (INT16)Random( sRandomVar );
|
|
sNewY = sY + sMinValue + (INT16)Random( sRandomVar );
|
|
|
|
if ( Random( 2 ) )
|
|
{
|
|
sNewX = -1 * sNewX;
|
|
}
|
|
|
|
if ( Random( 2 ) )
|
|
{
|
|
sNewY = -1 * sNewY;
|
|
}
|
|
|
|
// Make gridno....
|
|
sNewGridNo = GETWORLDINDEXFROMWORLDCOORDS( sNewY, sNewX );
|
|
|
|
// Check if visible on screen....
|
|
if ( cnt < 50 && !GridNoOnVisibleWorldTile( sNewGridNo ) )
|
|
{
|
|
sNewGridNo = NOWHERE;
|
|
}
|
|
cnt++;
|
|
}
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("PickRandomLocationAtMinSpacesAway: grid no = %d",sNewGridNo));
|
|
return( sNewGridNo );
|
|
}
|
|
|
|
void TryToStartRaid( )
|
|
{
|
|
// OK, check conditions,
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("TryToStartRaid"));
|
|
// Some are:
|
|
|
|
// Cannot be in battle ( this is handled by the fact of it begin shceduled in the first place...
|
|
|
|
// Cannot be auto-bandaging?
|
|
if ( gTacticalStatus.fAutoBandageMode )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("TryToStartRaid: auto-bandaging"));
|
|
return;
|
|
}
|
|
|
|
// Cannot be in conversation...
|
|
if ( gTacticalStatus.uiFlags & ENGAGED_IN_CONV )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("TryToStartRaid: in conversation"));
|
|
return;
|
|
}
|
|
|
|
// Cannot be traversing.....
|
|
|
|
// Ok, go...
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("TryToStartRaid: go!"));
|
|
|
|
gubAirRaidMode = AIR_RAID_START;
|
|
|
|
}
|
|
|
|
void AirRaidStart( )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("AirRaidStart"));
|
|
// Begin ambient sound....
|
|
guiSoundSample = PlayJA2Sample( S_RAID_AMBIENT, RATE_11025, 0, 10000, MIDDLEPAN );
|
|
|
|
gfFadingRaidIn = TRUE;
|
|
|
|
// Setup start time....
|
|
RESETTIMECOUNTER( giTimerAirRaidQuote, AIR_RAID_SAY_QUOTE_TIME );
|
|
|
|
gubAirRaidMode = AIR_RAID_LOOK_FOR_DIVE;
|
|
|
|
// If we are not in combat, change music mode...
|
|
if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
SetMusicMode( MUSIC_TACTICAL_BATTLE );
|
|
}
|
|
}
|
|
|
|
void AirRaidLookForDive( )
|
|
{
|
|
BOOLEAN fDoDive = FALSE;
|
|
BOOLEAN fDoQuote = FALSE;
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("AirRaidLookForDive: quote said? = %d",gfQuoteSaid));
|
|
|
|
if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( !gfQuoteSaid )
|
|
{
|
|
if ( TIMECOUNTERDONE( giTimerAirRaidQuote, AIR_RAID_SAY_QUOTE_TIME ) )
|
|
{
|
|
fDoQuote = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( giNumTurnsSinceLastDive > 1 && !gfQuoteSaid )
|
|
{
|
|
fDoQuote = TRUE;
|
|
}
|
|
}
|
|
|
|
// OK, check if we should say something....
|
|
if ( fDoQuote )
|
|
{
|
|
gfQuoteSaid = TRUE;
|
|
|
|
// Someone in group say quote...
|
|
SayQuoteFromAnyBodyInSector( QUOTE_AIR_RAID );
|
|
|
|
// Update timer
|
|
RESETTIMECOUNTER( giTimerAirRaidDiveStarted, AIR_RAID_DIVE_INTERVAL );
|
|
|
|
giNumTurnsSinceLastDive = 0;
|
|
|
|
// Do morale hit on our guys
|
|
HandleMoraleEvent( NULL, MORALE_AIRSTRIKE, gAirRaidDef.sSectorX, gAirRaidDef.sSectorY, ( INT8 ) gAirRaidDef.sSectorZ );
|
|
}
|
|
|
|
|
|
// If NOT in combat....
|
|
if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// OK, for now on, all we try to do is look for dives to make...
|
|
if ( gfQuoteSaid )
|
|
{
|
|
if ( TIMECOUNTERDONE( giTimerAirRaidDiveStarted, AIR_RAID_DIVE_INTERVAL ) )
|
|
{
|
|
// IN realtime, give a bit more leeway for time....
|
|
//if ( Random( 2 ) )
|
|
{
|
|
fDoDive = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// How many turns have gone by?
|
|
if ( (UINT32)giNumTurnsSinceLastDive > ( Random( 2 ) + 1 ) )
|
|
{
|
|
fDoDive = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( fDoDive )
|
|
{
|
|
// If we are are beginning game, only do gun dives..
|
|
if ( gAirRaidDef.uiFlags & AIR_RAID_BEGINNING_GAME && gGameOptions.ubDifficultyLevel < DIF_LEVEL_HARD )
|
|
{
|
|
if ( gbNumDives == 0 )
|
|
{
|
|
gubAirRaidMode = AIR_RAID_BEGIN_DIVE;
|
|
}
|
|
else if ( gbNumDives == 1 )
|
|
{
|
|
gubAirRaidMode = AIR_RAID_BEGIN_BOMBING;
|
|
}
|
|
else
|
|
{
|
|
gubAirRaidMode = AIR_RAID_BEGIN_DIVE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Randomly do dive...
|
|
if ( Random( 2 ) && gAirRaidDef.uiFlags & AIR_RAID_CAN_RANDOMIZE_TEASE_DIVES )
|
|
{
|
|
gubAirRaidMode = AIR_RAID_BEGIN_DIVE;
|
|
}
|
|
else
|
|
{
|
|
gubAirRaidMode = AIR_RAID_BEGIN_BOMBING;
|
|
}
|
|
}
|
|
gbNumDives++;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( giNumGridNosMovedThisTurn == 0 )
|
|
{
|
|
// Free up attacker...
|
|
ReduceAttackBusyCount( );
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Tried to free up attacker AIR RAID NO DIVE, attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
}
|
|
}
|
|
}
|
|
|
|
// End if we have made desired # of dives...
|
|
if ( gbNumDives == gbMaxDives )
|
|
{
|
|
// Air raid is over....
|
|
gubAirRaidMode = AIR_RAID_START_END;
|
|
}
|
|
}
|
|
|
|
|
|
void AirRaidStartEnding( )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("AirRaidStartEnding"));
|
|
// Fade out sound.....
|
|
gfFadingRaidOut = TRUE;
|
|
}
|
|
|
|
|
|
void BeginBombing( )
|
|
{
|
|
INT16 sGridNo;
|
|
UINT32 iSoundStartDelay;
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginBombing"));
|
|
|
|
if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Start diving sound...
|
|
PlayJA2Sample( S_RAID_WHISTLE, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
|
|
}
|
|
|
|
gubAirRaidMode = AIR_RAID_BOMBING;
|
|
|
|
// Pick location...
|
|
gsDiveTargetLocation = PickLocationNearAnyMercInSector( );
|
|
|
|
if ( gsDiveTargetLocation == NOWHERE )
|
|
{
|
|
gsDiveTargetLocation = 10234;
|
|
}
|
|
|
|
// Get location of aircraft....
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginBombing: pick location, gsDiveTargetLocation = %d",gsDiveTargetLocation));
|
|
sGridNo = PickRandomLocationAtMinSpacesAway( gsDiveTargetLocation , 300, 200 );
|
|
|
|
// Save X, y:
|
|
gsDiveX = CenterX( sGridNo );
|
|
gsDiveY = CenterY( sGridNo );
|
|
|
|
RESETTIMECOUNTER( giTimerAirRaidUpdate, RAID_DELAY );
|
|
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
iSoundStartDelay = 0;
|
|
}
|
|
else
|
|
{
|
|
iSoundStartDelay = TIME_FROM_BOMB_SOUND_TO_ATTACK_DELAY;
|
|
}
|
|
RESETTIMECOUNTER( giTimerAirRaidDiveStarted, iSoundStartDelay );
|
|
|
|
|
|
giNumTurnsSinceDiveStarted = 0;
|
|
|
|
// Get direction....
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginBombing: get direction"));
|
|
gubDiveDirection = (INT8)GetDirectionToGridNoFromGridNo( sGridNo, gsDiveTargetLocation );
|
|
|
|
gsNumGridNosMoved = 0;
|
|
gsNotLocatedYet = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BeginDive( )
|
|
{
|
|
INT16 sGridNo;
|
|
UINT32 iSoundStartDelay;
|
|
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginDive"));
|
|
// Start diving sound...
|
|
PlayJA2Sample( S_RAID_DIVE, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
|
|
|
|
gubAirRaidMode = AIR_RAID_DIVING;
|
|
|
|
// Increment attacker bust count....
|
|
gTacticalStatus.ubAttackBusyCount++;
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting attack BEGIN DIVE %d", gTacticalStatus.ubAttackBusyCount) );
|
|
DebugAttackBusy( String("!!!!!!! Starting attack BEGIN DIVE %d", gTacticalStatus.ubAttackBusyCount) );
|
|
|
|
// Pick location...
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginDive: pick location"));
|
|
gsDiveTargetLocation = PickLocationNearAnyMercInSector( );
|
|
|
|
if ( gsDiveTargetLocation == NOWHERE )
|
|
{
|
|
gsDiveTargetLocation = 10234;
|
|
}
|
|
|
|
// Get location of aircraft....
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginDive: pick location at min spaces away, gsDiveTargetLocation = %d",gsDiveTargetLocation));
|
|
sGridNo = PickRandomLocationAtMinSpacesAway( gsDiveTargetLocation, 300, 200 );
|
|
|
|
// Save X, y:
|
|
gsDiveX = CenterX( sGridNo );
|
|
gsDiveY = CenterY( sGridNo );
|
|
|
|
RESETTIMECOUNTER( giTimerAirRaidUpdate, RAID_DELAY );
|
|
giNumTurnsSinceDiveStarted = 0;
|
|
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
iSoundStartDelay = 0;
|
|
}
|
|
else
|
|
{
|
|
iSoundStartDelay = TIME_FROM_DIVE_SOUND_TO_ATTACK_DELAY;
|
|
}
|
|
RESETTIMECOUNTER( giTimerAirRaidDiveStarted, iSoundStartDelay );
|
|
|
|
|
|
// Get direction....
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("BeginDive: get direction"));
|
|
gubDiveDirection = (INT8)GetDirectionToGridNoFromGridNo( sGridNo, gsDiveTargetLocation );
|
|
|
|
gsNumGridNosMoved = 0;
|
|
gsNotLocatedYet = TRUE;
|
|
|
|
}
|
|
|
|
|
|
void MoveDiveAirplane( FLOAT dAngle )
|
|
{
|
|
FLOAT dDeltaPos;
|
|
|
|
// Find delta Movement for X pos
|
|
dDeltaPos = MOVE_X * (FLOAT)sin( dAngle );
|
|
|
|
// Find new position
|
|
gsDiveX = (INT16)( gsDiveX + dDeltaPos );
|
|
|
|
// Find delta Movement for Y pos
|
|
dDeltaPos = MOVE_X * (FLOAT)cos( dAngle );
|
|
|
|
// Find new pos
|
|
gsDiveY = (INT16)( gsDiveY + dDeltaPos );
|
|
|
|
|
|
}
|
|
|
|
|
|
void DoDive( )
|
|
{
|
|
INT16 sRange;
|
|
INT16 sGridNo, sOldGridNo;
|
|
|
|
INT16 sTargetX, sTargetY;
|
|
INT16 sStrafeX, sStrafeY;
|
|
FLOAT dDeltaX, dDeltaY, dAngle, dDeltaXPos, dDeltaYPos;
|
|
INT16 sX, sY;
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive");
|
|
|
|
// Delay for a specific perion of time to allow sound to Q up...
|
|
if ( TIMECOUNTERDONE( giTimerAirRaidDiveStarted, 0 ) )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive: tease or not");
|
|
// OK, rancomly decide to not do this dive...
|
|
if ( gAirRaidDef.uiFlags & AIR_RAID_CAN_RANDOMIZE_TEASE_DIVES )
|
|
{
|
|
//if ( Random( 10 ) == 0 )
|
|
//{
|
|
// // Finish....
|
|
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive: just teasing");
|
|
// gubAirRaidMode = AIR_RAID_END_DIVE;
|
|
// return;
|
|
//}
|
|
}
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive: locate target");
|
|
if ( gsNotLocatedYet && !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
gsNotLocatedYet = FALSE;
|
|
LocateGridNo( gsDiveTargetLocation );
|
|
}
|
|
|
|
sOldGridNo = GETWORLDINDEXFROMWORLDCOORDS( gsDiveY, gsDiveX );
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive: dive until we are a certain range to target");
|
|
// Dive until we are a certain range to target....
|
|
sRange = PythSpacesAway( sOldGridNo, gsDiveTargetLocation );
|
|
|
|
// If sRange
|
|
if ( sRange < 3 )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive: end dive");
|
|
// Finish....
|
|
gubAirRaidMode = AIR_RAID_END_DIVE;
|
|
return;
|
|
}
|
|
|
|
if ( TIMECOUNTERDONE( giTimerAirRaidUpdate, RAID_DELAY ) )
|
|
{
|
|
RESETTIMECOUNTER( giTimerAirRaidUpdate, RAID_DELAY );
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive: move towards target");
|
|
// Move Towards target....
|
|
sTargetX = CenterX( gsDiveTargetLocation );
|
|
sTargetY = CenterY( gsDiveTargetLocation );
|
|
|
|
// Determine deltas
|
|
dDeltaX = (FLOAT)( sTargetX - gsDiveX );
|
|
dDeltaY = (FLOAT)( sTargetY - gsDiveY );
|
|
|
|
// Determine angle
|
|
dAngle = (FLOAT)atan2( dDeltaX, dDeltaY );
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive: move plane");
|
|
MoveDiveAirplane( dAngle );
|
|
|
|
gpRaidSoldier->dXPos = gsDiveX;
|
|
gpRaidSoldier->sX = gsDiveX;
|
|
gpRaidSoldier->dYPos = gsDiveY;
|
|
gpRaidSoldier->sY = gsDiveY;
|
|
|
|
// Figure gridno....
|
|
sGridNo = GETWORLDINDEXFROMWORLDCOORDS( gsDiveY, gsDiveX );
|
|
gpRaidSoldier->sGridNo = sGridNo;
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("DoDive: figure out grid number, sgridno = %d, soldgridno = %d", sGridNo, sOldGridNo));
|
|
if ( sOldGridNo != sGridNo )
|
|
{
|
|
gsNumGridNosMoved++;
|
|
|
|
giNumGridNosMovedThisTurn++;
|
|
|
|
// OK, shoot bullets....
|
|
// Get positions of guns...
|
|
|
|
// Get target.....
|
|
dDeltaXPos = STRAFE_DIST * (FLOAT)sin( dAngle );
|
|
sStrafeX = (INT16)( gsDiveX + dDeltaXPos );
|
|
|
|
// Find delta Movement for Y pos
|
|
dDeltaYPos = STRAFE_DIST * (FLOAT)cos( dAngle );
|
|
sStrafeY = (INT16)( gsDiveY + dDeltaYPos );
|
|
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
LocateGridNo( sGridNo );
|
|
}
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoDive: Fire bullets");
|
|
if ( GridNoOnVisibleWorldTile( (INT16)( GETWORLDINDEXFROMWORLDCOORDS( sStrafeY, sStrafeX ) ) ) )
|
|
{
|
|
//if ( gsNotLocatedYet && !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
// {
|
|
// gsNotLocatedYet = FALSE;
|
|
// LocateGridNo( sGridNo );
|
|
// }
|
|
|
|
//if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Increase attacker busy...
|
|
//gTacticalStatus.ubAttackBusyCount++;
|
|
//DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting attack AIR RAID ( fire gun ), attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
|
|
// INcrement bullet fired...
|
|
// gpRaidSoldier->bBulletsLeft++;
|
|
}
|
|
|
|
// For now use first position....
|
|
|
|
|
|
gpRaidSoldier->ubTargetID = NOBODY;
|
|
FireBulletGivenTarget( gpRaidSoldier, sStrafeX, sStrafeY, 0, gpRaidSoldier->usAttackingWeapon, 10, FALSE, FALSE );
|
|
}
|
|
|
|
// Do second one.... ( ll )
|
|
sX = (INT16)( gsDiveX + ( (FLOAT)sin( dAngle + ( PI/2) ) * 40 ) );
|
|
sY = (INT16)( gsDiveY + ( (FLOAT)cos( dAngle + ( PI/2) ) * 40 ) );
|
|
|
|
gpRaidSoldier->dXPos = sX;
|
|
gpRaidSoldier->sX = sX;
|
|
gpRaidSoldier->dYPos = sY;
|
|
gpRaidSoldier->sY = sY;
|
|
gpRaidSoldier->sGridNo = GETWORLDINDEXFROMWORLDCOORDS( sY, sX );
|
|
|
|
// Get target.....
|
|
sStrafeX = (INT16)( sX + dDeltaXPos );
|
|
|
|
// Find delta Movement for Y pos
|
|
sStrafeY = (INT16)( sY + dDeltaYPos );
|
|
|
|
if ( GridNoOnVisibleWorldTile( (INT16)( GETWORLDINDEXFROMWORLDCOORDS( sStrafeY, sStrafeX ) ) ) )
|
|
{
|
|
//if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Increase attacker busy...
|
|
//gTacticalStatus.ubAttackBusyCount++;
|
|
//DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting attack AIR RAID ( second one ), attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
|
|
// INcrement bullet fired...
|
|
// gpRaidSoldier->bBulletsLeft++;
|
|
|
|
}
|
|
|
|
// For now use first position....
|
|
FireBulletGivenTarget( gpRaidSoldier, sStrafeX, sStrafeY, 0, gpRaidSoldier->usAttackingWeapon, 10, FALSE, FALSE );
|
|
}
|
|
|
|
}
|
|
|
|
if ( giNumGridNosMovedThisTurn >= 6 )
|
|
{
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Free up attacker...
|
|
ReduceAttackBusyCount( );
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Tried to free up attacker AIR RAID DIVE DONE FOR THIS TURN, attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void DoBombing( )
|
|
{
|
|
INT16 sRange;
|
|
INT16 sGridNo, sOldGridNo, sBombGridNo;
|
|
|
|
INT16 sTargetX, sTargetY;
|
|
UINT16 usItem;
|
|
INT16 sStrafeX, sStrafeY;
|
|
FLOAT dDeltaX, dDeltaY, dAngle, dDeltaXPos, dDeltaYPos;
|
|
BOOLEAN fLocate = FALSE;
|
|
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoBombing");
|
|
|
|
// Delay for a specific perion of time to allow sound to Q up...
|
|
if ( TIMECOUNTERDONE( giTimerAirRaidDiveStarted, 0 ) )
|
|
{
|
|
// OK, rancomly decide to not do this dive...
|
|
if ( gAirRaidDef.uiFlags & AIR_RAID_CAN_RANDOMIZE_TEASE_DIVES )
|
|
{
|
|
//if ( Random( 10 ) == 0 )
|
|
//{
|
|
// // Finish....
|
|
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"DoBombing: just teasing");
|
|
// gubAirRaidMode = AIR_RAID_END_BOMBING;
|
|
// return;
|
|
//}
|
|
}
|
|
|
|
if ( gsNotLocatedYet && !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
gsNotLocatedYet = FALSE;
|
|
LocateGridNo( gsDiveTargetLocation );
|
|
}
|
|
|
|
sOldGridNo = GETWORLDINDEXFROMWORLDCOORDS( gsDiveY, gsDiveX );
|
|
|
|
// Dive until we are a certain range to target....
|
|
sRange = PythSpacesAway( sOldGridNo, gsDiveTargetLocation );
|
|
|
|
// If sRange
|
|
if ( sRange < 3 )
|
|
{
|
|
// Finish....
|
|
gubAirRaidMode = AIR_RAID_END_BOMBING;
|
|
return;
|
|
}
|
|
|
|
if ( TIMECOUNTERDONE( giTimerAirRaidUpdate, RAID_DELAY ) )
|
|
{
|
|
RESETTIMECOUNTER( giTimerAirRaidUpdate, RAID_DELAY );
|
|
|
|
// Move Towards target....
|
|
sTargetX = CenterX( gsDiveTargetLocation );
|
|
sTargetY = CenterY( gsDiveTargetLocation );
|
|
|
|
// Determine deltas
|
|
dDeltaX = (FLOAT)( sTargetX - gsDiveX );
|
|
dDeltaY = (FLOAT)( sTargetY - gsDiveY );
|
|
|
|
// Determine angle
|
|
dAngle = (FLOAT)atan2( dDeltaX, dDeltaY );
|
|
|
|
MoveDiveAirplane( dAngle );
|
|
|
|
gpRaidSoldier->dXPos = gsDiveX;
|
|
gpRaidSoldier->sX = gsDiveX;
|
|
gpRaidSoldier->dYPos = gsDiveY;
|
|
gpRaidSoldier->sY = gsDiveY;
|
|
|
|
// Figure gridno....
|
|
sGridNo = GETWORLDINDEXFROMWORLDCOORDS( gsDiveY, gsDiveX );
|
|
gpRaidSoldier->sGridNo = sGridNo;
|
|
|
|
if ( sOldGridNo != sGridNo )
|
|
{
|
|
// Every once and a while, drop bomb....
|
|
gsNumGridNosMoved++;
|
|
|
|
giNumGridNosMovedThisTurn++;
|
|
|
|
if ( ( gsNumGridNosMoved % 4 ) == 0 )
|
|
{
|
|
// Get target.....
|
|
dDeltaXPos = BOMB_DIST * (FLOAT)sin( dAngle );
|
|
sStrafeX = (INT16)( gsDiveX + dDeltaXPos );
|
|
|
|
// Find delta Movement for Y pos
|
|
dDeltaYPos = BOMB_DIST * (FLOAT)cos( dAngle );
|
|
sStrafeY = (INT16)( gsDiveY + dDeltaYPos );
|
|
|
|
if ( GridNoOnVisibleWorldTile( (INT16)( GETWORLDINDEXFROMWORLDCOORDS( sStrafeY, sStrafeX ) ) ) )
|
|
{
|
|
//if ( gsNotLocatedYet && !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
//{
|
|
// gsNotLocatedYet = FALSE;
|
|
// LocateGridNo( sGridNo );
|
|
//}
|
|
|
|
|
|
if ( Random( 2 ) )
|
|
{
|
|
usItem = HAND_GRENADE;
|
|
}
|
|
else
|
|
{
|
|
usItem = RDX;
|
|
}
|
|
|
|
// Pick random gridno....
|
|
sBombGridNo = PickRandomLocationAtMinSpacesAway( (INT16)( GETWORLDINDEXFROMWORLDCOORDS( sStrafeY, sStrafeX ) ) , 40, 40 );
|
|
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
fLocate = TRUE;
|
|
// Increase attacker busy...
|
|
gTacticalStatus.ubAttackBusyCount++;
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting attack AIR RAID ( bombs away ), attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
DebugAttackBusy( String("!!!!!!! Starting attack AIR RAID ( bombs away ), attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
}
|
|
|
|
// Drop bombs...
|
|
InternalIgniteExplosion( NOBODY, CenterX( sBombGridNo ), CenterY( sBombGridNo ), 0, sBombGridNo, usItem, fLocate , (UINT8)IsRoofPresentAtGridno( sBombGridNo ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( giNumGridNosMovedThisTurn >= 6 )
|
|
{
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Free up attacker...
|
|
ReduceAttackBusyCount( );
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Tried to free up attacker AIR RAID BOMB ATTACK DONE FOR THIS TURN, attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HandleAirRaid( )
|
|
{
|
|
INT32 iVol;
|
|
UINT32 uiClock;
|
|
|
|
// OK,
|
|
if ( gfInAirRaid )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleAirRaid: air raid mode = %d, quote said = %d",gubAirRaidMode,gfQuoteSaid));
|
|
|
|
// are we in meanwhile?
|
|
|
|
if ( AreInMeanwhile() )
|
|
return;
|
|
|
|
// Are we in TB?
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Do we have the batton?
|
|
if ( !gfHaveTBBatton )
|
|
{
|
|
// Don;t do anything else!
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( WillAirRaidBeStopped( gAirRaidDef.sSectorX, gAirRaidDef.sSectorY ) )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"HandleAirRaid: SAM just taken over");
|
|
gfFadingRaidOut=TRUE;
|
|
gfFadingRaidIn=FALSE;
|
|
}
|
|
|
|
// Madd - handle running out of the sector
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleAirRaid: check for mercs: first id = %d, last id = %d ",gTacticalStatus.Team[ gbPlayerNum ].bFirstID, gTacticalStatus.Team[ gbPlayerNum ].bLastID));
|
|
SOLDIERTYPE * pSoldier;
|
|
BOOLEAN fOK = FALSE;
|
|
int cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
for ( cnt = 0, pSoldier = MercPtrs[ cnt ]; cnt < gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++)
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleAirRaid: soldier id = %d, active = %d",pSoldier->ubID,pSoldier->bActive));
|
|
if ( pSoldier->bActive )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleAirRaid: soldier sectors: x = %d, y = %d, z = %d",pSoldier->sSectorX,pSoldier->sSectorY,pSoldier->bSectorZ ));
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleAirRaid: air raid sectors: x = %d, y = %d, z = %d",gAirRaidDef.sSectorX,gAirRaidDef.sSectorY,gAirRaidDef.sSectorZ ));
|
|
if( pSoldier->sSectorX == gAirRaidDef.sSectorX && pSoldier->sSectorY == gAirRaidDef.sSectorY && pSoldier->bSectorZ == gAirRaidDef.sSectorZ && !pSoldier->fBetweenSectors && pSoldier->bLife && pSoldier->bAssignment != IN_TRANSIT )
|
|
{
|
|
fOK = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"HandleAirRaid: do we have some guys in this sector?");
|
|
if ( !fOK )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"HandleAirRaid: no we don't");
|
|
gfFadingRaidOut=TRUE;
|
|
gfFadingRaidIn=FALSE;
|
|
}
|
|
|
|
uiClock = GetJA2Clock( );
|
|
|
|
if ( ( uiClock - guiRaidLastUpdate ) > SCRIPT_DELAY )
|
|
{
|
|
giNumFrames++;
|
|
|
|
guiRaidLastUpdate = uiClock;
|
|
|
|
if( gfFadingRaidIn )
|
|
{
|
|
if( guiSoundSample!=NO_SAMPLE )
|
|
{
|
|
if ( ( giNumFrames % 10 ) == 0 )
|
|
{
|
|
iVol=SoundGetVolume( guiSoundSample );
|
|
iVol=__min( HIGHVOLUME, iVol+1);
|
|
SoundSetVolume(guiSoundSample, iVol);
|
|
if(iVol==HIGHVOLUME)
|
|
gfFadingRaidIn=FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gfFadingRaidIn=FALSE;
|
|
}
|
|
}
|
|
else if( gfFadingRaidOut )
|
|
{
|
|
if( guiSoundSample!=NO_SAMPLE )
|
|
{
|
|
if ( ( giNumFrames % 10 ) == 0 )
|
|
{
|
|
iVol=SoundGetVolume(guiSoundSample);
|
|
|
|
iVol=__max( 0, iVol-1);
|
|
|
|
SoundSetVolume(guiSoundSample, iVol);
|
|
if(iVol==0)
|
|
{
|
|
gfFadingRaidOut=FALSE;
|
|
|
|
gubAirRaidMode = AIR_RAID_END;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
gfFadingRaidOut=FALSE;
|
|
gubAirRaidMode = AIR_RAID_END;
|
|
}
|
|
}
|
|
|
|
switch( gubAirRaidMode )
|
|
{
|
|
case AIR_RAID_TRYING_TO_START:
|
|
|
|
TryToStartRaid( );
|
|
break;
|
|
|
|
case AIR_RAID_START:
|
|
|
|
AirRaidStart( );
|
|
break;
|
|
|
|
case AIR_RAID_LOOK_FOR_DIVE:
|
|
|
|
AirRaidLookForDive( );
|
|
break;
|
|
|
|
case AIR_RAID_START_END:
|
|
|
|
AirRaidStartEnding( );
|
|
break;
|
|
|
|
case AIR_RAID_END:
|
|
|
|
EndAirRaid( );
|
|
break;
|
|
|
|
case AIR_RAID_BEGIN_DIVE:
|
|
|
|
BeginDive( );
|
|
break;
|
|
|
|
case AIR_RAID_DIVING:
|
|
|
|
// If in combat, check if we have reached our max...
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
if ( giNumGridNosMovedThisTurn < 6 )
|
|
{
|
|
DoDive( );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DoDive( );
|
|
}
|
|
break;
|
|
|
|
case AIR_RAID_END_DIVE:
|
|
|
|
giNumTurnsSinceLastDive = 0;
|
|
RESETTIMECOUNTER( giTimerAirRaidDiveStarted, AIR_RAID_DIVE_INTERVAL );
|
|
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Free up attacker...
|
|
ReduceAttackBusyCount( );
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Tried to free up attacker AIR RAID ENDING DIVE, attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
}
|
|
|
|
gubAirRaidMode = AIR_RAID_LOOK_FOR_DIVE;
|
|
break;
|
|
|
|
case AIR_RAID_END_BOMBING:
|
|
|
|
RESETTIMECOUNTER( giTimerAirRaidDiveStarted, AIR_RAID_DIVE_INTERVAL );
|
|
giNumTurnsSinceLastDive = 0;
|
|
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
// Free up attacker...
|
|
ReduceAttackBusyCount( );
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Tried to free up attacker AIR RAID ENDING DIVE, attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
}
|
|
|
|
gubAirRaidMode = AIR_RAID_LOOK_FOR_DIVE;
|
|
break;
|
|
|
|
case AIR_RAID_BEGIN_BOMBING:
|
|
BeginBombing( );
|
|
break;
|
|
|
|
case AIR_RAID_BOMBING:
|
|
DoBombing( );
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleAirRaid: in combat"));
|
|
// Do we have the batton?
|
|
if ( gfHaveTBBatton )
|
|
{
|
|
// Are we through with attacker busy count?
|
|
if ( gTacticalStatus.ubAttackBusyCount == 0 )
|
|
{
|
|
// Relinquish control....
|
|
gfAirRaidHasHadTurn = TRUE;
|
|
gfHaveTBBatton = FALSE;
|
|
BeginTeamTurn( gubBeginTeamTurn );
|
|
}
|
|
}
|
|
}
|
|
DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("HandleAirRaid: done"));
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN InAirRaid( )
|
|
{
|
|
return FALSE;
|
|
// return( gfInAirRaid );
|
|
}
|
|
|
|
|
|
BOOLEAN HandleAirRaidEndTurn( UINT8 ubTeam )
|
|
{
|
|
return( TRUE ); // lal bugfix air raid hangs (remove to enable air raid)
|
|
|
|
if ( !gfInAirRaid )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
if ( gfAirRaidHasHadTurn )
|
|
{
|
|
gfAirRaidHasHadTurn = FALSE;
|
|
return( TRUE );
|
|
}
|
|
|
|
giNumTurnsSinceLastDive++;
|
|
giNumTurnsSinceDiveStarted++;
|
|
giNumGridNosMovedThisTurn = 0;
|
|
gubBeginTeamTurn = ubTeam;
|
|
gfHaveTBBatton = TRUE;
|
|
|
|
// ATE: Even if we have an attacker busy problem.. init to 0 now
|
|
//gTacticalStatus.ubAttackBusyCount = 0;
|
|
|
|
// Increment attacker bust count....
|
|
gTacticalStatus.ubAttackBusyCount++;
|
|
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("!!!!!!! Starting attack AIR RAID, attack count now %d", gTacticalStatus.ubAttackBusyCount) );
|
|
DebugAttackBusy( String("!!!!!!! Starting attack AIR RAID, attack count now %d\n", gTacticalStatus.ubAttackBusyCount) );
|
|
|
|
AddTopMessage( AIR_RAID_TURN_MESSAGE, TacticalStr[ AIR_RAID_TURN_STR ] );
|
|
|
|
// OK, handle some sound effects, depending on the mode we are in...
|
|
if ( ( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
switch( gubAirRaidMode )
|
|
{
|
|
case AIR_RAID_BOMBING:
|
|
|
|
// Start diving sound...
|
|
PlayJA2Sample( S_RAID_TB_BOMB, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
|
|
break;
|
|
|
|
case AIR_RAID_BEGIN_DIVE:
|
|
|
|
PlayJA2Sample( S_RAID_TB_DIVE, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
BOOLEAN SaveAirRaidInfoToSaveGameFile( HWFILE hFile )
|
|
{
|
|
UINT32 uiNumBytesWritten;
|
|
AIR_RAID_SAVE_STRUCT sAirRaidSaveStruct;
|
|
|
|
// Put all the globals into the save struct
|
|
sAirRaidSaveStruct.fInAirRaid = gfInAirRaid;
|
|
sAirRaidSaveStruct.fAirRaidScheduled = gfAirRaidScheduled;
|
|
sAirRaidSaveStruct.ubAirRaidMode = gubAirRaidMode;
|
|
sAirRaidSaveStruct.uiSoundSample = guiSoundSample;
|
|
sAirRaidSaveStruct.uiRaidLastUpdate = guiRaidLastUpdate;
|
|
sAirRaidSaveStruct.fFadingRaidIn = gfFadingRaidIn;
|
|
sAirRaidSaveStruct.fQuoteSaid = gfQuoteSaid;
|
|
sAirRaidSaveStruct.bNumDives = gbNumDives;
|
|
sAirRaidSaveStruct.bMaxDives = gbMaxDives;
|
|
sAirRaidSaveStruct.fFadingRaidOut = gfFadingRaidOut;
|
|
sAirRaidSaveStruct.sDiveX = gsDiveX;
|
|
sAirRaidSaveStruct.sDiveY = gsDiveY;
|
|
sAirRaidSaveStruct.sDiveTargetLocation = gsDiveTargetLocation;
|
|
sAirRaidSaveStruct.ubDiveDirection = gubDiveDirection;
|
|
sAirRaidSaveStruct.sNumGridNosMoved = gsNumGridNosMoved;
|
|
sAirRaidSaveStruct.iNumTurnsSinceLastDive = giNumTurnsSinceLastDive;
|
|
sAirRaidSaveStruct.iNumTurnsSinceDiveStarted = giNumTurnsSinceDiveStarted;
|
|
sAirRaidSaveStruct.iNumGridNosMovedThisTurn = giNumGridNosMovedThisTurn;
|
|
sAirRaidSaveStruct.fAirRaidHasHadTurn = gfAirRaidHasHadTurn;
|
|
sAirRaidSaveStruct.ubBeginTeamTurn = gubBeginTeamTurn;
|
|
sAirRaidSaveStruct.fHaveTBBatton = gfHaveTBBatton;
|
|
|
|
sAirRaidSaveStruct.sNotLocatedYet = gsNotLocatedYet;
|
|
sAirRaidSaveStruct.iNumFrames = giNumFrames;
|
|
|
|
|
|
// if( gpRaidSoldier )
|
|
// {
|
|
// sAirRaidSaveStruct.bLevel = gpRaidSoldier->bLevel;
|
|
// sAirRaidSaveStruct.bTeam = gpRaidSoldier->bTeam;
|
|
// sAirRaidSaveStruct.bSide = gpRaidSoldier->bSide;
|
|
// sAirRaidSaveStruct.ubAttackerID = gpRaidSoldier->ubAttackerID;
|
|
// sAirRaidSaveStruct.usAttackingWeapon = gpRaidSoldier->usAttackingWeapon;
|
|
// sAirRaidSaveStruct.dXPos = gpRaidSoldier->dXPos;
|
|
// sAirRaidSaveStruct.dYPos = gpRaidSoldier->dYPos;
|
|
// sAirRaidSaveStruct.sX = gpRaidSoldier->sX;
|
|
// sAirRaidSaveStruct.sY = gpRaidSoldier->sY;
|
|
// sAirRaidSaveStruct.sGridNo = gpRaidSoldier->sGridNo;
|
|
//
|
|
// sAirRaidSaveStruct.sRaidSoldierID = MAX_NUM_SOLDIERS - 1;
|
|
//// sAirRaidSaveStruct.sRaidSoldierID = gpRaidSoldier->ubID;
|
|
// }
|
|
// else
|
|
sAirRaidSaveStruct.sRaidSoldierID = -1;
|
|
|
|
|
|
memcpy( &sAirRaidSaveStruct.AirRaidDef, &gAirRaidDef, sizeof( AIR_RAID_DEFINITION ) );
|
|
|
|
|
|
//Save the Air Raid Save Struct
|
|
FileWrite( hFile, &sAirRaidSaveStruct, sizeof( AIR_RAID_SAVE_STRUCT ), &uiNumBytesWritten );
|
|
if( uiNumBytesWritten != sizeof( AIR_RAID_SAVE_STRUCT ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOLEAN LoadAirRaidInfoFromSaveGameFile( HWFILE hFile )
|
|
{
|
|
AIR_RAID_SAVE_STRUCT sAirRaidSaveStruct;
|
|
UINT32 uiNumBytesRead;
|
|
|
|
|
|
//Load the number of REAL_OBJECTs in the array
|
|
FileRead( hFile, &sAirRaidSaveStruct, sizeof( AIR_RAID_SAVE_STRUCT ), &uiNumBytesRead );
|
|
if( uiNumBytesRead != sizeof( AIR_RAID_SAVE_STRUCT ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
|
|
// Put all the globals into the save struct
|
|
gfInAirRaid = sAirRaidSaveStruct.fInAirRaid;
|
|
gfAirRaidScheduled = sAirRaidSaveStruct.fAirRaidScheduled;
|
|
gubAirRaidMode = sAirRaidSaveStruct.ubAirRaidMode;
|
|
guiSoundSample = sAirRaidSaveStruct.uiSoundSample;
|
|
guiRaidLastUpdate = sAirRaidSaveStruct.uiRaidLastUpdate;
|
|
gfFadingRaidIn = sAirRaidSaveStruct.fFadingRaidIn;
|
|
gfQuoteSaid = sAirRaidSaveStruct.fQuoteSaid;
|
|
gbNumDives = sAirRaidSaveStruct.bNumDives;
|
|
gbMaxDives = sAirRaidSaveStruct.bMaxDives;
|
|
gfFadingRaidOut = sAirRaidSaveStruct.fFadingRaidOut;
|
|
gsDiveX = sAirRaidSaveStruct.sDiveX;
|
|
gsDiveY = sAirRaidSaveStruct.sDiveY;
|
|
gsDiveTargetLocation = sAirRaidSaveStruct.sDiveTargetLocation;
|
|
gubDiveDirection = sAirRaidSaveStruct.ubDiveDirection;
|
|
gsNumGridNosMoved = sAirRaidSaveStruct.sNumGridNosMoved;
|
|
giNumTurnsSinceLastDive = sAirRaidSaveStruct.iNumTurnsSinceLastDive;
|
|
giNumTurnsSinceDiveStarted = sAirRaidSaveStruct.iNumTurnsSinceDiveStarted;
|
|
giNumGridNosMovedThisTurn = sAirRaidSaveStruct.iNumGridNosMovedThisTurn;
|
|
gfAirRaidHasHadTurn = sAirRaidSaveStruct.fAirRaidHasHadTurn;
|
|
gubBeginTeamTurn = sAirRaidSaveStruct.ubBeginTeamTurn;
|
|
gfHaveTBBatton = sAirRaidSaveStruct.fHaveTBBatton;
|
|
|
|
gsNotLocatedYet = sAirRaidSaveStruct.sNotLocatedYet;
|
|
giNumFrames = sAirRaidSaveStruct.iNumFrames;
|
|
|
|
|
|
if( sAirRaidSaveStruct.sRaidSoldierID != -1 )
|
|
{
|
|
gpRaidSoldier = &Menptr[ sAirRaidSaveStruct.sRaidSoldierID ];
|
|
|
|
gpRaidSoldier->bLevel = sAirRaidSaveStruct.bLevel;
|
|
gpRaidSoldier->bTeam = sAirRaidSaveStruct.bTeam;
|
|
gpRaidSoldier->bSide = sAirRaidSaveStruct.bSide;
|
|
gpRaidSoldier->ubAttackerID = sAirRaidSaveStruct.ubAttackerID;
|
|
gpRaidSoldier->usAttackingWeapon = sAirRaidSaveStruct.usAttackingWeapon;
|
|
gpRaidSoldier->dXPos = sAirRaidSaveStruct.dXPos;
|
|
gpRaidSoldier->dYPos = sAirRaidSaveStruct.dYPos;
|
|
gpRaidSoldier->sX = sAirRaidSaveStruct.sX;
|
|
gpRaidSoldier->sY = sAirRaidSaveStruct.sY;
|
|
gpRaidSoldier->sGridNo = sAirRaidSaveStruct.sGridNo;
|
|
}
|
|
else
|
|
gpRaidSoldier = NULL;
|
|
|
|
memcpy( &gAirRaidDef, &sAirRaidSaveStruct.AirRaidDef, sizeof( AIR_RAID_DEFINITION ) );
|
|
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
|
|
void EndAirRaid( )
|
|
{
|
|
gfInAirRaid = FALSE;
|
|
|
|
// Stop sound
|
|
SoundStop( guiSoundSample );
|
|
|
|
// Change music back...
|
|
if ( !( gTacticalStatus.uiFlags & INCOMBAT ) )
|
|
{
|
|
SetMusicMode( MUSIC_TACTICAL_NOTHING );
|
|
|
|
if ( !gTacticalStatus.Team[ ENEMY_TEAM ].bTeamActive && !gTacticalStatus.Team[ CREATURE_TEAM ].bTeamActive )
|
|
{
|
|
SOLDIERTYPE * pTeamSoldier;
|
|
INT32 cnt;
|
|
|
|
// Loop through all militia and restore them to peaceful status
|
|
cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID;
|
|
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++,pTeamSoldier++)
|
|
{
|
|
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector )
|
|
{
|
|
pTeamSoldier->bAlertStatus = STATUS_GREEN;
|
|
}
|
|
}
|
|
gTacticalStatus.Team[ MILITIA_TEAM ].bAwareOfOpposition = FALSE;
|
|
|
|
cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID;
|
|
// Loop through all civs and restore them to peaceful status
|
|
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CIV_TEAM ].bLastID; cnt++,pTeamSoldier++)
|
|
{
|
|
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector )
|
|
{
|
|
pTeamSoldier->bAlertStatus = STATUS_GREEN;
|
|
}
|
|
}
|
|
gTacticalStatus.Team[ CIV_TEAM ].bAwareOfOpposition = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
// OK, look at flags...
|
|
if ( gAirRaidDef.uiFlags & AIR_RAID_BEGINNING_GAME )
|
|
{ // OK, make enemy appear in Omerta
|
|
// Talk to strategic AI for this...
|
|
//GROUP *pGroup;
|
|
//Create a patrol group originating from sector B9
|
|
//pGroup = CreateNewEnemyGroupDepartingFromSector( SEC_B9, (UINT8)(2 + Random( 2 ) + gGameOptions.ubDifficultyLevel), 0 );
|
|
//Move the patrol group north to attack Omerta
|
|
//AddWaypointToPGroup( pGroup, 9, 1 ); //A9
|
|
//Because we want them to arrive right away, we will toast the arrival event. The information
|
|
//is already set up though.
|
|
//DeleteStrategicEvent( EVENT_GROUP_ARRIVAL, pGroup->ubGroupID );
|
|
//Simply reinsert the event, but the time is now.
|
|
//AddStrategicEvent( EVENT_GROUP_ARRIVAL, GetWorldTotalMin(), pGroup->ubGroupID );
|
|
}
|
|
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_BETAVERSION, L"Ending Air Raid." );
|
|
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"The skies have cleared..." );
|
|
UnLockPauseState();
|
|
}
|
|
|
|
// Madd
|
|
void CheckForAndSetupAirRaid ()
|
|
{
|
|
//INT16 sSectorX;
|
|
//INT16 sSectorY;
|
|
//BOOLEAN fDoAirRaid=FALSE;
|
|
//SECTORINFO * pSector;
|
|
//INT16 sMenInSector;
|
|
//INT16 sMinMenForRaid;
|
|
//SOLDIERTYPE * pSoldier;
|
|
//INT16 cnt=0;
|
|
|
|
//DebugMsg(TOPIC_JA2,DBG_LEVEL_3,"CheckForAndSetupAirRaid");
|
|
|
|
//switch ( gGameOptions.ubDifficultyLevel )
|
|
//{
|
|
// case DIF_LEVEL_EASY:
|
|
// sMinMenForRaid = 10;
|
|
// break;
|
|
// case DIF_LEVEL_MEDIUM:
|
|
// sMinMenForRaid = 8;
|
|
// break;
|
|
// case DIF_LEVEL_HARD:
|
|
// sMinMenForRaid = 6;
|
|
// break;
|
|
// case DIF_LEVEL_INSANE:
|
|
// sMinMenForRaid = 4;
|
|
// break;
|
|
//}
|
|
|
|
//for ( sSectorY = 0;sSectorY < MAP_WORLD_Y;sSectorY++ )
|
|
//{
|
|
// for ( sSectorX = 0;sSectorX < MAP_WORLD_X;sSectorX++ )
|
|
// {
|
|
// pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
|
|
|
|
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CheckForAndSetupAirRaid: sector (%d,%d)",sSectorX,sSectorY));
|
|
|
|
// //only attack towns and sam sites
|
|
// if( StrategicMap[CALCULATE_STRATEGIC_INDEX( sSectorX, sSectorY ) ].bNameId == BLANK_SECTOR && !IsThisSectorASAMSector( sSectorX, sSectorY, 0 ))
|
|
// continue;
|
|
|
|
// sMenInSector = 0;
|
|
// cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
|
|
// for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++, pSoldier++ )
|
|
// {
|
|
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CheckForAndSetupAirRaid: soldier id = %d, (x,y,z) = (%d,%d,%d)",pSoldier->bActive,pSoldier->sSectorX,pSoldier->sSectorY,pSoldier->bSectorZ ));
|
|
// if ( pSoldier->sSectorX == sSectorX && pSoldier->sSectorY == sSectorY && pSoldier->bSectorZ == 0 && pSoldier->bActive )
|
|
// sMenInSector++;
|
|
// }
|
|
//
|
|
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CheckForAndSetupAirRaid: men %d, min men %d",sMenInSector,sMinMenForRaid));
|
|
// if ( !WillAirRaidBeStopped ( sSectorX, sSectorY ) && sMenInSector >= sMinMenForRaid && Random(4) < gGameOptions.ubDifficultyLevel )
|
|
// {
|
|
// DebugMsg(TOPIC_JA2,DBG_LEVEL_3,String("CheckForAndSetupAirRaid: do a raid"));
|
|
// fDoAirRaid = TRUE;
|
|
// break;
|
|
// }
|
|
// }
|
|
// if( fDoAirRaid )
|
|
// break;
|
|
//}
|
|
|
|
//if ( fDoAirRaid )
|
|
//{
|
|
// AIR_RAID_DEFINITION AirRaidDef;
|
|
|
|
// AirRaidDef.sSectorX = sSectorX;
|
|
// AirRaidDef.sSectorY = sSectorY;
|
|
// AirRaidDef.sSectorZ = 0;
|
|
// AirRaidDef.bIntensity = max(1,gGameOptions.ubDifficultyLevel-1) ;
|
|
// AirRaidDef.uiFlags = AIR_RAID_CAN_RANDOMIZE_TEASE_DIVES;
|
|
// AirRaidDef.ubNumMinsFromCurrentTime = Random(840) + 1;
|
|
|
|
// ScheduleAirRaid( &AirRaidDef );
|
|
|
|
return;
|
|
//}
|
|
}
|
|
|
|
void EnemyCallInAirStrike (INT16 sSectorX, INT16 sSectorY)
|
|
{
|
|
//AIR_RAID_DEFINITION AirRaidDef;
|
|
|
|
//AirRaidDef.sSectorX = sSectorX;
|
|
//AirRaidDef.sSectorY = sSectorY;
|
|
//AirRaidDef.sSectorZ = 0;
|
|
//AirRaidDef.bIntensity = max(1,gGameOptions.ubDifficultyLevel-1);
|
|
//AirRaidDef.uiFlags = AIR_RAID_BOMBS_ONLY;
|
|
//AirRaidDef.ubNumMinsFromCurrentTime = Random(2);
|
|
|
|
//if ( AirRaidDef.bIntensity > 0 )
|
|
// ScheduleAirRaid( &AirRaidDef );
|
|
|
|
return;
|
|
}
|