aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/mod
diff options
context:
space:
mode:
authorRoyalBlue1 <malte.hoermeyer@web.de>2022-02-21 00:54:52 +0100
committerRoyalBlue1 <malte.hoermeyer@web.de>2022-03-25 19:59:02 +0100
commitc56e68e17c7f525a69311e36ba76a6aad3e27ee4 (patch)
tree13e07deccbdbb96593e7bda795f0912a821eb0cc /Northstar.CustomServers/mod
parentbc47d316929fcad6f9e39309bf1ad9bcebf4bd2b (diff)
downloadNorthstarMods-c56e68e17c7f525a69311e36ba76a6aad3e27ee4.tar.gz
NorthstarMods-c56e68e17c7f525a69311e36ba76a6aad3e27ee4.zip
Added wave event logic
added some first Events created method to get 9 most spawned enemies for client ui split Harvester Fx to make shield disappear when down
Diffstat (limited to 'Northstar.CustomServers/mod')
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut18
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut471
-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.nut59
4 files changed, 465 insertions, 90 deletions
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut
index 71bbd345..e5e60bf2 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/_harvester.gnut
@@ -1,5 +1,6 @@
global function SpawnHarvester
-global function startHarvesterFX
+global function generateBeamFX
+global function generateShieldFX
global struct HarvesterStruct {
entity harvester
@@ -45,13 +46,18 @@ HarvesterStruct function SpawnHarvester(vector origin,vector angles,int health,i
return ret
}
-HarvesterStruct function startHarvesterFX(HarvesterStruct harvester)
+HarvesterStruct function generateBeamFX(HarvesterStruct harvester)
{
entity Harvester_Beam = StartParticleEffectOnEntity_ReturnEntity(harvester.harvester,GetParticleSystemIndex(FX_HARVESTER_BEAM),FX_PATTACH_ABSORIGIN_FOLLOW,0)
- EffectSetControlPointVector( Harvester_Beam, 1, < 126.0, 188.0, 236.0 > )
- entity Harvester_Shield = StartParticleEffectOnEntity_ReturnEntity(harvester.harvester,GetParticleSystemIndex(FX_HARVESTER_OVERSHIELD),FX_PATTACH_ABSORIGIN_FOLLOW,0)
- EffectSetControlPointVector( Harvester_Shield, 1, < 126.0, 188.0, 236.0 > )
+ EffectSetControlPointVector( Harvester_Beam, 1, GetShieldTriLerpColor(0.0) )
harvester.particleBeam = Harvester_Beam
- harvester.particleShield = Harvester_Shield
return harvester
}
+
+HarvesterStruct function generateShieldFX(HarvesterStruct harvester)
+{
+ entity Harvester_Shield = StartParticleEffectOnEntity_ReturnEntity(harvester.harvester,GetParticleSystemIndex(FX_HARVESTER_OVERSHIELD),FX_PATTACH_ABSORIGIN_FOLLOW,0)
+ EffectSetControlPointVector( Harvester_Shield, 1, GetShieldTriLerpColor(0.0) )
+ harvester.particleShield = Harvester_Shield
+ return harvester
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
index 4f434fd2..ef952b24 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
@@ -1,11 +1,47 @@
global function GamemodeFD_Init
global function RateSpawnpoints_FD
-global function useHarvesterShieldBoost
-global function spawnSmokes
-global function waveStart
global function startHarvester
+global function createSmokeEvent
+global function createArcTitanEvent
+global function createWaitForTimeEvent
+global function createSuperSpectreEvent
+global function createDroppodGruntEvent
+
+global struct SmokeEvent{
+ vector position
+ float lifetime
+}
+
+global struct SpawnEvent{
+ vector origin
+ vector angles
+ string route
+ 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 amount of spawned enemys
+ string npcClassName
+ string aiSettings
+}
+
+global struct WaitEvent{
+ float amount
+}
+
+global struct SoundEvent{
+ string soundEventName
+}
+
+global struct WaveEvent{
+ void functionref(SmokeEvent,SpawnEvent,WaitEvent,SoundEvent) eventFunction
+ SmokeEvent smokeEvent
+ SpawnEvent spawnEvent
+ WaitEvent waitEvent
+ SoundEvent soundEvent
+}
-global HarvesterStruct harvesterStruct
+
+global HarvesterStruct fd_harvester
+global vector shopPosition
+global array<array<WaveEvent> > waveEvents
struct {
array<entity> aiSpawnpoints
@@ -21,53 +57,43 @@ void function GamemodeFD_Init()
PrecacheParticleSystem($"P_smokescreen_FD")
AddCallback_EntitiesDidLoad(LoadEntities)
AddDamageCallback("prop_script",OnDamagedPropScript)
-
+ AddCallback_GameStateEnter( eGameState.Playing,startMainGameLoop)
+ AddClientCommandCallback("FD_UseHarvesterShieldBoost",useShieldBoost)
}
void function RateSpawnpoints_FD(int _0, array<entity> _1, int _2, entity _3)
{
-
+
}
-bool function useHarvesterShieldBoost() //returns true when acturally used
+bool function useShieldBoost(entity player,array<string> args)
{
- if(harvesterStruct.harvester.GetShieldHealth()<harvesterStruct.harvester.GetShieldHealthMax())
- {
- thread useHarvesterShieldBoost_threaded()
- return true
+ if((GetGlobalNetTime("FD_harvesterInvulTime")<Time())&&(player.GetPlayerNetInt("numHarvesterShieldBoost")>0))
+ {
+ fd_harvester.harvester.SetShieldHealth(fd_harvester.harvester.GetShieldHealthMax())
+ SetGlobalNetTime("FD_harvesterInvulTime",Time()+5)
+ player.SetPlayerNetInt( "numHarvesterShieldBoost", player.GetPlayerNetInt( "numHarvesterShieldBoost" ) - 1 )
}
- return false
+ return true
}
-void function useHarvesterShieldBoost_threaded()
+
+void function startMainGameLoop()
{
- harvesterStruct.shieldBoost = true
- wait 5
- harvesterStruct.shieldBoost = false
+ thread mainGameLoop()
}
-void function spawnSmokes()
-{
- entity owner = GetPlayerArray()[0]
- foreach(entity pos in file.smokePoints)
- {
- SmokescreenStruct smokescreen
- smokescreen.smokescreenFX = $"P_smokescreen_FD"
- smokescreen.ownerTeam = owner.GetTeam()
- smokescreen.damageSource = eDamageSourceId.mp_weapon_grenade_electric_smoke
- smokescreen.deploySound1p = "explo_electric_smoke_impact"
- smokescreen.deploySound3p = "explo_electric_smoke_impact"
- smokescreen.isElectric = false
- smokescreen.origin = pos.GetOrigin()+<0,0,150>
- smokescreen.angles = pos.GetAngles()
- smokescreen.lifetime = 30
- smokescreen.fxXYRadius = 150
- smokescreen.fxZRadius = 120
- smokescreen.fxOffsets = [ <120.0, 0.0, 0.0>,<0.0, 120.0, 0.0>, <0.0, 0.0, 0.0>,<0.0, -120.0, 0.0>,< -120.0, 0.0, 0.0>, <0.0, 100.0, 0.0>]
- Smokescreen(smokescreen)
- }
+void function mainGameLoop()
+{
+ startHarvester()
+ runWave(0)
+
}
+
+
+
+
array<entity> function getRoute(string routeName)
{
foreach(entity node in file.routeNodes)
@@ -80,36 +106,98 @@ array<entity> function getRoute(string routeName)
printt("Route not found")
return []
}
-
-vector function getShopPosition()
+array<int> function getEnemyTypesForWave(int wave)
{
- switch(GetMapName())
+ 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[wave])
{
- case"mp_forwardbase_kodai":
- return < -3862.13, 1267.69, 1060.06>
- default:
- return <0,0,0>
+ 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.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){
+ printt("Key",key,"has value",value)
+ SetGlobalNetInt(FD_GetAINetIndex_byAITypeID(key),value)
+ 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)
}
- unreachable
+ return ret
}
-void function waveStart()
+void function runWave(int waveIndex)
{
file.haversterWasDamaged = false
- array<int> enemys = [eFD_AITypeIDs.TITAN,eFD_AITypeIDs.GRUNT,-1,-1,-1,-1,-1,-1,-1]
+ array<int> enemys = getEnemyTypesForWave(waveIndex)
- SetGlobalNetInt("FD_currentWave",2)
+ SetGlobalNetInt("FD_currentWave",waveIndex)
SetGlobalNetBool("FD_waveActive",true)
- SetGlobalNetInt(FD_GetAINetIndex_byAITypeID( eFD_AITypeIDs.TITAN), 69)
- SetGlobalNetInt(FD_GetAINetIndex_byAITypeID( eFD_AITypeIDs.GRUNT), 420)
+
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])
}
-
+ foreach(WaveEvent event in waveEvents[waveIndex])
+ {
+ event.eventFunction(event.smokeEvent,event.spawnEvent,event.waitEvent,event.soundEvent)
+ }
}
@@ -117,16 +205,16 @@ void function waveStart()
void function OnDamagedPropScript(entity prop,var damageInfo)
{
- if(!IsValid(harvesterStruct.harvester))
+ if(!IsValid(fd_harvester.harvester))
return
if(!IsValid(prop))
return
- if(harvesterStruct.harvester!=prop)
+ if(fd_harvester.harvester!=prop)
return
- if(harvesterStruct.shieldBoost)
+ if(GetGlobalNetTime("FD_harvesterInvulTime")>Time())
{
prop.SetShieldHealth(prop.GetShieldHealthMax())
return
@@ -145,19 +233,19 @@ void function OnDamagedPropScript(entity prop,var damageInfo)
if ( !attacker )
return
//TODO Log damage source for round lose screen
- harvesterStruct.lastDamage = Time()
+
+ fd_harvester.lastDamage = Time()
if(prop.GetShieldHealth()==0)
{
+
float newHealth = prop.GetHealth()-damageAmount
if(newHealth<0)
{
- EmitSoundAtPosition(TEAM_UNASSIGNED,harvesterStruct.harvester.GetOrigin(),"coop_generator_destroyed")
+ EmitSoundAtPosition(TEAM_UNASSIGNED,fd_harvester.harvester.GetOrigin(),"coop_generator_destroyed")
newHealth=0
- harvesterStruct.rings.Destroy()
-
+ fd_harvester.rings.Destroy()
}
-
-
+
prop.SetHealth(newHealth)
file.haversterWasDamaged = true
}
@@ -168,33 +256,42 @@ void function OnDamagedPropScript(entity prop,var damageInfo)
void function HarvesterThink()
{
- entity harvester = harvesterStruct.harvester
+ entity harvester = fd_harvester.harvester
EmitSoundOnEntity(harvester,"coop_generator_startup")
float lastTime = Time()
wait 4
- int lastShieldHealth = 6000
- HarvesterStruct temp = startHarvesterFX(harvesterStruct)
- harvesterStruct.particleBeam = temp.particleBeam
- harvesterStruct.particleShield = temp.particleShield
- wait 5
+ int lastShieldHealth = harvester.GetShieldHealth()
+ generateBeamFX(fd_harvester)
+ generateShieldFX(fd_harvester)
+
EmitSoundOnEntity(harvester,"coop_generator_ambient_healthy")
- entity particleBeam = harvesterStruct.particleBeam
- entity particleShield = harvesterStruct.particleShield
+
while(IsAlive(harvester)){
float currentTime = Time()
float deltaTime = currentTime -lastTime
- vector shieldColor = GraphCappedVector(harvester.GetShieldHealth(), 0, harvester.GetShieldHealthMax(),TEAM_COLOR_ENEMY, TEAM_COLOR_FRIENDLY)
- EffectSetControlPointVector( particleShield, 1, shieldColor )
- vector beamColor = GraphCappedVector(harvester.GetHealth(), 0, harvester.GetMaxHealth(), TEAM_COLOR_ENEMY, TEAM_COLOR_FRIENDLY)
- EffectSetControlPointVector( particleBeam, 1, beamColor )
- if(((currentTime-harvesterStruct.lastDamage)>=GENERATOR_SHIELD_REGEN_DELAY)&&(harvester.GetShieldHealth()<harvester.GetShieldHealthMax()))
+ 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()))
{
- printt((currentTime-harvesterStruct.lastDamage))
+ if(!IsValid(fd_harvester.particleShield))
+ generateShieldFX(fd_harvester)
+ //printt((currentTime-fd_harvester.lastDamage))
if(harvester.GetShieldHealth()==0)
EmitSoundOnEntity(harvester,"coop_generator_shieldrecharge_start")
EmitSoundOnEntity(harvester,"coop_generator_shieldrecharge_resume")
@@ -229,11 +326,11 @@ void function startHarvester(){
void function HarvesterAlarm()
{
- while(IsAlive(harvesterStruct.harvester))
+ while(IsAlive(fd_harvester.harvester))
{
- if(harvesterStruct.harvester.GetShieldHealth()==0)
+ if(fd_harvester.harvester.GetShieldHealth()==0)
{
- EmitSoundOnEntity(harvesterStruct.harvester,"coop_generator_underattack_alarm")
+ EmitSoundOnEntity(fd_harvester.harvester,"coop_generator_underattack_alarm")
wait 2.5
}
else
@@ -242,12 +339,20 @@ void function HarvesterAlarm()
}
}
}
+void function initNetVars(){
+ SetGlobalNetInt("FD_totalWaves",waveEvents.len())
+ if(GetCurrentPlaylistVarInt("fd_difficulty",0)>=5)
+ SetGlobalNetInt("FD_restartsRemaining",0)
+ else
+ SetGlobalNetInt("FD_restartsRemaining",2)
+
+}
+
void function LoadEntities()
{
- SetGlobalNetInt("FD_totalWaves",5)
- SetGlobalNetInt("FD_restartsRemaining",2)
- CreateBoostStoreLocation(TEAM_MILITIA,getShopPosition(),<0,0,0>)
+ initNetVars()
+ CreateBoostStoreLocation(TEAM_MILITIA,shopPosition,<0,0,0>)
OpenBoostStores()
@@ -262,9 +367,9 @@ void function LoadEntities()
switch(info_target.kv.editorclass){
case"info_fd_harvester":
HarvesterStruct ret = SpawnHarvester(info_target.GetOrigin(),info_target.GetAngles(),25000,6000,TEAM_IMC)
- harvesterStruct.harvester = ret.harvester
- harvesterStruct.rings = ret.rings
- harvesterStruct.lastDamage = ret.lastDamage
+ fd_harvester.harvester = ret.harvester
+ fd_harvester.rings = ret.rings
+ fd_harvester.lastDamage = ret.lastDamage
break
case"info_fd_mode_model":
@@ -272,6 +377,9 @@ void function LoadEntities()
break
case"info_fd_ai_position":
file.aiSpawnpoints.append(info_target)
+ if(info_target.kv.aiType=="3")
+ CreatePropDynamic($"models/vehicle/escape_pod/escape_pod.mdl",info_target.GetOrigin(),info_target.GetAngles(),6)
+
break
case"info_fd_route_node":
file.routeNodes.append(info_target)
@@ -290,4 +398,201 @@ void function LoadEntities()
}
-} \ No newline at end of file
+}
+
+/****************************************************************************************************************\
+####### # # ####### # # ####### ##### ####### # # ####### ###### # ####### ####### ######
+# # # # ## # # # # # ## # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # # # # #
+##### # # ##### # # # # # #### ##### # # # ##### ###### # # # # # ######
+# # # # # # # # # # # # # # # # # ####### # # # # #
+# # # # # ## # # # # # ## # # # # # # # # # #
+####### # ####### # # # ##### ####### # # ####### # # # # # ####### # #
+\*****************************************************************************************************************/
+
+WaveEvent function createSmokeEvent(vector position,float lifetime)
+{
+ WaveEvent event
+ event.eventFunction = spawnSmoke
+ event.smokeEvent.position = position
+ event.smokeEvent.lifetime = lifetime
+ return event
+}
+
+WaveEvent function createArcTitanEvent(vector origin,vector angles,string route)
+{
+ WaveEvent event
+ event.eventFunction = spawnArcTitan
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TITAN_ARC
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ return event
+}
+
+WaveEvent function createSuperSpectreEvent(vector origin,vector angles,string route)
+{
+ WaveEvent event
+ event.eventFunction = spawnSuperSpectre
+ event.spawnEvent.spawnType= eFD_AITypeIDs.REAPER
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ return event
+}
+
+WaveEvent function createDroppodGruntEvent(vector origin,string route)
+{
+ WaveEvent event
+ event.eventFunction = spawnDroppodGrunts
+ event.spawnEvent.spawnType= eFD_AITypeIDs.GRUNT
+ event.spawnEvent.spawnAmount = 4
+ event.spawnEvent.origin = origin
+ event.spawnEvent.route = route
+ return event
+}
+
+WaveEvent function createWaitForTimeEvent(float amount)
+{
+ WaveEvent event
+ event.eventFunction = waitForTime
+ event.waitEvent.amount = amount
+ return event
+}
+
+WaveEvent function createGenericSpawnEvent(string npcClassName,vector origin,vector angles,string route,int spawnType,int spawnAmount)
+{
+ WaveEvent event
+ event.eventFunction = spawnGenericNPC
+ event.spawnEvent.npcClassName = npcClassName
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ event.spawnEvent.route = route
+ event.spawnEvent.spawnType = spawnType
+ event.spawnEvent.spawnAmount = spawnAmount
+ return event
+}
+
+
+WaveEvent function createGenericTitanSpawnWithAiSettingsEvent(string npcClassName,string aiSettings,vector origin,vector angles,string route,int spawnType,int spawnAmount)
+{
+ WaveEvent event
+ event.eventFunction = spawnGenericNPCTitanwithSettings
+ 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
+ return event
+}
+
+/************************************************************************************************************\
+####### # # ####### # # ####### ####### # # # # ##### ####### ### ####### # # #####
+# # # # ## # # # # # ## # # # # # # # ## # # #
+# # # # # # # # # # # # # # # # # # # # # # #
+##### # # ##### # # # # ##### # # # # # # # # # # # # # #####
+# # # # # # # # # # # # # # # # # # # # # # #
+# # # # # ## # # # # # ## # # # # # # # ## # #
+####### # ####### # # # # ##### # # ##### # ### ####### # # #####
+\************************************************************************************************************/
+
+void function spawnSmoke(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ printt("smoke")
+ SmokescreenStruct smokescreen
+ smokescreen.smokescreenFX = $"P_smokescreen_FD"
+ smokescreen.isElectric = false
+ smokescreen.origin = smokeEvent.position
+ smokescreen.angles = <0,0,0>
+ smokescreen.lifetime = smokeEvent.lifetime
+ smokescreen.fxXYRadius = 150
+ smokescreen.fxZRadius = 120
+ smokescreen.fxOffsets = [ <120.0, 0.0, 0.0>,<0.0, 120.0, 0.0>, <0.0, 0.0, 0.0>,<0.0, -120.0, 0.0>,< -120.0, 0.0, 0.0>, <0.0, 100.0, 0.0>]
+ Smokescreen(smokescreen)
+}
+
+void function spawnArcTitan(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ entity npc = CreateArcTitan(TEAM_IMC,spawnEvent.origin,spawnEvent.angles)
+ DispatchSpawn(npc)
+}
+
+void function waitForTime(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ wait waitEvent.amount
+}
+
+void function waitUntil(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ wait waitEvent.amount
+}
+
+void function spawnSuperSpectre(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ entity npc = CreateSuperSpectre(TEAM_IMC,spawnEvent.origin,spawnEvent.angles)
+ DispatchSpawn(npc)
+}
+
+void function spawnDroppodGrunts(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ CreateTrackedDroppod(spawnEvent.origin,TEAM_IMC)
+}
+void function spawnGenericNPC(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ entity npc = CreateNPC( spawnEvent.npcClassName, TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ DispatchSpawn(npc)
+}
+void function spawnGenericNPCTitanwithSettings(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ entity npc = CreateNPCTitan( spawnEvent.npcClassName, TEAM_IMC, spawnEvent.origin, spawnEvent.angles )
+ SetSpawnOption_AISettings( npc, spawnEvent.aiSettings)
+ DispatchSpawn(npc)
+}
+void function spawnNukeTitan(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
+{
+ entity npc = CreateNPCTitan("titan_ogre",TEAM_IMC, spawnEvent.origin, spawnEvent.angles)
+ SetSpawnOption_AISettings(npc,"npc_titan_minigun_nuke")
+ DispachSpawn(npc)
+}
+
+/********************************************************************************************************************\
+# # ####### # ###### ####### ###### ####### # # # # ##### ####### ### ####### # # #####
+# # # # # # # # # # # # ## # # # # # # # ## # # #
+# # # # # # # # # # # # # # # # # # # # # # # #
+####### ##### # ###### ##### ###### ##### # # # # # # # # # # # # # #####
+# # # # # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # ## # # # # # # # ## # #
+# # ####### ####### # ####### # # # ##### # # ##### # ### ####### # # #####
+\********************************************************************************************************************/
+
+
+void function CreateTrackedDroppod( vector origin, int team , )
+{
+
+
+ entity pod = CreateDropPod( origin, <0,0,0> )
+ SetTeam( pod, team )
+ InitFireteamDropPod( pod )
+ waitthread LaunchAnimDropPod( pod, "pod_testpath", origin, <0,0,0> )
+
+ string squadName = MakeSquadName( team, UniqueString( "ZiplineTable" ) )
+ array<entity> guys
+
+ for ( int i = 0; i < 4; i++ )
+ {
+ entity guy = CreateSoldier( team, origin,<0,0,0> )
+
+ SetTeam( guy, team )
+ guy.EnableNPCFlag( NPC_ALLOW_PATROL | NPC_ALLOW_INVESTIGATE | NPC_ALLOW_HAND_SIGNALS | NPC_ALLOW_FLEE )
+ DispatchSpawn( guy )
+
+ SetSquad( guy, squadName )
+ guys.append( guy )
+ }
+
+ ActivateFireteamDropPod( pod, guys )
+}
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..76dbb310 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
@@ -24,4 +24,11 @@ void function FixBatterySpawns( entity spawn )
PowerUp powerupDef = GetPowerUpFromItemRef( expect string( spawn.kv.powerUpType ) )
if ( powerupDef.spawnFunc() )
spawn.SetOrigin( BATTERY_SPAWNS[file.batteryIndex++] )
+}
+global function CodeCallback_MapInit
+
+void function CodeCallback_MapInit()
+{
+ if(GameRules_GetGameMode()=="fd")
+ initFrontierDefenseData()
} \ 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..bc68d794 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,58 @@
-//fuck \ No newline at end of file
+global function initFrontierDefenseData
+
+
+void function initFrontierDefenseData()
+{
+ shopPosition = < -3862.13, 1267.69, 1060.06>
+
+
+
+ array<WaveEvent> wave0
+ array<WaveEvent> wave1
+ array<WaveEvent> wave2
+ array<WaveEvent> wave3
+ array<WaveEvent> wave4
+
+
+
+ //wave0.append(createSmokeEvent(< -12, 1720, 1556>,30))
+ //wave0.append(createSmokeEvent(< -64, 964, 1556>,30))
+ //wave0.append(createWaitForTimeEvent(5))
+ wave0.append(createSuperSpectreEvent(< -64, 964, 1556>,<0,0,0>,""))
+ wave0.append(createArcTitanEvent(< -12, 1720, 1556>,<0,0,0>,""))
+ wave0.append(createDroppodGruntEvent(< -12, 1720, 1556>,""))
+
+ waveEvents.append(wave0)
+ waveEvents.append(wave1)
+ waveEvents.append(wave2)
+ waveEvents.append(wave3)
+ waveEvents.append(wave4)
+}
+
+/*
+void function initFrontierDefenseData()
+{
+ shopPosition =
+
+ SmokeEvent emptySmokeEvent
+ SpawnEvent emptySpawnEvent
+ WaitEvent emptyWaitEvent
+ SoundEvent emptySoundEvent
+
+ 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