aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/mod/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/mod/scripts')
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut9
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut10
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_cloak_drone.gnut2
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_emp_titans.gnut22
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_spectres.gnut234
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_titans.gnut12
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_nuke_titans.gnut5
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_sniper_titans.gnut227
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_spawn.gnut2
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stalker.gnut93
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stationary_firing_positions.gnut43
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret.gnut113
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret_sentry.gnut6
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut15
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut1999
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd_events.nut1349
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd_nav.nut271
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/item_inventory/sv_item_inventory.gnut4
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut6
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut6
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal.nut5
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02.nut4
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock.nut9
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai.nut7
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai_fd.nut632
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch.nut9
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave.nut5
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead.nut9
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead_fd.nut569
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02.nut7
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise.nut9
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise_fd.nut618
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw.nut9
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut5
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames_fd.nut24
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut17
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/weapons/_cloaker.gnut6
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/weapons/sh_phase_shift.gnut774
46 files changed, 7284 insertions, 54 deletions
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut
index 3bdb1d8a..191c3b24 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut
@@ -12,7 +12,6 @@ global struct HarvesterStruct {
bool harvesterShieldDown
float harvesterDamageTaken
bool havesterWasDamaged
-
}
HarvesterStruct function SpawnHarvester( vector origin, vector angles, int health, int shieldHealth, int team )
@@ -32,14 +31,20 @@ HarvesterStruct function SpawnHarvester( vector origin, vector angles, int healt
SetObjectCanBeMeleed( harvester, true )
SetVisibleEntitiesInConeQueriableEnabled( harvester, true )
SetTeam(harvester,team)
-
+ // create dangerous area to all AI because we dont want any AI clipping into the harvester ever
+ // radius of 90 cos thats like 7.5 metres? AI shouldnt rally need to get closer than that (except nuke titans and stalkers)
+ // stalkers dont care about dangerous areas
+ // nuke titan detonation radius is larger than 90
+ AI_CreateDangerousArea_Static( harvester, null, 90, TEAM_INVALID, true, true, origin )
DispatchSpawn( harvester )
+ SetGlobalNetEnt( "FD_activeHarvester", harvester )
entity blackbox = CreatePropDynamic( MODEL_HARVESTER_TOWER_COLLISION, origin, angles, 0 )
blackbox.Hide()
blackbox.Solid()
// blackbox.kv.CollisionGroup = TRACE_COLLISION_GROUP_PLAYER
+ ToggleNPCPathsForEntity( blackbox, false )
entity rings = CreatePropDynamic( MODEL_HARVESTER_TOWER_RINGS, origin, angles, 6 )
thread PlayAnim( rings, "generator_cycle_fast" )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
index 76cb4ac4..24dbb62d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
@@ -3,6 +3,7 @@ global function SvLoadoutsMP_Init
global function SetLoadoutGracePeriodEnabled
global function SetWeaponDropsEnabled
+global function SetAllowLoadoutChangeFunc
global function AddCallback_OnTryGetTitanLoadout
global function GetTitanLoadoutForPlayer
@@ -22,6 +23,8 @@ struct {
array< TryGetTitanLoadoutCallbackType > onTryGetTitanLoadoutCallbacks
array<entity> dirtyLoadouts
+
+ bool functionref( entity ) allowChangeLoadoutFunc = null
} file
void function SvLoadoutsMP_Init()
@@ -60,6 +63,11 @@ void function SetLoadoutGracePeriodEnabled( bool enabled )
file.loadoutGracePeriodEnabled = enabled
}
+void function SetAllowLoadoutChangeFunc( bool functionref( entity ) func )
+{
+ file.allowChangeLoadoutFunc = func
+}
+
void function SetWeaponDropsEnabled( bool enabled )
{
file.weaponDropsEnabled = enabled
@@ -303,7 +311,7 @@ void function TryGivePilotLoadoutForGracePeriod( entity player )
else
respawnTimeReal = expect float( player.s.respawnTime )
- if ( ( ( Time() - respawnTimeReal <= CLASS_CHANGE_GRACE_PERIOD || GetGameState() < eGameState.Playing ) && file.loadoutGracePeriodEnabled ) || player.p.usingLoadoutCrate )
+ if ( ( ( Time() - respawnTimeReal <= CLASS_CHANGE_GRACE_PERIOD || GetGameState() < eGameState.Playing ) && file.loadoutGracePeriodEnabled ) || player.p.usingLoadoutCrate || ( file.allowChangeLoadoutFunc != null && file.allowChangeLoadoutFunc( player ) ) )
{
if ( !Loadouts_CanGivePilotLoadout( player ) && player.GetParent() != null && ( HasCinematicFlag( player, CE_FLAG_INTRO ) || HasCinematicFlag( player, CE_FLAG_CLASSIC_MP_SPAWNING ) || HasCinematicFlag( player, CE_FLAG_WAVE_SPAWNING ) ) )
thread GiveLoadoutWhenIntroOver( player )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_cloak_drone.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_cloak_drone.gnut
index e3addf81..a71b71f1 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_cloak_drone.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_cloak_drone.gnut
@@ -219,7 +219,7 @@ void function CloakedDronePathThink( entity cloakedDrone )
continue
//Don't cloak arc titans
- if ( guy.GetTargetName() == "empTitan" )
+ if ( IsEMPTitan( guy ) )
continue
if ( IsSniperSpectre( guy ) )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_emp_titans.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_emp_titans.gnut
index 638166c8..2792d617 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_emp_titans.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_emp_titans.gnut
@@ -3,6 +3,7 @@ untyped
global function EmpTitans_Init
global function EMPTitanThinkConstant
+global function IsEMPTitan
const DAMAGE_AGAINST_TITANS = 150
const DAMAGE_AGAINST_PILOTS = 40
@@ -11,6 +12,11 @@ const EMP_DAMAGE_TICK_RATE = 0.3
const FX_EMP_FIELD = $"P_xo_emp_field"
const FX_EMP_FIELD_1P = $"P_body_emp_1P"
+struct
+{
+ array<entity> empTitans
+} file
+
function EmpTitans_Init()
{
AddDamageCallbackSourceID( eDamageSourceId.titanEmpField, EmpField_DamagedEntity )
@@ -31,7 +37,8 @@ void function EMPTitanThinkConstant( entity titan )
DisableTitanRodeo( titan )
//Used to identify this titan as an arc titan
- SetTargetName( titan, "empTitan" )
+ // SetTargetName( titan, "empTitan" ) // unable to do this due to FD reasons
+ file.empTitans.append( titan )
//Wait for titan to stand up and exit bubble shield before deploying arc ability.
WaitTillHotDropComplete( titan )
@@ -88,6 +95,8 @@ void function EMPTitanThinkConstant( entity titan )
{
StopSoundOnEntity( titan, "EMP_Titan_Electrical_Field" )
EnableTitanRodeo( titan ) //Make the arc titan rodeoable now that it is no longer electrified.
+ if (file.empTitans.find( titan ) )
+ file.empTitans.remove( file.empTitans.find( titan ) )
}
foreach ( particleSystem in particles )
@@ -108,7 +117,7 @@ void function EMPTitanThinkConstant( entity titan )
{
origin = titan.GetAttachmentOrigin( attachID )
- RadiusDamage(
+ RadiusDamage(
origin, // center
titan, // attacker
titan, // inflictor
@@ -134,7 +143,7 @@ void function EmpField_DamagedEntity( entity target, var damageInfo )
entity titan = DamageInfo_GetAttacker( damageInfo )
if ( !IsValid( titan ) )
- return
+ return
local className = target.GetClassName()
if ( className == "rpg_missile" || className == "npc_turret_sentry" || className == "grenade" )
@@ -178,4 +187,9 @@ void function EmpField_DamagedEntity( entity target, var damageInfo )
string function GetEMPAttachmentForTitan( entity titan )
{
return "hijack"
-} \ No newline at end of file
+}
+
+bool function IsEMPTitan( entity titan )
+{
+ return file.empTitans.find( titan ) != -1 ? true : false
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_spectres.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_spectres.gnut
index 080e2f68..c63d9dd2 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_spectres.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_spectres.gnut
@@ -1,7 +1,237 @@
+untyped
+
global function MortarSpectreGetSquadFiringPositions
+global function MortarSpectreSquadThink
+
+global function SpectresPlayAnim
+
+const float MORTAR_SPECTRE_ABORT_ATTACK_HEALTH_FRAC = 0.50 // will stop mortar attack if any of the spectres health gets below 50% of their current health.
+const float MORTAR_SPECTRE_POSITION_SEARCH_RANGE = 6144 //3072 // How far away from their spawn point a mortar spectre squad will look for positions to mortar from.
+const float MORTAR_SPECTRE_ENGAGE_DELAY = 3.0 // How long before a mortar spectre squad start to attack the generator if interrupted getting to their mortar position.
+const float MORTAR_SPECTRE_REENGAGE_DELAY = 7.0 // How long before a mortar spectre squad goes back to attacking the generator after breaking of an attack.
+
+const float MORTAR_SPECTRE_TRACKER_SHIELD_MAX = 1000.0 // just using 1000 for now, doesnt really matter as long as the shieldFrac is accurate enough
+
+const array<vector> MORTAR_SPECTRE_POSITION_OFFSETS = [ < 60, 0, 0 >, < 0, 60, 0 >, < -60, 0, 0 >, < 0, -60, 0 > ] // guessing
+
array<vector> function MortarSpectreGetSquadFiringPositions( vector origin, vector testTarget )
{
- array< vector > ret
+ array<vector> ret
+ foreach ( vector position in MORTAR_SPECTRE_POSITION_OFFSETS )
+ {
+ ret.append( OriginToGround( testTarget + position + < 0, 0, 100 > ) ) // offsetting by 100 up so that OriginToGround doesnt put it down a floor
+ }
return ret
-} \ No newline at end of file
+}
+
+// --------------------------------------------------------------------
+// MORTAR SPECTRE LOGIC
+// --------------------------------------------------------------------
+
+void function MortarSpectreSquadThink( array< entity > spectres, entity harvester )
+{
+ if ( spectres.len() == 0)
+ return
+
+ // get the closest available stationary position for mortar spectres
+ StationaryAIPosition ornull mortarPosition = GetClosestAvailableStationaryPosition( /* spectres[0] isnt ideal but the spectres all spawn in the same position atm */ spectres[0].GetOrigin(), MORTAR_SPECTRE_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.MORTAR_SPECTRE )
+ while ( mortarPosition == null )
+ {
+ // in case all stationary spectre positions are in use wait for one to become available
+ wait 5
+ // should change this to use an average position or the start position or something but for now this is fine
+ mortarPosition = GetClosestAvailableStationaryPosition( spectres[0].GetOrigin(), MORTAR_SPECTRE_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.MORTAR_SPECTRE )
+ }
+ // create the entity responsible for managing this squad of spectres
+ // note: client shows the ui thing for this entity if the y angle is not 0
+ // it also shows the set up time thing based on the shield frac of the entity? weird
+ entity squadMarker = CreatePropScript( $"models/dev/empty_model.mdl", expect StationaryAIPosition( mortarPosition ).origin + < 0, 0, 150 >, < 0, 1, 0 > )
+ SetTargetName( squadMarker, "mortarPosition" )
+ squadMarker.SetShieldHealthMax( MORTAR_SPECTRE_TRACKER_SHIELD_MAX )
+ squadMarker.Minimap_SetCustomState( eMinimapObject_prop_script.FD_MORTAR_POSITION )
+
+ thread MortarSpectreSquadDeathThink( spectres, squadMarker )
+
+ // wait until at least 1 spectre has reached their position
+ int i = 0
+ foreach( entity spectre in spectres )
+ {
+ thread MortarSpectreMoveToMortarPosition( spectre, squadMarker, OriginToGround( expect StationaryAIPosition( mortarPosition ).origin + MORTAR_SPECTRE_POSITION_OFFSETS[i] + < 0, 0, 100 > ) )
+
+ if ( i++ >= MORTAR_SPECTRE_POSITION_OFFSETS.len() )
+ {
+ i = 0
+ }
+ }
+ squadMarker.WaitSignal( "BeginMortarAttack" )
+ // show the ui thing
+ squadMarker.SetAngles( < 0, 0, 0 > )
+ // start the setup timer
+ float setupEndTime = Time() + GetCurrentPlaylistVarFloat( "fd_mortar_spectre_setup_time", 5 ) // default to 5 seconds
+ // wait for setup timer
+ while ( Time() < setupEndTime )
+ {
+ if ( !IsValid( squadMarker ) )
+ {
+ break
+ }
+ float timeRemainingFrac = ( setupEndTime - Time() ) / GetCurrentPlaylistVarFloat( "fd_mortar_spectre_setup_time", 5 ) // default to 5 seconds
+ squadMarker.SetShieldHealth( ( 1 - timeRemainingFrac ) * MORTAR_SPECTRE_TRACKER_SHIELD_MAX )
+ WaitFrame()
+ }
+
+
+ if ( GetCurrentPlaylistVarFloat( "fd_grunt_shield_captains", 1 ) ) // idk if correct or not? doest seem to be a playlist var for mortar spectre shield
+ {
+ // create shield here
+
+ }
+
+ foreach( entity spectre in spectres )
+ {
+ if ( IsValid( spectre ) )
+ thread MortarSpectreAttack( spectre, harvester, squadMarker )
+ }
+}
+
+void function MortarSpectreAttack( entity spectre, entity harvester, entity signaler )
+{
+ spectre.EndSignal( "OnSyncedMeleeVictim" )
+ spectre.EndSignal( "OnDeath" )
+ spectre.EndSignal( "OnDestroy" )
+
+ string originalWeaponClassName
+ array<string> originalWeaponMods
+
+ spectre.ai.mortarTarget = harvester
+
+ thread MortarSpectreInterruptThink( spectre, harvester, signaler )
+
+ while( true )
+ {
+ array<entity> weapons = spectre.GetMainWeapons()
+ if ( weapons.len() == 0 )
+ break
+ entity weapon = weapons[0]
+ if ( !IsValid( weapon ) )
+ break
+ originalWeaponClassName = weapon.GetWeaponClassName()
+ originalWeaponMods = weapon.GetMods()
+
+ spectre.TakeWeaponNow( weapon.GetWeaponClassName() )
+ spectre.GiveWeapon( "mp_weapon_rocket_launcher", [ "fd_mortar_mode" ] )
+ thread MortarSpectreAttacksHarvester( spectre, harvester, signaler )
+
+ spectre.WaitSignal( "InterruptMortarAttack" )
+
+ spectre.TakeWeaponNow( "mp_weapon_rocket_launcher" )
+ spectre.GiveWeapon( originalWeaponClassName, originalWeaponMods )
+
+
+ wait MORTAR_SPECTRE_REENGAGE_DELAY
+ if ( !IsValid( spectre ) )
+ break
+ }
+}
+
+// this should hopefully be replaced with an animation that fires the mortar rockets properly, but i cant find it, so this will have to do
+void function MortarSpectreAttacksHarvester( entity spectre, entity harvester, entity signaler )
+{
+ spectre.EndSignal( "InterruptMortarAttack" )
+ spectre.EndSignal( "OnSyncedMeleeVictim" )
+ spectre.EndSignal( "OnDeath" )
+ spectre.EndSignal( "OnDestroy" )
+
+ entity weapon = spectre.GetActiveWeapon()
+ wait RandomFloatRange( 0, 4 ) // this is a complete guess, idk how long it takes for them to shoot normally
+ while ( true )
+ {
+ // if the spectre drops the weapon, or if something somehow steals it, we should stop firing missiles from it
+ if ( weapon.GetWeaponOwner() != spectre )
+ break
+ entity missile = weapon.FireWeaponMissile( spectre.GetOrigin(), < 0, 0, 90 >, 1800.0, damageTypes.projectileImpact, damageTypes.explosive, false, PROJECTILE_NOT_PREDICTED )
+ weapon.SetWeaponPrimaryAmmoCount( weapon.GetWeaponPrimaryAmmoCount() - 1 ) // remove the ammo manually
+ MortarMissileFiredCallback( missile, spectre )
+ wait RandomFloatRange( 6, 10 ) // this is a complete guess, idk how long it takes for them to shoot normally
+ }
+}
+
+void function MortarSpectreSquadDeathThink( array< entity > spectres, entity signaler )
+{
+ int numAlive = spectres.len() // assume all alive at start
+ while ( numAlive != 0 )
+ {
+ WaitFrame()
+ numAlive = spectres.len()
+ foreach ( entity spectre in spectres )
+ {
+ if ( IsValid( spectre ) && IsAlive( spectre ) )
+ continue
+ numAlive--
+ }
+ }
+ signaler.Destroy()
+}
+
+void function MortarSpectreMoveToMortarPosition( entity spectre, entity signaler, vector position )
+{
+ spectre.EndSignal( "OnSyncedMeleeVictim" )
+ spectre.EndSignal( "OnDeath" )
+ spectre.EndSignal( "OnDestroy" )
+
+ spectre.AssaultPoint( position )
+ spectre.AssaultSetGoalRadius( spectre.GetMinGoalRadius() )
+ spectre.AssaultSetFightRadius( 0 )
+
+ table result = spectre.WaitSignal( "OnFinishedAssault", "OnFailedToPath" )
+ if ( result.signal == "OnFinishedAssault" )
+ signaler.Signal( "BeginMortarAttack" )
+}
+
+void function MortarSpectreInterruptThink( entity spectre, entity harvester, entity signaler )
+{
+ spectre.EndSignal( "OnSyncedMeleeVictim" )
+ spectre.EndSignal( "OnDeath" )
+ spectre.EndSignal( "OnDestroy" )
+
+ float oldHealth = spectre.GetHealth().tofloat()
+
+ while ( true )
+ {
+ WaitFrame()
+ // check if we have taken enough damage to warrant an interruption, and we are close enough to the mortar position
+ if ( spectre.GetHealth().tofloat() / oldHealth < MORTAR_SPECTRE_ABORT_ATTACK_HEALTH_FRAC && Distance2D( spectre.GetOrigin(), signaler.GetOrigin() ) <= 80 ) // random magic 80 for now
+ {
+ oldHealth = spectre.GetHealth().tofloat()
+ spectre.Signal( "InterruptMortarAttack" )
+ continue
+ }
+
+ if ( IsValid( spectre.GetEnemy() ) && spectre.CanSee( spectre.GetEnemy() ) && !IsCloaked( spectre.GetEnemy() ) )
+ {
+ oldHealth = spectre.GetHealth().tofloat()
+ spectre.Signal( "InterruptMortarAttack" )
+ }
+ }
+}
+
+void function SpectresPlayAnim( string anim )
+{
+ foreach (entity spectre in GetNPCArrayByClass("npc_spectre"))
+ {
+ thread thing( anim, spectre)
+ }
+}
+
+void function thing( string anim, entity spectre )
+{
+ try
+ {
+ PlayAnim( spectre, anim)
+ }
+ catch (ex)
+ {
+ print(ex)
+ }
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_titans.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_titans.gnut
index 08598808..f23c05f9 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_titans.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_mortar_titans.gnut
@@ -100,14 +100,14 @@ void function MortarMissileThink( entity missile, entity weaponOwner )
{
float frac = min( 1, pow( ( Time() - startTime ) / estTravelTime, 2.0 ) )
- if ( frac > 1.0 )
- break
+ if ( frac > 1.0 )
+ break
float homingSpeed = GraphCapped( frac, 0, 1, homingSpeedMin, homingSpeedMax )
- missile.SetHomingSpeeds( homingSpeed, 0 )
+ missile.SetHomingSpeeds( homingSpeed, 0 )
- wait 0.25
+ wait 0.25
}
missile.ClearMissileTargetPosition()
@@ -304,12 +304,12 @@ void function MortarTitanThink( entity titan, entity generator )
WaitTillHotDropComplete( titan )
float minEngagementDuration = 5
- StationaryAIPosition ornull mortarPosition = GetRandomStationaryPosition( titan.GetOrigin(), MORTAR_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.MORTAR_TITAN )
+ StationaryAIPosition ornull mortarPosition = GetClosestAvailableStationaryPosition( titan.GetOrigin(), MORTAR_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.MORTAR_TITAN )
while ( mortarPosition == null )
{
// incase all stationary titan positions are in use wait for one to become available
wait 5
- mortarPosition = GetRandomStationaryPosition( titan.GetOrigin(), MORTAR_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.MORTAR_TITAN )
+ mortarPosition = GetClosestAvailableStationaryPosition( titan.GetOrigin(), MORTAR_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.MORTAR_TITAN )
}
expect StationaryAIPosition( mortarPosition )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_nuke_titans.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_nuke_titans.gnut
index 0d4b43c9..1e8ec316 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_nuke_titans.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_nuke_titans.gnut
@@ -33,6 +33,9 @@ void function NukeTitanSeekOutGenerator( entity titan, entity generator )
titan.EndSignal( "OnDeath" )
titan.EndSignal( "OnDestroy" )
titan.EndSignal( "Doomed" )
+ // should fix crash with invalid generator?
+ generator.EndSignal( "OnDeath" )
+ generator.EndSignal( "OnDestroy" )
WaitSignal( titan, "FD_ReachedHarvester", "OnFailedToPath" )
@@ -58,7 +61,7 @@ void function NukeTitanSeekOutGenerator( entity titan, entity generator )
{
titan.SetEnemy( generator )
thread AssaultOrigin( titan, validPos[0], goalRadius )
- titan.AssaultSetFightRadius( goalRadius )
+ titan.AssaultSetFightRadius( 0 ) // dont want to set a fight radius because then the nuke titan will stop and shoot
wait 0.5
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_sniper_titans.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_sniper_titans.gnut
index 37b89169..b1ff4fa2 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_sniper_titans.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_sniper_titans.gnut
@@ -1 +1,226 @@
-//fuck \ No newline at end of file
+untyped
+
+global function MoveToSniperPosition
+global function SniperTitanThink
+
+const float SNIPER_TITAN_POSITION_SEARCH_RANGE = 4120
+
+
+
+void function MoveToSniperPosition( entity titan, vector origin, entity target )
+{
+ titan.EndSignal( "OnSyncedMeleeVictim" )
+ titan.EndSignal( "OnDeath" )
+ titan.EndSignal( "OnDestroy" )
+ target.EndSignal( "OnDeath" )
+ target.EndSignal( "OnDestroy" )
+
+ titan.EnableNPCMoveFlag( NPCMF_PREFER_SPRINT )
+
+ float goalRadius = titan.GetMinGoalRadius()
+
+ OnThreadEnd(
+ function() : ( titan )
+ {
+ if ( !IsValid( titan ) )
+ return
+
+ local classname = titan.GetClassName()
+ titan.DisableNPCMoveFlag( NPCMF_PREFER_SPRINT )
+ }
+ )
+
+ local tries = 0
+ while( true )
+ {
+ local dist = Distance( titan.GetOrigin(), origin )
+ if ( dist <= goalRadius * 2 )
+ break
+
+ printt( "Sniper titan moving toward his goal", dist, tries++ )
+ titan.AssaultPoint( origin )
+ titan.AssaultSetGoalRadius( goalRadius )
+ titan.AssaultSetFightRadius( 0 )
+ local result = WaitSignal( titan, "OnFinishedAssault", "OnEnterGoalRadius" )
+ printt( "Sniper titan done moving into position")
+ }
+}
+
+void function SniperTitanThink( entity titan, entity generator)
+{
+ titan.EndSignal( "OnSyncedMeleeVictim" )
+ titan.EndSignal( "OnDeath" )
+ titan.EndSignal( "OnDestroy" )
+ generator.EndSignal( "OnDeath" )
+ generator.EndSignal( "OnDestroy" )
+
+ entity soul = titan.GetTitanSoul()
+ soul.EndSignal( "OnDestroy" )
+
+ titan.SetScriptName( "sniper_titan" )
+
+ WaitTillHotDropComplete( titan )
+
+ float minEngagementDuration = 5
+ StationaryAIPosition ornull sniperPosition = GetClosestAvailableStationaryPosition( titan.GetOrigin(), SNIPER_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.SNIPER_TITAN )
+ while ( sniperPosition == null )
+ {
+ // incase all stationary titan positions are in use wait for one to become available
+ wait 5
+ sniperPosition = GetClosestAvailableStationaryPosition( titan.GetOrigin(), SNIPER_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.SNIPER_TITAN )
+ }
+
+ expect StationaryAIPosition( sniperPosition )
+
+ ClaimStationaryAIPosition( sniperPosition )
+
+ OnThreadEnd(
+ function() : ( sniperPosition )
+ {
+ // release sniper position when dead
+ ReleaseStationaryAIPosition( sniperPosition )
+ }
+ )
+ titan.SetEnemyChangeCallback( EnemyChanged)
+ thread CheckEnemy( titan ,generator)
+ while( true )
+ {
+ WaitFrame()
+ vector origin = sniperPosition.origin
+ waitthread MoveToSniperPosition( titan, origin, generator )
+
+ thread SniperTitanAttack( titan, generator )
+
+ waitthread WaitForInterruption( titan ,generator)
+ }
+}
+// check if titan can see enemy
+void function CheckEnemy(entity titan,entity generator)
+{
+ titan.EndSignal( "OnSyncedMeleeVictim" )
+ titan.EndSignal( "OnDeath" )
+ titan.EndSignal( "OnDestroy" )
+ generator.EndSignal( "OnDeath" )
+ generator.EndSignal( "OnDestroy" )
+
+ while (IsValid(titan))
+ {
+ wait 1
+ if (!IsValid(titan.GetEnemy()))
+ continue
+
+ if (!titan.CanSee(titan.GetEnemy()) && titan.GetEnemy() == generator)
+ {
+ waitthread CreateSniperTarget( titan , generator)
+ wait 1 // wait for 1 second so the signal doesn't get called too soon
+ table result = WaitSignal( titan, "SniperSwitchedEnemy" )
+ }
+ }
+}
+
+void function CreateSniperTarget(entity titan,entity generator)
+{
+ titan.EndSignal( "OnSyncedMeleeVictim" )
+ titan.EndSignal( "OnDeath" )
+ titan.EndSignal( "OnDestroy" )
+ generator.EndSignal( "OnDeath" )
+ generator.EndSignal( "OnDestroy" )
+
+ vector origin = titan.EyePosition()
+ TraceResults result = TraceLine( origin, generator.GetOrigin() + <0, 0, 250>, titan , TRACE_MASK_BLOCKLOS, TRACE_COLLISION_GROUP_NONE )
+ // check if the endPos is too near the titan
+ while (Distance(result.endPos, origin) < 200 || Distance(result.endPos, generator.GetOrigin()) < 200)
+ {
+ wait 2.0
+ origin = titan.EyePosition()
+ result = TraceLine( origin, generator.GetOrigin() + <0, 0, 250>, titan )
+ }
+ entity snipertarget = CreateEntity( "info_target" )
+ DispatchSpawn( snipertarget )
+ snipertarget.SetOrigin( result.endPos ) // in front of the harvester i hope
+ SetTeam( snipertarget, TEAM_MILITIA )
+ snipertarget.EnableAttackableByAI( 40, 0, AI_AP_FLAG_NONE )
+ titan.SetEnemy( snipertarget )
+ wait 1 // wait for 1 second so the signal doesn't get called too soon
+ titan.WaitSignal( "SniperSwitchedEnemy" )
+
+ OnThreadEnd(
+ function() : ( snipertarget )
+ {
+ if ( !IsValid( snipertarget ) )
+ return
+
+ snipertarget.Destroy()
+ }
+ )
+}
+
+void function EnemyChanged( entity titan)
+{
+ titan.Signal( "SniperSwitchedEnemy" )
+ entity enemy = titan.GetEnemy()
+ if ( !IsValid( enemy ) ) // if you have no enemy, focus on attacking the harvester
+ {
+ thread SniperTitanAttack( titan, fd_harvester.harvester)
+ enemy = fd_harvester.harvester
+ }
+}
+
+function SniperTitanAttack( entity titan, entity target )
+{
+ titan.EndSignal( "OnSyncedMeleeVictim" )
+ titan.EndSignal( "OnDeath" )
+ titan.EndSignal( "OnDestroy" )
+
+ OnThreadEnd(
+ function() : ( titan )
+ {
+ if ( !IsValid( titan ) )
+ return
+ }
+ )
+
+ titan.SetEnemy( target )
+}
+
+void function WaitForInterruption( entity titan ,entity generator)
+{
+ Assert( IsNewThread(), "Must be threaded off" )
+
+ titan.EndSignal( "OnSyncedMeleeVictim" )
+ titan.EndSignal( "OnDeath" )
+ titan.EndSignal( "OnDestroy" )
+ generator.EndSignal( "OnDeath" )
+ generator.EndSignal( "OnDestroy" )
+
+ entity soul = titan.GetTitanSoul()
+ soul.EndSignal( "OnDestroy" )
+
+ float playerProximityDistSqr = pow( 256, 2 )
+ float healthBreakOff = ( titan.GetHealth() + soul.GetShieldHealth() ) * 0.9
+
+ while( true )
+ {
+ if ( IsEnemyWithinDist( titan, playerProximityDistSqr ) )
+ break
+ if ( ( titan.GetHealth() + soul.GetShieldHealth() ) < healthBreakOff )
+ break
+ wait 1
+ }
+
+ titan.ClearEnemy()
+}
+
+bool function IsEnemyWithinDist( entity titan, float dist )
+{
+ vector origin = titan.GetOrigin()
+ array<entity> players = GetPlayerArrayOfEnemies_Alive( titan.GetTeam() )
+
+ foreach( player in players )
+ {
+ if ( DistanceSqr( player.GetOrigin(), origin ) < dist )
+ return true
+ }
+
+ return false
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_spawn.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_spawn.gnut
index 7e4d2cdd..8599f429 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_spawn.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_spawn.gnut
@@ -223,7 +223,7 @@ entity function CreateOgre( int team, vector origin, vector angles, array<string
entity function CreateArcTitan( int team, vector origin, vector angles, array<string> settingsMods = [] )
{
entity npc = CreateNPCTitan( "titan_stryder", team, origin, angles, settingsMods )
- SetSpawnOption_AISettings( npc, "npc_titan_arc" )
+ SetSpawnOption_AISettings( npc, "npc_titan_stryder_leadwall_arc" )
return npc
}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stalker.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stalker.gnut
index f49560e0..0b4d6a9a 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stalker.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stalker.gnut
@@ -1,7 +1,9 @@
+untyped
global function AiStalker_Init
global function GetDeathForce
global function StalkerGearOverloads
global function StalkerMeltingDown
+global function FDStalkerThink
global function IsStalkerLimbBlownOff
@@ -157,6 +159,95 @@ void function StalkerOnDamaged_Internal( entity npc, var damageInfo )
npc.SetActivityModifier( ACT_MODIFIER_STAGGER, true )
}
}
+ if( GameRules_GetGameMode() == FD )
+ thread StalkerSprint( npc, damageInfo )
+}
+
+void function StalkerSprint( entity npc, var damageInfo )
+{
+ npc.EndSignal("OnDeath")
+ npc.EndSignal("OnDestroy")
+ float damage = DamageInfo_GetDamage( damageInfo )
+
+ if (!IsCrawling(npc)&&( npc.GetHealth() - damage < 50 || npc.GetHealth() <= 80))
+ {
+ entity weapon = npc.GetActiveWeapon()
+ if (IsValid(weapon))
+ npc.TakeActiveWeapon() // when stalkers fall over on harvester they will randomly shoot their guns, we don't want that.
+ npc.EnableNPCMoveFlag( NPCMF_PREFER_SPRINT )
+ npc.SetCapabilityFlag( bits_CAP_MOVE_SHOOT | bits_CAP_WEAPON_RANGE_ATTACK1 | bits_CAP_AIM_GUN, false )
+ npc.SetNPCFlag( NPC_IGNORE_ALL, true )
+ npc.SetNPCFlag( NPC_DISABLE_SENSING, true )
+ npc.SetNoTarget( true )
+ npc.ClearMoveAnim()
+ npc.SetMoveAnim("sp_spectre_sprint_F")
+ npc.s.isSprinting = true
+ }
+}
+
+void function FDStalkerThink( entity npc, entity generator )
+{
+ npc.EndSignal( "OnDeath" )
+ npc.EndSignal( "OnDestroy" )
+ generator.EndSignal( "OnDeath" )
+ generator.EndSignal( "OnDestroy" )
+ npc.s.isSprinting <- false
+ thread FDStalkerGetsStunned( npc , generator )
+ while ( IsAlive( npc ) )
+ {
+ WaitFrame()
+
+ // cant sprint with 1 leg
+ // also upped to 1800 so that stalkers sprint from roughly their vanilla positions, could probably do it based on % of distance left to go?
+ if ( DistanceSqr( npc.GetOrigin(), generator.GetOrigin() ) < (1800 * 1800) )
+ {
+ if(!IsCrawling( npc ) && !npc.s.isSprinting)
+ {
+ entity weapon = npc.GetActiveWeapon()
+ if (IsValid(weapon))
+ npc.TakeActiveWeapon() // when stalkers fall over on harvester they will randomly shoot their guns, we don't want that.
+ npc.EnableNPCMoveFlag( NPCMF_PREFER_SPRINT )
+ npc.SetCapabilityFlag( bits_CAP_MOVE_SHOOT | bits_CAP_WEAPON_RANGE_ATTACK1 | bits_CAP_AIM_GUN, false )
+ npc.EnableNPCFlag( NPC_DISABLE_SENSING | NPC_IGNORE_ALL )
+ npc.ClearMoveAnim()
+ npc.SetMoveAnim("sp_spectre_sprint_F")
+ npc.SetNoTarget( true )
+ // stalkers were just going to the final node and stopping, meaning they never actually reached the harvester
+ npc.s.isSprinting = true
+ }
+ npc.AssaultPoint(generator.GetOrigin())
+ }
+
+ // upped from 230 to more accurately mimic vanilla i think?
+ if ( DistanceSqr( npc.GetOrigin(), generator.GetOrigin() ) > (275 * 275) )
+ continue
+
+ break
+ }
+
+ thread StalkerGearOverloads( npc )
+}
+
+void function FDStalkerGetsStunned( entity npc , entity generator )
+{
+ npc.EndSignal( "OnDeath" )
+ npc.EndSignal( "OnDestroy" )
+ npc.WaitSignal( "ArcStunned" )
+ print("arc trapped...")
+
+ if(IsCrawling(npc))
+ return
+
+ entity weapon = npc.GetActiveWeapon()
+ if (IsValid(weapon))
+ npc.TakeActiveWeapon() // when stalkers fall over on harvester they will randomly shoot their guns, we don't want that.
+ npc.EnableNPCMoveFlag( NPCMF_PREFER_SPRINT )
+ npc.SetCapabilityFlag( bits_CAP_MOVE_SHOOT | bits_CAP_WEAPON_RANGE_ATTACK1 | bits_CAP_AIM_GUN, false )
+ npc.EnableNPCFlag( NPC_DISABLE_SENSING | NPC_IGNORE_ALL )
+ npc.ClearMoveAnim()
+ npc.SetMoveAnim("sp_spectre_sprint_F")
+ npc.SetNoTarget( true ) // stop keeping track of any player and instead go for the harvester
+ npc.s.isSprinting = true
}
bool function TryDismemberStalker( entity npc, var damageInfo, entity attacker, int hitGroup )
@@ -603,4 +694,4 @@ vector function GetDeathForce()
vector angles = <RandomFloatRange(-45,-75),RandomFloat(360),0>
vector forward = AnglesToForward( angles )
return forward * RandomFloatRange( 0.25, 0.75 )
-} \ No newline at end of file
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stationary_firing_positions.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stationary_firing_positions.gnut
index 50b6cc75..430de58a 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stationary_firing_positions.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_stationary_firing_positions.gnut
@@ -5,6 +5,7 @@ global function GetRandomStationaryPosition
global function GetClosestAvailableStationaryPosition
global function ClaimStationaryAIPosition
global function ReleaseStationaryAIPosition
+global function DebugDrawStationaryAiPositions
global enum eStationaryAIPositionTypes
{
@@ -258,4 +259,44 @@ int function DistanceCompareClosestForStationaryAIPosition( ArrayDistanceEntryFo
return -1
return 0;
-} \ No newline at end of file
+}
+
+
+void function DebugDrawStationaryAiPositions( int typeMask )
+{
+ thread DebugDrawStationaryAiPositions_thread( typeMask )
+}
+
+
+void function DebugDrawStationaryAiPositions_thread( int typeMask )
+{
+ while( true )
+ {
+ for( int i = 0; i < 4; i++ )
+ {
+ if( ( 1 << i ) & typeMask )
+ foreach( StationaryAIPosition a in file.stationaryPositions[i] )
+ {
+ switch( i )
+ {
+ case 0:
+ DebugDrawSphere( a.origin, 50, 255, 255, 0,false, 0.5 )
+ case 1:
+ DebugDrawSphere( a.origin, 50, 0, 255, 255, false, 0.5 )
+ case 2:
+ DebugDrawSphere( a.origin, 50, 0, 0, 255, false, 0.5 )
+ case 3:
+ DebugDrawSphere( a.origin, 50, 255, 0, 255, false, 0.5 )
+ }
+
+ if( a.inUse )
+ DebugDrawSphere( a.origin, 40, 255, 0, 0, false, 0.5 )
+ else
+ DebugDrawSphere( a.origin, 40, 0, 255, 0, false, 0.5 )
+
+ }
+ }
+ wait 0.4
+ }
+
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret.gnut
index 73813385..08d76f7d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret.gnut
@@ -1,11 +1,16 @@
+untyped
global function AiTurret_Init
global function GetMegaTurretLinkedToPanel
global function MegaTurretUsabilityFunc
global function SetUsePromptForPanel
+global function IsTurretActive
+global function TurretRefundThink
+global function RevivableTurret_DamageCallback
+global function RevivableTurret_Revive
void function AiTurret_Init()
{
-
+ RegisterSignal( "TurretOffline" )
}
entity function GetMegaTurretLinkedToPanel( entity panel )
@@ -21,4 +26,108 @@ string function MegaTurretUsabilityFunc( var turret, var panel )
void function SetUsePromptForPanel( var panel, var turret )
{
-} \ No newline at end of file
+}
+
+bool function IsTurretActive( entity turret )
+{
+ // ----- Turret State ----- //
+ // TURRET_SEARCHING , TURRET_INACTIVE , TURRET_ACTIVE , TURRET_DEPLOYING , TURRET_RETIRING , TURRET_DEAD //
+
+ bool turretsActive = turret.GetTurretState() == TURRET_DEPLOYING
+ turretsActive = turretsActive || turret.GetTurretState() == TURRET_SEARCHING
+ turretsActive = turretsActive || turret.GetTurretState() == TURRET_ACTIVE
+ return turretsActive
+}
+
+void function TurretRefundThink( entity turret )
+{
+ turret.EndSignal( "OnDestroy" )
+ turret.EndSignal( "OnDeath" )
+ turret.EndSignal( "CancelRefund" )
+ turret.EndSignal( "TurretOffline" )
+
+ while( turret.e.burnReward == "" || !IsTurretActive( turret ) ){
+ WaitFrame()
+ }
+ turret.SetUsable()
+ turret.SetUsableByGroup( "owner pilot" )
+ turret.SetUsePrompts( "#REFUND_HOLD_USE", "#REFUND_PRESS_USE" )
+
+ entity player = expect entity( turret.WaitSignal( "OnPlayerUse" ).player )
+
+ if ( turret.e.burnReward == "" )
+ return
+
+ BurnMeter_GiveRewardDirect( player, turret.e.burnReward )
+ entity weapon = player.GetOffhandWeapon( OFFHAND_INVENTORY )
+
+ // Defensive: meaning the boost didn't make it to the inventory for some reason
+ if ( weapon == null )
+ return
+
+ weapon.w.savedKillCount = int( turret.kv.killCount )
+ turret.DisableTurret()
+ turret.Signal( "StopTurretLaser" )
+ weapon.e.fd_roundDeployed = turret.e.fd_roundDeployed
+
+ EmitSoundAtPosition( TEAM_UNASSIGNED, turret.GetOrigin(), "Emplacement_Move_Dissolve" )
+ turret.Signal( "BoostRefunded" )
+ turret.UnsetUsable()
+ turret.SetInvulnerable()
+ turret.Dissolve( ENTITY_DISSOLVE_CORE, Vector( 0, 0, 0 ), 100 )
+}
+
+void function RevivableTurret_DamageCallback( entity turret, var damageInfo )
+{
+ if( turret.GetHealth() <= DamageInfo_GetDamage( damageInfo ) )
+ {
+ turret.Signal( "TurretOffline" )
+ turret.SetHealth( 1 )
+ turret.SetUsable()
+ turret.SetUsableByGroup( "friendlies pilot" )
+ turret.SetUsePrompts( "#TURRET_WAKEUP_HOLD_USE", "#TURRET_WAKEUP_PRESS_USE" )
+ turret.useFunction = RevivableTurret_UseFunction
+ thread RevivableTurret_Kill( turret )
+ DamageInfo_SetDamage( damageInfo, 0.0 )
+ }
+}
+
+function RevivableTurret_UseFunction( player , turret )
+{
+ entity tur = expect entity( turret )
+ entity ent = expect entity( player )
+ entity owner = tur.GetBossPlayer()
+ if( ent != owner )
+ {
+ int ownerEHandle = owner.GetEncodedEHandle()
+ AddPlayerScore( ent, "FDRepairTurret" )
+ MessageToTeam( TEAM_MILITIA,eEventNotifications.FD_TurretRepair, null, ent, ownerEHandle )
+ }
+ thread RevivableTurret_Revive( tur )
+ return true
+}
+
+
+void function RevivableTurret_Revive( entity turret )
+{
+ turret.UnsetUsable()
+ turret.SetHealth( turret.GetMaxHealth() )
+ turret.ClearInvulnerable()
+ turret.Anim_ScriptedPlay( "deploy" )
+ wait 1.0
+ turret.EnableTurret()
+ turret.DisableNPCFlag( NPC_IGNORE_ALL )
+ turret.SetNoTarget( false )
+ thread TurretRefundThink( turret )
+}
+
+void function RevivableTurret_Kill( entity turret )
+{
+ turret.EnableNPCFlag( NPC_IGNORE_ALL )
+ turret.SetNoTarget( true )
+ turret.SetInvulnerable()
+ turret.Anim_ScriptedPlay( "undeploy" )
+ wait 1
+ turret.SetNoTarget( true )
+ turret.DisableTurret()
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret_sentry.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret_sentry.gnut
index e34b3082..5d0cff0a 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret_sentry.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_turret_sentry.gnut
@@ -8,13 +8,14 @@ const SENTRY_TURRET_AIM_FX_BLUE = $"P_wpn_lasercannon_aim_short_blue"
void function AiTurretSentry_Init()
{
PrecacheParticleSystem( DEAD_SENTRY_TURRET_FX )
- //PrecacheParticleSystem( SENTRY_TURRET_AIM_FX_RED )
- //PrecacheParticleSystem( SENTRY_TURRET_AIM_FX_BLUE )
+ PrecacheParticleSystem( SENTRY_TURRET_AIM_FX_RED )
+ PrecacheParticleSystem( SENTRY_TURRET_AIM_FX_BLUE )
//PrecacheParticleSystem( SENTRY_TURRET_AIM_FX2 )
AddSpawnCallback( "npc_turret_sentry", LightTurretSpawnFunction )
AddDeathCallback( "npc_turret_sentry", LightTurretDeathFX )
+ RegisterSignal( "StopTurretLaser" )
//RegisterSignal( "TurretDisabled" )
//RegisterSignal( "HandleTargetDeath" )
//RegisterSignal( "OnPlayerDisconnectResetTurret" )
@@ -55,6 +56,7 @@ void function LightTurretSpawnFunction( entity turret )
void function SentryTurretAimLaser( entity turret )
{
+ EndSignal( turret, "StopTurretLaser" )
entity fx1 = PlayLoopFXOnEntity( SENTRY_TURRET_AIM_FX_RED, turret, "camera_glow", null, null, ENTITY_VISIBLE_TO_ENEMY )
entity fx2 = PlayLoopFXOnEntity( SENTRY_TURRET_AIM_FX_BLUE, turret, "camera_glow", null, null, ENTITY_VISIBLE_TO_FRIENDLY )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut b/Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut
index 56750352..eb4e111c 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/burnmeter/_burnmeter.gnut
@@ -67,6 +67,7 @@ void function BurnMeter_Init()
AddCallback_OnClientConnected( InitBurncardsForLateJoiner )
AddCallback_OnPlayerRespawned( StartPhaseRewindLifetime )
+ AddCallback_OnPlayerRespawned( InitialisePermenantAmpedWeaponsForPlayer )
AddCallback_OnTitanBecomesPilot( RemoveAmpedWeaponsForTitanPilot )
// necessary signals
@@ -347,9 +348,10 @@ void function PlayerUsesAmpedWeaponsBurncardThreaded( entity player )
void function RemoveAmpedWeaponsForTitanPilot( entity player, entity titan )
{
- foreach ( entity weapon in player.GetMainWeapons() )
- foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) )
- weapon.RemoveMod( mod )
+ if ( !( "hasPermenantAmpedWeapons" in player.s ) || !player.s.hasPermenantAmpedWeapons )
+ foreach ( entity weapon in player.GetMainWeapons() )
+ foreach ( string mod in GetWeaponBurnMods( weapon.GetWeaponClassName() ) )
+ weapon.RemoveMod( mod )
}
void function PlayerUsesSmartPistolBurncard( entity player )
@@ -570,8 +572,15 @@ void function PlayerUsesNukeBurncardThreaded( entity player )
thread TitanEjectPlayer( titan, true )
}
+void function InitialisePermenantAmpedWeaponsForPlayer( entity player )
+{
+ player.s.hasPermenantAmpedWeapons <- false
+}
+
void function PlayerUsesPermanentAmpedWeaponsBurncard( entity player )
{
+ player.s.hasPermenantAmpedWeapons = true
+
array<entity> weapons = player.GetMainWeapons()
//weapons.extend( player.GetOffhandWeapons() ) // idk? unsure of vanilla behaviour here
foreach ( entity weapon in weapons )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
index 8a6b8bf0..a730eb90 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
@@ -1,12 +1,2007 @@
+untyped
+
global function GamemodeFD_Init
global function RateSpawnpoints_FD
+global function startHarvester
+global function IsHarvesterAlive
+global function GetTargetNameForID
+
+global function DisableTitanSelection
+global function DisableTitanSelectionForPlayer
+global function EnableTitanSelection
+global function EnableTitanSelectionForPlayer
+global function FD_DropshipSetAnimationOverride
+
+enum eDropshipState{
+ Idle,
+ InProgress,
+ Returning
+ _count_
+}
+
+
+
+
+struct player_struct_fd{
+ bool diedThisRound
+ int scoreThisRound
+ int moneyThisRound
+ array< entity > deployedEntityThisRound
+ /*
+ int totalMVPs
+ int mortarUnitsKilled
+ int moneySpend
+ int coresUsed
+ float longestTitanLife
+ int turretsRepaired
+ int moneyShared
+ float timeNearHarvester //dont know how to track
+ float longestLife
+ int heals //dont know what to track
+ int titanKills
+ float damageDealt
+ int harvesterHeals
+ int turretKills
+ */
+ float lastRespawn
+ float lastTitanDrop
+ float lastNearHarvester
+ bool leaveHarvester
+}
+
+global HarvesterStruct& fd_harvester
+global vector shopPosition
+global vector shopAngles = < 0, 0, 0 >
+global vector FD_spawnPosition
+global vector FD_spawnAngles = < 0, 0, 0 >
+global table< string, array<vector> > routes
+global array<entity> routeNodes
+global array<entity> spawnedNPCs
+
+
+
+
+struct {
+ array<entity> aiSpawnpoints
+ array<entity> smokePoints
+ array<float> harvesterDamageSource
+ bool havesterWasDamaged
+ bool harvesterShieldDown
+ float harvesterDamageTaken
+ table<entity, player_struct_fd> players
+ table<entity, table<string, float> > playerAwardStats
+ entity harvester_info
+ bool playersHaveTitans = false
+ bool waveRestart = false
+
+ string animationOverride = ""
+ int dropshipState
+ int playersInShip
+ entity dropship
+ array<entity> playersInDropship
+}file
+
+
+const array<string> DROPSHIP_IDLE_ANIMS_POV = [
+
+ "ptpov_ds_coop_side_intro_gen_idle_B",
+ "ptpov_ds_coop_side_intro_gen_idle_A",
+ "ptpov_ds_coop_side_intro_gen_idle_C",
+ "ptpov_ds_coop_side_intro_gen_idle_D"
+]
+
+const array<string> DROPSHIP_IDLE_ANIMS = [
+
+ "pt_ds_coop_side_intro_gen_idle_B",
+ "pt_ds_coop_side_intro_gen_idle_A",
+ "pt_ds_coop_side_intro_gen_idle_C",
+ "pt_ds_coop_side_intro_gen_idle_D"
+]
+
+const array<string> DROPSHIP_EXIT_ANIMS_POV = [
+ "ptpov_ds_coop_side_intro_gen_exit_B",
+ "ptpov_ds_coop_side_intro_gen_exit_A",
+ "ptpov_ds_coop_side_intro_gen_exit_C",
+ "ptpov_ds_coop_side_intro_gen_exit_D"
+]
+
+const array<string> DROPSHIP_EXIT_ANIMS = [
+ "pt_ds_coop_side_intro_gen_exit_B",
+ "pt_ds_coop_side_intro_gen_exit_A",
+ "pt_ds_coop_side_intro_gen_exit_C",
+ "pt_ds_coop_side_intro_gen_exit_D"
+]
void function GamemodeFD_Init()
{
PrecacheModel( MODEL_ATTRITION_BANK )
+ PrecacheModel( $"models/humans/grunts/imc_grunt_shield_captain.mdl" )
+ PrecacheParticleSystem( $"P_smokescreen_FD" )
+
+ RegisterSignal( "SniperSwitchedEnemy" ) // for use in SniperTitanThink behavior.
+ RegisterSignal( "FD_ReachedHarvester" )
+ RegisterSignal( "OnFailedToPath" )
+
+ SetRoundBased( true )
+ SetShouldUseRoundWinningKillReplay( false )
+ Riff_ForceBoostAvailability( eBoostAvailability.Disabled )
+ PlayerEarnMeter_SetEnabled( false )
+ SetShouldUsePickLoadoutScreen( true )
+ SetAllowLoadoutChangeFunc( FD_ShouldAllowChangeLoadout )
+ SetGetDifficultyFunc( FD_GetDifficultyLevel )
+ TeamTitanSelectMenu_Init() // show the titan select menu in this mode
+
+ //general Callbacks
+ AddCallback_EntitiesDidLoad( LoadEntities )
+ AddCallback_GameStateEnter( eGameState.Prematch,FD_createHarvester )
+ AddCallback_GameStateEnter( eGameState.Playing, startMainGameLoop )
+ AddCallback_OnRoundEndCleanup( FD_NPCCleanup )
+ AddCallback_OnClientConnected( GamemodeFD_InitPlayer )
+ AddCallback_OnClientDisconnected( OnPlayerDisconnectedOrDestroyed )
+ AddCallback_OnPlayerGetsNewPilotLoadout( FD_OnPlayerGetsNewPilotLoadout )
+ ClassicMP_SetEpilogue( FD_SetupEpilogue )
+
+ //Damage Callbacks
+ AddDamageByCallback( "player", FD_DamageByPlayerCallback)
+ AddDamageCallback( "player", DamageScaleByDifficulty )
+ AddDamageCallback( "npc_titan", DamageScaleByDifficulty )
+ AddDamageCallback( "npc_turret_sentry", DamageScaleByDifficulty )
+ AddDamageCallback( "npc_turret_sentry",RevivableTurret_DamageCallback)
+ //Spawn Callbacks
+ AddSpawnCallback( "npc_titan", HealthScaleByDifficulty )
+ AddSpawnCallback( "npc_super_spectre", HealthScaleByDifficulty )
+ AddCallback_OnPlayerRespawned( FD_PlayerRespawnCallback )
+ AddSpawnCallback("npc_turret_sentry", AddTurretSentry )
+ //death Callbacks
+ AddCallback_OnNPCKilled( OnNpcDeath )
+ AddCallback_OnPlayerKilled( GamemodeFD_OnPlayerKilled )
+ AddDeathCallback( "npc_frag_drone", OnTickDeath ) // ticks dont come up in the other callback because of course they dont
+
+ //Command Callbacks
+ AddClientCommandCallback( "FD_ToggleReady", ClientCommandCallbackToggleReady )
+ AddClientCommandCallback( "FD_UseHarvesterShieldBoost", useShieldBoost )
+
+ //shop Callback
+ SetBoostPurchaseCallback( FD_BoostPurchaseCallback )
+ SetTeamReserveInteractCallback( FD_TeamReserveDepositOrWithdrawCallback )
+
+ //earn meter
+ ScoreEvent_SetupEarnMeterValuesForMixedModes()
+
+ //Data Collection
+ AddStunLaserHealCallback( FD_StunLaserHealTeammate )
+ AddBatteryHealCallback( FD_BatteryHealTeammate )
+ AddSmokeHealCallback( FD_SmokeHealTeammate )
+ SetUsedCoreCallback( FD_UsedCoreCallback )
+
+ //todo:are pointValueOverride exist?
+ //Score Event
+ AddArcTrapTriggeredCallback( FD_OnArcTrapTriggered )
+ AddArcWaveDamageCallback( FD_OnArcWaveDamage )
+ AddOnTetherCallback( FD_OnTetherTrapTriggered )
+ AddSonarStartCallback( FD_OnSonarStart )
+}
+
+// this might need updating when we do dropship things
+bool function FD_ShouldAllowChangeLoadout( entity player )
+{
+ return GetGlobalNetTime( "FD_nextWaveStartTime" ) > Time()
+}
+
+void function FD_BoostPurchaseCallback( entity player, BoostStoreData data )
+{
+ file.playerAwardStats[player]["moneySpent"] += float( data.cost )
+}
+
+void function FD_PlayerRespawnCallback( entity player )
+{
+ if( player in file.players )
+ file.players[player].lastRespawn = Time()
+
+ if( GetCurrentPlaylistVarInt( "fd_at_unlimited_ammo", 1 ) )
+ FD_GivePlayerInfiniteAntiTitanAmmo( player )
+
+ if ( !file.playersHaveTitans )
+ {
+ // why in the fuck do i need to WaitFrame() here, this sucks
+ thread PlayerEarnMeter_SetMode_Threaded( player, 0 )
+ }
+
+ if( file.dropshipState == eDropshipState.Returning )
+ return
+ if( GetGameState() != eGameState.Playing)
+ return
+
+ if( player.GetPersistentVar( "spawnAsTitan" ) )
+ return
+
+ player.SetInvulnerable()
+ if( file.dropshipState == eDropshipState.Idle )
+ {
+ thread FD_DropshipSpawnDropship()
+ }
+ //Attach player
+ FirstPersonSequenceStruct idleSequence
+ idleSequence.firstPersonAnim = DROPSHIP_IDLE_ANIMS_POV[ file.playersInShip ]
+ idleSequence.thirdPersonAnim = DROPSHIP_IDLE_ANIMS[ file.playersInShip++ ]
+ idleSequence.attachment = "ORIGIN"
+ idleSequence.teleport = true
+ idleSequence.viewConeFunction = ViewConeFree
+ idleSequence.hideProxy = true
+ thread FirstPersonSequence( idleSequence, player, file.dropship )
+ file.playersInDropship.append( player )
+}
+
+
+void function PlayerEarnMeter_SetMode_Threaded( entity player, int mode )
+{
+ WaitFrame()
+ if ( IsValid( player ) )
+ PlayerEarnMeter_SetMode( player, mode )
+}
+
+void function FD_OnPlayerGetsNewPilotLoadout( entity player, PilotLoadoutDef loadout )
+{
+ if( GetCurrentPlaylistVarInt( "fd_at_unlimited_ammo", 1 ) )
+ FD_GivePlayerInfiniteAntiTitanAmmo( player )
+}
+
+void function FD_GivePlayerInfiniteAntiTitanAmmo( entity player )
+{
+ array<entity> weapons = player.GetMainWeapons()
+ foreach ( entity weaponEnt in weapons )
+ {
+ if ( weaponEnt.GetWeaponInfoFileKeyField( "menu_category" ) != "at" )
+ continue
+
+ if( !weaponEnt.HasMod( "at_unlimited_ammo" ) )
+ {
+ array<string> mods = weaponEnt.GetMods()
+ mods.append( "at_unlimited_ammo" )
+ weaponEnt.SetMods( mods )
+ }
+ }
+}
+
+void function FD_TeamReserveDepositOrWithdrawCallback( entity player, string action, int amount )
+{
+ switch( action )
+ {
+ case"deposit":
+ file.playerAwardStats[player]["moneyShared"] += float( amount )
+ break
+ case"withdraw":
+ file.playerAwardStats[player]["moneyShared"] -= float( amount )
+ break
+ }
+}
+void function GamemodeFD_OnPlayerKilled( entity victim, entity attacker, var damageInfo )
+{
+ //set longest Time alive for end awards
+ float timeAlive = Time() - file.players[victim].lastRespawn
+ if(timeAlive>file.playerAwardStats[victim]["longestLife"])
+ file.playerAwardStats[victim]["longestLife"] = timeAlive
+
+ //set died this round for round end money boni
+ file.players[victim].diedThisRound = true
+
+ //play voicelines for amount of players alive
+ array<entity> militiaplayers = GetPlayerArrayOfTeam( TEAM_MILITIA )
+ int deaths = 0
+ foreach ( entity player in militiaplayers )
+ if ( !IsAlive( player ) )
+ deaths++
+
+ foreach( entity player in GetPlayerArray() )
+ {
+ if ( player == victim || player.GetTeam() != TEAM_MILITIA )
+ continue
+
+ if ( deaths == 1 ) // only one pilot died
+ PlayFactionDialogueToPlayer( "fd_singlePilotDown", player )
+ else if ( deaths > 1 && deaths < militiaplayers.len() - 1 ) // multiple pilots died but at least one alive
+ PlayFactionDialogueToPlayer( "fd_multiPilotDown", player )
+ else if ( deaths == militiaplayers.len() - 1 ) // ur shit out of luck ur the only survivor
+ PlayFactionDialogueToPlayer( "fd_onlyPlayerIsAlive", player )
+ }
+}
+
+void function FD_UsedCoreCallback( entity titan, entity weapon )
+{
+ if( !( titan in file.players ) )
+ {
+ return
+ }
+ file.playerAwardStats[titan]["coresUsed"] += 1
+}
+
+void function GamemodeFD_InitPlayer( entity player )
+{
+ player_struct_fd data
+ data.diedThisRound = false
+ data.leaveHarvester = true
+ file.players[player] <- data
+ table<string, float> awardStats
+ foreach( string statRef in GetFDStatRefs() )
+ {
+ awardStats[statRef] <- 0.0
+ }
+ file.playerAwardStats[player] <- awardStats
+ thread SetTurretSettings_threaded( player )
+ // only start the highlight when we start playing, not during dropship
+ if ( GetGameState() >= eGameState.Playing )
+ Highlight_SetFriendlyHighlight( player, "sp_friendly_hero" )
+
+ if( file.playersHaveTitans ) // first wave is index 0
+ {
+ PlayerEarnMeter_AddEarnedAndOwned( player, 1.0, 1.0 )
+ }
+ // unfortunate that i cant seem to find a nice callback for them exiting that menu but thisll have to do
+ thread TryDisableTitanSelectionForPlayerAfterDelay( player, TEAM_TITAN_SELECT_DURATION_MIDGAME )
+ thread TrackDeployedArcTrapThisRound( player )
+}
+
+void function TrackDeployedArcTrapThisRound( entity player )
+{
+ player.EndSignal( "OnDestroy" )
+
+ OnThreadEnd(
+ function() : ( player )
+ {
+ if ( IsValid( player ) )
+ OnPlayerDisconnectedOrDestroyed( player )
+ else
+ ClearInValidTurret()
+ }
+ )
+
+ while( IsValid( player ) )
+ {
+ entity ArcTrap = expect entity ( player.WaitSignal( "DeployArcTrap" ).projectile )
+ file.players[ player ].deployedEntityThisRound.append( ArcTrap )
+ AddEntityDestroyedCallback( ArcTrap, FD_OnEntityDestroyed )
+ }
+}
+
+void function TryDisableTitanSelectionForPlayerAfterDelay( entity player, float waitAmount )
+{
+ player.EndSignal( "OnDestroy" )//Do a crash protect when wait delay
+
+ OnThreadEnd(
+ function() : ( player )
+ {
+ if( IsValid( player ) )
+ {
+ DisableTitanSelectionForPlayer( player )
+ }
+ }
+ )
+
+ wait waitAmount
+ if ( file.playersHaveTitans )
+ DisableTitanSelectionForPlayer( player )
+}
+
+void function SetTurretSettings_threaded( entity player )
+{ //has to be delayed because PlayerConnect callbacks get called in wrong order
+ WaitFrame()
+ DeployableTurret_SetAISettingsForPlayer_AP( player, "npc_turret_sentry_burn_card_ap_fd" )
+ DeployableTurret_SetAISettingsForPlayer_AT( player, "npc_turret_sentry_burn_card_at_fd" )
+}
+
+void function OnTickDeath( entity victim, var damageInfo )
+{
+ int findIndex = spawnedNPCs.find( victim )
+ if ( findIndex != -1 )
+ {
+ spawnedNPCs.remove( findIndex )
+
+ SetGlobalNetInt( "FD_AICount_Ticks", GetGlobalNetInt( "FD_AICount_Ticks" ) -1 )
+
+ SetGlobalNetInt( "FD_AICount_Current", GetGlobalNetInt( "FD_AICount_Current" ) -1 )
+ }
+}
+
+void function OnNpcDeath( entity victim, entity attacker, var damageInfo )
+{
+ if( attacker.GetClassName() == "npc_turret_sentry" && IsValidPlayer( attacker.GetBossPlayer() ) )
+ {
+ file.playerAwardStats[ attacker.GetBossPlayer() ]["turretKills"]++
+ }
+ if( victim.IsTitan() && attacker in file.players )
+ file.playerAwardStats[attacker]["titanKills"]++
+ int victimTypeID = FD_GetAITypeID_ByString( victim.GetTargetName() )
+ if( ( victimTypeID == eFD_AITypeIDs.TITAN_MORTAR ) || ( victimTypeID == eFD_AITypeIDs.SPECTRE_MORTAR ) )
+ if( attacker in file.players )
+ file.playerAwardStats[attacker]["mortarUnitsKilled"]++
+ int findIndex = spawnedNPCs.find( victim )
+ if ( findIndex != -1 )
+ {
+ spawnedNPCs.remove( findIndex )
+
+ string netIndex = GetAiNetIdFromTargetName( victim.GetTargetName() )
+ if( netIndex != "" )
+ SetGlobalNetInt( netIndex, GetGlobalNetInt( netIndex ) - 1 )
+
+ SetGlobalNetInt( "FD_AICount_Current", GetGlobalNetInt( "FD_AICount_Current" ) - 1 )
+ }
+
+ if ( victim.GetOwner() == attacker || !attacker.IsPlayer() || ( attacker == victim ) || ( victim.GetBossPlayer() == attacker ) || victim.GetClassName() == "npc_turret_sentry" )
+ return
+
+ int playerScore = 0
+ int money = 0
+ int scriptDamageType = DamageInfo_GetCustomDamageType( damageInfo )
+ int damageSourceId = DamageInfo_GetDamageSourceIdentifier( damageInfo )
+
+ if ( victim.IsNPC() )
+ {
+ string eventName = FD_GetScoreEventName( victim.GetClassName() )
+ playerScore = ScoreEvent_GetPointValue( GetScoreEvent( eventName ) )
+
+ switch ( victim.GetClassName() )
+ {
+ case "npc_soldier":
+ money = 5
+ break
+ case "npc_drone":
+ case "npc_spectre":
+ money = 10
+ break
+ case "npc_stalker":
+ money = 15
+ break
+ case "npc_super_spectre":
+ money = 20
+ break
+ default:
+ money = 0 // titans seem to total up to 50 money undoomed health
+ }
+ foreach( player in GetPlayerArray() )
+ Remote_CallFunction_NonReplay( player, "ServerCallback_OnTitanKilled", attacker.GetEncodedEHandle(), victim.GetEncodedEHandle(), scriptDamageType, damageSourceId )
+ }
+ if ( money != 0 )
+ AddMoneyToPlayer( attacker , money )
+
+ attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, playerScore ) // seems to be how combat score is counted
+ file.players[attacker].scoreThisRound += playerScore
+ table<int, bool> alreadyAssisted
+ foreach( DamageHistoryStruct attackerInfo in victim.e.recentDamageHistory )
+ {
+ if ( !IsValid( attackerInfo.attacker ) || !attackerInfo.attacker.IsPlayer() || attackerInfo.attacker == victim )
+ continue
+
+ bool exists = attackerInfo.attacker.GetEncodedEHandle() in alreadyAssisted ? true : false
+ if( attackerInfo.attacker != attacker && !exists )
+ {
+ alreadyAssisted[attackerInfo.attacker.GetEncodedEHandle()] <- true
+ attackerInfo.attacker.AddToPlayerGameStat( PGS_DEFENSE_SCORE, playerScore ) // i assume this is how support score gets added
+ }
+ }
+
+
+}
+
+void function RateSpawnpoints_FD( int _0, array<entity> _1, int _2, entity _3 )
+{
+
+}
+
+bool function useShieldBoost( entity player, array<string> args )
+{
+ if( ( GetGlobalNetTime( "FD_harvesterInvulTime" ) < Time() ) && ( player.GetPlayerNetInt( "numHarvesterShieldBoost" ) > 0 ) )
+ {
+ fd_harvester.harvester.SetShieldHealth( fd_harvester.harvester.GetShieldHealthMax() )
+ SetGlobalNetTime( "FD_harvesterInvulTime", Time() + 5 )
+ AddPlayerScore( player, "FDShieldHarvester" )
+ MessageToTeam( TEAM_MILITIA,eEventNotifications.FD_PlayerBoostedHarvesterShield, null, player )
+ player.SetPlayerNetInt( "numHarvesterShieldBoost", player.GetPlayerNetInt( "numHarvesterShieldBoost" ) - 1 )
+ file.playerAwardStats[player]["harvesterHeals"]++
+ }
+ return true
+}
+
+void function startMainGameLoop()
+{
+ // only start the highlight when we start playing, not during dropship
+ foreach ( entity player in GetPlayerArray() )
+ Highlight_SetFriendlyHighlight( player, "sp_friendly_hero" )
+
+ thread mainGameLoop()
+}
+
+void function mainGameLoop()
+{
+ startHarvester()
+
+ bool showShop = false
+ for( int i = GetGlobalNetInt( "FD_currentWave" ); i < waveEvents.len(); i++ )
+ {
+ if( file.waveRestart )
+ {
+ showShop = true
+ foreach( entity player in GetPlayerArray() )
+ {
+ SetMoneyForPlayer( player, file.players[player].moneyThisRound )
+ player.SetPlayerNetInt( "numHarvesterShieldBoost", 0 )
+ player.SetPlayerNetInt( "numSuperRodeoGrenades", 0 )
+ PlayerInventory_TakeAllInventoryItems( player )
+ }
+ SetGlobalNetTime( "FD_nextWaveStartTime", Time() + 75 )
+ }
+
+ if( !runWave( i, showShop ) )
+ break
+
+ if( i == 0 )
+ {
+ PlayerEarnMeter_SetEnabled( true )
+ showShop = true
+ foreach( entity player in GetPlayerArray() )
+ {
+ PlayerEarnMeter_SetMode( player, 1 ) // show the earn meter
+ PlayerEarnMeter_AddEarnedAndOwned( player, 1.0, 1.0 )
+ }
+ file.playersHaveTitans = true
+ DisableTitanSelection()
+ }
+ }
+
+ // end of game
+ EnableTitanSelection()
+
+}
+
+
+
+array<int> function getHighestEnemyAmountsForWave( int waveIndex )
+{
+ table<int,int> npcs
+ npcs[eFD_AITypeIDs.TITAN] <- 0
+ npcs[eFD_AITypeIDs.TITAN_NUKE] <- 0
+ npcs[eFD_AITypeIDs.TITAN_ARC] <- 0
+ npcs[eFD_AITypeIDs.TITAN_MORTAR] <- 0
+ npcs[eFD_AITypeIDs.GRUNT] <- 0
+ npcs[eFD_AITypeIDs.SPECTRE] <- 0
+ npcs[eFD_AITypeIDs.SPECTRE_MORTAR] <- 0
+ npcs[eFD_AITypeIDs.STALKER] <- 0
+ npcs[eFD_AITypeIDs.REAPER] <- 0
+ npcs[eFD_AITypeIDs.TICK] <- 0
+ npcs[eFD_AITypeIDs.DRONE] <- 0
+ npcs[eFD_AITypeIDs.DRONE_CLOAK] <- 0
+ // npcs[eFD_AITypeIDs.RONIN] <- 0
+ // npcs[eFD_AITypeIDs.NORTHSTAR] <- 0
+ // npcs[eFD_AITypeIDs.SCORCH] <- 0
+ // npcs[eFD_AITypeIDs.LEGION] <- 0
+ // npcs[eFD_AITypeIDs.TONE] <- 0
+ // npcs[eFD_AITypeIDs.ION] <- 0
+ // npcs[eFD_AITypeIDs.MONARCH] <- 0
+ // npcs[eFD_AITypeIDs.TITAN_SNIPER] <- 0
+
+
+ foreach( WaveEvent e in waveEvents[waveIndex] )
+ {
+ if( e.spawnEvent.spawnAmount == 0 )
+ continue
+ switch( e.spawnEvent.spawnType )
+ {
+ case( eFD_AITypeIDs.TITAN ):
+ case( eFD_AITypeIDs.RONIN ):
+ case( eFD_AITypeIDs.NORTHSTAR ):
+ case( eFD_AITypeIDs.SCORCH ):
+ case( eFD_AITypeIDs.TONE ):
+ case( eFD_AITypeIDs.ION ):
+ case( eFD_AITypeIDs.MONARCH ):
+ case( eFD_AITypeIDs.LEGION ):
+ case( eFD_AITypeIDs.TITAN_SNIPER ):
+ npcs[eFD_AITypeIDs.TITAN] += e.spawnEvent.spawnAmount
+ break
+ default:
+ npcs[e.spawnEvent.spawnType] += e.spawnEvent.spawnAmount
+ }
+ }
+ array<int> ret = [ -1, -1, -1, -1, -1, -1, -1, -1, -1 ]
+ foreach( int key, int value in npcs )
+ {
+ if( value == 0 )
+ continue
+ int lowestArrayIndex = 0
+ bool keyIsSet = false
+ foreach( index, int arrayValue in ret )
+ {
+ if( arrayValue == -1 )
+ {
+ ret[index] = key
+ keyIsSet = true
+ break
+ }
+ if( npcs[ ret[lowestArrayIndex] ] > npcs[ ret[index] ] )
+ lowestArrayIndex = index
+ }
+ if( ( !keyIsSet ) && ( npcs[ ret[lowestArrayIndex] ] < value ) )
+ ret[lowestArrayIndex] = key
+ }
+ foreach( int val in ret )
+ {
+ printt( "ArrayVal", val )
+ }
+ return ret
+
+}
+void function SetEnemyAmountNetVars( int waveIndex )
+{
+ int total = 0
+ table<int,int> npcs
+ npcs[eFD_AITypeIDs.TITAN] <- 0
+ npcs[eFD_AITypeIDs.TITAN_NUKE] <- 0
+ npcs[eFD_AITypeIDs.TITAN_ARC] <- 0
+ npcs[eFD_AITypeIDs.TITAN_MORTAR] <- 0
+ npcs[eFD_AITypeIDs.GRUNT] <- 0
+ npcs[eFD_AITypeIDs.SPECTRE] <- 0
+ npcs[eFD_AITypeIDs.SPECTRE_MORTAR] <- 0
+ npcs[eFD_AITypeIDs.STALKER] <- 0
+ npcs[eFD_AITypeIDs.REAPER] <- 0
+ npcs[eFD_AITypeIDs.TICK] <- 0
+ npcs[eFD_AITypeIDs.DRONE] <- 0
+ npcs[eFD_AITypeIDs.DRONE_CLOAK] <- 0
+ // npcs[eFD_AITypeIDs.RONIN] <- 0
+ // npcs[eFD_AITypeIDs.NORTHSTAR] <- 0
+ // npcs[eFD_AITypeIDs.SCORCH] <- 0
+ // npcs[eFD_AITypeIDs.LEGION] <- 0
+ // npcs[eFD_AITypeIDs.TONE] <- 0
+ // npcs[eFD_AITypeIDs.ION] <- 0
+ // npcs[eFD_AITypeIDs.MONARCH] <- 0
+ // npcs[eFD_AITypeIDs.TITAN_SNIPER] <- 0
+
+
+ foreach( WaveEvent e in waveEvents[waveIndex] )
+ {
+ if( e.spawnEvent.spawnAmount == 0 )
+ continue
+ switch( e.spawnEvent.spawnType )
+ {
+ case( eFD_AITypeIDs.TITAN ):
+ case( eFD_AITypeIDs.RONIN ):
+ case( eFD_AITypeIDs.NORTHSTAR ):
+ case( eFD_AITypeIDs.SCORCH ):
+ case( eFD_AITypeIDs.TONE ):
+ case( eFD_AITypeIDs.ION ):
+ case( eFD_AITypeIDs.MONARCH ):
+ case( eFD_AITypeIDs.LEGION ):
+ case( eFD_AITypeIDs.TITAN_SNIPER ):
+ npcs[eFD_AITypeIDs.TITAN] += e.spawnEvent.spawnAmount
+ break
+ default:
+ npcs[e.spawnEvent.spawnType] += e.spawnEvent.spawnAmount
+
+ }
+ total+= e.spawnEvent.spawnAmount
+ }
+ SetGlobalNetInt( "FD_AICount_Titan", npcs[eFD_AITypeIDs.TITAN] )
+ SetGlobalNetInt( "FD_AICount_Titan_Nuke", npcs[eFD_AITypeIDs.TITAN_NUKE] )
+ SetGlobalNetInt( "FD_AICount_Titan_Mortar", npcs[eFD_AITypeIDs.TITAN_MORTAR] )
+ SetGlobalNetInt( "FD_AICount_Titan_Arc", npcs[eFD_AITypeIDs.TITAN_ARC] )
+ SetGlobalNetInt( "FD_AICount_Grunt", npcs[eFD_AITypeIDs.GRUNT] )
+ SetGlobalNetInt( "FD_AICount_Spectre", npcs[eFD_AITypeIDs.SPECTRE] )
+ SetGlobalNetInt( "FD_AICount_Spectre_Mortar", npcs[eFD_AITypeIDs.SPECTRE_MORTAR] )
+ SetGlobalNetInt( "FD_AICount_Stalker", npcs[eFD_AITypeIDs.STALKER] )
+ SetGlobalNetInt( "FD_AICount_Reaper", npcs[eFD_AITypeIDs.REAPER] )
+ SetGlobalNetInt( "FD_AICount_Ticks", npcs[eFD_AITypeIDs.TICK] )
+ SetGlobalNetInt( "FD_AICount_Drone", npcs[eFD_AITypeIDs.DRONE] )
+ SetGlobalNetInt( "FD_AICount_Drone_Cloak", npcs[eFD_AITypeIDs.DRONE_CLOAK] )
+ SetGlobalNetInt( "FD_AICount_Current", total )
+ SetGlobalNetInt( "FD_AICount_Total", total )
+
+}
+
+
+
+bool function runWave( int waveIndex, bool shouldDoBuyTime )
+{
+
+ SetGlobalNetInt( "FD_currentWave", waveIndex )
+ file.havesterWasDamaged = false
+ file.harvesterShieldDown = false
+ SetEnemyAmountNetVars( waveIndex )
+ for( int i = 0; i < 20; i++ )//Number of npc type ids
+ {
+ file.harvesterDamageSource.append( 0.0 )
+ }
+ foreach( entity player in GetPlayerArray() )
+ {
+ file.players[player].diedThisRound = false
+ file.players[player].scoreThisRound = 0
+ file.players[player].moneyThisRound = GetPlayerMoney( player )
+ file.players[ player ].deployedEntityThisRound.clear()
+ }
+ array<int> enemys = getHighestEnemyAmountsForWave( waveIndex )
+
+ foreach( entity player in GetPlayerArray() )
+ {
+ Remote_CallFunction_NonReplay( player, "ServerCallback_FD_AnnouncePreParty", enemys[0], enemys[1], enemys[2], enemys[3], enemys[4], enemys[5], enemys[6], enemys[7], enemys[8] )
+ }
+ if( file.waveRestart )
+ {
+ file.waveRestart = false
+ MessageToTeam( TEAM_MILITIA,eEventNotifications.FD_WaveRestart )
+ }
+ if( shouldDoBuyTime )
+ {
+ SetGlobalNetInt( "FD_waveState", WAVE_STATE_BREAK )
+ OpenBoostStores()
+ entity parentCrate = GetBoostStores()[0].GetParent()
+ parentCrate.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ Minimap_PingForTeam( TEAM_MILITIA, shopPosition, 150, 5, TEAM_COLOR_YOU / 255.0, 5 )
+ foreach( entity player in GetPlayerArray() )
+ Remote_CallFunction_NonReplay( player, "ServerCallback_FD_NotifyStoreOpen" )
+ while( Time() < GetGlobalNetTime( "FD_nextWaveStartTime" ) )
+ {
+ if( allPlayersReady() )
+ SetGlobalNetTime( "FD_nextWaveStartTime", Time() )
+ WaitFrame()
+ }
+ parentCrate.Minimap_Hide( TEAM_MILITIA, null )
+ CloseBoostStores()
+ MessageToTeam( TEAM_MILITIA, eEventNotifications.FD_StoreClosing )
+ }
+
+ //SetGlobalNetTime("FD_nextWaveStartTime",Time()+10)
+ wait 10
+ SetGlobalNetInt( "FD_waveState", WAVE_STATE_INCOMING )
+ foreach( entity player in GetPlayerArray() )
+ {
+ Remote_CallFunction_NonReplay( player, "ServerCallback_FD_ClearPreParty" )
+ player.SetPlayerNetBool( "FD_readyForNextWave", false )
+ }
+ SetGlobalNetBool( "FD_waveActive", true )
+ MessageToTeam( TEAM_MILITIA, eEventNotifications.FD_AnnounceWaveStart )
+ SetGlobalNetInt( "FD_waveState", WAVE_STATE_BREAK )
+
+ //main wave loop
+ thread SetWaveStateReady()
+ executeWave()
+ SetGlobalNetInt( "FD_waveState", WAVE_STATE_COMPLETE )
+ if( !IsHarvesterAlive( fd_harvester.harvester ) )
+ {
+ float totalDamage = 0.0
+ array<float> highestDamage = [ 0.0, 0.0, 0.0 ]
+ array<int> highestDamageSource = [ -1, -1, -1 ]
+ foreach(index,float damage in file.harvesterDamageSource)
+ {
+ totalDamage += damage
+ if( highestDamage[0] < damage )
+ {
+ highestDamage[2] = highestDamage[1]
+ highestDamageSource[2] = highestDamageSource[1]
+ highestDamage[1] = highestDamage[0]
+ highestDamageSource[1] = highestDamageSource[0]
+ highestDamageSource[0] = index
+ highestDamage[0] = damage
+ }
+ else if( highestDamage[1] < damage )
+ {
+ highestDamage[2] = highestDamage[1]
+ highestDamageSource[2] = highestDamageSource[1]
+ highestDamage[1] = damage
+ highestDamageSource[1] = index
+ }
+ else if( highestDamage[2] < damage )
+ {
+ highestDamage[2] = damage
+ highestDamageSource[2] = index
+ }
+ }
+
+ foreach( entity player in GetPlayerArray() )
+ {
+ Remote_CallFunction_NonReplay( player, "ServerCallback_FD_DisplayHarvesterKiller", GetGlobalNetInt( "FD_restartsRemaining" ), getHintForTypeId( highestDamageSource[0] ), highestDamageSource[0], highestDamage[0] / totalDamage, highestDamageSource[1], highestDamage[1] / totalDamage , highestDamageSource[2], highestDamage[2] / totalDamage )
+ }
+
+ if( GetGlobalNetInt( "FD_restartsRemaining" ) > 0 )
+ FD_DecrementRestarts()
+ else
+ SetRoundBased(false)
+
+ file.waveRestart = true //wave restart point
+ SetWinner( TEAM_IMC )//restart round
+ spawnedNPCs = [] // reset npcs count
+ restetWaveEvents()
+ foreach( player in GetPlayerArray() )
+ PlayerEarnMeter_AddEarnedAndOwned( player, 1.0, 1.0 )
+ return false
+ }
+
+
+ wait 2
+ //wave end
+
+ SetGlobalNetBool( "FD_waveActive", false )
+ MessageToTeam( TEAM_MILITIA, eEventNotifications.FD_AnnounceWaveEnd )
+
+ if ( isFinalWave() && IsHarvesterAlive( fd_harvester.harvester ) )
+ {
+ //Game won code
+ MessageToTeam( TEAM_MILITIA, eEventNotifications.FD_AnnounceWaveEnd )
+ foreach( entity player in GetPlayerArray() )
+ {
+ AddPlayerScore( player, "FDTeamWave" )
+ }
+ wait 1
+ int highestScore = 0;
+ entity highestScore_player = GetPlayerArray()[0]
+ foreach( entity player in GetPlayerArray() )
+ {
+
+ if( !file.players[player].diedThisRound )
+ AddPlayerScore( player, "FDDidntDie" )
+ if( highestScore < file.players[player].scoreThisRound )
+ {
+ highestScore = file.players[player].scoreThisRound
+ highestScore_player = player
+ }
+
+ }
+ file.playerAwardStats[highestScore_player]["mvp"]++
+ AddPlayerScore( highestScore_player, "FDWaveMVP" )
+ wait 1
+ foreach( entity player in GetPlayerArray() )
+ if( !file.havesterWasDamaged )
+ AddPlayerScore( player, "FDTeamFlawlessWave" )
+
+ foreach(entity player in GetPlayerArray() )
+ {
+ if( IsAlive( player ) )
+ {
+ float timeAlive = Time() - file.players[player].lastRespawn
+ if(timeAlive>file.playerAwardStats[player]["longestLife"])
+ file.playerAwardStats[player]["longestLife"] = timeAlive
+ }
+ if( IsValid( player.GetPetTitan ) )
+ {
+ float timeAlive = Time() - file.players[player].lastTitanDrop
+ if(timeAlive>file.playerAwardStats[player]["longestTitanLife"])
+ file.playerAwardStats[player]["longestTitanLife"] = timeAlive
+ }
+ }
+
+
+
+ SetRoundBased(false)
+ SetWinner(TEAM_MILITIA)
+ PlayFactionDialogueToTeam( "fd_matchVictory", TEAM_MILITIA )
+ return true
+ }
+
+ if(!file.havesterWasDamaged)
+ {
+ PlayFactionDialogueToTeam( "fd_waveRecapPerfect", TEAM_MILITIA )
+ wait 5
+ }
+ else
+ {
+ float damagepercent = ( ( file.harvesterDamageTaken / fd_harvester.harvester.GetMaxHealth().tofloat() ) * 100 )
+ float healthpercent = ( ( fd_harvester.harvester.GetHealth().tofloat() / fd_harvester.harvester.GetMaxHealth() ) * 100 )
+ if ( damagepercent < 5 ) // if less than 5% damage taken
+ PlayFactionDialogueToTeam( "fd_waveRecapNearPerfect", TEAM_MILITIA )
+ else if ( healthpercent < 15 ) // if less than 15% health remains and more than 5% damage taken
+ PlayFactionDialogueToTeam( "fd_waveRecapLowHealth", TEAM_MILITIA )
+ wait 5
+ }
+
+ if ( isSecondWave() )
+ {
+ // supposed to add dialogues like "GOOD WORK TEAM" then "YOUR TITAN IS READY"
+ // done ^
+ PlayFactionDialogueToTeam( "fd_titanReadyNag" , TEAM_MILITIA )
+ wait 5
+ }
+
+ //Player scoring
+ MessageToTeam( TEAM_MILITIA, eEventNotifications.FD_NotifyWaveBonusIncoming )
+ wait 2
+ foreach( entity player in GetPlayerArray() )
+ {
+ if ( isSecondWave() )
+ PlayFactionDialogueToPlayer( "fd_wavePayoutFirst", player )
+ else
+ PlayFactionDialogueToPlayer( "fd_wavePayoutAddtnl", player )
+ AddPlayerScore( player, "FDTeamWave" )
+ AddMoneyToPlayer( player, GetCurrentPlaylistVarInt( "fd_money_per_round", 600 ) )
+ // is this in the right place? do we want to be adding for each player?
+ // this function is called "Set" but in reality it is "Add"
+ SetJoinInProgressBonus( GetCurrentPlaylistVarInt( "fd_money_per_round" ,600 ) )
+ EmitSoundOnEntityOnlyToPlayer( player, player, "HUD_MP_BountyHunt_BankBonusPts_Deposit_Start_1P" )
+ }
+ wait 1
+ foreach( entity player in GetPlayerArray() )
+ {
+ if( !file.players[player].diedThisRound )
+ {
+ AddPlayerScore( player, "FDDidntDie" )
+ player.AddToPlayerGameStat( PGS_ASSAULT_SCORE, FD_SCORE_DIDNT_DIE )
+ }
+ AddMoneyToPlayer( player, 100 )
+ EmitSoundOnEntityOnlyToPlayer( player, player, "HUD_MP_BountyHunt_BankBonusPts_Deposit_Start_1P" )
+ }
+ wait 1
+ int highestScore = 0;
+ entity highestScore_player = GetPlayerArray()[0]
+ foreach( entity player in GetPlayerArray() )
+ {
+ if( highestScore < file.players[player].scoreThisRound )
+ {
+ highestScore = file.players[player].scoreThisRound
+ highestScore_player = player
+ }
+ }
+ file.playerAwardStats[highestScore_player]["mvp"]++
+ AddPlayerScore( highestScore_player, "FDWaveMVP" )
+ AddMoneyToPlayer( highestScore_player, 100 )
+ highestScore_player.AddToPlayerGameStat( PGS_ASSAULT_SCORE, FD_SCORE_MVP )
+ EmitSoundOnEntityOnlyToPlayer( highestScore_player, highestScore_player, "HUD_MP_BountyHunt_BankBonusPts_Deposit_Start_1P" )
+ foreach( entity player in GetPlayerArray() )
+ {
+ Remote_CallFunction_NonReplay( player, "ServerCallback_FD_NotifyMVP", highestScore_player.GetEncodedEHandle() )
+ }
+ wait 1
+ foreach( entity player in GetPlayerArray() )
+ {
+
+ if( !file.havesterWasDamaged )
+ {
+ AddPlayerScore( player, "FDTeamFlawlessWave" )
+ AddMoneyToPlayer( player, 100 )
+ player.AddToPlayerGameStat( PGS_ASSAULT_SCORE, FD_SCORE_TEAM_FLAWLESS_WAVE )
+ EmitSoundOnEntityOnlyToPlayer( player, player, "HUD_MP_BountyHunt_BankBonusPts_Deposit_Start_1P" )
+ }
+ }
+
+ wait 1
+
+ if( waveIndex<waveEvents.len() )
+ SetGlobalNetTime( "FD_nextWaveStartTime", Time() + 75 )
+
+ return true
+
+}
+
+void function SetWaveStateReady()
+{
+ wait 5
+ SetGlobalNetInt( "FD_waveState", WAVE_STATE_IN_PROGRESS )
+}
+
+void function FD_StunLaserHealTeammate( entity player, entity target, int shieldRestoreAmount )
+{
+ if( IsValid( player ) && player in file.players ){
+ file.playerAwardStats[player]["heals"] += float( shieldRestoreAmount )
+ player.AddToPlayerGameStat( PGS_DEFENSE_SCORE, shieldRestoreAmount / 100 )
+ file.players[ player ].scoreThisRound += shieldRestoreAmount / 100
+ }
+}
+
+void function FD_SmokeHealTeammate( entity player, entity target, int shieldRestoreAmount )
+{
+ if( IsValid( player ) && player in file.players ){
+ file.playerAwardStats[player]["heals"] += float( shieldRestoreAmount )
+ player.AddToPlayerGameStat( PGS_DEFENSE_SCORE, shieldRestoreAmount / 100 )
+ file.players[ player ].scoreThisRound += shieldRestoreAmount / 100
+ }
+}
+
+void function FD_BatteryHealTeammate( entity battery, entity titan, int shieldRestoreAmount, int healthRestoreAmount )
+{
+ if( !IsValid( battery ) )
+ return
+
+ entity BatteryParent = battery.GetParent()
+ entity TargetTitan
+ int currentHeal
+ int currentHealScore
+
+ if( titan.IsPlayer() )
+ TargetTitan = titan
+ else if( titan.GetBossPlayer() != null )
+ TargetTitan = titan.GetBossPlayer()
+ else
+ return
+
+ if( BatteryParent == TargetTitan )
+ return
+
+ if( IsValid( BatteryParent ) && BatteryParent in file.players ){
+ AddPlayerScore( BatteryParent, "FDTeamHeal" )
+ currentHeal = shieldRestoreAmount + healthRestoreAmount
+ currentHealScore = currentHeal / 100
+ file.playerAwardStats[BatteryParent]["heals"] += float( currentHeal )
+ BatteryParent.AddToPlayerGameStat( PGS_DEFENSE_SCORE, currentHealScore )
+ file.players[ BatteryParent ].scoreThisRound += currentHealScore
+ }
+}
+
+void function FD_OnArcTrapTriggered( entity victim, var damageInfo )
+{
+ entity owner = DamageInfo_GetAttacker( damageInfo )
+
+ if( !IsValidPlayer( owner ) )
+ return
+
+ AddPlayerScore( owner, "FDArcTrapTriggered" )
+}
+
+void function FD_OnArcWaveDamage( entity ent, var damageInfo )
+{
+ entity attacker = DamageInfo_GetAttacker( damageInfo )
+
+ if( !IsValidPlayer( attacker ) )
+ return
+
+ AddPlayerScore( attacker, "FDArcWave" )
+}
+
+void function FD_OnTetherTrapTriggered( entity owner, entity endEnt )
+{
+ if( !IsValidPlayer( owner ) )
+ return
+
+ AddPlayerScore( owner, "FDTetherTriggered" )
+}
+
+void function FD_OnSonarStart( entity ent, vector position, int sonarTeam, entity sonarOwner )
+{
+ if( !IsValidPlayer( sonarOwner ) )
+ return
+
+ AddPlayerScore( sonarOwner, "FDSonarPulse" )//should only triggered once during sonar time?
}
-void function RateSpawnpoints_FD(int _0, array<entity> _1, int _2, entity _3)
+void function FD_SetupEpilogue()
{
+ AddCallback_GameStateEnter( eGameState.Epilogue, FD_Epilogue )
+}
+
+void function FD_Epilogue()
+{
+ thread FD_Epilogue_threaded()
+}
+
+void function FD_Epilogue_threaded()
+{
+ table<string,entity> awardOwners
+ table<string,float> awardValues
+ wait 5
+ foreach(entity player in GetPlayerArray() )
+ {
+ player.FreezeControlsOnServer()
+ ScreenFadeToBlackForever( player, 6.0 )
+
+ foreach( string ref in GetFDStatRefs() )
+ {
+ if( !( ref in awardOwners ) )
+ {
+ awardOwners[ref] <- player
+ awardValues[ref] <- file.playerAwardStats[player][ref]
+ }
+ else if( awardValues[ref] < file.playerAwardStats[player][ref] )
+ {
+ awardOwners[ref] = player
+ awardValues[ref] = file.playerAwardStats[player][ref]
+ }
+ }
+ }
+ table<entity, string> awardResults
+ table<entity, float> awardResultValues
+
+ foreach(string ref,entity player in awardOwners)
+ {
+
+ if( awardValues[ref] > GetFDStatData( ref ).validityCheckValue ) //might be >=
+ {
+ awardResults[player] <- ref
+ awardResultValues[player] <- awardValues[ref]
+ }
+
+ }
+
+ int gameMode = PersistenceGetEnumIndexForItemName( "gamemodes", GAMETYPE )
+ int map = PersistenceGetEnumIndexForItemName( "maps", GetMapName() )
+ int myIndex
+ int numPlayers = GetPlayerArray().len()
+
+ foreach( entity player in GetPlayerArray() )
+ {
+ if( !( player in awardResults ) )
+ {
+ awardResults[player] <- "damageDealt"
+ awardResultValues[player] <- file.playerAwardStats[player]["damageDealt"]
+ }
+ }
+
+ foreach( entity player in GetPlayerArray() )
+ {
+ if( !IsValid( player ) )
+ continue
+
+ int i = 0
+ myIndex = player.GetPlayerIndex()
+
+ player.SetPersistentVar( "postGameDataFD.gameMode", gameMode )
+ player.SetPersistentVar( "postGameDataFD.map", map )
+ player.SetPersistentVar( "postGameDataFD.myIndex", myIndex )
+ player.SetPersistentVar( "postGameDataFD.numPlayers", numPlayers )
+
+ foreach( entity medalPlayer, string ref in awardResults )
+ {
+ if( !IsValid( medalPlayer ) )
+ continue
+
+ if( i == numPlayers )
+ break
+
+ int targetIndex = medalPlayer.GetPlayerIndex()
+ if( targetIndex >= 4 )
+ continue
+
+ string name = medalPlayer.GetPlayerName()
+ string xuid = medalPlayer.GetUID()
+ int awardId = GetFDStatData( ref ).index
+ float awardValue = awardResultValues[medalPlayer]
+ int suitIndex = GetPersistentSpawnLoadoutIndex( medalPlayer, "titan" )
+ int playerEHandle = medalPlayer.GetEncodedEHandle()
-} \ No newline at end of file
+ player.SetPersistentVar( "postGameDataFD.players[" + targetIndex + "].name", name )
+ player.SetPersistentVar( "postGameDataFD.players[" + targetIndex + "].xuid", xuid )
+ player.SetPersistentVar( "postGameDataFD.players[" + targetIndex + "].awardId", awardId )
+ player.SetPersistentVar( "postGameDataFD.players[" + targetIndex + "].awardValue", awardValue )
+ player.SetPersistentVar( "postGameDataFD.players[" + targetIndex + "].suitIndex", suitIndex )
+ Remote_CallFunction_NonReplay( player, "ServerCallback_UpdateGameStats", playerEHandle, awardId, awardValue, suitIndex )
+ i++
+ }
+ Remote_CallFunction_NonReplay( player, "ServerCallback_ShowGameStats", Time() + 19 )
+ }
+ /* //debugging prints
+ foreach( entity player, table< string, float > data in file.playerAwardStats)
+ {
+ printt("Stats for", player)
+ foreach( string ref, float val in data )
+ {
+ printt(" ",ref,val)
+ }
+ }
+ foreach( string ref, entity player in awardOwners )
+ {
+ printt( player, ref, awardValues[ref] )
+ }
+ */
+ wait 20
+ SetGameState(eGameState.Postmatch)
+}
+
+void function IncrementPlayerstat_TurretRevives( entity player )
+{
+ file.playerAwardStats[player]["turretsRepaired"]++
+}
+
+void function SpawnCallback_SafeTitanSpawnTime( entity ent )
+{
+ if( ent.IsTitan() && IsValid( GetPetTitanOwner( ent ) ) )
+ {
+ entity player = GetPetTitanOwner( ent )
+ file.players[player].lastTitanDrop = Time()
+ }
+}
+
+void function DeathCallback_CalculateTitanAliveTime( entity ent )
+{
+ if( ent.IsTitan() && IsValid( GetPetTitanOwner( ent ) ) )
+ {
+ entity player = GetPetTitanOwner( ent )
+ float aliveTime = file.players[player].lastTitanDrop - Time()
+ if( aliveTime > file.playerAwardStats[player]["longestTitanLife"] )
+ file.playerAwardStats[player]["longestTitanLife"] = aliveTime
+ }
+}
+
+void function OnHarvesterDamaged( entity harvester, var damageInfo )
+{
+ if ( !IsValid( harvester ) )
+ return
+
+ if( fd_harvester.harvester != harvester )
+ return
+
+ if ( GetGlobalNetTime( "FD_harvesterInvulTime" ) > Time() )
+ {
+ harvester.SetShieldHealth( harvester.GetShieldHealthMax() )
+ return
+ }
+
+ int damageSourceID = DamageInfo_GetDamageSourceIdentifier( damageInfo )
+ entity attacker = DamageInfo_GetAttacker( damageInfo )
+ float damageAmount = DamageInfo_GetDamage( damageInfo )
+
+ if ( !damageSourceID && !damageAmount && !attacker )
+ return
+
+ fd_harvester.lastDamage = Time()
+
+ damageAmount = ( damageAmount * GetCurrentPlaylistVarFloat( "fd_player_damage_scalar", 1.0 ) )
+
+
+
+ float shieldPercent = ( ( harvester.GetShieldHealth().tofloat() / harvester.GetShieldHealthMax() ) * 100 )
+ if ( shieldPercent < 100 && !file.harvesterShieldDown )
+ PlayFactionDialogueToTeam( "fd_baseShieldTakingDmg", TEAM_MILITIA )
+
+ if ( shieldPercent < 35 && !file.harvesterShieldDown ) // idk i made this up
+ PlayFactionDialogueToTeam( "fd_baseShieldLow", TEAM_MILITIA )
+
+ if ( harvester.GetShieldHealth() == 0 )
+ {
+ if( !file.harvesterShieldDown )
+ {
+ PlayFactionDialogueToTeam( "fd_baseShieldDown", TEAM_MILITIA )
+ file.harvesterShieldDown = true // prevent shield dialogues from repeating
+ }
+ file.harvesterDamageTaken = file.harvesterDamageTaken + damageAmount // track damage for wave recaps
+ float newHealth = harvester.GetHealth() - damageAmount
+ float oldhealthpercent = ( ( harvester.GetHealth().tofloat() / harvester.GetMaxHealth() ) * 100 )
+ float healthpercent = ( ( newHealth / harvester.GetMaxHealth() ) * 100 )
+
+ if ( healthpercent <= 75 && oldhealthpercent > 75 ) // we don't want the dialogue to keep saying "Harvester is below 75% health" everytime they take additional damage
+ PlayFactionDialogueToTeam( "fd_baseHealth75", TEAM_MILITIA )
+
+ if ( healthpercent <= 50 && oldhealthpercent > 50 )
+ PlayFactionDialogueToTeam( "fd_baseHealth50", TEAM_MILITIA )
+
+ if ( healthpercent <= 25 && oldhealthpercent > 25 )
+ PlayFactionDialogueToTeam( "fd_baseHealth25", TEAM_MILITIA )
+
+ if( healthpercent <= 10 )
+ PlayFactionDialogueToTeam( "fd_baseLowHealth", TEAM_MILITIA )
+
+ if( newHealth <= 0 )
+ {
+ EmitSoundAtPosition( TEAM_UNASSIGNED, fd_harvester.harvester.GetOrigin(), "coop_generator_destroyed" )
+ newHealth = 1
+ harvester.SetInvulnerable()
+ DamageInfo_SetDamage( damageInfo, 0.0 )
+ PlayFactionDialogueToTeam( "fd_baseDeath", TEAM_MILITIA )
+ fd_harvester.rings.Anim_Stop()
+ }
+ harvester.SetHealth( newHealth )
+ file.havesterWasDamaged = true
+ }
+
+ if ( DamageInfo_GetDamageSourceIdentifier( damageInfo ) == eDamageSourceId.mp_titancore_laser_cannon )
+ DamageInfo_SetDamage( damageInfo, DamageInfo_GetDamage( damageInfo ) / 10 ) // laser core shreds super well for some reason
+
+ if ( attacker.IsPlayer() )
+ attacker.NotifyDidDamage( harvester, DamageInfo_GetHitBox( damageInfo ), DamageInfo_GetDamagePosition( damageInfo ), DamageInfo_GetCustomDamageType( damageInfo ), DamageInfo_GetDamage( damageInfo ), DamageInfo_GetDamageFlags( damageInfo ), DamageInfo_GetHitGroup( damageInfo ), DamageInfo_GetWeapon( damageInfo ), DamageInfo_GetDistFromAttackOrigin( damageInfo ) )
+}
+
+void function FD_NPCCleanup()
+{
+ foreach( entity player in GetPlayerArray() )
+ {
+ foreach ( entity ent in file.players[ player ].deployedEntityThisRound )
+ {
+ if ( IsValid( ent ) )
+ ent.Destroy()
+ }
+ }
+ foreach ( entity npc in GetEntArrayByClass_Expensive( "C_AI_BaseNPC" ) )
+ {
+ entity BossPlayer = npc.GetBossPlayer()
+ if( IsValidPlayer( BossPlayer ) && !file.players[ BossPlayer ].deployedEntityThisRound.contains( npc ) )
+ continue
+
+ if ( IsValid( npc ) )
+ npc.Destroy()
+ }
+ if( IsValid( fd_harvester.harvester ) )
+ fd_harvester.harvester.Destroy()//Destroy harvester after match over
+}
+
+void function HarvesterThink()
+{
+ entity harvester = fd_harvester.harvester
+
+
+ EmitSoundOnEntity( harvester, "coop_generator_startup" )
+
+ float lastTime = Time()
+ wait 4
+ int lastShieldHealth = harvester.GetShieldHealth()
+ generateBeamFX( fd_harvester )
+ generateShieldFX( fd_harvester )
+
+ EmitSoundOnEntity( harvester, "coop_generator_ambient_healthy" )
+
+ bool isRegening = false // stops the regenning sound to keep stacking on top of each other
+
+ while ( IsHarvesterAlive( harvester ) )
+ {
+ float currentTime = Time()
+ float deltaTime = currentTime -lastTime
+
+ if ( IsValid( fd_harvester.particleShield ) )
+ {
+ vector shieldColor = GetShieldTriLerpColor( 1.0 - ( harvester.GetShieldHealth().tofloat() / harvester.GetShieldHealthMax().tofloat() ) )
+ EffectSetControlPointVector( fd_harvester.particleShield, 1, shieldColor )
+ }
+
+ if( IsValid( fd_harvester.particleBeam ) )
+ {
+ vector beamColor = GetShieldTriLerpColor( 1.0 - ( harvester.GetHealth().tofloat() / harvester.GetMaxHealth().tofloat() ) )
+ EffectSetControlPointVector( fd_harvester.particleBeam, 1, beamColor )
+ }
+
+ if ( fd_harvester.harvester.GetShieldHealth() == 0 )
+ if( IsValid( fd_harvester.particleShield ) )
+ fd_harvester.particleShield.Destroy()
+
+ if ( ( ( currentTime-fd_harvester.lastDamage ) >= GENERATOR_SHIELD_REGEN_DELAY ) && ( harvester.GetShieldHealth() < harvester.GetShieldHealthMax() ) )
+ {
+ if( !IsValid( fd_harvester.particleShield ) )
+ generateShieldFX( fd_harvester )
+
+ //printt((currentTime-fd_harvester.lastDamage))
+
+ if( harvester.GetShieldHealth() == 0 )
+ EmitSoundOnEntity( harvester, "coop_generator_shieldrecharge_start" )
+
+ if (!isRegening)
+ {
+ EmitSoundOnEntity( harvester, "coop_generator_shieldrecharge_resume" )
+ file.harvesterShieldDown = false
+ if (GetGlobalNetBool( "FD_waveActive" ) )
+ PlayFactionDialogueToTeam( "fd_baseShieldRecharging", TEAM_MILITIA )
+ else
+ PlayFactionDialogueToTeam( "fd_baseShieldRechargingShort", TEAM_MILITIA )
+ isRegening = true
+ }
+
+ float newShieldHealth = ( harvester.GetShieldHealthMax() / GENERATOR_SHIELD_REGEN_TIME * deltaTime ) + harvester.GetShieldHealth()
+
+ if ( newShieldHealth >= harvester.GetShieldHealthMax() )
+ {
+ StopSoundOnEntity( harvester, "coop_generator_shieldrecharge_resume" )
+ harvester.SetShieldHealth( harvester.GetShieldHealthMax() )
+ EmitSoundOnEntity( harvester, "coop_generator_shieldrecharge_end" )
+ if( GetGlobalNetBool( "FD_waveActive" ) )
+ PlayFactionDialogueToTeam( "fd_baseShieldUp", TEAM_MILITIA )
+ isRegening = false
+ }
+ else
+ {
+ harvester.SetShieldHealth( newShieldHealth )
+ }
+ } else if ( ( ( currentTime-fd_harvester.lastDamage ) < GENERATOR_SHIELD_REGEN_DELAY ) && ( harvester.GetShieldHealth() < harvester.GetShieldHealthMax() ) )
+ isRegening = false
+
+ if ( ( lastShieldHealth > 0 ) && ( harvester.GetShieldHealth() == 0 ) )
+ EmitSoundOnEntity( harvester, "coop_generator_shielddown" )
+
+ lastShieldHealth = harvester.GetShieldHealth()
+ lastTime = currentTime
+ WaitFrame()
+ }
+
+}
+
+void function startHarvester()
+{
+
+ thread HarvesterThink()
+ thread HarvesterAlarm()
+
+}
+
+void function HarvesterAlarm()
+{
+ while( IsHarvesterAlive( fd_harvester.harvester ) )
+ {
+ if( fd_harvester.harvester.GetShieldHealth() == 0 )
+ {
+ wait EmitSoundOnEntity( fd_harvester.harvester, "coop_generator_underattack_alarm" )
+ }
+ else
+ {
+ WaitFrame()
+ }
+ }
+}
+
+void function initNetVars()
+{
+ SetGlobalNetInt( "FD_totalWaves", waveEvents.len() )
+ SetGlobalNetInt( "burn_turretLimit", 2 )
+ if(!FD_HasRestarted())
+ {
+ bool showShop = false
+ SetGlobalNetInt( "FD_currentWave", 0 )
+ if( FD_IsDifficultyLevelOrHigher( eFDDifficultyLevel.INSANE ) )
+ FD_SetNumAllowedRestarts( 0 )
+ else
+ FD_SetNumAllowedRestarts( 2 )
+ }
+
+
+}
+
+void function FD_DamageByPlayerCallback( entity victim, var damageInfo )
+{
+ entity player = DamageInfo_GetAttacker( damageInfo )
+ if( !( player in file.players ) )
+ return
+ float damage = DamageInfo_GetDamage( damageInfo )
+ file.playerAwardStats[player]["damageDealt"] += damage
+ file.players[ player ].scoreThisRound += damage.tointeger() //TODO NOT HOW SCORE WORKS
+ if( victim.IsTitan() )
+ {
+ //TODO Money and score for titan damage
+ }
+
+}
+
+void function DamageScaleByDifficulty( entity ent, var damageInfo )
+{
+ entity attacker = DamageInfo_GetAttacker( damageInfo )
+
+ if ( !attacker )
+ return
+
+ if ( ent.GetTeam() != TEAM_MILITIA )
+ return
+
+ int damageSourceID = DamageInfo_GetDamageSourceIdentifier( damageInfo )
+ float damageAmount = DamageInfo_GetDamage( damageInfo )
+
+ if ( !damageSourceID && !damageAmount )
+ return
+
+ if ( attacker.IsPlayer() && attacker.GetTeam() == TEAM_IMC ) // in case we ever want a PvP in Frontier Defense, don't scale their damage
+ return
+
+
+ if ( attacker == ent ) // dont scale self damage
+ return
+
+
+ DamageInfo_SetDamage( damageInfo, ( damageAmount * GetCurrentPlaylistVarFloat( "fd_player_damage_scalar", 1.0 ) ) )
+
+
+
+}
+
+
+
+void function HealthScaleByDifficulty( entity ent )
+{
+
+ if ( ent.GetTeam() != TEAM_IMC )
+ return
+
+
+ if (ent.IsTitan()&& IsValid(GetPetTitanOwner( ent ) ) ) // in case we ever want pvp in FD
+ return
+
+ if ( ent.IsTitan() )
+ ent.SetMaxHealth( ent.GetMaxHealth() + GetCurrentPlaylistVarInt( "fd_titan_health_adjust", 0 ) )
+ else
+ ent.SetMaxHealth( ent.GetMaxHealth() + GetCurrentPlaylistVarInt( "fd_reaper_health_adjust", 0 ) )
+
+ if( GetCurrentPlaylistVarInt( "fd_pro_titan_shields", 0 ) && ent.IsTitan() )
+ {
+ entity soul = ent.GetTitanSoul()
+ if( IsValid( soul ) )
+ {
+ soul.SetShieldHealthMax( 2500 )
+ soul.SetShieldHealth( 2500 )
+ }
+ }
+
+
+}
+
+void function FD_createHarvester()
+{
+
+ fd_harvester = SpawnHarvester( file.harvester_info.GetOrigin(), file.harvester_info.GetAngles(), GetCurrentPlaylistVarInt( "fd_harvester_health", 25000 ), GetCurrentPlaylistVarInt( "fd_harvester_shield", 6000 ), TEAM_MILITIA )
+ fd_harvester.harvester.Minimap_SetAlignUpright( true )
+ fd_harvester.harvester.Minimap_AlwaysShow( TEAM_IMC, null )
+ fd_harvester.harvester.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ fd_harvester.harvester.Minimap_SetHeightTracking( true )
+ fd_harvester.harvester.Minimap_SetZOrder( MINIMAP_Z_OBJECT )
+ fd_harvester.harvester.Minimap_SetCustomState( eMinimapObject_prop_script.FD_HARVESTER )
+ AddEntityCallback_OnDamaged( fd_harvester.harvester, OnHarvesterDamaged )
+ thread CreateHarvesterHintTrigger( fd_harvester.harvester )
+}
+
+bool function IsHarvesterAlive( entity harvester )
+{
+ if ( harvester == null )
+ return false
+ if ( !harvester.IsValidInternal() )
+ return false
+ if( !harvester.IsEntAlive() )
+ return false
+
+ return harvester.GetHealth() > 1
+}
+
+void function CreateHarvesterHintTrigger( entity harvester )
+{
+ entity trig = CreateEntity( "trigger_cylinder" )
+ trig.SetRadius( 1000 ) //Test setting
+ trig.SetAboveHeight( 2500 ) //Test setting
+ trig.SetBelowHeight( 2500 ) //Test setting
+ trig.SetOrigin( harvester.GetOrigin() )
+ trig.kv.triggerFilterNpc = "none"
+ trig.kv.triggerFilterPlayer = "all"
+
+ SetTeam( trig, harvester.GetTeam() )
+ DispatchSpawn( trig )
+ trig.SetEnterCallback( OnEnterNearHarvesterTrigger )
+ trig.SetLeaveCallback( OnLeaveNearHarvesterTrigger )
+
+ harvester.EndSignal( "OnDestroy" )
+ trig.EndSignal( "OnDestroy" )
+
+ OnThreadEnd(
+ function() : ( trig )
+ {
+ if ( IsValid( trig ) )
+ trig.Destroy()
+ }
+ )
+
+ WaitForever()
+}
+
+void function OnEnterNearHarvesterTrigger( entity trig, entity activator )
+{
+ if( !( activator in file.players ) )
+ return
+
+ if( GetGlobalNetInt( "FD_waveState" ) != WAVE_STATE_IN_PROGRESS )
+ return
+
+ if ( activator != null && activator.IsPlayer() && activator.GetTeam() == trig.GetTeam() && file.players[activator].leaveHarvester == true )
+ {
+ file.players[activator].lastNearHarvester = Time()
+ file.players[activator].leaveHarvester = false
+ }
+}
+
+void function OnLeaveNearHarvesterTrigger( entity trig, entity activator )
+{
+ if( !( activator in file.players ) )
+ return
+
+ if( GetGlobalNetInt( "FD_waveState" ) != WAVE_STATE_IN_PROGRESS )
+ return
+
+ float CurrentTime = Time() - file.players[activator].lastNearHarvester
+
+ if ( activator != null && activator.IsPlayer() && activator.GetTeam() == trig.GetTeam() && file.players[activator].leaveHarvester == false )
+ {
+ file.playerAwardStats[activator]["timeNearHarvester"] += CurrentTime
+ file.players[activator].leaveHarvester = true
+ }
+}
+
+bool function isFinalWave()
+{
+ return ( ( GetGlobalNetInt( "FD_currentWave" ) + 1 ) == GetGlobalNetInt( "FD_totalWaves" ) )
+}
+
+bool function isSecondWave()
+{
+ return ( (GetGlobalNetInt( "FD_currentWave" ) + 1 ) == 1 )
+}
+
+void function LoadEntities()
+{
+ CreateBoostStoreLocation( TEAM_MILITIA, shopPosition, shopAngles )
+ foreach ( entity info_target in GetEntArrayByClass_Expensive( "info_target" ) )
+ {
+
+ if ( GameModeRemove( info_target ) )
+ continue
+
+ if( info_target.HasKey( "editorclass" ) )
+ {
+ switch( info_target.kv.editorclass )
+ {
+ case "info_fd_harvester":
+ file.harvester_info = info_target
+ break
+ case "info_fd_mode_model":
+ entity prop = CreatePropDynamic( info_target.GetModelName(), info_target.GetOrigin(), info_target.GetAngles(), 6 )
+ break
+ case "info_fd_ai_position":
+ AddStationaryAIPosition( info_target.GetOrigin(), int( info_target.kv.aiType ) )
+ break
+ case "info_fd_route_node":
+ routeNodes.append( info_target )
+ break
+ case "info_fd_smoke_screen":
+ file.smokePoints.append( info_target )
+ break
+ }
+ }
+ }
+ ValidateAndFinalizePendingStationaryPositions()
+ initNetVars()
+ SetTeam( GetTeamEnt( TEAM_IMC ), TEAM_IMC )
+}
+
+
+bool function allPlayersReady()
+{
+ foreach( entity player in GetPlayerArray() )
+ {
+ if( !player.GetPlayerNetBool( "FD_readyForNextWave" ) )
+ return false
+ }
+ return true
+}
+
+void function CheckLastPlayerReady()
+{
+ int readyplayers = 0
+ entity notready
+ foreach( entity player in GetPlayerArray() )
+ {
+ if( player.GetPlayerNetBool( "FD_readyForNextWave" ) )
+ readyplayers++
+ else
+ notready = player // keep a track of this player
+ }
+ if ( readyplayers == GetPlayerArray().len() - 1 )
+ PlayFactionDialogueToPlayer( "fd_playerNeedsToReadyUp", notready ) // ready up i swear there's one player like this in every match i've played
+}
+
+bool function ClientCommandCallbackToggleReady( entity player, array<string> args )
+{
+ if( args[0] == "true" )
+ {
+ player.SetPlayerNetBool( "FD_readyForNextWave", true )
+ MessageToTeam( TEAM_MILITIA,eEventNotifications.FD_PlayerReady, null, player )
+ }
+ if( args[0] == "false" )
+ player.SetPlayerNetBool( "FD_readyForNextWave", false )
+
+ CheckLastPlayerReady()
+ return true
+}
+
+int function getHintForTypeId( int typeId )
+{
+ //this is maybe a bit of an naive aproch
+ switch( typeId )
+ {
+ case eFD_AITypeIDs.TITAN_NUKE:
+ return ( 348 + RandomIntRangeInclusive( 0, 1 ) )
+ case eFD_AITypeIDs.TITAN_ARC:
+ return ( 350 + RandomIntRangeInclusive( 0, 1 ) )
+ case eFD_AITypeIDs.TITAN_MORTAR:
+ return ( 352 + RandomIntRangeInclusive( 0, 1 ) )
+ case eFD_AITypeIDs.GRUNT:
+ return 354
+ case eFD_AITypeIDs.SPECTRE:
+ return 355
+ case eFD_AITypeIDs.SPECTRE_MORTAR:
+ return ( 356 + RandomIntRangeInclusive( 0, 1 ) )
+ case eFD_AITypeIDs.STALKER:
+ if( RandomIntRangeInclusive( 0, 1 ) == 0 )
+ return 358
+ else
+ return 361
+ case eFD_AITypeIDs.REAPER:
+ return ( 359 + RandomIntRangeInclusive( 0, 1 ) )
+ case eFD_AITypeIDs.DRONE:
+ return 362
+ case eFD_AITypeIDs.TITAN_SNIPER:
+ return ( 371 + RandomIntRangeInclusive( 0, 2 ) )
+ default:
+ return ( 363 + RandomIntRangeInclusive( 0, 7 ) )
+ }
+ unreachable
+}
+
+string function GetTargetNameForID( int typeId )
+{
+ switch( typeId )
+ {
+ case eFD_AITypeIDs.TITAN_NUKE:
+ return "npc_titan_nuke"
+ case eFD_AITypeIDs.LEGION:
+ return "npc_titan_ogre_minigun"
+ case eFD_AITypeIDs.TITAN_ARC:
+ return "empTitan"
+ case eFD_AITypeIDs.RONIN:
+ return "npc_titan_stryder_leadwall"
+ case eFD_AITypeIDs.TITAN_MORTAR:
+ return "npc_titan_mortar"
+ case eFD_AITypeIDs.TONE:
+ return "npc_titan_atlas_tracker"
+ case eFD_AITypeIDs.TITAN_SNIPER:
+ return "npc_titan_sniper"
+ case eFD_AITypeIDs.NORTHSTAR:
+ return "npc_titan_stryder_sniper"
+ case eFD_AITypeIDs.ION:
+ return "npc_titan_atlas_stickybomb"
+ case eFD_AITypeIDs.SCORCH:
+ return "npc_titan_ogre_meteor"
+ case eFD_AITypeIDs.MONARCH:
+ return "npc_titan_atlas_vanguard"
+ case eFD_AITypeIDs.GRUNT:
+ return "grunt"
+ case eFD_AITypeIDs.SPECTRE:
+ return "spectre"
+ case eFD_AITypeIDs.SPECTRE_MORTAR:
+ return "mortar_spectre"
+ case eFD_AITypeIDs.STALKER:
+ return "stalker"
+ case eFD_AITypeIDs.REAPER:
+ return "reaper"
+ case eFD_AITypeIDs.TICK:
+ return "tick"
+ case eFD_AITypeIDs.DRONE:
+ return "drone"
+ case eFD_AITypeIDs.DRONE_CLOAK:
+ return "Cloak Drone" // have to be like this for some reason in cl_gamemode_fd
+ default:
+ return "titan"
+ }
+ unreachable
+}
+
+string function GetAiNetIdFromTargetName( string targetName )
+{
+ switch ( targetName )
+ {
+ case "titan":
+ case "sniperTitan":
+ case "npc_titan_ogre_meteor_boss_fd":
+ case "npc_titan_ogre_meteor":
+ case "npc_titan_ogre_minigun_boss_fd":
+ case "npc_titan_ogre_minigun":
+ case "npc_titan_atlas_stickybomb_boss_fd":
+ case "npc_titan_atlas_stickybomb":
+ case "npc_titan_atlas_tracker_boss_fd":
+ case "npc_titan_atlas_tracker":
+ case "npc_titan_stryder_leadwall_boss_fd":
+ case "npc_titan_stryder_leadwall":
+ case "npc_titan_stryder_sniper_boss_fd":
+ case "npc_titan_stryder_sniper":
+ case "npc_titan_sniper":
+ case "npc_titan_sniper_tone":
+ case "npc_titan_atlas_vanguard_boss_fd":
+ case "npc_titan_atlas_vanguard":
+ return "FD_AICount_Titan"
+ case "empTitan":
+ case "npc_titan_arc":
+ return "FD_AICount_Titan_Arc"
+ case "mortarTitan":
+ case "npc_titan_mortar":
+ return "FD_AICount_Titan_Mortar"
+ case "nukeTitan":
+ case "npc_titan_nuke":
+ return "FD_AICount_Titan_Nuke"
+ case "npc_soldier":
+ case "grunt":
+ return "FD_AICount_Grunt"
+ case "spectre":
+ return "FD_AICount_Spectre"
+ case "mortar_spectre":
+ return "FD_AICount_Spectre_Mortar"
+ case "npc_stalker":
+ case "stalker":
+ return "FD_AICount_Stalker"
+ case "npc_super_spectre":
+ case "reaper":
+ return "FD_AICount_Reaper"
+ case "npc_drone":
+ case "drone":
+ return "FD_AICount_Drone"
+ case "cloakedDrone":
+ case "Cloak Drone":
+ return "FD_AICount_Drone_Cloak"
+ case "tick":
+ return "FD_AICount_Ticks"
+ }
+ printt( "unknown target name ", targetName )
+ return ""
+}
+
+
+
+void function AddTurretSentry( entity turret )
+{
+ turret.Minimap_AlwaysShow( TEAM_IMC, null )
+ turret.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ turret.Minimap_SetHeightTracking( true )
+ turret.Minimap_SetCustomState( eMinimapObject_npc.FD_TURRET )
+ entity player = turret.GetBossPlayer()
+ file.players[ player ].deployedEntityThisRound.append( turret )
+ AddEntityDestroyedCallback( turret, FD_OnEntityDestroyed )
+ thread TurretRefundThink( turret )
+}
+
+function FD_OnEntityDestroyed( ent )
+{
+ expect entity( ent )
+
+ Assert( ent.IsValidInternal() )
+ entity player = IsTurret( ent ) ? ent.GetBossPlayer() : ent.GetOwner()
+
+ if( !IsValid( player ) )
+ return
+
+ if( file.players[ player ].deployedEntityThisRound.contains( ent ) )
+ file.players[ player ].deployedEntityThisRound.fastremovebyvalue( ent )
+}
+
+void function OnPlayerDisconnectedOrDestroyed( entity player )
+{
+ if( !IsValid( player ) )
+ {
+ ClearInValidTurret()
+ return
+ }
+
+ foreach ( entity npc in GetEntArrayByClass_Expensive( "C_AI_BaseNPC" ) )
+ {
+ entity BossPlayer = npc.GetBossPlayer()
+ if ( IsValidPlayer( BossPlayer ) && IsValid( npc ) && player == BossPlayer )
+ npc.Destroy()
+ }
+ file.players[ player ].deployedEntityThisRound.clear()
+}
+
+void function ClearInValidTurret()
+{
+ foreach( entity turret in GetNPCArrayByClass( "npc_turret_sentry" ) )
+ {
+ entity BossPlayer = turret.GetBossPlayer()
+ if ( !IsValidPlayer( BossPlayer ) && IsValid( turret ) )
+ turret.Destroy()
+ }
+}
+
+void function DisableTitanSelection()
+{
+ foreach ( entity player in GetPlayerArray() )
+ {
+ DisableTitanSelectionForPlayer( player )
+ }
+}
+
+void function EnableTitanSelection()
+{
+ foreach ( entity player in GetPlayerArray() )
+ {
+ EnableTitanSelectionForPlayer( player )
+ }
+}
+
+void function EnableTitanSelectionForPlayer( entity player )
+{
+ int enumCount = PersistenceGetEnumCount( "titanClasses" )
+
+ if( !IsValid( player ) )
+ return
+
+ for ( int i = 0; i < enumCount; i++ )
+ {
+ string enumName = PersistenceGetEnumItemNameForIndex( "titanClasses", i )
+ if ( enumName != "" )
+ player.SetPersistentVar( "titanClassLockState[" + enumName + "]", TITAN_CLASS_LOCK_STATE_AVAILABLE )
+
+ }
+}
+
+void function DisableTitanSelectionForPlayer( entity player )
+{
+ int enumCount = PersistenceGetEnumCount( "titanClasses" )
+
+ if( !IsValid( player ) )
+ return
+
+ for ( int i = 0; i < enumCount; i++ )
+ {
+ string enumName = PersistenceGetEnumItemNameForIndex( "titanClasses", i )
+ string selectedEnumName = PersistenceGetEnumItemNameForIndex( "titanClasses", player.GetPersistentVarAsInt("activeTitanLoadoutIndex") )
+ if ( enumName != "" && enumName != selectedEnumName )
+ player.SetPersistentVar( "titanClassLockState[" + enumName + "]", TITAN_CLASS_LOCK_STATE_LOCKED )
+ }
+}
+
+
+
+
+void function FD_DropshipSpawnDropship()
+{
+ file.playersInShip = 0
+ file.dropshipState = eDropshipState.InProgress
+ file.dropship = CreateDropship( TEAM_MILITIA, FD_spawnPosition , FD_spawnAngles )
+
+
+ file.dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" )
+ file.dropship.SetValueForModelKey( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" )
+
+ DispatchSpawn( file.dropship )
+ file.dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" )
+ file.dropship.SetInvulnerable()
+ file.dropship.SetNoTarget( true )
+
+ thread PlayAnim(file.dropship, FD_DropshipGetAnimation())
+
+ array<string> anims = GetRandomDropshipDropoffAnims()
+
+ //thread WarpinEffect( $"models/vehicle/crow_dropship/crow_dropship.mdl", anims[0], file.dropship.GetOrigin(),f ile.dropship.GetAngles() ) //this does not work
+ file.dropship.WaitSignal( "deploy" )
+ file.dropshipState = eDropshipState.Returning
+ foreach(int i,entity player in file.playersInDropship)
+ {
+ thread FD_DropshipDropPlayer( player, i )
+ }
+ file.playersInDropship.clear()
+
+ wait 8
+ file.dropshipState = eDropshipState.Idle
+}
+
+void function FD_DropshipDropPlayer(entity player,int playerDropshipIndex)
+{
+ player.EndSignal( "OnDestroy" )
+ FirstPersonSequenceStruct jumpSequence
+ jumpSequence.firstPersonAnim = DROPSHIP_EXIT_ANIMS_POV[ playerDropshipIndex ]
+ jumpSequence.thirdPersonAnim = DROPSHIP_EXIT_ANIMS[ playerDropshipIndex ]
+ jumpSequence.attachment = "ORIGIN"
+ jumpSequence.blendTime = 0.0
+ jumpSequence.viewConeFunction = ViewConeFree
+
+ thread FirstPersonSequence( jumpSequence, player, file.dropship )
+
+ //check the player
+ if( IsValid( player ) )
+ {
+ WaittillAnimDone( player )
+ player.ClearParent()
+ ClearPlayerAnimViewEntity( player )
+ player.ClearInvulnerable()
+ }
+}
+
+void function FD_DropshipSetAnimationOverride(string animation)
+{
+ file.animationOverride = animation
+}
+
+string function FD_DropshipGetAnimation()
+{
+ if(file.animationOverride!="")
+ return file.animationOverride
+
+ switch( GetMapName() )
+ {
+ case "mp_homestead":
+ return "dropship_coop_respawn_homestead"
+ case "mp_lagoon":
+ return "dropship_coop_respawn_lagoon"
+ case "mp_overlook":
+ return "dropship_coop_respawn_overlook"
+ case "mp_outpost":
+ return "dropship_coop_respawn_outpost"
+ case "mp_wargames":
+ return "dropship_coop_respawn_wargames"
+ case "mp_digsite":
+ return "dropship_coop_respawn_digsite"
+ }
+ return "dropship_coop_respawn"
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd_events.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd_events.nut
new file mode 100644
index 00000000..e73b73c5
--- /dev/null
+++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd_events.nut
@@ -0,0 +1,1349 @@
+global function CreateSmokeEvent
+global function CreateArcTitanEvent
+global function CreateWaitForTimeEvent
+global function CreateSuperSpectreEvent
+global function CreateSuperSpectreEventWithMinion
+global function CreateDroppodGruntEvent
+global function CreateNukeTitanEvent
+global function CreateMortarTitanEvent
+global function CreateGenericSpawnEvent
+global function CreateGenericTitanSpawnWithAiSettingsEvent
+global function CreateDroppodStalkerEvent
+global function CreateDroppodSpectreMortarEvent
+global function CreateWaitUntilAliveEvent
+global function CreateWaitUntilAliveWeightedEvent
+global function CreateCloakDroneEvent
+global function CreateDroppodTickEvent
+global function CreateSpawnDroneEvent
+global function CreateToneSniperTitanEvent
+global function CreateNorthstarSniperTitanEvent //northstars are always sniper titans
+global function CreateIonTitanEvent
+global function CreateScorchTitanEvent
+global function CreateRoninTitanEvent
+global function CreateToneTitanEvent
+global function CreateLegionTitanEvent
+global function CreateMonarchTitanEvent
+global function CreateWarningEvent
+global function executeWave
+global function restetWaveEvents
+global function WinWave
+
+global struct SmokeEvent{
+ vector position
+ float lifetime
+}
+
+global struct SpawnEvent{
+ vector origin
+ vector angles
+ string route //defines route taken by the ai
+ int skippedRouteNodes //defines how many route nodes will be skipped
+ int spawnType //Just used for Wave Info but can be used for spawn too should contain aid of spawned enemys
+ int spawnAmount //Just used for Wave Info but can be used for spawn too should contain amound of spawned enemys
+ string npcClassName
+ string aiSettings
+ string entityGlobalKey
+ bool shouldLoop = false
+}
+
+global struct FlowControlEvent{
+ float waitTime
+ int splitNextEventIndex
+ int waitAmount
+ int waitEntityType
+ array<string> waitGlobalDataKey
+}
+
+global struct SoundEvent{
+ string soundEventName
+}
+
+global struct WaveEvent{
+ void functionref(SmokeEvent,SpawnEvent,FlowControlEvent,SoundEvent) eventFunction
+ bool shouldThread
+ int executeOnThisCall //will actually be executed when called this many times
+ int timesExecuted
+ int nextEventIndex
+ SmokeEvent smokeEvent
+ SpawnEvent spawnEvent
+ FlowControlEvent flowControlEvent
+ SoundEvent soundEvent
+
+}
+
+global enum FD_IncomingWarnings
+{
+ CloakDrone,
+ ArcTitan,
+ Reaper,
+ MortarTitan,
+ NukeTitan
+}
+
+global table< string, entity > GlobalEventEntitys
+global array< array<WaveEvent> > waveEvents
+
+
+
+void function executeWave()
+{
+ print( "executeWave Start" )
+ thread runEvents( 0 )
+ while( IsHarvesterAlive( fd_harvester.harvester ) && ( !allEventsExecuted( GetGlobalNetInt( "FD_currentWave" ) ) ) )
+ WaitFrame()
+ wait 5 //incase droppod is last event so all npc are spawned
+ waitUntilLessThanAmountAlive( 0 )
+ waitUntilLessThanAmountAlive_expensive( 0 )
+
+ foreach (entity ent in GetEntArrayByClass_Expensive( "npc_turret_sentry" ) )
+ RevivableTurret_Revive( ent )
+}
+
+bool function allEventsExecuted( int waveIndex )
+{
+ foreach( WaveEvent e in waveEvents[waveIndex] )
+ {
+ if( e.executeOnThisCall > e.timesExecuted )
+ return false
+ }
+ return true
+}
+
+void function runEvents( int firstExecuteIndex )
+{
+ print( "runEvents Start" )
+ WaveEvent currentEvent = waveEvents[GetGlobalNetInt( "FD_currentWave" )][firstExecuteIndex]
+
+ while(true)
+ {
+ currentEvent.timesExecuted++
+ if(currentEvent.timesExecuted!=currentEvent.executeOnThisCall)
+ {
+ print( "not on this call" )
+ return
+ }
+ if( !IsHarvesterAlive(fd_harvester.harvester ) )
+ {
+ print( "harvesterDead" )
+ return
+ }
+ if( currentEvent.shouldThread )
+ {
+ print( "execute with thread" )
+ thread currentEvent.eventFunction( currentEvent.smokeEvent, currentEvent.spawnEvent, currentEvent.flowControlEvent, currentEvent.soundEvent )
+ }
+ else
+ {
+ print( "execute without thread" )
+ currentEvent.eventFunction( currentEvent.smokeEvent, currentEvent.spawnEvent, currentEvent.flowControlEvent, currentEvent.soundEvent )
+ }
+ if( currentEvent.nextEventIndex == 0 )
+ {
+ print( "zero index" )
+ return
+ }
+ currentEvent = waveEvents[GetGlobalNetInt( "FD_currentWave" )][currentEvent.nextEventIndex]
+ }
+ print( "runEvents End" )
+}
+
+void function restetWaveEvents()
+{
+ foreach( WaveEvent event in waveEvents[GetGlobalNetInt( "FD_currentWave" )] )
+ {
+ event.timesExecuted = 0
+ }
+}
+
+
+
+
+
+
+
+/****************************************************************************************************************\
+####### # # ####### # # ####### ##### ####### # # ####### ###### # ####### ####### ######
+# # # # ## # # # # # ## # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # #
+##### # # ##### # # # # # #### ##### # # # ##### ###### # # # # # ######
+# # # # # # # # # # # # # # # # # ####### # # # # #
+# # # # # ## # # # # # ## # # # # # # # # # #
+####### # ####### # # # ##### ####### # # ####### # # # # # ####### # #
+\*****************************************************************************************************************/
+
+WaveEvent function CreateSmokeEvent( vector position, float lifetime, int nextEventIndex, int executeOnThisCall = 1 )
+{
+ WaveEvent event
+ event.eventFunction = spawnSmoke
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.smokeEvent.position = position
+ event.smokeEvent.lifetime = lifetime
+ return event
+}
+
+WaveEvent function CreateArcTitanEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnArcTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TITAN_ARC
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateSuperSpectreEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnSuperSpectre
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.REAPER
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateSuperSpectreEventWithMinion( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnSuperSpectreWithMinion
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.REAPER
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateDroppodGruntEvent( vector origin, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnDroppodGrunts
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.GRUNT
+ event.spawnEvent.spawnAmount = 4
+ event.spawnEvent.origin = origin
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateDroppodStalkerEvent( vector origin, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnDroppodStalker
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.STALKER
+ event.spawnEvent.spawnAmount = 4
+ event.spawnEvent.origin = origin
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateDroppodSpectreMortarEvent( vector origin, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnDroppodSpectreMortar
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.SPECTRE_MORTAR
+ event.spawnEvent.spawnAmount = 4
+ event.spawnEvent.origin = origin
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateWaitForTimeEvent( float waitTime, int nextEventIndex, int executeOnThisCall = 1 )
+{
+ WaveEvent event
+ event.shouldThread = false
+ event.eventFunction = waitForTime
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.flowControlEvent.waitTime = waitTime
+ return event
+}
+
+WaveEvent function CreateWaitUntilAliveEvent( int amount, int nextEventIndex, int executeOnThisCall = 1 )
+{
+ WaveEvent event
+ event.eventFunction = waitUntilLessThanAmountAliveEvent
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = false
+ event.flowControlEvent.waitAmount = amount
+ return event
+}
+
+WaveEvent function CreateWaitUntilAliveWeightedEvent( int amount, int nextEventIndex, int executeOnThisCall = 1 )
+{
+ WaveEvent event
+ event.eventFunction = waitUntilLessThanAmountAliveEventWeighted
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = false
+ event.flowControlEvent.waitAmount = amount
+ return event
+}
+
+WaveEvent function CreateGenericSpawnEvent( string npcClassName, vector origin, vector angles, string route, int spawnType, int spawnAmount, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnGenericNPC
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.npcClassName = npcClassName
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.spawnType = spawnType
+ event.spawnEvent.spawnAmount = spawnAmount
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateGenericTitanSpawnWithAiSettingsEvent( string npcClassName, string aiSettings, vector origin, vector angles, string route, int spawnType, int spawnAmount, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnGenericNPCTitanwithSettings
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.npcClassName = npcClassName
+ event.spawnEvent.aiSettings = aiSettings
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.spawnType = spawnType
+ event.spawnEvent.spawnAmount = spawnAmount
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateNukeTitanEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnNukeTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TITAN_NUKE
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateMortarTitanEvent( vector origin, vector angles, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnMortarTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TITAN_MORTAR
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateCloakDroneEvent( vector origin, vector angles, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = fd_spawnCloakDrone
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.DRONE_CLOAK
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateDroppodTickEvent( vector origin, int amount, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = SpawnTick
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TICK
+ event.spawnEvent.spawnAmount = amount
+ event.spawnEvent.origin = origin
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateNorthstarSniperTitanEvent( vector origin, vector angles, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = spawnSniperTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TITAN_SNIPER
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateToneSniperTitanEvent( vector origin, vector angles, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = SpawnToneSniperTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TITAN_SNIPER
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+
+WaveEvent function CreateIonTitanEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = SpawnIonTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.ION
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateScorchTitanEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = SpawnScorchTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.SCORCH
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateRoninTitanEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = SpawnRoninTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.RONIN
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateToneTitanEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = SpawnToneTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TONE
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateLegionTitanEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = SpawnLegionTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.LEGION
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateMonarchTitanEvent( vector origin, vector angles, string route, int nextEventIndex, int executeOnThisCall = 1, string entityGlobalKey = "" )
+{
+ WaveEvent event
+ event.eventFunction = SpawnMonarchTitan
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.MONARCH
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ return event
+}
+
+WaveEvent function CreateWaitForDeathOfEntitysEvent( array<string> waitGlobalDataKey, int nextEventIndex, int executeOnThisCall = 1 )
+{
+ WaveEvent event
+ event.eventFunction = waitForDeathOfEntitys
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event. shouldThread = false
+ event.flowControlEvent.waitGlobalDataKey = waitGlobalDataKey
+ return event
+}
+
+WaveEvent function CreateWaitForLessThanTypedEvent(int aiTypeId,int amount,int nextEventIndex,int executeOnThisCall = 1 )
+{
+ WaveEvent event
+ event.eventFunction = waitForLessThanAliveTyped
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = false
+ event.flowControlEvent.waitAmount = amount
+ event.flowControlEvent.waitEntityType = aiTypeId
+ return event
+}
+
+WaveEvent function CreateSpawnDroneEvent(vector origin,vector angles,string route,int nextEventIndex, bool shouldLoop = true, int executeOnThisCall = 1,string entityGlobalKey="")
+{
+ WaveEvent event
+ event.eventFunction = spawnDrones
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.DRONE
+ event.spawnEvent.spawnAmount = 4
+ event.spawnEvent.origin = origin
+ event.spawnEvent.entityGlobalKey = entityGlobalKey
+ event.spawnEvent.route = route
+ event.spawnEvent.shouldLoop = shouldLoop
+ return event
+}
+
+
+
+WaveEvent function CreateWarningEvent( int warningType, int nextEventIndex, int executeOnThisCall = 1 )
+{
+ WaveEvent event
+ event.eventFunction = PlayWarning
+ event.executeOnThisCall = executeOnThisCall
+ event.nextEventIndex = nextEventIndex
+ event.shouldThread = false
+
+ event.soundEvent.soundEventName = "fd_inc" + ["CloakDrone", "ArcTitan", "Reaper", "TitansMortar", "TitansNuke"][warningType] + "Clump"
+ return event
+}
+
+/************************************************************************************************************\
+####### # # ####### # # ####### ####### # # # # ##### ####### ### ####### # # #####
+# # # # ## # # # # # ## # # # # # # # ## # # #
+# # # # # # # # # # # # # # # # # # # # # # #
+##### # # ##### # # # # ##### # # # # # # # # # # # # # #####
+# # # # # # # # # # # # # # # # # # # # # # #
+# # # # # ## # # # # # ## # # # # # # # ## # #
+####### # ####### # # # # ##### # # ##### # ### ####### # # #####
+\************************************************************************************************************/
+
+void function PlayWarning( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PlayFactionDialogueToTeam( soundEvent.soundEventName, TEAM_MILITIA )
+}
+
+void function spawnSmoke( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ printt( "smoke" )
+ SmokescreenStruct smokescreen
+ smokescreen.smokescreenFX = $"P_smokescreen_FD"
+ smokescreen.isElectric = false
+ smokescreen.origin = smokeEvent.position + < 0, 0, 100 >
+ smokescreen.angles = < 0, 0, 0 >
+ smokescreen.lifetime = smokeEvent.lifetime
+ smokescreen.fxXYRadius = 150
+ smokescreen.fxZRadius = 120
+ smokescreen.fxOffsets = [ < 130.0, 0.0, 0.0 >, < 0.0, 130.0, 0.0 >, < 0.0, 0.0, 0.0 >, < 0.0, -130.0, 0.0 >, < -130.0, 0.0, 0.0 >, < 0.0, 100.0, 0.0 > ]
+
+ Smokescreen(smokescreen)
+}
+
+void function spawnDrones( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ //TODO
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ array<vector> offsets = [ < 0, 32, 0 >, < 32, 0, 0 >, < 0, -32, 0 >, < -32, 0, 0 > ]
+
+
+ string squadName = MakeSquadName( TEAM_IMC, UniqueString( "ZiplineTable" ) )
+
+ for ( int i = 0; i < spawnEvent.spawnAmount; i++ )
+ {
+ entity guy
+
+ guy = CreateGenericDrone( TEAM_IMC, spawnEvent.origin + offsets[i], spawnEvent.angles )
+ SetSpawnOption_AISettings( guy, "npc_drone_plasma_fd" )
+
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[ spawnEvent.entityGlobalKey + i.tostring() ] <- guy
+ SetTeam( guy, TEAM_IMC )
+ guy.DisableNPCFlag( NPC_ALLOW_INVESTIGATE )
+ guy.EnableNPCFlag( NPC_STAY_CLOSE_TO_SQUAD )
+ guy.EnableNPCMoveFlag( NPCMF_WALK_ALWAYS | NPCMF_PREFER_SPRINT )
+ DispatchSpawn( guy )
+
+ //guy.GiveWeapon("mp_weapon_engineer_combat_drone")
+
+ SetSquad( guy, squadName )
+
+ SetTargetName( guy, GetTargetNameForID( eFD_AITypeIDs.DRONE ) )
+ AddMinimapForHumans( guy )
+ spawnedNPCs.append( guy )
+ thread droneNav_thread(guy, spawnEvent.route, 0, 500, spawnEvent.shouldLoop )
+ }
+
+
+}
+
+void function waitForDeathOfEntitys( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ while( IsHarvesterAlive( fd_harvester.harvester ) )
+ {
+ bool anyoneAlive = false
+ foreach( string key in flowControlEvent.waitGlobalDataKey )
+ {
+ if( !( key in GlobalEventEntitys ) )
+ continue
+ if( IsAlive( GlobalEventEntitys[key] ) )
+ anyoneAlive = true
+ }
+ if( !anyoneAlive )
+ break
+ }
+}
+
+void function waitForLessThanAliveTyped( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ while( IsHarvesterAlive( fd_harvester.harvester ) )
+ {
+ int amount
+ foreach( entity npc in spawnedNPCs )
+ {
+ if( FD_GetAITypeID_ByString( npc.GetTargetName() ) ) //TODO getaitypeid_bystring does not contain all possible strings
+ amount++
+ }
+ if( amount <= flowControlEvent.waitAmount )
+ break
+ WaitFrame()
+ }
+
+}
+
+void function spawnArcTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateArcTitan( TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ npc.DisableNPCFlag( NPC_ALLOW_INVESTIGATE | NPC_USE_SHOOTING_COVER | NPC_ALLOW_PATROL )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ SetSpawnOption_AISettings( npc, "npc_titan_stryder_leadwall_arc" )
+ spawnedNPCs.append( npc )
+ DispatchSpawn( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ npc.AssaultSetFightRadius( 0 )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ thread singleNav_thread( npc, spawnEvent.route )
+ thread EMPTitanThinkConstant( npc )
+
+}
+
+void function waitForTime( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ float waitUntil = Time() + flowControlEvent.waitTime
+ while( Time() < waitUntil )
+ {
+ if( !IsHarvesterAlive( fd_harvester.harvester ) )
+ return
+ WaitFrame()
+ }
+}
+
+void function waitUntilLessThanAmountAliveEvent( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ waitUntilLessThanAmountAlive( flowControlEvent.waitAmount )
+}
+void function waitUntilLessThanAmountAliveEventWeighted( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ waitUntilLessThanAmountAliveWeighted( flowControlEvent.waitAmount )
+}
+
+void function spawnSuperSpectre( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ wait 4.7
+
+ entity npc = CreateSuperSpectre( TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ SetSpawnOption_AISettings( npc, "npc_super_spectre_fd" )
+ spawnedNPCs.append( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ DispatchSpawn( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) )
+ AddMinimapForHumans( npc )
+ thread SuperSpectre_WarpFall( npc )
+ npc.WaitSignal( "WarpfallComplete" )
+ thread singleNav_thread( npc, spawnEvent.route )
+}
+
+void function spawnSuperSpectreWithMinion( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ wait 4.7
+
+ entity npc = CreateSuperSpectre( TEAM_IMC, spawnEvent.origin,spawnEvent.angles )
+ SetSpawnOption_AISettings( npc, "npc_super_spectre_fd" )
+ spawnedNPCs.append( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ DispatchSpawn( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) )
+ AddMinimapForHumans( npc )
+ thread SuperSpectre_WarpFall( npc )
+ npc.WaitSignal( "WarpfallComplete" )
+ thread ReaperMinionLauncherThink( npc )
+
+}
+
+void function spawnDroppodGrunts( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity pod = CreateDropPod( spawnEvent.origin, < 0, 0, 0 > )
+ SetTeam( pod, TEAM_IMC )
+ InitFireteamDropPod( pod )
+ waitthread LaunchAnimDropPod( pod, "pod_testpath", spawnEvent.origin, < 0, 0, 0 > )
+
+ string squadName = MakeSquadName( TEAM_IMC, UniqueString( "ZiplineTable" ) )
+ array<entity> guys
+
+ for ( int i = 0; i < spawnEvent.spawnAmount; i++ )
+ {
+ entity guy = CreateSoldier( TEAM_IMC, spawnEvent.origin, < 0, 0, 0 > )
+
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[ spawnEvent.entityGlobalKey+ i.tostring() ] <- guy
+ SetTeam( guy, TEAM_IMC )
+ guy.EnableNPCFlag( NPC_ALLOW_INVESTIGATE | NPC_ALLOW_HAND_SIGNALS | NPC_ALLOW_FLEE )
+ guy.DisableNPCFlag( NPC_ALLOW_PATROL )
+ DispatchSpawn( guy )
+
+ // should this grunt be a shield captain?
+ if (i < GetCurrentPlaylistVarInt( "fd_grunt_shield_captains", 0 ) )
+ thread ActivatePersonalShield( guy )
+
+ guy.SetParent( pod, "ATTACH", true )
+ SetSquad( guy, squadName )
+
+ // should this grunt have an anti titan weapon instead of its normal weapon?
+ if ( i < GetCurrentPlaylistVarInt( "fd_grunt_at_weapon_users", 0 ) )
+ {
+ guy.GiveWeapon( "mp_weapon_defender" ) // do grunts ever get a different anti titan weapon? - yes, TODO
+ // atm they arent using their AT weapons ever, but they do in fact get them, in fact some grunts are getting 2 since they already get a rocket_launcher
+ // this seems to be a problem elsewhere as opposed to something that is wrong here
+ }
+
+ SetTargetName( guy, GetTargetNameForID( eFD_AITypeIDs.GRUNT ) ) // do shield captains get their own target name in vanilla?
+ AddMinimapForHumans( guy )
+ spawnedNPCs.append( guy )
+ guys.append( guy )
+ }
+
+ ActivateFireteamDropPod( pod, guys )
+ thread SquadNav_Thread( guys,spawnEvent.route )
+}
+
+void function spawnDroppodStalker( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity pod = CreateDropPod( spawnEvent.origin, < 0, 0, 0 > )
+ SetTeam( pod, TEAM_IMC )
+ InitFireteamDropPod( pod )
+ waitthread LaunchAnimDropPod( pod, "pod_testpath", spawnEvent.origin, < 0, 0, 0 > )
+
+ string squadName = MakeSquadName( TEAM_IMC, UniqueString( "ZiplineTable" ) )
+ array<entity> guys
+ int difficultyLevel = FD_GetDifficultyLevel()
+
+ for ( int i = 0; i < spawnEvent.spawnAmount; i++ )
+ {
+ entity guy = CreateStalker( TEAM_IMC, spawnEvent.origin, < 0, 0, 0 > )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[ spawnEvent.entityGlobalKey + i.tostring() ] <- guy
+ SetTeam( guy, TEAM_IMC )
+ guy.EnableNPCFlag( NPC_ALLOW_INVESTIGATE | NPC_ALLOW_HAND_SIGNALS | NPC_ALLOW_FLEE )
+ guy.DisableNPCFlag( NPC_ALLOW_PATROL)
+ SetSpawnOption_AISettings( guy, "npc_stalker_fd" )
+ DispatchSpawn( guy )
+
+ SetSquad( guy, squadName )
+ guy.AssaultSetFightRadius( 0 ) // makes them keep moving instead of stopping to shoot you.
+ AddMinimapForHumans( guy )
+ spawnedNPCs.append( guy )
+ SetTargetName( guy, GetTargetNameForID( eFD_AITypeIDs.STALKER ) )
+ thread FDStalkerThink( guy , fd_harvester.harvester )
+ guys.append( guy )
+ }
+
+ switch ( difficultyLevel )
+ {
+ case eFDDifficultyLevel.EASY:
+ case eFDDifficultyLevel.NORMAL: // easy and normal stalkers have no weapons
+ foreach( npc in guys )
+ {
+ npc.TakeActiveWeapon()
+ npc.SetNoTarget( false )
+ npc.EnableNPCFlag( NPC_DISABLE_SENSING | NPC_IGNORE_ALL )
+ npc.SetEnemy( fd_harvester.harvester )
+ }
+ break
+ case eFDDifficultyLevel.HARD:
+ case eFDDifficultyLevel.MASTER:
+ case eFDDifficultyLevel.INSANE: // give all EPGs
+ foreach( npc in guys )
+ {
+ npc.TakeActiveWeapon()
+ npc.GiveWeapon( "mp_weapon_epg", [] )
+ npc.SetActiveWeaponByName( "mp_weapon_epg" )
+ }
+ break
+
+ default:
+ unreachable
+
+ }
+
+ ActivateFireteamDropPod( pod, guys )
+ SquadNav_Thread( guys, spawnEvent.route )
+
+}
+
+void function spawnDroppodSpectreMortar( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity pod = CreateDropPod( spawnEvent.origin, < 0, 0, 0 > )
+ SetTeam( pod, TEAM_IMC )
+ InitFireteamDropPod( pod )
+ waitthread LaunchAnimDropPod( pod, "pod_testpath", spawnEvent.origin, < 0, 0, 0 > )
+
+ string squadName = MakeSquadName( TEAM_IMC, UniqueString( "ZiplineTable" ) )
+ array<entity> guys
+
+ for ( int i = 0; i < 4; i++ )
+ {
+ entity guy = CreateSpectre( TEAM_IMC, spawnEvent.origin,< 0, 0, 0 > )
+ SetSpawnOption_AISettings( guy, "npc_spectre_mortar" )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[ spawnEvent.entityGlobalKey + i.tostring() ] <- guy
+ SetTeam( guy, TEAM_IMC )
+ DispatchSpawn( guy )
+ spawnedNPCs.append(guy)
+ SetSquad( guy, squadName )
+ SetTargetName( guy, GetTargetNameForID(eFD_AITypeIDs.SPECTRE_MORTAR))
+ AddMinimapForHumans(guy)
+ guys.append( guy )
+ }
+
+ ActivateFireteamDropPod( pod, guys )
+
+ thread MortarSpectreSquadThink( guys, fd_harvester.harvester )
+
+}
+
+void function spawnGenericNPC( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPC( spawnEvent.npcClassName, TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ DispatchSpawn( npc )
+}
+
+void function spawnGenericNPCTitanwithSettings( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( spawnEvent.npcClassName, TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ if( spawnEvent.aiSettings == "npc_titan_atlas_tracker_fd_sniper" )
+ SetTargetName( npc, "npc_titan_atlas_tracker" ) // required for client to create icons
+ SetSpawnOption_AISettings( npc, spawnEvent.aiSettings )
+ SetSpawnOption_Titanfall( npc )
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+}
+
+
+void function SpawnIonTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_atlas", TEAM_IMC, spawnEvent.origin, spawnEvent.angles)
+ SetSpawnOption_AISettings( npc, "npc_titan_atlas_stickybomb_boss_fd" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread singleNav_thread( npc, spawnEvent.route )
+}
+
+void function SpawnScorchTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_ogre", TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ SetSpawnOption_AISettings( npc, "npc_titan_ogre_meteor_boss_fd" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread singleNav_thread( npc, spawnEvent.route )
+}
+
+void function SpawnRoninTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_stryder", TEAM_IMC, spawnEvent.origin, spawnEvent.angles)
+ SetSpawnOption_AISettings (npc, "npc_titan_stryder_leadwall_boss_fd" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread singleNav_thread( npc, spawnEvent.route )
+}
+
+void function SpawnToneTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_atlas", TEAM_IMC, spawnEvent.origin, spawnEvent.angles)
+ SetSpawnOption_AISettings( npc, "npc_titan_atlas_tracker_boss_fd" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread singleNav_thread( npc, spawnEvent.route )
+}
+
+void function SpawnLegionTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_ogre", TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ SetSpawnOption_AISettings( npc, "npc_titan_ogre_minigun_boss_fd" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread singleNav_thread( npc, spawnEvent.route )
+}
+
+void function SpawnMonarchTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_atlas", TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ SetSpawnOption_AISettings( npc,"npc_titan_atlas_vanguard_boss_fd" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread singleNav_thread( npc, spawnEvent.route )
+}
+
+void function spawnNukeTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_ogre", TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ SetSpawnOption_AISettings( npc, "npc_titan_ogre_minigun_nuke" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ npc.EnableNPCMoveFlag( NPCMF_WALK_ALWAYS )
+ npc.AssaultSetFightRadius( 0 )
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread singleNav_thread( npc, spawnEvent.route )
+ thread NukeTitanThink( npc, fd_harvester.harvester )
+
+}
+
+void function spawnMortarTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_atlas", TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ SetSpawnOption_AISettings( npc, "npc_titan_atlas_tracker_mortar" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread MortarTitanThink( npc, fd_harvester.harvester )
+}
+
+void function spawnSniperTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_stryder", TEAM_IMC, spawnEvent.origin, spawnEvent.angles)
+ SetSpawnOption_AISettings( npc, "npc_titan_stryder_sniper_fd" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread SniperTitanThink( npc, fd_harvester.harvester )
+
+}
+
+void function SpawnToneSniperTitan( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity npc = CreateNPCTitan( "titan_atlas", TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ SetSpawnOption_AISettings( npc, "npc_titan_atlas_tracker_fd_sniper" )
+ SetSpawnOption_Titanfall( npc )
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) ) // required for client to create icons
+ DispatchSpawn( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ npc.AssaultSetFightRadius( 0 )
+ spawnedNPCs.append( npc )
+ AddMinimapForTitans( npc )
+ npc.WaitSignal( "TitanHotDropComplete" )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread SniperTitanThink( npc, fd_harvester.harvester )
+}
+
+void function fd_spawnCloakDrone( SmokeEvent smokeEvent, SpawnEvent spawnEvent,FlowControlEvent flowControlEvent,SoundEvent soundEvent )
+{
+ entity npc = SpawnCloakDrone( TEAM_IMC, spawnEvent.origin, spawnEvent.angles, fd_harvester.harvester.GetOrigin() )
+ spawnedNPCs.append( npc )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[spawnEvent.entityGlobalKey] <- npc
+ SetTargetName( npc, GetTargetNameForID( spawnEvent.spawnType ) )
+ AddMinimapForHumans( npc )
+}
+
+void function SpawnTick( SmokeEvent smokeEvent, SpawnEvent spawnEvent, FlowControlEvent flowControlEvent, SoundEvent soundEvent )
+{
+ PingMinimap( spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0 )
+ entity pod = CreateDropPod( spawnEvent.origin, < 0, 0, 0 > )
+ SetTeam( pod, TEAM_IMC )
+ InitFireteamDropPod( pod )
+ waitthread LaunchAnimDropPod( pod, "pod_testpath", spawnEvent.origin, < 0, 0, 0 > )
+
+ string squadName = MakeSquadName( TEAM_IMC, UniqueString( "ZiplineTable" ) )
+ array<entity> guys
+
+ for ( int i = 0; i < spawnEvent.spawnAmount; i++ )
+ {
+ entity guy = CreateFragDrone( TEAM_IMC, spawnEvent.origin, < 0, 0, 0 > )
+ if( spawnEvent.entityGlobalKey != "" )
+ GlobalEventEntitys[ spawnEvent.entityGlobalKey + i.tostring() ] <- guy
+ SetSpawnOption_AISettings( guy, "npc_frag_drone_fd" )
+ SetTeam( guy, TEAM_IMC )
+ guy.EnableNPCFlag( NPC_ALLOW_INVESTIGATE )
+ DispatchSpawn( guy )
+ AddMinimapForHumans( guy )
+ SetTargetName( guy, GetTargetNameForID( eFD_AITypeIDs.TICK ) )
+ SetSquad( guy, squadName )
+ spawnedNPCs.append( guy )
+ guy.AssaultSetFightRadius( expect int( guy.Dev_GetAISettingByKeyField( "LookDistDefault_Combat" ) ) ) // make the ticks target players very aggressively
+ guys.append( guy )
+ }
+
+ ActivateFireteamDropPod( pod, guys )
+ thread SquadNav_Thread( guys, spawnEvent.route )
+}
+
+
+
+/****************************************************************************************\
+####### # # ####### # # ####### # # ####### # ###### ####### ######
+# # # # ## # # # # # # # # # # #
+# # # # # # # # # # # # # # # # #
+##### # # ##### # # # # ####### ##### # ###### ##### ######
+# # # # # # # # # # # # # # # #
+# # # # # ## # # # # # # # # #
+####### # ####### # # # # # ####### ####### # ####### # #
+\****************************************************************************************/
+
+
+void function PingMinimap( float x, float y, float duration, float spreadRadius, float ringRadius, int colorIndex )
+{
+ foreach( entity player in GetPlayerArray() )
+ {
+ Remote_CallFunction_NonReplay( player, "ServerCallback_FD_PingMinimap", x, y, duration, spreadRadius, ringRadius, colorIndex )
+ }
+}
+
+void function waitUntilLessThanAmountAlive( int amount )
+{
+ int deduct = 0
+ foreach ( entity npc in spawnedNPCs )
+ {
+ if( !IsValid(npc) )
+ {
+ deduct++
+ continue
+ }
+ if( IsValid( GetPetTitanOwner( npc ) ) )
+ {
+ deduct++
+ continue
+ }
+ if( npc.GetTeam() == TEAM_MILITIA )
+ {
+ deduct++
+ continue
+ }
+ }
+ int aliveNPCs = spawnedNPCs.len() - deduct
+ while( aliveNPCs > amount )
+ {
+ WaitFrame()
+ deduct = 0
+ foreach ( entity npc in spawnedNPCs )
+ {
+ if( !IsValid( npc ) )
+ {
+ deduct++
+ continue
+ }
+ if( IsValid( GetPetTitanOwner( npc ) ) )
+ {
+ deduct++
+ continue
+ }
+ if( npc.GetTeam() == TEAM_MILITIA )
+ {
+ deduct++
+ continue
+ }
+ }
+ aliveNPCs = spawnedNPCs.len() - deduct
+
+ if( !IsHarvesterAlive( fd_harvester.harvester ) )
+ return
+ }
+}
+
+void function waitUntilLessThanAmountAliveWeighted( int amount, int humanWeight = 1, int reaperWeight = 3, int titanWeight = 5 )
+{
+
+ int aliveNPCsWeighted = 0;
+ foreach( npc in spawnedNPCs )
+ {
+ if( !IsValid( npc ) )
+ continue
+
+ if( IsValid( GetPetTitanOwner( npc ) ) )
+ continue
+
+ if( npc.GetTeam() == TEAM_MILITIA )
+ continue
+
+ if( npc.IsTitan() )
+ aliveNPCsWeighted += titanWeight
+ else if( npc.GetTargetName() == "reaper" )
+ aliveNPCsWeighted += reaperWeight
+ else
+ aliveNPCsWeighted += humanWeight
+ }
+ while( aliveNPCsWeighted > amount )
+ {
+ WaitFrame()
+ aliveNPCsWeighted = 0;
+ foreach( npc in spawnedNPCs )
+ {
+ if( !IsValid( npc ) )
+ continue
+
+ if( IsValid( GetPetTitanOwner( npc ) ) )
+ continue
+
+ if( npc.GetTeam() == TEAM_MILITIA )
+ continue
+
+ if( npc.IsTitan() )
+ aliveNPCsWeighted += titanWeight
+ else if( npc.GetTargetName() == "reaper" )
+ aliveNPCsWeighted += reaperWeight
+ else
+ aliveNPCsWeighted += humanWeight
+ }
+ if( !IsHarvesterAlive( fd_harvester.harvester ) )
+ return
+ }
+}
+
+void function waitUntilLessThanAmountAlive_expensive( int amount )
+{
+
+ array<entity> npcs = GetNPCArray()
+ int deduct = 0
+ foreach ( entity npc in npcs )
+ {
+ if( IsValid( GetPetTitanOwner( npc ) ) )
+ {
+ deduct++
+ continue
+ }
+ if( npc.GetTeam() == TEAM_MILITIA )
+ {
+ deduct++
+ continue
+ }
+ }
+ foreach( entity ent in GetEntArrayByClass_Expensive( "npc_drone" ) )
+ ent.Die()
+ int aliveTitans = npcs.len() - deduct
+ while( aliveTitans > amount )
+ {
+ WaitFrame()
+ npcs = GetNPCArray()
+ deduct = 0
+ foreach( entity npc in npcs )
+ {
+ if( IsValid( GetPetTitanOwner( npc ) ) )
+ {
+ deduct++
+ continue
+ }
+ if( npc.GetTeam() == TEAM_MILITIA )
+ {
+ deduct++
+ continue
+ }
+ }
+ aliveTitans = GetNPCArray().len() - deduct
+ if( !IsHarvesterAlive( fd_harvester.harvester ) )
+ return
+ }
+}
+
+void function AddMinimapForTitans( entity titan )
+{
+ titan.Minimap_SetAlignUpright( true )
+ titan.Minimap_AlwaysShow( TEAM_IMC, null )
+ titan.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ titan.Minimap_SetHeightTracking( true )
+ titan.Minimap_SetCustomState( eMinimapObject_npc_titan.AT_BOUNTY_BOSS )
+}
+
+// including drones
+void function AddMinimapForHumans( entity human )
+{
+ human.Minimap_SetAlignUpright( true )
+ human.Minimap_AlwaysShow( TEAM_IMC, null )
+ human.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ human.Minimap_SetHeightTracking( true )
+ human.Minimap_SetCustomState( eMinimapObject_npc.AI_TDM_AI )
+}
+
+
+
+void function WinWave()
+{
+ foreach( WaveEvent e in waveEvents[GetGlobalNetInt( "FD_currentWave" )] )
+ {
+ e.timesExecuted = e.executeOnThisCall
+ }
+}
+
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd_nav.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd_nav.nut
new file mode 100644
index 00000000..1948ac6b
--- /dev/null
+++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd_nav.nut
@@ -0,0 +1,271 @@
+global function singleNav_thread
+global function SquadNav_Thread
+global function droneNav_thread
+global function getRoute
+global function Dev_MarkRoute
+
+
+
+void function singleNav_thread( entity npc, string routeName, int nodesToSkip= 0, float nextDistance = -1.0, bool shouldLoop = false )
+{
+ npc.EndSignal( "OnDeath" )
+ npc.EndSignal( "OnDestroy" )
+
+
+
+ if( !npc.IsNPC() )
+ return
+ if ( nextDistance == -1 )
+ nextDistance = npc.GetMinGoalRadius()
+
+
+ /*array<entity> routeArray = getRoute(routeName)
+ WaitFrame()//so other code setting up what happens on signals is run before this
+ if(routeArray.len()==0)
+ {
+
+ npc.Signal("OnFailedToPath")
+ return
+ }
+ int skippedNodes = 0
+ foreach(entity node in routeArray)
+ {
+ if(!IsHarvesterAlive(fd_harvester.harvester))
+ return
+ if(skippedNodes < nodesToSkip)
+ {
+ skippedNodes++
+ continue
+ }
+ npc.AssaultPoint(node.GetOrigin())
+ npc.AssaultSetGoalRadius( 50 )
+ int i = 0
+ table result = npc.WaitSignal("OnFinishedAssault","OnFailedToPath")
+ if(result.signal == "OnFailedToPath")
+ break
+ }*/
+
+ // NEW STUFF
+ WaitFrame() // so other code setting up what happens on signals is run before this
+
+ entity targetNode
+ if ( routeName == "" )
+ {
+ float dist = 1000000000
+ foreach ( entity node in routeNodes )
+ {
+ if( !node.HasKey( "route_name" ) )
+ continue
+ if ( Distance( npc.GetOrigin(), node.GetOrigin() ) < dist )
+ {
+ dist = Distance( npc.GetOrigin(), node.GetOrigin() )
+ targetNode = node
+ }
+ }
+ printt("Entity had no route defined: using nearest node: " + targetNode.kv.route_name)
+ }
+ else
+ {
+ targetNode = GetRouteStart( routeName )
+ }
+
+ // skip nodes
+ for ( int i = 0; i < nodesToSkip; i++ )
+ {
+ targetNode = targetNode.GetLinkEnt()
+ }
+
+
+ while ( targetNode != null )
+ {
+ if( !IsHarvesterAlive( fd_harvester.harvester ) )
+ return
+ npc.AssaultPoint( targetNode.GetOrigin() )
+ npc.AssaultSetGoalRadius( nextDistance )
+ npc.AssaultSetFightRadius( 0 )
+
+ table result = npc.WaitSignal( "OnFinishedAssault", "OnEnterGoalRadius", "OnFailedToPath" )
+
+ targetNode = targetNode.GetLinkEnt()
+ }
+
+ npc.Signal( "FD_ReachedHarvester" )
+}
+
+void function SquadNav_Thread( array<entity> npcs, string routeName, int nodesToSkip = 0, float nextDistance = 200.0 )
+{
+ //TODO this function wont stop when noone alive anymore also it only works half of the time
+ /*
+ array<entity> routeArray = getRoute(routeName)
+ WaitFrame()//so other code setting up what happens on signals is run before this
+ if(routeArray.len()==0)
+ return
+
+ int nodeIndex = 0
+ foreach(entity node in routeArray)
+ {
+ if(!IsHarvesterAlive(fd_harvester.harvester))
+ return
+ if(nodeIndex++ < nodesToSkip)
+ continue
+
+ SquadAssaultOrigin(npcs,node.GetOrigin(),nextDistance)
+
+ }*/
+ // NEW STUFF
+ WaitFrame() // so other code setting up what happens on signals is run before this
+
+ entity targetNode
+ if ( routeName == "" )
+ {
+ float dist = 1000000000
+ foreach ( entity node in routeNodes )
+ {
+ if( !node.HasKey( "route_name" ) )
+ continue
+ if ( Distance( npcs[0].GetOrigin(), node.GetOrigin() ) < dist )
+ {
+ dist = Distance( npcs[0].GetOrigin(), node.GetOrigin() )
+ targetNode = node
+ }
+ }
+ printt("Entity had no route defined: using nearest node: " + targetNode.kv.route_name)
+ }
+ else
+ {
+ targetNode = GetRouteStart( routeName )
+ }
+
+ // skip nodes
+ for ( int i = 0; i < nodesToSkip; i++ )
+ {
+ targetNode = targetNode.GetLinkEnt()
+ }
+
+ while ( targetNode != null )
+ {
+ if( !IsHarvesterAlive( fd_harvester.harvester ) )
+ return
+
+ SquadAssaultOrigin( npcs, targetNode.GetOrigin(), nextDistance )
+
+ targetNode = targetNode.GetLinkEnt()
+ }
+
+}
+
+void function droneNav_thread( entity npc, string routeName,int nodesToSkip= 0,float nextDistance = 500.0, bool shouldLoop = false )
+{
+ npc.EndSignal( "OnDeath" )
+ npc.EndSignal( "OnDestroy" )
+
+ if( !npc.IsNPC() )
+ return
+
+
+ // NEW STUFF
+ WaitFrame() // so other code setting up what happens on signals is run before this
+
+ entity targetNode
+ entity firstNode
+ if ( routeName == "" )
+ {
+ float dist = 1000000000
+ foreach ( entity node in routeNodes )
+ {
+ if( !node.HasKey( "route_name" ) )
+ continue
+ if ( Distance( npc.GetOrigin(), node.GetOrigin() ) < dist )
+ {
+ dist = Distance( npc.GetOrigin(), node.GetOrigin() )
+ targetNode = node
+ firstNode = node
+ }
+ }
+ printt( "Entity had no route defined: using nearest node: " + targetNode.kv.route_name )
+ }
+ else
+ {
+ targetNode = GetRouteStart( routeName )
+ }
+
+ // skip nodes
+ for ( int i = 0; i < nodesToSkip; i++ )
+ {
+ targetNode = targetNode.GetLinkEnt()
+ firstNode = targetNode.GetLinkEnt()
+ }
+
+
+ while ( targetNode != null )
+ {
+ if( !IsHarvesterAlive( fd_harvester.harvester ) )
+ return
+ npc.AssaultPoint( targetNode.GetOrigin() + <0, 0, 300> )
+ npc.AssaultSetGoalRadius( nextDistance )
+ npc.AssaultSetGoalHeight( 100 )
+ npc.AssaultSetFightRadius( 0 )
+
+ table result = npc.WaitSignal( "OnFinishedAssault", "OnEnterGoalRadius", "OnFailedToPath" )
+
+ targetNode = targetNode.GetLinkEnt()
+ if ( targetNode == null )
+ printt( "drone finished pathing" )
+ if ( targetNode == null && shouldLoop )
+ {
+ printt( "drone reached end of loop, looping" )
+ targetNode = firstNode
+ }
+ }
+
+ npc.Signal( "FD_ReachedHarvester" )
+}
+
+entity function GetRouteStart( string routeName )
+{
+ foreach( entity node in routeNodes )
+ {
+ if( !node.HasKey( "route_name" ) )
+ continue
+ if( expect string( node.kv.route_name ) == routeName )
+ {
+ return node
+ }
+ }
+}
+
+array<entity> function getRoute( string routeName )
+{
+ array<entity> ret
+ array<entity> currentNode = []
+ foreach(entity node in routeNodes)
+ {
+ if( !node.HasKey( "route_name" ) )
+ continue
+ if( node.kv.route_name == routeName )
+ {
+ currentNode = [node]
+ break
+ }
+
+ }
+ if( currentNode.len() == 0 )
+ {
+ printt( "Route not found" )
+ return []
+ }
+ while( currentNode.len() != 0 )
+ {
+ ret.append( currentNode[0] )
+ currentNode = currentNode[0].GetLinkEntArray()
+ }
+ return ret
+}
+
+void function Dev_MarkRoute( string routename )
+{
+ foreach( entity e in getRoute( routename ) )
+ {
+ DebugDrawSphere( e.GetOrigin(), 30.0, 255, 0, 255, false, 40 )
+ }
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/item_inventory/sv_item_inventory.gnut b/Northstar.CustomServers/mod/scripts/vscripts/item_inventory/sv_item_inventory.gnut
index 9057f7d8..60bad8d1 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/item_inventory/sv_item_inventory.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/item_inventory/sv_item_inventory.gnut
@@ -112,6 +112,10 @@ void function PlayerInventory_GiveInventoryItem( entity player, InventoryItem in
player.TakeWeaponNow( preexistingWeapon.GetWeaponClassName() )
player.GiveOffhandWeapon( inventoryItem.weaponRef, OFFHAND_INVENTORY, mods )
+ if ( inventoryItem.itemType == eInventoryItemType.burnmeter ) {
+ entity weapon = player.GetOffhandWeapon(OFFHAND_INVENTORY)
+ weapon.e.burnReward = inventoryItem.burnReward.ref
+ }
}
void function PlayerInventory_PushInventoryItem( entity player, InventoryItem inventoryItem )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut
index 1102aae1..ce9227a2 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut
@@ -12,13 +12,13 @@ void function MpInitAILoadouts()
void function SetProficiency( entity npc )
{
- // unsure what the logic for deciding this should be so just going to default good
- npc.kv.WeaponProficiency = eWeaponProficiency.VERYGOOD
+ // i think this is correct? iirc grunts and stuff in attrition are *really* bad so having poor as their proficiency makes sense
+ npc.kv.WeaponProficiency = GetDifficultyLevel()
}
void function SPMP_UpdateNPCProficiency( entity npc )
{
-
+ SetProficiency( npc ) // this seems bad? dont see why they should be any different unless SP should use a different function
}
bool function IsAutoPopulateEnabled( var team = null )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut
index 8b2a4060..1781a21f 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut
@@ -25,6 +25,12 @@ void function CodeCallback_MapInit()
// there are some really busted titan startspawns that are on the fucking other side of the map from where they should be, so we remove them
AddSpawnCallback( "info_spawnpoint_titan_start", TrimBadTitanStartSpawns )
AddSpawnCallback( "sky_camera", FixSkycamFog )
+
+
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+
}
void function FixBatterySpawns( entity spawn )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal.nut
index 2e35417f..46525cea 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal.nut
@@ -4,6 +4,11 @@ void function CodeCallback_MapInit()
{
// there are some really busted titan startspawns that are on the fucking other side of the map from where they should be, so we remove them
AddSpawnCallback( "info_spawnpoint_titan_start", TrimBadTitanStartSpawns )
+
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+
}
void function TrimBadTitanStartSpawns( entity spawn )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_black_water_canal_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02.nut
index 0079d7e9..f0c17dcf 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02.nut
@@ -3,6 +3,10 @@ global function CodeCallback_MapInit
void function CodeCallback_MapInit()
{
AddCallback_EntitiesDidLoad( CreateEvacNodes )
+
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
}
void function CreateEvacNodes()
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_colony02_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock.nut
index 37b89169..e6eb493d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock.nut
@@ -1 +1,8 @@
-//fuck \ No newline at end of file
+global function CodeCallback_MapInit
+
+void function CodeCallback_MapInit()
+{
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_drydock_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai.nut
index 345a86d9..99965a1b 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai.nut
@@ -1,5 +1,6 @@
global function CodeCallback_MapInit
+
struct {
int batteryIndex = 0
} file
@@ -14,6 +15,10 @@ void function CodeCallback_MapInit()
{
// Battery spawns (in LTS/Free Agents) are in old locations, so we move them to the proper locations
AddSpawnCallbackEditorClass( "script_ref", "script_power_up_other", FixBatterySpawns )
+
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
}
void function FixBatterySpawns( entity spawn )
@@ -24,4 +29,4 @@ void function FixBatterySpawns( entity spawn )
PowerUp powerupDef = GetPowerUpFromItemRef( expect string( spawn.kv.powerUpType ) )
if ( powerupDef.spawnFunc() )
spawn.SetOrigin( BATTERY_SPAWNS[file.batteryIndex++] )
-} \ No newline at end of file
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai_fd.nut
index 37b89169..65278f6d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai_fd.nut
@@ -1 +1,631 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+
+
+void function initFrontierDefenseData()
+{
+ shopPosition = < -3862.13, 1267.69, 1060.06 >
+ FD_spawnPosition = < -838.6, 2629.63, 1592 >
+ FD_spawnAngles = < 0, 180, 0 >
+
+ int index = 1
+
+ array< WaveEvent > wave1
+ wave1.append( CreateSmokeEvent( < -12, 1720, 1540 >, 90, index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.2, index++ ) )
+ wave1.append( CreateSmokeEvent( < -64, 964, 1540 >, 90, index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.4, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 864.625000, 693.750000, 1379.910034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.9332962, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 884.625000, 1721.750000, 1377.410034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.1667023, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1226.410034, 1391.130005, 1334.689941 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.0499954, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1258.060059, 921.593994, 1330.750000 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.0, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1116.630005, 329.750000, 1372.280029 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave1.append( CreateWaitUntilAliveWeightedEvent( 8, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 864.625000, 693.750000, 1379.910034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.1669998, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 884.625000, 1721.750000, 1377.410034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.6159973, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1226.410034, 1391.130005, 1334.689941 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.8840027, index++ ) )
+ wave1.append( CreateDroppodStalkerEvent( < 1258.060059, 921.593994, 1330.750000 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.5999985, index++ ) )
+ wave1.append( CreateDroppodStalkerEvent( < 1116.630005, 329.750000, 1372.280029 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave1.append( CreateWaitUntilAliveWeightedEvent( 8, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 864.625000, 693.750000, 1379.910034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.3829956, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 884.625000, 1721.750000, 1377.410034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.6340027, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1226.410034, 1391.130005, 1334.689941 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.3829956, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1258.060059, 921.593994, 1330.750000 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.5, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1116.630005, 329.750000, 1372.280029 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave1.append( CreateWaitUntilAliveWeightedEvent( 8, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 864.625000, 693.750000, 1379.910034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.5, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 884.625000, 1721.750000, 1377.410034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.9840088, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1226.410034, 1391.130005, 1334.689941 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.5, index++ ) )
+ wave1.append( CreateDroppodStalkerEvent( < 1258.060059, 921.593994, 1330.750000 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.2829895, index++ ) )
+ wave1.append( CreateDroppodStalkerEvent( < 1116.630005, 329.750000, 1372.280029 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave1.append( CreateWaitUntilAliveWeightedEvent( 8, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 864.625000, 693.750000, 1379.910034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.5, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 884.625000, 1721.750000, 1377.410034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.1829987, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1226.410034, 1391.130005, 1334.689941 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.449997, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1258.060059, 921.593994, 1330.750000 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.66700745, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1116.630005, 329.750000, 1372.280029 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave1.append( CreateWaitUntilAliveWeightedEvent( 8, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 864.625000, 693.750000, 1379.910034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.2169952, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 884.625000, 1721.750000, 1377.410034 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 0.6159973, index++ ) )
+ wave1.append( CreateDroppodGruntEvent( < 1226.410034, 1391.130005, 1334.689941 >, "hillRouteClose", index++ ) )
+ wave1.append( CreateWaitForTimeEvent( 1.4840088, index++ ) )
+ wave1.append( CreateToneSniperTitanEvent( < 1373.469971, 1219.410034, 1314.339966 >, < 0.000000, 169.541000, 0.000000 >, 0 ) )
+ waveEvents.append( wave1 )
+ index = 1
+ array< WaveEvent > wave2
+ wave2.append( CreateDroppodTickEvent( < 864.625000, 693.750000, 1379.910034 >, 4, "hillRouteClose", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.1, index++ ) )
+ wave2.append( CreateSmokeEvent( < -12, 1720, 1540 >, 120, index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.2, index++ ) )
+ wave2.append( CreateSmokeEvent( < -64, 964, 1540 >, 120, index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.7169983, index++ ) )
+ wave2.append( CreateDroppodTickEvent( < 884.625000, 1721.750000, 1377.410034 >, 4, "hillRouteClose", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.6500244, index++ ) )
+ wave2.append( CreateDroppodTickEvent( < 1226.410034, 1391.130005, 1334.689941 >, 4, "hillRouteClose", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.0329895, index++ ) )
+ wave2.append( CreateDroppodTickEvent( < 1258.060059, 921.593994, 1330.750000 >, 4, "hillRouteClose", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 12, index++ ) )
+ wave2.append( CreateToneSniperTitanEvent( < 1373.469971, 1219.410034, 1314.339966 >, < 0.000000, 169.541000, 0.000000 >, index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.0159912, index++ ) )
+ wave2.append( CreateToneSniperTitanEvent( < 1209.469971, 579.406006, 1332.310059 >, < 0.000000, 169.541000, 0.000000 >, index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.8999939, index++ ) )
+ wave2.append( CreateToneTitanEvent( < 2475.810059, -3544.189941, 810.218994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.3000183, index++ ) )
+ wave2.append( CreateToneTitanEvent( < 2665.060059, 4456.129883, 960.687988 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.1499939, index++ ) )
+ wave2.append( CreateDroppodSpectreMortarEvent( < 864.625000, 693.750000, 1379.910034 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateDroppodSpectreMortarEvent( < 884.625000, 1721.750000, 1377.410034 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.6000061, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 1226.410034, 1391.130005, 1334.689941 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.6999817, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 864.625000, 693.750000, 1379.910034 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 2.9160156, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 1258.060059, 921.593994, 1330.750000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 864.625000, 693.750000, 1379.910034 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.8659973, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 884.625000, 1721.750000, 1377.410034 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.6839905, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 1226.410034, 1391.130005, 1334.689941 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.4160156, index++ ) )
+ wave2.append( CreateToneTitanEvent( < 2475.810059, -3544.189941, 810.218994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.6000061, index++ ) )
+ wave2.append( CreateToneTitanEvent( < 2665.060059, 4456.129883, 960.687988 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateWarningEvent( FD_IncomingWarnings.Reaper, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 1856.959961, -3177.639893, 812.718018 >, < -0.000000, -162.389999, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.03302, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 3123.000000, 4201.589844, 950.937988 >, < 0.000000, -117.246002, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 3.6169739, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 681.140991, -3538.780029, 813.127014 >, < 0.000000, -169.145996, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.78302, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2614.629883, 4771.560059, 947.968994 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 3.1829834, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2184.969971, -3550.040039, 819.479980 >, < 0.000000, 177.582993, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 1764.410034, 4424.220215, 953.375000 >, < -0.000000, -170.024002, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateDroppodTickEvent( < 3248.840088, 161.156006, 951.781006 >, 4, "hillRouteClose", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.1499939, index++ ) )
+ wave2.append( CreateDroppodTickEvent( < 3156.560059, 2266.939941, 951.781006 >, 4, "hillRouteClose", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateDroppodTickEvent( < 3248.840088, 161.156006, 951.781006 >, 4, "hillRouteClose", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.1170044, index++ ) )
+ wave2.append( CreateDroppodTickEvent( < 3156.560059, 2266.939941, 951.781006 >, 4, "hillRouteClose", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.8829956, index++ ) )
+ wave2.append( CreateToneTitanEvent( < 4466.220215, 1469.410034, 947.281006 >, < 0.000000, 169.541000, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 3.5169983, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 2336.000000, 1968.000000, 953.531006 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 3248.840088, 161.156006, 951.781006 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 2.6660156, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 3156.560059, 2266.939941, 951.781006 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.1999817, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 2336.000000, 1968.000000, 953.531006 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 4163.069824, 1471.650024, 944.281006 >, < -0.000000, -179.416000, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.5159912, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 4210.669922, 895.575989, 944.281006 >, < -0.000000, -164.787003, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 2.75, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 3577.010010, 1491.959961, 944.281006 >, < -0.000000, 169.908005, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.1340027, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 3982.860107, 1778.540039, 944.281006 >, < -0.000000, 179.488007, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 2457.310059, -2563.659912, 789.250000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.3840027, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 1935.839966, 3727.840088, 931.656006 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2182.939941, -3549.810059, 819.468994 >, < 0.000000, 177.582993, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.1159668, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 1045.339966, -2843.340088, 804.812988 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.5670166, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2357.739990, 4476.339844, 962.960022 >, < -0.000000, 177.669998, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.7000122, index++ ) )
+ wave2.append( CreateDroppodGruntEvent( < 2111.840088, 3295.840088, 939.031006 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateSmokeEvent( < 2684, 1252, 1092 >, 120, index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.2, index++ ) )
+ wave2.append( CreateSmokeEvent( < 2452, 1812, 1092 >, 120, index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.2, index++ ) )
+ wave2.append( CreateSmokeEvent( < 2336, 636, 1092 >, 120, index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.6, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2343.590088, -3185.840088, 788.312988 >, < -0.000000, 174.550995, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.8500366, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2338.270020, 4684.279785, 952.682007 >, < -0.000000, -167.669006, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2177.209961, -3539.600098, 817.719971 >, < 0.000000, 178.065994, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.0, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2401.719971, 4475.089844, 962.406006 >, < 0.000000, 177.626999, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.0, index++ ) )
+ wave2.append( CreateIonTitanEvent( < 1817.380005, -3585.909912, 813.937988 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.032959, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2576.909912, -3007.250000, 796.093994 >, < 0.000000, -165.850006, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.28302002, index++ ) )
+ wave2.append( CreateIonTitanEvent( < 2614.879883, 4771.560059, 951.000000 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.7839966, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2828.399902, 4138.450195, 938.893982 >, < 0.000000, -171.078995, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateLegionTitanEvent( < 4466.689941, 1469.410034, 947.281006 >, < 0.000000, 169.541000, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 4182.189941, 917.906006, 944.281006 >, < 0.000000, -124.805000, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.3170166, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2747.790039, 1574.170044, 944.281006 >, < -0.000000, -164.485001, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave2.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave2.append( CreateScorchTitanEvent( < 2821.659912, -2937.090088, 827.937988 >, < 0.000000, 117.202003, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.0, index++ ) )
+ wave2.append( CreateScorchTitanEvent( < 3123.560059, 4202.060059, 954.343994 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 0.1159668, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2169.590088, -3540.250000, 817.875000 >, < -0.000000, 178.065002, 0.000000 >, "", index++ ) )
+ wave2.append( CreateWaitForTimeEvent( 1.3840332, index++ ) )
+ wave2.append( CreateSuperSpectreEvent( < 2354.810059, 4476.589844, 962.968994 >, < -0.000000, 177.759003, 0.000000 >, "", 0 ) )
+ waveEvents.append( wave2 )
+ index = 1
+ array< WaveEvent > wave3
+ wave3.append( CreateRoninTitanEvent( < 1763.839966, -1608.750000, 810.281006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.1670288, index++ ) )
+ wave3.append( CreateSmokeEvent( < -2264, -2096, 928 >, 120, index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.333, index++ ) )
+ wave3.append( CreateSmokeEvent( < -3132, -1904, 928 >, 120, index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.2, index++ ) )
+ wave3.append( CreateSmokeEvent( < -1548, -2240, 928 >, 120, index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.067, index++ ) )
+ wave3.append( CreateCloakDroneEvent( < 1883.910034, -1569.939941, 1108.000000 >, < 0.000000, 0.000000, 0.000000 >, index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.1499634, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 2457.310059, -2563.659912, 789.250000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.3829956, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 1045.339966, -2843.340088, 804.812988 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 3.4000244, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 346.312988, -2838.659912, 803.968994 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.1170044, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 1418.310059, -2254.659912, 810.031006 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave3.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave3.append( CreateWarningEvent( FD_IncomingWarnings.Reaper, index++ ) )
+ wave3.append( CreateSuperSpectreEvent( < 2170.020020, -3549.570068, 819.468994 >, < -0.000000, 177.626007, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.0669556, index++ ) )
+ wave3.append( CreateSuperSpectreEvent( < 2577.060059, -3007.379883, 796.093994 >, < -0.000000, -165.850006, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.1329956, index++ ) )
+ wave3.append( CreateSuperSpectreEvent( < 1512.939941, -3294.090088, 798.000000 >, < -0.000000, 89.077103, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.4000244, index++ ) )
+ wave3.append( CreateSuperSpectreEvent( < 1531.000000, -1779.880005, 800.031006 >, < 0.000000, 133.110001, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave3.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave3.append( CreateScorchTitanEvent( < 2475.909912, -3544.659912, 810.281006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.6829834, index++ ) )
+ wave3.append( CreateIonTitanEvent( < 2821.340088, -2936.719971, 827.937988 >, < 0.000000, 117.202003, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.7839966, index++ ) )
+ wave3.append( CreateIonTitanEvent( < 1503.810059, -3600.189941, 813.687988 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.0, index++ ) )
+ wave3.append( CreateScorchTitanEvent( < 1559.910034, -2024.660034, 803.031006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave3.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave3.append( CreateSpawnDroneEvent( < 2487.310059, -2561.379883, 5744.229980 >, < 0.004999, 90.003700, 0.000004 >, "", index++, false ) )
+ wave3.append( CreateWaitForTimeEvent( 0.0, index++ ) )
+ wave3.append( CreateSpawnDroneEvent( < 2457.310059, -2591.379883, 5744.189941 >, < 0.004999, 90.003700, 0.000004 >, "", index++, false ) )
+ wave3.append( CreateWaitForTimeEvent( 0.0, index++ ) )
+ wave3.append( CreateSpawnDroneEvent( < 2457.310059, -2531.379883, 5744.319824 >, < 0.004999, 90.003700, 0.000004 >, "", index++, false ) )
+ wave3.append( CreateWaitForTimeEvent( 0.0, index++ ) )
+ wave3.append( CreateSpawnDroneEvent( < 2427.310059, -2561.379883, 5744.549805 >, < 0.004999, 90.003700, 0.000004 >, "", index++, false ) )
+ wave3.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave3.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 2457.310059, -2563.659912, 789.250000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.282959, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 1045.339966, -2843.340088, 804.812988 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 2.6170044, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 346.312988, -2838.659912, 803.968994 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.9660034, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 1418.310059, -2254.659912, 810.031006 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.0999756, index++ ) )
+ wave3.append( CreateToneSniperTitanEvent( < 4466.220215, 1469.410034, 947.281006 >, < 0.000000, 169.541000, 0.000000 >, index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.6170044, index++ ) )
+ wave3.append( CreateMonarchTitanEvent( < 4453.129883, 964.750000, 947.281006 >, < 0.000000, -172.529007, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave3.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave3.append( CreateRoninTitanEvent( < 1763.839966, -1608.750000, 810.281006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.61602783, index++ ) )
+ wave3.append( CreateRoninTitanEvent( < 2359.840088, -1596.750000, 802.718994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.9840088, index++ ) )
+ wave3.append( CreateToneTitanEvent( < 2475.810059, -3544.189941, 810.218994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.0999756, index++ ) )
+ wave3.append( CreateToneTitanEvent( < 2821.340088, -2936.719971, 827.937988 >, < 0.000000, 117.202003, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave3.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave3.append( CreateSuperSpectreEvent( < 2180.080078, -3539.689941, 817.739014 >, < 0.000000, 178.065994, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.6329956, index++ ) )
+ wave3.append( CreateLegionTitanEvent( < 2680.219971, -1724.630005, 809.718994 >, < 0.000000, 169.320999, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.06695557, index++ ) )
+ wave3.append( CreateSuperSpectreEvent( < 2533.800049, -3018.310059, 795.421021 >, < 0.000000, -165.806000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.0170288, index++ ) )
+ wave3.append( CreateLegionTitanEvent( < 1763.910034, -1608.660034, 810.218994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.16601562, index++ ) )
+ wave3.append( CreateSuperSpectreEvent( < 1512.839966, -3298.719971, 797.968994 >, < -0.000000, 89.120796, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.0, index++ ) )
+ wave3.append( CreateSuperSpectreEvent( < 1499.910034, -1748.660034, 801.656006 >, < -0.000000, 132.934998, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 2.2340088, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 2457.310059, -2563.659912, 789.250000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.4829712, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 1045.339966, -2843.340088, 804.812988 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 2.9000244, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 346.312988, -2838.659912, 803.968994 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.5999756, index++ ) )
+ wave3.append( CreateDroppodGruntEvent( < 1418.310059, -2254.659912, 810.031006 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.6829834, index++ ) )
+ wave3.append( CreateScorchTitanEvent( < 1503.910034, -3600.659912, 813.781006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.3170166, index++ ) )
+ wave3.append( CreateScorchTitanEvent( < 2475.909912, -3544.659912, 810.281006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave3.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave3.append( CreateToneTitanEvent( < 1763.810059, -1608.189941, 810.000000 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.9000244, index++ ) )
+ wave3.append( CreateToneTitanEvent( < 2359.810059, -1596.189941, 802.718994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.5839844, index++ ) )
+ wave3.append( CreateWarningEvent( FD_IncomingWarnings.CloakDrone, index++ ) )
+ wave3.append( CreateCloakDroneEvent( < 1923.000000, -1544.000000, 1108.000000 >, < 0.000000, 0.000000, 0.000000 >, index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.3330078, index++ ) )
+ wave3.append( CreateCloakDroneEvent( < 1982.020020, -1598.000000, 1236.040039 >, < 0.000000, 0.000000, 0.000000 >, index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave3.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave3.append( CreateLegionTitanEvent( < 4466.689941, 1469.410034, 947.281006 >, < 0.000000, 169.541000, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 0.7999878, index++ ) )
+ wave3.append( CreateLegionTitanEvent( < 4453.589844, 964.906006, 947.281006 >, < 0.000000, -172.529007, 0.000000 >, "", index++ ) )
+ wave3.append( CreateWaitForTimeEvent( 1.4000244, index++ ) )
+ wave3.append( CreateMonarchTitanEvent( < 3866.659912, 1445.630005, 947.281006 >, < 0.000000, 180.000000, 0.000000 >, "", 0 ) )
+ waveEvents.append( wave3 )
+ index = 1
+ array< WaveEvent > wave4
+ wave4.append( CreateDroppodStalkerEvent( < 1935.839966, 3727.840088, 931.656006 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.6000366, index++ ) )
+ wave4.append( CreateSmokeEvent( < -2596, 3224, 1104 >, 120, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.1, index++ ) )
+ wave4.append( CreateSmokeEvent( < -3252, 3052, 1104 >, 120, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 2111.840088, 3295.840088, 939.031006 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.1, index++ ) )
+ wave4.append( CreateSmokeEvent( < -1728, 3136, 1104 >, 120, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.8, index++ ) )
+ wave4.append( CreateScorchTitanEvent( < 2665.340088, 4456.500000, 960.656006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.8829956, index++ ) )
+ wave4.append( CreateToneTitanEvent( < 3123.250000, 4201.689941, 954.281006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.6000366, index++ ) )
+ wave4.append( CreateToneTitanEvent( < 1324.160034, 4820.189941, 937.531006 >, < 0.000000, -90.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.0, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 3144.659912, 2935.629883, 917.218994 >, < 0.000000, 179.341003, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.2000122, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 3739.129883, 1985.719971, 947.281006 >, < 0.000000, 180.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.5, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 1087.839966, 3863.840088, 931.750000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.3499756, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 908.750000, 3093.629883, 967.500000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.2999878, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 3156.560059, 2266.939941, 951.781006 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave4.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 1935.839966, 3727.840088, 931.656006 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.7000122, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 2111.840088, 3295.840088, 939.031006 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.9830322, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 1087.839966, 3863.840088, 931.750000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 3.5999756, index++ ) )
+ wave4.append( CreateWarningEvent( FD_IncomingWarnings.MortarTitan, index++ ) )
+ wave4.append( CreateMortarTitanEvent( < 2475.810059, -3544.189941, 810.218994 >, < 0.000000, 90.000000, 0.000000 >, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.5830078, index++ ) )
+ wave4.append( CreateMortarTitanEvent( < 2821.340088, -2936.719971, 827.937988 >, < 0.000000, 117.202003, 0.000000 >, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.3499756, index++ ) )
+ wave4.append( CreateScorchTitanEvent( < 2665.340088, 4456.500000, 960.656006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.0670166, index++ ) )
+ wave4.append( CreateScorchTitanEvent( < 3123.560059, 4202.060059, 954.343994 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.21698, index++ ) )
+ wave4.append( CreateIonTitanEvent( < 1324.160034, 4820.189941, 937.531006 >, < 0.000000, -90.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.9160156, index++ ) )
+ wave4.append( CreateIonTitanEvent( < 3144.159912, 2935.530029, 917.187988 >, < 0.000000, 179.341003, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.684021, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 3739.129883, 1985.719971, 947.281006 >, < 0.000000, 180.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.5999756, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < -31.906300, 4688.660156, 1027.660034 >, < 0.000000, -90.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.2659912, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 1293.939941, 1827.410034, 1321.750000 >, < 0.000000, 169.541000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.5339966, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 908.750000, 3093.629883, 967.500000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.3000488, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 3156.560059, 2266.939941, 951.781006 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave4.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave4.append( CreateWarningEvent( FD_IncomingWarnings.Reaper, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 2355.209961, 4472.799805, 963.218994 >, < -0.000000, 175.473007, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.5999756, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 2835.689941, 4139.939941, 939.281006 >, < 0.000000, -171.078995, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.0170288, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 1014.690002, 4844.540039, 941.236023 >, < -0.000000, 173.994995, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.6170044, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 2833.949951, 2953.350098, 910.458008 >, < -0.000000, 178.046997, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.5830078, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 4164.439941, 1471.750000, 944.281006 >, < -0.000000, -179.429001, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.117004395, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 1935.839966, 3727.840088, 931.656006 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.0999756, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 4207.680176, 894.888977, 944.281006 >, < -0.000000, -167.283005, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.21600342, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 2111.840088, 3295.840088, 939.031006 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.9840088, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 3570.689941, 1491.780029, 944.281006 >, < 0.000000, 169.761002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.23297119, index++ ) )
+ wave4.append( CreateDroppodStalkerEvent( < 1087.839966, 3863.840088, 931.750000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.3670044, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 3604.739990, 835.104004, 944.281006 >, < -0.000000, -159.296997, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave4.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave4.append( CreateWarningEvent( FD_IncomingWarnings.ArcTitan, index++ ) )
+ wave4.append( CreateArcTitanEvent( < 2665.469971, 4456.529785, 960.656006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.1, index++ ) )
+ wave4.append( CreateSmokeEvent( < -2596, 3224, 1104 >, 120, index++ ) )
+ wave4.append( CreateSmokeEvent( < -3252, 3052, 1104 >, 120, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.2, index++ ) )
+ wave4.append( CreateSmokeEvent( < -1728, 3136, 1104 >, 120, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.9199829, index++ ) )
+ wave4.append( CreateArcTitanEvent( < 3123.659912, 4202.089844, 954.343994 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.6799927, index++ ) )
+ wave4.append( CreateScorchTitanEvent( < 1324.060059, 4820.660156, 937.562988 >, < 0.000000, -90.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.2200317, index++ ) )
+ wave4.append( CreateScorchTitanEvent( < 3144.659912, 2935.629883, 917.218994 >, < 0.000000, 179.341003, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.90997314, index++ ) )
+ wave4.append( CreateToneTitanEvent( < 3738.659912, 1985.630005, 947.281006 >, < 0.000000, 180.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.5700073, index++ ) )
+ wave4.append( CreateToneTitanEvent( < -31.812500, 4688.189941, 1027.560059 >, < 0.000000, -90.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.4000244, index++ ) )
+ wave4.append( CreateRoninTitanEvent( < 1294.030029, 1827.339966, 1321.719971 >, < 0.000000, 169.541000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.9299927, index++ ) )
+ wave4.append( CreateRoninTitanEvent( < 4278.029785, 1771.339966, 947.281006 >, < 0.000000, 169.541000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.8899536, index++ ) )
+ wave4.append( CreateToneSniperTitanEvent( < 4453.129883, 964.750000, 947.281006 >, < 0.000000, -172.529007, 0.000000 >, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.210083, index++ ) )
+ wave4.append( CreateToneSniperTitanEvent( < 3866.659912, 1445.630005, 947.281006 >, < 0.000000, 180.000000, 0.000000 >, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.0, index++ ) )
+ wave4.append( CreateCloakDroneEvent( < 4432.939941, 1262.939941, 1244.000000 >, < 0.000000, 0.000000, 0.000000 >, index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 4.3898926, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 3878.439941, 933.812988, 944.281006 >, < -0.000000, -79.509102, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.2000732, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 4008.780029, 378.406006, 944.281006 >, < 0.000000, -120.498001, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.92993164, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 2916.810059, 2679.780029, 939.000000 >, < -0.000000, -44.335999, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.5800781, index++ ) )
+ wave4.append( CreateSuperSpectreEvent( < 545.906006, 1309.910034, 1438.750000 >, < 0.000000, -166.860001, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave4.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave4.append( CreateWarningEvent( FD_IncomingWarnings.NukeTitan, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 2665.340088, 4456.500000, 960.656006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.0198975, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 3123.560059, 4202.060059, 954.343994 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.9000244, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 3144.659912, 2935.629883, 917.218994 >, < 0.000000, 179.341003, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 1.5, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 1324.060059, 4820.660156, 937.562988 >, < 0.000000, -90.000000, 0.000000 >, "", index++ ) )
+ wave4.append( CreateWaitForTimeEvent( 0.60998535, index++ ) )
+ wave4.append( CreateNukeTitanEvent( < 3739.129883, 1985.719971, 947.281006 >, < 0.000000, 180.000000, 0.000000 >, "", 0 ) )
+ waveEvents.append( wave4 )
+ index = 1
+ array< WaveEvent > wave5
+ wave5.append( CreateSmokeEvent( < -12, 1720, 1540 >, 120, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.1, index++ ) )
+ wave5.append( CreateSmokeEvent( < -64, 964, 1540 >, 120, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.3, index++ ) )
+ wave5.append( CreateSmokeEvent( < -2264, -2096, 928 >, 120, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.3, index++ ) )
+ wave5.append( CreateSmokeEvent( < -3132, -1904, 928 >, 120, index++ ) )
+ wave5.append( CreateDroppodTickEvent( < 864.625000, 693.750000, 1379.910034 >, 4, "hillRouteClose", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.1, index++ ) )
+ wave5.append( CreateSmokeEvent( < -1548, -2240, 928 >, 120, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.1, index++ ) )
+ wave5.append( CreateSmokeEvent( < -2596, 3224, 1104 >, 120, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.2, index++ ) )
+ wave5.append( CreateSmokeEvent( < -3252, 3052, 1104 >, 120, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.3, index++ ) )
+ wave5.append( CreateSmokeEvent( < -1728, 3136, 1104 >, 120, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.4, index++ ) )
+ wave5.append( CreateDroppodTickEvent( < 884.625000, 1721.750000, 1377.410034 >, 4, "hillRouteClose", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.79992676, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1226.410034, 1391.130005, 1334.689941 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.9400635, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1258.060059, 921.593994, 1330.750000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 1094.089966, 1330.660034, 1354.969971 >, < -0.000000, 157.544006, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.7800293, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 857.406006, 739.843994, 1373.030029 >, < -0.000000, 151.962997, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 2.0700684, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 1048.969971, 1660.810059, 1349.089966 >, < 0.000000, -100.986000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.2099609, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 2724.129883, 2458.629883, 946.155029 >, < -0.000000, -127.245003, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 1092.119995, 1331.380005, 1355.650024 >, < 0.000000, 157.500000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.1699219, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 938.187988, 707.406006, 1362.939941 >, < -0.000000, 153.720993, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 2.710083, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1528.660034, -1443.339966, 816.031006 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.1199951, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1418.310059, -2254.659912, 810.031006 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 2.2999268, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 2475.810059, -3544.189941, 810.218994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.3000488, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 2821.340088, -2936.719971, 827.937988 >, < 0.000000, 117.202003, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.8000488, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 1511.339966, -1445.229980, 825.757996 >, < -0.000000, 141.589996, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.099975586, index++ ) )
+ wave5.append( CreateScorchTitanEvent( < 1559.910034, -2024.660034, 803.031006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.57995605, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 2086.750000, -1459.000000, 810.750000 >, < -0.000000, 143.964996, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.6199951, index++ ) )
+ wave5.append( CreateIonTitanEvent( < 2665.060059, 4456.129883, 960.687988 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.8800049, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 3123.250000, 4201.689941, 954.281006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.3399658, index++ ) )
+ wave5.append( CreateLegionTitanEvent( < 3144.659912, 2935.629883, 917.218994 >, < 0.000000, 179.341003, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 2457.310059, -2563.659912, 789.250000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.92004395, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1045.339966, -2843.340088, 804.812988 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateIonTitanEvent( < 4466.220215, 1469.410034, 947.281006 >, < 0.000000, 169.541000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.9499512, index++ ) )
+ wave5.append( CreateIonTitanEvent( < 4453.129883, 964.750000, 947.281006 >, < 0.000000, -172.529007, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.17004395, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 1548.780029, -1475.209961, 805.556030 >, < -0.000000, 141.876999, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.5, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 2087.750000, -1461.540039, 810.366028 >, < -0.000000, 143.395004, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 3.9799805, index++ ) )
+ wave5.append( CreateScorchTitanEvent( < 2475.909912, -3544.659912, 810.281006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.3399658, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 2821.340088, -2936.719971, 827.937988 >, < 0.000000, 117.202003, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.85998535, index++ ) )
+ wave5.append( CreateIonTitanEvent( < 1817.380005, -3585.909912, 813.937988 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.9400635, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1528.660034, -1443.339966, 816.031006 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.1099854, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1418.310059, -2254.659912, 810.031006 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.9899902, index++ ) )
+ wave5.append( CreateScorchTitanEvent( < 1559.910034, -2024.660034, 803.031006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.8100586, index++ ) )
+ wave5.append( CreateScorchTitanEvent( < 2411.909912, -1108.660034, 803.375000 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.289917, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 1511.310059, -1437.780029, 826.656006 >, < -0.000000, 142.382996, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.710083, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 2129.800049, -1492.459961, 806.202026 >, < 0.000000, 143.744995, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 2665.060059, 4456.129883, 960.687988 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.5600586, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 3123.250000, 4201.689941, 954.281006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.3199463, index++ ) )
+ wave5.append( CreateMonarchTitanEvent( < 1324.160034, 4820.189941, 937.531006 >, < 0.000000, -90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 1511.160034, -1437.079956, 809.958008 >, < -0.000000, 142.475998, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.1899414, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 2091.909912, -1464.430054, 809.992981 >, < -0.000000, 143.503998, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.8800049, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1528.660034, -1443.339966, 816.031006 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.1500244, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 1418.310059, -2254.659912, 810.031006 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.3499756, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 1452.199951, -1794.530029, 804.614990 >, < -0.000000, 112.485001, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.22998047, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 896.656006, -1227.339966, 964.437988 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.8699951, index++ ) )
+ wave5.append( CreateSuperSpectreEvent( < 2162.209961, -1065.609985, 806.807007 >, < -0.000000, -174.283005, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.11999512, index++ ) )
+ wave5.append( CreateDroppodStalkerEvent( < 2457.310059, -2563.659912, 789.250000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 2665.060059, 4456.129883, 960.687988 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.5999756, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 3123.250000, 4201.689941, 954.281006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.60009766, index++ ) )
+ wave5.append( CreateCloakDroneEvent( < 2674.979980, 4322.020020, 1283.979980 >, < 0.000000, 0.000000, 0.000000 >, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 2475.810059, -3544.189941, 810.218994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.2999268, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 2821.340088, -2936.719971, 827.937988 >, < 0.000000, 117.202003, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.70007324, index++ ) )
+ wave5.append( CreateCloakDroneEvent( < 2363.000000, -3327.010010, 1235.989990 >, < 0.000000, 0.000000, 0.000000 >, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 6.0, index++ ) )
+ wave5.append( CreateScorchTitanEvent( < 1763.910034, -1608.660034, 810.218994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.2999268, index++ ) )
+ wave5.append( CreateScorchTitanEvent( < 2359.909912, -1596.660034, 802.718994 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.4000244, index++ ) )
+ wave5.append( CreateIonTitanEvent( < 1559.810059, -2024.189941, 803.031006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.6999512, index++ ) )
+ wave5.append( CreateIonTitanEvent( < 2411.810059, -1108.189941, 803.375000 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateToneSniperTitanEvent( < 4466.220215, 1469.410034, 947.281006 >, < 0.000000, 169.541000, 0.000000 >, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.9000244, index++ ) )
+ wave5.append( CreateToneSniperTitanEvent( < 4453.129883, 964.750000, 947.281006 >, < 0.000000, -172.529007, 0.000000 >, index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.0999756, index++ ) )
+ wave5.append( CreateArcTitanEvent( < 3867.219971, 1445.689941, 947.281006 >, < 0.000000, 180.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateNukeTitanEvent( < 2475.909912, -3544.659912, 810.281006 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.2000732, index++ ) )
+ wave5.append( CreateNukeTitanEvent( < 2665.340088, 4456.500000, 960.656006 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.2999268, index++ ) )
+ wave5.append( CreateNukeTitanEvent( < 2821.659912, -2937.090088, 827.937988 >, < 0.000000, 117.202003, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.8000488, index++ ) )
+ wave5.append( CreateNukeTitanEvent( < 3123.560059, 4202.060059, 954.343994 >, < 0.000000, -141.108002, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.0999756, index++ ) )
+ wave5.append( CreateNukeTitanEvent( < 1817.469971, -3586.379883, 814.062988 >, < 0.000000, 90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 0.6999512, index++ ) )
+ wave5.append( CreateNukeTitanEvent( < 1324.060059, 4820.660156, 937.562988 >, < 0.000000, -90.000000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 5.0, index++ ) )
+ wave5.append( CreateWaitUntilAliveWeightedEvent( 16, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 4466.220215, 1469.410034, 947.281006 >, < 0.000000, 169.541000, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.3000488, index++ ) )
+ wave5.append( CreateToneTitanEvent( < 4453.129883, 964.750000, 947.281006 >, < 0.000000, -172.529007, 0.000000 >, "", index++ ) )
+ wave5.append( CreateWaitForTimeEvent( 1.3000488, index++ ) )
+ wave5.append( CreateScorchTitanEvent( < 3867.129883, 1445.719971, 947.281006 >, < 0.000000, 180.000000, 0.000000 >, "", 0 ) )
+ waveEvents.append( wave5 )
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch.nut
index 37b89169..e6eb493d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch.nut
@@ -1 +1,8 @@
-//fuck \ No newline at end of file
+global function CodeCallback_MapInit
+
+void function CodeCallback_MapInit()
+{
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_glitch_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave.nut
index f4b48f6d..9b5d3080 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave.nut
@@ -4,6 +4,11 @@ void function CodeCallback_MapInit()
{
// there are some really busted titan startspawns that are on the fucking other side of the map from where they should be, so we remove them
AddSpawnCallback( "info_spawnpoint_titan_start", TrimBadTitanStartSpawns )
+
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+
}
void function TrimBadTitanStartSpawns( entity spawn )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_grave_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead.nut
index 37b89169..e6eb493d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead.nut
@@ -1 +1,8 @@
-//fuck \ No newline at end of file
+global function CodeCallback_MapInit
+
+void function CodeCallback_MapInit()
+{
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead_fd.nut
index 37b89169..dce818cb 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_homestead_fd.nut
@@ -1 +1,568 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = < -800.156, -4250, -63 >
+ shopAngles = < 9, 60, 0 >
+ FD_spawnPosition = < 576.47, -3946.24, -174.07>
+ FD_spawnAngles = < 0, 60, 0 >
+
+ int index = 1
+ array<WaveEvent> wave1
+ wave1.append(CreateSpawnDroneEvent(< 6050.669922 , 132.485001 , 4918.959961 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave1.append(CreateWaitForTimeEvent(1.5,index++))
+ wave1.append(CreateSpawnDroneEvent(< 3341.850098 , 2237.580078 , 4965.220215 >,< 0.004999 , -115.792000 , 0.000004 >,"centerLeftDrones_Loop3",index++))
+ wave1.append(CreateWaitForTimeEvent(1.5,index++))
+ wave1.append(CreateDroppodGruntEvent(< 68.781303 , -516.468994 , -97.937500 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.5999985,index++))
+ wave1.append(CreateDroppodGruntEvent(< -770.500000 , 1070.060059 , -159.781006 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.9000015,index++))
+ wave1.append(CreateDroppodGruntEvent(< 2696.000000 , -1068.719971 , -92.687500 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0,index++))
+ wave1.append(CreateDroppodGruntEvent(< 2420.310059 , -1135.250000 , -159.218994 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ // replaced this with the one below because it seemed off?
+ //wave1.append(CreateSpawnDroneEvent(< -697.750000 , 940.593994 , 153.656006 >,< -0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave1.append(CreateSpawnDroneEvent(< 6050.669922 , 132.485001 , 4918.959961 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave1.append(CreateWaitForTimeEvent(0.5999985,index++))
+ // replaced this with the one below because it seemed off?
+ //wave1.append(CreateSpawnDroneEvent(< 2696.909912 , -388.062988 , 349.250000 >,< -0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave1.append(CreateSpawnDroneEvent(< 3341.850098 , 2237.580078 , 4965.220215 >,< 0.004999 , -115.792000 , 0.000004 >,"centerLeftDrones_Loop3",index++))
+ wave1.append(CreateWaitForTimeEvent(1.199997,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.1000061,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.2999954,index++))
+ wave1.append(CreateDroppodGruntEvent(< 2870.810059 , -2727.629883 , 77.968803 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.25,index++))
+ wave1.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.5830078,index++))
+ wave1.append(CreateDroppodGruntEvent(< 4731.839844 , -2077.219971 , -35.625000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(2.7829895,index++))
+ wave1.append(CreateDroppodGruntEvent(< -1197.939941 , 1928.560059 , 80.031303 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.3340149,index++))
+ wave1.append(CreateDroppodGruntEvent(< -610.500000 , 1743.060059 , 93.156303 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.2659912,index++))
+ wave1.append(CreateSuperSpectreEvent(< 779.500000 , -365.375000 , -166.093994 >,< 0.000000 , -52.734402 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.6170044,index++))
+ wave1.append(CreateDroppodGruntEvent(< -3570.879883 , -1498.500000 , -49.625000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodGruntEvent(< -3570.879883 , -1498.500000 , -49.625000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.2999878,index++))
+ wave1.append(CreateSpawnDroneEvent(< 6050.669922 , 132.485001 , 4877.899902 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave1.append(CreateWaitForTimeEvent(2.0170135,index++))
+ wave1.append(CreateSpawnDroneEvent(< 5994.600098 , 1378.760010 , 4810.569824 >,< 0.004999 , -73.121300 , 0.000004 >,"centerLeftDrones_Loop3",index++))
+ wave1.append(CreateWaitForTimeEvent(0.6659851,index++))
+ wave1.append(CreateSpawnDroneEvent(< 3381.919922 , 2251.550049 , 4955.319824 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave1.append(CreateWaitForTimeEvent(2.0,index++))
+ wave1.append(CreateSuperSpectreEvent(< 2918.379883 , -3060.629883 , -25.187500 >,< -0.000000 , -170.770996 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.300003,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0829926,index++))
+ wave1.append(CreateDroppodGruntEvent(< 2870.810059 , -2727.629883 , 77.968803 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.93400574,index++))
+ wave1.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(2.9000092,index++))
+ wave1.append(CreateDroppodGruntEvent(< 4009.219971 , 3091.500000 , -2.406250 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodGruntEvent(< 4009.219971 , 3091.500000 , -2.406250 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.4669952,index++))
+ wave1.append(CreateDroppodGruntEvent(< 5542.589844 , 2078.189941 , -31.531300 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0330048,index++))
+ wave1.append(CreateDroppodGruntEvent(< 5204.000000 , 1308.000000 , 7.593750 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateSuperSpectreEvent(< -523.031006 , 807.125000 , -167.218994 >,< 0.000000 , -91.450203 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.2169952,index++))
+ wave1.append(CreateSuperSpectreEvent(< 3316.060059 , -2935.530029 , -67.218803 >,< -0.000000 , -156.182007 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodSpectreMortarEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.1000061,index++))
+ wave1.append(CreateDroppodSpectreMortarEvent(< -1881.280029 , 1307.310059 , -159.781006 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0,index++))
+ wave1.append(CreateDroppodSpectreMortarEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.5,index++))
+ wave1.append(CreateDroppodSpectreMortarEvent(< -1008.880005 , 1265.500000 , -159.781006 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0,index++))
+ wave1.append(CreateDroppodSpectreMortarEvent(< 2870.810059 , -2727.629883 , 77.968803 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodGruntEvent(< -1881.280029 , 1307.310059 , -159.781006 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodGruntEvent(< 2812.340088 , -1307.750000 , -156.563004 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave1.append(CreateDroppodGruntEvent(< 2696.000000 , -1068.719971 , -92.687500 >,"",0))
+ waveEvents.append(wave1)
+ index = 1
+ array<WaveEvent> wave2
+ wave2.append(CreateSpawnDroneEvent(< 6090.759766 , 146.453995 , 4888.700195 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave2.append(CreateWaitForTimeEvent(1.1170044,index++))
+ wave2.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.78302,index++))
+ wave2.append(CreateDroppodGruntEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(3.21698,index++))
+ wave2.append(CreateDroppodGruntEvent(< 68.781303 , -516.468994 , -97.937500 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.7669983,index++))
+ wave2.append(CreateDroppodGruntEvent(< -770.500000 , 1070.060059 , -159.781006 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.0,index++))
+ wave2.append(CreateDroppodGruntEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateSpawnDroneEvent(< 6036.729980 , 172.546997 , 4870.890137 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave2.append(CreateWaitForTimeEvent(2.7000122,index++))
+ wave2.append(CreateSpawnDroneEvent(< 6012.029785 , 1321.359985 , 4831.279785 >,< 0.004999 , -73.121300 , 0.000004 >,"centerLeftDrones_Loop3",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateSpawnDroneEvent(< 6076.790039 , 186.516006 , 4886.330078 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateSpawnDroneEvent(< 3367.949951 , 2291.610107 , 4918.220215 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave2.append(CreateWaitForTimeEvent(1.4830322,index++))
+ wave2.append(CreateDroppodSpectreMortarEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.6170044,index++))
+ wave2.append(CreateDroppodSpectreMortarEvent(< -1881.280029 , 1307.310059 , -159.781006 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateDroppodGruntEvent(< 2812.340088 , -1307.750000 , -156.563004 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.3500366,index++))
+ wave2.append(CreateDroppodGruntEvent(< -3570.879883 , -1498.500000 , -49.625000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(3.0,index++))
+ wave2.append(CreateToneSniperTitanEvent(< 1484.189941 , 968.218994 , 97.968803 >,< -0.922852 , -141.942993 , -1.582030 >,index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateDroppodGruntEvent(< 2812.340088 , -1307.750000 , -156.563004 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.1670532,index++))
+ wave2.append(CreateDroppodGruntEvent(< 2696.000000 , -1068.719971 , -92.687500 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.4829712,index++))
+ wave2.append(CreateMortarTitanEvent(< -515.187988 , 1099.160034 , -162.281006 >,< 0.000000 , -90.000000 , 0.000000 >,index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateDroppodGruntEvent(< 68.781303 , -516.468994 , -97.937500 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.5170288,index++))
+ wave2.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(3.0999756,index++))
+ wave2.append(CreateDroppodGruntEvent(< -770.500000 , 1070.060059 , -159.781006 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateDroppodGruntEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8829956,index++))
+ wave2.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.6170044,index++))
+ wave2.append(CreateDroppodGruntEvent(< -3570.879883 , -1498.500000 , -49.625000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.3670044,index++))
+ wave2.append(CreateDroppodGruntEvent(< 2870.810059 , -2727.629883 , 77.968803 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(2.8999634,index++))
+ wave2.append(CreateDroppodGruntEvent(< 2812.340088 , -1307.750000 , -156.563004 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave2.append(CreateDroppodGruntEvent(< -3570.879883 , -1498.500000 , -49.625000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.532959,index++))
+ wave2.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8670044,index++))
+ wave2.append(CreateNukeTitanEvent(< 2758.840088 , -436.187988 , -75.156303 >,< -0.922852 , -141.942993 , -1.582030 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.61602783,index++))
+ wave2.append(CreateNukeTitanEvent(< -515.281006 , 1099.630005 , -162.281006 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8999634,index++))
+ wave2.append(CreateNukeTitanEvent(< 4027.840088 , -2180.129883 , -61.937500 >,< -0.922852 , -143.613007 , -1.582030 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8840332,index++))
+ wave2.append(CreateNukeTitanEvent(< -918.125000 , 890.625000 , -155.250000 >,< 0.000000 , 90.000000 , 0.000000 >,"",0))
+ waveEvents.append(wave2)
+ index = 1
+ array<WaveEvent> wave3
+ wave3.append(CreateSpawnDroneEvent(< 6050.669922 , 132.485001 , 4893.919922 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(1.0170288,index++))
+ wave3.append(CreateSpawnDroneEvent(< 6032.029785 , 1358.760010 , 4813.379883 >,< 0.004999 , -73.121300 , 0.000004 >,"centerLeftDrones_Loop3",index++))
+ wave3.append(CreateWaitForTimeEvent(0.8829956,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3327.889893 , 2277.639893 , 4935.830078 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(0.7839966,index++))
+ wave3.append(CreateSpawnDroneEvent(< 4582.979980 , 2624.050049 , 4906.810059 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(0.9160156,index++))
+ wave3.append(CreateSpawnDroneEvent(< 4024.330078 , 3117.510010 , 4947.189941 >,< 0.004999 , -25.792200 , 0.000004 >,"centerRightDrones_Loop4",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3341.850098 , 2237.580078 , 4889.950195 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateSuperSpectreEvent(< -515.437988 , -263.281006 , 420.281006 >,< -0.000000 , 176.923996 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.2160034,index++))
+ wave3.append(CreateSuperSpectreEvent(< 2567.189941 , -3095.969971 , 25.437500 >,< -0.000000 , -174.945999 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.10003662,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3341.850098 , 2237.580078 , 4936.169922 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3381.919922 , 2251.550049 , 4946.819824 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(0.717041,index++))
+ wave3.append(CreateSpawnDroneEvent(< 2880.760010 , 3060.300049 , 4874.819824 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(0.782959,index++))
+ wave3.append(CreateSpawnDroneEvent(< 4569.009766 , 2664.110107 , 4897.569824 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(1.4169922,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3984.270020 , 3103.570068 , 4931.939941 >,< 0.004999 , -25.792200 , 0.000004 >,"centerRightDrones_Loop4",index++))
+ wave3.append(CreateWaitForTimeEvent(1.4830322,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3381.919922 , 2251.550049 , 4931.640137 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(4.0999756,index++))
+ wave3.append(CreateIonTitanEvent(< -515.187988 , 1099.160034 , -162.281006 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.0170288,index++))
+ wave3.append(CreateIonTitanEvent(< 3574.409912 , -2788.219971 , -68.312500 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateDroppodGruntEvent(< 25.437500 , -2.062500 , -159.781006 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.96698,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.950012,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3367.949951 , 2291.610107 , 4920.089844 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(1.4829712,index++))
+ wave3.append(CreateMortarTitanEvent(< -515.187988 , 1099.160034 , -162.281006 >,< 0.000000 , -90.000000 , 0.000000 >,index++))
+ wave3.append(CreateWaitForTimeEvent(0.717041,index++))
+ wave3.append(CreateMortarTitanEvent(< 3574.409912 , -2788.219971 , -68.312500 >,< 0.000000 , 0.000000 , 0.000000 >,index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateDroppodGruntEvent(< -1197.939941 , 1928.560059 , 80.031303 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.5,index++))
+ wave3.append(CreateDroppodGruntEvent(< -610.500000 , 1743.060059 , 93.156303 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.3829956,index++))
+ wave3.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.21698,index++))
+ wave3.append(CreateToneSniperTitanEvent(< 1484.189941 , 968.218994 , 97.968803 >,< -0.922852 , -141.942993 , -1.582030 >,index++))
+ wave3.append(CreateWaitForTimeEvent(0.6000366,index++))
+ wave3.append(CreateMortarTitanEvent(< 1984.030029 , 138.125000 , -75.031303 >,< -0.922852 , -97.602501 , -1.582030 >,index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateDroppodGruntEvent(< -1197.939941 , 1928.560059 , 80.031303 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.5,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave3.append(CreateSuperSpectreEvent(< 512.492004 , -288.734985 , -167.218994 >,< 0.000000 , 148.755005 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.41705322,index++))
+ wave3.append(CreateDroppodGruntEvent(< -610.500000 , 1743.060059 , 93.156303 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.017029,index++))
+ wave3.append(CreateSuperSpectreEvent(< 3324.590088 , -2931.780029 , -67.531303 >,< 0.000000 , -156.138000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(2.6829834,index++))
+ wave3.append(CreateSpawnDroneEvent(< 6090.759766 , 146.453995 , 4907.120117 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(1.217041,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3367.949951 , 2291.610107 , 4934.399902 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateDroppodGruntEvent(< -1197.939941 , 1928.560059 , 80.031303 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.1329956,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(4.049988,index++))
+ wave3.append(CreateSpawnDroneEvent(< 6076.790039 , 186.516006 , 4905.089844 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(1.2330322,index++))
+ wave3.append(CreateSpawnDroneEvent(< 6012.029785 , 1321.359985 , 4808.120117 >,< 0.004999 , -73.121300 , 0.000004 >,"centerLeftDrones_Loop3",index++))
+ wave3.append(CreateWaitForTimeEvent(1.0999756,index++))
+ wave3.append(CreateSpawnDroneEvent(< 5204.000000 , 1275.729980 , 4938.310059 >,< 0.004999 , -89.996300 , 0.000004 >,"centerRightDrones_Loop2",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3367.949951 , 2291.610107 , 4898.049805 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(1.1669922,index++))
+ wave3.append(CreateSpawnDroneEvent(< 4542.890137 , 2610.110107 , 4888.470215 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(1.3330078,index++))
+ wave3.append(CreateSpawnDroneEvent(< 2826.729980 , 3086.419922 , 4851.450195 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(0.9500122,index++))
+ wave3.append(CreateNukeTitanEvent(< 3573.939941 , -2788.310059 , -68.281303 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.532959,index++))
+ wave3.append(CreateNukeTitanEvent(< -1799.530029 , 1310.839966 , -164.218994 >,< -0.922852 , -151.830994 , -1.582030 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.7839966,index++))
+ wave3.append(CreateNukeTitanEvent(< 4027.840088 , -2180.129883 , -61.937500 >,< -0.922852 , -143.613007 , -1.582030 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.5,index++))
+ wave3.append(CreateNukeTitanEvent(< -2077.379883 , 950.062988 , -143.813004 >,< 0.000000 , 90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(4.31604,index++))
+ wave3.append(CreateSuperSpectreEvent(< -522.593994 , -251.406006 , 416.437988 >,< -0.000000 , 169.408997 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateSpawnDroneEvent(< 6076.790039 , 186.516006 , 4864.759766 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(0.8840332,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3367.949951 , 2291.610107 , 4941.009766 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave3.append(CreateWaitForTimeEvent(0.8999634,index++))
+ wave3.append(CreateScorchTitanEvent(< 5251.529785 , 2049.280029 , 13.125000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.5159912,index++))
+ wave3.append(CreateScorchTitanEvent(< 4249.879883 , 2937.159912 , -44.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.467041,index++))
+ wave3.append(CreateNukeTitanEvent(< 3573.939941 , -2788.310059 , -68.281303 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.9329834,index++))
+ wave3.append(CreateNukeTitanEvent(< -1799.530029 , 1310.839966 , -164.218994 >,< -0.922852 , -151.830994 , -1.582030 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.3999634,index++))
+ wave3.append(CreateDroppodGruntEvent(< -1197.939941 , 1928.560059 , 80.031303 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.2000122,index++))
+ wave3.append(CreateDroppodGruntEvent(< -3570.879883 , -1498.500000 , -49.625000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave3.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",0))
+ waveEvents.append(wave3)
+ index = 1
+ array<WaveEvent> wave4
+ wave4.append(CreateIonTitanEvent(< -1799.910034 , 1310.530029 , -164.218994 >,< -0.922852 , -151.830994 , -1.582030 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateSuperSpectreEvent(< -2619.399902 , 511.446014 , -141.567993 >,< -0.000000 , -139.373001 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.5,index++))
+ wave4.append(CreateSuperSpectreEvent(< -1172.420044 , 1221.010010 , -167.218994 >,< 0.000000 , -175.912994 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.11999512,index++))
+ wave4.append(CreateSpawnDroneEvent(< 6090.759766 , 146.453995 , 4879.229980 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave4.append(CreateWaitForTimeEvent(1.0999756,index++))
+ wave4.append(CreateSpawnDroneEvent(< 3381.919922 , 2251.550049 , 4925.459961 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave4.append(CreateWaitForTimeEvent(1.0599365,index++))
+ wave4.append(CreateDroppodGruntEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1400146,index++))
+ wave4.append(CreateDroppodSpectreMortarEvent(< 5542.589844 , 2078.189941 , -31.531300 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateDroppodGruntEvent(< -3570.879883 , -1498.500000 , -49.625000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1199951,index++))
+ wave4.append(CreateDroppodSpectreMortarEvent(< -3375.090088 , -1307.969971 , -90.593803 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1999512,index++))
+ wave4.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1600342,index++))
+ wave4.append(CreateDroppodSpectreMortarEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateScorchTitanEvent(< 5251.529785 , 2049.280029 , 13.125000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.7800293,index++))
+ wave4.append(CreateScorchTitanEvent(< 4249.879883 , 2937.159912 , -44.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.920044,index++))
+ wave4.append(CreateSuperSpectreEvent(< 275.593994 , -144.656006 , -156.968994 >,< 0.000000 , -168.091003 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateRoninTitanEvent(< -1799.439941 , 1310.839966 , -164.218994 >,< -0.922852 , -151.830994 , -1.582030 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateSuperSpectreEvent(< -2191.379883 , 875.562988 , -139.968994 >,< -0.000000 , -142.382996 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.11999512,index++))
+ wave4.append(CreateRoninTitanEvent(< 3573.840088 , -2788.250000 , -68.250000 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.57995605,index++))
+ wave4.append(CreateSuperSpectreEvent(< -1868.939941 , 1052.229980 , -153.057007 >,< -0.000000 , -156.475006 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateSuperSpectreEvent(< 3465.909912 , -2830.469971 , -68.375000 >,< -0.922858 , -149.106003 , -1.582030 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.9699707,index++))
+ wave4.append(CreateIonTitanEvent(< 5136.720215 , -2059.379883 , -105.125000 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.5,index++))
+ wave4.append(CreateSuperSpectreEvent(< 3640.330078 , -2726.229980 , -72.381897 >,< -0.922858 , -146.380997 , -1.582030 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateSuperSpectreEvent(< 3683.840088 , -2703.780029 , -69.718803 >,< -0.922858 , -149.766006 , -1.582030 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.6800537,index++))
+ wave4.append(CreateSuperSpectreEvent(< 2472.750000 , -733.406006 , -117.594002 >,< -0.922852 , -132.231003 , -1.582030 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateDroppodGruntEvent(< 4230.189941 , -366.312988 , 22.968800 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.79003906,index++))
+ wave4.append(CreateDroppodGruntEvent(< -1197.939941 , 1928.560059 , 80.031303 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.0100098,index++))
+ wave4.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateSuperSpectreEvent(< 2614.300049 , -3101.199951 , 14.673600 >,< 0.000000 , -172.837006 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.8199463,index++))
+ wave4.append(CreateSuperSpectreEvent(< -2551.510010 , 644.447998 , -123.125000 >,< -0.922858 , -132.886993 , -1.582030 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.4100342,index++))
+ wave4.append(CreateSuperSpectreEvent(< 3910.250000 , -2404.560059 , -89.156303 >,< -0.922852 , -121.376999 , -1.582030 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateSpawnDroneEvent(< 6050.669922 , 132.485001 , 4890.120117 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave4.append(CreateWaitForTimeEvent(0.8099365,index++))
+ wave4.append(CreateSpawnDroneEvent(< 5994.600098 , 1378.760010 , 4814.129883 >,< 0.004999 , -73.121300 , 0.000004 >,"centerLeftDrones_Loop3",index++))
+ wave4.append(CreateWaitForTimeEvent(1.5,index++))
+ wave4.append(CreateSpawnDroneEvent(< 5234.000000 , 1305.729980 , 4936.160156 >,< 0.004999 , -89.996300 , 0.000004 >,"centerRightDrones_Loop2",index++))
+ wave4.append(CreateWaitForTimeEvent(1.2000732,index++))
+ wave4.append(CreateSpawnDroneEvent(< 3341.850098 , 2237.580078 , 4911.430176 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateSpawnDroneEvent(< 3327.889893 , 2277.639893 , 4940.600098 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave4.append(CreateWaitForTimeEvent(0.8300781,index++))
+ wave4.append(CreateSpawnDroneEvent(< 2866.790039 , 3100.360107 , 4857.200195 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave4.append(CreateWaitForTimeEvent(1.2799072,index++))
+ wave4.append(CreateToneSniperTitanEvent(< 1484.189941 , 968.218994 , 97.968803 >,< -0.922852 , -141.942993 , -1.582030 >,index++))
+ wave4.append(CreateWaitForTimeEvent(1.2900391,index++))
+ wave4.append(CreateToneTitanEvent(< -515.187988 , 1099.160034 , -162.281006 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.60998535,index++))
+ wave4.append(CreateToneTitanEvent(< 3574.409912 , -2788.219971 , -68.312500 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(2.9899902,index++))
+ wave4.append(CreateDroppodGruntEvent(< 68.781303 , -516.468994 , -97.937500 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.4100342,index++))
+ wave4.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateSpawnDroneEvent(< 6036.729980 , 172.546997 , 4861.959961 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave4.append(CreateWaitForTimeEvent(0.98999023,index++))
+ wave4.append(CreateSpawnDroneEvent(< 6032.029785 , 1358.760010 , 4831.629883 >,< 0.004999 , -73.121300 , 0.000004 >,"centerLeftDrones_Loop3",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1099854,index++))
+ wave4.append(CreateSpawnDroneEvent(< 5204.000000 , 1335.729980 , 4926.459961 >,< 0.004999 , -89.996300 , 0.000004 >,"centerRightDrones_Loop2",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateToneSniperTitanEvent(< 1484.189941 , 968.218994 , 97.968803 >,< -0.922852 , -141.942993 , -1.582030 >,index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave4.append(CreateDroppodGruntEvent(< -1197.939941 , 1928.560059 , 80.031303 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1099854,index++))
+ wave4.append(CreateDroppodGruntEvent(< 3917.000000 , -2654.719971 , -81.468803 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.0400391,index++))
+ wave4.append(CreateSuperSpectreEvent(< 496.070007 , -280.742004 , -167.218994 >,< 0.000000 , 148.403000 , 0.000000 >,"",0))
+ waveEvents.append(wave4)
+ index = 1
+ array<WaveEvent> wave5
+ wave5.append(CreateDroppodSpectreMortarEvent(< 3754.719971 , -2589.250000 , -63.906300 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.7800293,index++))
+ wave5.append(CreateDroppodSpectreMortarEvent(< -1881.280029 , 1307.310059 , -159.781006 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1300049,index++))
+ wave5.append(CreateDroppodSpectreMortarEvent(< 5204.000000 , 1308.000000 , 7.593750 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1899414,index++))
+ wave5.append(CreateMortarTitanEvent(< 1484.189941 , 968.218994 , 97.968803 >,< -0.922852 , -141.942993 , -1.582030 >,index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateNukeTitanEvent(< 5251.529785 , 2049.280029 , 13.125000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0999756,index++))
+ wave5.append(CreateNukeTitanEvent(< 4249.879883 , 2937.159912 , -44.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(4.580078,index++))
+ wave5.append(CreateSuperSpectreEvent(< 4956.689941 , 1462.579956 , 55.508598 >,< -0.000000 , -158.052002 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.92993164,index++))
+ wave5.append(CreateSuperSpectreEvent(< 3183.560059 , 2090.909912 , -48.263699 >,< -0.000000 , -105.017998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateNorthstarSniperTitanEvent(< 5251.560059 , 2049.379883 , 13.093800 >,< 0.000000 , -90.000000 , 0.000000 >,index++))
+ wave5.append(CreateWaitForTimeEvent(0.8000488,index++))
+ wave5.append(CreateToneSniperTitanEvent(< 4249.970215 , 2936.689941 , -44.187500 >,< 0.000000 , -90.000000 , 0.000000 >,index++))
+ wave5.append(CreateWaitForTimeEvent(6.910034,index++))
+ wave5.append(CreateNukeTitanEvent(< 5748.529785 , 1979.339966 , -71.062500 >,< 0.000000 , -142.690002 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3898926,index++))
+ wave5.append(CreateNukeTitanEvent(< 3610.939941 , 2928.689941 , 22.218800 >,< 0.000000 , -113.642998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(3.9000244,index++))
+ wave5.append(CreateArcTitanEvent(< 2758.969971 , -436.187988 , -75.125000 >,< -0.922852 , -141.942993 , -1.582030 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0100098,index++))
+ wave5.append(CreateSuperSpectreEvent(< 4416.339844 , 1310.920044 , 4.697280 >,< 0.000000 , -124.364998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.98999023,index++))
+ wave5.append(CreateSuperSpectreEvent(< 5161.879883 , 804.687988 , -41.937500 >,< 0.000000 , -134.824005 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateNukeTitanEvent(< 5251.529785 , 2049.280029 , 13.125000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0,index++))
+ wave5.append(CreateNukeTitanEvent(< 4249.879883 , 2937.159912 , -44.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.23999023,index++))
+ wave5.append(CreateSpawnDroneEvent(< 3027.270020 , 1470.109985 , 196.347000 >,< 13.667000 , -114.433998 , 0.000000 >,"centerRightDrones_Loop6",index++))
+ wave5.append(CreateWaitForTimeEvent(0.10998535,index++))
+ wave5.append(CreateSpawnDroneEvent(< 2938.060059 , 1411.089966 , 100.563004 >,< 13.667000 , -110.039001 , 0.000000 >,"centerRightDrones_Loop6",index++))
+ wave5.append(CreateWaitForTimeEvent(0.11999512,index++))
+ wave5.append(CreateSpawnDroneEvent(< 3031.810059 , 1541.949951 , 103.435997 >,< 12.767300 , -112.807999 , -0.000001 >,"centerRightDrones_Loop6",index++))
+ wave5.append(CreateWaitForTimeEvent(3.5999756,index++))
+ wave5.append(CreateSuperSpectreEvent(< 5122.479980 , 1549.989990 , 38.913399 >,< -0.000000 , -147.757004 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.82006836,index++))
+ wave5.append(CreateSuperSpectreEvent(< 3277.000000 , 2468.239990 , -11.818300 >,< -0.000000 , -106.505997 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.709961,index++))
+ wave5.append(CreateSuperSpectreEvent(< 3270.409912 , 2209.939941 , -29.437500 >,< -0.000000 , -109.906998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1999512,index++))
+ wave5.append(CreateSuperSpectreEvent(< 5253.410156 , 1635.689941 , 16.718800 >,< 0.000000 , -146.908997 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateNukeTitanEvent(< 5605.439941 , 1266.410034 , -54.562500 >,< 0.000000 , -162.641998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.2199707,index++))
+ wave5.append(CreateNukeTitanEvent(< 4249.879883 , 2937.159912 , -44.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.6800537,index++))
+ wave5.append(CreateSuperSpectreEvent(< 5153.359863 , 1756.530029 , 39.026600 >,< 0.000000 , -111.313004 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.2199707,index++))
+ wave5.append(CreateArcTitanEvent(< 5748.660156 , 1979.380005 , -71.062500 >,< 0.000000 , -142.690002 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.70007324,index++))
+ wave5.append(CreateNukeTitanEvent(< 5375.560059 , 2948.280029 , -33.250000 >,< 0.000000 , -142.690002 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave5.append(CreateSuperSpectreEvent(< 5297.750000 , 59.281300 , -167.063004 >,< 0.000000 , -54.975601 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.16992188,index++))
+ wave5.append(CreateNukeTitanEvent(< 3897.439941 , 3308.530029 , -20.593800 >,< 0.000000 , -113.642998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.5300293,index++))
+ wave5.append(CreateSuperSpectreEvent(< 3347.310059 , 2737.810059 , 18.812500 >,< -0.000000 , -102.084999 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.47998047,index++))
+ wave5.append(CreateArcTitanEvent(< 2758.969971 , -436.187988 , -75.125000 >,< -0.922852 , -141.942993 , -1.582030 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4000244,index++))
+ wave5.append(CreateNukeTitanEvent(< 5251.529785 , 2049.280029 , 13.125000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.2900391,index++))
+ wave5.append(CreateNukeTitanEvent(< 3610.939941 , 2928.689941 , 22.218800 >,< 0.000000 , -113.642998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.60998535,index++))
+ wave5.append(CreateSpawnDroneEvent(< 3341.850098 , 2237.580078 , 4942.560059 >,< 0.004999 , -115.792000 , 0.000004 >,"centerRightDrones_Loop1",index++))
+ wave5.append(CreateWaitForTimeEvent(0.73999023,index++))
+ wave5.append(CreateNukeTitanEvent(< 5797.589844 , 1407.689941 , -93.906303 >,< 0.000000 , -161.498993 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.7800293,index++))
+ wave5.append(CreateNukeTitanEvent(< 4320.029785 , 2913.030029 , -56.593800 >,< 0.000000 , -113.642998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0200195,index++))
+ wave5.append(CreateSuperSpectreEvent(< 3990.439941 , 419.718994 , -130.875000 >,< -0.000000 , -171.210999 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3599854,index++))
+ wave5.append(CreateSuperSpectreEvent(< 2692.169922 , 2159.280029 , -142.787003 >,< -0.000000 , -84.377403 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateArcTitanEvent(< 5251.560059 , 2049.379883 , 13.093800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4399414,index++))
+ wave5.append(CreateNukeTitanEvent(< 5748.529785 , 1979.339966 , -71.062500 >,< 0.000000 , -142.690002 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.8800049,index++))
+ wave5.append(CreateNukeTitanEvent(< 4249.879883 , 2937.159912 , -44.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave5.append(CreateMortarTitanEvent(< 1484.189941 , 968.218994 , 97.968803 >,< -0.922852 , -141.942993 , -1.582030 >,index++))
+ wave5.append(CreateWaitForTimeEvent(0.7199707,index++))
+ wave5.append(CreateNukeTitanEvent(< 5797.589844 , 1407.689941 , -93.906303 >,< 0.000000 , -161.498993 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave5.append(CreateNukeTitanEvent(< 3610.939941 , 2928.689941 , 22.218800 >,< 0.000000 , -113.642998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(2.9100342,index++))
+ wave5.append(CreateNukeTitanEvent(< 5375.560059 , 2948.280029 , -33.250000 >,< 0.000000 , -142.690002 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.77001953,index++))
+ wave5.append(CreateNukeTitanEvent(< 3897.439941 , 3308.530029 , -20.593800 >,< 0.000000 , -113.642998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3199463,index++))
+ wave5.append(CreateNukeTitanEvent(< 5251.529785 , 2049.280029 , 13.125000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3601074,index++))
+ wave5.append(CreateNukeTitanEvent(< 4699.589844 , 2906.159912 , -72.843803 >,< 0.000000 , -115.795998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateSuperSpectreEvent(< -524.656006 , -249.875000 , 416.437988 >,< -0.000000 , 161.938004 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateScorchTitanEvent(< 5251.529785 , 2049.280029 , 13.125000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.9199219,index++))
+ wave5.append(CreateScorchTitanEvent(< 4249.879883 , 2937.159912 , -44.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateNukeTitanEvent(< 5605.439941 , 1266.410034 , -54.562500 >,< 0.000000 , -162.641998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3800049,index++))
+ wave5.append(CreateNukeTitanEvent(< 1484.500000 , 968.593994 , 98.031303 >,< -0.922852 , -141.942993 , -1.582030 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveWeightedEvent(12,index++))
+ wave5.append(CreateScorchTitanEvent(< 5251.529785 , 2049.280029 , 13.125000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.8300781,index++))
+ wave5.append(CreateScorchTitanEvent(< 4249.879883 , 2937.159912 , -44.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4899902,index++))
+ wave5.append(CreateNukeTitanEvent(< 5748.529785 , 1979.339966 , -71.062500 >,< 0.000000 , -142.690002 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0,index++))
+ wave5.append(CreateNukeTitanEvent(< 3610.939941 , 2928.689941 , 22.218800 >,< 0.000000 , -113.642998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.8800049,index++))
+ wave5.append(CreateNukeTitanEvent(< 5797.589844 , 1407.689941 , -93.906303 >,< 0.000000 , -161.498993 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.7199707,index++))
+ wave5.append(CreateNukeTitanEvent(< 3897.439941 , 3308.530029 , -20.593800 >,< 0.000000 , -113.642998 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.60998535,index++))
+ wave5.append(CreateNukeTitanEvent(< 5375.560059 , 2948.280029 , -33.250000 >,< 0.000000 , -142.690002 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.9499512,index++))
+ wave5.append(CreateNukeTitanEvent(< 4699.589844 , 2906.159912 , -72.843803 >,< 0.000000 , -115.795998 , 0.000000 >,"",0))
+ waveEvents.append(wave5)
+
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02.nut
index 37b89169..3441fc60 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02.nut
@@ -1 +1,6 @@
-//fuck \ No newline at end of file
+void function CodeCallback_MapInit()
+{
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_relic02_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise.nut
index 37b89169..e6eb493d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise.nut
@@ -1 +1,8 @@
-//fuck \ No newline at end of file
+global function CodeCallback_MapInit
+
+void function CodeCallback_MapInit()
+{
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise_fd.nut
index 37b89169..fb0452db 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_rise_fd.nut
@@ -1 +1,617 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+
+
+void function initFrontierDefenseData()
+{
+ shopPosition = < -5165.42, -679.285, 384.031 > //only aproximate position
+ FD_spawnPosition = < -5325.66, -1363.046, 384.031 >
+
+ FD_spawnAngles = < 0, 0, 0 >
+
+ int index = 1
+ array<WaveEvent> wave1
+ wave1.append(CreateNukeTitanEvent(< 3562.689941 , 597.062988 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateNukeTitanEvent(< 2007.030029 , -57.000000 , 243.468994 >,< -0.000000 , -157.455994 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateNukeTitanEvent(< 3562.689941 , 597.062988 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.2999954,index++))
+ wave1.append(CreateDroppodStalkerEvent(< -3328.030029 , 1423.030029 , 327.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0999985,index++))
+ wave1.append(CreateDroppodGruntEvent(< -3224.000000 , 1101.719971 , 327.562988 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.5,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3637.560059 , 571.968994 , 151.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodStalkerEvent(< -3218.719971 , -1766.530029 , 391.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateNukeTitanEvent(< 1989.280029 , -64.187500 , 243.438004 >,< -0.000000 , -158.511002 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateSuperSpectreEvent(< 2611.629883 , 78.937500 , 197.813004 >,< 0.000000 , -168.794006 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< -3218.719971 , -1766.530029 , 391.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3637.560059 , 571.968994 , 151.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< -991.843994 , 411.093994 , 254.656006 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0,index++))
+ wave1.append(CreateDroppodStalkerEvent(< -3328.030029 , 1423.030029 , 327.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0999908,index++))
+ wave1.append(CreateDroppodStalkerEvent(< -3218.719971 , -1766.530029 , 391.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(2.800003,index++))
+ wave1.append(CreateDroppodStalkerEvent(< 2117.560059 , 1491.969971 , 21.625000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.3999939,index++))
+ wave1.append(CreateDroppodGruntEvent(< -2995.780029 , -1754.030029 , 391.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< -2442.189941 , -522.093994 , 391.562988 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3349.560059 , -12.031300 , 161.313004 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< -2240.590088 , -572.375000 , 357.218994 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< -2442.189941 , -522.093994 , 391.562988 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3637.560059 , 571.968994 , 151.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.5,index++))
+ wave1.append(CreateDroppodGruntEvent(< -2240.590088 , -572.375000 , 357.218994 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.2000122,index++))
+ wave1.append(CreateDroppodGruntEvent(< -2228.689941 , 278.750000 , 324.625000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave1.append(CreateDroppodGruntEvent(< 2117.560059 , 1491.969971 , 21.625000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodStalkerEvent(< -3328.030029 , 1423.030029 , 327.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave1.append(CreateDroppodStalkerEvent(< -3218.719971 , -1766.530029 , 391.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave1.append(CreateDroppodStalkerEvent(< -2442.189941 , -522.093994 , 391.562988 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(2.8339844,index++))
+ wave1.append(CreateDroppodGruntEvent(< 3349.560059 , -12.031300 , 161.313004 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.0830078,index++))
+ wave1.append(CreateDroppodGruntEvent(< -2240.590088 , -572.375000 , 357.218994 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< -2442.189941 , -522.093994 , 391.562988 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.7669983,index++))
+ wave1.append(CreateNukeTitanEvent(< 3562.689941 , 597.062988 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.1999817,index++))
+ wave1.append(CreateNukeTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.3170166,index++))
+ wave1.append(CreateDroppodGruntEvent(< -3328.030029 , 1423.030029 , 327.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(0.7999878,index++))
+ wave1.append(CreateDroppodGruntEvent(< -3218.719971 , -1766.530029 , 391.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< 2117.560059 , 1491.969971 , 21.625000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(2.0,index++))
+ wave1.append(CreateDroppodGruntEvent(< -1274.589966 , 1488.410034 , 271.593994 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(2.5,index++))
+ wave1.append(CreateDroppodGruntEvent(< -996.187988 , -1501.560059 , 255.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.3999939,index++))
+ wave1.append(CreateDroppodGruntEvent(< -1252.689941 , -1680.530029 , 255.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(1.7669983,index++))
+ wave1.append(CreateDroppodGruntEvent(< -1589.910034 , 1445.589966 , 271.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateDroppodGruntEvent(< -996.187988 , -1501.560059 , 255.500000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateNukeTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateSuperSpectreEvent(< 1823.390015 , -62.063999 , 229.139999 >,< -0.000000 , -178.341995 , 0.000000 >,"",index++))
+ wave1.append(CreateWaitForTimeEvent(5.0,index++))
+ wave1.append(CreateWaitUntilAliveEvent(0,index++))
+ wave1.append(CreateNukeTitanEvent(< 2072.510010 , -114.669998 , 240.608994 >,< 0.000000 , -2.153320 , 0.000000 >,"",0))
+ waveEvents.append(wave1)
+ index = 1
+ array<WaveEvent> wave2
+ wave2.append(CreateDroppodGruntEvent(< -3328.030029 , 1423.030029 , 327.500000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(2.0,index++))
+ wave2.append(CreateDroppodGruntEvent(< -3224.000000 , 1101.719971 , 327.562988 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave2.append(CreateDroppodStalkerEvent(< -3104.379883 , 1348.000000 , 327.500000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.9169922,index++))
+ wave2.append(CreateDroppodStalkerEvent(< -3218.719971 , -1766.530029 , 391.500000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveEvent(0,index++))
+ wave2.append(CreateScorchTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveEvent(0,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2337.030029 , -69.686699 , 226.059998 >,< -0.000000 , -179.475006 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.3170166,index++))
+ wave2.append(CreateSuperSpectreEvent(< 41.778801 , 1492.930054 , 207.095001 >,< -0.000000 , -107.139999 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.3330078,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1897.969971 , 3546.590088 , 11.343800 >,< -0.000000 , -97.514702 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.5830078,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2715.909912 , 2444.469971 , 287.549011 >,< -0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8170166,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1463.780029 , 1324.219971 , 131.906006 >,< -0.000000 , -139.350998 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.75,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1463.060059 , 797.065979 , 169.285995 >,< -0.000000 , 167.210999 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8329468,index++))
+ wave2.append(CreateSuperSpectreEvent(< 936.437988 , 2916.439941 , 45.218800 >,< 0.000000 , -98.833000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.6340332,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1320.030029 , 3197.560059 , 20.562500 >,< 0.000000 , -170.464005 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.9500122,index++))
+ wave2.append(CreateScorchTitanEvent(< 1403.640015 , 6.090660 , 248.841995 >,< -0.000000 , 154.104996 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(2.3330078,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1887.949951 , 2189.469971 , 8.031250 >,< -0.000000 , -178.822998 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveEvent(0,index++))
+ wave2.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.53302,index++))
+ wave2.append(CreateSuperSpectreEvent(< 158.718994 , 1828.060059 , 205.938004 >,< 0.000000 , -112.807999 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.56695557,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1455.800049 , 791.848999 , 172.475998 >,< -0.000000 , 166.639999 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8170166,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2348.000000 , -132.188004 , 234.906006 >,< -0.000000 , 166.641006 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(2.1000366,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1475.770020 , 1334.510010 , 127.028000 >,< 0.000000 , -139.307007 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.6159668,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2163.419922 , 1372.069946 , 38.044701 >,< -0.000000 , -165.878006 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.7000122,index++))
+ wave2.append(CreateArcTitanEvent(< 3600.000000 , 21.718800 , 194.000000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.5839844,index++))
+ wave2.append(CreateSuperSpectreEvent(< 889.906006 , 2926.129883 , 50.593800 >,< -0.000000 , -93.427696 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8829956,index++))
+ wave2.append(CreateScorchTitanEvent(< 3146.129883 , 42.906300 , 172.250000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.5170288,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2071.060059 , 2108.060059 , 8.031250 >,< 0.000000 , -160.093002 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(3.065979,index++))
+ wave2.append(CreateArcTitanEvent(< 1324.250000 , 43.000000 , 256.625000 >,< -0.000000 , 154.600006 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.21698,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1455.780029 , 792.064026 , 172.410004 >,< -0.000000 , 166.639008 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave2.append(CreateSuperSpectreEvent(< 153.862000 , 1829.819946 , 206.039993 >,< -0.000000 , -112.330002 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.23297119,index++))
+ wave2.append(CreateScorchTitanEvent(< 2474.560059 , 1404.660034 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.5170288,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1576.560059 , -228.938004 , 236.343994 >,< -0.000000 , -173.188004 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.75,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1478.390015 , 1336.760010 , 125.976997 >,< 0.000000 , -139.307007 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(2.7000122,index++))
+ wave2.append(CreateArcTitanEvent(< 1272.239990 , 68.484001 , 256.885986 >,< -0.000000 , 154.994003 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8999634,index++))
+ wave2.append(CreateSuperSpectreEvent(< 889.038025 , 2913.489990 , 50.996201 >,< -0.000000 , -93.384903 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.5830078,index++))
+ wave2.append(CreateScorchTitanEvent(< 1209.160034 , 96.343803 , 256.281006 >,< -0.000000 , 154.688004 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.4500122,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2054.219971 , 2189.840088 , 8.031250 >,< 0.000000 , -178.550003 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.8170166,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1611.719971 , -210.145996 , 235.520004 >,< 0.000000 , -141.108002 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.2999878,index++))
+ wave2.append(CreateSuperSpectreEvent(< 150.729996 , 1828.010010 , 206.033005 >,< 0.000000 , -112.105003 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(3.3170166,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2517.409912 , 274.963013 , 213.567001 >,< 0.000000 , -150.468994 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(5.0,index++))
+ wave2.append(CreateWaitUntilAliveEvent(0,index++))
+ wave2.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.0999756,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2351.110107 , -69.093002 , 225.748001 >,< -0.000000 , -179.738007 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.3000488,index++))
+ wave2.append(CreateSuperSpectreEvent(< 153.097000 , 1827.900024 , 206.031998 >,< 0.000000 , -112.323997 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(3.1170044,index++))
+ wave2.append(CreateSuperSpectreEvent(< 3145.469971 , 43.000000 , 169.281006 >,< -0.000000 , -180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.56695557,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2774.689941 , 1398.219971 , 69.062500 >,< -0.000000 , 17.050800 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.03302,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1480.160034 , 1338.219971 , 125.280998 >,< 0.000000 , -139.350998 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.08300781,index++))
+ wave2.append(CreateScorchTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.9840088,index++))
+ wave2.append(CreateNukeTitanEvent(< 2775.560059 , 220.063004 , 174.468994 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.39996338,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1897.969971 , 3546.590088 , 11.343800 >,< 0.000000 , -97.514603 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.81604004,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2715.909912 , 2444.469971 , 264.968994 >,< -0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(1.93396,index++))
+ wave2.append(CreateArcTitanEvent(< 1344.760010 , 33.344200 , 256.279999 >,< -0.000000 , 154.438995 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.46600342,index++))
+ wave2.append(CreateSuperSpectreEvent(< 938.549988 , -22.322100 , 250.496002 >,< -0.000000 , 135.744995 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.4500122,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1322.630005 , 3196.280029 , 19.882500 >,< 0.000000 , -173.231995 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(0.6500244,index++))
+ wave2.append(CreateSuperSpectreEvent(< 2501.810059 , -40.656300 , 215.906006 >,< -0.000000 , 179.735992 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(2.8169556,index++))
+ wave2.append(CreateSuperSpectreEvent(< 1895.780029 , 2189.280029 , 8.031250 >,< -0.000000 , -179.473007 , 0.000000 >,"",index++))
+ wave2.append(CreateWaitForTimeEvent(3.4170532,index++))
+ wave2.append(CreateScorchTitanEvent(< 1701.880005 , -121.780998 , 227.375000 >,< -0.000000 , -13.095700 , 0.000000 >,"",0))
+ waveEvents.append(wave2)
+ index = 1
+ array<WaveEvent> wave3
+ wave3.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.8170166,index++))
+ wave3.append(CreateArcTitanEvent(< 1904.310059 , 3554.219971 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.3829956,index++))
+ wave3.append(CreateArcTitanEvent(< 2474.689941 , 1404.589966 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.0,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3637.560059 , 571.968994 , 151.500000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.0830078,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3349.560059 , -12.031300 , 161.313004 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.8170166,index++))
+ wave3.append(CreateDroppodStalkerEvent(< 2117.560059 , 1491.969971 , 21.625000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave3.append(CreateDroppodStalkerEvent(< 2221.560059 , -196.031006 , 250.625000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(3.1170044,index++))
+ wave3.append(CreateDroppodGruntEvent(< 2677.560059 , 1907.969971 , 53.250000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(2.5499878,index++))
+ wave3.append(CreateArcTitanEvent(< 1323.239990 , 43.979000 , 256.675995 >,< -0.000000 , 174.664993 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveEvent(0,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3637.560059 , 571.968994 , 151.500000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.6170044,index++))
+ wave3.append(CreateDroppodGruntEvent(< 3349.560059 , -12.031300 , 161.313004 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.1329956,index++))
+ wave3.append(CreateDroppodStalkerEvent(< 2117.560059 , 1491.969971 , 21.625000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.6669922,index++))
+ wave3.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.2000122,index++))
+ wave3.append(CreateToneSniperTitanEvent(< 3599.439941 , 21.687500 , 193.781006 >,< 0.000000 , 180.000000 , 0.000000 >,index++))
+ wave3.append(CreateWaitForTimeEvent(5.017029,index++))
+ wave3.append(CreateSuperSpectreEvent(< 3145.469971 , 43.000000 , 419.500000 >,< -0.000000 , -180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.3659668,index++))
+ wave3.append(CreateToneTitanEvent(< 2474.090088 , 1404.560059 , 63.500000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.23400879,index++))
+ wave3.append(CreateSuperSpectreEvent(< 1904.189941 , 3540.340088 , 11.500000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.5,index++))
+ wave3.append(CreateToneTitanEvent(< 2695.500000 , 3543.280029 , 30.843800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave3.append(CreateSuperSpectreEvent(< 2276.209961 , -301.247009 , 255.914001 >,< -0.000000 , 123.747002 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.2000122,index++))
+ wave3.append(CreateSuperSpectreEvent(< 1281.839966 , 3074.530029 , 14.156300 >,< -0.000000 , -166.376999 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.6999512,index++))
+ wave3.append(CreateSuperSpectreEvent(< 1002.700012 , -84.696800 , 254.085007 >,< 0.000000 , 135.615005 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.3330078,index++))
+ wave3.append(CreateArcTitanEvent(< 1407.380005 , 4.218750 , 249.938004 >,< 0.000000 , 154.072006 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.117004395,index++))
+ wave3.append(CreateSuperSpectreEvent(< 422.968994 , 2117.439941 , 153.593994 >,< -0.000000 , -152.798004 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.6160278,index++))
+ wave3.append(CreateToneSniperTitanEvent(< 1608.089966 , -689.601013 , 258.437988 >,< -0.000000 , -164.445999 , 0.000000 >,index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveEvent(0,index++))
+ wave3.append(CreateToneTitanEvent(< 3599.439941 , 21.687500 , 193.781006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.8999634,index++))
+ wave3.append(CreateNukeTitanEvent(< 3562.689941 , 597.062988 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.3829956,index++))
+ wave3.append(CreateNukeTitanEvent(< 1904.250000 , 3554.129883 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.184021,index++))
+ wave3.append(CreateNukeTitanEvent(< 3146.129883 , 42.906300 , 172.250000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave3.append(CreateToneSniperTitanEvent(< 2645.750000 , -114.375000 , 234.563004 >,< 0.000000 , 180.000000 , 0.000000 >,index++))
+ wave3.append(CreateWaitForTimeEvent(1.4330444,index++))
+ wave3.append(CreateSpawnDroneEvent(< 3503.659912 , 11.184200 , 463.877014 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.6669922,index++))
+ wave3.append(CreateDroppodStalkerEvent(< -991.843994 , 411.093994 , 254.656006 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveEvent(0,index++))
+ wave3.append(CreateSuperSpectreEvent(< 3325.479980 , 201.667007 , 179.955002 >,< -0.000000 , -158.610992 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.8670044,index++))
+ wave3.append(CreateSuperSpectreEvent(< 1677.130005 , 3349.620117 , 18.890200 >,< 0.000000 , -153.281006 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.217041,index++))
+ wave3.append(CreateSpawnDroneEvent(< 191.919998 , -1930.219971 , 6534.589844 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.315979,index++))
+ wave3.append(CreateSpawnDroneEvent(< 478.014008 , -2108.659912 , 6535.350098 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave3.append(CreateArcTitanEvent(< 2474.689941 , 1404.589966 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.2669678,index++))
+ wave3.append(CreateToneTitanEvent(< 3562.219971 , 596.968994 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.8330078,index++))
+ wave3.append(CreateToneTitanEvent(< 1904.339966 , 3553.659912 , 13.750000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.1669922,index++))
+ wave3.append(CreateToneTitanEvent(< 3599.439941 , 21.687500 , 193.781006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.1329956,index++))
+ wave3.append(CreateScorchTitanEvent(< 1580.530029 , 3133.030029 , 12.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.0840454,index++))
+ wave3.append(CreateScorchTitanEvent(< 3146.129883 , 42.906300 , 172.250000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.782959,index++))
+ wave3.append(CreateScorchTitanEvent(< 2646.219971 , -114.280998 , 234.438004 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.1500244,index++))
+ wave3.append(CreateNukeTitanEvent(< 2368.409912 , 2199.159912 , 11.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.2669678,index++))
+ wave3.append(CreateNukeTitanEvent(< 3321.590088 , 3089.659912 , 53.437500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.0,index++))
+ wave3.append(CreateNukeTitanEvent(< 2474.560059 , 1404.660034 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveEvent(0,index++))
+ wave3.append(CreateArcTitanEvent(< 1904.310059 , 3554.219971 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(0.79992676,index++))
+ wave3.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.0999756,index++))
+ wave3.append(CreateArcTitanEvent(< 1580.630005 , 3133.000000 , 12.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.3000488,index++))
+ wave3.append(CreateArcTitanEvent(< 2695.469971 , 3543.840088 , 31.062500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.4000244,index++))
+ wave3.append(CreateArcTitanEvent(< 2730.000000 , 2866.090088 , 13.093800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(1.2999268,index++))
+ wave3.append(CreateArcTitanEvent(< 991.500000 , 3212.439941 , 79.531303 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave3.append(CreateWaitForTimeEvent(5.0,index++))
+ wave3.append(CreateWaitUntilAliveEvent(0,index++))
+ wave3.append(CreateArcTitanEvent(< 2716.030029 , 2445.219971 , 17.687500 >,< 0.000000 , -90.000000 , 0.000000 >,"",0))
+ waveEvents.append(wave3)
+ index = 1
+ array<WaveEvent> wave4
+ wave4.append(CreateSpawnDroneEvent(< 102.452003 , -2172.350098 , 6554.939941 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.2000732,index++))
+ wave4.append(CreateSpawnDroneEvent(< -445.360992 , 2927.620117 , 6683.160156 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveEvent(0,index++))
+ wave4.append(CreateSpawnDroneEvent(< 70.420502 , -2144.540039 , 6547.779785 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.4000244,index++))
+ wave4.append(CreateSpawnDroneEvent(< 191.919998 , -1930.219971 , 6563.669922 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.5,index++))
+ wave4.append(CreateSpawnDroneEvent(< -417.548004 , 2959.649902 , 6676.850098 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveEvent(0,index++))
+ wave4.append(CreateSpawnDroneEvent(< 74.639198 , -2204.379883 , 6556.439941 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.8000488,index++))
+ wave4.append(CreateScorchTitanEvent(< 3562.689941 , 597.062988 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1999512,index++))
+ wave4.append(CreateSpawnDroneEvent(< 3523.969971 , 589.687988 , 463.968994 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.5,index++))
+ wave4.append(CreateScorchTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave4.append(CreateScorchTitanEvent(< 3146.129883 , 42.906300 , 172.250000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave4.append(CreateArcTitanEvent(< 2474.689941 , 1404.589966 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.89990234,index++))
+ wave4.append(CreateDroppodStalkerEvent(< -3218.719971 , -1766.530029 , 391.500000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.2000732,index++))
+ wave4.append(CreateDroppodStalkerEvent(< -3328.030029 , 1423.030029 , 327.500000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(2.9000244,index++))
+ wave4.append(CreateScorchTitanEvent(< 2695.409912 , 3543.750000 , 31.031300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave4.append(CreateScorchTitanEvent(< 1930.030029 , 3156.879883 , 11.156300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.79992676,index++))
+ wave4.append(CreateSuperSpectreEvent(< 2485.379883 , 2253.969971 , 8.031250 >,< 0.000000 , -151.039993 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.20007324,index++))
+ wave4.append(CreateScorchTitanEvent(< 1585.530029 , 3552.379883 , 53.968800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave4.append(CreateSuperSpectreEvent(< 3107.750000 , 2873.530029 , 11.531300 >,< -0.000000 , -114.477997 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.5,index++))
+ wave4.append(CreateArcTitanEvent(< 3171.560059 , 608.468994 , 150.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave4.append(CreateArcTitanEvent(< 1700.560059 , 1538.380005 , 21.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveEvent(0,index++))
+ wave4.append(CreateArcTitanEvent(< 2474.689941 , 1404.589966 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveEvent(0,index++))
+ wave4.append(CreateSuperSpectreEvent(< 3266.909912 , 586.875000 , 161.000000 >,< 0.000000 , -169.102005 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.2999268,index++))
+ wave4.append(CreateSuperSpectreEvent(< 3319.340088 , 120.438004 , 158.375000 >,< -0.000000 , 179.209000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveEvent(0,index++))
+ wave4.append(CreateSuperSpectreEvent(< 2479.770020 , 2250.840088 , 8.031250 >,< 0.000000 , -151.039993 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave4.append(CreateSuperSpectreEvent(< 1670.160034 , 3346.110107 , 18.495300 >,< 0.000000 , -153.237000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.5,index++))
+ wave4.append(CreateNukeTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.6999512,index++))
+ wave4.append(CreateSuperSpectreEvent(< 3104.560059 , 2874.250000 , 11.468800 >,< -0.000000 , -119.355003 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.70007324,index++))
+ wave4.append(CreateSuperSpectreEvent(< 1285.500000 , 3074.939941 , 13.343800 >,< -0.000000 , -166.641006 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.2999268,index++))
+ wave4.append(CreateSuperSpectreEvent(< 2612.909912 , 3263.360107 , 8.372550 >,< 0.000000 , -93.867203 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.5,index++))
+ wave4.append(CreateSpawnDroneEvent(< 3436.909912 , 101.063004 , 463.968994 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.4000244,index++))
+ wave4.append(CreateScorchTitanEvent(< 1904.250000 , 3554.129883 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.5,index++))
+ wave4.append(CreateScorchTitanEvent(< 2715.969971 , 2445.129883 , 17.687500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.6999512,index++))
+ wave4.append(CreateScorchTitanEvent(< 1580.530029 , 3133.030029 , 12.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.60009766,index++))
+ wave4.append(CreateToneSniperTitanEvent(< 2695.500000 , 3543.280029 , 30.843800 >,< 0.000000 , -90.000000 , 0.000000 >,index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveEvent(0,index++))
+ wave4.append(CreateArcTitanEvent(< 991.500000 , 3212.439941 , 79.531303 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1000977,index++))
+ wave4.append(CreateSpawnDroneEvent(< 74.639198 , -2204.379883 , 6556.759766 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1999512,index++))
+ wave4.append(CreateSpawnDroneEvent(< -417.548004 , 2959.649902 , 6681.479980 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveEvent(0,index++))
+ wave4.append(CreateSpawnDroneEvent(< 74.639198 , -2204.379883 , 6554.790039 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.2000732,index++))
+ wave4.append(CreateSpawnDroneEvent(< 164.108002 , -1962.290039 , 6565.899902 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.2999268,index++))
+ wave4.append(CreateSpawnDroneEvent(< -417.548004 , 2959.649902 , 6676.520020 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(5.0,index++))
+ wave4.append(CreateWaitUntilAliveEvent(0,index++))
+ wave4.append(CreateSpawnDroneEvent(< 74.639198 , -2204.379883 , 6552.459961 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave4.append(CreateArcTitanEvent(< 2716.030029 , 2445.219971 , 17.687500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.5,index++))
+ wave4.append(CreateArcTitanEvent(< 3321.659912 , 3089.750000 , 53.437500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.0,index++))
+ wave4.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.6999512,index++))
+ wave4.append(CreateArcTitanEvent(< 3600.000000 , 21.718800 , 194.000000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave4.append(CreateArcTitanEvent(< 1904.310059 , 3554.219971 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.1999512,index++))
+ wave4.append(CreateArcTitanEvent(< 2695.469971 , 3543.840088 , 31.062500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave4.append(CreateWaitForTimeEvent(1.0999756,index++))
+ wave4.append(CreateArcTitanEvent(< 1580.630005 , 3133.000000 , 12.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",0))
+ waveEvents.append(wave4)
+ index = 1
+ array<WaveEvent> wave5
+ wave5.append(CreateToneSniperTitanEvent(< 3599.439941 , 21.687500 , 193.781006 >,< 0.000000 , 180.000000 , 0.000000 >,index++))
+ wave5.append(CreateWaitForTimeEvent(0.5800781,index++))
+ wave5.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4000244,index++))
+ wave5.append(CreateArcTitanEvent(< 3146.219971 , 42.875000 , 172.218994 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.82995605,index++))
+ wave5.append(CreateArcTitanEvent(< 1904.310059 , 3554.219971 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0,index++))
+ wave5.append(CreateToneTitanEvent(< 2645.750000 , -114.375000 , 234.563004 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.5699463,index++))
+ wave5.append(CreateToneTitanEvent(< 1580.060059 , 3132.939941 , 12.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.95007324,index++))
+ wave5.append(CreateNukeTitanEvent(< 2474.560059 , 1404.660034 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3699951,index++))
+ wave5.append(CreateNukeTitanEvent(< 2368.409912 , 2199.159912 , 11.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave5.append(CreateNukeTitanEvent(< 3321.590088 , 3089.659912 , 53.437500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0,index++))
+ wave5.append(CreateNukeTitanEvent(< 2695.409912 , 3543.750000 , 31.031300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.079956,index++))
+ wave5.append(CreateNukeTitanEvent(< 3608.689941 , 324.875000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1500244,index++))
+ wave5.append(CreateNukeTitanEvent(< 991.468994 , 3212.340088 , 79.500000 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.2700195,index++))
+ wave5.append(CreateSpawnDroneEvent(< 102.452003 , -2172.350098 , 6532.419922 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.60998535,index++))
+ wave5.append(CreateSpawnDroneEvent(< 196.169998 , -1990.069946 , 6516.410156 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.2999268,index++))
+ wave5.append(CreateSpawnDroneEvent(< -417.548004 , 2959.649902 , 6638.049805 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1000977,index++))
+ wave5.append(CreateSpawnDroneEvent(< -355.891998 , 3169.709961 , 6646.209961 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(3.8999023,index++))
+ wave5.append(CreateSpawnDroneEvent(< 102.452003 , -2172.350098 , 6502.850098 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveEvent(0,index++))
+ wave5.append(CreateSpawnDroneEvent(< 74.639198 , -2204.379883 , 6526.680176 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.72998047,index++))
+ wave5.append(CreateNukeTitanEvent(< 3562.689941 , 597.062988 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.97998047,index++))
+ wave5.append(CreateNukeTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.420044,index++))
+ wave5.append(CreateNukeTitanEvent(< 3146.129883 , 42.906300 , 172.250000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.880005,index++))
+ wave5.append(CreateToneTitanEvent(< 2645.750000 , -114.375000 , 234.563004 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave5.append(CreateSpawnDroneEvent(< 3496.929932 , 95.000397 , 463.927002 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.8000488,index++))
+ wave5.append(CreateNukeTitanEvent(< 3171.469971 , 608.500000 , 150.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.9000244,index++))
+ wave5.append(CreateNukeTitanEvent(< 3608.689941 , 324.875000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1199951,index++))
+ wave5.append(CreateNukeTitanEvent(< 2474.560059 , 1404.660034 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.79992676,index++))
+ wave5.append(CreateToneTitanEvent(< 2367.909912 , 2199.060059 , 11.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.5,index++))
+ wave5.append(CreateSpawnDroneEvent(< 191.919998 , -1930.219971 , 6518.930176 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0999756,index++))
+ wave5.append(CreateSpawnDroneEvent(< 478.014008 , -2108.659912 , 6532.169922 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.2800293,index++))
+ wave5.append(CreateSpawnDroneEvent(< 70.420502 , -2144.540039 , 6517.500000 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4899902,index++))
+ wave5.append(CreateSpawnDroneEvent(< 3466.889893 , 69.121399 , 591.948975 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.5999756,index++))
+ wave5.append(CreateSpawnDroneEvent(< -323.829987 , 3141.929932 , 6701.140137 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveEvent(0,index++))
+ wave5.append(CreateSpawnDroneEvent(< 196.169998 , -1990.069946 , 6509.910156 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1600342,index++))
+ wave5.append(CreateSpawnDroneEvent(< 445.983002 , -2080.850098 , 6576.009766 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4499512,index++))
+ wave5.append(CreateNukeTitanEvent(< 2474.560059 , 1404.660034 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3699951,index++))
+ wave5.append(CreateNukeTitanEvent(< 3171.469971 , 608.500000 , 150.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3200684,index++))
+ wave5.append(CreateNukeTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1799316,index++))
+ wave5.append(CreateNukeTitanEvent(< 3146.129883 , 42.906300 , 172.250000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3300781,index++))
+ wave5.append(CreateNukeTitanEvent(< 2646.219971 , -114.280998 , 234.438004 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4499512,index++))
+ wave5.append(CreateNukeTitanEvent(< 2368.409912 , 2199.159912 , 11.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.8399658,index++))
+ wave5.append(CreateSpawnDroneEvent(< 2550.909912 , 1338.000000 , 392.437988 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1600342,index++))
+ wave5.append(CreateSpawnDroneEvent(< 2652.000000 , 1237.910034 , 520.499023 >,< 0.000000 , 0.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0200195,index++))
+ wave5.append(CreateArcTitanEvent(< 3321.659912 , 3089.750000 , 53.437500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1999512,index++))
+ wave5.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4000244,index++))
+ wave5.append(CreateArcTitanEvent(< 2474.689941 , 1404.589966 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.8000488,index++))
+ wave5.append(CreateNukeTitanEvent(< 1904.250000 , 3554.129883 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.3800049,index++))
+ wave5.append(CreateNukeTitanEvent(< 1580.530029 , 3133.030029 , 12.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.73999023,index++))
+ wave5.append(CreateNukeTitanEvent(< 2729.939941 , 2866.000000 , 13.093800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.89990234,index++))
+ wave5.append(CreateSpawnDroneEvent(< 102.452003 , -2172.350098 , 6507.430176 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.5600586,index++))
+ wave5.append(CreateSpawnDroneEvent(< 164.108002 , -1962.290039 , 6557.959961 >,< 0.004999 , -175.953003 , 0.000004 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveEvent(0,index++))
+ wave5.append(CreateNukeTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.8000488,index++))
+ wave5.append(CreateNukeTitanEvent(< 3146.129883 , 42.906300 , 172.250000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1199951,index++))
+ wave5.append(CreateNukeTitanEvent(< 3562.689941 , 597.062988 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1600342,index++))
+ wave5.append(CreateNukeTitanEvent(< 2646.219971 , -114.280998 , 234.438004 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1999512,index++))
+ wave5.append(CreateNukeTitanEvent(< 1904.250000 , 3554.129883 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.2199707,index++))
+ wave5.append(CreateNukeTitanEvent(< 2715.969971 , 2445.129883 , 17.687500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.60009766,index++))
+ wave5.append(CreateToneTitanEvent(< 2474.090088 , 1404.560059 , 63.500000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.5,index++))
+ wave5.append(CreateNukeTitanEvent(< 1580.530029 , 3133.030029 , 12.375000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.57995605,index++))
+ wave5.append(CreateNukeTitanEvent(< 2695.409912 , 3543.750000 , 31.031300 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.420044,index++))
+ wave5.append(CreateNukeTitanEvent(< 3321.590088 , 3089.659912 , 53.437500 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1199951,index++))
+ wave5.append(CreateNukeTitanEvent(< 3599.909912 , 21.781300 , 193.906006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.95996094,index++))
+ wave5.append(CreateNukeTitanEvent(< 1700.469971 , 1538.439941 , 21.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveEvent(0,index++))
+ wave5.append(CreateNukeTitanEvent(< 2474.560059 , 1404.660034 , 63.562500 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0300293,index++))
+ wave5.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.1699219,index++))
+ wave5.append(CreateArcTitanEvent(< 3600.000000 , 21.718800 , 194.000000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0200195,index++))
+ wave5.append(CreateArcTitanEvent(< 1904.310059 , 3554.219971 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0,index++))
+ wave5.append(CreateNukeTitanEvent(< 3146.129883 , 42.906300 , 172.250000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.8100586,index++))
+ wave5.append(CreateNukeTitanEvent(< 2646.219971 , -114.280998 , 234.438004 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4899902,index++))
+ wave5.append(CreateNukeTitanEvent(< 2368.409912 , 2199.159912 , 11.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveEvent(0,index++))
+ wave5.append(CreateArcTitanEvent(< 3562.780029 , 597.000000 , 147.031006 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.7800293,index++))
+ wave5.append(CreateArcTitanEvent(< 3600.000000 , 21.718800 , 194.000000 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0200195,index++))
+ wave5.append(CreateArcTitanEvent(< 3146.219971 , 42.875000 , 172.218994 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0,index++))
+ wave5.append(CreateArcTitanEvent(< 1904.310059 , 3554.219971 , 13.718800 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.67993164,index++))
+ wave5.append(CreateScorchTitanEvent(< 255.968994 , 2110.750000 , 184.938004 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0300293,index++))
+ wave5.append(CreateScorchTitanEvent(< 1700.469971 , 1538.439941 , 21.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(5.0,index++))
+ wave5.append(CreateWaitUntilAliveEvent(0,index++))
+ wave5.append(CreateScorchTitanEvent(< 255.968994 , 2110.750000 , 184.938004 >,< 0.000000 , -90.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(0.70007324,index++))
+ wave5.append(CreateNukeTitanEvent(< 1762.500000 , 758.437988 , 143.593994 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.0,index++))
+ wave5.append(CreateNukeTitanEvent(< 2646.219971 , -114.280998 , 234.438004 >,< 0.000000 , 180.000000 , 0.000000 >,"",index++))
+ wave5.append(CreateWaitForTimeEvent(1.4000244,index++))
+ wave5.append(CreateNukeTitanEvent(< 1700.469971 , 1538.439941 , 21.031300 >,< 0.000000 , 180.000000 , 0.000000 >,"",0))
+ waveEvents.append(wave5)
+
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw.nut
index 37b89169..e6eb493d 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw.nut
@@ -1 +1,8 @@
-//fuck \ No newline at end of file
+global function CodeCallback_MapInit
+
+void function CodeCallback_MapInit()
+{
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_thaw_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut
index 8d859ba6..d0ce4f79 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames.nut
@@ -29,8 +29,13 @@ void function CodeCallback_MapInit()
// currently disabled until finished: intro
if ( !IsFFAGame() )
ClassicMP_SetLevelIntro( WargamesIntroSetup, 20.0 )
+
+ // Load Frontier Defense Data
+ if( GameRules_GetGameMode() == "fd" )
+ initFrontierDefenseData()
}
+
void function AddEvacNodes()
{
AddEvacNode( GetEnt( "evac_location1" ) )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames_fd.nut
index 37b89169..cd3e2822 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_wargames_fd.nut
@@ -1 +1,23 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+void function initFrontierDefenseData()
+{
+ shopPosition = <0,0,0>
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+
+
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut b/Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut
index 78cfdb27..153be7cd 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/rodeo/_rodeo_titan.gnut
@@ -27,6 +27,7 @@ global function Rodeo_PilotPicksUpBattery_Silent
global function AddOnRodeoStartedCallback
global function AddOnRodeoEndedCallback
+global function AddBatteryHealCallback
global function PilotBattery_SetMaxCount
global function ThrowRiderOff
@@ -92,6 +93,7 @@ struct
{
array<void functionref(entity,entity)> onRodeoEndedCallbacks
array<void functionref(entity,entity)> onRodeoStartedCallbacks
+ array<void functionref(entity,entity,int,int)> batteryHealCallbacks
table<entity, AntiRodeoPlayerData> antiRodeoPlayerData
@@ -535,6 +537,12 @@ void function AddOnRodeoEndedCallback( void functionref(entity,entity) callbackF
file.onRodeoEndedCallbacks.append( callbackFunc )
}
+void function AddBatteryHealCallback( void functionref(entity,entity,int,int) callbackFunc )
+{
+ Assert (!( file.batteryHealCallbacks.contains( callbackFunc ) ))
+ file.batteryHealCallbacks.append( callbackFunc )
+}
+
function PlayerBeginsTitanRodeo( entity player, RodeoPackageStruct rodeoPackage, entity rodeoTitan )
{
entity soul = rodeoTitan.GetTitanSoul()
@@ -1769,6 +1777,8 @@ void function Rodeo_ApplyBatteryToTitan( entity battery, entity titan )
int addHealth = int( healingAmount * frac )
int totalHealth = minint( titan.GetMaxHealth(), titan.GetHealth() + addHealth )
+ if( titan.GetHealth() + addHealth > titan.GetMaxHealth() )
+ addHealth = titan.GetMaxHealth() - titan.GetHealth()
if ( soul.IsDoomed() && batteryIsAmped )
{
UndoomTitan( titan, 1 )
@@ -1779,6 +1789,11 @@ void function Rodeo_ApplyBatteryToTitan( entity battery, entity titan )
titan.SetHealth( totalHealth )
soul.SetShieldHealth( soul.GetShieldHealthMax() )
}
+
+ foreach ( callbackFunc in file.batteryHealCallbacks )
+ {
+ callbackFunc( battery, titan, shieldDifference, addHealth )
+ }
}
if ( battery != null )
@@ -2456,4 +2471,4 @@ bool function ClientCommand_TryNukeGrenade( entity player, array<string> args )
return true
}
-#endif \ No newline at end of file
+#endif
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/weapons/_cloaker.gnut b/Northstar.CustomServers/mod/scripts/vscripts/weapons/_cloaker.gnut
index 6ec0bc0a..b4045f3e 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/weapons/_cloaker.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/weapons/_cloaker.gnut
@@ -97,6 +97,8 @@ function CloakerThink( entity cloaker, float radius, array<string> ents = [ "any
void function CloakerCloaksGuy( guy )
{
+ if( guy.IsNPC() )
+ guy.SetCanCloak(true) // if you don't want to cloak specific targets, it should be handled by shouldCloakGuyFunc in CloakerThink
guy.SetCloakDuration( 2.0, -1, 0 )
EmitSoundOnEntity( guy, CLOAKED_DRONE_CLOAK_START_SFX )
EmitSoundOnEntity( guy, CLOAKED_DRONE_CLOAK_LOOP_SFX )
@@ -110,6 +112,8 @@ void function CloakerDeCloaksGuy( guy )
StopSoundOnEntity( guy, CLOAKED_DRONE_CLOAK_LOOP_SFX )
guy.Minimap_AlwaysShow( TEAM_IMC, null )
guy.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ if( guy.IsNPC() )
+ guy.SetCanCloak(false)
}
bool function CloakerShouldCloakGuy( entity cloaker, entity guy )
@@ -118,4 +122,4 @@ bool function CloakerShouldCloakGuy( entity cloaker, entity guy )
return false
return true
-} \ No newline at end of file
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/weapons/sh_phase_shift.gnut b/Northstar.CustomServers/mod/scripts/vscripts/weapons/sh_phase_shift.gnut
new file mode 100644
index 00000000..52d07f00
--- /dev/null
+++ b/Northstar.CustomServers/mod/scripts/vscripts/weapons/sh_phase_shift.gnut
@@ -0,0 +1,774 @@
+untyped
+#if CLIENT
+#endif
+
+global function MpAbilityShifter_Init
+global function PhaseShift
+global function CodeCallback_EnterPhaseShift
+global function CodeCallback_ExitPhaseShift
+global function CancelPhaseShift
+
+#if SERVER
+global function PlayPhaseShiftDisappearFX
+global function UntrackAllToneMarks
+#endif
+
+const SHIFTER_OUTRO_TIME_BEFORE_END = 1.5
+
+const SHIFTER_PRE_FX = $"P_warpjump_FP"
+
+const SHIFTER_APPEAR_FX = $"P_phase_shift_main"
+const SHIFTER_APPEAR_FX_TITAN = $"P_phase_shift_main_XO"
+const SHIFTER_DISAPPEAR_FX = $"P_phase_shift_main"
+const SHIFTER_DISAPPEAR_FX_TITAN = $"P_phase_shift_main_XO"
+
+const SHIFTER_SCREEN_FX = $"P_phase_shift_screen"
+const SHIFTER_PERSONAL_FX = $"P_phase_shift_player"
+const SHIFTER_SCREEN_FX_START = $"P_phase_shift_screen_start"
+const SHIFTER_COLORCORRECTION = "materials/correction/mp_ability_shifter.raw"
+
+const SHIFTER_PRE_SOUND_1P = "Pilot_PhaseShift_PreActivate_1P"
+const SHIFTER_PRE_SOUND_3P = "Pilot_PhaseShift_PreActivate_3P"
+global const SHIFTER_START_SOUND_1P = "Pilot_PhaseShift_Activate_1P"
+global const SHIFTER_START_SOUND_3P = "Pilot_PhaseShift_Activate_3P"
+const SHIFTER_LOOP_SOUND_1P = "Pilot_PhaseShift_Loop_1P"
+const SHIFTER_LOOP_SOUND_3P = "Pilot_PhaseShift_Loop_3P"
+const SHIFTER_PRE_END_SOUND_1P = "Pilot_PhaseShift_WarningToEnd_1P"
+const SHIFTER_PRE_END_SOUND_3P = "Pilot_PhaseShift_WarningToEnd_3P"
+global const SHIFTER_END_SOUND_1P = "Pilot_PhaseShift_End_1P"
+global const SHIFTER_END_SOUND_3P = "Pilot_PhaseShift_End_3P"
+
+const SHIFTER_PRE_SOUND_1P_TITAN = "Pilot_PhaseShift_PreActivate_1P"
+const SHIFTER_PRE_SOUND_3P_TITAN = "Pilot_PhaseShift_PreActivate_3P"
+global const SHIFTER_START_SOUND_1P_TITAN = "titan_phasedash_activate_1p"
+global const SHIFTER_START_SOUND_3P_TITAN = "titan_phasedash_activate_3p"
+const SHIFTER_LOOP_SOUND_1P_TITAN = "titan_phasedash_loop_1p"
+const SHIFTER_LOOP_SOUND_3P_TITAN = "titan_phasedash_loop_3p"
+const SHIFTER_PRE_END_SOUND_1P_TITAN = "titan_phasedash_warningtoend_1p"
+const SHIFTER_PRE_END_SOUND_3P_TITAN = "titan_phasedash_warningtoend_3p"
+global const SHIFTER_END_SOUND_1P_TITAN = "titan_phasedash_end_1p"
+global const SHIFTER_END_SOUND_3P_TITAN = "titan_phasedash_end_3p"
+
+const int TELEFRAG_DAMAGE = 5000;
+
+struct
+{
+} file;
+
+void function CodeCallback_EnterPhaseShift( entity ent )
+{
+ PhaseShift( ent, 0.0, 999.0 )
+}
+
+void function CodeCallback_ExitPhaseShift( entity ent )
+{
+#if SERVER
+ CancelPhaseShift( ent )
+#endif
+}
+
+void function CancelPhaseShift( entity ent )
+{
+ ent.PhaseShiftCancel()
+
+#if SERVER
+ ent.Signal( "ForceStopPhaseShift" )
+ PlayPhaseShiftAppearFX( ent )
+#endif //
+}
+
+
+void function MpAbilityShifter_Init()
+{
+#if CLIENT
+ //ColorCorrection_RegisterRemoteTurret( "materials/correction/remote_turret.raw" )
+
+ ColorCorrection_RegisterPhaseShift( SHIFTER_COLORCORRECTION )
+ thread ClientPhaseShiftFirstPersonFXThread()
+
+ thread ClientRemoteTurretFirstPersonFXThread()
+#endif // #if CLIENT
+
+ PrecacheParticleSystem( SHIFTER_PRE_FX )
+ PrecacheParticleSystem( SHIFTER_APPEAR_FX )
+ PrecacheParticleSystem( SHIFTER_APPEAR_FX_TITAN )
+ PrecacheParticleSystem( SHIFTER_DISAPPEAR_FX )
+ PrecacheParticleSystem( SHIFTER_DISAPPEAR_FX_TITAN )
+ PrecacheParticleSystem( SHIFTER_PERSONAL_FX )
+ PrecacheParticleSystem( SHIFTER_SCREEN_FX )
+ PrecacheParticleSystem( SHIFTER_SCREEN_FX_START )
+
+ MpAbilityShifterWeapon_Init()
+
+ RegisterSignal( "StartPhaseShift" )
+ RegisterSignal( "StopPhaseShift" )
+ RegisterSignal( "ForceStopPhaseShift" )
+}
+
+int function PhaseShift( entity ent, float warmupTime, float duration )
+{
+ if ( !IsAlive( ent ) )
+ return 0
+
+ if ( ent.IsPhaseShifted() )
+ return 0
+
+ // PROTO: this should be better eventually
+ // this is to prevent weirdness if you're already in a context action
+ if ( ent.IsPlayer() )
+ {
+ entity proxy = ent.GetFirstPersonProxy()
+ if ( ( ent.ContextAction_IsActive() || (proxy != null && proxy.Anim_IsActive()) )
+ && !ent.IsZiplining()
+ && !ent.ContextAction_IsLeeching()
+ && ent.GetTitanSoulBeingRodeoed() == null )
+ {
+ return 0
+ }
+
+ ent.PhaseShiftBegin( warmupTime, duration )
+
+ #if SERVER
+ thread ServerPhaseShiftPlayerThread( ent, warmupTime, duration )
+ #else
+ thread ClientPhaseShiftWarmupThread( ent, warmupTime )
+ #endif // #if SERVER
+
+ return 1
+ }
+ else
+ {
+ ent.PhaseShiftBegin( warmupTime, duration )
+
+ #if SERVER
+ thread ServerPhaseShiftPlayerThread( ent, warmupTime, duration )
+ #endif // #if SERVER
+
+ return 1
+ }
+
+ unreachable
+}
+
+#if SERVER
+void function ServerPhaseShiftPlayerThread( entity ent, float warmupTime, float shiftTime )
+{
+ ent.EndSignal( "OnDeath" )
+ ent.EndSignal( "ForceStopPhaseShift" )
+
+ // initialise the two ent.s variables if needed
+ if ( !( "oldPhaseStateLock" in ent.s ) || !( "oldPhaseState" in ent.s ) )
+ {
+ ent.s.oldPhaseStateLock <- false
+ ent.s.oldPhaseState <- false
+ }
+
+ bool keepAnimActive = false
+
+ if ( ent.IsPlayer() )
+ {
+ ent.EndSignal( "player_embarks_titan" )
+
+ Leech_Disallow( ent )
+ // EmitSoundOnEntityExceptToPlayer( ent, ent, SHIFTER_PRE_SOUND_3P )
+
+ entity proxy = ent.GetFirstPersonProxy()
+ if ( proxy != null )
+ proxy.SetForceVisibleInPhaseShift( true )
+
+ if ( Rodeo_IsAttached( ent ) )
+ {
+ if ( ent.GetParent() != null && ent.GetParent().IsPhaseShifted() )
+ keepAnimActive = true
+ else
+ ent.Signal( "RodeoOver" )
+ }
+
+ if ( ent.IsTitan() )
+ {
+ UntrackAllToneMarks( ent )
+ entity titanSoul = ent.GetTitanSoul()
+ if ( titanSoul != null )
+ {
+ if ( titanSoul.soul.batteryContainer != null )
+ {
+ titanSoul.soul.batteryContainer.SetForceVisibleInPhaseShift( true )
+ }
+ }
+ }
+
+ Battery_StopFXAndHideIconForPlayer( ent )
+ }
+ else
+ {
+ if ( ent.IsTitan() )
+ UntrackAllToneMarks( ent )
+ ent.EnableNPCFlag( NPC_IGNORE_ALL )
+ EmitSoundOnEntity( ent, SHIFTER_PRE_SOUND_3P )
+ }
+
+ // only change the oldPhaseState if it's not locked
+ if ( !ent.s.oldPhaseStateLock || !GetConVarBool("ns_use_phase_fix") )
+ {
+ ent.s.oldPhaseStateLock <- true
+ ent.s.oldPhaseState <- ent.GetNoTarget()
+ }
+
+ OnThreadEnd(
+ function() : ( ent )
+ {
+ if ( IsValid( ent ) )
+ {
+ ent.Signal( "StopPhaseShift" )
+ ent.Solid()
+ ent.SetNoTarget( ent.s.oldPhaseState )
+ // unlock the oldPhaseState
+ ent.s.oldPhaseStateLock <- false
+
+ StopSoundOnEntity( ent, SHIFTER_PRE_SOUND_3P )
+ StopSoundOnEntity( ent, SHIFTER_LOOP_SOUND_3P )
+ StopSoundOnEntity( ent, SHIFTER_PRE_SOUND_3P_TITAN )
+ StopSoundOnEntity( ent, SHIFTER_LOOP_SOUND_3P_TITAN )
+
+ ent.DisablePhaseShiftFlags()
+
+ if ( ent.IsPlayer() )
+ {
+ Leech_Allow( ent )
+ UpdatePlayerHighlightsSettings( ent )
+
+ if ( GetSoulFromPlayer( ent ) != null )
+ {
+ entity soul = GetSoulFromPlayer( ent )
+ if ( soul.soul.batteryContainer != null )
+ {
+ soul.soul.batteryContainer.SetForceVisibleInPhaseShift( false )
+ }
+ }
+
+ entity proxy = ent.GetFirstPersonProxy()
+ if ( proxy != null )
+ proxy.SetForceVisibleInPhaseShift( false )
+
+ if ( PlayerHasBattery( ent ) )
+ Battery_StartFX( GetBatteryOnBack( ent ) )
+ }
+ else
+ {
+ ent.DisableNPCFlag( NPC_IGNORE_ALL )
+ Highlight_ClearEnemyHighlight( ent )
+ }
+
+ entity teleFragTarget = ent.GetEntityAtPhaseShiftExitPosition();
+ if ( IsValid( teleFragTarget ) )
+ {
+ if ( !IsHumanSized( teleFragTarget ) )
+ {
+ if ( ShouldEntitySelfKill( ent, teleFragTarget ) )
+ {
+ ent.TakeDamage( ent.GetHealth() + 1, teleFragTarget, teleFragTarget, { damageSourceId = eDamageSourceId.phase_shift, scriptType = DF_GIB | DF_BYPASS_SHIELD | DF_SKIPS_DOOMED_STATE } );
+ }
+ else
+ {
+ printt( "Pushed players apart" )
+ PushPlayersApart( teleFragTarget, ent, 600.0 ) // this will work for NPCs too
+ }
+ }
+ else
+ {
+ teleFragTarget.TakeDamage( teleFragTarget.GetHealth() + 1, ent, ent, { damageSourceId = eDamageSourceId.phase_shift, scriptType = DF_GIB | DF_BYPASS_SHIELD | DF_SKIPS_DOOMED_STATE } );
+ }
+ }
+ }
+ }
+ )
+
+ wait warmupTime
+
+ //thread PROTO_CapVelocity( ent )
+
+ entity soul
+ if ( ent.IsTitan() )
+ {
+ soul = ent.GetTitanSoul()
+ string titanType = GetSoulTitanSubClass( soul )
+ entity rider = GetRodeoPilot( ent )
+ if ( rider != null && Rodeo_IsAttached( rider ) )
+ {
+ if ( !rider.IsPlayer() )
+ rider.Signal( "RodeoOver" )
+ else
+ PhaseShift( rider, 0, shiftTime )
+ }
+ }
+
+ entity fx = PlayPhaseShiftDisappearFX( ent )
+ thread PhaseShiftDisappearEffectCleanup( ent, fx, shiftTime )
+
+ ent.Signal( "StartPhaseShift" )
+ if ( !keepAnimActive )
+ ent.Signal( "ScriptAnimStop" )
+ ent.NotSolid()
+ ent.SetNoTarget( true )
+ ent.EnablePhaseShiftFlags()
+ ent.Highlight_SetCurrentContext( -1 )
+
+ if ( ent.IsPlayer() )
+ {
+ PlayerDropsScriptedItems( ent )
+ if ( ent.IsTitan() )
+ {
+ EmitSoundOnEntityExceptToPlayer( ent, ent, SHIFTER_START_SOUND_3P_TITAN )
+ EmitSoundOnEntityExceptToPlayerNotPredicted( ent, ent, SHIFTER_LOOP_SOUND_3P_TITAN )
+ }
+ else
+ {
+ EmitSoundOnEntityExceptToPlayer( ent, ent, SHIFTER_START_SOUND_3P )
+ EmitSoundOnEntityExceptToPlayerNotPredicted( ent, ent, SHIFTER_LOOP_SOUND_3P )
+ }
+
+ foreach( statusEffect in ent.p.empStatusEffectsToClearForPhaseShift ) //Not great, done to avoid needing code work to get a separate empSlow/empSTurnEffects
+ {
+ StatusEffect_Stop( ent, statusEffect )
+ }
+
+ ent.p.empStatusEffectsToClearForPhaseShift.clear()
+ }
+ else
+ {
+ if ( ent.IsTitan() )
+ {
+ EmitSoundOnEntity( ent, SHIFTER_START_SOUND_3P_TITAN )
+ EmitSoundOnEntity( ent, SHIFTER_LOOP_SOUND_3P_TITAN )
+ }
+ else
+ {
+ EmitSoundOnEntity( ent, SHIFTER_START_SOUND_3P )
+ EmitSoundOnEntity( ent, SHIFTER_LOOP_SOUND_3P )
+ }
+ }
+
+ float FX_WARMUP_TIME = 0.3
+ bool timeAdjusted = false
+
+ if ( shiftTime > FX_WARMUP_TIME )
+ {
+ shiftTime -= FX_WARMUP_TIME // need to play the fx a little earlier so the timing lines up
+ timeAdjusted = true
+ }
+
+ if ( shiftTime >= SHIFTER_OUTRO_TIME_BEFORE_END )
+ {
+ wait ( shiftTime - SHIFTER_OUTRO_TIME_BEFORE_END )
+
+ if ( ent.IsPlayer() )
+ {
+ if ( ent.IsTitan() )
+ {
+ EmitSoundOnEntityOnlyToPlayer( ent, ent, SHIFTER_PRE_END_SOUND_1P_TITAN )
+ EmitSoundOnEntityExceptToPlayer( ent, ent, SHIFTER_PRE_END_SOUND_3P_TITAN )
+ }
+ else
+ {
+ EmitSoundOnEntityOnlyToPlayer( ent, ent, SHIFTER_PRE_END_SOUND_1P )
+ EmitSoundOnEntityExceptToPlayer( ent, ent, SHIFTER_PRE_END_SOUND_3P )
+ }
+
+ }
+ else
+ {
+ if ( ent.IsTitan() )
+ EmitSoundOnEntity( ent, SHIFTER_PRE_END_SOUND_3P_TITAN )
+ else
+ EmitSoundOnEntity( ent, SHIFTER_PRE_END_SOUND_3P )
+ }
+
+ wait SHIFTER_OUTRO_TIME_BEFORE_END
+ }
+ else
+ {
+ wait shiftTime
+ }
+
+ PlayPhaseShiftAppearFX( ent )
+
+ if ( timeAdjusted )
+ wait FX_WARMUP_TIME
+}
+
+// ASSUMES THAT SECOND ENTITY IS NOT HUMAN SIZED
+bool function ShouldEntitySelfKill( entity ent, entity largeTelefragTarget )
+{
+ if ( IsHumanSized( ent ) )
+ return true
+
+ if ( IsSingleplayer() )
+ return false
+
+ return ( DistanceSqr( largeTelefragTarget.GetOrigin(), ent.GetOrigin() ) < 4096.0 )
+}
+
+void function PhaseShiftDisappearEffectCleanup( entity ent, entity fx, float duration )
+{
+ fx.EndSignal( "OnDestroy" )
+ ent.EndSignal( "ForceStopPhaseShift" )
+
+ OnThreadEnd(
+ function() : ( fx )
+ {
+ if ( IsValid( fx ) )
+ {
+ EffectStop( fx )
+ }
+ }
+ )
+
+ float bufferTime = 1.4
+ if ( ent.IsTitan() )
+ bufferTime = 0.0
+
+ wait max( duration - bufferTime, 0.0 )
+}
+
+entity function PlayPhaseShiftAppearFX( entity ent )
+{
+ asset effect = SHIFTER_APPEAR_FX
+ if ( !IsHumanSized( ent ) )
+ effect = SHIFTER_APPEAR_FX_TITAN
+
+ if ( ent.IsPlayer() )
+ {
+ if ( ent.IsTitan() )
+ EmitSoundOnEntityExceptToPlayer( ent, ent, SHIFTER_END_SOUND_3P_TITAN )
+ else
+ EmitSoundOnEntityExceptToPlayer( ent, ent, SHIFTER_END_SOUND_3P )
+
+ return PlayFXOnEntityForEveryoneExceptPlayer( effect, ent, ent )
+ }
+ else
+ {
+ if ( ent.IsTitan() )
+ EmitSoundOnEntity( ent, SHIFTER_END_SOUND_3P_TITAN )
+ else
+ EmitSoundOnEntity( ent, SHIFTER_END_SOUND_3P )
+ return PlayFXOnEntity( effect, ent )
+ }
+}
+
+entity function PlayPhaseShiftDisappearFX( entity ent )
+{
+ asset effect = SHIFTER_DISAPPEAR_FX
+ if ( !IsHumanSized( ent ) )
+ effect = SHIFTER_DISAPPEAR_FX_TITAN
+
+ int fxid = GetParticleSystemIndex( effect )
+ int attachId = ent.LookupAttachment( "ORIGIN" )
+
+ return StartParticleEffectOnEntity_ReturnEntity( ent, fxid, FX_PATTACH_POINT_FOLLOW, attachId )
+}
+
+array<entity> function GetAttachedEnts( entity ent )
+{
+ array<entity> ents = [ ent ]
+
+ if ( HasSoul( ent ) )
+ {
+ entity soul = ent.GetTitanSoul()
+ if ( IsValid( soul.soul.batteryContainer ) )
+ ents.append( soul.soul.batteryContainer )
+ }
+
+ entity weapon = ent.GetActiveWeapon()
+ if ( IsValid( weapon ) )
+ ents.append( weapon )
+
+ return ents
+}
+
+/*
+void function PROTO_CapVelocity( player )
+{
+ player.EndSignal( "OnDeath" )
+ player.EndSignal( "StopPhaseShift" )
+
+ while( 1 )
+ {
+ local newVel = player.GetVelocity()
+ local zVel = newVel.z
+ newVel = Vector( newVel.x, newVel.y, 0 )
+ local speed = Length( newVel )
+ newVel = Normalize( newVel )
+ speed = min( speed, 400 )
+ newVel = newVel * speed
+ player.SetVelocity( Vector(newVel.x,newVel.y,zVel) )
+ WaitFrame()
+ }
+}
+*/
+
+void function UntrackAllToneMarks( entity ent )
+{
+ if ( IsSingleplayer() ) //JFS::Probably want to remove this for R3
+ return
+
+ array<entity> enemyTitans = GetTitanArrayOfEnemies( ent.GetTeam() )
+ foreach( titan in enemyTitans )
+ {
+ entity offhand = titan.GetOffhandWeapon( OFFHAND_RIGHT )
+ if ( !IsValid( offhand ) )
+ return
+
+ if ( offhand.GetWeaponClassName() != "mp_titanweapon_tracker_rockets" )
+ continue
+
+ offhand.SmartAmmo_UntrackEntity( ent )
+ }
+}
+#endif // #if SERVER
+
+
+#if CLIENT
+void function ClientPhaseShiftWarmupThread( entity player, float warmupTime )
+{
+ player.EndSignal( "OnDeath" )
+
+ if ( player != GetLocalViewPlayer() )
+ return
+ if ( InPrediction() && !IsFirstTimePredicted() )
+ return
+
+ if ( warmupTime <= 0 )
+ return
+
+ int index = GetParticleSystemIndex( SHIFTER_PRE_FX )
+ int fxID = StartParticleEffectInWorldWithHandle( index, ZERO_VECTOR, ZERO_VECTOR )
+
+ OnThreadEnd(
+ function() : ( fxID )
+ {
+ EffectStop( fxID, true, true );
+ }
+ )
+
+ if ( player.IsTitan() )
+ EmitSoundOnEntity( player, SHIFTER_PRE_SOUND_1P_TITAN )
+ else
+ EmitSoundOnEntity( player, SHIFTER_PRE_SOUND_1P )
+
+ wait warmupTime
+}
+
+void function ClientPhaseShiftFirstPersonFXThread()
+{
+ int effectSparkles;
+ int effectScreen;
+ bool effectsAreActive = false;
+ bool endSoundPlayed = false;
+ entity ourPlayer = null;
+
+ while( true )
+ {
+ if ( effectsAreActive )
+ {
+ entity localViewPlayer = GetLocalViewPlayer();
+
+ bool needShutdown = false;
+ if ( !IsValid( ourPlayer ) || !IsAlive( ourPlayer ) )
+ needShutdown = true;
+ else if ( ourPlayer != localViewPlayer )
+ needShutdown = true;
+ else if ( !ourPlayer.IsPhaseShifted() )
+ needShutdown = true;
+
+ if ( needShutdown )
+ {
+ if ( IsValid( ourPlayer ) && (ourPlayer == localViewPlayer) )
+ {
+ // FX
+ {
+ int fxIndex = GetParticleSystemIndex( SHIFTER_SCREEN_FX_START )
+ StartParticleEffectInWorldWithHandle( fxIndex, ZERO_VECTOR, ZERO_VECTOR )
+ }
+
+ // FX
+ {
+ int fxIndex = GetParticleSystemIndex( SHIFTER_APPEAR_FX )
+ vector viewAngles = ourPlayer.EyeAngles()
+ vector viewForward = AnglesToForward( viewAngles )
+ vector viewForward2d = Normalize( Vector( viewForward.x, viewForward.y, 0.0 ) )
+ StartParticleEffectOnEntityWithPos( ourPlayer, fxIndex, FX_PATTACH_ABSORIGIN, -1, (viewForward2d * 30), ZERO_VECTOR )
+ }
+
+ if ( ourPlayer.IsTitan() )
+ {
+ EmitSoundOnEntity( ourPlayer, SHIFTER_END_SOUND_1P_TITAN )
+ }
+ else
+ {
+ EmitSoundOnEntity( ourPlayer, SHIFTER_END_SOUND_1P )
+ }
+ StopSoundOnEntity( ourPlayer, SHIFTER_LOOP_SOUND_1P )
+ StopSoundOnEntity( ourPlayer, SHIFTER_LOOP_SOUND_1P_TITAN )
+ }
+
+ ClientPhaseShift_SCRIPT_HACKS_OFF()
+
+ EffectStop( effectSparkles, true, true )
+ EffectStop( effectScreen, true, true )
+ effectsAreActive = false;
+ ourPlayer = null;
+ endSoundPlayed = false;
+ }
+ else if ( IsValid( localViewPlayer ) && localViewPlayer.IsPhaseShifted() )
+ {
+ if ( !endSoundPlayed && (localViewPlayer.PhaseShiftTimeRemaining() <= SHIFTER_OUTRO_TIME_BEFORE_END) )
+ {
+ endSoundPlayed = true;
+ if ( localViewPlayer.IsTitan() )
+ EmitSoundOnEntity( localViewPlayer, SHIFTER_PRE_END_SOUND_1P_TITAN )
+ else
+ EmitSoundOnEntity( localViewPlayer, SHIFTER_PRE_END_SOUND_1P )
+ }
+ }
+
+ }
+
+ if ( !effectsAreActive )
+ {
+ entity localViewPlayer = GetLocalViewPlayer();
+
+ if ( IsValid( localViewPlayer ) && localViewPlayer.IsPhaseShifted() )
+ {
+ // FX
+ {
+ int fxIndex = GetParticleSystemIndex( SHIFTER_PERSONAL_FX )
+ int attachIdx = localViewPlayer.LookupAttachment( "CHESTFOCUS" )
+ effectSparkles = StartParticleEffectOnEntity( localViewPlayer, fxIndex, FX_PATTACH_POINT_FOLLOW, attachIdx )
+ }
+
+ // FX
+ {
+ int fxIndex = GetParticleSystemIndex( SHIFTER_SCREEN_FX )
+ effectScreen = StartParticleEffectInWorldWithHandle( fxIndex, ZERO_VECTOR, ZERO_VECTOR )
+ }
+
+ // FX
+ {
+ int fxIndex = GetParticleSystemIndex( SHIFTER_SCREEN_FX_START )
+ StartParticleEffectInWorldWithHandle( fxIndex, ZERO_VECTOR, ZERO_VECTOR )
+ }
+
+ // FX
+ {
+ entity viewModelEntity = localViewPlayer.GetViewModelEntity()
+ entity firstPersonProxy = localViewPlayer.GetPredictedFirstPersonProxy()
+
+ if ( IsValid( viewModelEntity ) )
+ {
+ viewModelEntity.Highlight_HideInside( 0.0 )
+ viewModelEntity.Highlight_HideOutline( 0.0 )
+ }
+
+ if ( IsValid( firstPersonProxy ) )
+ {
+ firstPersonProxy.Highlight_HideInside( 0.0 )
+ firstPersonProxy.Highlight_HideOutline( 0.0 )
+ }
+ }
+
+ ClientPhaseShift_SCRIPT_HACKS_ON()
+
+ if ( localViewPlayer.IsTitan() )
+ EmitSoundOnEntity( localViewPlayer, SHIFTER_START_SOUND_1P_TITAN )
+ else
+ EmitSoundOnEntity( localViewPlayer, SHIFTER_START_SOUND_1P )
+
+ if ( localViewPlayer.IsTitan() )
+ EmitSoundOnEntity( localViewPlayer, SHIFTER_LOOP_SOUND_1P_TITAN )
+ else
+ EmitSoundOnEntity( localViewPlayer, SHIFTER_LOOP_SOUND_1P )
+
+ effectsAreActive = true;
+ ourPlayer = localViewPlayer;
+ }
+ }
+
+ WaitFrame()
+ }
+}
+
+void function ClientRemoteTurretFirstPersonFXThread()
+{
+ int effectSparkles;
+ int effectScreen;
+ bool effectsAreActive = false;
+ entity ourPlayer = null;
+
+ const string TURRET_LOOP_SOUND = "Pilot_RemoteTurret_Loop_1P"
+
+ while( true )
+ {
+ if ( effectsAreActive )
+ {
+ entity localViewPlayer = GetLocalViewPlayer();
+
+ bool needShutdown = false;
+ if ( !IsValid( ourPlayer ) || !IsAlive( ourPlayer ) )
+ needShutdown = true;
+ else if ( ourPlayer != localViewPlayer )
+ needShutdown = true;
+ else if ( ourPlayer.GetRemoteTurret() == null )
+ needShutdown = true;
+
+ if ( needShutdown )
+ {
+ if ( IsValid( ourPlayer ) && (ourPlayer == localViewPlayer) )
+ StopSoundOnEntity( ourPlayer, TURRET_LOOP_SOUND )
+
+ effectsAreActive = false;
+ ourPlayer = null;
+ }
+ }
+
+ if ( !effectsAreActive )
+ {
+ entity localViewPlayer = GetLocalViewPlayer();
+ if ( IsValid( localViewPlayer ) && (localViewPlayer.GetRemoteTurret() != null) )
+ {
+ EmitSoundOnEntity( localViewPlayer, TURRET_LOOP_SOUND )
+ effectsAreActive = true;
+ ourPlayer = localViewPlayer;
+ }
+ }
+
+ WaitFrame()
+ }
+}
+
+void function ClientPhaseShift_SCRIPT_HACKS_ON()
+{
+ entity localViewPlayer = GetLocalViewPlayer();
+
+ localViewPlayer.Signal( "StartPhaseShift" )
+
+ if ( localViewPlayer == GetLocalClientPlayer() )
+ {
+ //localViewPlayer.cv.PlayerPetTitanIcon.Hide()
+ //localViewPlayer.cv.PlayerPetTitanArrow.Hide()
+ //localViewPlayer.cv.PlayerPetTitanLabel.Hide()
+ }
+}
+
+void function ClientPhaseShift_SCRIPT_HACKS_OFF()
+{
+ entity localViewPlayer = GetLocalViewPlayer();
+
+ if ( localViewPlayer == GetLocalClientPlayer() )
+ UpdatePetTitanIcon( localViewPlayer )
+
+ //It would be great if we could automatically hide icons using SetEntityOverhead if that entity is phased out.
+ // if ( GameRules_GetGameMode() == SURVIVOR )
+ // DisplayScrapCounter( GetLocalClientPlayer(), LIFE_ALIVE, LIFE_ALIVE )
+}
+
+#endif // #if CLIENT