local SINGLE_TICK = 0.015 if ( !( "_Motherland_EntAdditions" in ROOT ) ) { ::_Motherland_EntAdditions <- class { function SetDestroyCallback( entity, callback ) { local scope = entity.GetScriptScope() || ( entity.ValidateScriptScope(), entity.GetScriptScope() ) scope.setdelegate( {}.setdelegate( { parent = scope.getdelegate() id = entity.GetScriptId() index = entity.entindex() callback = callback function _get ( k ) { return parent[k] } function _delslot ( k ) { if ( k == id ) { entity = EntIndexToHScript( index ) local scope = entity.GetScriptScope() scope.self <- entity callback.pcall( scope ) } delete parent[k] } } ) ) } Precache = { //mini-sentry spawnflag function obj_sentrygun ( ent, spawnflags ) { if ( spawnflags & 64 ) SetPropBool( ent, "m_bMiniBuilding", true ) } } OnPostSpawn = { //non-solid spawnflag function func_button ( ent, spawnflags ) { if ( spawnflags & 16384 ) { ent.AddEFlags( EFL_USE_PARTITION_WHEN_NOT_SOLID ) ent.AddSolidFlags( FSOLID_NOT_SOLID ) } } function func_rot_button ( ent, spawnflags ) { //fix broken locked spawnflag if ( spawnflags & SF_BUTTON_LOCKED ) SetPropBool( ent, "m_bLocked", true ) } //mini-sentry spawnflag function obj_sentrygun ( ent, spawnflags ) { if ( spawnflags & 64 ) { ent.SetModelScale( 0.75, 0.0 ) ent.SetSkin( ent.GetSkin() + 2 ) } } //fix invulnerable flag not working function obj_dispenser ( ent, spawnflags ) { if ( spawnflags & 2 ) SetPropInt( ent, "m_takedamage", 0 ) } //start disabled spawnflag function light_dynamic ( ent, spawnflags ) { if ( spawnflags & 16 ) ent.AcceptInput( "TurnOff", "", null, null ) } //fix func_rotating capping at 360,000 degrees //fix killing func_rotating before stopping sound causing sound to play forever function func_rotating ( ent, spawnflags ) { local maxangle = 350000.0 //max angle is actually 360,000.0, reset it a bit earlier just in case local xyz = array( 3, 0.0 ) local scope = ent.GetScriptScope() || ( ent.ValidateScriptScope(), ent.GetScriptScope() ) function RotateFixThink() { for ( local i = 0; i < 3; i++ ) { xyz[i] = GetPropFloat( ent, format( "m_angRotation[%d]", i ) ) if ( xyz[i] == 0.0 || xyz[i] < maxangle ) continue xyz[i] %= 360.0 // xyz[i] = 0; //jitter on reset ent.SetLocalAngles( QAngle( xyz[0], xyz[1], xyz[2] ) ) break } return -1 } AddThinkToEnt( ent, "RotateFixThink" ) scope.RotateFixThink <- RotateFixThink scope.noise <- GetPropString( ent, "m_NoiseRunning" ) _Motherland_EntAdditions.SetDestroyCallback( ent, @() StopAmbientSoundOn( self.GetScriptScope().noise, self ) ) } // add spawnflag to apply to all players // add spawnflag to allow for taking damage // fix not being able to disable on dead players // fix persisting between map/round changes function point_viewcontrol ( ent, spawnflags ) { function InputEnable() { if ( !ent || !ent.IsValid() ) return true if ( spawnflags & 512 ) { local takedamage = GetPropInt( activator, "m_takedamage" ) SetPropEntity( ent, "m_hPlayer", null ) EntFireByHandle( activator, "RunScriptCode", format( "SetPropInt( self, `m_takedamage`, %d )", takedamage ), SINGLE_TICK, null, null ) } if ( ent.IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) return true if ( spawnflags & 256 ) { ent.AddEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ) for ( local i = 1, player; i <= MAX_CLIENTS; player = PlayerInstanceFromIndex( i ), i++ ) { if ( player && player.IsValid() ) { ent.AcceptInput( "Enable", "", player, player ) SetPropEntity( ent, "m_hPlayer", player ) } } ent.RemoveEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ) } return true } function InputDisable() { if ( !ent || !ent.IsValid() || ent.IsEFlagSet( EFL_IS_BEING_LIFTED_BY_BARNACLE ) ) return true if ( !activator.IsAlive() ) { SetPropEntity( ent, "m_hPlayer", activator ) local life_state = GetPropInt( activator, "m_lifeState" ) SetPropInt( activator, "m_lifeState", LIFE_ALIVE ) EntFireByHandle( activator, "RunScriptCode", format( "SetPropInt( self, `m_lifeState`, %d )", life_state ), SINGLE_TICK, null, null ) } if ( spawnflags & 256 ) { ent.AddEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ) for ( local i = 1, player; i <= MAX_CLIENTS; player = PlayerInstanceFromIndex( i ), i++ ) { if ( player && player.IsValid() ) { SetPropEntity( ent, "m_hPlayer", player ) local life_state = GetPropInt( player, "m_lifeState" ) SetPropInt( player, "m_lifeState", LIFE_ALIVE ) ent.AcceptInput( "Disable", "", player, player ) EntFireByHandle( player, "RunScriptCode", format( "SetPropInt( self, `m_lifeState`, %d )", life_state ), SINGLE_TICK, null, null ) } } ent.RemoveEFlags( EFL_IS_BEING_LIFTED_BY_BARNACLE ) } return true } local scope = ent.GetScriptScope() || ( ent.ValidateScriptScope(), ent.GetScriptScope() ) scope.InputEnable <- InputEnable scope.Inputenable <- InputEnable scope.InputDisable <- InputDisable scope.Inputdisable <- InputDisable } //fix TeamNum not working //fix FireSound not working, added volume setting ( example: "sound_name_here.wav|40" ) //fix ModelScale not working on arrows/rockets function tf_point_weapon_mimic ( ent, spawnflags ) { local particle = CreateByClassname( "trigger_particle" ) local scope = ent.GetScriptScope() || ( ent.ValidateScriptScope(), ent.GetScriptScope() ) local modelscale = GetPropFloat( ent, "m_flModelScale" ) local firesound = GetPropString( ent, "m_pzsFireSound" ) function ProjectileFixes() { for ( local projectile; projectile = FindByClassnameWithin( projectile, "tf_projectile*", ent.GetOrigin(), 1 ); ) { if ( projectile.GetEFlags() & EFL_NO_MEGAPHYSCANNON_RAGDOLL ) continue if ( modelscale != 1 ) projectile.SetModelScale( modelscale, 0.0 ) if ( firesound != "" ) { local vol = 1.0 if ( firesound.find( "|" ) ) { local split = split( firesound, "|" ) firesound = split[0] vol = split[1].tofloat() } EmitSoundEx( {sound_name = firesound, entity = ent, volume = vol} ) } projectile.SetTeam( ent.GetTeam() ) if ( startswith( projectile.GetClassname(), "tf_projectile_pipe" ) ) { projectile.SetSkin( ent.GetTeam() - 2 ) projectile.AcceptInput( "DispatchEffect", "ParticleEffectStop", null, null ) local particlename = "" projectile.GetTeam() < 3 ? particlename = "pipebombtrail_red" : particlename = "pipebombtrail_blue" particle.KeyValueFromString( "particle_name", particlename ) particle.KeyValueFromInt( "attachment_type", PATTACH_ABSORIGIN_FOLLOW ) particle.KeyValueFromInt( "spawnflags", SF_TRIGGER_ALLOW_ALL ) DispatchSpawn( particle ) EntFireByHandle( particle, "StartTouch", "!activator", -1, projectile, projectile ) if ( GetPropBool( ent, "m_bCrits" ) ) { local particlecrits = projectile.GetTeam() < 3 ? "critical_pipe_red" : "critical_pipe_blue" particle.KeyValueFromString( "particle_name", particlecrits ) EntFireByHandle( particle, "StartTouch", "!activator", -1, projectile, projectile ) } } projectile.AddEFlags( EFL_NO_MEGAPHYSCANNON_RAGDOLL ) } return -1 } scope.ProjectileFixes <- ProjectileFixes AddThinkToEnt( ent, "ProjectileFixes" ) } } Events = { function OnGameEvent_recalculate_holidays( _ ) { if ( GetRoundState() == GR_STATE_GAME_OVER ) EntFire( "player", "RunScriptCode", "DoEntFire( `point_viewcontrol`, `Disable`, ``, -1, self, self )" ) } function OnGameEvent_round_start( _ ) { EntFire( "player", "RunScriptCode", "DoEntFire( `point_viewcontrol`, `Disable`, ``, -1, self, self )" ) } function OnGameEvent_teamplay_round_start( _ ) { EntFire( "player", "RunScriptCode", "DoEntFire( `point_viewcontrol`, `Disable`, ``, -1, self, self )" ) } } } __CollectGameEventCallbacks( _Motherland_EntAdditions.Events ) } function Precache() { local classname = self.GetClassname() local spawnflags = GetPropInt( self, "m_spawnflags" ) if ( classname in _Motherland_EntAdditions.Precache ) _Motherland_EntAdditions.Precache[classname]( self, spawnflags ) } function OnPostSpawn() { local classname = self.GetClassname() local spawnflags = GetPropInt( self, "m_spawnflags" ) if ( classname in _Motherland_EntAdditions.OnPostSpawn ) _Motherland_EntAdditions.OnPostSpawn[classname]( self, spawnflags ) }