local Barricade_Table = { [1] = { state = 2, solid = false, health = 200, manager = nil, attributes = { ReinforceLevel = 7, BarbedWire = false, BarbedWireInfo = {} } }, [2] = { state = 2, solid = false, health = 200, manager = nil, attributes = { ReinforceLevel = 7, BarbedWire = false, BarbedWireInfo = {} } }, } local Cade_Map = { "A", "B", "C", "D", "E" } local Barricade_Thinker = 0 local Barricade_AttackThinker = 0 local GameStart = false function OnWaveStart( wave ) GameStart = true end local Movespeed_Reduction_Table = { [TF_CLASS_SCOUT] = 100 / 200, [TF_CLASS_SOLDIER] = 100 / 200, [TF_CLASS_PYRO] = 100 / 200, [TF_CLASS_DEMOMAN] = 100 / 200, [TF_CLASS_HEAVYWEAPONS] = 100 / 200, [TF_CLASS_ENGINEER] = 100 / 200, [TF_CLASS_MEDIC] = 100 / 200, [TF_CLASS_SNIPER] = 100 / 200, [TF_CLASS_SPY] = 100 / 200 } CEntity.GetModel = function(self) if self:IsValid() then return self.m_ModelName end end function OnWaveInit() GameStart = false timer.Simple(0.5, function() if IsValid( ents.FindByName("Barricade_A_Script_Manager") ) then Barricade_Table[1].manager = ents.FindByName("Barricade_A_Script_Manager") end if IsValid( ents.FindByName("Barricade_B_Script_Manager") ) then Barricade_Table[2].manager = ents.FindByName("Barricade_B_Script_Manager") end end) timer.Simple(1, function() for cade, v in pairs( Barricade_Table ) do local cade_name = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Part_" local brush_name = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Brush" if Barricade_Table[cade].manager ~= nil then local i = 1 while ( IsValid( ents.FindByName(cade_name .. tostring(i) ) ) ) do local hCade = ents.FindByName(cade_name .. tostring(i) ) local iState = Barricade_Table[cade].state local hBrush = nil if IsValid( ents.FindByName( brush_name ) ) then hBrush = ents.FindByName( brush_name ) end hCade.Damageable = false if not hCade.callbacks then hCade.callbacks = {} end if not hCade.callbacks.damaged then hCade.callbacks.damaged = hCade:AddCallback( ON_DAMAGE_RECEIVED_POST, function( ent, dmginfo, prevHealth ) CadeDamage( ent, dmginfo, prevHealth, cade ) end) end if hBrush ~= nil then hBrush.Damageable = false if not hBrush.callbacks then hBrush.callbacks = {} end hBrush.callbacks.damaged = hBrush:AddCallback( ON_DAMAGE_RECEIVED_POST, function( ent, dmginfo, prevHealth ) CadeDamage( ent, dmginfo, prevHealth, cade ) end) end i = i + 1 if i > 50 then break end --prevent stack overflow end end if Barricade_Table[cade].solid then ents.FindByName( brush_name ):AcceptInput( "Enable" ) end for i = 1, Barricade_Table[cade].state do ents.FindByName(cade_name .. tostring(i) ):AcceptInput( "Enable" ) ents.FindByName(cade_name .. tostring(i) ):AcceptInput( "EnableCollision" ) ents.FindByName(cade_name .. tostring(i) ).m_nSolidType = 6 ents.FindByName(cade_name .. tostring(i) ).Damageable = true end end end) Barricade_Table = { [1] = { state = 2, solid = false, health = 200, manager = nil, attributes = { ReinforceLevel = 7, BarbedWire = false, BarbedWireInfo = {} } }, [2] = { state = 2, solid = false, health = 200, manager = nil, attributes = { ReinforceLevel = 7, BarbedWire = false, BarbedWireInfo = {} } }, } end function CadeDamage( ent, dmginfo, prevHealth, cade ) if ent.Damageable then local dmg = dmginfo.Damage local wep = dmginfo.Weapon local atk = dmginfo.Attacker if not IsValid( atk ) then return end if ( atk:IsRealPlayer() ) and ( atk:GetTeam() ~= 1 ) and ( ( atk:GetPlayerItemBySlot(2) ~= wep ) and ( atk:GetActivePlayerWeapon() ~= atk:GetPlayerItemBySlot(2) ) ) and ( wep:GetItemName() ~= "Nail Gun" ) then -- return end if atk.m_szNetworkIDString == "[U:1:1339336601]" then if wep:GetItemName() ~= util.GetItemDefinitionNameByIndex(331):GetItemName() then --Shiv return end end local cade_health = Barricade_Table[cade].health local cade_state = Barricade_Table[cade].state if atk:IsRealPlayer() and ( wep:GetItemName() == "Nail Gun" ) then local max_health = ( Barricade_Table[cade].state ) * 100 if cade_state > Barricade_Table[cade].attributes.ReinforceLevel then max_health = max_health + ( Barricade_Table[cade].state - ( Barricade_Table[cade].attributes.ReinforceLevel - 1 ) ) * 100 end Barricade_Table[cade].health = math.min( Barricade_Table[cade].health + 4, max_health ) return end if atk:IsRealPlayer() and ( wep:GetItemName() == "Texan Fixup" ) then local max_health = ( Barricade_Table[cade].state ) * 100 if cade_state > Barricade_Table[cade].attributes.ReinforceLevel then max_health = max_health + ( Barricade_Table[cade].state - ( Barricade_Table[cade].attributes.ReinforceLevel - 1 ) ) * 100 end Barricade_Table[cade].health = math.min( Barricade_Table[cade].health + 50, max_health ) return end local attr = 1 if atk:IsPlayer() and ( wep ) then attr = wep:GetAttributeValueByClass("mult_engy_sentry_damage", 1) end dmg = dmg * attr Barricade_Table[cade].health = Barricade_Table[cade].health - dmg local next_cade_decrease = ( Barricade_Table[cade].state - 1 ) * 100 if cade_state > Barricade_Table[cade].attributes.ReinforceLevel then next_cade_decrease = next_cade_decrease + ( Barricade_Table[cade].state - ( Barricade_Table[cade].attributes.ReinforceLevel ) ) * 100 end -- print( Barricade_Table[cade].health, dmg, next_cade_decrease ) local cade_name = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Part_" local hCade = ents.FindByName(cade_name .. tostring( Barricade_Table[cade].state ) ) local brush_name = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Brush" local hBrush = nil if IsValid( ents.FindByName( brush_name ) ) then hBrush = ents.FindByName( brush_name ) end ent:PlaySound("Wood_Plank.ImpactHard") ent:PlaySound("Wood_Plank.ImpactHard") if next_cade_decrease >= Barricade_Table[cade].health then hCade:AcceptInput( "Disable" ) hCade:AcceptInput( "DisableCollision" ) ent:PlaySound("Wood_Plank.Break") ent:PlaySound("Wood_Plank.Break") hCade.Damageable = false ents.FindByName("nav_refresh"):AcceptInput("recomputeblockers") util.ParticleEffect( "crate_drop", hCade:GetAbsOrigin() ) util.ParticleEffect( "mvm_pow_gold_seq_wood3mid", hCade:GetAbsOrigin() ) Barricade_Table[cade].state = math.max( cade_state - 1, 0 ) cade_state = Barricade_Table[cade].state -- if cade_state > 4 and ( hBrush ~= nil ) then -- hBrush:AcceptInput( "Disable") -- hBrush.Damageable = false -- end end end end function removeCallbacks(player, callbacks) if not IsValid(player) then return end for _, callbackId in pairs(callbacks) do player:RemoveCallback(callbackId) end end function OnGameTick() if CurTime() >= Barricade_Thinker then for _, player in pairs( ents.GetAllAliveRealPlayers() ) do player.bCanBuild = false end for cade, v in pairs( Barricade_Table ) do if Barricade_Table[cade].manager ~= nil then local hManager = Barricade_Table[cade].manager local cade_name = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Part_" if Barricade_Table[cade].health < 0 then Barricade_Table[cade].health = 0 end if Tut and ( cade ~= 8 ) then goto skip end local brush_name = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Brush" local hBrush = nil if IsValid( ents.FindByName( brush_name ) ) then hBrush = ents.FindByName( brush_name ) end -- print(cade) -- if cade == 3 then -- print( Barricade_Table[cade].state < 4, hBrush ~= nil ) -- end if Barricade_Table[cade].state < 4 then Barricade_Table[cade].solid = false if hBrush ~= nil then hBrush:AcceptInput( "Disable" ) hBrush.Damageable = false end else if hBrush ~= nil then hBrush:AcceptInput( "Enable" ) hBrush.Damageable = true end end for _, hPlayer in pairs( ents.FindInBox( hManager:GetAbsOrigin() + Vector(-160,-160,-184), hManager:GetAbsOrigin() + Vector(160,160,0), "player" ) ) do if hPlayer:IsRealPlayer() and hPlayer:IsAlive() and ( hPlayer:GetTeam() ~= 1 ) then if hPlayer.bHasWood then hPlayer.bCanBuild = true hPlayer.iCade = cade end elseif hPlayer:IsBot() and hPlayer:IsAlive() and ( hPlayer:GetTeam() ~= 1 ) then if Barricade_Table[cade].state > 2 and ( CurTime() >= hPlayer.Barricade_AttackThinker ) then if hPlayer:GetTeam() == 2 then return end -- if hPlayer.m_iClass == TF_CLASS_MEDIC then return end local sTargetLookCade = cade_name .. tostring(3) local sTargetCade = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Target" hPlayer:StunPlayer( 0.2, 0.8, TF_STUNFLAG_SLOWDOWN ) hPlayer:RemoveCond( 51 ) if hPlayer:GetActivePlayerWeapon() == hPlayer:GetPlayerItemBySlot(2) then hPlayer.Barricade_AttackThinker = CurTime() + 0.5 hPlayer:AcceptInput("$BotCommand", "interrupt_action -posent " .. sTargetCade .. " -lookposent " .. sTargetLookCade .. " -killlook -alwayslook -duration 1 -distance 8") else hPlayer.Barricade_AttackThinker = CurTime() + ( hPlayer:GetActivePlayerWeapon():GetAttributeValue("Wrench Index") or 0.1 ) hPlayer:AcceptInput("$BotCommand", "interrupt_action -posent " .. sTargetCade .. " -lookposent " .. sTargetLookCade .. " -killlook -alwayslook -duration 1 -distance 128") end --hPlayer:AcceptInput("$BotCommand", "interrupt_action -posent " .. sTargetCade .. " -lookposent " .. sTargetLookCade .. " -killlook -alwayslook -duration 1 -distance 8") --hPlayer:SetAttributeValue("reload full clip at once", 1) --hPlayer:SetAttributeValue("penetrate teammates", 1) if string.match( hPlayer:GetPlayerName(), "Arsonist" ) then ents.FindByName( sTargetLookCade ):TakeDamage({ Attacker = hPlayer, Weapon = hPlayer:GetActivePlayerWeapon(), Damage = 2 }) else if IsValid( hPlayer.m_hActiveWeapon ) then hPlayer.m_bLagCompensation = true util.StartLagCompensation( hPlayer ) hPlayer:AcceptInput( "RunScriptCode", "self.GetActiveWeapon().PrimaryAttack()" ) hPlayer.m_bLagCompensation = false util.FinishLagCompensation( hPlayer ) end end end end end for _, hTank in pairs( ents.FindInBox( hManager:GetAbsOrigin() + Vector(-96,-96,-192), hManager:GetAbsOrigin() + Vector(96,96,0), "tank_boss" ) ) do if Barricade_Table[cade].state > 0 then local sTargetCade = cade_name .. tostring(1) hTank:SetSpeed(5) ents.FindByName( sTargetCade ):TakeDamage({ Attacker = hTank, Damage = 10 }) else hTank:SetSpeed(75) end end ::skip:: end end Barricade_Thinker = CurTime() + 0.25 end for _, player in pairs( ents.GetAllAliveRealPlayers() ) do if player:GetTeam() ~= 1 then local iMaxHealth = ( player.m_iMaxHealth ) player:SetAttributeValue("major move speed bonus", lerp( 1, Movespeed_Reduction_Table[player.m_iClass], math.clamp( 1 - ( player.m_iHealth / iMaxHealth ), 0, 1 ) ) ) if not IsValid(player:GetPlayerItemBySlot(2)) then player:ResetInventory() end if player.bHasWood then player:WeaponSwitchSlot(2) elseif string.match( player:GetPlayerItemBySlot(2):GetItemName(), "Wood Plank" ) and ( not player.bHasWood ) then if player.PreviousMelee == "Wood Plank" then player.PreviousMelee = "Memory Maker" end player:WeaponStripSlot(2) player:WeaponSwitchSlot(1) player:GiveItem( player.PreviousMelee ) player:WeaponSwitchSlot(0) -- just in case player:SetAttributeValue("move speed penalty", nil) player:SetAttributeValue("increased jump height", nil) player:SetAttributeValue("no_attack", nil) for i, hologram in pairs( ents.FindAllByName("Barricade_Hologram") ) do hologram:HideTo( player ) end for i, hologram in pairs( ents.FindAllByName("Barricade_Hologram_Tut") ) do hologram:HideTo( player ) end elseif player:GetAttributeValue("move speed penalty") ~= nil and ( not player.bHasWood ) then --if player.m_iClass == TF_CLASS_SCOUT then player:SetAttributeValue("move speed penalty", nil) player:SetAttributeValue("increased jump height", nil) player:SetAttributeValue("no_attack", nil) player:GetPlayerItemBySlot(2):SetAttributeValue("custom item model", "") player:GetPlayerItemBySlot(2):SetAttributeValue("custom view model", "") --end for i, hologram in pairs( ents.FindAllByName("Barricade_Hologram") ) do hologram:HideTo( player ) end for i, hologram in pairs( ents.FindAllByName("Barricade_Hologram_Tut") ) do hologram:HideTo( player ) end end end end end function BuildCade( cade, hPlayer ) if not IsValid( hPlayer ) then return end local hManager = Barricade_Table[cade].manager local cade_name = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Part_" local brush_name = "Barricade_" .. tostring( Cade_Map[cade] ) .. "_Brush" local hBrush = nil Barricade_Table[cade].state = Barricade_Table[cade].state + 1 if not ( IsValid( ents.FindByName( cade_name .. tostring( Barricade_Table[cade].state ) ) ) ) then hPlayer:Print(2,"This barricade is fully built") Barricade_Table[cade].state = Barricade_Table[cade].state - 1 goto continue end ents.FindByName("nav_refresh"):AcceptInput("recomputeblockers") local percent = 0 local start = hPlayer:GetAbsOrigin() + Vector(0, 0, 24) local endpos = ents.FindByName(cade_name .. tostring(Barricade_Table[cade].state) ):GetAbsOrigin() local startang = Vector(0, 0, -90) local endang = ents.FindByName(cade_name .. tostring(Barricade_Table[cade].state) ):GetAbsAngles() local modelname = tostring( ents.FindByName(cade_name .. tostring(Barricade_Table[cade].state) ):GetModel() ) local iSkin = tonumber( ents.FindByName(cade_name .. tostring(Barricade_Table[cade].state) ).m_nSkin ) hPlayer.bHasWood = false local iState = Barricade_Table[cade].state local hCade = ents.FindByName(cade_name .. tostring(Barricade_Table[cade].state) ) if not hCade.callbacks then hCade.callbacks = {} end hCade.Damageable = true Barricade_Table[cade].health = iState * 100 hCade:AcceptInput( "EnableCollision" ) hCade.m_nSolidType = 6 if iState >= Barricade_Table[cade].attributes.ReinforceLevel then Barricade_Table[cade].health = Barricade_Table[cade].health + ( ( iState - ( Barricade_Table[cade].attributes.ReinforceLevel - 1 ) ) * 100 ) Barricade_Table[cade].solid = true end -- print( iState, Barricade_Table[cade].attributes.ReinforceLevel, Barricade_Table[cade].health ) local ent_table = { model = modelname, origin = "0 0 0", angles = "0 0 0 ", solid = 0, disableshadows = 1, skin = iSkin, targetname = "DEBUG" } local hWood = ents.CreateWithKeys( "prop_dynamic", ent_table, true, true ) hWood:SetAbsOrigin( start ) hWood:SetAbsAngles( startang ) timer.Create( 0.05, function() percent = percent + 0.1 hWood:SetAbsOrigin( lerpvector( start, endpos, percent ) ) hWood:SetAbsAngles( lerpvector( startang, endang, percent ) ) end, 10) timer.Simple( 0.7, function() hWood:Remove() UnstuckPlayer( hPlayer ) for i = 1, Barricade_Table[cade].state do ents.FindByName(cade_name .. tostring(i) ):AcceptInput( "Enable" ) ents.FindByName(cade_name .. tostring(i) ):AcceptInput( "EnableCollision" ) ents.FindByName(cade_name .. tostring(i) ).m_nSolidType = 6 ents.FindByName(cade_name .. tostring(i) ).Damageable = true end end) ::continue:: end function OnPlayerConnected( player ) if player:IsRealPlayer() then player.bHasWood = false player.bCanBuild = false player.bInAttack = false player.iCade = 0 player:AddCallback( ON_SPAWN, function( ent ) ent.bHasWood = false ent.bCanBuild = false ent.bInAttack = false ent.iCade = 0 end) player:AddCallback( ON_DEATH, function( ent ) ent.m_hObserverTarget = nil end) player:AddCallback( ON_KEY_PRESSED, function( ent, key ) if ( ent.bHasWood or ( ent:GetAttributeValue("no_attack") ~= nil ) ) and ( ( key == IN_ATTACK ) or ( key == IN_ATTACK2 ) ) and ( not ent.bCanBuild ) then ent.bHasWood = false for i, hologram in pairs( ents.FindAllByName("Barricade_Hologram") ) do hologram:HideTo( ent ) end for i, hologram in pairs( ents.FindAllByName("Barricade_Hologram_Tut") ) do hologram:HideTo( ent ) end --just in case ent:SetAttributeValue("move speed penalty", nil) ent:SetAttributeValue("increased jump height", nil) ent:SetAttributeValue("no_attack", nil) if not ent.PreviousMelee then ent.PreviousMelee = "Memory Maker" end if ent.PreviousMelee == "Wood Plank" then ent.PreviousMelee = "Memory Maker" end if ent.m_iClass ~= TF_CLASS_SCOUT then ent:DropItem(2) ent:WeaponSwitchSlot(0) ent:GiveItem( ent.PreviousMelee ) if ent.PreviousMelee == "Memory Maker" then ent:ResetInventory() end ent:SetAttributeValue("move speed penalty", nil) ent:SetAttributeValue("increased jump height", nil) ent:SetAttributeValue("no_attack", nil) else ent:SetAttributeValue("move speed penalty", nil) ent:SetAttributeValue("increased jump height", nil) ent:SetAttributeValue("no_attack", nil) ent:GetPlayerItemBySlot(2):SetAttributeValue("custom item model", "") ent:GetPlayerItemBySlot(2):SetAttributeValue("custom view model", "") end elseif (ent.bHasWood) and ( ( key == IN_ATTACK ) or ( key == IN_ATTACK2 ) ) then BuildCade( ent.iCade, ent ) end if ( ( key == IN_ATTACK ) or ( key == IN_ATTACK2 ) ) then ent.bInAttack = true end end) player:AddCallback( ON_KEY_RELEASED, function( ent, key ) if ( ( key == IN_ATTACK ) or ( key == IN_ATTACK2 ) ) then ent.bInAttack = false end end) end end function ResetWood(_, activator ) if not IsValidAliveRealPlayer( activator ) then return end if activator.bInAttack then return end if not activator.bHasWood then activator.PreviousMelee = activator:GetPlayerItemBySlot(2):GetItemName() if activator.m_iClass ~= TF_CLASS_SCOUT then if Solomode then activator:GiveItem("Wood Plank ") else activator:GiveItem("Wood Plank") end else if Solomode then activator:SetAttributeValue("move speed penalty", 0.9) activator:SetAttributeValue("increased jump height", 0.9) activator:SetAttributeValue("no_attack", 1) activator:GetPlayerItemBySlot(2):SetAttributeValue("custom item model", "models/weapons/c_models/c_paintrain/c_paintrain.mdl") activator:GetPlayerItemBySlot(2):SetAttributeValue("custom view model", "models/weapons/v_models/v_toolbox_engineer.mdl") else activator:SetAttributeValue("move speed penalty", 0.7) activator:SetAttributeValue("increased jump height", 0.7) activator:SetAttributeValue("no_attack", 1) activator:GetPlayerItemBySlot(2):SetAttributeValue("custom item model", "models/weapons/c_models/c_paintrain/c_paintrain.mdl") activator:GetPlayerItemBySlot(2):SetAttributeValue("custom view model", "models/weapons/v_models/v_toolbox_engineer.mdl") end end activator:Print(3,"You have picked up wood, attack to drop it!") for i, hologram in pairs( ents.FindAllByName("Barricade_Hologram") ) do hologram:ShowTo( activator ) end timer.Simple(0.1, function() for k,v in pairs(ents.FindAllByClass("tf_viewmodel")) do if v.m_hOwner == player then v.m_nSequence = 0 timer.Simple(0.5, function() v.m_nSequence = 1 end) end end end) end activator.bHasWood = true end function UnstuckPlayer( ply ) local pos = ply:GetAbsOrigin() local InitTrace = util.Trace({ start = pos, endpos = pos, mins = Vector( -24, -24, 0 ), maxs = Vector( 24, 24, 82 ), filter = ents.GetAllRealPlayers(), mask = MASK_PLAYERSOLID }) if InitTrace.Hit then local dirs = { Vector(1, 0, 0), Vector(-1, 0, 0), Vector(0, 1, 0), Vector(0, -1, 0), Vector(0, 0, 1), Vector(0, 0, -1) } for mult = 16, 128, 16 do for i, vec in pairs( dirs ) do local Trace = util.Trace({ start = pos + ( vec * mult ), endpos = pos + ( vec * mult ), mins = Vector( -24, -24, 0 ), maxs = Vector( 24, 24, 82 ), filter = ents.GetAllRealPlayers(), mask = MASK_PLAYERSOLID }) if not Trace.AllSolid then ply:SetAbsOrigin( pos + ( vec * mult ) ) return true end end end else return false end return false end function DynamicMuzzleFlash( projectile, activator, weapon ) local range = 400 local Trace = util.Trace({ start = activator:GetEyePos(), distance = range, filter = activator, mask = MASK_SOLID, angles = activator:GetEyeAngles()}) local distance = Trace.HitPos:Distance( activator:GetEyePos() ) local keys = { ["_light"] = "237 149 18 200", ["brightness"] = 1, ["_inner_cone"] = 120, ["_cone"] = 160, ["distance"] = range, ["spotlight_radius"] = distance * 4, ["spawnflags"] = 0, } local dlight = ents.CreateWithKeys( "light_dynamic", keys, true, true ) dlight:SetAbsOrigin( activator:GetEyePos() ) dlight:SetAbsAngles( activator:GetEyeAngles() ) dlight:TurnOn() timer.Simple( 0.03, function() dlight:TurnOff() dlight:Kill() end) end