aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/scripts/vscripts/_on_spawned.gnut
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/_on_spawned.gnut')
-rw-r--r--Northstar.CustomServers/scripts/vscripts/_on_spawned.gnut508
1 files changed, 508 insertions, 0 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/_on_spawned.gnut b/Northstar.CustomServers/scripts/vscripts/_on_spawned.gnut
new file mode 100644
index 000000000..d1935d629
--- /dev/null
+++ b/Northstar.CustomServers/scripts/vscripts/_on_spawned.gnut
@@ -0,0 +1,508 @@
+untyped
+
+global function CodeCallback_PreSpawn
+global function CodeCallback_OnSpawned
+global function RunMySpawnFunctions
+global function AddScriptNoteworthySpawnCallback
+global function SpawnFromSpawnerArray
+global function AddSpawnCallback
+global function AddSpawnCallbackEditorClass
+global function AddSpawnCallback_ScriptName
+global function GetLeveledAISettings
+global function GetSpawnAISettings
+global function GetDefaultAISetting
+
+void function CodeCallback_PreSpawn( entity npc )
+{
+ /*
+ SCRIPTERS READ THIS
+
+ The purpose of this function is to fixup npc fields coming from all the many places they can come from, so that code doesn't break them during DispatchSpawn.
+ If you want to fix an AI field on spawned, you should do it in ai_spawn_content, unless the field change is related to code functionality and needs
+ to change before code spawns the AI. Then, it should be here.
+
+ Thanks
+ -Mackey
+ */
+ Assert( npc.IsNPC() )
+
+ if ( !npc.HasAISettings() )
+ {
+ // this ai has no ai settings file
+ string aisettings = GetDefaultAISetting( npc )
+ Assert( aisettings != "" )
+ SetAISettingsWrapper( npc, aisettings )
+ }
+
+ if ( npc.IsTitan() )
+ {
+ if ( npc.ai.titanSettings.titanSetFile == "" )
+ {
+ if ( npc.HasKey( "leveled_titan_settings" ) )
+ {
+ SetTitanSettings( npc.ai.titanSettings, expect string( npc.kv.leveled_titan_settings ) )
+ }
+ }
+
+ var builtInLoadout
+
+ if ( npc.HasKey( "leveled_titan_loadout" ) )
+ {
+ builtInLoadout = npc.GetValueForKey( "leveled_titan_loadout" )
+ }
+ else
+ {
+ if ( npc.Dev_GetAISettingByKeyField( "WeaponCapacity" ) == "FromLoadout" )
+ builtInLoadout = npc.Dev_GetAISettingByKeyField( "npc_titan_player_settings" )
+ }
+
+ if ( builtInLoadout != null )
+ {
+ // derive loadout from built in loadout in this case
+ expect string( builtInLoadout )
+ if ( npc.ai.titanSettings.titanSetFile != builtInLoadout )
+ SetTitanSettings( npc.ai.titanSettings, builtInLoadout )
+
+ npc.ai.titanSpawnLoadout.setFile = builtInLoadout
+ // OverwriteLoadoutWithDefaultsForSetFile_ExceptSpecialAndAntiRodeo( npc.ai.titanSpawnLoadout )
+ OverwriteLoadoutWithDefaultsForSetFile( npc.ai.titanSpawnLoadout ) // get the entire loadout, including defensive and tactical
+
+ //Set camo, decal, and skin indices from npc settings.
+ //Using Dev_GetAISettingsByKeyField_Global because titan has not spawned yet, so the non-global version of this function does not work.
+ var camoIndex = Dev_GetAISettingByKeyField_Global( npc.GetAISettingsName(), "titanCamoIndex" )
+ var decalIndex = Dev_GetAISettingByKeyField_Global( npc.GetAISettingsName(), "titanDecalIndex" )
+ var skinIndex = Dev_GetAISettingByKeyField_Global( npc.GetAISettingsName(), "titanSkinIndex" )
+ if ( camoIndex != null )
+ npc.ai.titanSpawnLoadout.camoIndex = expect int ( camoIndex )
+ if ( decalIndex != null )
+ npc.ai.titanSpawnLoadout.decalIndex = expect int ( decalIndex )
+ if ( skinIndex != null )
+ npc.ai.titanSpawnLoadout.skinIndex = expect int ( skinIndex )
+ }
+
+ AssignSpawnOptionsFromLeveled( npc, SetSpawnOption_Weapon, "additionalequipment", "primaryWeapon_mods" )
+ npc.kv.additionalequipment = ""
+ AssignSpawnOptionsFromLeveled( npc, SetSpawnOption_Ordnance, "titanOrdnance", "titanOrdnance_mods" )
+ AssignSpawnOptionsFromLeveled( npc, SetSpawnOption_Special, "titanSpecial", "titanSpecial_mods" )
+ AssignSpawnOptionsFromLeveled( npc, SetSpawnOption_Antirodeo, "titanAntiRodeo", "titanAntiRodeo_mods" )
+
+ // temp fix for npc_create npc_titan, probably should refactor away npc.ai.titanSettings
+ if ( npc.ai.titanSettings.titanSetFile == "" )
+ SetTitanSettings( npc.ai.titanSettings, expect string( npc.Dev_GetAISettingByKeyField( "npc_titan_player_settings" ) ) )
+
+ CreateTitanModelAndSkinSetup( npc )
+
+ if ( npc.GetAIClass() == AIC_TITAN_BUDDY )
+ npc.kv.squadname = "bt"
+ }
+ else
+ {
+ npc.SetValueForModelKey( npc.GetSettingModelName() )
+ }
+
+ if ( !IsTurret( npc ) && IsSingleplayer() && npc.kv.squadname == "" && npc.GetTeam() >= FIRST_GAME_TEAM )
+ npc.SetAutoSquad()
+ //AutoSquadnameAssignment( npc )
+
+ if ( !npc.IsTitan() )
+ {
+ AssignGrenadeWeaponFromAISettings( npc )
+
+ AssignDroneSpawnAISettings( npc )
+
+ if ( npc.ai.mySpawnOptions_weapon == null )
+ {
+ if ( !IsTurret( npc ) )
+ {
+ NPCDefaultWeapon ornull defaultWeapon = GetNPCDefaultWeaponForLevel( npc )
+ if ( defaultWeapon != null )
+ {
+ expect NPCDefaultWeapon( defaultWeapon )
+ SetSpawnOption_Weapon( npc, defaultWeapon.wep, defaultWeapon.mods )
+ npc.kv.additionalequipment = ""
+ return
+ }
+ }
+
+ switch ( npc.kv.additionalequipment )
+ {
+ case "":
+ case "auto_weapon":
+ case "auto_weapon_antititan":
+ case "auto_weapon_sidearm":
+ case "auto_weapon_rifle":
+ case "auto_weapon_lmg":
+ case "auto_weapon_shield_captain":
+ case "auto_weapon_shotgun":
+ case "auto_weapon_smg":
+ case "auto_weapon_sniper":
+ case "auto_weapon_specialist":
+
+ // fill weapon in from ai settings file
+ npc.kv.additionalequipment = ""
+ string aiSettingsWeapon = npc.AISetting_GetDefaultWeapon()
+ if ( aiSettingsWeapon != "" )
+ SetSpawnOption_Weapon( npc, aiSettingsWeapon )
+ break
+
+ case "none":
+ npc.kv.additionalequipment = ""
+ break
+ }
+ }
+ }
+}
+
+void function AssignDroneSpawnAISettings( entity npc )
+{
+ if ( npc.HasKey( "script_drone_type" ) )
+ {
+ var droneType = npc.kv.script_drone_type
+ if ( droneType != null )
+ {
+ expect string( droneType )
+ if ( droneType.tolower() == "none" )
+ droneType = ""
+ npc.ai.droneSpawnAISettings = droneType
+ }
+ return
+ }
+
+ npc.ai.droneSpawnAISettings = npc.AISetting_SummonDrone()
+}
+
+
+void function AssignGrenadeWeaponFromAISettings( entity npc )
+{
+ if( npc.kv.grenadeWeaponName == "none" )
+ {
+ npc.kv.grenadeWeaponName = ""
+ return
+ }
+
+ if ( npc.kv.GrenadeWeaponName != "" )
+ return
+
+ string grenadeWeaponName = npc.AISetting_GetGrenadeWeapon()
+ if ( grenadeWeaponName == "" )
+ return
+
+ npc.kv.grenadeWeaponName = grenadeWeaponName
+}
+
+void function AssignSpawnOptionsFromLeveled( entity npc, void functionref( entity, string, array<string> = 0 ) spawnSettingsFunc, string kvWeapon, string kvWeaponMods )
+{
+ if ( !npc.HasKey( kvWeapon ) )
+ return
+ string weapon = npc.GetValueForKey( kvWeapon )
+ if ( weapon == "" )
+ return
+
+ array<string> mods
+ if ( npc.HasKey( kvWeaponMods ) )
+ {
+ mods = split( npc.GetValueForKey( kvWeaponMods ), " " )
+ }
+
+ spawnSettingsFunc( npc, weapon, mods )
+}
+
+string function GetDefaultAISetting( entity npc )
+{
+// change this to map directly by file name from subClass, and error if its not there.
+// This insures consistent settings file naming and makes settings files less of a mix-and-match concept.
+// subclasses should also sub-name off their class (except for craaaaaazy soldier/grunt guy)
+
+ if ( npc.mySpawnOptions_aiSettings != null )
+ {
+ // you have to include base if you use SpawnOption_AISettings
+ return string( npc.mySpawnOptions_aiSettings )
+ }
+
+ if ( npc.HasKey( "leveled_aisettings" ) )
+ {
+ return GetLeveledAISettings( npc )
+ }
+
+ if ( npc.IsTitan() && npc.ai.titanSettings.titanSetFile != "" )
+ {
+ // from titan player set file
+ string settingsKey = GetAISettingsStringForMode()
+
+ var aiSettings = Dev_GetPlayerSettingByKeyField_Global( npc.ai.titanSettings.titanSetFile, settingsKey )
+ if ( aiSettings != null )
+ return expect string( aiSettings )
+ }
+
+ return npc.GetClassName()
+}
+
+string function GetLeveledAISettings( entity npc )
+{
+ Assert( npc.IsNPC() )
+ Assert( npc.HasKey( "leveled_aisettings" ) )
+ string settings = expect string( npc.kv.leveled_aisettings )
+ switch ( settings )
+ {
+ // remap deprecated substrings for awhile
+ case "npc_soldier_drone_summoner_shield":
+ return "npc_soldier_drone_summoner"
+ }
+ return settings
+}
+
+string function GetSpawnAISettings( entity npc )
+{
+ if ( npc.mySpawnOptions_aiSettings != null)
+ return expect string( npc.mySpawnOptions_aiSettings )
+ else if ( npc.HasKey( "leveled_aisettings" ) )
+ return expect string( npc.kv.leveled_aisettings )
+
+ return ""
+}
+
+void function CodeCallback_OnSpawned( entity ent )
+{
+ if ( IsSpawner( ent ) )
+ {
+ var spawnerKVs = ent.GetSpawnEntityKeyValues()
+ if ( "script_flag_killed" in spawnerKVs )
+ thread SetupFlagKilledForNPC( ent )
+ return
+ }
+
+ string classname = ent.GetClassName()
+
+ if ( classname in _entityClassVars )
+ {
+ if ( !ent._entityVars )
+ InitEntityVars( ent )
+
+ //ent.ConnectOutput( "OnDestroy", "_RemoveFromEntityList" )
+ }
+
+ int teamNum = int( expect string( ent.kv.teamnumber ) )
+ if ( teamNum != 0 )
+ SetTeam( ent, teamNum )
+
+ SetModelSkinFromLeveled( ent )
+
+ if ( IsLobby() )
+ {
+ RunMySpawnFunctions( ent )
+ return
+ }
+
+ if ( ent.IsNPC() )
+ {
+ CommonNPCOnSpawned( ent )
+ }
+
+ if ( ent instanceof CBaseCombatCharacter && ent.GetModelName() != $"" )
+ InitDamageStates( ent )
+
+ if ( ent instanceof CProjectile || ent instanceof CBaseGrenade )
+ thread PROTO_InitTrackedProjectile( ent )
+
+ /*
+ if ( !( "totalSpawned" in level ) )
+ {
+ level.totalSpawned <- {}
+ level.totalSpawned.total <- 0
+ }
+
+ if ( !( "classname" in level.totalSpawned ) )
+ {
+ level.totalSpawned[ classname ] <- {}
+ }
+
+ level.totalSpawned[ classname ][ ent ] <- ent
+ level.totalSpawned.total++
+ */
+
+ RegisterForDamageDeathCallbacks( ent )
+
+ RunMySpawnFunctions( ent )
+}
+
+function RunMySpawnFunctions( entity self )
+{
+ if ( !IsValid( self ) )
+ {
+ // entity was deleted already
+ return
+ }
+
+ RunSpawnCallbacks( self )
+ RunEditorClassCallbacks( self )
+ RunScriptNoteworthyCallbacks( self )
+ RunScriptNameCallbacks( self )
+}
+
+void function AddSpawnCallback( string classname, void functionref( entity ) func )
+{
+ foreach ( spawnCallbackFuncArray funcArray in svGlobal.spawnCallbackFuncs )
+ {
+ if ( funcArray.entityClassname == classname )
+ {
+ funcArray.callbackArray.append( func )
+ return
+ }
+ }
+
+ spawnCallbackFuncArray funcArray
+ funcArray.entityClassname = classname
+ funcArray.callbackArray.append( func )
+ svGlobal.spawnCallbackFuncs.append( funcArray )
+}
+
+void function AddSpawnCallbackEditorClass( string classname, string editorClassname, void functionref( entity ) func )
+{
+ foreach ( spawnCallbackEditorClassFuncArray funcArray in svGlobal.spawnCallbackEditorClassFuncs )
+ {
+ if ( funcArray.entityClassname == classname && funcArray.entityEditorClassname == editorClassname )
+ {
+ funcArray.callbackArray.append( func )
+ return
+ }
+ }
+
+ spawnCallbackEditorClassFuncArray funcArray
+ funcArray.entityClassname = classname
+ funcArray.entityEditorClassname = editorClassname
+ funcArray.callbackArray.append( func )
+ svGlobal.spawnCallbackEditorClassFuncs.append( funcArray )
+}
+
+function RunSpawnCallbacks( entity self )
+{
+ string classname = self.GetClassName()
+
+ foreach ( spawnCallbackFuncArray funcArray in svGlobal.spawnCallbackFuncs )
+ {
+ if ( funcArray.entityClassname == classname )
+ {
+ foreach ( func in funcArray.callbackArray )
+ {
+ func( self )
+ }
+ }
+ }
+}
+
+function RunEditorClassCallbacks( entity self )
+{
+ string editorClassname = GetEditorClass( self )
+ if ( editorClassname == "" )
+ return
+
+ string classname = self.GetClassName()
+
+ foreach ( spawnCallbackEditorClassFuncArray funcArray in svGlobal.spawnCallbackEditorClassFuncs )
+ {
+ if ( funcArray.entityEditorClassname == editorClassname )
+ {
+ //Assert( funcArray.entityClassname == classname, "Editor classname callback was set on entity with wrong base classname type" )
+ if ( funcArray.entityClassname != classname )
+ CodeWarning( "Entity " + editorClassname + " is expecting alias of " + funcArray.entityClassname + " but found a " + classname + ". You may just need to reexport from LevelEd and recompile the map to fix this." )
+
+ foreach ( func in funcArray.callbackArray )
+ {
+ thread func( self )
+ }
+ }
+ }
+}
+
+array<entity> function SpawnFromSpawnerArray( array<entity> spawners, void functionref( entity ) ornull spawnSettingsFunc = null )
+{
+ array<entity> spawned
+ if ( spawnSettingsFunc == null )
+ {
+ foreach ( entity spawner in spawners )
+ {
+ entity ent = spawner.SpawnEntity()
+ DispatchSpawn( ent )
+ spawned.append( ent )
+ }
+ }
+ else
+ {
+ expect void functionref( entity )( spawnSettingsFunc )
+ foreach ( entity spawner in spawners )
+ {
+ entity ent = spawner.SpawnEntity()
+ spawnSettingsFunc( ent )
+ DispatchSpawn( ent )
+ spawned.append( ent )
+ }
+ }
+
+ return spawned
+}
+
+void function RunScriptNameCallbacks( entity ent )
+{
+ string name = ent.GetScriptName()
+ if ( !( name in svGlobal.spawnCallbacks_scriptName ) )
+ return
+
+ foreach ( callback in svGlobal.spawnCallbacks_scriptName[ name ] )
+ {
+ thread callback( ent )
+ }
+}
+
+void function AddSpawnCallback_ScriptName( string scriptName, void functionref( entity ) func )
+{
+ if ( !( scriptName in svGlobal.spawnCallbacks_scriptName ) )
+ svGlobal.spawnCallbacks_scriptName[ scriptName ] <- []
+ svGlobal.spawnCallbacks_scriptName[ scriptName ].append( func )
+}
+
+void function RunScriptNoteworthyCallbacks( entity ent )
+{
+ if ( !( ent.HasKey( "script_noteworthy" ) ) )
+ return
+
+ foreach ( noteworthyCallback in svGlobal.spawnCallbackFuncs_scriptNoteworthy )
+ {
+ if ( ent.kv.script_noteworthy != noteworthyCallback.scriptNoteworthy )
+ continue
+
+ foreach ( func in noteworthyCallback.callbackArray )
+ {
+ func( ent )
+ }
+
+ break // ??? break?
+ }
+}
+
+void function AddScriptNoteworthySpawnCallback( string script_noteworthy, void functionref( entity ) func )
+{
+ foreach ( noteworthyCallback in svGlobal.spawnCallbackFuncs_scriptNoteworthy )
+ {
+ if ( script_noteworthy != noteworthyCallback.scriptNoteworthy )
+ continue
+
+ noteworthyCallback.callbackArray.append( func )
+ return
+ }
+
+ spawnCallbackFuncArray_scriptNoteworthy newNoteworthyCallback
+ newNoteworthyCallback.scriptNoteworthy = script_noteworthy
+ newNoteworthyCallback.callbackArray.append( func )
+ svGlobal.spawnCallbackFuncs_scriptNoteworthy.append( newNoteworthyCallback )
+}
+
+void function SetModelSkinFromLeveled( entity ent )
+{
+ // Hack that we have to wait a frame for it to work. Code should just do this for us anyways.
+ if ( !ent.HasKey( "modelskin" ) )
+ return
+
+ int skin = expect int( ent.kv.modelskin.tointeger() )
+ if ( skin > 0 )
+ ent.SetSkin( skin )
+}