--please do not modify or copy this for your own needs --you may use this unmodified version if you credit me :) --made by Wacev --improved version of robot_extras.lua --features better and more scripts and bot functions --https://steamcommunity.com/profiles/76561198009331097/ function has_value (tab, val) for index, value in pairs(tab) do if value == val then return true end end return false end function OnWaveSpawnBot(bot, wave, tags) GiveCallbacks( bot, tags ) end function GiveCallbacks( bot, tags ) if bot.m_iClass ~= TF_CLASS_SPY then local usesLeft = 3 local maxHealth = bot.m_iHealth local curHealth = bot.m_iHealth local enraged = false local ShotCount = 0 local enrageCount = 0 local maxammo = bot.m_hActiveWeapon.m_iClip1 local __Callback_Enrage__ = nil local __Callback_Uber__ = nil local __Callback_FireCanteens__ = nil local __Callback_Cleanup__ = nil __Callback_Cleanup__ = bot:AddCallback(ON_DEATH, function() --clean up bot:RemoveCallback(ON_DAMAGE_RECEIVED_POST, __Callback_Enrage__) bot:RemoveCallback(ON_DAMAGE_RECEIVED_PRE, __Callback_Uber__) bot:RemoveCallback(ON_DEATH, __Callback_Cleanup__) for i=0, 2 do if ( IsValid( bot:GetPlayerItemBySlot(i) ) ) and ( __Callback_FireCanteens__ ) then bot:GetPlayerItemBySlot(i):RemoveCallback(ON_FIRE_WEAPON_PRE, __Callback_FireCanteens__) end end end) __Callback_Enrage__ = bot:AddCallback(ON_DAMAGE_RECEIVED_POST, function(ent, damage, previousHealth) curHealth = bot.m_iHealth if IsValid(bot:GetPlayerItemBySlot(0)) then if ( bot:GetPlayerItemBySlot(0):GetItemName() == "The Phlogistinator" ) and ( not has_value(tags, "bot_boss") ) and ( not bot:InCond(44) ) then --phlog taunt when injured function. if curHealth <= maxHealth*0.8 and ( enraged == false ) then enraged = true bot:Taunt("TAUNT_BASE_WEAPON", 0) end end end if has_value(tags, "bot_enragable") then --enrage bot function if curHealth <= maxHealth*0.65 and ( enraged == false ) then if maxHealth > 20000 then enraged = true bot:AddCond(34,17) bot:AddCond(26,17) bot:AddCond(71,1) bot:AddCond(52,2.5) bot:ChangeAttributes("Enraged") timer.Simple(17, function() bot:ChangeAttributes("Defualt") end) else enraged = true bot:AddCond(34,7) bot:AddCond(26,7) bot:AddCond(71,1) bot:AddCond(52,2.5) bot:ChangeAttributes("Enraged") timer.Simple(7, function() bot:ChangeAttributes("Defualt") end) end end end end) __Callback_Uber__ = bot:AddCallback(ON_DAMAGE_RECEIVED_PRE, function(ent, damage) curHealth = bot.m_iHealth if has_value(tags, "bot_canteenuber") then --uber canteen bot function if not bot:InCond(8) then if curHealth <= maxHealth*0.25 and ( enraged == false ) then usesLeft = 0 bot:AddCond(52,5) util.PrintToChatAll('\x0799CCFF' .. tostring(bot:GetPlayerName()) .. ' \x07FBECCBhas used thier \x079ec34fÜBERCHARGE \x07FBECCBPower Up Canteen!') for _, player in pairs(ents.GetAllPlayers()) do --play the canteen sound to all players if player:IsRealPlayer() then player:PlaySoundToSelf("MVM.PlayerUsedPowerup") player:PlaySoundToSelf("MVM.PlayerUsedPowerup") end end enraged = true elseif damage.Damage >= curHealth and ( enraged == false ) then -- makes the uber canteen bot servive a lethal strike -- usesLeft = 0 bot:AddCond(52,5) util.PrintToChatAll('\x0799CCFF' .. tostring(bot:GetPlayerName()) .. ' \x07FBECCBhas used thier \x079ec34fÜBERCHARGE \x07FBECCBPower Up Canteen!') for _, player in pairs(ents.GetAllPlayers()) do --play the canteen sound to all players if player:IsRealPlayer() then player:PlaySoundToSelf("MVM.PlayerUsedPowerup") player:PlaySoundToSelf("MVM.PlayerUsedPowerup") end end enraged = true end end end end) timer.Simple(0.5, function() __Callback_FireCanteens__ = bot.m_hActiveWeapon:AddCallback(ON_FIRE_WEAPON_PRE, function(ent) if has_value(tags, "bot_canteencrit") then --crit canteen bot function if ( not bot:InCond(34) ) and ( not bot:InCond(51) ) then --only increment shot count when not critboosted and not in spawn ShotCount = ShotCount + 1 if ShotCount >= 3 and ( enrageCount < 3 ) then ShotCount = 0 enrageCount = enrageCount + 1 bot:AddCond(34,5) util.PrintToChatAll('\x0799CCFF' .. tostring(bot:GetPlayerName()) .. ' \x07FBECCBhas used thier \x079ec34fCRITS \x07FBECCBPower Up Canteen!') --what an ungodly parameter for _, player in pairs(ents.GetAllPlayers()) do --play the canteen sound to all players if player:IsRealPlayer() then player:PlaySoundToSelf("MVM.PlayerUsedPowerup") player:PlaySoundToSelf("MVM.PlayerUsedPowerup") end end end else ShotCount = 0 --to prevent back to back to back crit canteens end end if has_value(tags, "bot_canteenammo") then --ammo canteen bot function if ent.m_iClip1 == 0 and (usesLeft ~= 0) then usesLeft = usesLeft - 1 ent.m_iClip1 = maxammo util.PrintToChatAll('\x0799CCFF' .. tostring(bot:GetPlayerName()) .. ' \x07FBECCBhas used thier \x079ec34fAMMO REFILL \x07FBECCBPower Up Canteen!') for _, player in pairs(ents.GetAllPlayers()) do --play the canteen sound to all players if player:IsRealPlayer() then player:PlaySoundToSelf("MVM.PlayerUsedPowerup") player:PlaySoundToSelf("MVM.PlayerUsedPowerup") end end end end end) end) end end PlayerTable = {} PlayerCount = 0 function RecountPlayers( teamnum ) PlayerCount = 0 for i,v in pairs(PlayerTable) do PlayerTable[i] = nil end if teamnum == nil or ( not teamnum ) then for index, player in pairs(ents.GetAllPlayers()) do if ( player:IsRealPlayer() ) then PlayerTable[PlayerCount] = player PlayerCount = PlayerCount + 1 end end else for index, player in pairs(ents.GetAllPlayers()) do if ( player.m_iTeamNum ~= teamnum ) and ( player.m_iTeamNum ~= 1 ) and ( player:IsAlive() ) then PlayerTable[PlayerCount] = player PlayerCount = PlayerCount + 1 end end end end function OrbitalRocket(projectile,activator,weapon) RecountPlayers( activator.m_iTeamNum ) local RandomPlayer = PlayerTable[math.random(0,#PlayerTable)] OrbitalRocketMain(RandomPlayer,activator,projectile:GetNetIndex(), ( activator:InCond(34) ) or ( activator:InCond(11) ) ) end function OrbitalRocketMain(target,attacker,index,critboosted) if (target:IsValid()) and (attacker:IsValid()) then timer.Simple(3, function() local KeyValues = { model = "models/props_mvm/indicator/indicator_circle_long.mdl", skin = 1, origin = target:GetAbsOrigin(), disableshadows = 1, targetname = 'indicator ' .. tostring(index) } local KeyValues2 = { origin = target:GetAbsOrigin() + Vector(0, 0, 1100), angles = "90 0 0", Crits = 0, SpreadAngle = 0, targetname = 'shooter ' .. tostring(index), teamnum = attacker.m_iTeamNum } local mimic = ents.CreateWithKeys("tf_point_weapon_mimic", KeyValues2, true, true) mimic["$weaponname"] = "Orbital Strike Rocket" mimic["$AddWeaponAttribute"] = "dmg penalty vs players|" .. tostring( ( attacker.m_hActiveWeapon:GetAttributeValue( "throwable damage" ) ) or 1 ) if critboosted then mimic["Crits"] = 1 end local ring = ents.CreateWithKeys("prop_dynamic", KeyValues, true, true) ring:AcceptInput("SetAnimation","start") timer.Create(0.1, function() util.StartLagCompensation(target) local Trace = util.Trace({ start = target:GetAbsOrigin() + Vector(0, 0, 16), mask = MASK_PLAYERSOLID, angles = Vector(90, 0, 0), mins = Vector(-16, -16, 0), maxs = Vector(16, 16, 0), filter = ents.GetAllPlayers() }) util.FinishLagCompensation(target) ring:SetAbsOrigin(Trace.HitPos + Vector(0, 0, 8)) mimic:SetAbsOrigin(Trace.HitPos + Vector(0, 0, 1100)) end, 2.5 / 0.1) timer.Simple(2.7, function() ring:AcceptInput("Skin", 0) end) timer.Simple(3.7, function() mimic:AcceptInput("FireOnce") end) timer.Simple(4.7, function() ring:AcceptInput("SetAnimation","end") end) timer.Simple(5.2, function() ents.FindByName('indicator ' .. tostring(index)):AcceptInput("kill") mimic:AcceptInput("kill") end) end) end end