diff options
author | x3Karma <juliuslimck@gmail.com> | 2022-05-12 19:49:09 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-12 13:49:09 +0200 |
commit | dd4a613adb63b30b50a86c0e9a359cb9025351d1 (patch) | |
tree | 787913d6a20376a3f1e418f37cbe8a55066c1889 /Northstar.CustomServers | |
parent | 9d77289574cf8e410ec66264c1d7bd542fa5d6d7 (diff) | |
download | NorthstarMods-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')
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 +}*/ |