diff options
Diffstat (limited to 'Northstar.CustomServers/scripts/vscripts/_utility.gnut')
-rw-r--r-- | Northstar.CustomServers/scripts/vscripts/_utility.gnut | 4394 |
1 files changed, 0 insertions, 4394 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/_utility.gnut b/Northstar.CustomServers/scripts/vscripts/_utility.gnut deleted file mode 100644 index 50851dae..00000000 --- a/Northstar.CustomServers/scripts/vscripts/_utility.gnut +++ /dev/null @@ -1,4394 +0,0 @@ - -globalize_all_functions - -//========================================================= -// _utility -// -//========================================================= - -int functionref( bool = false ) ornull te = null -int EntTracker = 0 - -global const C_PLAYFX_SINGLE = 0 -global const C_PLAYFX_MULTIPLE = 1 -global const C_PLAYFX_LOOP = 2 - -global const MUTEALLFADEIN = 2 - -global struct ZipLine -{ - entity start - entity mid - entity end -} - -global int HUMAN_RAGDOLL_IMPACT_TABLE_IDX = -1 - -global struct ArrayDotResultStruct -{ - entity ent - float dot -} - -global struct ShieldDamageModifier -{ - float permanentDamageFrac = TITAN_SHIELD_PERMAMENT_DAMAGE_FRAC - bool normalizeShieldDamage = false - float damageScale = 1.0 -} - - -struct -{ - bool isSkyboxView = false -} file - -void function Utility_Init() -{ - te = TotalEnts - EntTracker = 0 - - #document( "SetDeathFuncName", "Sets the name of a function that runs when the NPC dies." ) - #document( "CenterPrint", "Print to the screen" ) - #document( "GetAllSoldiers", "Get all living soldiers." ) - #document( "ClearDeathFuncName", "Clears the script death function." ) - - HUMAN_RAGDOLL_IMPACT_TABLE_IDX = PrecacheImpactEffectTable( "ragdoll_human" ) - - RegisterSignal( "PetTitanUpdated" ) - RegisterSignal( "WaitDeadTimeOut" ) - RegisterSignal( "InventoryChanged" ) - - AddClientCommandCallback( "OnDevnetBugScreenshot", ClientCommand_OnDevnetBugScreenshot ) - #if DEV - FlagInit( "AimAssistSwitchTest_Enabled" ) - AddClientCommandCallback( "DoomTitan", ClientCommand_DoomTitan ) - #endif -} - -void function GiveAllTitans() -{ - - array<entity> players = GetPlayerArray() - foreach ( player in players ) - { - #if MP - GiveTitanToPlayer( player ) - #endif - - if ( player.IsTitan() ) - { - entity soul = player.GetTitanSoul() - if ( soul ) - { - SoulTitanCore_SetNextAvailableTime( soul, 1 ) - } - } - } - - array<entity> titans = GetNPCArrayByClass( "npc_titan" ) - foreach ( titan in titans ) - { - entity soul = titan.GetTitanSoul() - if ( soul ) - SoulTitanCore_SetNextAvailableTime( soul, 1 ) - } -} - -#if DEV - -void function KillAllBadguys() -{ - array<entity> npcs = GetNPCArrayOfEnemies( GetPlayerArray()[0].GetTeam() ) - foreach ( n in npcs ) - { - if ( n.GetClassName() == "npc_bullseye" ) - continue - - if ( !IsAlive( n ) ) - continue - n.Die() - } -} - -bool function ClientCommand_DoomTitan( entity player, array<string> args ) -{ - entity titan - if ( player.IsTitan() ) - titan = player - else - titan = player.GetPetTitan() - - if ( !IsAlive( titan ) ) - return true - - if ( GetDoomedState( titan ) ) - return true - - entity soul = titan.GetTitanSoul() - soul.SetShieldHealth( 0 ) - - titan.TakeDamage( titan.GetHealth(), null, null, { damageSourceId=damagedef_suicide, scriptType = DF_SKIP_DAMAGE_PROT } ) - - return true -} -#endif - -void function PrintPlaylists() -{ - printt( "=== PLAYLIST NAMES: ===" ) - - int count = GetPlaylistCount() - for ( int i = 0; i < count; i++ ) - { - printt( "--", GetPlaylistName( i ) ) - } -} - -entity function CreateEntity( string name ) -{ -// if ( name == "npc_titan" ) -// { -// DumpStack(3) -// } -// if ( name == "info_particle_system" ) -// { -// printl( " " ) -// DumpStack(3) -// } - return Entities_CreateByClassname( name ) -} - -// used from the console to quick-test fields -void function setnpcfields( string key, var val ) -{ - array<entity> npcs = GetNPCArrayByClass( "npc_soldier" ) - foreach ( npc in npcs ) - { - npc.kv[ key ] = val - } -} - -void function WaitUntilNumDead( array<entity> guys, int numDead ) -{ - Assert( numDead <= guys.len(), "asked for " + numDead + " guys to die, but only passed in an array of " + guys.len() + " guys." ) - float timeout = -1 - __WaitUntilDeadInternal( guys, numDead, timeout, __WaitUntilDeadTracker ) -} - -void function WaitUntilNumDeadWithTimeout( array<entity> guys, int numDead, float timeout ) -{ - Assert( numDead <= guys.len(), "asked for " + numDead + " guys to die, but only passed in an array of " + guys.len() + " guys." ) - Assert( timeout > 0 ) - __WaitUntilDeadInternal( guys, numDead, timeout, __WaitUntilDeadTracker ) -} - -void function WaitUntilAllDead( array<entity> guys ) -{ - int count = guys.len() - float timeout = -1 - __WaitUntilDeadInternal( guys, count, timeout, __WaitUntilDeadTracker ) -} - -void function WaitUntilAllDeadWithTimeout( array<entity> guys, float timeout ) -{ - int count = guys.len() - Assert( timeout > 0 ) - __WaitUntilDeadInternal( guys, count, timeout, __WaitUntilDeadTracker ) -} - -void function WaitUntilNumDeadOrLeeched( array<entity> guys, int numDead ) -{ - Assert( numDead <= guys.len(), "asked for " + numDead + " guys to die, but only passed in an array of " + guys.len() + " guys." ) - float timeout = -1 - __WaitUntilDeadInternal( guys, numDead, timeout, __WaitUntilDeadOrLeechedTracker ) -} - -void function WaitUntilNumDeadOrLeechedWithTimeout( array<entity> guys, int numDead, float timeout ) -{ - Assert( numDead <= guys.len(), "asked for " + numDead + " guys to die, but only passed in an array of " + guys.len() + " guys." ) - Assert( timeout > 0 ) - __WaitUntilDeadInternal( guys, numDead, timeout, __WaitUntilDeadOrLeechedTracker ) -} - -void function WaitUntilAllDeadOrLeeched( array<entity> guys ) -{ - int count = guys.len() - float timeout = -1 - __WaitUntilDeadInternal( guys, count, timeout, __WaitUntilDeadOrLeechedTracker ) -} - -void function WaitUntilAllDeadOrLeechedWithTimeout( array<entity> guys, float timeout ) -{ - int count = guys.len() - Assert( timeout > 0 ) - __WaitUntilDeadInternal( guys, count, timeout, __WaitUntilDeadOrLeechedTracker ) -} - -void function __WaitUntilDeadInternal( array<entity> guys, int numDead, float timeout, void functionref( entity, table<string, int> ) deathTrackerFunc ) -{ - table<string, int> master = { count = numDead } - - if ( timeout > 0.0 ) - thread __WaitUntilDeadTrackerDelayedSignal( master, "WaitDeadTimeOut", timeout ) - - //when the thread ends, let child threads know - OnThreadEnd( - function() : ( master ) - { - Signal( master, "OnDestroy" ) - } - ) - - foreach ( guy in guys ) - thread deathTrackerFunc( guy, master ) - - while ( master.count > 0 ) - { - table result = WaitSignal( master, "OnDeath", "WaitDeadTimeOut" ) - if ( result.signal == "WaitDeadTimeOut" ) //can't do endsignal, because it will kill the calling function too - return - } -} - -void function __WaitUntilDeadTrackerDelayedSignal( table<string, int> master, string signal, float delay ) -{ - EndSignal( master, signal ) - - wait delay - if ( IsValid( master ) ) - Signal( master, signal ) -} - -void function __WaitUntilDeadTracker( entity guy, table<string, int> master ) -{ - EndSignal( master, "OnDestroy" ) - if ( IsAlive( guy ) ) - WaitSignal( guy, "OnDeath", "OnDestroy" ) - - master.count-- - Signal( master, "OnDeath" ) -} - -void function __WaitUntilDeadOrLeechedTracker( entity guy, table<string, int> master ) -{ - EndSignal( master, "OnDestroy" ) - if ( IsAlive( guy ) ) - WaitSignal( guy, "OnDeath", "OnDestroy", "OnLeeched" ) - - master.count-- - Signal( master, "OnDeath" ) -} - -void function SetRebreatherMaskVisible( entity ent, bool visible ) -{ - asset modelname = ent.GetModelName() - - int maskIdx = ent.FindBodyGroup( "mask" ) - if ( maskIdx == -1 ) - return - - int visibleIdx = 1 - if ( !visible ) - visibleIdx = 0 - - ent.SetBodygroup( maskIdx, visibleIdx ) -} - -int function EntHasSpawnflag( entity ent, int spawnflagHexVal ) -{ - return ( expect int( ent.kv.spawnflags ) & spawnflagHexVal ) -} - -entity function CreateInfoTarget( vector origin = <0,0,0>, vector angles = <0,0,0> ) -{ - entity info_target = CreateEntity( "info_target" ) - info_target.SetOrigin( origin ) - info_target.SetAngles( angles ) - DispatchSpawn( info_target ) - return info_target -} - -entity function CreateExpensiveScriptMover( vector origin = <0.0, 0.0, 0.0>, vector angles = <0.0, 0.0, 0.0>, int solidType = 0 ) -{ - entity script_mover = CreateEntity( "script_mover" ) - script_mover.kv.solid = solidType - script_mover.SetValueForModelKey( $"models/dev/empty_model.mdl" ) - script_mover.kv.SpawnAsPhysicsMover = 0 - script_mover.SetOrigin( origin ) - script_mover.SetAngles( angles ) - - DispatchSpawn( script_mover ) - return script_mover -} - -entity function CreateScriptMover( vector origin = <0.0, 0.0, 0.0>, vector angles = <0.0, 0.0, 0.0>, int solidType = 0 ) -{ - entity script_mover = CreateEntity( "script_mover_lightweight" ) - script_mover.kv.solid = solidType - script_mover.SetValueForModelKey( $"models/dev/empty_model.mdl" ) - script_mover.kv.SpawnAsPhysicsMover = 0 - script_mover.SetOrigin( origin ) - script_mover.SetAngles( angles ) - DispatchSpawn( script_mover ) - return script_mover -} - -entity function CreateScriptMoverModel( asset model, vector origin = <0.0, 0.0, 0.0>, vector angles = <0.0, 0.0, 0.0>, int solidType = 0, float fadeDist = -1 ) -{ - entity script_mover = CreateEntity( "script_mover_lightweight" ) - script_mover.kv.solid = solidType - script_mover.kv.fadedist = fadeDist - script_mover.SetValueForModelKey( model ) - script_mover.kv.SpawnAsPhysicsMover = 0 - script_mover.SetOrigin( origin ) - script_mover.SetAngles( angles ) - DispatchSpawn( script_mover ) - return script_mover -} - -entity function CreateExpensiveScriptMoverModel( asset model, vector origin = <0.0, 0.0, 0.0>, vector angles = <0.0, 0.0, 0.0>, int solidType = 0, float fadeDist = -1 ) -{ - entity script_mover = CreateEntity( "script_mover" ) - script_mover.kv.solid = solidType - script_mover.kv.fadedist = fadeDist - script_mover.SetValueForModelKey( model ) - script_mover.kv.SpawnAsPhysicsMover = 0 - script_mover.SetOrigin( origin ) - script_mover.SetAngles( angles ) - DispatchSpawn( script_mover ) - return script_mover -} - -entity function CreateOwnedScriptMover( entity owner ) -{ - entity script_mover = CreateEntity( "script_mover" ) - script_mover.kv.solid = 0 - script_mover.SetValueForModelKey( $"models/dev/empty_model.mdl" ) - script_mover.kv.SpawnAsPhysicsMover = 0 - script_mover.SetOrigin( owner.GetOrigin() ) - script_mover.SetAngles( owner.GetAngles() ) - DispatchSpawn( script_mover ) - script_mover.Hide() - - script_mover.SetOwner( owner ) - return script_mover -} - -// useful for finding out what ents are in a level. Should only be used for debugging. -int function TotalEnts( bool hidden = false ) -{ - array<entity> entities - - EntTracker++ - - entity ent = Entities_FindInSphere( null, < 0, 0, 0 >, 90000 ) - string name - for ( ;; ) - { - if ( ent == null ) - break - - entities.append( ent ) - - name = ent.GetTargetName() - - string strPrefix = "Old ent" - if ( ent.e.totalEntsStoredID == 0 ) - { - string strPrefix = "* New ent" - ent.e.totalEntsStoredID = EntTracker - } - - string strPostfix = "" - if ( name != "" ) - strPostfix = " \"" + name + "\"" - - if ( !hidden ) - printl( strPrefix + " (" + ent.e.totalEntsStoredID + "): " + ent + strPostfix ) - - ent = Entities_FindInSphere( ent, < 0, 0, 0 >, 90000 ) - } - - if ( !hidden ) - printl( "Total entities " + entities.len() ) - - return entities.len() -} - -bool function IsThreadTop() -{ - return getstackinfos( 3 ) == null -} - -string function ThisFunc() -{ - return expect string( expect table( getstackinfos( 2 ) )[ "func" ] ) -} - -entity function ge( int index ) // shorthand version for typing from console -{ - return GetEntByIndex( index ) -} - -entity function GetEnt( string name ) -{ - entity ent = Entities_FindByName( null, name ) - if ( ent == null ) - { - ent = Entities_FindByClassname( null, name ) - Assert( Entities_FindByClassname( ent, name ) == null, "Tried to GetEnt but there were multiple entities with that name" ) - } - else - { - Assert( Entities_FindByName( ent, name ) == null, "Tried to GetEnt but there were multiple entities with name " + name ) - } - - return ent -} - -array<entity> function ArrayWithinCenter( array<entity> ents, vector start, int range ) -{ - array<entity> Array - foreach ( ent in ents ) - { - if ( Distance( start, ent.GetWorldSpaceCenter() ) > range ) - continue - - Array.append( ent ) - } - - return Array -} - -vector function GetCenter( array<entity> ents ) -{ - vector total - - foreach ( ent in ents ) - { - total += ent.GetOrigin() - } - - total.x /= float( ents.len() ) - total.y /= float( ents.len() ) - total.z /= float( ents.len() ) - - return total -} - -void function TableRemoveInvalid( table<entity, entity> Table ) -{ - array<entity> deleteKey = [] - - foreach ( entity key, entity value in Table ) - { - if ( !IsValid_ThisFrame( key ) ) - deleteKey.append( key ) - - if ( !IsValid_ThisFrame( value ) ) - deleteKey.append( key ) - } - - foreach ( key in deleteKey ) - { - // in this search, two things could end up on the same key - if ( key in Table ) - delete Table[ key ] - } -} - -void function TableRemoveInvalidByValue( table<entity, entity> Table ) -{ - array<entity> deleteKey = [] - - foreach ( key, entity value in Table ) - { - if ( !IsValid_ThisFrame( value ) ) - deleteKey.append( key ) - } - - foreach ( key in deleteKey ) - { - delete Table[ key ] - } -} - -void function TableRemoveDeadByKey( table<entity, entity> Table ) -{ - array<entity> deleteKey = [] - - foreach ( key, value in Table ) - { - if ( !IsAlive( key ) ) - deleteKey.append( key ) - } - - foreach ( key in deleteKey ) - { - delete Table[ key ] - } -} - - -void function ArrayDump( array<var> Array ) -{ - for ( int i = 0; i < Array.len(); i++ ) - { - printl( "index " + i + " is: " + Array[i] ) - } -} - - -int function DotCompareLargest( ArrayDotResultStruct a, ArrayDotResultStruct b ) -{ - if ( a.dot < b.dot ) - return 1 - else if ( a.dot > b.dot ) - return -1 - - return 0 -} - -int function DotCompareSmallest( ArrayDotResultStruct a, ArrayDotResultStruct b ) -{ - if ( a.dot > b.dot ) - return 1 - else if ( a.dot < b.dot ) - return -1 - - return 0 -} - -array<ArrayDotResultStruct> function ArrayDotResults( array<entity> Array, entity ent ) -{ - array<ArrayDotResultStruct> allResults - - foreach ( arrayEnt in Array ) - { - ArrayDotResultStruct results - - results.dot = VectorDot_EntToEnt( ent, arrayEnt ) - results.ent = arrayEnt - allResults.append( results ) - } - - return allResults -} - - -// Return an array of entities ordered from closest to furthest from the facing of the entity -array<entity> function ArrayClosestToView( array<entity> Array, entity ent ) -{ - Assert( type( Array ) == "array" ) - array<ArrayDotResultStruct> allResults = ArrayDotResults( Array, ent ) - - allResults.sort( DotCompareLargest ) - - array<entity> returnEntities = [] - - foreach ( index, result in allResults ) - { - //printl( "Results are " + result.dot ) - returnEntities.insert( index, result.ent ) - } - - // the actual distances aren't returned - return returnEntities -} - - -entity function SpawnRefEnt( entity ent ) -{ - printl( "Ent model " + ent.GetValueForModelKey() ) - int attach = ent.LookupAttachment( "ref" ) - vector origin = ent.GetAttachmentOrigin( attach ) - vector angles = ent.GetAttachmentAngles( attach ) - - entity ref = CreateEntity( "prop_dynamic" ) - //ref.kv.SpawnAsPhysicsMover = 0 - ref.SetValueForModelKey( $"models/dev/empty_model.mdl" ) - DispatchSpawn( ref ) - - ref.SetOrigin( origin ) - ref.SetAngles( angles ) - ref.Hide() - return ref -} - -entity function CreateScriptRef( vector ornull origin = null, vector ornull angles = null ) -{ - entity ent = CreateEntity( "script_ref" ) - - if ( origin ) - ent.SetOrigin( expect vector( origin ) ) - - if ( angles ) - ent.SetAngles( expect vector( angles ) ) - - DispatchSpawn( ent ) - return ent -} - -entity function CreateScriptRefMinimap( vector origin, vector angles ) -{ - entity ent = CreateEntity( "script_ref_minimap" ) - - ent.SetOrigin( origin ) - ent.SetAngles( angles ) - - DispatchSpawn( ent ) - - return ent -} - -bool function exists( table tbl, string val ) -{ - if ( !(val in tbl) ) - return false - - return tbl[ val ] != null -} - -var function TableRandomIndex( table Table ) -{ - array Array = [] - - foreach ( index, _ in Table ) - { - Array.append( index ) - } - - return Array.getrandom() -} - -// should improve this -float function YawDifference( float yaw1, float yaw2 ) -{ - Assert( yaw1 >= 0 ) - Assert( yaw1 <= 360 ) - Assert( yaw2 >= 0 ) - Assert( yaw2 <= 360 ) - - float diff = fabs( yaw1 - yaw2 ) - - if ( diff > 180 ) - return 360 - diff - else - return diff - - unreachable -} - - - -/*function TrackIsTouching( ent ) -{ - return // now uses IsTouching - - //ent.s.touching <- {} - //ent.ConnectOutput( "OnStartTouch", TrackIsTouching_OnStartTouch ) - //ent.ConnectOutput( "OnEndTouch", TrackIsTouching_OnEndTouch ) -} - -void function TrackIsTouching_OnStartTouch( entity self, entity activator, entity caller, var value ) -{ - if ( activator ) - { - self.s.touching[ activator ] <- true - } -} - -void function TrackIsTouching_OnEndTouch( entity self, entity activator, entity caller, var value ) -{ - if ( activator ) - { - if ( activator in self.s.touching ) - { - delete self.s.touching[ activator ] - } - } -}*/ - -void function NPC_NoTarget( entity self ) -{ - self.SetNoTarget( true ) - self.SetNoTargetSmartAmmo( true ) -} - -vector function GetSimpleTraceEnd( vector start, vector end, float frac ) -{ - vector vec = end - start - vec *= frac - return start + vec -} - -bool function LoadedMain() -{ - if ( "LoadedMain" in level ) - return true - - level.LoadedMain <- true - - return false -} - -void function Warning( string msg ) -{ - printl( "*** WARNING ***" ) - printl( msg ) - DumpStack() - printl( "*** WARNING ***" ) -} - -void function TimeOut( float time ) -{ - table Table = {} - EndSignal( Table, "OnDeath" ) - delaythread( time ) Signal( Table, "OnDeath" ) -} - -string function GetActiveWeaponClass( entity player ) -{ - entity weapon = player.GetActiveWeapon() - Assert( weapon != null ) - - string weaponclass = weapon.GetWeaponClassName() - return weaponclass -} - -bool function HasWeapon( entity ent, string weaponClassName, array<string> mods = [] ) -{ - Assert( ent.IsPlayer() || ent.IsNPC() ) - - array<entity> weaponArray = ent.GetMainWeapons() - foreach ( weapon in weaponArray ) - { - if ( weapon.GetWeaponClassName() == weaponClassName ) - { - if ( WeaponHasSameMods( weapon, mods ) ) - return true - } - } - - return false -} - -bool function HasOrdnance( entity ent, string weaponClassName, array<string> mods = [] ) -{ - return HasOffhandForSlot( ent, OFFHAND_ORDNANCE, weaponClassName, mods ) -} - -bool function HasCoreAbility( entity ent, string weaponClassName, array<string> mods = [] ) -{ - return HasOffhandForSlot( ent, OFFHAND_EQUIPMENT, weaponClassName, mods ) -} - -bool function HasSpecial( entity ent, string weaponClassName, array<string> mods = [] ) -{ - return HasOffhandForSlot( ent, OFFHAND_SPECIAL, weaponClassName, mods ) -} - -bool function HasAntiRodeo( entity ent, string weaponClassName, array<string> mods = [] ) -{ - return HasOffhandForSlot( ent, OFFHAND_ANTIRODEO, weaponClassName, mods ) -} - -bool function HasMelee( entity ent, string weaponClassName, array<string> mods = [] ) -{ - return HasOffhandForSlot( ent, OFFHAND_MELEE, weaponClassName, mods ) -} - -bool function HasOffhandForSlot( entity ent, int slot, string weaponClassName, array<string> mods = [] ) -{ - Assert( ent.IsPlayer() || ent.IsNPC() ) - - entity weapon = ent.GetOffhandWeapon( slot ) - if ( !IsValid( weapon ) ) - return false - - if ( weapon.GetWeaponClassName() != weaponClassName ) - return false - - return WeaponHasSameMods( weapon, mods ) -} - -bool function WeaponHasSameMods( entity weapon, array<string> mods = [] ) -{ - array hasMods = clone mods - foreach ( mod in weapon.GetMods() ) - { - hasMods.removebyvalue( mod ) - } - - // has all the same mods. - return hasMods.len() == 0 -} - -bool function HasOffhandWeapon( entity ent, string weaponClassName ) -{ - Assert( ent.IsPlayer() || ent.IsNPC() ) - - array<entity> weaponArray = ent.GetOffhandWeapons() - foreach ( weapon in weaponArray ) - { - if ( weapon.GetWeaponClassName() == weaponClassName ) - return true - } - - return false -} - -float function GetFraction( float value, float min, float max ) -{ - return ( value - min ) / ( max - min ) -} - -float function GetFractionClamped( float value, float min, float max ) -{ - float frac = GetFraction( value, min, max ) - return clamp( frac, 0.0, 1.0 ) -} - -float function GetValueFromFraction( float value, float value_min, float value_max, float return_min, float return_max ) -{ - float frac = GetFractionClamped( value, value_min, value_max ) - float retVal = return_min + ( ( return_max - return_min ) * frac ) - return clamp( retVal, return_min, return_max ) -} - -bool function VectorCompare( vector vec1, vector vec2 ) -{ - if ( vec1.x != vec2.x ) - return false - - if ( vec1.y != vec2.y ) - return false - - return vec1.z == vec2.z -} - -// returns vectordot from viewEnt to targetEnt -float function VectorDot_EntToEnt( entity viewEnt, entity targetEnt ) -{ - vector maxs = targetEnt.GetBoundingMaxs() - vector mins = targetEnt.GetBoundingMins() - maxs += mins - maxs.x *= 0.5 - maxs.y *= 0.5 - maxs.z *= 0.5 - vector targetOrg = targetEnt.GetOrigin() + maxs - - maxs = viewEnt.GetBoundingMaxs() - mins = viewEnt.GetBoundingMins() - maxs += mins - maxs.x *= 0.5 - maxs.y *= 0.5 - maxs.z *= 0.5 - vector viewOrg = viewEnt.GetOrigin() + maxs - - //DebugDrawLine( targetOrg, viewOrg, 255, 255, 255, true, 0.5 ) - vector vecToEnt = ( targetOrg - viewOrg ) - vecToEnt = Normalize( vecToEnt ) - - float dotVal = DotProduct( vecToEnt, viewEnt.GetForwardVector() ) - return dotVal -} - -void function PrecacheEffect( asset effectName ) -{ - entity warningParticle = CreateEntity( "info_particle_system" ) - warningParticle.SetValueForEffectNameKey( effectName ) - warningParticle.kv.start_active = 0 - DispatchSpawn( warningParticle ) - warningParticle.Destroy() -} - -void function PrecacheEntity( string entName, asset model = $"" ) -{ - entity tempEnt = CreateEntity( entName ) - - if ( model != $"" ) - tempEnt.SetValueForModelKey( model ) - - tempEnt.kv.spawnflags = SF_NPC_ALLOW_SPAWN_SOLID - - DispatchSpawn( tempEnt ) - tempEnt.Destroy() -} - -void function PrecacheProjectileEntity( string entName, string weaponClassName, asset model = $"" ) -{ - entity tempEnt = Entities_CreateProjectileByClassname( entName, weaponClassName ) - - if ( model != $"" ) - tempEnt.SetValueForModelKey( model ) - - tempEnt.kv.spawnflags = SF_NPC_ALLOW_SPAWN_SOLID - - DispatchSpawn( tempEnt ) - tempEnt.Destroy() -} - -void function PrecacheSprite( asset spriteName ) -{ - entity sprite = CreateEntity( "env_sprite_oriented" ) - sprite.SetValueForModelKey( spriteName ) - sprite.kv.spawnflags = 1 - DispatchSpawn( sprite ) - sprite.Destroy() -} - -entity function CreatePointMessage( string msg, vector origin, int displayRadius = 512 ) -{ - entity point_message = CreateEntity( "point_message" ) - point_message.SetOrigin( origin ) - point_message.kv.message = msg - point_message.kv.radius = displayRadius - - DispatchSpawn( point_message ) - - return point_message -} - -entity function CreateGameText( string msg, float xPos, float yPos, int channel, string color = "255 255 255", float fadein = 2, float fadeout = 0.5, float holdtime = 2 ) -{ - entity game_text = CreateEntity( "game_text" ) - - game_text.SetScriptName( "gt" + UniqueString() ) - game_text.kv.message = msg - game_text.kv["x"] = xPos - game_text.kv["y"] = yPos - game_text.kv.channel = channel - game_text.kv.color = color - game_text.kv.color2 = "240 110 0" // doesn't appear to do anything atm, not supporting in params - game_text.kv.fadein = fadein - game_text.kv.fadeout = fadeout - game_text.kv.holdtime = holdtime - game_text.kv.fxtime = "0.25" - - DispatchSpawn( game_text ) - - return game_text -} - -// pass the origin where the player's feet would be -// tests a player sized box for any collision and returns true only if it's clear -bool function PlayerCanTeleportHere( entity player, vector testOrg, entity ignoreEnt = null ) //TODO: This is a copy of SP's PlayerPosInSolid(). Not changing it to avoid patching SP. Merge into one function next game -{ - int solidMask = TRACE_MASK_PLAYERSOLID - vector mins - vector maxs - int collisionGroup = TRACE_COLLISION_GROUP_PLAYER - array<entity> ignoreEnts = [ player ] - - if ( IsValid( ignoreEnt ) ) - ignoreEnts.append( ignoreEnt ) - TraceResults result - - mins = player.GetPlayerMins() - maxs = player.GetPlayerMaxs() - result = TraceHull( testOrg, testOrg + < 0, 0, 1 >, mins, maxs, ignoreEnts, solidMask, collisionGroup ) - - if ( result.startSolid ) - return false - - return true -} - - -enum eAttach -{ - No - ViewAndTeleport - View - Teleport - ThirdPersonView -} - - -void function LoadDiamond() -{ - printl( " " ) - printl( " " ) - printl( " " ) - - // Draw a diamond of a random size and phase (of the moon) so it is easy to separate sections of logs. - int random_spread = RandomIntRange( 4, 7 ) - float random_fullness = RandomFloat( 2.0 ) - bool functionref( int, int ) compare_func - string msg - - if ( RandomFloat( 1.0 ) > 0.5 ) - { - compare_func = bool function( int a, int b ) - { - return a <= b - } - } - else - { - compare_func = bool function( int a, int b ) - { - return a >= b - } - } - - for ( int i = 0; i <= random_spread - 2; i++ ) - { - msg = "" - - for ( int p = 0; p <= random_spread - i; p++ ) - { - msg = msg + " " - } - - for ( int p = 0; p <= i * 2; p++ ) - { - if ( p == i * 2 || p == 0 ) - { - msg = msg + "*" - } - else - { - int an_int = int( i * random_fullness ) - - if ( compare_func( p, an_int ) ) - msg = msg + "*" - else - msg = msg + " " - } - } - - printl( msg ) - } - - for ( int i = random_spread - 1; i >= 0; i-- ) - { - msg = "" - - for ( int p = 0; p <= random_spread - i; p++ ) - { - msg = msg + " " - } - - - for ( int p = 0; p <= i * 2; p++ ) - { - if ( p == i * 2 || p == 0 ) - { - msg = msg + "*" - } - else - { - if ( compare_func( p, int( i * random_fullness ) ) ) - { - msg = msg + "*" - } - else - { - msg = msg + " " - } - } - } - - printl( msg ) - } - - printl( " " ) - printl( " " ) - printl( " " ) -} - -// this will clear all dropped weapons in the map -void function ClearDroppedWeapons( float delayTime = 0.0 ) -{ - if ( delayTime > 0 ) - wait delayTime - - bool onlyNotOwnedWeapons = true // don't get the ones in guys' hands - array<entity> weapons = GetWeaponArray( onlyNotOwnedWeapons ) - - foreach ( weapon in weapons ) - { - // don't clean up weapon pickups that were placed in leveled - int spawnflags = expect string( weapon.kv.spawnflags ).tointeger() - if ( spawnflags & SF_WEAPON_START_CONSTRAINED ) - continue - - weapon.Destroy() - } -} - -void function ClearActiveProjectilesForTeam( int team, vector searchOrigin = <0,0,0>, float searchDist = -1 ) -{ - array<entity> projectiles = GetProjectileArrayEx( "any", team, TEAM_ANY, searchOrigin, searchDist ) - - printt( "cleaning up", projectiles.len(), "weapon projectiles for team", team ) - - foreach ( proj in projectiles ) - { - if( !IsValid( proj ) ) - continue - - proj.Destroy() - } -} - -void function RestockPlayerAmmo_Silent( entity player = null ) -{ - RestockPlayerAmmo( player, true ) -} - -void function RestockPlayerAmmo( entity player = null, bool isSilent = false ) -{ - array<entity> players - if ( IsAlive( player ) ) - players.append( player ) - else - players = GetPlayerArray_Alive() - - foreach( player in players ) - { - player.RefillAllAmmo() - - if ( !isSilent ) - EmitSoundOnEntityOnlyToPlayer( player, player, "Coop_AmmoBox_AmmoRefill" ) - } -} - -entity function CreateLightSprite( vector origin, vector angles, string lightcolor = "255 0 0", float scale = 0.5 ) -{ - // attach a light so we can see it - entity env_sprite = CreateEntity( "env_sprite" ) - env_sprite.SetScriptName( UniqueString( "molotov_sprite" ) ) - env_sprite.kv.rendermode = 5 - env_sprite.kv.origin = origin - env_sprite.kv.angles = angles - env_sprite.kv.rendercolor = lightcolor - env_sprite.kv.renderamt = 255 - env_sprite.kv.framerate = "10.0" - env_sprite.SetValueForModelKey( $"sprites/glow_05.vmt" ) - env_sprite.kv.scale = string( scale ) - env_sprite.kv.spawnflags = 1 - env_sprite.kv.GlowProxySize = 16.0 - env_sprite.kv.HDRColorScale = 1.0 - DispatchSpawn( env_sprite ) - EntFireByHandle( env_sprite, "ShowSprite", "", 0, null, null ) - - return env_sprite -} - -// defaultWinner: if it's a tie, return this value -int function GetCurrentWinner( int defaultWinner = TEAM_MILITIA ) -{ - int imcScore - int militiaScore - - if ( IsRoundBased() ) - { - imcScore = GameRules_GetTeamScore2( TEAM_IMC ) - militiaScore = GameRules_GetTeamScore2( TEAM_MILITIA ) - - if ( IsRoundBasedUsingTeamScore() && ( imcScore == militiaScore ) ) - { - imcScore = GameRules_GetTeamScore( TEAM_IMC ) - militiaScore = GameRules_GetTeamScore( TEAM_MILITIA ) - } - } - else - { - imcScore = GameRules_GetTeamScore( TEAM_IMC ) - militiaScore = GameRules_GetTeamScore( TEAM_MILITIA ) - } - - int currentWinner = defaultWinner - - if ( militiaScore > imcScore ) - currentWinner = TEAM_MILITIA - else if ( imcScore > militiaScore ) - currentWinner = TEAM_IMC - - return currentWinner -} - -void function SetNpcFollowsPlayerOverride( entity player, void functionref( entity, entity ) override ) -{ - player.p.followPlayerOverride = override -} - -void function ClearNpcFollowsPlayerOverride( entity player ) -{ - player.p.followPlayerOverride = null -} - -void function AddCallback_GameStateEnter( int gameState, void functionref() callbackFunc ) -{ - Assert( gameState < svGlobal.gameStateEnterCallbacks.len() ) - - Assert( !svGlobal.gameStateEnterCallbacks[ gameState ].contains( callbackFunc ), "Already added " + string( callbackFunc ) + " with AddCallback_GameStateEnter" ) - - svGlobal.gameStateEnterCallbacks[ gameState ].append( callbackFunc ) -} - -void function GM_SetObserverFunc( void functionref( entity ) callbackFunc ) -{ - svGlobal.observerFunc = callbackFunc -} - -void function GM_AddPlayingThinkFunc( void functionref() callbackFunc ) -{ - Assert( !svGlobal.playingThinkFuncTable.contains( callbackFunc ), "Already added " + string( callbackFunc ) + " with GM_AddPlayingThinkFunc" ) - - svGlobal.playingThinkFuncTable.append( callbackFunc ) -} - -void function GM_AddThirtySecondsLeftFunc( void functionref() callbackFunc ) -{ - Assert( !svGlobal.thirtySecondsLeftFuncTable.contains( callbackFunc ), "Already added " + string( callbackFunc ) + " with GM_AddThirtySecondsLeftFunc" ) - - svGlobal.thirtySecondsLeftFuncTable.append( callbackFunc ) -} - -void function GM_SetMatchProgressAnnounceFunc( void functionref( int ) callbackFunc ) -{ - svGlobal.matchProgressAnnounceFunc = callbackFunc -} - -// Get an absolute offset poistion to an entity even if it's been rotated in world space -vector function GetEntPosPlusOffset( entity ent, float offsetX, float offsetY, float offsetZ ) -{ - vector entAngles = ent.GetAngles() - vector entOrg = ent.GetOrigin() - - vector right = AnglesToRight( entAngles ) - right = Normalize( right ) - vector pos = entOrg + ( right * offsetY ) - - vector forward = AnglesToForward( entAngles ) - forward = Normalize( forward ) - pos = pos + ( forward * offsetX ) - - vector up = AnglesToUp( entAngles ) - up = Normalize( up ) - pos = pos + ( up * offsetZ ) - - return pos -} - -void function EmitSoundToTeamPlayers( string alias, int team ) -{ - array<entity> players = GetPlayerArrayOfTeam( team ) - - foreach ( player in players ) - EmitSoundOnEntityOnlyToPlayer( player, player, alias ) -} - -void function EmitDifferentSoundsAtPositionForPlayerAndWorld( string soundForPlayer, string soundForWorld, vector position, entity player, int teamNum ) -{ - if ( IsValid( player ) && player.IsPlayer() ) - { - EmitSoundAtPositionExceptToPlayer( teamNum, position, player, soundForWorld ) - EmitSoundAtPositionOnlyToPlayer( teamNum, position, player, soundForPlayer) - } - else - { - EmitSoundAtPosition( teamNum, position, soundForWorld ) - } -} - -void function EmitDifferentSoundsOnEntityForPlayerAndWorld( string soundForPlayer, string soundForWorld, entity soundEnt, entity player ) -{ - if ( IsValid( player ) && player.IsPlayer() ) - { - EmitSoundOnEntityExceptToPlayerNotPredicted( soundEnt, player, soundForWorld ) - EmitSoundOnEntityOnlyToPlayer(soundEnt, player, soundForPlayer) - } - else - { - EmitSoundOnEntity( soundEnt, soundForWorld ) - } -} - -// Drop an entity to the ground by tracing straight down from its z-axis -void function DropToGround( entity ent ) -{ - vector targetOrigin = OriginToGround( ent.GetOrigin() + <0,0,1> ) - ent.SetOrigin( targetOrigin ) -} - -void function DropTitanToGround( entity titan, array<entity> ignoreEnts ) -{ - vector endOrigin = titan.GetOrigin() - < 0, 0, 20000 > - vector mins = GetBoundsMin( HULL_TITAN ) - vector maxs = GetBoundsMax( HULL_TITAN ) - TraceResults traceResult = TraceHull( titan.GetOrigin(), endOrigin, mins, maxs, ignoreEnts, TRACE_MASK_TITANSOLID, TRACE_COLLISION_GROUP_NONE ) - - titan.SetOrigin( traceResult.endPos ) -} - -vector function OriginToGround( vector origin ) -{ - vector endOrigin = origin - < 0, 0, 20000 > - TraceResults traceResult = TraceLine( origin, endOrigin, [], TRACE_MASK_NPCWORLDSTATIC, TRACE_COLLISION_GROUP_NONE ) - - return traceResult.endPos -} - -float function GetVerticalClearance( vector origin ) -{ - vector endOrigin = origin + < 0, 0, 20000 > - TraceResults traceResult = TraceLine( origin, endOrigin, [], TRACE_MASK_NPCWORLDSTATIC, TRACE_COLLISION_GROUP_NONE ) - vector endPos = traceResult.endPos - float zDelta = ( endPos.z - origin.z ) - - return zDelta -} - -// --------------------------------------------------------------------- -// Determine if an entity is a valid player spawnpoint -// --------------------------------------------------------------------- -bool function PlayerSpawnpointIsValid( entity ent ) -{ - if ( ent.GetClassName() != "prop_dynamic" ) - return false - if ( ent.GetValueForModelKey() != $"models/humans/pete/mri_male.mdl" ) - return false - - return true -} - -// --------------------------------------------------------------------- -// Make an NPC or the player invincible (true/false) -// (_npc.nut intercepts incoming damage and negates it if the ent is tagged as invincible) -// --------------------------------------------------------------------- -void function MakeInvincible( entity ent ) -{ - Assert( IsValid( ent ), "Tried to make invalid " + ent + " invincible" ) - Assert( ent.IsNPC() || ent.IsPlayer(), "MakeInvincible() can only be called on NPCs and the player" ) - Assert( IsAlive( ent ), "Tried to make dead ent " + ent + " invincible" ) - - ent.SetInvulnerable() -} - -void function ClearInvincible( entity ent ) -{ - Assert( IsValid( ent ), "Tried to clear invalid " + ent + " invincible" ) - - ent.ClearInvulnerable() -} - -bool function IsInvincible( entity ent ) -{ - return ent.IsInvulnerable() -} - -//------------------------------------- -// Teleport an entity (teleporter) to an entity's org and angles (ent) -//-------------------------------------- -void function TeleportToEnt( entity teleporter, entity ent ) -{ - Assert( teleporter != null, "Unable to teleport null entity" ) - Assert( ent != null, "Unable to teleport to a null entity" ) - teleporter.SetOrigin( ent.GetOrigin() ) - teleporter.SetAngles( ent.GetAngles() ) -} - -//----------------------------------------------------------- -// CreateShake() - create and fire an env_shake at a specified origin -// - returns the shake in case you want to parent it -//------------------------------------------------------------ - -entity function CreateShake_internal( vector org, float amplitude, float frequency, float duration, float radius, int spawnFlags ) -{ - entity env_shake = CreateEntity( "env_shake" ) - env_shake.kv.amplitude = amplitude - env_shake.kv.radius = radius - env_shake.kv.duration = duration - env_shake.kv.frequency = frequency - env_shake.kv.spawnflags = spawnFlags - - DispatchSpawn( env_shake ) - - env_shake.SetOrigin( org ) - - EntFireByHandle( env_shake, "StartShake", "", 0, null, null ) - EntFireByHandle( env_shake, "Kill", "", ( duration + 1 ), null, null ) - - return env_shake -} - -entity function CreateShake( vector org, float amplitude = 16, float frequency = 150, float duration = 1.5, float radius = 2048 ) -{ - return CreateShake_internal( org, amplitude, frequency, duration, radius, 0 ); -} - -entity function CreateShakeRumbleOnly( vector org, float amplitude = 16, float frequency = 150, float duration = 1.5, float radius = 2048 ) -{ - return CreateShake_internal( org, amplitude, frequency, duration, radius, SF_SHAKE_RUMBLE_ONLY ); -} - -entity function CreateShakeNoRumble( vector org, float amplitude = 16, float frequency = 150, float duration = 1.5, float radius = 2048 ) -{ - return CreateShake_internal( org, amplitude, frequency, duration, radius, SF_SHAKE_NO_RUMBLE ); -} - -entity function CreateAirShake( vector org, float amplitude = 16, float frequency = 150, float duration = 1.5, float radius = 2048 ) -{ - return CreateShake_internal( org, amplitude, frequency, duration, radius, SF_SHAKE_INAIR ); -} - -entity function CreateAirShakeRumbleOnly( vector org, float amplitude = 16, float frequency = 150, float duration = 1.5, float radius = 2048 ) -{ - return CreateShake_internal( org, amplitude, frequency, duration, radius, (SF_SHAKE_INAIR | SF_SHAKE_RUMBLE_ONLY) ); -} - -entity function CreateAirShakeNoRumble( vector org, float amplitude = 16, float frequency = 150, float duration = 1.5, float radius = 2048 ) -{ - return CreateShake_internal( org, amplitude, frequency, duration, radius, (SF_SHAKE_INAIR | SF_SHAKE_NO_RUMBLE) ); -} - -//------------------------------------- -// CreatePhysExplosion - physExplosion...small, medium or large -//-------------------------------------- -entity function CreatePhysExplosion( vector org, float radius, int magnitude = 1, int flags = 1, bool dealsDamage = true ) -{ - entity env_physexplosion = CreateEntity( "env_physexplosion" ) - env_physexplosion.kv.spawnflags = flags // default 1 = No Damage - Only Force - env_physexplosion.kv.magnitude = magnitude - env_physexplosion.kv.radius = string( radius ) - env_physexplosion.SetOrigin( org ) - env_physexplosion.kv.scriptDamageType = damageTypes.explosive - DispatchSpawn( env_physexplosion ) - - EntFireByHandle( env_physexplosion, "Explode", "", 0, null, null ) - EntFireByHandle( env_physexplosion, "Kill", "", 2, null, null ) -} - -//----------------------------------------------------------- -// CreatePropDynamic( model ) - create a generic prop_dynamic with default properties -//------------------------------------------------------------ -entity function CreatePropDynamic( asset model, vector ornull origin = null, vector ornull angles = null, var solidType = 0, float fadeDist = -1 ) -{ - entity prop_dynamic = CreateEntity( "prop_dynamic" ) - prop_dynamic.SetValueForModelKey( model ) - prop_dynamic.kv.fadedist = fadeDist - prop_dynamic.kv.renderamt = 255 - prop_dynamic.kv.rendercolor = "255 255 255" - prop_dynamic.kv.solid = solidType // 0 = no collision, 2 = bounding box, 6 = use vPhysics, 8 = hitboxes only - if ( origin ) - { - // hack: Setting origin twice. SetOrigin needs to happen before DispatchSpawn, otherwise the prop may not touch triggers - prop_dynamic.SetOrigin( expect vector( origin ) ) - if ( angles ) - prop_dynamic.SetAngles( expect vector( angles ) ) - } - DispatchSpawn( prop_dynamic ) - if ( origin ) - { - // hack: Setting origin twice. SetOrigin needs to happen after DispatchSpawn, otherwise origin is snapped to nearest whole unit - prop_dynamic.SetOrigin( expect vector( origin ) ) - if ( angles ) - prop_dynamic.SetAngles( expect vector( angles ) ) - } - - return prop_dynamic -} - - -//----------------------------------------------------------- -// CreatePropDynamicLightweight( model ) - create a generic prop_dynamic_lightweight with default properties -//------------------------------------------------------------ -entity function CreatePropDynamicLightweight( asset model, vector ornull origin = null, vector ornull angles = null, var solidType = 0, float fadeDist = -1 ) -{ - entity prop_dynamic = CreateEntity( "prop_dynamic_lightweight" ) - prop_dynamic.SetValueForModelKey( model ) - prop_dynamic.kv.fadedist = fadeDist - prop_dynamic.kv.renderamt = 255 - prop_dynamic.kv.rendercolor = "255 255 255" - prop_dynamic.kv.solid = solidType // 0 = no collision, 2 = bounding box, 6 = use vPhysics, 8 = hitboxes only - if ( origin ) - { - // hack: Setting origin twice. SetOrigin needs to happen before DispatchSpawn, otherwise the prop may not touch triggers - prop_dynamic.SetOrigin( expect vector( origin ) ) - if ( angles ) - prop_dynamic.SetAngles( expect vector( angles ) ) - } - DispatchSpawn( prop_dynamic ) - if ( origin ) - { - // hack: Setting origin twice. SetOrigin needs to happen after DispatchSpawn, otherwise origin is snapped to nearest whole unit - prop_dynamic.SetOrigin( expect vector( origin ) ) - if ( angles ) - prop_dynamic.SetAngles( expect vector( angles ) ) - } - - return prop_dynamic -} - - -//----------------------------------------------------------- -// CreatePropScript( model ) - create a generic prop_script with default properties -//------------------------------------------------------------ -entity function CreatePropScript( asset model, vector ornull origin = null, vector ornull angles = null, int solidType = 0, float fadeDist = -1 ) -{ - entity prop_script = CreateEntity( "prop_script" ) - prop_script.SetValueForModelKey( model ) - prop_script.kv.fadedist = fadeDist - prop_script.kv.renderamt = 255 - prop_script.kv.rendercolor = "255 255 255" - prop_script.kv.solid = solidType // 0 = no collision, 2 = bounding box, 6 = use vPhysics, 8 = hitboxes only - if ( origin ) - { - // hack: Setting origin twice. SetOrigin needs to happen before DispatchSpawn, otherwise the prop may not touch triggers - prop_script.SetOrigin( expect vector( origin ) ) - if ( angles ) - prop_script.SetAngles( expect vector( angles ) ) - } - DispatchSpawn( prop_script ) - if ( origin ) - { - // hack: Setting origin twice. SetOrigin needs to happen after DispatchSpawn, otherwise origin is snapped to nearest whole unit - prop_script.SetOrigin( expect vector( origin ) ) - if ( angles ) - prop_script.SetAngles( expect vector( angles ) ) - } - - return prop_script -} - - - -//----------------------------------------------------------- -// CreatePropPhysics( model ) - create a generic prop_physics with default properties -//------------------------------------------------------------ -entity function CreatePropPhysics( asset model, vector origin, vector angles ) -{ - entity prop_physics = CreateEntity( "prop_physics" ) - prop_physics.SetValueForModelKey( model ) - prop_physics.kv.spawnflags = 0 - prop_physics.kv.fadedist = -1 - prop_physics.kv.physdamagescale = 0.1 - prop_physics.kv.inertiaScale = 1.0 - prop_physics.kv.renderamt = 255 - prop_physics.kv.rendercolor = "255 255 255" - SetTeam( prop_physics, TEAM_BOTH ) // need to have a team other then 0 or it won't take impact damage - - prop_physics.SetOrigin( origin ) - prop_physics.SetAngles( angles ) - DispatchSpawn( prop_physics ) - - return prop_physics -} - -//----------------------------------------------------------- -// SpawnBullseye() - creates a npc_bullseye and attaches it to an entity -//------------------------------------------------------------ -entity function SpawnBullseye( int team, entity ent = null ) -{ - entity bullseye = CreateEntity( "npc_bullseye" ) - bullseye.SetScriptName( UniqueString( "bullseye" ) ) - bullseye.kv.rendercolor = "255 255 255" - bullseye.kv.renderamt = 0 - bullseye.kv.health = 9999 - bullseye.kv.max_health = -1 - bullseye.kv.spawnflags = 516 - bullseye.kv.FieldOfView = 0.5 - bullseye.kv.FieldOfViewAlert = 0.2 - bullseye.kv.AccuracyMultiplier = 1.0 - bullseye.kv.physdamagescale = 1.0 - bullseye.kv.WeaponProficiency = eWeaponProficiency.VERYGOOD - bullseye.kv.minangle = "360" - DispatchSpawn( bullseye ) - - SetTeam( bullseye, team ) - - if ( ent ) - { - vector bounds = ent.GetBoundingMaxs() - bullseye.SetOrigin( ent.GetOrigin() + < 0, 0, bounds.z * 0.5 > ) - bullseye.SetParent( ent ) - } - - return bullseye -} - -void function CenterPrint( ... ) -{ - string msg = "" - for ( int i = 0; i < vargc; i++ ) - msg = ( msg + " " + string( vargv[ i ] ) ) - - int words = expect int( vargc ) - if ( words < 1 ) - words = 1 - - float delay = GraphCapped( float( words ), 2.0, 8.0, 2.1, 3.5 ) - - entity ent = CreateGameText( msg, -1, 0.5, 10, "255 255 255", 0.25, 0.25, delay ) - EntFireByHandle( ent, "Display", "", 0, null, null ) - - thread DestroyCenterPrint( ent, delay ) -} - -void function DestroyCenterPrint( entity ent, float delay ) -{ - wait( delay ) - ent.Destroy() -} - -bool function IsValidPlayer( entity player ) -{ - if ( !IsValid( player ) ) - return false - - if ( !player.IsPlayer() ) - return false - - if ( IsDisconnected( player ) ) - return false - - return true -} - -bool function IsDisconnected( entity player ) -{ - return player.p.isDisconnected -} - -/****************************************************************************************************\ -/* -|* PLAY FX -\* -\****************************************************************************************************/ - -entity function PlayFX( asset effectName, vector org, vector ornull optionalAng = null, vector ornull overrideAngle = null ) -{ - return __CreateFxInternal( effectName, null, "", org, optionalAng, C_PLAYFX_SINGLE, null, -1, null, overrideAngle ) -} - -entity function PlayFXWithControlPoint( asset effectName, vector org, entity cpoint1, int visibilityFlagOverride = -1, entity visibilityFlagEntOverride = null, vector ornull overrideAngle = null, int _type = C_PLAYFX_SINGLE ) -{ - return __CreateFxInternal( effectName, null, "", org, null, _type, cpoint1, visibilityFlagOverride, visibilityFlagEntOverride, overrideAngle) -} - -entity function PlayFXOnEntityWithControlPoint( asset effectName, entity ent, entity cpoint1, int visibilityFlagOverride = -1, entity visibilityFlagEntOverride = null, vector ornull overrideAngle = null, int _type = C_PLAYFX_SINGLE ) -{ - return __CreateFxInternal( effectName, ent, "", null, null, _type, cpoint1, visibilityFlagOverride, visibilityFlagEntOverride, overrideAngle) -} - -entity function PlayFXOnEntity( asset effectName, entity ent, string optionalTag = "", vector ornull optionalTranslation = null, vector ornull optionalRotation = null, int visibilityFlagOverride = -1, entity visibilityFlagEntOverride = null, vector ornull overrideAngle = null ) -{ - return __CreateFxInternal( effectName, ent, optionalTag, optionalTranslation, optionalRotation, C_PLAYFX_SINGLE, null, visibilityFlagOverride, visibilityFlagEntOverride, overrideAngle ) -} - -entity function PlayFXForPlayer( asset effectName, entity player, vector ornull org, vector ornull optionalAng = null ) -{ - return __CreateFxInternal( effectName, null, "", org, optionalAng, C_PLAYFX_SINGLE, null, ENTITY_VISIBLE_TO_OWNER, player ) -} - -entity function PlayFXOnEntityForEveryoneExceptPlayer( asset effectName, entity ent, entity player, string optionalTag = "", vector ornull optionalTranslation = null, vector ornull optionalRotation = null ) -{ - return __CreateFxInternal( effectName, ent, optionalTag, optionalTranslation, optionalRotation, C_PLAYFX_SINGLE, null, (ENTITY_VISIBLE_TO_FRIENDLY | ENTITY_VISIBLE_TO_ENEMY), player ) -} - -entity function PlayFXForEveryoneExceptPlayer( asset effectName, entity player, vector ornull org, vector ornull optionalAng = null ) -{ - return __CreateFxInternal( effectName, null, "", org, optionalAng, C_PLAYFX_SINGLE, null, (ENTITY_VISIBLE_TO_FRIENDLY | ENTITY_VISIBLE_TO_ENEMY), player ) -} - -void function PlayFXOnTitanPlayerForTime( asset effectName, entity titan, string attachment, float duration ) -{ - titan.EndSignal( "OnDeath" ) - titan.EndSignal( "DisembarkingTitan" ) - titan.EndSignal( "TitanEjectionStarted" ) - - entity fx = PlayFXOnEntityForEveryoneExceptPlayer( effectName, titan, titan, attachment ) - - OnThreadEnd( - function() : ( fx ) - { - if ( IsValid(fx) ) - { - fx.Destroy() - } - } - ) - - wait duration -} - -entity function ClientStylePlayFXOnEntity( asset effectName, entity ent, string tag, float duration = 2.0 ) -{ - string name = ent.GetScriptName() - ent.SetScriptName( UniqueString() ) // hack because you can only specify control points by name - // hack this is also not quite right because we can't specify the attachment type on the server... should be trivial to add in code: - // change DEFINE_FIELD( m_parentAttachmentType, FIELD_INTEGER ), to DEFINE_KEYFIELD( m_parentAttachmentType, FIELD_INTEGER, "attachmentType" ), - entity result = __CreateFxInternal( effectName, ent, tag, null, null, C_PLAYFX_SINGLE, ent, (ENTITY_VISIBLE_TO_FRIENDLY | ENTITY_VISIBLE_TO_ENEMY), ent ) - EntFireByHandle( result, "Kill", "", duration, null, null ) - ent.SetScriptName( name ) - - return result -} - -entity function PlayLoopFX( asset effectName, vector ornull org, vector ornull optionalAng = null ) -{ - return __CreateFxInternal( effectName, null, "", org, optionalAng, C_PLAYFX_LOOP ) -} - -entity function PlayLoopFXOnEntity( asset effectName, entity ent, string optionalTag = "", vector ornull optionalTranslation = null, vector ornull optionalRotation = null, int visibilityFlagOverride = -1, entity visibilityFlagEntOverride = null ) -{ - return __CreateFxInternal( effectName, ent, optionalTag, optionalTranslation, optionalRotation, C_PLAYFX_LOOP, null, visibilityFlagOverride, visibilityFlagEntOverride ) -} - -entity function __CreateFxInternal( asset effectName, entity ent, string optionalTag = "", vector ornull optionalTranslation = <0,0,0>, vector ornull optionalRotation = <0,0,0>, - int _type = C_PLAYFX_SINGLE, entity cpointEnt1 = null, int visibilityFlagOverride = -1, entity visibilityFlagEntOverride = null, vector ornull overrideAngle = null ) -{ - entity fx = CreateEntity( "info_particle_system" ) - fx.SetValueForEffectNameKey( effectName ) - if( visibilityFlagOverride != -1 ) - fx.kv.VisibilityFlags = visibilityFlagOverride - else - fx.kv.VisibilityFlags = ENTITY_VISIBLE_TO_EVERYONE - fx.kv.start_active = 1 - fx.e.fxType = _type - - if ( _type == C_PLAYFX_SINGLE ) - fx.DoNotCreateFXOnRestore(); - - vector coreOrg - vector coreAng - - //are we attaching to an ent? - if ( ent ) - { - //are we attaching to a tag on an ent - if ( optionalTag != "" ) - { - int attachID = ent.LookupAttachment( optionalTag ) - coreOrg = ent.GetAttachmentOrigin( attachID ) - coreAng = ent.GetAttachmentAngles( attachID ) - } - else - { - coreOrg = ent.GetOrigin() - coreAng = ent.GetAngles() - } - - fx.Code_SetTeam( ent.GetTeam() ); - } - else //if not we're just playing in space - { - optionalTag = "" - coreOrg = < 0, 0, 0 > - coreAng = < 0, 0, 0 > - } - - if ( optionalTranslation ) - { - expect vector( optionalTranslation ) - if ( ent ) - coreOrg = PositionOffsetFromEnt( ent, optionalTranslation.x, optionalTranslation.y, optionalTranslation.z ) - else - coreOrg = coreOrg + optionalTranslation - } - - coreOrg = ClampToWorldspace( coreOrg ) - fx.SetOrigin( coreOrg ) - - if ( overrideAngle ) - { - expect vector( overrideAngle ) - fx.SetAngles( overrideAngle ) - } - else if ( optionalRotation ) - { - expect vector( optionalRotation ) - fx.SetAngles( coreAng + optionalRotation ) - } - else - { - fx.SetAngles( coreAng ) - } - - if ( ent ) - { - if ( !ent.IsMarkedForDeletion() ) // TODO: This is a hack for shipping. The real solution is to spawn the FX before deleting the parent entity. - { - fx.SetParent( ent, optionalTag, true ) - } - } - - if ( visibilityFlagEntOverride != null ) - fx.SetOwner( visibilityFlagEntOverride ) - - if ( cpointEnt1 ) - fx.kv.cpoint1 = cpointEnt1.GetTargetName() - - DispatchSpawn( fx ) - thread __DeleteFxInternal( fx ) - - //SetTargetName( fx, "FX_" + effectName ) - return fx -} - -void function __DeleteFxInternal( entity fx ) -{ - //if it loops or is multiple then don't delete internally - if ( fx.e.fxType == C_PLAYFX_MULTIPLE ) - return - - if ( fx.e.fxType == C_PLAYFX_LOOP ) - return - - wait 30 //no way to know when an effect is over - if ( !IsValid( fx ) ) - return - - fx.ClearParent() - fx.Destroy() -} - -void function StartFX( entity fx ) -{ - Assert( fx.e.fxType == C_PLAYFX_LOOP, "Tried to use StartFX() on effect that is not LOOPING" ) - EntFireByHandle( fx, "Start", "", 0, null, null ) -} - -void function StopFX( entity fx ) -{ - Assert( fx.e.fxType == C_PLAYFX_LOOP, "Tried to use StopFX() on effect that is not LOOPING" ) - EntFireByHandle( fx, "Stop", "", 0, null, null ) -} - -void function ReplayFX( entity fx ) -{ - Assert( fx.e.fxType == C_PLAYFX_MULTIPLE, "Tried to use ReplayFX() on effect that is not MULTIPLE" ) - //thread it because there is a WaitFrame() inside the function - thread __ReplayFXInternal( fx ) -} - -void function __ReplayFXInternal( entity fx ) -{ - //for non-looping fx, we must stop first before we can fire again - EntFireByHandle( fx, "Stop", "", 0, null, null ) - //we can't start in the same frame, WaitFrame() skips 1 false - //it should be noted that "WaitFrame()" doesn't work with a timescale above 1 - WaitFrame() - //may have died since the last frame - if ( IsValid( fx ) ) - EntFireByHandle( fx, "Start", "", 0, null, null ) -} - -void function Entity_StopFXArray( entity ent ) -{ - foreach( fx in ent.e.fxArray ) - { - if ( IsValid( fx ) ) - { - StopFX( fx ) - fx.Destroy() - } - } -} - -/****************************************************************************************************\ -|* end play fx -\****************************************************************************************************/ - - -table function GetDamageTableFromInfo( var damageInfo ) -{ - table Table = {} - Table.damageSourceId <- DamageInfo_GetDamageSourceIdentifier( damageInfo ) - Table.origin <- DamageInfo_GetDamagePosition( damageInfo ) - Table.force <- DamageInfo_GetDamageForce( damageInfo ) - Table.scriptType <- DamageInfo_GetCustomDamageType( damageInfo ) - - return Table -} - -bool function EntityInSolid( entity ent, entity ignoreEnt = null, int buffer = 0 ) //TODO: This function returns true for a player standing inside a friendly grunt. It also returns true if you are right up against a ceiling.Needs fixing for next game -{ - Assert( IsValid( ent ) ) - int solidMask - vector mins - vector maxs - int collisionGroup - array<entity> ignoreEnts = [] - - ignoreEnts.append( ent ) - - if ( IsValid( ignoreEnt ) ) - { - ignoreEnts.append( ignoreEnt ) - } - - if ( ent.IsTitan() ) - solidMask = TRACE_MASK_TITANSOLID - else if ( ent.IsPlayer() ) - solidMask = TRACE_MASK_PLAYERSOLID - else - solidMask = TRACE_MASK_NPCSOLID - - if ( ent.IsPlayer() ) - { - mins = ent.GetPlayerMins() - maxs = ent.GetPlayerMaxs() - collisionGroup = TRACE_COLLISION_GROUP_PLAYER - } - else - { - Assert( ent.IsNPC() ) - mins = ent.GetBoundingMins() - maxs = ent.GetBoundingMaxs() - collisionGroup = TRACE_COLLISION_GROUP_NONE - } - - if ( buffer > 0 ) - { - mins.x -= float( buffer ) - mins.y -= float( buffer ) - maxs.x += float( buffer ) - maxs.y += float( buffer ) - } - - // if we got into solid, teleport back to safe place - vector currentOrigin = ent.GetOrigin() - TraceResults result = TraceHull( currentOrigin, currentOrigin + < 0, 0, 1 >, mins, maxs, ignoreEnts, solidMask, collisionGroup ) - //PrintTable( result ) - //DrawArrow( result.endPos, Vector(0,0,0), 5, 150 ) - if ( result.startSolid ) - return true - - return result.fraction < 1.0 // TODO: Probably not needed according to Jiesang. Fix after ship. -} - -bool function EntityInSpecifiedEnt( entity ent, entity specifiedEnt, int buffer = 0 ) -{ - Assert( IsValid( ent ) ) - Assert( IsValid( specifiedEnt ) ) - - int solidMask - vector mins - vector maxs - int collisionGroup - - if ( ent.IsTitan() ) - solidMask = TRACE_MASK_TITANSOLID - else if ( ent.IsPlayer() ) - solidMask = TRACE_MASK_PLAYERSOLID - else - solidMask = TRACE_MASK_NPCSOLID - - if ( ent.IsPlayer() ) - { - mins = ent.GetPlayerMins() - maxs = ent.GetPlayerMaxs() - collisionGroup = TRACE_COLLISION_GROUP_PLAYER - } - else - { - Assert( ent.IsNPC() ) - mins = ent.GetBoundingMins() - maxs = ent.GetBoundingMaxs() - collisionGroup = TRACE_COLLISION_GROUP_NONE - } - - if ( buffer > 0 ) - { - mins.x -= float( buffer ) - mins.y -= float( buffer ) - maxs.x += float( buffer ) - maxs.y += float( buffer ) - } - - // if we got into solid, teleport back to safe place - vector currentOrigin = ent.GetOrigin() - TraceResults result = TraceHull( currentOrigin, currentOrigin + < 0, 0, 1 >, mins, maxs, null, solidMask, collisionGroup ) - //PrintTable( result ) - //DrawArrow( result.endPos, Vector(0,0,0), 5, 150 ) - if ( result.startSolid == false ) - return false - - return result.hitEnt == specifiedEnt -} - -void function KillFromInfo( entity ent, var damageInfo ) -{ - entity attacker = DamageInfo_GetAttacker( damageInfo ) - entity weapon = DamageInfo_GetWeapon( damageInfo ) - //float amount = DamageInfo_GetDamage( damageInfo ) - - // JFS: if the player became invalid, the attacker becomes the projectile which is bad - if ( attacker.IsProjectile() ) - attacker = svGlobal.worldspawn - - if ( !weapon ) - weapon = attacker - - table Table = GetDamageTableFromInfo( damageInfo ) - Table.forceKill <- true - - ent.TakeDamage( 9999, attacker, weapon, Table ) -} - - -entity function GetPlayerTitanInMap( entity player ) -{ - // temporarily flipped - entity petTitan = player.GetPetTitan() - if ( IsValid( petTitan ) && IsAlive( petTitan ) ) - return petTitan - - // first try to return the player's actual titan - if ( player.IsTitan() ) - return player - - return null -} - - -entity function GetPlayerTitanFromSouls( entity player ) -{ - // returns the first owned titan found - array<entity> souls = GetTitanSoulArray() - foreach ( soul in souls ) - { - if ( !IsValid( soul ) ) - continue - - if ( soul.GetBossPlayer() != player ) - continue - - if ( !IsAlive( soul.GetTitan() ) ) - continue - - return soul.GetTitan() - } - - return null -} - -void function DisableTitanShield( entity titan ) -{ - entity soul = titan.GetTitanSoul() - - soul.SetShieldHealth( 0 ) - soul.SetShieldHealthMax( 0 ) -} - -void function DisableShield( entity ent ) -{ - entity soul = ent.GetTitanSoul() - - if ( soul ) - { - DisableTitanShield( ent ) - return - } - - ent.SetShieldHealth( 0 ) - ent.SetShieldHealthMax( 0 ) -} - -void function SetVelocityTowardsEntity( entity entToMove, entity targetEnt, float speed ) -{ - Assert( speed > 0 ) - Assert( IsValid( entToMove ) ) - Assert( IsValid( targetEnt ) ) - - vector direction = ( targetEnt.GetWorldSpaceCenter() - entToMove.GetOrigin() ) - direction = Normalize( direction ) * speed - entToMove.SetVelocity( direction ) -} - -void function SetVelocityTowardsEntityTag( entity entToMove, entity targetEnt, string targetTag, float speed ) -{ - Assert( speed > 0 ) - Assert( IsValid( entToMove ) ) - Assert( IsValid( targetEnt ) ) - - int attachID = targetEnt.LookupAttachment( targetTag ) - vector attachOrigin = targetEnt.GetAttachmentOrigin( attachID ) - - vector direction = ( attachOrigin - entToMove.GetOrigin() ) - direction = Normalize( direction ) * speed - entToMove.SetVelocity( direction ) -} - -void function EntityDemigod_TryAdjustDamageInfo( entity ent, var damageInfo ) -{ - float dmg = DamageInfo_GetDamage( damageInfo ) - if ( dmg <= 0 ) - return - - if ( ent.IsTitan() && !GetDoomedState( ent ) ) //Allow demigod titans to go into doomed - return - - int bottomLimit = 5 - if ( ent.GetHealth() <= bottomLimit ) - ent.SetHealth( bottomLimit + 1 ) //Set it up so that you at least take 1 damage, for hit indicators etc to trigger - - int health = ent.GetHealth() - - if ( health - dmg <= bottomLimit ) - { - int newdmg = health - bottomLimit - DamageInfo_SetDamage( damageInfo, newdmg ) - //printt( "setting damage to ", newdmg ) - } -} - -void function DebugDamageInfo( entity ent, var damageInfo ) -{ - printt( "damage to " + ent + ": " + DamageInfo_GetDamage( damageInfo ) ) - int damageType = DamageInfo_GetCustomDamageType( damageInfo ) - printt( "explosive: " + ( damageType & DF_EXPLOSION ) ) - printt( "bullet: " + ( damageType & DF_BULLET ) ) - printt( "gib: " + ( damageType & DF_GIB ) ) - - vector dampos = DamageInfo_GetDamagePosition( damageInfo ) - vector org = DamageInfo_GetInflictor( damageInfo ).GetOrigin() - DebugDrawLine( dampos, org, 255, 0, 0, true, 10.0 ) - DebugDrawLine( org, ent.GetOrigin(), 255, 255, 0, true, 10.0 ) -} - -vector function RandomVecInDome( vector dir ) -{ - vector angles = VectorToAngles( dir ) - vector forward = AnglesToForward( angles ) - vector right = AnglesToRight( angles ) - vector up = AnglesToUp( angles ) - - float offsetRight = RandomFloatRange( -1, 1 ) - float offsetUp = RandomFloatRange( -1, 1 ) - float offsetForward = RandomFloat( 1.0 ) - - vector endPos = < 0, 0, 0 > - endPos += forward * offsetForward - endPos += up * offsetUp - endPos += right * offsetRight - endPos.Norm() - - return endPos -} - -float function GetAnimEventTime( asset modelname, string anim, string event ) -{ - entity dummy = CreatePropDynamic( modelname ) - dummy.Hide() - - float duration = dummy.GetSequenceDuration( anim ) - float frac = dummy.GetScriptedAnimEventCycleFrac( anim, event ) - - dummy.Destroy() - - //this might cause some issues in R2 - but we'll fix them as we go - it's important this doesn't silently fail - Assert( frac > 0.0, "event: " + event + " doesn't exist in animation: " + anim ) - Assert( frac < 1.0, "event: " + event + " doesn't exist in animation: " + anim ) - - return duration * frac -} - -void function SetDeathFuncName( entity npc, string functionNameString ) -{ - Assert( npc.kv.deathScriptFuncName == "", "deathScriptFuncName was already set" ) - npc.kv.deathScriptFuncName = functionNameString -} - -void function ClearDeathFuncName( entity npc ) -{ - npc.kv.deathScriptFuncName = "" -} - -/*function PushSunLightAngles( x, y, z ) -{ - entity clight = GetEnt( "env_cascade_light" ) - Assert( clight ) - - clight.PushAngles( x, y, z ) -} - -function PopSunLightAngles() -{ - entity clight = GetEnt( "env_cascade_light" ) - Assert( clight ) - - clight.PopAngles() -}*/ - -entity function GetPilotAntiPersonnelWeapon( entity player ) -{ - array<entity> weaponsArray = player.GetMainWeapons() - foreach( weapon in weaponsArray ) - { - int weaponType = weapon.GetWeaponType() - if ( weaponType == WT_SIDEARM || weaponType == WT_ANTITITAN ) - continue; - - return weapon - } - - return null -} - -entity function GetPilotSideArmWeapon( entity player ) -{ - array<entity> weaponsArray = player.GetMainWeapons() - foreach( weapon in weaponsArray ) - { - if ( weapon.GetWeaponType() == WT_SIDEARM ) - return weapon - } - - return null -} - -entity function GetPilotAntiTitanWeapon( entity player ) -{ - array<entity> weaponsArray = player.GetMainWeapons() - foreach( weapon in weaponsArray ) - { - if ( weapon.GetWeaponType() == WT_ANTITITAN ) - return weapon - } - - return null -} - -bool function PilotHasSniperWeapon( entity player ) -{ - array<entity> weaponsArray = player.GetMainWeapons() - foreach ( weapon in weaponsArray ) - { - if ( IsValid( weapon ) && weapon.GetWeaponInfoFileKeyField( "is_sniper" ) == 1 ) - return true - } - - return false -} - -bool function PilotActiveWeaponIsSniper( entity player ) -{ - entity weapon = player.GetActiveWeapon() - - if ( IsValid( weapon ) && weapon.GetWeaponInfoFileKeyField( "is_sniper" ) == 1 ) - return true - - return false -} - -void function ScreenFadeToColor( entity player, float r, float g, float b, float a, float fadeTime = 1.7, float holdTime = 0.0 ) -{ - Assert( IsValid( player ) ) - - ScreenFade( player, r, g, b, a, fadeTime, holdTime, FFADE_OUT | FFADE_PURGE ) -} - - -void function ScreenFadeFromColor( entity player, float r, float g, float b, float a, float fadeTime = 2.0, float holdTime = 2.0 ) -{ - Assert( IsValid( player ) ) - - ScreenFade( player, r, g, b, a, fadeTime, holdTime, FFADE_IN | FFADE_PURGE ) -} - -void function ScreenFadeToBlack( entity player, float fadeTime, float holdTime ) -{ - Assert( IsValid( player ) ) - - ScreenFade( player, 0, 0, 1, 255, fadeTime, holdTime, FFADE_OUT | FFADE_PURGE ) -} - -void function ScreenFadeFromBlack( entity player, float fadeTime = 2.0, float holdTime = 2.0 ) -{ - Assert( IsValid( player ) ) - - ScreenFade( player, 0, 1, 0, 255, fadeTime, holdTime, FFADE_IN | FFADE_PURGE ) -} - -void function ScreenFadeToBlackForever( entity player, float fadeTime = 1.7 ) -{ - Assert( IsValid( player ) ) - - ScreenFade( player, 0, 0, 1, 255, fadeTime, 0, FFADE_OUT | FFADE_STAYOUT ) -} - -/******************************************************* -/ Server Effects -/ -/ CreateServerEffect_Friendly( effectName, team ) -/ CreateServerEffect_Enemy( effectName, team ) -/ CreateServerEffect_Owner( effectName, owner ) -/ SetServerEffectControlPoint( effectEnt, controlPoint, vecValue ) -/ StartServerEffect( effectEnt ) -/ StartServerEffectInWorld( effectEnt, origin, angles ) -/ StartServerEffectOnEntity( effectEnt, ent, tag = null ) -/ -*******************************************************/ - -// NOTE: this does not play the effect, use StartEffectOnEntity -entity function CreateServerEffect_Friendly( asset effectName, int team ) -{ - entity friendlyEffect = _CreateServerEffect( effectName, 2 ) // ENTITY_VISIBLE_TO_FRIENDLY - friendlyEffect.kv.TeamNum = team - friendlyEffect.kv.teamnumber = team - - return friendlyEffect -} - -// NOTE: this does not play the effect, use StartEffectOnEntity -entity function CreateServerEffect_Enemy( asset effectName, int team ) -{ - entity enemyEffect = _CreateServerEffect( effectName, 4 ) // ENTITY_VISIBLE_TO_ENEMY - enemyEffect.kv.TeamNum = team - enemyEffect.kv.teamnumber = team - - return enemyEffect -} - -// NOTE: this does not play the effect, use StartEffectOnEntity -entity function CreateServerEffect_Owner( asset effectName, entity owner ) -{ - Assert( IsValid( owner ) ) - - entity ownerEffect = _CreateServerEffect( effectName, 1 ) // ENTITY_VISIBLE_TO_OWNER - ownerEffect.kv.TeamNum = owner.GetTeam() - ownerEffect.SetOwner( owner ) - - return ownerEffect -} - -entity function _CreateServerEffect( asset effectName, int visFlags ) -{ - entity serverEffect = CreateEntity( "info_particle_system" ) - serverEffect.SetOrigin( <0, 0, 0> ) - serverEffect.SetAngles( <0, 0, 0> ) - serverEffect.SetValueForEffectNameKey( effectName ) - serverEffect.kv.start_active = 1 - serverEffect.kv.VisibilityFlags = visFlags - - thread _ServerEffectCleanup( serverEffect ) - return serverEffect -} - -entity function SetServerEffectControlPoint( entity effectEnt, int controlPoint, vector vecValue ) // for now, only support static -{ - entity helper = CreateEntity( "info_placement_helper" ) - helper.SetOrigin( vecValue ) - effectEnt.SetControlPointEnt( controlPoint, helper ) - effectEnt.e.fxControlPoints.append( helper ) - - return helper -} - -void function StartServerEffect( entity effectEnt ) -{ - DispatchSpawn( effectEnt ) -} - -void function StartServerEffectInWorld( entity effectEnt, vector origin, vector angles ) -{ - effectEnt.SetOrigin( origin ) - effectEnt.SetAngles( angles ) - DispatchSpawn( effectEnt ) -} - -void function StartServerEffectOnEntity( entity effectEnt, entity ent, string tag = "" ) -{ - Assert( IsValid( effectEnt ) ) - Assert( IsValid( ent ) ) - - if ( tag != "" ) - { - int attachID = ent.LookupAttachment( tag ) - vector origin = ent.GetAttachmentOrigin( attachID ) - vector angles = ent.GetAttachmentAngles( attachID ) - - origin = ClampToWorldspace( origin ) - effectEnt.SetOrigin( origin ) - effectEnt.SetAngles( angles ) - effectEnt.SetParent( ent, tag, true ) - } - else - { - effectEnt.SetParent( ent ) - } - - DispatchSpawn( effectEnt ) -} - -void function _ServerEffectCleanup( entity effectEnt ) -{ - effectEnt.WaitSignal( "OnDestroy" ) - - foreach ( entity controlPoint in effectEnt.e.fxControlPoints ) - { - controlPoint.Destroy() - } -} - -float function GetYaw( vector org1, vector org2 ) -{ - vector vec = org2 - org1 - vector angles = VectorToAngles( vec ) - return angles.y -} - -void function HideName( entity ent ) -{ - ent.SetNameVisibleToFriendly( false ) - ent.SetNameVisibleToEnemy( false ) - ent.SetNameVisibleToNeutral( false ) - ent.SetNameVisibleToOwner( false ) -} - -void function ShowName( entity ent ) -{ - ent.SetNameVisibleToFriendly( true ) - ent.SetNameVisibleToEnemy( true ) - ent.SetNameVisibleToNeutral( true ) - ent.SetNameVisibleToOwner( true ) -} - -void function ShowNameToAllExceptOwner( entity ent ) -{ - ent.SetNameVisibleToFriendly( true ) - ent.SetNameVisibleToEnemy( true ) - ent.SetNameVisibleToNeutral( true ) - ent.SetNameVisibleToOwner( false ) -} - -void function EmitSoundOnEntityToTeamExceptPlayer( entity ent, string sound, int team, entity excludePlayer ) -{ - array<entity> players = GetPlayerArrayOfTeam( team ) - - foreach ( player in players ) - { - if ( player == excludePlayer ) - continue - - EmitSoundOnEntityOnlyToPlayer( ent, player, sound ) - } -} - -#if DEV -// DEV function to toggle player view between the skybox and the real world. -void function ToggleSkyboxView( float scale = 0.001 ) -{ - entity player = GetEntByIndex( 1 ) - - entity skyboxCamLevel = GetEnt( "skybox_cam_level" ) - - Assert( IsValid( skyboxCamLevel ), "Could not find a sky_camera entity named \"skybox_cam_level\" in this map." ) - - vector skyOrigin = skyboxCamLevel.GetOrigin() - - if ( !file.isSkyboxView ) - { - if ( !player.IsNoclipping() ) - { - ClientCommand( player, "noclip" ) - wait( 0.25 ) - } - - ClientCommand( player, "sv_noclipspeed 0.1" ) - file.isSkyboxView = true - vector offset = player.GetOrigin() - offset *= scale - - player.SetOrigin( skyOrigin + offset - < 0.0, 0.0, 60.0 - (60.0 * scale) > ) - } - else - { - ClientCommand( player, "sv_noclipspeed 5" ) - file.isSkyboxView = false - vector offset = player.GetOrigin() - skyOrigin + < 0.0, 0.0, 60.0 - (60.0 * scale) > - offset *= 1.0 / scale - - offset = ClampToWorldspace( offset ) - - player.SetOrigin( offset ) - } -} - -void function DamageRange( float value, float headShotMultiplier, int playerHealth = 200 ) -{ - printt( "Damage Range: ", value, headShotMultiplier ) - - float bodyShot = value - float headShot = value * headShotMultiplier - - int maxHeadshots = 0 - - int simHealth = playerHealth - while ( simHealth > 0 ) - { - simHealth = (simHealth.tofloat() - headShot).tointeger() - maxHeadshots++ - } - - printt( "HeadShots: BodyShots: Total:" ) - - simHealth = playerHealth - int numHeadshots = 0 - while ( numHeadshots < maxHeadshots ) - { - simHealth = playerHealth - for ( int hsIdx = 0; hsIdx < numHeadshots; hsIdx++ ) - { - simHealth = (simHealth.tofloat() - headShot).tointeger() - } - - int numBodyShots = 0 - while ( simHealth > 0 ) - { - simHealth = (simHealth.tofloat() - bodyShot).tointeger() - numBodyShots++ - } - printt( format( "%i %i %i", numHeadshots, numBodyShots, numHeadshots + numBodyShots ) ) - numHeadshots++ - } - - printt( format( "%i %i %i", numHeadshots, 0, numHeadshots ) ) -} - -#endif // DEV - -void function MuteAll( entity player, int fadeOutTime = 2 ) -{ - //DumpStack(2) - Assert( player.IsPlayer() ) - - Assert( fadeOutTime >= 1 && fadeOutTime <= 4 , "Only have 4 kinds of fadeout to play, time must be in the range [1,4]" ) - - string fadeoutSoundString - - switch( fadeOutTime ) - { - case 1: - fadeoutSoundString = "1_second_fadeout" - break - - case 2: - fadeoutSoundString = "2_second_fadeout" - break - - case 3: - fadeoutSoundString = "3_second_fadeout" - break - - case 4: - fadeoutSoundString = "4_second_fadeout" - break - - default: - unreachable - - } - - printt( "Apply " + fadeoutSoundString + " to player: " + player ) - - EmitSoundOnEntityOnlyToPlayer( player, player, fadeoutSoundString ) -} - -//Mutes all except halftime sounds and dialogue -void function MuteHalfTime( entity player ) -{ - Assert( player.IsPlayer() ) - printt( "Apply HalfTime_fadeout to player: " + player ) - EmitSoundOnEntityOnlyToPlayer( player, player, "HalfTime_fadeout" ) -} - -void function UnMuteAll( entity player ) -{ - //DumpStack(2) - Assert( player.IsPlayer() ) - - //Just stop all the possible fadeout sounds. - printt( "Stopping all fadeout for player: " + player ) - StopSoundOnEntity( player, "1_second_fadeout" ) - StopSoundOnEntity( player, "2_second_fadeout" ) - StopSoundOnEntity( player, "3_second_fadeout" ) - StopSoundOnEntity( player, "4_second_fadeout" ) - StopSoundOnEntity( player, "HalfTime_fadeout" ) -} - -void function AllPlayersMuteAll( int time = MUTEALLFADEIN ) -{ - array<entity> players = GetPlayerArray() - - foreach ( player in players ) - MuteAll( player, time ) -} - -void function AllPlayersUnMuteAll() -{ - array<entity> players = GetPlayerArray() - - foreach ( player in players ) - UnMuteAll( player ) -} - -void function TakeAmmoFromPlayer( entity player ) -{ - array<entity> mainWeapons = player.GetMainWeapons() - array<entity> offhandWeapons = player.GetOffhandWeapons() - - foreach ( weapon in mainWeapons ) - { - weapon.SetWeaponPrimaryAmmoCount( 0 ) - - if ( weapon.GetWeaponPrimaryClipCountMax() > 0 ) - weapon.SetWeaponPrimaryClipCount( 0 ) - } - - foreach ( weapon in offhandWeapons ) - { - weapon.SetWeaponPrimaryAmmoCount( 0 ) - - if ( weapon.GetWeaponPrimaryClipCountMax() > 0 ) - weapon.SetWeaponPrimaryClipCount( 0 ) - } -} - - -bool function NearFlagSpawnPoint( vector dropPoint ) -{ - if ( "flagSpawnPoint" in level && IsValid( level.flagSpawnPoint ) ) - { - vector fspOrigin = expect entity( level.flagSpawnPoint ).GetOrigin() - if ( Distance( fspOrigin, dropPoint ) < SAFE_TITANFALL_DISTANCE_CTF ) - return true - } - - if ( "flagReturnPoint" in level && IsValid( level.flagReturnPoint ) ) - { - vector fspOrigin = expect entity( level.flagReturnPoint ).GetOrigin() - if ( Distance( fspOrigin, dropPoint ) < SAFE_TITANFALL_DISTANCE_CTF ) - return true - } - - if ( "flagSpawnPoints" in level ) - { - foreach ( flagSpawnPoint in svGlobal.flagSpawnPoints ) - { - vector fspOrigin = flagSpawnPoint.GetOrigin() - if ( Distance( fspOrigin, dropPoint ) < SAFE_TITANFALL_DISTANCE_CTF ) - return true - } - } - - return false -} - -bool function HasCinematicFlag( entity player, int flag ) -{ - Assert( player.IsPlayer() ) - Assert( IsValid( player ) ) - return ( player.GetCinematicEventFlags() & flag ) != 0 -} - -void function AddCinematicFlag( entity player, int flag ) -{ - Assert( player.IsPlayer() ) - Assert( IsValid( player ) ) - player.SetCinematicEventFlags( player.GetCinematicEventFlags() | flag ) - player.Signal( "CE_FLAGS_CHANGED" ) -} - -void function RemoveCinematicFlag( entity player, int flag ) -{ - Assert( player.IsPlayer() ) - Assert( IsValid( player ) ) - player.SetCinematicEventFlags( player.GetCinematicEventFlags() & ( ~flag ) ) - player.Signal( "CE_FLAGS_CHANGED" ) -} - -void function SkyScaleDefault( entity ent, float time = 1.0 ) -{ - if ( IsValid( ent ) ) - ent.LerpSkyScale( SKYSCALE_DEFAULT, time ) -} - -void function MoveSpawn( string targetName, vector origin, vector angles ) -{ - entity ent = GetEnt( targetName ) - ent.SetOrigin( origin ) - ent.SetAngles( angles ) -} - -/* -function CheckDailyChallengeAchievement( entity player ) -{ - if ( player.GetPersistentVar( "cu8achievement.ach_allDailyChallengesForDay" ) == true ) - return - - int maxRefs = PersistenceGetArrayCount( "activeDailyChallenges" ) - int todaysDailiesComplete = 0 - int today = Daily_GetDayForCurrentTime() - for ( int i = 0; i < maxRefs; i++ ) - { - int day = player.GetPersistentVarAsInt( "activeDailyChallenges[" + i + "].day" ) - if ( day != today ) - continue - - local ref = player.GetPersistentVar( "activeDailyChallenges[" + i + "].ref" ) - if ( !IsChallengeComplete( ref, player ) ) - continue - - todaysDailiesComplete++ - } - - if ( todaysDailiesComplete >= 3 ) - player.SetPersistentVar( "cu8achievement.ach_allDailyChallengesForDay", true ) -} -*/ - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Get an array of all linked entities targeted to one after the other down the chain -array<entity> function GetEntityTargetChain_Deprecated( entity ent ) -{ - array<entity> entityChain = [] - entity currentEnt = ent - entity nextEnt - - while ( true ) - { - nextEnt = GetEnt( currentEnt.GetTarget_Deprecated() ) - if ( IsValid( nextEnt ) ) - entityChain.append( nextEnt ) - else - return entityChain - currentEnt = nextEnt - } - - unreachable -} - -void function PlayImpactFXTable( vector origin, entity owner, string impactFX, int flags = 0 ) -{ - Explosion( - origin, //center, - owner, //attacker, - owner, //inflictor,flags - 0, //damage, - 0, //damageHeavyArmor, - 1, //innerRadius, - 1, //outerRadius, - flags, //flags, - origin, //projectileLaunchOrigin, - 0, //explosionForce, - damageTypes.explosive, //scriptDamageFlags, - -1, //scriptDamageSourceIdentifier, - impactFX ) //impactEffectTableName -} - -void function SetSignalDelayed( entity ent, string signal, float delay ) -{ - thread __SetSignalDelayedThread( ent, signal, delay ) -} - -void function __SetSignalDelayedThread( entity ent, string signal, float delay ) -{ - EndSignal( ent, signal ) // so that if we call this again with the same signal on the same ent we won't get multiple signal events. - - wait delay - if ( IsValid( ent ) ) - Signal( ent, signal ) -} - -#if DEV -table function GetPlayerPos( entity player = null ) -{ - if ( !player ) - player = gp()[0] - - vector org = player.GetOrigin() - vector vec = player.GetViewVector() - vector ang = VectorToAngles( vec ) - - return { origin = org, angles = ang } -} - -string function GetScriptPos( entity player = null ) -{ - table playerPos = GetPlayerPos( player ) - vector origin = expect vector( playerPos.origin ) - vector angles = expect vector( playerPos.angles ) - - string returnStr = CreateOriginAnglesString( origin, <0, angles.y, 0> ) - return returnStr -} - -string function CreateOriginAnglesString( vector origin, vector angles ) -{ - string returnStr = "< " + origin.x + ", " + origin.y + ", " + origin.z + " >, < " + angles.x + ", " + angles.y + ", " + angles.z + " >" - return returnStr -} - -void function DistCheck_SetTestPoint() -{ - svGlobal.distCheckTestPoint = expect vector( GetPlayerPos().origin ) - printt( "DistCheck test point set to:", svGlobal.distCheckTestPoint ) -} - -void function DistCheck() -{ - vector here = expect vector( GetPlayerPos().origin ) - float dist = Distance( here, svGlobal.distCheckTestPoint ) - printt( "Distance:", dist, "units from", svGlobal.distCheckTestPoint ) -} -#endif // DEV - -void function ClearChildren( entity parentEnt ) //Probably should have code give us a GetChildren() function that returns a list instead of having to iterate through NextMovePeer -{ - entity childEnt = parentEnt.FirstMoveChild() - entity nextChildEnt - - while ( childEnt != null ) - { - nextChildEnt = childEnt.NextMovePeer() - childEnt.ClearParent() - - childEnt = nextChildEnt - } -} - -void function ForceTimeLimitDone() -{ - level.devForcedWin = true - level.devForcedTimeLimit = true - svGlobal.levelEnt.Signal( "devForcedWin" ) - ServerCommand( "mp_enabletimelimit 1" ) - ServerCommand( "mp_enablematchending 1" ) -} - - -void function UpdateBadRepPresent() -{ - array<entity> players = GetPlayerArray() - bool found = false -/* always set to false for now - foreach ( player in players ) - { - if ( player.HasBadReputation() ) - { - found = true - break - } - } -*/ - level.nv.badRepPresent = found - level.ui.badRepPresent = found -} - -void function Dev_PrintMessage( entity player, string text, string subText = "", float duration = 7.0, string soundAlias = "" ) -{ - #if DEV - // Build the message on the client - string sendMessage - for ( int textType = 0 ; textType < 2 ; textType++ ) - { - sendMessage = textType == 0 ? text : subText - - for ( int i = 0; i < sendMessage.len(); i++ ) - { - Remote_CallFunction_NonReplay( player, "Dev_BuildClientMessage", textType, sendMessage[i] ) - } - } - Remote_CallFunction_NonReplay( player, "Dev_PrintClientMessage", duration ) - if ( soundAlias != "" ) - EmitSoundOnEntity( player, soundAlias ) - #endif -} - -bool function IsAttackDefendBased() //If needed to, we can make this a .nv and then move this function into utility_shared -{ - return expect bool( level.attackDefendBased ) -} - -bool function IsRoundBasedUsingTeamScore() //If needed to, we can make this a .nv and then move this function into utility_shared -{ - return IsRoundBased() && expect bool( level.roundBasedUsingTeamScore ) -} - -bool function ShouldResetRoundBasedTeamScore() -{ - return IsRoundBased() && svGlobal.roundBasedTeamScore_RoundReset -} - -void function CreateZipline( vector startPos, vector endPos ) -{ - string startpointName = UniqueString( "rope_startpoint" ) - string endpointName = UniqueString( "rope_endpoint" ) - - entity rope_start = CreateEntity( "move_rope" ) - SetTargetName( rope_start, startpointName ) - rope_start.kv.NextKey = endpointName - rope_start.kv.MoveSpeed = 64 - rope_start.kv.Slack = 25 - rope_start.kv.Subdiv = "2" - rope_start.kv.Width = "2" - rope_start.kv.Type = "0" - rope_start.kv.TextureScale = "1" - rope_start.kv.RopeMaterial = "cable/zipline.vmt" - rope_start.kv.PositionInterpolator = 2 - rope_start.kv.Zipline = "1" - rope_start.kv.ZiplineAutoDetachDistance = "150" - rope_start.kv.ZiplineSagEnable = "0" - rope_start.kv.ZiplineSagHeight = "50" - rope_start.SetOrigin( startPos ) - - entity rope_end = CreateEntity( "keyframe_rope" ) - SetTargetName( rope_end, endpointName ) - rope_end.kv.MoveSpeed = 64 - rope_end.kv.Slack = 25 - rope_end.kv.Subdiv = "2" - rope_end.kv.Width = "2" - rope_end.kv.Type = "0" - rope_end.kv.TextureScale = "1" - rope_end.kv.RopeMaterial = "cable/zipline.vmt" - rope_end.kv.PositionInterpolator = 2 - rope_end.kv.Zipline = "1" - rope_end.kv.ZiplineAutoDetachDistance = "150" - rope_end.kv.ZiplineSagEnable = "0" - rope_end.kv.ZiplineSagHeight = "50" - rope_end.SetOrigin( endPos ) - - DispatchSpawn( rope_start ) - DispatchSpawn( rope_end ) -} - -string function GetNPCTitanSettingFile( entity titan ) -{ - Assert( titan.IsTitan(), titan + " is not a titan" ) - return titan.ai.titanSettings.titanSetFile -} - -void function DecodeBitField( int bitField ) -{ - for ( int bitIndex = 0; bitIndex < 32; bitIndex++ ) - { - if ( bitField & (1 << bitIndex) ) - { - printt( "Comparison: ", bitField, "& ( 1 <<", bitIndex, ") = ", bitField & (1 << bitIndex) ) - printt( "BIT SET: ", bitIndex, bitField, 1 << bitIndex ) - } - } -} - -void function DropWeapon( entity npc ) -{ - entity weapon = npc.GetActiveWeapon() - if ( !weapon ) - return - - string name = weapon.GetWeaponClassName() - - // giving the weapon you have drops a new one in its place - npc.GiveWeapon( name ) - npc.TakeActiveWeapon() -} - -void function TestGiveGunTo( int index, string weaponName ) -{ - entity ent = GetEntByIndex( index ) - if ( !ent ) - { - printt( "No entity for index:", index ) - return; - } - - TakePrimaryWeapon( ent ) - ent.GiveWeapon( weaponName ) - ent.SetActiveWeaponByName( weaponName ) -} - -string function GetEditorClass( entity self ) -{ - if ( self.HasKey( "editorclass" ) ) - return expect string( self.kv.editorclass ) - - return "" -} - -bool function TitanHasRegenningShield( entity soul ) -{ - if ( !TitanShieldRegenEnabled() ) - return false - - if ( !TitanShieldDecayEnabled() ) - return true - - if ( SoulHasPassive( soul, ePassives.PAS_SHIELD_BOOST ) ) - return true - - return false -} - -void function DelayShieldDecayTime( entity soul, float delay ) -{ - soul.e.nextShieldDecayTime = Time() + delay -} - -void function HighlightWeapon( entity weapon ) -{ -#if HAS_WEAPON_PICKUP_HIGHLIGHT - if ( weapon.IsLoadoutPickup() ) - { - Highlight_SetOwnedHighlight( weapon, "sp_loadout_pickup" ) - Highlight_SetNeutralHighlight( weapon, "sp_loadout_pickup" ) - } - else - { - Highlight_SetOwnedHighlight( weapon, "weapon_drop_active" ) - Highlight_SetNeutralHighlight( weapon, "weapon_drop_normal" ) - } -#endif // #if HAS_WEAPON_PICKUP_HIGHLIGHT -} - -void function WaitTillLookingAt( entity player, entity ent, bool doTrace, float degrees, float minDist = 0, float timeOut = 0, entity trigger = null, string failsafeFlag = "" ) -{ - EndSignal( ent, "OnDestroy" ) - EndSignal( player, "OnDeath" ) - - //trigger = the trigger ther player must be touching while doing the check - //failsafeFlag = bypass everything if this flag gets set - - if ( failsafeFlag != "" ) - EndSignal( level, failsafeFlag ) - - float minDistSqr = minDist * minDist - Assert( minDistSqr >= 0 ) - float timeoutTime = Time() + timeOut - - while( true ) - { - - if ( timeOut > 0 && Time() > timeoutTime ) - break - - if ( failsafeFlag != "" && Flag( failsafeFlag ) ) - break - - // Within range? - if ( minDistSqr > 0 && DistanceSqr( player.GetOrigin(), ent.GetOrigin() ) > minDistSqr ) - { - WaitFrame() - continue - } - - // Touching trigger? - if ( ( trigger != null ) && ( !trigger.IsTouching( player ) ) ) - { - WaitFrame() - continue - } - - if ( PlayerCanSee( player, ent, doTrace, degrees ) ) - break - - WaitFrame() - } -} - -void function SetTargetName( entity ent, string name ) -{ - ent.SetValueForKey( "targetname", name ) -} - -ZipLine function CreateZipLine( vector start, vector end, int autoDetachDistance = 150, float ziplineMoveSpeedScale = 1.0 ) -{ - 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 = 0 - rope_start.kv.ZiplineMoveSpeedScale = ziplineMoveSpeedScale - rope_start.kv.Slack = 0 - rope_start.kv.Subdiv = 0 - rope_start.kv.Width = "2" - rope_start.kv.TextureScale = "1" - rope_start.kv.RopeMaterial = "cable/zipline.vmt" - rope_start.kv.PositionInterpolator = 2 - rope_start.kv.Zipline = "1" - rope_start.kv.ZiplineAutoDetachDistance = string( autoDetachDistance ) - rope_start.kv.ZiplineSagEnable = "0" - rope_start.kv.ZiplineSagHeight = "0" - rope_start.SetOrigin( start ) - - entity rope_mid = CreateEntity( "keyframe_rope" ) - SetTargetName( rope_mid, midpointName ) - rope_start.kv.NextKey = endpointName - rope_mid.SetOrigin( ( start + end ) * 0.5 ) - //rope_mid.SetOrigin( start ) - - entity rope_end = CreateEntity( "keyframe_rope" ) - SetTargetName( rope_end, endpointName ) - rope_end.SetOrigin( end ) - - // Dispatch spawn entities - DispatchSpawn( rope_start ) - DispatchSpawn( rope_mid ) - DispatchSpawn( rope_end ) - - ZipLine zipLine - zipLine.start = rope_start - zipLine.mid = rope_mid - zipLine.end = rope_end - - return zipLine -} - -entity function GetPlayerFromEntity( entity ent ) -{ - entity player = null - - if ( ent.IsPlayer() ) - { - player = ent - } - else if ( ent.IsNPC() ) - { - player = ent.GetBossPlayer() - } - else - { - player = ent.GetOwner() - if ( !player || !player.IsPlayer() ) - return null - } - - if ( IsValid_ThisFrame( player ) ) - return player - - return null -} - -void function SetHumanRagdollImpactTable( entity ent ) -{ - ent.SetRagdollImpactFX( HUMAN_RAGDOLL_IMPACT_TABLE_IDX ) -} - -bool function ScriptManagedEntArrayContains( int handle, entity ent ) -{ - array< entity > ents = GetScriptManagedEntArray( handle ) - foreach ( ent in ents ) - { - if ( ent == ent ) - return true - } - - return false -} - -void function HideCrit( entity ent ) -{ - int bodyGroupIndex = ent.FindBodyGroup( "hitpoints" ) - - if ( bodyGroupIndex == -1 ) - { - return - } - - ent.SetBodygroup( bodyGroupIndex, 1 ) -} - -void function ShowCrit( entity ent ) -{ - int bodyGroupIndex = ent.FindBodyGroup( "hitpoints" ) - - if ( bodyGroupIndex == -1 ) - { - return - } - - ent.SetBodygroup( bodyGroupIndex, 0 ) -} - - -#if DEV -void function TeleportEnemyBotToView() -{ - entity player = gp()[0] - - TraceResults traceResults = PlayerViewTrace( player ) - - if ( traceResults.fraction >= 1.0 ) - return - - array<entity> players = GetPlayerArrayOfEnemies_Alive( player.GetTeam() ) - foreach ( enemy in players ) - { - if ( !enemy.IsBot() ) - continue - - enemy.SetOrigin( traceResults.endPos ) - return - } -} - -void function TeleportEntityToView( entity ent ) -{ - entity player = gp()[0] - - TraceResults traceResults = PlayerViewTrace( player ) - - if ( traceResults.fraction >= 1.0 ) - return - - ent.SetOrigin( traceResults.endPos ) - //traceResults.surfaceNormal -} - -void function TeleportFriendlyBotToView() -{ - entity player = gp()[0] - - TraceResults traceResults = PlayerViewTrace( player ) - - if ( traceResults.fraction >= 1.0 ) - return - - array<entity> players = GetPlayerArrayOfTeam_Alive( player.GetTeam() ) - foreach ( enemy in players ) - { - if ( !enemy.IsBot() ) - continue - - enemy.SetOrigin( traceResults.endPos ) - return - } -} - -void function TeleportBotToAbove() -{ - entity player = gp()[0] - - array<entity> players = GetPlayerArray_AlivePilots() - foreach ( enemy in players ) - { - if ( !enemy.IsBot() ) - continue - - enemy.SetOrigin( player.GetOrigin() + < 0, 0, 512 > ) - return - } -} - -TraceResults function PlayerViewTrace( entity player, float distance = 10000 ) -{ - vector eyePosition = player.EyePosition() - vector viewVector = player.GetViewVector() - - TraceResults traceResults = TraceLine( eyePosition, eyePosition + viewVector * distance, player, TRACE_MASK_SHOT_BRUSHONLY, TRACE_COLLISION_GROUP_NONE ) - - return traceResults -} -#endif - -void function ClearPlayerAnimViewEntity( entity player, float time = 0.3 ) -{ - entity viewEnt = player.GetFirstPersonProxy() - viewEnt.HideFirstPersonProxy() - viewEnt.Anim_Stop() - - player.AnimViewEntity_SetLerpOutTime( time ) - player.AnimViewEntity_Clear() - player.p.currViewConeFunction = null -} - - -void function BrushMoves( entity brush ) -{ - float moveTime = float( brush.kv.move_time ) - int movedir = int( brush.kv.movedirection ) - - BrushMovesInDirection( brush, movedir, moveTime ) -} - - -void function BrushMovesInDirection( entity ent, int dir, float moveTime = 0, float blendIn = 0, float blendOut = 0, float lip = 8 ) -{ - entity mover = CreateOwnedScriptMover( ent ) - OnThreadEnd( - function() : ( ent, mover ) - { - if ( IsValid( ent ) ) - ent.ClearParent() - if ( IsValid( mover ) ) - mover.Destroy() - } - ) - - dir %= 360 - if ( dir > 180 ) - dir -= 360 - else if ( dir < -180 ) - dir += 360 - - string moveAxis = GetMoveAxisFromDir( dir ) - - ent.SetParent( mover ) - vector origin = ent.GetOrigin() - float moveAmount - if ( ent.HasKey( "move_amount" ) ) - { - moveAmount = float( ent.kv.move_amount ) - lip - switch ( moveAxis ) - { - case "x": - case "y": - if ( dir < 0 ) - moveAmount *= -1 - break - - case "z": - if ( dir == -1 ) - moveAmount *= -1 - break - } - } - else - { - switch ( moveAxis ) - { - case "x": - moveAmount = GetEntWidth( ent ) - lip - if ( dir < 0 ) - moveAmount *= -1 - break - - case "y": - moveAmount = GetEntDepth( ent ) - lip - if ( dir < 0 ) - moveAmount *= -1 - break - - case "z": - moveAmount = GetEntHeight( ent ) - lip - if ( dir == -1 ) - moveAmount *= -1 - break - } - } - - switch ( moveAxis ) - { - case "x": - origin.x += moveAmount - break - case "y": - origin.y += moveAmount - break - case "z": - origin.z += moveAmount - break - } - - if ( moveTime > 0 ) - { - mover.NonPhysicsMoveTo( origin, moveTime, blendIn, blendOut ) - wait moveTime - } - else - { - mover.SetOrigin( origin ) - } -} - -string function GetMoveAxisFromDir( int dir ) -{ - if ( dir == 1 || dir == -1 ) - return "z" - - if ( dir % 180 == 0 ) - return "x" - - return "y" -} - - -float function GetEntHeight( entity ent ) -{ - return ent.GetBoundingMaxs().z - ent.GetBoundingMins().z -} - -float function GetEntWidth( entity ent ) -{ - return ent.GetBoundingMaxs().x - ent.GetBoundingMins().x -} - -float function GetEntDepth( entity ent ) -{ - return ent.GetBoundingMaxs().y - ent.GetBoundingMins().y -} - -void function PushEntWithVelocity( entity ent, vector velocity ) -{ - if ( !ent.IsPlayer() && !ent.IsNPC() ) - return - - if ( !IsAlive( ent ) ) - return - - float scale = 1.0 - float pushbackScale = 1.0 - if ( ent.IsTitan() ) - { - entity soul = ent.GetTitanSoul() - if ( soul != null ) // defensive fix - { - string settings = GetSoulPlayerSettings( soul ) - var scale = Dev_GetPlayerSettingByKeyField_Global( settings, "pushbackScale" ) - if ( scale != null ) - { - pushbackScale = expect float( scale ) - } - } - } - - scale = 1.0 - StatusEffect_Get( ent, eStatusEffect.pushback_dampen ) - scale = scale * pushbackScale - - velocity *= scale - - ent.SetVelocity( velocity ) -} - - - -bool function IsPlayerMalePilot( entity player ) -{ - Assert( player.IsPlayer() ) - - if ( !IsPilot( player ) ) - return false - - return !IsPlayerFemale( player ) -} - -bool function IsPlayerFemalePilot( entity player ) -{ - Assert( player.IsPlayer() ) - - if ( !IsPilot( player ) ) - return false - - return IsPlayerFemale( player ) -} - -bool function IsFacingEnemy( entity guy, entity enemy, int viewAngle = 75 ) -{ - vector dir = enemy.GetOrigin() - guy.GetOrigin() - dir = Normalize( dir ) - float dot = DotProduct( guy.GetPlayerOrNPCViewVector(), dir ) - float yaw = DotToAngle( dot ) - - return ( yaw < viewAngle ) -} - -void function SetSquad( entity guy, string squadName ) -{ - Assert( IsValid( guy ) ) - - if ( guy.kv.squadname == squadName ) - return - - // we only want squads containing NPCs of the same class - #if HAS_AI_SQUAD_LIMITS - Assert( SquadValidForClass( squadName, guy.GetClassName() ), "Can't put AI " + guy + " in squad " + squadName + ", because it contains one or more AI with a different class." ) - Assert( SquadCanAcceptNewMembers( guy, squadName ), "Can't add AI " + guy + " to squad " + squadName + ", because that squad already has " + SQUAD_SIZE + " slots filled or reserved." ) - #endif - - guy.SetSquad( squadName ) -} - -void function PushPlayersApart( entity target, entity attacker, float speed ) -{ - vector dif = Normalize( target.GetOrigin() - attacker.GetOrigin() ) - dif *= speed - PushPlayerAway( target, dif ) - PushPlayerAway( attacker, -dif ) -} - -void function PushPlayerAway( entity target, vector velocity ) -{ - #if MP - if ( !target.IsPlayer() && !target.IsNPC() ) - return - #endif - - vector result = velocity // + target.GetVelocity() - result.z = max( 200, fabs( velocity.z ) ) - target.SetVelocity( result ) - //DebugDrawLine( target.GetOrigin(), target.GetOrigin() + result * 5, 255, 0, 0, true, 5.0 ) -} - - -int function SortBySpawnTime( entity ent1, entity ent2 ) -{ - if ( ent1.e.spawnTime > ent2.e.spawnTime ) - return 1 - - if ( ent2.e.spawnTime > ent1.e.spawnTime ) - return -1 - - return 0 -} - -void function HolsterAndDisableWeapons( entity player ) -{ - player.HolsterWeapon() - DisableOffhandWeapons( player ) -} - -void function HolsterViewModelAndDisableWeapons( entity player ) //Note that this skips the first person holster animation, and it appears to 3p observers you still have a gun out -{ - player.DisableWeaponViewModel() - DisableOffhandWeapons( player ) -} - - -void function DeployAndEnableWeapons( entity player ) -{ - player.DeployWeapon() - EnableOffhandWeapons( player ) -} - -void function DeployViewModelAndEnableWeapons( entity player ) -{ - if ( IsAlive( player ) ) - player.EnableWeaponViewModel() - EnableOffhandWeapons( player ) -} - -//Investigate: This might be getting called without enableoffhandweapons being called. If so, Server_TurnOffhandWeaponsDisabledOn() should be used instead of this stack system. -void function DisableOffhandWeapons( entity player ) -{ - player.Server_TurnOffhandWeaponsDisabledOn() - player.p.disableOffhandWeaponsStackCount++ -} - -void function EnableOffhandWeapons( entity player ) -{ - player.p.disableOffhandWeaponsStackCount-- - if ( player.p.disableOffhandWeaponsStackCount <= 0 ) - player.Server_TurnOffhandWeaponsDisabledOff() - - Assert( player.p.disableOffhandWeaponsStackCount >= 0, "Warning! Called EnableOffhandWeapons() but the weapons aren't disabled!" ) -} - -void function PushEntWithDamageInfoAndDistanceScale( entity ent, var damageInfo, float nearRange, float farRange, float nearScale, float farScale, float forceMultiplier_dotBase = 0.5 ) -{ - float scale = GraphCapped( DamageInfo_GetDistFromAttackOrigin( damageInfo ), nearRange, farRange, nearScale, farScale ) - - if ( scale > 0 ) - PushEntWithDamageInfo( ent, damageInfo, forceMultiplier_dotBase, scale ) -} - -void function PushEntWithDamageInfo( entity ent, var damageInfo, float forceMultiplier_dotBase = 0.5, float forceMultiplier_dotScale = 0.5 ) -{ - int source = DamageInfo_GetDamageSourceIdentifier( damageInfo ) - switch ( source ) - { - case eDamageSourceId.mp_titanweapon_vortex_shield: - case eDamageSourceId.mp_titanweapon_vortex_shield_ion: - return - } - - entity projectile = DamageInfo_GetInflictor( damageInfo ) - if ( !IsValid( projectile ) ) - return - - vector attackDirection = Normalize( projectile.GetVelocity() ) - float damage = DamageInfo_GetDamage( damageInfo ) - - PushEntWithDamageFromDirection( ent, damage, attackDirection, forceMultiplier_dotBase, forceMultiplier_dotScale ) -} - -void function PushEntWithDamageFromDirection( entity ent, float damage, vector attackDirection, float forceMultiplier_dotBase = 0.5, float forceMultiplier_dotScale = 0.5 ) -{ - - float speed - if ( damage < 900 ) - speed = GraphCapped( damage, 0, 900, 0, 650 ) - else - speed = GraphCapped( damage, 900, 1400, 650, 1400 ) - - vector direction = attackDirection + <0,0,0> - direction.z *= 0.25 - vector force = direction * speed - - force += < 0, 0, fabs( direction.z ) * 0.25 > - - vector velocity = ent.GetVelocity() - vector baseVel = Normalize( velocity + <0,0,0> ) - - float dot = DotProduct( baseVel, attackDirection ) * -1 - float dotMultiplier - if ( dot > 0 ) - { - dot *= forceMultiplier_dotScale - } - else - { - dot = 0 - } - - force *= ( forceMultiplier_dotBase + dot ) - //printt( "force " + Length( force ) ) - velocity += force - PushEntWithVelocity( ent, velocity ) -} - - -void function SetPlayerAnimViewEntity( entity player, entity model ) -{ - // clear any attempts to hide the view anim entity - player.Signal( "NewViewAnimEntity" ) - player.AnimViewEntity_SetEntity( model ) -} - - -void function RandomizeHead( entity model ) //Randomize head across all available heads -{ - int headIndex = model.FindBodyGroup( "head" ) - if ( headIndex == -1 ) - { - //printt( "HeadIndex == -1, returning" ) - return - } - int numOfHeads = model.GetBodyGroupModelCount( headIndex ) - 1 // last one is no head - //printt( "Num of Heads: " + numOfHeads ) - - if ( HasTeamSkin( model ) ) - { - RandomizeHeadByTeam( model, headIndex, numOfHeads ) - return - } - else - { - int randomHeadIndex = RandomInt( numOfHeads ) - //printt( "Set head to: : " + randomHeadIndex ) - model.SetBodygroup( headIndex, randomHeadIndex ) - } -} - -bool function HasTeamSkin( entity model ) -{ - return "teamSkin" in model.CreateTableFromModelKeyValues() -} - -void function RandomizeHeadByTeam( entity model, int headIndex, int numOfHeads ) //Randomize head across heads available to a particular team. Assumes for a model all imc heads are first, then all militia heads are later. -{ - float midPoint = float( numOfHeads / 2 ) - - int randomHeadIndex = 0 - if ( model.GetTeam() == TEAM_IMC ) - { - randomHeadIndex = RandomInt( midPoint ) - } - else if ( model.GetTeam() == TEAM_MILITIA ) - { - randomHeadIndex = RandomIntRange( midPoint, numOfHeads ) - } - //printt( "Model ", model.GetModelName(), " is using ", numOfHeads, " randomHeadIndex") - - //printt( "Set head to: : " + randomHeadIndex ) - model.SetBodygroup( headIndex, randomHeadIndex ) -} - -void function TakeWeaponsForArray( entity ent, array<entity> weapons ) -{ - foreach ( weapon in weapons ) - { - ent.TakeWeaponNow( weapon.GetWeaponClassName() ) - } -} - -void function ScaleHealth( entity ent, float scale ) -{ - Assert( IsAlive( ent ) ) - - int maxHealth = ent.GetMaxHealth() - float healthRatio = float( ent.GetHealth() ) / maxHealth - maxHealth = int( maxHealth * scale ) - ent.SetHealth( maxHealth * healthRatio ) - ent.SetMaxHealth( maxHealth ) -} - -void function TeleportPlayerToEnt( entity player, entity org ) -{ - if ( !IsValid( player ) ) - return - Assert( player.IsPlayer() ) - player.SetOrigin( org.GetOrigin() ) - player.SetAngles( org.GetAngles() ) -} - -float function ShieldModifyDamage( entity ent, var damageInfo ) -{ - entity victim - if ( ent.IsTitan() ) - victim = ent.GetTitanSoul() - else - victim = ent - - int shieldHealth = victim.GetShieldHealth() - - float damage = DamageInfo_GetDamage( damageInfo ) - - int damageSourceIdentifier = DamageInfo_GetDamageSourceIdentifier( damageInfo ) - ShieldDamageModifier damageModifier = GetShieldDamageModifier( damageInfo ) - damage *= damageModifier.damageScale - - float healthFrac = GetHealthFrac( victim ) - - float permanentDamage = (damage * damageModifier.permanentDamageFrac * healthFrac) - - float shieldDamage - - if ( damageSourceIdentifier == eDamageSourceId.titanEmpField ) - { - shieldDamage = min( 1000.0, float( shieldHealth ) ) - } - else - { - if ( damageModifier.normalizeShieldDamage ) - shieldDamage = damage * 0.5 - else - shieldDamage = damage - permanentDamage - - // if ( IsSoul( victim ) && SoulHasPassive( victim, ePassives.PAS_SHIELD_BOOST ) ) - // shieldDamage *= SHIELD_BOOST_DAMAGE_DAMPEN - - if ( IsSoul( victim ) && SoulHasPassive( victim, ePassives.PAS_BERSERKER ) ) - shieldDamage *= BERSERKER_INCOMING_DAMAGE_DAMPEN - } - - float newShieldHealth = shieldHealth - shieldDamage - - victim.SetShieldHealth( max( 0, newShieldHealth ) ) - - if ( shieldHealth > 0 && newShieldHealth <= 0 ) - { - if ( ent.IsPlayer() ) - { - EmitSoundOnEntityExceptToPlayer( ent, ent, "titan_energyshield_down_3P" ) - EmitSoundOnEntityOnlyToPlayer( ent, ent, "titan_energyshield_down_1P" ) - } - else if ( ent.GetScriptName() == "fw_team_tower" ) - { - EmitSoundOnEntity( ent, "TitanWar_Harvester_ShieldDown" ) - - #if FACTION_DIALOGUE_ENABLED - PlayFactionDialogueToTeam( "fortwar_baseShieldDownFriendly", ent.GetTeam() ) - PlayFactionDialogueToTeam( "fortwar_baseShieldDownEnemy", GetOtherTeam( ent.GetTeam() ) ) - #endif - } - else - { - EmitSoundOnEntity( ent, "titan_energyshield_down_3P" ) - } - } - - DamageInfo_AddCustomDamageType( damageInfo, DF_SHIELD_DAMAGE ) - - if ( newShieldHealth < 0 ) - { - DamageInfo_SetDamage( damageInfo, fabs( newShieldHealth ) + permanentDamage ) - } - else - { - if ( permanentDamage == 0 ) - { - entity attacker = DamageInfo_GetAttacker( damageInfo ) - vector damageOrigin = GetDamageOrigin( damageInfo, ent ) - int damageType = DamageInfo_GetCustomDamageType( damageInfo ) - int attackerEHandle = attacker.GetEncodedEHandle() - int damageSourceId = DamageInfo_GetDamageSourceIdentifier( damageInfo ) - - if ( attacker.IsPlayer() ) - attacker.NotifyDidDamage( ent, DamageInfo_GetHitBox( damageInfo ), DamageInfo_GetDamagePosition( damageInfo ), damageType, shieldDamage, DamageInfo_GetDamageFlags( damageInfo ), DamageInfo_GetHitGroup( damageInfo ), DamageInfo_GetWeapon( damageInfo ), DamageInfo_GetDistFromAttackOrigin( damageInfo ) ) - if ( ent.IsPlayer() ) - Remote_CallFunction_Replay( ent, "ServerCallback_TitanTookDamage", shieldDamage, damageOrigin.x, damageOrigin.y, damageOrigin.z, damageType, damageSourceId, attackerEHandle, null, false, 0 ) - } - DamageInfo_SetDamage( damageInfo, permanentDamage ) - } - - float actualShieldDamage = min( shieldHealth, shieldDamage ) - - if ( actualShieldDamage > 0 ) - { - foreach ( func in ent.e.entPostShieldDamageCallbacks ) - { - func( ent, damageInfo, actualShieldDamage ) - } - } - - return actualShieldDamage -} - -ShieldDamageModifier function GetShieldDamageModifier( var damageInfo ) -{ - ShieldDamageModifier damageModifier - - // Disabling Shield Damage Modifiers and rebalancing the weapons. The below mechanics seem cool in an R1 style system though so leaving them commented out. - // NOTE: Changing Damage Scale has a buggy interaction with permanent damage that must be fixed if we re-enable this. - /* - int damageSourceIdentifier = DamageInfo_GetDamageSourceIdentifier( damageInfo ) - - switch ( damageSourceIdentifier ) - { - case eDamageSourceId.mp_weapon_thermite_grenade: - damageModifier.permanentDamageFrac = 0.9 - break - } - - if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_ELECTRICAL ) - { - // amped version - if ( damageSourceIdentifier == eDamageSourceId.mp_titanweapon_xo16 ) - damageModifier.damageScale *= 1.5 - - // amped version - if ( damageSourceIdentifier == eDamageSourceId.mp_titanweapon_triple_threat ) - damageModifier.damageScale *= 1.5 - - if ( damageSourceIdentifier == eDamageSourceId.mp_titanweapon_arc_cannon ) - damageModifier.damageScale *= 1.5 - } - */ - - if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_ELECTRICAL ) - { - int damageSourceIdentifier = DamageInfo_GetDamageSourceIdentifier( damageInfo ) - // Vanguard Arc Rounds - if ( damageSourceIdentifier == eDamageSourceId.mp_titanweapon_xo16_vanguard ) - damageModifier.damageScale *= 1.5 - } - - - return damageModifier -} - - - -void function AddCallback_NPCLeeched( void functionref( entity, entity ) callbackFunc ) -{ - Assert( !( svGlobal.onLeechedCustomCallbackFunc.contains( callbackFunc ) ) ) - svGlobal.onLeechedCustomCallbackFunc.append( callbackFunc ) -} - -void function MessageToPlayer( entity player, int eventID, entity ent = null, var eventVal = null ) -{ - var eHandle = null - if ( ent ) - eHandle = ent.GetEncodedEHandle() - - Remote_CallFunction_NonReplay( player, "ServerCallback_EventNotification", eventID, eHandle, eventVal ) - //SendHudMessage( player, message, 0.33, 0.28, 255, 255, 255, 255, 0.15, 3.0, 0.5 ) -} - - -void function MessageToTeam( int team, int eventID, entity excludePlayer = null, entity ent = null, var eventVal = null ) -{ - array<entity> players = GetPlayerArray() - - foreach ( player in players ) - { - if ( player.GetTeam() != team ) - continue - - if ( player == excludePlayer ) - continue - - MessageToPlayer( player, eventID, ent, eventVal ) - } -} - -void function MessageToAll( int eventID, entity excludePlayer = null, entity ent = null, var eventVal = null ) -{ - array<entity> players = GetPlayerArray() - - foreach ( player in players ) - { - if ( player == excludePlayer ) - continue - - MessageToPlayer( player, eventID, ent, eventVal ) - } -} - - - -string function ReloadScriptsInternal() -{ - reloadingScripts = true - reloadedScripts = true - ReloadingScriptsBegin() - - if ( IsMenuLevel() ) - { - reloadingScripts = false - ReloadingScriptsEnd() - return "" - } - - TitanEmbark_Init() - - ReloadScriptCallbacks() - - reloadingScripts = false - ReloadingScriptsEnd() - - return ( "reloaded server scripts" ) -} - -string function ReloadScripts() -{ - ServerCommand( "fs_report_sync_opens 0" ) // makes reload scripts slow - delaythread ( 0 ) ReloadScriptsInternal() - - return ( "reloaded server scripts" ) -} - -int function GameTime_TimeLimitSeconds() -{ - if ( IsRoundBased() ) - { - return ( GetRoundTimeLimit_ForGameMode() * 60.0 ).tointeger() - } - else - { - if ( IsSuddenDeathGameMode() && GetGameState() == eGameState.SuddenDeath ) - return ( GetTimeLimit_ForGameMode() * 60.0 ).tointeger() + ( GetSuddenDeathTimeLimit_ForGameMode() * 60.0 ).tointeger() - else - return ( GetTimeLimit_ForGameMode() * 60.0 ).tointeger() - } - unreachable -} - -int function GetSuddenDeathTimeLimit_ForGameMode() -{ - string mode = GameRules_GetGameMode() - string playlistString = "suddendeath_timelimit" - - return GetCurrentPlaylistVarInt( playlistString, 4 ) -} - -int function GameTime_TimeLimitMinutes() -{ - if ( IsRoundBased() ) - return floor( GetRoundTimeLimit_ForGameMode() ).tointeger() - else - return floor( GetTimeLimit_ForGameMode() ).tointeger() - unreachable -} - -int function GameTime_TimeLeftMinutes() -{ - if ( GetGameState() == eGameState.WaitingForPlayers ) - return 0 - if ( GetGameState() == eGameState.Prematch ) - return int( ( expect float( GetServerVar( "gameStartTime" ) ) - Time()) / 60.0 ) - - return floor( GameTime_TimeLimitMinutes() - GameTime_PlayingTime() / 60 ).tointeger() -} - -int function GameTime_TimeLeftSeconds() -{ - if ( GetGameState() == eGameState.Prematch ) - return int( expect float( GetServerVar( "gameStartTime" ) ) - Time() ) - - return floor( GameTime_TimeLimitSeconds() - GameTime_PlayingTime() ).tointeger() -} - -int function GameTime_Seconds() -{ - return floor( Time() ).tointeger() -} - -int function GameTime_Minutes() -{ - return int( floor( GameTime_Seconds() / 60 ) ) -} - -float function GameTime_PlayingTime() -{ - return GameTime_PlayingTimeSince( Time() ) -} - -float function GameTime_PlayingTimeSince( float sinceTime ) -{ - int gameState = GetGameState() - - // temp fix because i have no fucking clue why this crashes - - if ( gameState < eGameState.Playing ) - return 0 - - if ( IsRoundBased() ) - { - if ( gameState > eGameState.SuddenDeath ) - return (expect float( GetServerVar( "roundEndTime" ) ) - expect float( GetServerVar( "roundStartTime" ) ) ) - else - return sinceTime - expect float( GetServerVar( "roundStartTime" ) ) - - } - else - { - if ( gameState > eGameState.SuddenDeath ) - return (expect float( GetServerVar( "gameEndTime" ) ) - expect float( GetServerVar( "gameStartTime" ) ) ) - else - return sinceTime - expect float( GetServerVar( "gameStartTime" ) ) - } - - unreachable -} - -float function GameTime_TimeSpentInCurrentState() -{ - return Time() - expect float( GetServerVar( "gameStateChangeTime" ) ) -} - -int function GameScore_GetFirstToScoreLimit() -{ - return expect int( level.firstToScoreLimit ) -} - -bool function GameScore_AllowPointsOverLimit() -{ - return svGlobal.allowPointsOverLimit -} - -int function GameScore_GetWinningTeam() -{ - if ( GameScore_GetFirstToScoreLimit() ) - return GameScore_GetFirstToScoreLimit() - - if ( IsRoundBased() ) - { - if ( GameRules_GetTeamScore2( TEAM_IMC ) > GameRules_GetTeamScore2( TEAM_MILITIA ) ) - return TEAM_IMC - else if ( GameRules_GetTeamScore2( TEAM_MILITIA ) > GameRules_GetTeamScore2( TEAM_IMC ) ) - return TEAM_MILITIA - } - else - { - if ( GameRules_GetTeamScore( TEAM_IMC ) > GameRules_GetTeamScore( TEAM_MILITIA ) ) - return TEAM_IMC - else if ( GameRules_GetTeamScore( TEAM_MILITIA ) > GameRules_GetTeamScore( TEAM_IMC ) ) - return TEAM_MILITIA - } - - return TEAM_UNASSIGNED -} - -int function GameScore_GetWinningTeam_ThisRound() -{ - if ( GameScore_GetFirstToScoreLimit() ) - return GameScore_GetFirstToScoreLimit() - - Assert ( IsRoundBased() ) - - if ( GameRules_GetTeamScore( TEAM_IMC ) > GameRules_GetTeamScore( TEAM_MILITIA ) ) - return TEAM_IMC - else if ( GameRules_GetTeamScore( TEAM_MILITIA ) > GameRules_GetTeamScore( TEAM_IMC ) ) - return TEAM_MILITIA - - return TEAM_UNASSIGNED -} - -#if DEV -void function KillIMC() -{ - array<entity> enemies = GetNPCArrayOfTeam( TEAM_IMC ) - foreach ( enemy in enemies ) - { - enemy.Die() - } -} - -void function killtitans() -{ - printt( "Script command: Kill all titans" ) - array<entity> titans = GetTitanArray() - foreach ( titan in titans ) - titan.Die() -} - -void function killminions() -{ - printt( "Script command: Kill all minions" ) - array<entity> minions = GetAllMinions() - foreach ( minion in minions ) - { - minion.Die() - } -} -#endif - - -array<entity> function GetTeamMinions( int team ) -{ - array<entity> ai = GetNPCArrayByClass( "npc_soldier" ) - ai.extend( GetNPCArrayByClass( "npc_spectre" ) ) - - for ( int i = 0; i < ai.len(); i++ ) - { - if ( ai[i].GetTeam() != team ) - { - ai.remove(i) - i-- - } - } - - return ai -} - -array<entity> function GetAllMinions() -{ - array<entity> ai = GetNPCArrayByClass( "npc_soldier" ) - ai.extend( GetNPCArrayByClass( "npc_spectre" ) ) - ai.extend( GetNPCArrayByClass( "npc_drone" ) ) - - return ai -} - - -bool function GameScore_IsLowScoreDifference() -{ - int winningTeam = GameScore_GetWinningTeam() - - if ( !winningTeam ) - return true - - int losingTeam = GetOtherTeam( winningTeam ) - - int winningTeamScore - int losingTeamScore - - if ( IsRoundBased() ) - { - winningTeamScore = GameRules_GetTeamScore2( winningTeam ) - losingTeamScore = GameRules_GetTeamScore2( losingTeam ) - } - else - { - winningTeamScore = GameRules_GetTeamScore( winningTeam ) - losingTeamScore = GameRules_GetTeamScore( losingTeam ) - } - - return ( winningTeamScore - losingTeamScore < 2 ) -} - -bool function IsFastPilot( entity player ) -{ - Assert( IsPilot( player ), "Pilot only check" ) - - if ( player.IsWallHanging() ) - return false - - if ( player.IsWallRunning() ) - return true - - if ( !player.IsOnGround() ) - return true - - if ( LengthSqr( player.GetSmoothedVelocity() ) > 180*180 || LengthSqr( player.GetVelocity() ) > 180*180 ) - return true - - return false -} - -void function KillPlayer( entity player, int damageSource ) -{ - #if DEV - printt( "Played Killed from script: " ) - DumpStack() - #endif - - Assert( IsAlive( player ) ) - Assert( player.IsPlayer() ) - player.Die( svGlobal.worldspawn, svGlobal.worldspawn, { damageSourceId = damageSource, scriptType=DF_SKIP_DAMAGE_PROT | DF_SKIPS_DOOMED_STATE } ) -} - - -////////////////////////////////////////////////////////// -void function TurretChangeTeam( entity turret, int team ) -{ - if ( team != TEAM_UNASSIGNED ) - { - // If a turret is on some player's team it should never be invulnerable - MakeTurretVulnerable( turret ) - } - - SetTeam( turret, team ) - - // refresh the turret client side particle effects - UpdateTurretClientSideParticleEffects( turret ) -} - -void function MakeTurretInvulnerable( entity turret ) -{ - Assert( IsValid( turret ) ) - turret.SetInvulnerable() - turret.SetNoTarget(true) - turret.SetNoTargetSmartAmmo(true) -} - -void function MakeTurretVulnerable( entity turret ) -{ - Assert( IsValid( turret ) ) - turret.ClearInvulnerable() - turret.SetNoTarget(false) - turret.SetNoTargetSmartAmmo(false) -} - - -void function UpdateTurretClientSideParticleEffects( entity turret ) -{ - if ( !IsValid( turret ) ) - return - - int turretEHandle = turret.GetEncodedEHandle() - array<entity> players = GetPlayerArray() - foreach( player in players ) - { - Remote_CallFunction_Replay( player, "ServerCallback_TurretRefresh", turretEHandle ) - } -} - - - -bool function TakePrimaryWeapon( entity player ) -{ - array<entity> weapons = player.GetMainWeapons() - foreach ( index, weaponEnt in weapons ) - { - int weaponType = weaponEnt.GetWeaponType() - if ( weaponType == WT_SIDEARM || weaponType == WT_ANTITITAN ) - continue; - - string weapon = weaponEnt.GetWeaponClassName() - player.TakeWeaponNow( weapon ) - return true - } - return false -} - -bool function TakeSecondaryWeapon( entity player ) -{ - array<entity> weapons = player.GetMainWeapons() - foreach ( index, weaponEnt in weapons ) - { - if ( weaponEnt.GetWeaponType() != WT_ANTITITAN ) - continue - - string weapon = weaponEnt.GetWeaponClassName() - player.TakeWeaponNow( weapon ) - return true - } - return false -} - -bool function TakeSidearmWeapon( entity player ) -{ - array<entity> weapons = player.GetMainWeapons() - foreach ( index, weaponEnt in weapons ) - { - if ( weaponEnt.GetWeaponType() != WT_SIDEARM ) - continue - - string weapon = weaponEnt.GetWeaponClassName() - player.TakeWeaponNow( weapon ) - return true - } - return false -} - -void function TakeAllWeapons( entity ent ) -{ - if ( ent.IsPlayer() ) - { - ent.RemoveAllItems() - array<entity> weapons = ent.GetMainWeapons() - foreach ( weapon in weapons ) - { - Assert( 0, ent + " still has weapon " + weapon.GetWeaponClassName() + " after doing takeallweapons" ) - } - } - else - { - array<entity> weapons = ent.GetMainWeapons() - TakeWeaponsForArray( ent, weapons ) - - weapons = ent.GetOffhandWeapons() - foreach ( index, weapon in clone weapons ) - { - ent.TakeOffhandWeapon( index ) - } - TakeWeaponsForArray( ent, weapons ) - } -} - - -void function SetSpawnflags( entity ent, int spawnFlags ) -{ - ent.kv.spawnflags = spawnFlags -} - - -void function DestroyAfterDelay( entity ent, float delay ) -{ - Assert( IsNewThread(), "Must be threaded off" ) - - ent.EndSignal( "OnDestroy" ) - - wait( delay ) - - ent.Destroy() -} - -void function UnlockAchievement( entity player, int achievementID ) -{ - Assert( IsValid( player ), "Can't unlock achievement on invalid player entity" ) - Assert( player.IsPlayer(), "Can't unlock achivement on non-player entity" ) - Assert( achievementID > 0 && achievementID < achievements.MAX_ACHIVEMENTS, "Tried to unlock achievement with invalid enum value" ) - - Remote_CallFunction_UI( player, "ScriptCallback_UnlockAchievement", achievementID ) -} - -void function UpdateHeroStatsForPlayer( entity player ) -{ - if ( !IsValid( player ) ) - return - Remote_CallFunction_NonReplay( player, "ServerCallback_UpdateHeroStats" ) -} - -void function TestDeathFall() -{ - entity trigger = GetEntByScriptName( "DeathFallTrigger" ) - table results = WaitSignal( trigger, "OnTrigger" ) - printt( "DEATH FALL TRIGGERED" ) - PrintTable( results ) -} - -bool function PlayerHasTitan( entity player ) -{ - entity titan - if ( player.IsTitan() ) - titan = player - else - titan = player.GetPetTitan() - - if ( IsAlive( titan ) ) - return true - - return false -} |