timer.Simple( 1, function() print("Version: 42") -- servers take a while to load anymore, so I do this to let me know when its updated end) local FrostBite_Enabled = false local FrostBite_Max = 300 local FrostBite_UpdateRate = 0.1 -- runs every 7 ticks local FrostBite_DamageRate = 0.5 -- for some reason not accurate, about 2.5-4 seconds local FrostBite_OutsideGain = 0.75 -- 40 seconds to hit max frostbite | baseline value local FrostBite_InsideReduction = 3 -- 13 seconds to emtpy frostbite meter | this value gets subtracted from FrostBite_OutsideGain as a base local FrostBite_InsideSpawnReduction = 6 -- 6 seconds to emtpy frostbite meter | this value gets subtracted from FrostBite_OutsideGain as a base local FrostBite_BarrelFireReduction = 1.5 -- 40 seconds to emtpy frostbite meter | this value gets subtracted from FrostBite_OutsideGain as a base local FrostBite_FireReduction = 0.34 -- Being near 1 burning robot reduces frostbite gain by this much, stacks with other burning robots | 3 needed to break even | this value gets subtracted from FrostBite_OutsideGain as a base local FrostBite_FireRatePenalty = 1.5 local FrostBite_ReloadPenalty = 1.6 local FrostBite_DamageThreshold = 0.75 local FrostBite_DamageMin = 2 local FrostBite_DamageMax = 16 local FrostBite_BarrelFireRange = 200 local FrostBite_BarrelFireCloseRange = 150 local FrostBite_FireRange = 192 local Leap_Power = 800 local MISC_Update_Delay = CurTime() function IsValidAlivePlayer(ent) return IsValid(ent) and ent:IsPlayer() and ent:IsAlive(); end CEntity.IsMidair = function(self) if (IsValidAlivePlayer(self)) then return not (self.movetype == MOVETYPE_WALK and (self.m_fFlags & FL_ONGROUND ~= 0)); end end CEntity.GetEyeAngles = function(self) if (IsValidAlivePlayer(self)) then return Vector( self.m_angEyeAngles[1], self.m_angEyeAngles[2], 0 ) end end CEntity.GetPlayerVelocity = function(self) if (IsValidAlivePlayer(self)) then return self.m_vecAbsVelocity end end CEntity.SetPlayerVelocity = function(self, vel) if (IsValidAlivePlayer(self)) then self.m_vecAbsVelocity = vel end end function IsValidPlayer(ent) return IsValid(ent) and ent:IsPlayer(); end CEntity.GetEyePos = function(self) if (not IsValidPlayer(self)) then return; end local eyepos = self:GetAbsOrigin(); eyepos.z = eyepos.z + self["m_vecViewOffset[2]"]; return eyepos end CEntity.HasLineOfSight = function( self, tar ) if self and tar then local ignore_tbl = { self, tar } for _, ply in pairs(ents.GetAllPlayers()) do table.insert(ignore_tbl, ply) end local Trace = util.Trace({ start = self:GetAbsOrigin() + Vector(0,0,16), endpos = tar:GetEyePos(), mask = MASK_SOLID, filter = ents.GetAllPlayers() }) local Trace2 = util.Trace({ start = self:GetAbsOrigin(), endpos = tar:GetAbsOrigin(), mask = MASK_SOLID, filter = ents.GetAllPlayers() }) if ( not Trace.Hit ) or ( not Trace2.Hit ) then return true else return false end end end math.Clamp = function( value, min, max ) if min and max then if min > max then min, max = max, min end if value > max then value = max end if min > value then value = min end return value elseif min and ( not max ) then return math.min( value ) elseif max and ( not min ) then return math.max( value ) end end math.round = function(num, decimals) if (not decimals or decimals <= 0) then return math.floor(num + 0.5) else local mod = 10 ^ decimals return math.floor((num * mod) + 0.5) / mod end end math.remap = function( value, inMin, inMax, outMin, outMax ) return outMin + ( ( ( value - inMin ) / ( inMax - inMin ) ) * ( outMax - outMin ) ) end function lerp(start, goal, exp) return start + (goal - start) * exp end function LunchBreak(taunt, activator) if taunt == "scenes/player/heavy/low/taunt04.vcd" then for _, player in pairs(ents.FindInSphere(activator:GetAbsOrigin(),512)) do if player:IsRealPlayer() and ( player.m_iTeamNum == 2 ) then player:AddCond( TF_COND_RADIUSHEAL_ON_DAMAGE , 4.3, activator) end end end end function FrostBite_Enable() FrostBite_Enabled = true end function FrostBite_Disable() FrostBite_Enabled = false end function FrostBite_Add( tar, amount ) if tar and amount then if ( tar:GetPlayerItemBySlot(2):GetAttributeValue( "wrench index" ) or 0 ) == 2 then amount = amount * 0.5 end tar.FrostBite_Buildup = math.Clamp( tar.FrostBite_Buildup + amount, 0, FrostBite_Max ) end end function OnWaveInit(wave) timer.Simple(0.5, function() ents.FindByName("indoor_warehouse"):AddCallback( ON_START_TOUCH, function(_, player) player.FrostBite_Indoors = true player.FrostBite_IndoorsSpawn = false end) ents.FindByName("indoor_warehouse"):AddCallback( ON_END_TOUCH, function(_, player) player.FrostBite_Indoors = false end) ents.FindByName("indoor_shack"):AddCallback( ON_START_TOUCH, function(_, player) player.FrostBite_Indoors = true player.FrostBite_IndoorsSpawn = false end) ents.FindByName("indoor_shack"):AddCallback( ON_END_TOUCH, function(_, player) player.FrostBite_Indoors = false end) ents.FindByName("indoor_upgrade"):AddCallback( ON_START_TOUCH, function(_, player) player.FrostBite_Indoors = true player.FrostBite_IndoorsSpawn = false end) ents.FindByName("indoor_upgrade"):AddCallback( ON_END_TOUCH, function(_, player) player.FrostBite_Indoors = false end) ents.FindByName("indoor_spawn"):AddCallback( ON_START_TOUCH, function(_, player) player.FrostBite_Indoors = true player.FrostBite_IndoorsSpawn = true end) ents.FindByName("indoor_spawn"):AddCallback( ON_END_TOUCH, function(_, player) player.FrostBite_Indoors = false player.FrostBite_IndoorsSpawn = false end) end) end function OnGameTick() for _, player in pairs( ents.GetAllPlayers() ) do if player:IsRealPlayer() then if ( player.m_iTeamNum ~= 1 ) and ( player:IsAlive() ) then if ( player.Pouncing ) and ( player:IsMidair() ) then player:SetAttributeValue( "damage force reduction", 0.25 ) player:SetAttributeValue( "damage bonus hidden", 1.5 ) player:SetAttributeValue( "increased air control", 2 ) elseif ( player.Pouncing ) and ( not player:IsMidair() ) then timer.Simple(0.1, function() --delay so that fall dmg reduction can work, and also as a feel good delay player.Pouncing = false end) elseif ( not player.Pouncing ) and ( not player:IsMidair() ) then player:SetAttributeValue( "damage force reduction", nil ) player:SetAttributeValue( "damage bonus hidden", nil ) player:SetAttributeValue( "increased air control", nil ) end if ( player:IsMidair() ) and ( ( player:GetPlayerItemBySlot(2):GetAttributeValue("wrench index") or 0 ) == 3 ) and ( CurTime() >= player.Leap_Recharge ) then player:GetPlayerItemBySlot(2):SetAttributeValue( "alt-fire disabled", 1 ) else player:GetPlayerItemBySlot(2):SetAttributeValue( "alt-fire disabled", nil ) end local damage local percent if ( CurTime() >= player.FrostBite_Delay ) then -- doing speedboost checks here for performance for _, fire in pairs( ents.FindInSphere( player:GetAbsOrigin(), FrostBite_BarrelFireRange, "env_fire" ) ) do if fire:IsValid() and ( ( player:GetPlayerItemBySlot(2):GetAttributeValue("wrench index") or 0 ) == 1 ) and ( fire:HasLineOfSight( player ) ) then player:AddCond( TF_COND_SPEED_BOOST, 3 ) end end for _, burning_ply in pairs( ents.FindInSphere( player:GetAbsOrigin(), FrostBite_BarrelFireRange ) ) do if burning_ply:IsValid() and burning_ply:IsPlayer() then if burning_ply:InCond( TF_COND_BURNING ) and ( burning_ply.m_iTeamNum ~= 1 ) and ( burning_ply:IsAlive() ) and ( ( player:GetPlayerItemBySlot(2):GetAttributeValue("wrench index") or 0 ) == 1 ) then player:AddCond( TF_COND_SPEED_BOOST, 3 ) end if burning_ply:InCond( TF_COND_AIMING ) and ( burning_ply.m_iTeamNum ~= 1 ) and ( burning_ply:IsAlive() ) and ( ( burning_ply:GetPlayerItemBySlot(0):GetAttributeValue("ring of fire while aiming", true ) or 0 ) > 0 ) and ( ( player:GetPlayerItemBySlot(2):GetAttributeValue("wrench index") or 0 ) == 1 ) then player:AddCond( TF_COND_SPEED_BOOST, 3 ) end end end if ( FrostBite_Enabled ) then player.FrostBite_Delay = CurTime() + FrostBite_UpdateRate player.FrostBite_Gain = FrostBite_OutsideGain -- set this as a baseline if ( player:GetPlayerItemBySlot(2):GetAttributeValue( "wrench index" ) or 0 ) == 2 then player.FrostBite_Gain = player.FrostBite_Gain * 0.5 end if player.FrostBite_Indoors then if player.FrostBite_IndoorsSpawn then player.FrostBite_Gain = player.FrostBite_Gain - FrostBite_InsideSpawnReduction else player.FrostBite_Gain = player.FrostBite_Gain - FrostBite_InsideReduction end end for _, fire in pairs( ents.FindInSphere( player:GetAbsOrigin(), FrostBite_BarrelFireRange, "env_fire" ) ) do if fire:IsValid() and ( fire:HasLineOfSight( player ) ) then player.FrostBite_Gain = player.FrostBite_Gain - FrostBite_BarrelFireReduction end if fire:GetAbsOrigin():Distance( player:GetAbsOrigin() ) <= FrostBite_BarrelFireCloseRange and ( fire:HasLineOfSight( player ) ) then player.FrostBite_Gain = player.FrostBite_Gain - FrostBite_BarrelFireReduction end end for _, burning_ply in pairs( ents.FindInSphere( player:GetAbsOrigin(), FrostBite_BarrelFireRange ) ) do if burning_ply:IsValid() and burning_ply:IsPlayer() then if burning_ply:InCond( TF_COND_BURNING ) and ( burning_ply.m_iTeamNum ~= 1 ) and ( burning_ply:IsAlive() ) then player.FrostBite_Gain = player.FrostBite_Gain - FrostBite_FireReduction end if burning_ply:InCond( TF_COND_AIMING ) and ( burning_ply.m_iTeamNum ~= 1 ) and ( burning_ply:IsAlive() ) and ( ( burning_ply:GetPlayerItemBySlot(0):GetAttributeValue("ring of fire while aiming", true ) or 0 ) > 0 ) then player.FrostBite_Gain = player.FrostBite_Gain - ( FrostBite_FireReduction * ( ( burning_ply:GetPlayerItemBySlot(0):GetAttributeValue("ring of fire while aiming", true ) or 0 ) / 12 ) ) end end end player.FrostBite_Buildup = math.Clamp( player.FrostBite_Buildup + player.FrostBite_Gain, 0, FrostBite_Max ) percent = ( player.FrostBite_Buildup / FrostBite_Max ) local fire_rate = lerp( 1, FrostBite_FireRatePenalty, percent ) local reload = lerp( 1, FrostBite_ReloadPenalty, percent ) if percent >= FrostBite_DamageThreshold then damage = lerp( FrostBite_DamageMin, FrostBite_DamageMax, percent ) end player:SetAttributeValue( "fire rate penalty", fire_rate) player:SetAttributeValue( "reload time increased", reload) player:ShowHudText({channel = 5, y = 0.85, x = -0.72, r1 = 115, r2 = 115, g1 = 181, g2 = 181, b1 = 217, b2 = 217, effect = 1, fixTime = 0, fadeinTime = 0, fadeoutTime = 0.5, holdTime = FrostBite_UpdateRate * 2}, "Frostbite: " .. tostring( math.round( percent * 100, 0 ) ) .. "%" ) else player:SetAttributeValue( "fire rate penalty", nil ) player:SetAttributeValue( "reload time increased", nil ) end -- ▰ (filled) | ▱ (not filled) if ( player:GetPlayerItemBySlot(2):GetAttributeValue("wrench index") or 0 ) == 3 then local text_length = 12 local message = "Pounce! " local color = { 200, 50, 50 } if CurTime() >= player.Leap_Recharge then color = { 50, 200, 50 } for i = 1, text_length do message = message .. "▰" end message = message .. " READY" if not player.Leap_Recharged_SND then player:PlaySoundToSelf("TFPlayer.ReCharged") player.Leap_Recharged_SND = true end else color = { 200, 50, 50 } local time_remaining = player.Leap_Recharge - CurTime() local time_remaining_percent = time_remaining / player.Leap_Recharge_Dur local message_percent = 1.0 / text_length local recharge_meter = math.ceil( time_remaining_percent / message_percent ) for i = 1, ( text_length - recharge_meter ) do message = message .. "▰" text_length = text_length - 1 end for i = 1, text_length do message = message .. "▱" end end player:ShowHudText({channel = 2, y = 0.6, x = -0.855 + ( string.len( message ) / 106 ), r1 = color[1], r2 = color[1], g1 = color[2], g2 = color[2], b1 = color[3], b2 = color[3], effect = 1, fixTime = 0, fadeinTime = 0, fadeoutTime = 5, holdTime = MISC_Update_Delay * 2}, message ) end end if ( CurTime() >= player.FrostBite_DamageDelay ) and ( FrostBite_Enabled ) then local dmginfo = { Attacker = player, Damage = damage, DamageType = DMG_SHOCK | DMG_PREVENT_PHYSICS_FORCE } player:TakeDamage( dmginfo ) player.FrostBite_DamageDelay = CurTime() + FrostBite_DamageRate end end end end end function OnPlayerConnected(player) if player:IsRealPlayer() then player.FrostBite_Buildup = 0 player.FrostBite_Gain = 0 player.FrostBite_Delay = CurTime() player.FrostBite_DamageDelay = CurTime() player.FrostBite_IndoorsSpawn = true player.FrostBite_Indoors = true player.Leap_Recharge_Dur = 5 player.Leap_Recharge = 3 player.Pouncing = false player.Leap_Recharged_SND = false player:AddCallback( ON_SPAWN, function( ent ) ent.FrostBite_Buildup = 0 ent.FrostBite_Gain = 0 ent.FrostBite_Delay = CurTime() ent.FrostBite_DamageDelay = CurTime() ent.FrostBite_IndoorsSpawn = true ent.FrostBite_Indoors = true player.Leap_Recharge_Dur = 5 player.Leap_Recharge = 3 player.Pouncing = false player.Leap_Recharged_SND = false end) player:AddCallback( ON_KEY_PRESSED, function( ent, key ) if ( key == IN_ATTACK2 ) and ( ( ent.m_hActiveWeapon:GetAttributeValue("wrench index") or 0 ) == 3 ) and ( ent:IsMidair() ) then if CurTime() >= ent.Leap_Recharge then ent.Leap_Recharge = CurTime() + ent.Leap_Recharge_Dur ent.Pouncing = true ent.Leap_Recharged_SND = false local eye_angle = ent:GetEyeAngles():GetForward() local velocity = Vector( Leap_Power, Leap_Power, Leap_Power ) * eye_angle ent:SetPlayerVelocity( ent:GetPlayerVelocity() + velocity ) ent:AcceptInput("RunScriptCode", "EmitSoundOn(`Heavy.Pounce`,self)" ) end end end) end player:AddCallback(ON_DAMAGE_RECEIVED_PRE, function(ent, dmginfo) --kgb honorbound if ent:IsValid() and dmginfo.Attacker:IsValid() and ent:IsPlayer() and dmginfo.Attacker:IsPlayer() and ( ent ~= dmginfo.Attacker ) and ( ent.m_iTeamNum ~= 1 ) and ( dmginfo.Damage >= 20 ) then -- teamnum 1 is spectators local attacker = dmginfo.Attacker if ( ent.m_hActiveWeapon ) and ( ent.m_hActiveWeapon:IsValid() ) and ( ( ent.m_hActiveWeapon:GetItemName() == "The Killing Gloves of Boxing" ) and ( attacker.m_hActiveWeapon:GetItemName() == "The Killing Gloves of Boxing" ) ) and ( ( ent:GetPlayerItemBySlot(2):GetAttributeValue("honorbound") == 1 ) or ( attacker:GetPlayerItemBySlot(2):GetAttributeValue("honorbound") == 1 ) ) then if ent.m_bIsMiniBoss == 1 then dmginfo.Damage = 500 else dmginfo.Damage = ent.m_iHealth * 5 end if attacker:IsBot() and attacker.m_bIsMiniBoss == 0 then timer.Simple(0.2, function() attacker:Taunt("TAUNT_BASE_WEAPON", 0) end) end return true end end if ent:IsValid() and ent:IsRealPlayer() and ( FrostBite_Enabled ) and ( ( dmginfo.DamageType & DMG_IGNITE ) == DMG_IGNITE ) then -- The ' & ' opperator is the bitwise and, complex shit but it makes the messy damage types (268435464 for example) into something more checkable like 268435456 (DMG_DIRECT) ent.FrostBite_Buildup = math.Clamp( player.FrostBite_Buildup - ( dmginfo.Damage / 4 ), 0, FrostBite_Max ) end if ent:IsValid() and ent:IsRealPlayer() and ( ( dmginfo.DamageType & DMG_FALL ) == DMG_FALL ) and ( ent.Pouncing ) then dmginfo.Damage = dmginfo.Damage * 0.5 return true end end) end function ChristmasPunch(damage, activator, caller) --activator is the one with the weapon, caller is the one that got hit util.ParticleEffect("xms_snowburst", caller:GetAbsOrigin() + Vector(0,0,48)) caller:PlaySound("xmas.jingle_noisemaker") if caller:IsPlayer() then for _, player in pairs(ents.FindInSphere(caller:GetAbsOrigin(),128)) do if damage > 300 then if activator.m_iTeamNum ~= player.m_iTeamNum and (player:IsPlayer()) then --not same team if player.m_bIsMiniBoss == 0 then player:StunPlayer(6, 0.9, TF_STUNFLAGS_LOSERSTATE, activator) else player:StunPlayer(2, 0.9, TF_STUNFLAGS_LOSERSTATE, activator) end end else if activator.m_iTeamNum ~= player.m_iTeamNum and (player:IsPlayer()) then --not same team if player.m_bIsMiniBoss == 0 then player:StunPlayer(3, 0.67, TF_STUNFLAG_SLOWDOWN, activator) else player:StunPlayer(1, 0.75, TF_STUNFLAG_SLOWDOWN, activator) end end end end end end function FrostBite_Freeze(damage, activator, caller) --activator is the one with the weapon, caller is the one that got hit if caller:IsRealPlayer() and caller:IsAlive() and ( caller.m_iTeamNum ~= 1 ) then local amount = activator.m_hActiveWeapon:GetAttributeValue("tag__eotlearlysupport") FrostBite_Add( caller, amount ) end end function SecondLife(taunt, activator) if (not IsValid(activator) or not activator:IsAlive()) then return end if taunt == "scenes/player/heavy/low/taunt04.vcd" then timer.Simple(1.2, function() for _, reanimator in pairs(ents.FindInSphere(activator:GetAbsOrigin(), 200)) do if reanimator:GetClassname() == "entity_revive_marker" then if reanimator:HasLineOfSight( activator ) then reanimator.m_hOwner:ForceRespawnDead() reanimator.m_hOwner:PlaySoundToSelf( "mvm/mvm_revive.wav" ) reanimator.m_hOwner:SpeakResponseConcept( "TLK_RESURRECTED" ) reanimator.m_hOwner:Teleport( activator:GetAbsOrigin() ) reanimator.m_hOwner:AddCond( 51, 2 ) reanimator.m_hOwner.m_flItemChargeMeter[2] = 50 --start lunchbox items at 50% charge, to avoid chain bananas activator:PlaySoundToSelf( "mvm/mvm_revive.wav" ) activator.m_flItemChargeMeter[2] = 0 activator:StunPlayer( 0.2, 1, TF_STUNFLAG_BONKSTUCK ) if not ( ( activator:GetPlayerItemBySlot(1):GetAttributeValue( "ragdolls plasma effect" ) or 0 ) == 1 ) then break else activator.m_iHealth = math.min( activator.m_iHealth + 50, activator.m_iMaxHealth ) end end end end end) end end