diff options
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/pilot')
5 files changed, 0 insertions, 2250 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/pilot/_leeching.gnut b/Northstar.CustomServers/scripts/vscripts/pilot/_leeching.gnut deleted file mode 100644 index c9d1f9dd..00000000 --- a/Northstar.CustomServers/scripts/vscripts/pilot/_leeching.gnut +++ /dev/null @@ -1,493 +0,0 @@ -global function Leeching_Init - -global function DoLeechAnimEvent -global function DoLeech -global function TryLeechAbortCallback -global function StartLeechingProgress -global function StopLeechingProgress -global function EnableLeeching -global function DisableLeeching -global function MarvinWeaponsFree -global function GetLeechedEnts -global function DataKnifeSuccessSounds -global function DataKnifeCanceledSounds - -global function GetTeamLeechedEnts - -// _leeching.nut -// sets up global stuff for leeching -global const MARVIN_EMOTE_SOUND_HAPPY = "diag_spectre_gs_LeechEnd_01_1" -global const MARVIN_EMOTE_SOUND_SAD = "diag_spectre_gs_LeechAborted_01_1" -global const MARVIN_EMOTE_SOUND_PAIN = "diag_spectre_gs_LeechStart_01_1" - -#if MP -global const bool WIFI_HACK_OVERFLOW_DIES = false // Kill a random leeched ent from within the team, exluding the current target, to create a new team member when hacked -#elseif SP -global const bool WIFI_HACK_OVERFLOW_DIES = true -#endif - -struct LeechFuncInfo -{ - string classname - void functionref(entity,entity) DoLeech - void functionref(entity,entity) LeechStart - void functionref(entity,entity) LeechAbort -} - -struct -{ - table<string, LeechFuncInfo> leechFuncs -} file - -void function Leeching_Init() -{ - RegisterSignal( "OnLeeched" ) - RegisterSignal( "OnStartLeech" ) - RegisterSignal( "OnStopLeeched" ) - RegisterSignal( "EnableLeeching" ) - - // Spectre leech - LeechFuncInfo spectre - spectre.classname = "npc_spectre" - spectre.DoLeech = LeechGeneric - spectre.LeechStart = LeechStartGeneric - spectre.LeechAbort = LeechAbortGeneric - file.leechFuncs[spectre.classname] <- spectre - - // Reaper leech - LeechFuncInfo reaper - reaper.classname = "npc_super_spectre" - reaper.DoLeech = LeechGeneric - reaper.LeechStart = LeechStartGeneric - reaper.LeechAbort = LeechAbortGeneric - file.leechFuncs[reaper.classname] <- reaper - - // Drone leech - LeechFuncInfo drone - drone.classname = "npc_drone" - drone.DoLeech = LeechGeneric - drone.LeechStart = LeechStartGeneric - drone.LeechAbort = LeechAbortGeneric - file.leechFuncs[drone.classname] <- drone - - // Gunship leech - LeechFuncInfo gunship - gunship.classname = "npc_gunship" - gunship.DoLeech = LeechGeneric - gunship.LeechStart = LeechStartGeneric - gunship.LeechAbort = LeechAbortGeneric - file.leechFuncs[gunship.classname] <- gunship - - LeechFuncInfo relay - relay.classname = "logic_relay" - relay.DoLeech = Leech_LogicRelay - file.leechFuncs[relay.classname] <- relay - - LeechFuncInfo physbox - physbox.classname = "func_physbox" - physbox.DoLeech = Leech_FuncPhysbox - file.leechFuncs[physbox.classname] <- physbox -} - -void function EnableLeeching( entity self ) -{ - self.SetUsePrompts( "#DEFAULT_HACK_HOLD_PROMPT", "#DEFAULT_HACK_HOLD_PROMPT" ) - - Leech_SetLeechable( self ) -} - -void function DisableLeeching( entity self ) -{ - if ( !IsValid_ThisFrame( self ) ) - return - - self.SetUsePrompts( " ", " " ) - - Leech_ClearLeechable( self ) -} - -void function StartLeechingProgress( entity self, entity leecher ) -{ - self.Signal( "OnStartLeech" ) - leecher.Signal( "OnStartLeech" ) - self.ai.leechInProgress = true - self.ai.leechStartTime = Time() - - TryLeechStartCallback( self, leecher ) -} - -void function StopLeechingProgress( entity self ) -{ - self.ai.leechInProgress = false - self.ai.leechStartTime = -1 -} - -// called when any entity gets leeched -void function DoLeechAnimEvent( entity self ) -{ - entity leecher = expect entity( GetOptionalAnimEventVar( self, "leech_switchteam" ) ) - - DoLeech( self, leecher ) -} - -void function DoLeech( entity self, entity leecher ) -{ - if ( !IsLeechable( self ) ) - EnableLeeching( self ) - - Assert( "s" in self, "Self " + self + " has no .s" ) - Assert( leecher ) - - // DEPRECATED- no scripts are currently using the results.player functionality- slayback - // logic_relays get Triggered when the object is leeched - //local results = {} - //results.player <- leecher - //self.Signal( "OnLeeched", results ) - //leecher.Signal( "OnLeeched", results ) - - Signal( self, "OnLeeched" ) - Signal( leecher, "OnLeeched" ) - - //DisableLeeching( self ) - - //_EnableLeechedPointMessage() - - if ( leecher.IsPlayer() ) - { - if ( self.IsNPC() ) - self.SetBossPlayer( leecher ) - - TableRemoveDeadByKey( leecher.p.leechedEnts ) - - leecher.p.leechedEnts[ self ] <- self - - // this will kill a random leeched ent from within the team, exluding the current target. - if ( WIFI_HACK_OVERFLOW_DIES ) - ReleaseLeechOverflow( leecher, self ) - } - - if ( self.IsNPC() ) - { - SetTeam( self, leecher.GetTeam() ) - SetSquad( self, "" ) - self.SetAutoSquad() - self.ClearPotentialThreatPos() - self.DisableBehavior( "Assault" ) - - foreach ( trigger in self.e.sonarTriggers ) - { - OnSonarTriggerLeaveInternal( trigger, self ) - } - - #if DEV - // if crosshair spawned, switch squad so he isn't mixed in a squad with opposing team spectres - string squadname = expect string( self.kv.squadname ) - if ( squadname.find( "crosshairSpawnSquad" ) != null ) - self.SetSquad( "crosshairSpawnSquad_team_" + self.GetTeam() + "_" + self.GetClassName() ) - #endif - } - - // call a class specific leeching function for custom behavior - string targetCN = self.GetClassName() - if ( targetCN in file.leechFuncs ) - { - LeechFuncInfo info = file.leechFuncs[ targetCN ] - - // Assert( "DoLeech" in file.leechFuncs[ targetCN ] ) // not sure how to check legit functionref -slayback - void functionref(entity,entity) classLeechingFunc = file.leechFuncs[ targetCN ].DoLeech - thread classLeechingFunc( self, leecher ) - } -} - -array<entity> function GetTeamLeechedEnts( int team ) -{ - array<entity> players = GetPlayerArrayOfTeam( team ) - int totalCount = 0 - - array<entity> leechedArray - foreach ( player in players ) - { - if ( IsValid( player ) && !player.IsBot() ) - leechedArray.extend( GetLeechedEnts( player ) ) - } - - return leechedArray -} - -array<entity> function GetLeechedEnts( entity leecher = null ) -{ - array<entity> ents - - foreach ( entity ent in leecher.p.leechedEnts ) - { - if ( IsAlive( ent ) ) - ents.append( ent ) - } - - return ents -} - -void function TryLeechStartCallback( entity self, entity leecher ) -{ - string leechtargetCN = self.GetClassName() - if ( leechtargetCN in file.leechFuncs ) - { - if ( "LeechStart" in file.leechFuncs[ leechtargetCN ] ) - { - void functionref(entity,entity) leechStartFunc = file.leechFuncs[ leechtargetCN ].LeechStart - thread leechStartFunc( self, leecher ) - } - } -} - -void function TryLeechAbortCallback( entity self, entity leecher ) -{ - string leechtargetCN = self.GetClassName() - if ( leechtargetCN in file.leechFuncs ) - { - if ( "LeechAbort" in file.leechFuncs[ leechtargetCN ] ) - { - void functionref(entity,entity) leechAbortFunc = file.leechFuncs[ leechtargetCN ].LeechAbort - thread leechAbortFunc( self, leecher ) - } - } -} - -void function DataKnifeSuccessSounds( entity player ) -{ - EmitDifferentSoundsOnEntityForPlayerAndWorld( "dataknife_complete", "dataknife_complete_3p", player, player ) -} - -void function DataKnifeCanceledSounds( entity player ) -{ - EmitDifferentSoundsOnEntityForPlayerAndWorld( "dataknife_aborted", "dataknife_aborted_3p", player, player ) -} - - -// --- CLASS SPECIFIC LEECH FUNCTIONS --- -void function Leech_LogicRelay( entity self, entity leecher ) -{ - Assert( self.GetClassName() == "logic_relay" ) - - // logic_relays get Triggered when the object is leeched - EntFire( self, "Trigger" ) -} - -void function Leech_FuncPhysbox( entity self, entity leecher ) -{ - Assert( self.GetClassName() == "func_physbox" ) - - EntFire( self, "FireUser1" ) -} - - -void function MarvinWeaponsFree( entity self ) -{ - Assert( IsAlive( self ), self + " is dead, not alive!" ) - - // already have a weapon - if ( !self.GetActiveWeapon() ) - return - - self.EndSignal( "OnStopLeeched" ) - self.EndSignal( "OnDeath" ) - self.EndSignal( "OnTakeWeapon" ) - - OnThreadEnd( - function () : ( self ) - { - if ( !IsAlive( self ) ) - return - } - ) - - // its combat, time to get the hate on - EntFire( self, "UnholsterWeapon" ) - - WaitForever() -} - - -void function LeechStart_Marvin( entity self, entity leecher ) -{ - //self.SetSkin( 4 ) - EmitSoundOnEntity( self, MARVIN_EMOTE_SOUND_PAIN ) -} - -void function LeechAbort_Marvin( entity self, entity leecher ) -{ - //self.SetSkin( 1 ) // happy - EmitSoundOnEntity( self, MARVIN_EMOTE_SOUND_SAD ) -} - - -// Spectre leech - -void function Leech_Spectre( entity self, entity leecher ) -{ - thread Leech_SpectreThread( self, leecher ) -} -////////////////////////////////////////////////////////////////////////////////////////////////////////// -void function Leech_SpectreThread( entity self, entity leecher ) -{ - Assert( self.GetClassName() == "npc_spectre" ) - - self.EndSignal( "OnDestroy" ) - self.EndSignal( "OnDeath" ) - self.EndSignal( "OnLeeched" ) - - EmitSoundOnEntity( self, MARVIN_EMOTE_SOUND_HAPPY ) - - Assert( leecher.IsPlayer() ) - - leecher.EndSignal( "OnDestroy" ) - - AddPlayerScore( leecher, "LeechSpectre" ) - - float timerCredit = GetCurrentPlaylistVarFloat( "spectre_kill_credit", 0.5 ) - if ( PlayerHasServerFlag( leecher, SFLAG_HUNTER_SPECTRE ) ) - timerCredit *= 2.5 - DecrementBuildTimer( leecher, timerCredit ) - - NPCFollowsPlayer( self, leecher ) - - OnThreadEnd( - function() : ( self, leecher ) - { - // leecher is still connected so don't kill the spectre - if ( IsValid( leecher ) && !IsDisconnected( leecher ) ) - return - - // leecher is disconnected so kill the spectre - if ( IsAlive( self ) ) - self.Die() - } - ) - - foreach ( callbackFunc in svGlobal.onLeechedCustomCallbackFunc ) - { - callbackFunc( self, leecher ) - } - - WaitForever() -} -/////////////////////////////////////////////////////////////////////////////////////////////////////////// -void function LeechGeneric( entity self, entity leecher ) -{ - thread LeechGenericThread( self, leecher ) -} - -/////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Run after the npc is successfully leeched -// HACK: Should make this used by all leeched ents to avoid copy/pasted duplication. Will switch Spectre over to use this soon -void function LeechGenericThread( entity self, entity leecher ) -{ - Assert( IsValid( self ) ) - self.EndSignal( "OnDestroy" ) - self.EndSignal( "OnDeath" ) - self.EndSignal( "OnLeeched" ) - - Assert( leecher.IsPlayer() ) - leecher.EndSignal( "OnDestroy" ) - - string leechSound - float timerCredit - - //-------------------------------------------- - // Handle class-specific stuff - //--------------------------------------------- - switch ( self.GetClassName() ) - { - case "npc_spectre": - leechSound = MARVIN_EMOTE_SOUND_HAPPY - AddPlayerScore( leecher, "LeechSpectre" ) - timerCredit = GetCurrentPlaylistVarFloat( "spectre_kill_credit", 0.5 ) - if ( PlayerHasServerFlag( leecher, SFLAG_HUNTER_SPECTRE ) ) - timerCredit *= 2.5 - break - case "npc_super_spectre": - leechSound = MARVIN_EMOTE_SOUND_HAPPY - AddPlayerScore( leecher, "LeechSuperSpectre" ) - timerCredit = GetCurrentPlaylistVarFloat( "spectre_kill_credit", 0.5 ) - break - case "npc_drone": - leechSound = MARVIN_EMOTE_SOUND_HAPPY - AddPlayerScore( leecher, "LeechDrone" ) - timerCredit = GetCurrentPlaylistVarFloat( "spectre_kill_credit", 0.5 ) - break - case "npc_gunship": - leechSound = MARVIN_EMOTE_SOUND_HAPPY - timerCredit = GetCurrentPlaylistVarFloat( "spectre_kill_credit", 0.5 ) - break - default: - Assert( 0, "Unhandled hacked entity: " + self.GetClassName() ) - } - - EmitSoundOnEntity( self, leechSound ) - DecrementBuildTimer( leecher, timerCredit ) - - // Multiplayer the leeched NPCs still follow the player, but in SP we don't want them to - if ( IsMultiplayer() ) - NPCFollowsPlayer( self, leecher ) - - //-------------------------------------------- - // Any leech custom callback funcs? - //--------------------------------------------- - foreach ( callbackFunc in svGlobal.onLeechedCustomCallbackFunc ) - { - callbackFunc( self, leecher ) - } - -} - -///////////////////////////////////////////////////////////////////////////////////// -void function LeechStartGeneric( entity self, entity leecher ) -{ - string leechStartSound - - switch( self.GetClassName() ) - { - case "npc_spectre": - leechStartSound = MARVIN_EMOTE_SOUND_PAIN - break - case "npc_super_spectre": - leechStartSound = MARVIN_EMOTE_SOUND_PAIN - break - case "npc_drone": - leechStartSound = MARVIN_EMOTE_SOUND_PAIN - break - case "npc_gunship": - leechStartSound = MARVIN_EMOTE_SOUND_PAIN - break - } - Assert( leechStartSound != "", "Couldn't find leechStartSound for: " + self ) - - EmitSoundOnEntity( self, leechStartSound ) -} -///////////////////////////////////////////////////////////////////////////////////// -void function LeechAbortGeneric( entity self, entity leecher ) -{ - string leechAbortSound - - switch( self.GetClassName() ) - { - case "npc_spectre": - leechAbortSound = MARVIN_EMOTE_SOUND_SAD - break - case "npc_super_spectre": - leechAbortSound = MARVIN_EMOTE_SOUND_SAD - break - case "npc_drone": - leechAbortSound = MARVIN_EMOTE_SOUND_SAD - break - case "npc_gunship": - leechAbortSound = MARVIN_EMOTE_SOUND_SAD - break - } - Assert( leechAbortSound != "", "Couldn't find leechAbortSound for: " + self ) - - EmitSoundOnEntity( self, leechAbortSound ) - -} - -// --- END CLASS SPECIFIC LEECH FUNCTIONS ---
\ No newline at end of file diff --git a/Northstar.CustomServers/scripts/vscripts/pilot/_pilot_leeching.gnut b/Northstar.CustomServers/scripts/vscripts/pilot/_pilot_leeching.gnut deleted file mode 100644 index 596ca711..00000000 --- a/Northstar.CustomServers/scripts/vscripts/pilot/_pilot_leeching.gnut +++ /dev/null @@ -1,610 +0,0 @@ -global function PlayerLeeching_Init - -global function LeechSurroundingSpectres -global function CodeCallback_LeechStart -global function LeechPropagate -global function ReleaseLeechOverflow -global function IsBeingLeeched - -// 384 ~ 32 feet -// 256 ~ 21.3 feet -// 192 ~ 16 feet -// 128 ~ 10.6 feet -const float SPECTRE_LEECH_SURROUNDING_RANGE = 384.0 - -#if MP -const int GLOBAL_LEECH_LIMIT = 100 // per team -const int MAX_LEECHABLE = 100 // per player -const bool PROPAGATE_ON_LEECH = true -#elseif SP -const int GLOBAL_LEECH_LIMIT = 8 -const int MAX_LEECHABLE = 4 -const bool PROPAGATE_ON_LEECH = false -#endif - -void function PlayerLeeching_Init() -{ - #if SERVER - PrecacheModel( DATA_KNIFE_MODEL ) - #endif -} - -void function PlayerStopLeeching( entity player, entity target ) -{ - Assert( target != null ) - Assert( player.p.leechTarget == target ) - - StopLeechingProgress( player.p.leechTarget ) - - player.p.leechTarget = null -} - -void function CodeCallback_LeechStart( entity player, entity target ) -{ - thread LeechStartThread( player, target ) -} - -void function LeechStartThread( entity player, entity target ) -{ - if ( !IsAlive( target ) ) - return - - if ( !IsAlive( player ) ) - return - - LeechActionInfo action = FindLeechAction( player, target ) - if ( !action.isValid ) - return - -/* - if ( player.ContextAction_IsActive() - || player.ContextAction_IsActive() - || target.ContextAction_IsActive() ) - { - return - } -*/ - - player.EndSignal( "ScriptAnimStop" ) - player.EndSignal( "OnDeath" ) - target.EndSignal( "OnDestroy" ) - target.EndSignal( "OnDeath" ) - target.EndSignal( "ScriptAnimStop" ) - - StartLeechingProgress( target, player ) - - LeechData e - e.playerStartOrg = player.GetOrigin() - e.targetStartPos = target.GetOrigin() - - OnThreadEnd - ( - function() : ( e, player, target ) - { - if ( IsValid( player ) ) - { - player.SetSyncedEntity( null ) - if ( player.ContextAction_IsLeeching() ) - player.Event_LeechEnd() - - // reset to start position in case animation moves us at all - //player.SetOrigin( e.playerStartOrg ) - player.Anim_Stop() - player.UnforceStand() - - // done with first person anims - ClearPlayerAnimViewEntity( player ) - DeployAndEnableWeapons( player ) - } - - if ( IsValid( target ) ) - { - if ( !e.success ) - { - if ( IsValid( player ) ) - { - TryLeechAbortCallback( target, player ) //Make "failed leech" sounds play here after exiting leech animation - } - } - - #if MP - target.SetUsable() - #endif - target.SetNoTarget( false ) - target.SetNoTargetSmartAmmo( false ) - target.Anim_Stop() - target.ClearParent() - if ( IsAlive( target ) ) - { - // Note that e.targetStartPos is not guarranteed to be a safe spot since we can have moving geo in the game now - PutEntityInSafeSpot( target, null, null, target.GetOrigin(), target.GetOrigin() ) - } - - if ( target.ContextAction_IsLeeching() ) - target.Event_LeechEnd() - - } - - foreach ( knife in e.knives ) - { - if ( IsValid( knife ) ) - { - knife.Destroy() - } - - } - - if ( IsValid( player ) && player.p.leechTarget ) - { - PlayerStopLeeching( player, player.p.leechTarget ) - } - - if ( IsValid( e.ref ) ) - { - if ( IsValid( player ) ) - player.ClearParent() - - if ( IsValid( target ) ) - target.ClearParent() - - //printt( "kill the ref" ) - if ( IsValid( e.ref ) && !e.ref.IsPlayer() ) - e.ref.Destroy() - } - } - ) - - Assert( player.p.leechTarget == null ) - player.p.leechTarget = target - player.Event_LeechStart() - target.Event_LeechStart() - player.ForceStand() - HolsterAndDisableWeapons( player ) - - float leechTime = svGlobal.defaultPilotLeechTime - if ( PlayerHasPassive( player, ePassives.PAS_FAST_HACK ) ) - leechTime *= 0.85 - - e.leechTime = leechTime - - #if MP - target.UnsetUsable() - #endif - target.SetNoTarget( true ) - target.SetNoTargetSmartAmmo( true ) - - if ( IsSpectre( target ) ) - TellSquadmatesSpectreIsGettingLeeched( target, player ) - - waitthread PlayerLeechTargetAnimation( player, target, action, e ) - - e.leechStartTime = Time() - Remote_CallFunction_Replay( player, "ServerCallback_DataKnifeStartLeech", e.leechTime ) - waitthread WaittillFinishedLeeching( player, target, e ) - - if ( e.success ) - { - thread DataKnifeSuccessSounds( player ) - - DoLeech( target, player ) - PlayerStopLeeching( player, target ) - - // this will kill a random leeched ent from within the team, exluding the current target. When it's not done elsewhere - if ( !WIFI_HACK_OVERFLOW_DIES ) - ReleaseLeechOverflow( player, target ) - - //this is called when the player leeches - not when the system is leeching other spectres - if ( PROPAGATE_ON_LEECH && IsSpectre( target ) ) - LeechSurroundingSpectres( target.GetOrigin(), player ) - } - else - { - DataKnifeCanceledSounds( player ) - Remote_CallFunction_Replay( player, "ServerCallback_DataKnifeCancelLeech" ) - PlayerStopLeeching( player, player.p.leechTarget ) - } - - waitthread PlayerExitLeechingAnim( player, target, action, e ) -} - -void function TellSquadmatesSpectreIsGettingLeeched( entity spectre, entity player ) -{ - string squadName = expect string( spectre.kv.squadname ) - if ( squadName == "" ) - return - - array<entity> squad = GetNPCArrayBySquad( squadName ) - squad.removebyvalue( spectre ) - - foreach ( squadMate in squad ) - { - //printt( "Setting enemy of " + squadMate + " to player: " + player ) - squadMate.SetEnemyLKP( player, player.GetOrigin() ) - } -} - -void function ReleaseLeechOverflow( entity player, entity lastLeeched ) -{ - array<entity> teamLeechedEnts = GetTeamLeechedEnts( player.GetTeam() ) - array<entity> leechedEnts = GetLeechedEnts( player ) - int globalOverflow = GLOBAL_LEECH_LIMIT - teamLeechedEnts.len() - int playerOverflow = MAX_LEECHABLE - leechedEnts.len() - - int overflow = minint( globalOverflow, playerOverflow ) - - if ( overflow >= 0 ) - return - - overflow = abs( overflow ) - - teamLeechedEnts.randomize() - foreach ( ent in teamLeechedEnts ) - { - if ( lastLeeched == ent ) - continue - - entity owner = ent.GetBossPlayer() - Assert( owner.IsPlayer() ) - - - // I think it's better to kill the overflow then have it become an enemy again. - ent.Die() - - delete owner.p.leechedEnts[ ent ] - overflow-- - - if ( overflow == 0 ) - break - } - - Assert( overflow == 0 ) -} - - -int function GetMaxNumberOfLeechedEnts( entity player ) -{ - int teamLeechedCount = GetTeamLeechedEnts( player.GetTeam() ).len() - int leechedEntsCount = GetLeechedEnts( player ).len() - int teamLimit = maxint( 0, GLOBAL_LEECH_LIMIT - teamLeechedCount ) - int maxSize = maxint( 0, MAX_LEECHABLE - leechedEntsCount ) - maxSize = minint( teamLimit, maxSize ) - - return maxSize -} - -void function LeechSurroundingSpectres( vector origin, entity player ) -{ - array<entity> enemySpectreArray = GetNPCArrayEx( "npc_spectre", TEAM_ANY, player.GetTeam(), player.GetOrigin(), SPECTRE_LEECH_SURROUNDING_RANGE ) - - if ( !enemySpectreArray.len() ) - return - - // don't resize the array if we should kill the overflow instead - if ( !WIFI_HACK_OVERFLOW_DIES ) - { - int maxSize = GetMaxNumberOfLeechedEnts( player ) - int newSize = minint( enemySpectreArray.len(), maxSize ) - - enemySpectreArray.resize( newSize, null ) - } - - foreach ( spectre in enemySpectreArray ) - { - thread LeechPropagate( spectre, player ) - } - - if ( enemySpectreArray.len() ) - { - if ( PlayerHasPassive( player, ePassives.PAS_WIFI_SPECTRE ) ) - { - EmitSoundOnEntity( player, "BurnCard_WiFiVirus_TurnSpectre" ) - printt( "play BurnCard_WiFiVirus_TurnSpectre" ) - } - } -} - -void function LeechPropagate( entity spectre, entity player ) -{ - if ( spectre.ContextAction_IsActive() ) - return - - if ( !spectre.IsInterruptable() ) - return - - if ( spectre.GetParent() ) - return - - if ( !Leech_IsLeechable( spectre ) ) - return - - player.EndSignal( "OnDestroy" ) - spectre.EndSignal( "OnDestroy" ) - spectre.EndSignal( "OnDeath" ) - - spectre.Event_LeechStart() - - AddAnimEvent( spectre, "leech_switchteam", DoLeechAnimEvent, player ) - - OnThreadEnd( - function() : ( spectre ) - { - if ( IsValid( spectre ) ) - { - DeleteAnimEvent( spectre, "leech_switchteam" ) - - if ( spectre.ContextAction_IsLeeching() ) - spectre.Event_LeechEnd() - } - } - ) - - spectre.Anim_Stop() - waitthread PlayAnim( spectre, "sp_reboot" ) - spectre.SetVelocity( Vector(0,0,0) ) -} - -void function WaittillFinishedLeeching( entity player, entity target, LeechData e ) -{ - player.EndSignal( "OnDeath" ) - player.EndSignal( "ScriptAnimStop" ) - target.EndSignal( "OnDeath" ) - - if ( !player.UseButtonPressed() ) - return - - float waitTime = e.leechTime - float timePassed = Time() - e.leechStartTime - waitTime -= timePassed - if ( waitTime > 0 ) - { - float startTime = Time() - while ( Time() < startTime + waitTime && player.UseButtonPressed() ) - { - WaitFrame() - } - } - - if ( player.UseButtonPressed() ) - e.success = true -} - -///////////////////////////////////////////////////////////// -bool function IsLeechTargetUsedAsAnimNode( entity target ) -{ - return target.AISetting_LeechAnimTag() != "" -} - -///////////////////////////////////////////////////////////// -void function PlayerLeechTargetAnimation( entity player, entity target, LeechActionInfo action, LeechData e ) -{ - Assert( action.isValid ) - vector targetStartOrg = target.GetOrigin() - vector targetStartAng = target.GetAngles() - - vector initialPlayerPosition = player.GetOrigin() - vector initialTargetPosition = target.GetOrigin() - - vector endOrigin = target.GetOrigin() - vector startOrigin = player.GetOrigin() - vector refVec = endOrigin - startOrigin - string animTag - - FirstPersonSequenceStruct playerSequence - - //--------------------------------------------------------- - // Leech anims played on the leech target, or at player position? - //--------------------------------------------------------- - if ( IsLeechTargetUsedAsAnimNode( target ) ) - { - e.ref = CreateLeechingScriptMoverBetweenEnts( player, target ) - animTag = target.AISetting_LeechAnimTag() - Assert( animTag != "" ) - e.ref.SetOrigin( target.GetOrigin() ) - e.ref.SetParent( target, animTag ) - } - else - { - e.ref = player - e.ref.SetOrigin( e.playerStartOrg ) - playerSequence.playerPushable = true - } - - e.ref.EndSignal( "OnDestroy" ) - - //----------------------------------------------------------------- - // Player FirstPersonSequence for the leeching - //----------------------------------------------------------------- - playerSequence.blendTime = 0.25 - playerSequence.attachment = "ref" - - //----------------------------------------------------------------- - // Only create FirstPersonSequence for leech target if anims exist - //----------------------------------------------------------------- - bool haveTargetSequence = false - FirstPersonSequenceStruct targetSequence - - if ( action.targetAnimation3pStart != "" ) - { - targetSequence = clone playerSequence - haveTargetSequence = true - } - - playerSequence.thirdPersonAnim = action.playerAnimation3pStart - playerSequence.thirdPersonAnimIdle = action.playerAnimation3pIdle - playerSequence.firstPersonAnim = action.playerAnimation1pStart - playerSequence.firstPersonAnimIdle = action.playerAnimation1pIdle - - entity viewmodel = player.GetFirstPersonProxy() - - if ( !HasAnimEvent( viewmodel, "PlaySound_DataKnife_Hack_Spectre_Pt1" ) ) - AddAnimEvent( viewmodel, "PlaySound_DataKnife_Hack_Spectre_Pt1", PlaySound_DataKnife_Hack_Spectre_Pt1 ) - - if ( !HasAnimEvent( viewmodel, "PlaySound_DataKnife_Hack_Spectre_Pt2" ) ) - AddAnimEvent( viewmodel, "PlaySound_DataKnife_Hack_Spectre_Pt2", PlaySound_DataKnife_Hack_Spectre_Pt2 ) - - if ( !HasAnimEvent( viewmodel, "PlaySound_DataKnife_Hack_Spectre_Pt3" ) ) - AddAnimEvent( viewmodel, "PlaySound_DataKnife_Hack_Spectre_Pt3", PlaySound_DataKnife_Hack_Spectre_Pt3 ) - - if ( !HasAnimEvent( viewmodel, "PlaySound_Spectre_Servo_Heavy_Short" ) ) - AddAnimEvent( viewmodel, "PlaySound_Spectre_Servo_Heavy_Short", PlaySound_Spectre_Servo_Heavy_Short ) - - if ( !HasAnimEvent( viewmodel, "PlaySound_DataKnife_Hack_Spectre_ArmorRattle" ) ) - AddAnimEvent( viewmodel, "PlaySound_DataKnife_Hack_Spectre_ArmorRattle", PlaySound_DataKnife_Hack_Spectre_ArmorRattle ) - - if ( haveTargetSequence ) - { - targetSequence.thirdPersonAnim = action.targetAnimation3pStart - targetSequence.thirdPersonAnimIdle = action.targetAnimation3pIdle - } - - playerSequence.noParent = true - - //----------------------------------- - // Data knife - //----------------------------------- - asset model = DATA_KNIFE_MODEL - - string knifeTag = GetTagForDataknife( target ) - entity thirdPersonKnife = CreatePropDynamic( model ) - SetTargetName( thirdPersonKnife, "thirdPersonKnife" ) - thirdPersonKnife.SetParent( player, knifeTag, false, 0.0 ) - e.knives.append( thirdPersonKnife ) - - SetForceDrawWhileParented( target, true ) - - //------------------------------------------------------------------------------ - // Play leech anim sequence for player, but only for target if leech anims exist - //------------------------------------------------------------------------------- - player.SetSyncedEntity( target ) - entity ref = e.ref - if ( haveTargetSequence ) - thread Animate_PlayerLeechTarget( targetSequence, target, ref ) - - waitthread FirstPersonSequence( playerSequence, player, null ) -} - - -//Basically copy pasted from CreateMeleeScriptMoverBetweenEnts -entity function CreateLeechingScriptMoverBetweenEnts( entity attacker, entity target ) -{ - vector endOrigin = target.GetOrigin() - vector startOrigin = attacker.GetOrigin() - vector refVec = endOrigin - startOrigin - - vector refAng = VectorToAngles( refVec ) - float pitch = refAng.x - if ( pitch > 180 ) - pitch -= 360 - if ( fabs( pitch ) > 35 ) //If pitch is too much, use angles from target - refAng = target.GetAngles() // Leech does it from behind target, so use target's angles. - - vector refPos = endOrigin - refVec * 0.5 - - entity ref = CreateOwnedScriptMover( attacker ) - ref.SetOrigin( refPos ) - ref.SetAngles( refAng ) - - return ref -} - -void function Animate_PlayerLeechTarget( FirstPersonSequenceStruct targetSequence, entity target, entity ref ) -{ - ref.EndSignal( "OnDestroy" ) - target.EndSignal( "OnDestroy" ) - waitthread FirstPersonSequence( targetSequence, target, ref ) -} - -void function PlayerExitLeechingAnim( entity player, entity target, LeechActionInfo action, LeechData e ) -{ - FirstPersonSequenceStruct playerSequence - playerSequence.blendTime = 0.3 - playerSequence.attachment = "ref" - playerSequence.teleport = false - playerSequence.noParent = true - playerSequence.playerPushable = true - - //-------------------------------------- - // Target animates only if he has anims - //--------------------------------------- - bool hasTargetSequence = false - FirstPersonSequenceStruct targetSequence - if ( action.targetAnimation3pEnd != "" ) - { - targetSequence = clone playerSequence - hasTargetSequence = true - } - - playerSequence.thirdPersonAnim = action.playerAnimation3pEnd - playerSequence.firstPersonAnim = action.playerAnimation1pEnd - playerSequence.snapPlayerFeetToEyes = false - - entity ref = e.ref - - if ( hasTargetSequence ) - { - targetSequence.thirdPersonAnim = action.targetAnimation3pEnd - thread FirstPersonSequence( targetSequence, target, ref ) - } - waitthread FirstPersonSequence( playerSequence, player, null ) - - //------------------------------------------------------------- - // Detach from rodeo if applicable (drones, superspectres, etc) - //------------------------------------------------------------- - if ( Rodeo_IsAttached( player ) ) - player.Signal( "RodeoOver" ) -} - -bool function IsBeingLeeched( entity npc ) -{ - return npc.ai.leechInProgress -} - -void function PlaySound_DataKnife_Hack_Spectre_Pt1( entity playerFirstPersonProxy ) -{ - entity player = playerFirstPersonProxy.GetOwner() - if ( !IsValid( player ) ) - return - - EmitSoundOnEntityOnlyToPlayer( player, player, "DataKnife_Hack_Spectre_Pt1" ) - -} - -void function PlaySound_DataKnife_Hack_Spectre_Pt2( entity playerFirstPersonProxy ) -{ - entity player = playerFirstPersonProxy.GetOwner() - if ( !IsValid( player ) ) - return - - EmitSoundOnEntityOnlyToPlayer( player, player, "DataKnife_Hack_Spectre_Pt2" ) - -} - -void function PlaySound_DataKnife_Hack_Spectre_Pt3( entity playerFirstPersonProxy ) -{ - entity player = playerFirstPersonProxy.GetOwner() - if ( !IsValid( player ) ) - return - - EmitSoundOnEntityOnlyToPlayer( player, player, "DataKnife_Hack_Spectre_Pt3" ) - -} - -void function PlaySound_Spectre_Servo_Heavy_Short( entity playerFirstPersonProxy ) -{ - entity player = playerFirstPersonProxy.GetOwner() - if ( !IsValid( player ) ) - return - - EmitSoundOnEntityOnlyToPlayer( player, player, "Spectre.Servo.Heavy.Short" ) - -} - -void function PlaySound_DataKnife_Hack_Spectre_ArmorRattle( entity playerFirstPersonProxy ) -{ - entity player = playerFirstPersonProxy.GetOwner() - if ( !IsValid( player ) ) - return - - EmitSoundOnEntityOnlyToPlayer( player, player, "DataKnife_Hack_Spectre_ArmorRattle" ) - -}
\ No newline at end of file diff --git a/Northstar.CustomServers/scripts/vscripts/pilot/_slamzoom.nut b/Northstar.CustomServers/scripts/vscripts/pilot/_slamzoom.nut deleted file mode 100644 index 83ee3916..00000000 --- a/Northstar.CustomServers/scripts/vscripts/pilot/_slamzoom.nut +++ /dev/null @@ -1,85 +0,0 @@ -untyped - -global function ShouldSlamzoomSpawn -global function SlammzoomSpawn - -const SLAMZOOM_WHOOSH_SOUND = "UI_InGame_MarkedForDeath_PlayerUnmarked" -const SLAMZOOM_COLOR_CORRECTION = "materials/correction/player_electric_damage.raw" - -function ShouldSlamzoomSpawn() -{ - return ( GetCurrentPlaylistVarInt( "enable_slamzoom_spawn", 0 ) == 1 ) -} - -function SlammzoomSpawn( entity player, vector origin, vector angles, entity friendlyPilot = null ) -{ - player.EndSignal( "OnDestroy" ) - player.SetOrigin( origin ) - player.SnapEyeAngles( angles ) - - vector landorigin = player.EyePosition() - - // slamzoom - int slamzoom_height = 4000 - float slamzoom_time1 = 0.5 - float slamzoom_time2 = 0.7 - float slamzoom_rotate_time = 0.3 - int slamzoom_angle = 90 - int enter_angle = 90 - slamzoom_angle - - vector start_angles = Vector( -90-enter_angle, angles.y, 0 ) - vector start_vector = AnglesToForward( start_angles ) - - // origin = origin + Vector(0,0,48) - - entity camera = CreateTitanDropCamera( origin + start_vector * slamzoom_height, Vector( slamzoom_angle, angles.y, 0.0) ) - camera.Fire( "Enable", "!activator", 0, player ) - - entity mover = CreateScriptMover() - if ( IsValid( camera ) ) - { - // camera can be invalid for a moment when server shuts down - mover.SetOrigin( camera.GetOrigin() ) - mover.SetAngles( camera.GetAngles() ) - camera.SetParent( mover ) - } - - OnThreadEnd( - function() : ( mover, camera ) - { - if ( IsValid( mover ) ) - mover.Destroy() - if ( IsValid( camera ) ) - camera.Destroy() - } - ) - - player.isSpawning = mover - mover.MoveTo( mover.GetOrigin() + (start_vector * 100), slamzoom_time1, slamzoom_time1*0.4, slamzoom_time1*0.4 ) - wait slamzoom_time1 - EmitSoundOnEntityOnlyToPlayer( player, player, SLAMZOOM_WHOOSH_SOUND ) - mover.MoveTo( landorigin, slamzoom_time2, slamzoom_time2*0.5, slamzoom_time2*0.2 ) - wait slamzoom_time2 - slamzoom_rotate_time - mover.RotateTo( angles, slamzoom_rotate_time, slamzoom_rotate_time*0.2, slamzoom_rotate_time*0.2 ) - wait slamzoom_rotate_time - player.isSpawning = null - wait 0.1 - if ( IsValid( camera ) ) - { - // camera can be invalid for a moment when server shuts down - camera.FireNow( "Disable", "!activator", null, player ) - } - - if ( IsValid( friendlyPilot ) ) - { - MessageToPlayer( friendlyPilot, eEventNotifications.FriendlyPlayerSpawnedOnYou, player ) - MessageToPlayer( player, eEventNotifications.SpawnedOnFriendlyPlayer, friendlyPilot ) - } - - if ( ShouldGivePlayerInfoOnSpawn() ) - thread GivePlayerInfoOnSpawn( player ) - - player.SetOrigin( origin ) - player.SnapEyeAngles( angles ) - player.RespawnPlayer( null ) -}
\ No newline at end of file diff --git a/Northstar.CustomServers/scripts/vscripts/pilot/_zipline.gnut b/Northstar.CustomServers/scripts/vscripts/pilot/_zipline.gnut deleted file mode 100644 index a129c479..00000000 --- a/Northstar.CustomServers/scripts/vscripts/pilot/_zipline.gnut +++ /dev/null @@ -1,838 +0,0 @@ -untyped - -global function Zipline_Init - -global function GuyZiplinesToGround -global function GetZiplineSpawns -global function GetHookOriginFromNode -global function ZiplineInit - -global function CodeCallback_ZiplineMount -global function CodeCallback_ZiplineStart -global function CodeCallback_ZiplineMove -global function CodeCallback_ZiplineStop - -global function AddCallback_ZiplineStart -global function AddCallback_ZiplineStop - -global function TrackMoverDirection -global function CreateRopeEntities -global function SpawnZiplineEntities -global function GetZiplineLandingAnims -global function AnimDoneStuckInSolidFailSafe - -struct { - array<string> zipLineLandingAnimations = [ - "pt_zipline_dismount_standF", - "pt_zipline_dismount_crouchF", - "pt_zipline_dismount_crouch180", - "pt_zipline_dismount_breakright", - "pt_zipline_land" - "pt_zipline_land" - "pt_zipline_land" - "pt_zipline_land" - "pt_zipline_land" - "pt_zipline_land" - ] - - array<string> zipLinePlayerLandingAnimations = [ - "pt_zipline_dismount_standF" - ] - - array<string> zipLineReadyAnimations = [ - "pt_zipline_ready_idleA", - "pt_zipline_ready_idleB" - ] -} file - -//typedef EntitiesDidLoadCallbackType void functionref(entity) -array<void functionref(entity,entity)> _ZiplineStartCallbacks -array<void functionref(entity)> _ZiplineStopCallbacks - -function Zipline_Init() -{ - if ( reloadingScripts ) - return - - RegisterSignal( "deploy" ) - RegisterSignal( "stop_deploy" ) - RegisterSignal( "npc_deployed" ) - - VehicleDropshipNew_Init() - - level.MIN_ZIPLINE_LAND_DIST_SQRD <- 128 * 128 - level.MIN_ZIPLINE_HOOK_DIST_SQRD <- 256 * 256 - level._info_spawnpoint_dropships <- {} - AddSpawnCallback( "info_spawnpoint_dropship", AddToSpawnpointDropships ) - - PrecacheParticleSystem( $"hmn_mcorps_jump_jet_wallrun_full" ) - PrecacheParticleSystem( $"hmn_imc_jump_jet_wallrun_full" ) - PrecacheParticleSystem( $"P_Zipline_hld_1" ) - -} - -void function AddToSpawnpointDropships( entity self ) -{ - level._info_spawnpoint_dropships[ self ] <- self -} - -function GetZiplineSpawns() -{ - local targets = [] - foreach ( ent in clone level._info_spawnpoint_dropships ) - { - if ( IsValid( ent ) ) - { - targets.append( ent ) - continue - } - - delete level._info_spawnpoint_dropships[ ent ] - } - - return targets -} - - -function GuyZiplinesToGround( guy, Table ) -{ - expect entity( guy ) - - OnThreadEnd( - function() : ( guy ) - { - if ( IsValid( guy ) ) - guy.SetEfficientMode( false ) - } - ) - - local ship = Table.ship - local dropPos = GetDropPos( Table ) - - // ship didn't find a drop spot - if ( dropPos == null ) - WaitForever() - - //DebugDrawLine( guy.GetOrigin(), dropPos, 255, 0, 0, true, 8.0 ) - - local attachOrigin = ship.GetAttachmentOrigin( Table.attachIndex ) - local nodeOrigin = dropPos - local hookOrigin = GetHookOriginFromNode( guy.GetOrigin(), nodeOrigin, attachOrigin ) - - // couldn't find a place to hook it? This needs to be tested on precompile - if ( !hookOrigin ) - { - printt( "WARNING! Bad zipline dropship position!" ) - WaitForever() - } - - Table.hookOrigin <- hookOrigin - - // Track the movement of the script mover that moves the guy to the ground - local e = {} - - waitthread GuyRidesZiplineToGround( guy, Table, e, dropPos ) - - //DebugDrawLine( guy.GetOrigin(), dropPos, 255, 0, 135, true, 5.0 ) - - if ( !( "forward" in Table ) ) - { - // the sequence ended before the guy reached the ground - local start = guy.GetOrigin() - // this needs functionification - local end = Table.hookOrigin + Vector( 0,0,-80 ) - TraceResults result = TraceLine( start, end, guy ) - local angles = guy.GetAngles() - Table.forward <- AnglesToForward( angles ) - Table.origin <- result.endPos - } - - // the guy detaches and falls to the ground - string landingAnim = file.zipLineLandingAnimations.getrandom() - //DrawArrow( guy.GetOrigin(), guy.GetAngles(), 5.0, 80 ) - - if ( !guy.IsInterruptable() ) - return - - guy.Anim_ScriptedPlay( landingAnim ) - guy.Anim_EnablePlanting() - - ShowName( guy ) - - local vec = e.currentOrigin - e.oldOrigin - - guy.SetVelocity( vec * 15 ) - - thread AnimDoneStuckInSolidFailSafe( guy ) -} - -function AnimDoneStuckInSolidFailSafe( entity guy ) -{ - guy.EndSignal( "OnDeath" ) - guy.WaitSignal( "OnAnimationDone" ) - - if ( EntityInSolid( guy ) ) - { - vector ornull clampedPos - clampedPos = NavMesh_ClampPointForAIWithExtents( guy.GetOrigin(), guy, < 400, 400, 400 > ) - - if ( clampedPos != null ) - { - guy.SetOrigin( expect vector( clampedPos ) ) - printt( guy + " was in solid, teleported" ) - } - } -} - -function TrackMoverDirection( mover, e ) -{ - mover.EndSignal( "OnDestroy" ) - // track the way the mover movers, so we can do the - // correct velocity on the falling guy - local origin = mover.GetOrigin() - e.oldOrigin <- origin - e.currentOrigin <- origin - - for ( ;; ) - { - WaitFrame() - e.oldOrigin = e.currentOrigin - e.currentOrigin = mover.GetOrigin() - } -} - -function GuyRidesZiplineToGround( entity guy, zipline, e, dropPos ) -{ - entity mover = CreateOwnedScriptMover( guy ) - mover.EndSignal( "OnDestroy" ) - - thread TrackMoverDirection( mover, e ) - - OnThreadEnd( - function() : ( mover, zipline, guy ) - { - thread ZiplineRetracts( zipline ) - - if ( IsValid( guy ) ) - { - guy.ClearParent() - StopSoundOnEntity( guy, "3p_zipline_loop" ) - EmitSoundOnEntity( guy, "3p_zipline_detach" ) - } - - if ( IsValid( mover ) ) - mover.Kill_Deprecated_UseDestroyInstead() - } - ) - - - local rideDist = Distance( guy.GetOrigin(), zipline.hookOrigin ) - - // how long it takes the zipline to travel 1000 units - zipline.pinTime <- Graph( rideDist, 0, 1000, 0, 0.4 ) - - // how long it takes the zipline to retract, - zipline.retractTime <- Graph( rideDist, 0, 1000, 0, 0.5 ) - - // how long it takes the rider to ride 1000 units - float rideTime = Graph( rideDist, 0, 1000, 0, 2.5 ) - - - // orient the script_mover in the direction its going - local angles = guy.GetAngles() - local forward = AnglesToForward( angles ) - local right = AnglesToRight( angles ) - - CreateRopeEntities( zipline ) - - local zipAttachOrigin = zipline.ship.GetAttachmentOrigin( zipline.attachIndex ) - zipline.end.SetOrigin( zipAttachOrigin ) - - zipline.start.SetParent( zipline.ship, zipline.shipAttach ) - zipline.mid.SetParent( zipline.ship, zipline.shipAttach ) - - // now that the origin is set we can spawn the zipline, otherwise we - // see the zipline lerp in - SpawnZiplineEntities( zipline ) - - - // the zipline shoots out - ZiplineMover( expect entity( zipline.end ), zipline.hookOrigin, zipline.pinTime ) - - EmitSoundAtPosition( TEAM_UNASSIGNED, zipAttachOrigin, "dropship_zipline_zipfire" ) - delaythread( zipline.pinTime ) ZiplineMoveCleanup( zipline ) - -// wait zipline.pinTime * 0.37 - wait zipline.pinTime - EmitSoundAtPosition( TEAM_UNASSIGNED, zipline.hookOrigin, "dropship_zipline_impact" ) - - zipline.mid.SetParent( mover, "ref", false ) - thread MoverMovesToGround( zipline, mover, rideTime ) - - if ( !IsAlive( guy ) || !guy.IsInterruptable() ) - return - - guy.SetParent( mover, "ref", false, 0.0 ) - - EmitSoundOnEntity( guy, "3p_zipline_attach" ) - waitthread PlayAnim( guy, "pt_zipline_ready2slide", mover ) - EmitSoundOnEntity( guy, "3p_zipline_loop" ) - - if ( !IsAlive( guy ) || !guy.IsInterruptable() || guy.GetParent() != mover ) - return - - // Anim_PlayWithRefPoint requires that the guy be parented to the ref point. - thread PlayAnim( guy, ZIPLINE_IDLE_ANIM, mover, "ref" ) - - //thread ZiplineAutoClipsToGeo( zipline, mover ) - - //wait 0.4 // some time to clear the lip - - local nodeOrigin = dropPos - //DebugDrawLine( guy.GetOrigin(), nodeOrigin, 200, 255, 50, true, 8.0 ) - - rideDist = Distance( guy.GetOrigin(), nodeOrigin ) - rideDist -= 100 // for animation at end - if ( rideDist < 0 ) - rideDist = 0 - rideTime = Graph( rideDist, 0, 100, 0, 0.15 ) -/* - printt( "ride time " + rideTime ) - local endTime = Time() + rideTime - for ( ;; ) - { - if ( Time() >= endTime ) - return - - DebugDrawLine( guy.GetOrigin(), nodeOrigin, 255, 0, 0, true, 0.15 ) - DebugDrawText( nodeOrigin, ( endTime - Time() ) + "", true, 0.15 ) - WaitFrame() - } -*/ - wait rideTime - - thread ZiplineStuckFailsafe( guy, nodeOrigin ) -} - -function ZiplineStuckFailsafe( guy, nodeOrigin ) -{ - TimeOut( 15.0 ) - - guy.EndSignal( "OnDeath" ) - - guy.WaitSignal( "OnFailedToPath" ) - - guy.SetOrigin( nodeOrigin ) - printt( "Warning: AI Path failsafe at " + nodeOrigin ) -} - -function ZiplineMoveCleanup( zipline ) -{ - // work around for moveto bug - if ( IsValid( zipline.end ) ) - { - zipline.end.SetOrigin( zipline.hookOrigin ) - } -} - -function MoverMovesToGround( zipline, mover, timeTotal ) -{ - // this handles the start point moving. - mover.EndSignal( "OnDestroy" ) - zipline.ship.EndSignal( "OnDestroy" ) - - local origin = zipline.ship.GetAttachmentOrigin( zipline.attachIndex ) - local angles = zipline.ship.GetAttachmentAngles( zipline.attachIndex ) - mover.SetOrigin( origin ) - mover.SetAngles( angles ) - - local start = zipline.start.GetOrigin() - local end = zipline.hookOrigin + Vector( 0,0,-180 ) - - local blendTime = 0.5 - if ( timeTotal <= blendTime ) - blendTime = 0 - - angles = VectorToAngles( end - start ) - angles.x = 0 - angles.z = 0 - - mover.MoveTo( end, timeTotal, blendTime, 0 ) - mover.RotateTo( angles, 0.2 ) -} - - -function WaitUntilZiplinerNearsGround( guy, zipline ) -{ - local start, end, frac - local angles = guy.GetAngles() - local forward = AnglesToForward( angles ) - - local zipAngles, zipForward, dropDist - - if ( guy.IsNPC() ) - dropDist = 150 - else - dropDist = 10 //much closer for player - - local mins = guy.GetBoundingMins() - local maxs = guy.GetBoundingMaxs() - - TraceResults result - - for ( ;; ) - { - start = guy.GetOrigin() - end = start + Vector(0,0,-dropDist) - end += forward * dropDist -// TraceResults result = TraceLine( start, end, guy ) - result = TraceHull( start, end, mins, maxs, guy, TRACE_MASK_NPCSOLID_BRUSHONLY, TRACE_COLLISION_GROUP_NONE ) - //DebugDrawLine( start, end, 255, 0, 0, true, 0.2 ) - - if ( result.fraction < 1.0 ) - break - - start = guy.GetOrigin() - end = zipline.hookOrigin + Vector( 0,0,-80 ) - - zipForward = ( end - start ) - zipForward.Norm() - zipForward *= 250 - - end = start + zipForward - //DebugDrawLine( start, end, 255, 0, 0, true, 0.1 ) - -// result = TraceLine( start, end, guy ) - //DebugDrawLine( start, end, 255, 150, 0, true, 0.2 ) - result = TraceHull( start, end, mins, maxs, guy, TRACE_MASK_NPCSOLID_BRUSHONLY, TRACE_COLLISION_GROUP_NONE ) - - if ( result.fraction < 1.0 ) - break - - WaitFrame() - } - - zipline.origin <- result.endPos - zipline.forward <- forward -} - - -function ZiplineRetracts( zipline ) -{ - if ( !IsValid( zipline.start ) ) - return - if ( !IsValid( zipline.mid ) ) - return - if ( !IsValid( zipline.end ) ) - return - - OnThreadEnd( - function() : ( zipline ) - { - if ( IsValid( zipline.start ) ) - zipline.start.Kill_Deprecated_UseDestroyInstead() - - if ( IsValid( zipline.mid ) ) - zipline.mid.Kill_Deprecated_UseDestroyInstead() - - // is the only one that's not parented and only gets deleted here - zipline.end.Kill_Deprecated_UseDestroyInstead() - } - ) - - // IsValid check succeeds, even if a delete brought us here. - // IsValid should've failed. - if ( !IsAlive( expect entity( zipline.ship ) ) ) - return - - zipline.ship.EndSignal( "OnDestroy" ) - - zipline.start.EndSignal( "OnDestroy" ) - zipline.mid.EndSignal( "OnDestroy" ) - zipline.end.EndSignal( "OnDestroy" ) - - local start, end, mid - local startDist - local endDist - local totalDist - local progress - local newMidPoint - local midRetractProgress - - local startTime = Time() - local endTime = startTime + 0.3 - - zipline.mid.ClearParent() - - start = zipline.start.GetOrigin() - end = zipline.end.GetOrigin() - mid = zipline.mid.GetOrigin() - - startDist = Distance( mid, start ) - endDist = Distance( mid, end ) - totalDist = startDist + endDist - - if ( totalDist <= 0 ) - return - - progress = startDist / totalDist -// newMidPoint = end * progress + start * ( 1 - progress ) -// -// // how far from the midpoint we are, vertically -// local mid_z_offset = newMidPoint.z - mid.z -// local addOffset - - for ( ;; ) - { - start = zipline.start.GetOrigin() - end = zipline.end.GetOrigin() - - newMidPoint = end * progress + start * ( 1 - progress ) - - midRetractProgress = GraphCapped( Time(), startTime, endTime, 0, 1 ) - if ( midRetractProgress >= 1.0 ) - break - - newMidPoint = mid * ( 1 - midRetractProgress ) + newMidPoint * midRetractProgress - //addOffset = mid_z_offset * ( 1 - midRetractProgress ) - //newMidPoint.z -= addOffset - //DebugDrawLine( zipline.mid.GetOrigin(), newMidPoint, 255, 0, 0, true, 0.2 ) - - if ( !IsValid( zipline.mid ) ) - { - printt( "Invalid zipline mid! Impossible!" ) - } - else - { - zipline.mid.SetOrigin( newMidPoint ) - } - - -// startDist = Distance( mid, start ) -// endDist = Distance( mid, end ) -// totalDist = startDist + endDist -// progress = startDist / totalDist - WaitFrame() - } - -// DebugDrawLine( zipline.start.GetOrigin(), zipline.mid.GetOrigin(), 255, 100, 50, true, 5.0 ) -// DebugDrawLine( zipline.end.GetOrigin(), zipline.mid.GetOrigin(), 60, 100, 244, true, 5.0 ) - local moveTime = 0.4 - ZiplineMover( expect entity( zipline.start ), zipline.end.GetOrigin(), moveTime ) - ZiplineMover( expect entity( zipline.mid ), zipline.end.GetOrigin(), moveTime ) - - wait moveTime -/* - startTime = Time() - endTime = startTime + zipline.retractTime - end = zipline.end.GetOrigin() - - if ( !IsValid( zipline.mid ) ) - return - mid = zipline.mid.GetOrigin() - - local org - - for ( ;; ) - { - start = zipline.start.GetOrigin() - - progress = Graph( Time(), startTime, endTime ) - if ( progress >= 1.0 ) - break - - org = end * ( 1 - progress ) + start * progress - zipline.end.SetOrigin( org ) - - org = mid * ( 1 - progress ) + start * progress - - if ( !IsValid( zipline.mid ) ) - return - zipline.mid.SetOrigin( org ) - - WaitFrame() - } -*/ -} - -function CreateRopeEntities( Table ) -{ - local subdivisions = 8 // 25 - local slack = 100 // 25 - string midpointName = UniqueString( "rope_midpoint" ) - string endpointName = UniqueString( "rope_endpoint" ) - - entity rope_start = CreateEntity( "move_rope" ) - rope_start.kv.NextKey = midpointName - rope_start.kv.MoveSpeed = 64 - rope_start.kv.Slack = slack - rope_start.kv.Subdiv = subdivisions - rope_start.kv.Width = "2" - rope_start.kv.TextureScale = "1" - rope_start.kv.RopeMaterial = "cable/cable.vmt" - rope_start.kv.PositionInterpolator = 2 - - entity rope_mid = CreateEntity( "keyframe_rope" ) - SetTargetName( rope_mid, midpointName ) - rope_mid.kv.NextKey = endpointName - rope_mid.kv.MoveSpeed = 64 - rope_mid.kv.Slack = slack - rope_mid.kv.Subdiv = subdivisions - rope_mid.kv.Width = "2" - rope_mid.kv.TextureScale = "1" - rope_mid.kv.RopeMaterial = "cable/cable.vmt" - - entity rope_end = CreateEntity( "keyframe_rope" ) - SetTargetName( rope_end, endpointName ) - rope_end.kv.MoveSpeed = 64 - rope_end.kv.Slack = slack - rope_end.kv.Subdiv = subdivisions - rope_end.kv.Width = "2" - rope_end.kv.TextureScale = "1" - rope_end.kv.RopeMaterial = "cable/cable.vmt" - - Table.start <- rope_start - Table.mid <- rope_mid - Table.end <- rope_end - - return Table -} - -function SpawnZiplineEntities( Table ) -{ - // after origins are set - DispatchSpawn( Table.start ) - DispatchSpawn( Table.mid ) - DispatchSpawn( Table.end ) - return Table -} - -function GetDropPos( zipline ) -{ - entity ship = expect entity( zipline.ship ) - if ( !HasDropshipDropTable( ship ) ) - return null - - DropTable dropTable = GetDropshipDropTable( ship ) - - foreach ( side, nodeTables in dropTable.nodes ) - { - foreach ( nodeTable in nodeTables ) - { - if ( nodeTable.attachName == zipline.shipAttach ) - return nodeTable.origin - } - } - - return null -} - -function GetHookOriginFromNode( origin, nodeOrigin, attachOrigin ) -{ - // need to use the slope of guy to node to get the slope for the zipline, then launch it from the attachment origin - local dropVec = nodeOrigin - origin - local dropDist = Length( dropVec ) - dropVec.Norm() - -// DrawArrow( nodeOrigin, Vector(0,0,0), 5, 100 ) - local attachEnd = attachOrigin + dropVec * ( dropDist + 1500 ) // some buffer - TraceResults zipTrace = TraceLine( attachOrigin, attachEnd, null, TRACE_MASK_NPCWORLDSTATIC ) - -// DebugDrawLine( attachOrigin, zipTrace.endPos, 0, 255, 0, true, 5.0 ) -// DebugDrawLine( zipTrace.endPos, attachEnd, 255, 0, 0, true, 5.0 ) - - // zipline didn't connect with anything - if ( zipTrace.fraction == 1.0 ) - { -// DebugDrawLine( attachOrigin, attachEnd, 255, 255, 0, true, 5.0 ) - return null - } - - if ( Distance( zipTrace.endPos, attachOrigin ) < 300 ) - return null - - return zipTrace.endPos -} - -function ZiplineInit( entity player ) -{ - player.s.ziplineEffects <- [] -} - -function CreateZiplineJetEffects( entity player ) -{ - asset jumpJetEffectFriendlyName = $"hmn_imc_jump_jet_wallrun_full" - asset jumpJetEffectEnemyName = $"hmn_mcorps_jump_jet_wallrun_full" - int playerTeam = player.GetTeam() - - //HACK! - //Create 2 sets of jump jet effects, 1 visible to friendly, 1 visible to enemy - //Doing this for a myriad of reasons on the server as opposed to on the client like the rest - //of the jump jet effects. Since ziplining isn't all that common an action it should be fine - - //create left jump jetfriendly - entity leftJumpJetFriendly = CreateEntity( "info_particle_system" ) - leftJumpJetFriendly.kv.start_active = 1 - leftJumpJetFriendly.kv.VisibilityFlags = ENTITY_VISIBLE_TO_FRIENDLY - leftJumpJetFriendly.SetValueForEffectNameKey( jumpJetEffectFriendlyName ) - SetTargetName( leftJumpJetFriendly, UniqueString() ) - leftJumpJetFriendly.SetParent( player, "vent_left_back", false, 0 ) - SetTeam( leftJumpJetFriendly, playerTeam ) - leftJumpJetFriendly.SetOwner( player) - DispatchSpawn( leftJumpJetFriendly ) - - //now create right jump jet for friendly - entity rightJumpJetFriendly = CreateEntity( "info_particle_system" ) - rightJumpJetFriendly.kv.start_active = 1 - rightJumpJetFriendly.kv.VisibilityFlags = ENTITY_VISIBLE_TO_FRIENDLY - rightJumpJetFriendly.SetValueForEffectNameKey( jumpJetEffectFriendlyName ) - SetTargetName( rightJumpJetFriendly, UniqueString() ) - rightJumpJetFriendly.SetParent( player, "vent_right_back", false, 0 ) - SetTeam( rightJumpJetFriendly, playerTeam ) - rightJumpJetFriendly.SetOwner( player) - DispatchSpawn( rightJumpJetFriendly ) - - //create left jump jet for enemy - entity leftJumpJetEnemy = CreateEntity( "info_particle_system" ) - leftJumpJetEnemy.kv.start_active = 1 - leftJumpJetEnemy.kv.VisibilityFlags = ENTITY_VISIBLE_TO_ENEMY - leftJumpJetEnemy.SetValueForEffectNameKey( jumpJetEffectEnemyName ) - SetTargetName( leftJumpJetEnemy, UniqueString() ) - leftJumpJetEnemy.SetParent( player, "vent_left_back", false, 0 ) - SetTeam( leftJumpJetEnemy, playerTeam ) - leftJumpJetEnemy.SetOwner( player) - DispatchSpawn( leftJumpJetEnemy ) - - //now create right jump jet for enemy - entity rightJumpJetEnemy = CreateEntity( "info_particle_system" ) - rightJumpJetEnemy.kv.start_active = 1 - rightJumpJetEnemy.kv.VisibilityFlags = ENTITY_VISIBLE_TO_ENEMY - rightJumpJetEnemy.SetValueForEffectNameKey( jumpJetEffectEnemyName ) - SetTargetName( rightJumpJetEnemy, UniqueString() ) - rightJumpJetEnemy.SetParent( player, "vent_right_back", false, 0 ) - SetTeam( rightJumpJetEnemy, playerTeam ) - rightJumpJetEnemy.SetOwner( player) - DispatchSpawn( rightJumpJetEnemy ) - - //sparks from the hand - entity handSparks = CreateEntity( "info_particle_system" ) - handSparks.kv.start_active = 1 - handSparks.kv.VisibilityFlags = ENTITY_VISIBLE_TO_FRIENDLY | ENTITY_VISIBLE_TO_ENEMY - handSparks.SetValueForEffectNameKey( $"P_Zipline_hld_1" ) - SetTargetName( handSparks, UniqueString() ) - handSparks.SetParent( player, "L_HAND", false, 0 ) - handSparks.SetOwner( player) - DispatchSpawn( handSparks ) - - //Do it again for greater intensity! - entity handSparks2 = CreateEntity( "info_particle_system" ) - handSparks2.kv.start_active = 1 - handSparks2.kv.VisibilityFlags = ENTITY_VISIBLE_TO_FRIENDLY | ENTITY_VISIBLE_TO_ENEMY - handSparks2.SetValueForEffectNameKey( $"P_Zipline_hld_1" ) - SetTargetName( handSparks2, UniqueString() ) - handSparks2.SetParent( player, "L_HAND", false, 0 ) - handSparks2.SetOwner( player) - DispatchSpawn( handSparks2 ) - - player.s.ziplineEffects.append( leftJumpJetFriendly ) - player.s.ziplineEffects.append( rightJumpJetFriendly ) - player.s.ziplineEffects.append( leftJumpJetEnemy ) - player.s.ziplineEffects.append( rightJumpJetEnemy ) - - player.s.ziplineEffects.append( handSparks ) - player.s.ziplineEffects.append( handSparks2 ) -} - -void function CodeCallback_ZiplineMount( entity player, entity zipline ) -{ - // printl( "Mounting zipline") - #if SERVER - EmitDifferentSoundsOnEntityForPlayerAndWorld( "player_zipline_attach", "3p_zipline_attach", player, player ) - #endif - -} - -void function CodeCallback_ZiplineStart( entity player, entity zipline ) -{ - #if SERVER - CreateZiplineJetEffects( player ) - EmitDifferentSoundsOnEntityForPlayerAndWorld( "player_zipline_loop", "3p_zipline_loop", player, player ) - foreach ( callback in _ZiplineStartCallbacks ) - thread callback( player, zipline ) - #endif -} - -void function CodeCallback_ZiplineMove( entity player, entity zipline ) -{ - #if SERVER - if ( player.IsPhaseShifted() ) - { - foreach( effect in player.s.ziplineEffects ) - { - IsValid( effect ) - effect.Destroy() - } - player.s.ziplineEffects.clear() - } - else if ( player.s.ziplineEffects.len() <= 0 ) - { - CreateZiplineJetEffects( player ); - } - #endif -} - -void function CodeCallback_ZiplineStop( entity player ) -{ - #if SERVER - foreach( effect in player.s.ziplineEffects ) - { - IsValid( effect ) - effect.Destroy() - } - player.s.ziplineEffects.clear() - - StopSoundOnEntity( player, "player_zipline_loop" ) - StopSoundOnEntity( player, "3p_zipline_loop" ) - - EmitDifferentSoundsOnEntityForPlayerAndWorld( "player_zipline_detach", "3p_zipline_detach", player, player ) - - foreach ( callback in _ZiplineStopCallbacks ) - thread callback( player ) - #endif -} - -void function AddCallback_ZiplineStart( void functionref(entity,entity) callback ) -{ - _ZiplineStartCallbacks.append( callback ) -} - -void function AddCallback_ZiplineStop( void functionref(entity) callback ) -{ - _ZiplineStopCallbacks.append( callback ) -} - -function ZiplineMover( entity ent, end, timeTotal, blendIn = 0, blendOut = 0 ) -{ - Assert( !IsThreadTop(), "This should not be waitthreaded off, it creates timing issues." ) - entity mover = CreateOwnedScriptMover( ent ) - ent.SetParent( mover ) - - OnThreadEnd( - function() : ( ent, mover ) - { - if ( IsValid( mover ) ) - mover.Destroy() - } - ) - - mover.MoveTo( end, timeTotal, blendIn, blendOut ) - wait timeTotal - - if ( IsValid( ent ) ) - ent.ClearParent() -} - -array<string> function GetZiplineLandingAnims() -{ - return file.zipLineLandingAnimations -}
\ No newline at end of file diff --git a/Northstar.CustomServers/scripts/vscripts/pilot/class_wallrun.gnut b/Northstar.CustomServers/scripts/vscripts/pilot/class_wallrun.gnut deleted file mode 100644 index 58de59c1..00000000 --- a/Northstar.CustomServers/scripts/vscripts/pilot/class_wallrun.gnut +++ /dev/null @@ -1,224 +0,0 @@ -untyped - -global function ClassWallrun_Init - -global function Wallrun_AddPlayer -global function Wallrun_OnPlayerSpawn -global function Wallrun_OnPlayerDeath -global function Wallrun_PlayerTookDamage -global function Wallrun_EnforceWeaponDefaults -global function Wallrun_CreateCopyOfPilotModel - -function ClassWallrun_Init() -{ - - // Make weapons less effective when playing at higher difficulty. - level.lethalityMods <- {} -} - -function Wallrun_AddPlayer( player ) -{ - player.playerClassData[level.pilotClass] <- {} -} - - -function Wallrun_EnforceWeaponDefaults( player ) -{ - if ( player.playerClassData[ level.pilotClass ].primaryWeapon ) - { - // settings already exist - return - } - - player.playerClassData[ level.pilotClass ].primaryWeapon = "mp_weapon_r97" - player.playerClassData[ level.pilotClass ].secondaryWeapon = "mp_weapon_sniper" - - local offhandWeaponTable = {} - offhandWeaponTable[0] <- { weapon = "mp_weapon_frag_grenade", mods = [] } - offhandWeaponTable[1] <- { weapon = "mp_ability_heal", mods = [] } - - player.playerClassData[ level.pilotClass ].offhandWeapons = offhandWeaponTable - player.playerClassData[ level.pilotClass ].playerSetFile = DEFAULT_PILOT_SETTINGS -} - - -function Wallrun_OnPlayerSpawn( player ) -{ -} - - -function Wallrun_PlayerTookDamage( entity player, damageInfo, entity attacker ) -{ - if ( IsDemigod( player ) ) - { - EntityDemigod_TryAdjustDamageInfo( player, damageInfo ) - return - } - - AdjustDamageForRodeoPlayers( player, damageInfo, attacker ) - - #if VERBOSE_DAMAGE_PRINTOUTS - printt( " After Wallrun_PlayerTookDamage:", DamageInfo_GetDamage( damageInfo ) ) - #endif - - if ( player.GetShieldHealthMax() > 0 ) - { - local shieldDamage = PilotShieldHealthUpdate( player, damageInfo ) - return shieldDamage - } - - return -} - -function AdjustDamageForRodeoPlayers( entity player, var damageInfo, entity attacker ) -{ - if ( player == attacker ) - return - - local titanSoulRodeoed = player.GetTitanSoulBeingRodeoed() - if ( !IsValid( titanSoulRodeoed ) ) - return - - local playerParent = titanSoulRodeoed.GetTitan() - - // dont let npcs hurt rodeo player - if ( attacker.IsNPC() && attacker != playerParent && DamageInfo_GetDamageSourceIdentifier( damageInfo ) != eDamageSourceId.mp_titanability_smoke ) - { - DamageInfo_SetDamage( damageInfo, 0 ) - return - } - - local damage = DamageInfo_GetDamage( damageInfo ) - - if ( !ShouldAdjustDamageForRodeoPlayer( damageInfo ) ) - return - - local maxPer500ms - - if ( attacker == playerParent ) - { - // rodeo'd player can't damage quite as much - maxPer500ms = 56 - } - else - if ( playerParent.GetTeam() == player.GetTeam() ) - { - // riding same team titan protects you a bit from random fire on that titan - if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_EXPLOSION ) - { - maxPer500ms = 75 - } - else if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_MELEE ) //If melee, players still die in one hit - { - maxPer500ms = player.GetMaxHealth() + 1 - } - else - { - maxPer500ms = 175 - } - } - else - { - return - } - - //Set a cap on how much damage the playerParent can do. - local damageTaken = GetTotalDamageTakenInTime( player, 0.5 ) - - local allowedDamage = maxPer500ms - damageTaken - if ( damage < allowedDamage ) - return - - damage = allowedDamage - if ( damage <= 0 ) - damage = 0 - - DamageInfo_SetDamage( damageInfo, damage ) -} - - -function ShouldAdjustDamageForRodeoPlayer( damageInfo ) -{ - int sourceID = DamageInfo_GetDamageSourceIdentifier( damageInfo ) - - switch( sourceID ) - { - case eDamageSourceId.rodeo_trap: - case eDamageSourceId.mp_titanweapon_vortex_shield: - case eDamageSourceId.mp_titanweapon_vortex_shield_ion: - case eDamageSourceId.mp_titanability_smoke: - case eDamageSourceId.mp_weapon_satchel: //added so that rodeoing players are no longer invulnerable to their satchels when detonated by Titan's smoke - return false - - default: - return true - } -} - - -function Wallrun_OnPlayerDeath( entity player, damageInfo ) -{ - if ( IsValidHeadShot( damageInfo, player ) ) - { - int damageType = DamageInfo_GetCustomDamageType( damageInfo ) - local soundAlias - if ( damageType & DF_SHOTGUN ) - { - EmitSoundOnEntityOnlyToPlayer( player, player, "Flesh.Shotgun.BulletImpact_Headshot_3P_vs_1P" ) - soundAlias = "Flesh.Shotgun.BulletImpact_Headshot_3P_vs_3P" - } - else if ( damageType & damageTypes.bullet || damageType & DF_BULLET ) - { - EmitSoundOnEntityOnlyToPlayer( player, player, "Flesh.Light.BulletImpact_Headshot_3P_vs_1P" ) - soundAlias = "Flesh.Light.BulletImpact_Headshot_3P_vs_3P" - } - else if ( damageType & damageTypes.largeCaliber || damageType & DF_GIB ) - { - EmitSoundOnEntityOnlyToPlayer( player, player, "Flesh.Heavy.BulletImpact_Headshot_3P_vs_1P" ) - soundAlias = "Flesh.Heavy.BulletImpact_Headshot_3P_vs_3P" - } - - if ( soundAlias ) - { - entity attacker = DamageInfo_GetAttacker( damageInfo ) - array<entity> pilotArray = GetPlayerArray() - //Iterating because we need to not play this sound on 2 pilots and the function only allows for 1. Performance difference is negligible according to Eric M between this and adding a specific code function. - foreach ( pilot in pilotArray ) - { - if ( !IsValid( pilot ) ) - continue - - if ( pilot == player || pilot == attacker ) - continue - - EmitSoundOnEntityOnlyToPlayer( player, pilot, soundAlias ) - } - } - } -} - - -entity function Wallrun_CreateCopyOfPilotModel( entity player ) -{ - const string PLAYER_SETTINGS_FIELD = "bodymodel" - - asset modelName - if ( player.IsTitan() ) - { - modelName = GetPlayerSettingsAssetForClassName( player.s.storedPlayerSettings, PLAYER_SETTINGS_FIELD ) - } - else - { - modelName = player.GetPlayerSettingsAsset( PLAYER_SETTINGS_FIELD ) - } - - entity model = CreatePropDynamic( modelName ) - - SetTeam( model, player.GetTeam() ) - - //model.SetSkin( 0 ) - - RandomizeHead( model ) - - return model -} |