aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers
diff options
context:
space:
mode:
authorx3Karma <juliuslimck@gmail.com>2022-05-12 19:49:09 +0800
committerGitHub <noreply@github.com>2022-05-12 13:49:09 +0200
commitdd4a613adb63b30b50a86c0e9a359cb9025351d1 (patch)
tree787913d6a20376a3f1e418f37cbe8a55066c1889 /Northstar.CustomServers
parent9d77289574cf8e410ec66264c1d7bd542fa5d6d7 (diff)
downloadNorthstarMods-dd4a613adb63b30b50a86c0e9a359cb9025351d1.tar.gz
NorthstarMods-dd4a613adb63b30b50a86c0e9a359cb9025351d1.zip
Frontier Defense stuff (#355)
* Update _gamemode_fd.nut - stop including player-owned Auto-Titans in the final check - Add CreateToneSniperEvent and CreateNorthstarSniperTitanEvent - Sniper titans have their own AI pathing (See _ai_sniper_titans.nut) - Added Combat and Support Scoring - Added experimental human nav paths - Moved all AddDeathCallbacks for NPCs into AddCallback_OnNPCKilled - NPCs check logs doesn't spam the console - fixed overhead icon not showing * Update _ai_cloak_drone.gnut - changed to IsEMPTitan check - no idea why cloak is not working * Update _ai_emp_titans.gnut - Added IsEMPTitan check * Update _ai_sniper_titans.gnut - Experimental pathing, they work, they wont attack * Update mp_forwardbase_kodai_fd.nut - Wave 1 in Kodai is fully done ( i think, might need to add more smokes in between subwaves )
Diffstat (limited to 'Northstar.CustomServers')
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_cloak_drone.gnut49
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_emp_titans.gnut20
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_sniper_titans.gnut89
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut258
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_forwardbase_kodai_fd.nut78
5 files changed, 450 insertions, 44 deletions
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..33437ad7 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 ) )
@@ -334,7 +334,11 @@ void function CloakedDronePathFollowNPC( entity cloakedDrone, entity goalNPC )
function() : ( goalNPC )
{
if ( IsAlive( goalNPC ) )
+ {
goalNPC.s.cloakedDrone = null
+ if(IsCloaked(goalNPC))
+ goalNPC.Signal( "KillHandleCloakEnd" )
+ }
}
)
@@ -382,6 +386,9 @@ void function CloakedDronePathFollowNPC( entity cloakedDrone, entity goalNPC )
float startTime = Time()
path.goalValid = false
+ if(!IsCloaked(goalNPC))
+ CloakNPC(goalNPC)
+
CloakedDroneFindPathDefault( path, defaultHeight, mins, maxs, cloakedDrone, goalNPC, mask )
//find a new path if necessary
@@ -676,3 +683,43 @@ function IsSquadCenterClose( npc, dist = 256 )
return false
}
+
+void function CloakNPC ( entity npc )
+{
+ npc.SetCloakDuration( 1.0, -1, 1.0 )
+
+ EmitSoundOnEntity( npc, "cloak_on_3P" )
+ EmitSoundOnEntity( npc, "cloak_sustain_loop_3P" )
+
+ thread HandleNPCCloakEnd( npc )
+}
+
+void function HandleNPCCloakEnd( entity npc )
+{
+ npc.EndSignal( "OnDeath" )
+ npc.Signal( "OnStartCloak" )
+ npc.EndSignal( "OnStartCloak" )
+ npc.EndSignal( "KillHandleCloakEnd" ) //Calling DisableCloak() after EnableCloak() doesn't kill this thread by design (to allow attacking through cloak etc), so this signal is for when you want to kill this thread
+
+ OnThreadEnd(
+ function() : ( npc )
+ {
+ if ( !IsValid( npc ) )
+ return
+
+ StopSoundOnEntity( npc, "cloak_sustain_loop_3P" )
+
+ if ( !IsCloaked( npc ) )
+ return
+
+ if ( !IsAlive( npc ) || !npc.IsHuman() )
+ {
+ EmitSoundOnEntity( npc, "cloak_interruptend_3P" )
+ npc.SetCloakDuration( 0, 0, 1.0 )
+ return
+ }
+ }
+ )
+
+ WaitForever()
+}
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 fd1bbff1..8fde4343 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 )
@@ -28,10 +34,11 @@ void function EMPTitanThinkConstant( entity titan )
titan.EndSignal( "StopEMPField" )
//We don't want pilots accidently rodeoing an electrified titan.
- // DisableTitanRodeo( 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 )
@@ -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_sniper_titans.gnut b/Northstar.CustomServers/mod/scripts/vscripts/ai/_ai_sniper_titans.gnut
index 37b89169..f91699b4 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,88 @@
-//fuck \ No newline at end of file
+untyped
+
+global function MoveToSniperPosition
+global function SniperTitanThink
+
+const float SNIPER_TITAN_POSITION_SEARCH_RANGE = 2048
+
+void function MoveToSniperPosition( entity titan, vector origin, entity target )
+{
+ titan.EndSignal( "OnSyncedMeleeVictim" )
+ titan.EndSignal( "OnDeath" )
+ titan.EndSignal( "OnDestroy" )
+
+ titan.SetLookDistOverride( 320 )
+ titan.EnableNPCMoveFlag( NPCMF_PREFER_SPRINT )
+
+ float goalRadius = titan.GetMinGoalRadius()
+
+ OnThreadEnd(
+ function() : ( titan )
+ {
+ if ( !IsValid( titan ) )
+ return
+
+ local classname = titan.GetClassName()
+ titan.DisableLookDistOverride()
+ 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.SetEnemy( target )
+ local result = WaitSignal( titan, "OnFinishedAssault", "OnEnterGoalRadius" )
+ }
+}
+
+void function SniperTitanThink( entity titan, entity generator )
+{
+ titan.EndSignal( "OnSyncedMeleeVictim" )
+ titan.EndSignal( "OnDeath" )
+ titan.EndSignal( "OnDestroy" )
+
+ entity soul = titan.GetTitanSoul()
+ soul.EndSignal( "OnDestroy" )
+
+ // titan.SetScriptName( "sniper_titan" )
+
+ WaitTillHotDropComplete( titan )
+
+ float minEngagementDuration = 5
+ StationaryAIPosition ornull sniperPosition = GetRandomStationaryPosition( 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 = GetRandomStationaryPosition( titan.GetOrigin(), SNIPER_TITAN_POSITION_SEARCH_RANGE, eStationaryAIPositionTypes.SNIPER_TITAN )
+ }
+
+ expect StationaryAIPosition( sniperPosition )
+
+ ClaimStationaryAIPosition( sniperPosition )
+
+ OnThreadEnd(
+ function() : ( sniperPosition )
+ {
+ // release mortar position when dead
+ ReleaseStationaryAIPosition( sniperPosition )
+ }
+ )
+
+ while( true )
+ {
+ vector origin = sniperPosition.origin
+ titan.SetEnemy( generator )
+ waitthread MoveToSniperPosition( titan, origin, generator )
+
+ WaitForever()
+ }
+}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
index 58f497a6..e50abd16 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_fd.nut
@@ -15,6 +15,8 @@ global function createDroppodSpectreMortarEvent
global function createWaitUntilAliveEvent
global function createCloakDroneEvent
global function CreateTickEvent
+global function CreateToneSniperTitanEvent
+global function CreateNorthstarSniperTitanEvent
global struct SmokeEvent{
vector position
@@ -110,13 +112,7 @@ void function GamemodeFD_Init()
AddDamageByCallback("player",FD_DamageByPlayerCallback)
- AddDeathCallback("npc_titan",OnNpcDeath)
- AddDeathCallback("npc_stalker",OnNpcDeath)
- AddDeathCallback("npc_spectre",OnNpcDeath)
- AddDeathCallback("npc_super_spectre",OnNpcDeath)
- AddDeathCallback("npc_soldier",OnNpcDeath)
- AddDeathCallback("npc_frag_drone",OnNpcDeath)
- AddDeathCallback("npc_drone",OnNpcDeath)
+ AddCallback_OnNPCKilled(OnNpcDeath)
SetUsedCoreCallback(FD_UsedCoreCallback)
AddClientCommandCallback("FD_ToggleReady",ClientCommandCallbackToggleReady)
@@ -151,14 +147,64 @@ void function GamemodeFD_InitPlayer(entity player)
}
-void function OnNpcDeath( entity ent, var damageInfo )
+void function OnNpcDeath( entity victim, entity attacker, var damageInfo )
{
- int findIndex = file.spawnedNPCs.find( ent )
+ int findIndex = file.spawnedNPCs.find( victim )
if ( findIndex != -1 )
{
file.spawnedNPCs.remove( findIndex )
}
+ if ( victim.GetOwner() == attacker && !attacker.IsPlayer() && attacker == victim )
+ return
+
+ int playerScore = 0
+ int money = 0
+ 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": // not sure
+ 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
+ }
+ }
+ if (money != 0)
+ {
+ AddMoneyToPlayer( attacker , money )
+ print("give that fat stash babeeeee")
+ }
+
+ attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, playerScore ) // seems to be how combat score is counted
+
+ 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){}
@@ -272,6 +318,7 @@ array<int> function getEnemyTypesForWave(int wave)
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
@@ -460,6 +507,7 @@ bool function runWave(int waveIndex,bool shouldDoBuyTime)
file.players[highestScore_player].totalMVPs += 1
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())
{
@@ -473,6 +521,7 @@ bool function runWave(int waveIndex,bool shouldDoBuyTime)
{
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")
}
}
@@ -733,11 +782,12 @@ void function titanNav_thread(entity titan, string routeName,float nextDistance
if(Distance(fd_harvester.harvester.GetOrigin(),titan.GetOrigin())<Distance(fd_harvester.harvester.GetOrigin(),node.GetOrigin()))
continue
titan.AssaultPoint(node.GetOrigin())
+ titan.AssaultSetGoalRadius( 100 )
int i = 0
while((Distance(titan.GetOrigin(),node.GetOrigin())>nextDistance))
{
WaitFrame()
- //printt(Distance(titan.GetOrigin(),node.GetOrigin()))
+ // printt(Distance(titan.GetOrigin(),node.GetOrigin()))
// i++
// if(i>1200)
// {
@@ -749,6 +799,44 @@ void function titanNav_thread(entity titan, string routeName,float nextDistance
titan.Signal("FD_ReachedHarvester")
}
+void function HumanNav_Thread( entity npc )
+{
+ npc.EndSignal( "OnDeath" )
+ npc.EndSignal( "OnDestroy" )
+
+ entity generator = fd_harvester.harvester
+ float goalRadius = 100
+ float checkRadiusSqr = 400 * 400
+
+ array<vector> pos = NavMesh_GetNeighborPositions( generator.GetOrigin(), HULL_HUMAN, 5 )
+ pos = ArrayClosestVector( pos, npc.GetOrigin() )
+
+ array<vector> validPos
+ foreach ( point in pos )
+ {
+ if ( DistanceSqr( generator.GetOrigin(), point ) <= checkRadiusSqr && NavMesh_IsPosReachableForAI( npc, point ) )
+ {
+ validPos.append( point )
+ }
+ }
+
+ int posLen = validPos.len()
+ while( posLen >= 1 )
+ {
+ npc.SetEnemy( generator )
+ thread AssaultOrigin( npc, validPos[0], goalRadius )
+ npc.AssaultSetFightRadius( goalRadius )
+
+ wait 0.5
+
+ if ( DistanceSqr( npc.GetOrigin(), generator.GetOrigin() ) > checkRadiusSqr )
+ continue
+
+ break
+ }
+ npc.Signal("FD_ReachedHarvester")
+}
+
bool function allPlayersReady()
{
foreach(entity player in GetPlayerArray())
@@ -802,6 +890,37 @@ int function getHintForTypeId(int typeId)
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 "npc_titan_arc"
+ case eFD_AITypeIDs.RONIN:
+ return "npc_titan_stryder_leadwall"
+ case eFD_AITypeIDs.TITAN_MORTAR:
+ return "npc_titanmortar"
+ case eFD_AITypeIDs.TONE:
+ return "npc_titan_atlas_tracker"
+ case eFD_AITypeIDs.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"
+ default:
+ return "titan"
+ }
+ unreachable
+}
+
/****************************************************************************************************************\
####### # # ####### # # ####### ##### ####### # # ####### ###### # ####### ####### ######
# # # # ## # # # # # ## # # # # # # # # # # #
@@ -979,6 +1098,30 @@ WaveEvent function CreateTickEvent( vector origin, vector angles, int amount = 4
return event
}
+WaveEvent function CreateNorthstarSniperTitanEvent(vector origin,vector angles)
+{
+ WaveEvent event
+ event.eventFunction = spawnSniperTitan
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TITAN_SNIPER
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ return event
+}
+
+WaveEvent function CreateToneSniperTitanEvent(vector origin,vector angles)
+{
+ WaveEvent event
+ event.eventFunction = SpawnToneSniperTitan
+ event.shouldThread = true
+ event.spawnEvent.spawnType= eFD_AITypeIDs.TITAN_SNIPER
+ event.spawnEvent.spawnAmount = 1
+ event.spawnEvent.origin = origin
+ event.spawnEvent.angles = angles
+ return event
+}
+
/************************************************************************************************************\
####### # # ####### # # ####### ####### # # # # ##### ####### ### ####### # # #####
# # # # ## # # # # # ## # # # # # # # ## # # #
@@ -1011,9 +1154,13 @@ void function spawnArcTitan(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEven
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")
file.spawnedNPCs.append(npc)
DispatchSpawn(npc)
+ npc.Minimap_AlwaysShow( TEAM_IMC, null )
+ npc.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
thread titanNav_thread(npc,spawnEvent.route)
thread EMPTitanThinkConstant(npc)
}
@@ -1048,7 +1195,7 @@ void function spawnSuperSpectre(SmokeEvent smokeEvent,SpawnEvent spawnEvent,Wait
void function spawnDroppodGrunts(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
{
PingMinimap(spawnEvent.origin.x, spawnEvent.origin.y, 4, 600, 150, 0)
- thread CreateTrackedDroppodSoldier(spawnEvent.origin,TEAM_IMC)
+ thread CreateTrackedDroppodSoldier(spawnEvent.origin,TEAM_IMC, spawnEvent.route)
}
void function spawnDroppodStalker(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
@@ -1074,8 +1221,14 @@ void function spawnGenericNPCTitanwithSettings(SmokeEvent smokeEvent,SpawnEvent
{
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)
+ npc.Minimap_AlwaysShow( TEAM_IMC, null )
+ npc.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
file.spawnedNPCs.append(npc)
}
@@ -1085,9 +1238,13 @@ void function spawnNukeTitan(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEve
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)
DispatchSpawn(npc)
file.spawnedNPCs.append(npc)
+ npc.Minimap_AlwaysShow( TEAM_IMC, null )
+ npc.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
thread titanNav_thread(npc,spawnEvent.route)
thread NukeTitanThink(npc,fd_harvester.harvester)
@@ -1100,8 +1257,12 @@ void function spawnMortarTitan(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitE
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)
file.spawnedNPCs.append(npc)
+ npc.Minimap_AlwaysShow( TEAM_IMC, null )
+ npc.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
thread MortarTitanThink(npc,fd_harvester.harvester)
}
@@ -1111,11 +1272,32 @@ void function spawnSniperTitan(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitE
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)
file.spawnedNPCs.append(npc)
- thread MortarTitanThink(npc,fd_harvester.harvester)
+ npc.Minimap_AlwaysShow( TEAM_IMC, null )
+ npc.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread SniperTitanThink(npc,fd_harvester.harvester)
+
+}
+
+void function SpawnToneSniperTitan(SmokeEvent smokeEvent,SpawnEvent spawnEvent,WaitEvent waitEvent,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 )
+ file.spawnedNPCs.append(npc)
+ npc.Minimap_AlwaysShow( TEAM_IMC, null )
+ npc.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ npc.GetTitanSoul().SetTitanSoulNetBool( "showOverheadIcon", true )
+ thread SniperTitanThink(npc,fd_harvester.harvester)
}
+
void function fd_spawnCloakDrone(SmokeEvent smokeEffect,SpawnEvent spawnEvent,WaitEvent waitEvent,SoundEvent soundEvent)
{
entity npc = SpawnCloakDrone( TEAM_IMC, spawnEvent.origin, spawnEvent.angles, file.harvester_info.GetOrigin() )
@@ -1150,7 +1332,7 @@ void function spawnSuperSpectre_threaded(entity npc)
thread ReaperMinionLauncherThink(npc)
}
-void function CreateTrackedDroppodSoldier( vector origin, int team)
+void function CreateTrackedDroppodSoldier( vector origin, int team, string route = "")
{
@@ -1161,6 +1343,7 @@ void function CreateTrackedDroppodSoldier( vector origin, int team)
string squadName = MakeSquadName( team, UniqueString( "ZiplineTable" ) )
array<entity> guys
+ bool adychecked = false
for ( int i = 0; i < 4; i++ )
{
@@ -1168,9 +1351,17 @@ void function CreateTrackedDroppodSoldier( vector origin, int team)
SetTeam( guy, team )
guy.EnableNPCFlag( NPC_ALLOW_PATROL | NPC_ALLOW_INVESTIGATE | NPC_ALLOW_HAND_SIGNALS | NPC_ALLOW_FLEE )
+ guy.EnableNPCMoveFlag(NPCMF_WALK_ALWAYS)
DispatchSpawn( guy )
- SetSquad( guy, squadName )
+ guy.SetParent( pod, "ATTACH", true )
+ SetSquad( guy, squadName )
+
+ thread HumanNav_Thread(guy)
+
+ guy.Minimap_AlwaysShow( TEAM_IMC, null )
+ guy.Minimap_AlwaysShow( TEAM_MILITIA, null )
+ file.spawnedNPCs.append(guy)
guys.append( guy )
}
@@ -1247,13 +1438,13 @@ void function CreateTrackedDroppodTick( vector origin, int team, string route =
SetSpawnOption_AISettings(guy, "npc_frag_drone_fd")
SetTeam( guy, team )
guy.EnableNPCFlag( NPC_ALLOW_PATROL | NPC_ALLOW_INVESTIGATE )
- guy.EnableNPCMoveFlag(NPCMF_WALK_ALWAYS)
+ guy.EnableNPCMoveFlag(NPCMF_WALK_ALWAYS | NPCMF_PREFER_SPRINT)
DispatchSpawn( guy )
-
+ guy.Minimap_AlwaysShow( TEAM_IMC, null )
+ guy.Minimap_AlwaysShow( TEAM_MILITIA, null )
SetSquad( guy, squadName )
- if (route != "")
- thread titanNav_thread(guy, route) // not working i think
+ thread HumanNav_Thread(guy) // not working i think
guys.append( guy )
}
@@ -1272,28 +1463,47 @@ void function waitUntilLessThanAmountAlive(int amount)
{
printt("start wait")
int aliveTitans = file.spawnedNPCs.len()
-
+ float lasttime = Time()
while(aliveTitans>amount)
{
WaitFrame()
aliveTitans = file.spawnedNPCs.len()
if(!IsAlive(fd_harvester.harvester))
break
- printt("titans alive ", aliveTitans)
+ if (Time() > lasttime + 5) // stop log spam
+ {
+ printt("npcs alive ", aliveTitans)
+ lasttime = Time()
+ }
}
}
void function waitUntilLessThanAmountAlive_expensive(int amount)
{
printt("start wait")
- int aliveTitans = GetEntArrayByClassWildCard_Expensive("*npc*").len()
-
+ array<entity> npcs = GetEntArrayByClassWildCard_Expensive("*npc*")
+ int deduct = 0
+ for ( int i = npcs.len() - 1; i >= 0; i-- )
+ {
+ entity npc = npcs[i]
+ if (IsValid(GetPetTitanOwner( npc )))
+ {
+ print("found player npc titan")
+ deduct++
+ }
+ }
+ float lasttime = Time()
+ int aliveTitans = npcs.len()
while(aliveTitans>amount)
{
WaitFrame()
- aliveTitans = GetEntArrayByClassWildCard_Expensive("*npc*").len()
+ aliveTitans = GetEntArrayByClassWildCard_Expensive("*npc*").len() - deduct
if(!IsAlive(fd_harvester.harvester))
break
- printt("titans alive ", aliveTitans)
+ if (Time() > lasttime + 5) // stop log spam
+ {
+ printt("npcs alive ", aliveTitans)
+ lasttime = Time()
+ }
}
}
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 9fe18045..341cfc21 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
@@ -3,9 +3,7 @@ global function initFrontierDefenseData
void function initFrontierDefenseData()
{
- shopPosition = < -3862.13, 1267.69, 1060.06>
-
-
+ shopPosition = < -3862.13, 1267.69, 1060.06 >
array<WaveEvent> wave0
array<WaveEvent> wave1
@@ -13,18 +11,68 @@ void function initFrontierDefenseData()
array<WaveEvent> wave3
array<WaveEvent> wave4
- wave0.append(createSuperSpectreEvent(< -64, 964, 1456>, < 0,0,0 >, "hillRouteClose"))
-
- //wave0.append(createSmokeEvent(< -12, 1720, 1456>,30))
- // wave0.append(createSmokeEvent(< -64, 964, 1456>,30))
- // wave0.append(createWaitForTimeEvent(10))
- // wave0.append(createSuperSpectreEvent(< -64, 964, 1456>,<0,0,0>,""))
-
-
+ //wave0.append(createSuperSpectreEvent(< -64, 964, 1456>, <0,0,0 >, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 865, 694, 1380>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 885, 1722, 1377>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1226, 1391, 1355>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1258, 922, 1331>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1117, 330, 1372>, "hillRouteClose"))
+
+ wave0.append(createSmokeEvent(< -12, 1720, 1456>,30))
+ wave0.append(createSmokeEvent(< -64, 964, 1456>,30))
+
+ wave0.append(createWaitForTimeEvent(7))
+ wave0.append(createWaitUntilAliveEvent(1))
+
+ wave0.append(createDroppodGruntEvent( < 1309, 2122, 1324>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 985, -110, 1369>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 264, 2840, 968>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 2193, 434, 955>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 909, 3094, 968>, "hillRouteClose"))
+
+ wave0.append(createWaitForTimeEvent(7))
+ wave0.append(createWaitUntilAliveEvent(1))
+
+ wave0.append(createDroppodGruntEvent( < 865, 694, 1380>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 885, 1722, 1377>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1226, 1391, 1355>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1258, 922, 1331>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1117, 330, 1372>, "hillRouteClose"))
+
+ wave0.append(createWaitForTimeEvent(7))
+ wave0.append(createWaitUntilAliveEvent(1))
+
+ wave0.append(createDroppodGruntEvent( < 1309, 2122, 1324>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 985, -110, 1369>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 264, 2840, 968>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 2193, 434, 955>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 909, 3094, 968>, "hillRouteClose"))
+
+ wave0.append(createWaitForTimeEvent(7))
+ wave0.append(createWaitUntilAliveEvent(1))
+
+ wave0.append(createDroppodGruntEvent( < 865, 694, 1380>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 885, 1722, 1377>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1226, 1391, 1355>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1258, 922, 1331>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 1117, 330, 1372>, "hillRouteClose"))
+
+ wave0.append(createWaitForTimeEvent(7))
+ wave0.append(createWaitUntilAliveEvent(1))
+
+ wave0.append(createDroppodGruntEvent( < 1309, 2122, 1324>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 985, -110, 1369>, "hillRouteClose"))
+ wave0.append(createDroppodGruntEvent( < 264, 2840, 968>, "hillRouteClose"))
+ wave0.append(CreateToneSniperTitanEvent( < 1373, 1219, 1314>, <0,0,0>))
+ // wave0.append(CreateTickEvent( < -64, 964, 1458>, <0,0,0>, 4, "hillRouteClose" ))
+ wave0.append(createWaitForTimeEvent(10))
+
+ // wave0.append(CreateTickEvent( < -64, 964, 1458>, <0,0,0>, 56, "hillRouteClose" ))
//wave0.append(createMortarTitanEvent(< 1632, 4720, 944>,<0,0,0>))
- //.append(createCloakDroneEvent(< 1632, 4720, 1200>,<0,0,0>))
wave0.append(createWaitUntilAliveEvent(0))
- wave1.append(createArcTitanEvent(< -12, 1720, 1456>,<0,0,0>,"hillRouteClose"))
+ wave1.append(createArcTitanEvent(< -12, 1720, 1456>,<0,0,0>, "hillRouteClose"))
+ wave1.append(createNukeTitanEvent( < -64, 964, 1456>,<0,0,0>, "hillRouteClose"))
+ wave1.append(createCloakDroneEvent(< 1632, 4720, 1200>,<0,0,0>))
wave1.append(createWaitUntilAliveEvent(0))
// wave0.append(createArcTitanEvent(< -12, 1720, 1456>,<0,0,0>,"hillRouteClose"))
@@ -32,7 +80,7 @@ void function initFrontierDefenseData()
//wave0.append(createDroppodStalkerEvent(< -12, 1720, 1456>,""))
waveEvents.append(wave0)
-
+
//waveEvents.append(wave0)
waveEvents.append(wave1)
//waveEvents.append(wave2)
@@ -62,4 +110,4 @@ void function initFrontierDefenseData()
waveEvents.append(wave2)
waveEvents.append(wave3)
waveEvents.append(wave4)
-}*/ \ No newline at end of file
+}*/