-- the stuff below is made by Royal -- they deserve a LOT of kudos for everything here GR_STATE_BETWEEN_RNDS = 10 MAX_COORD_FLOAT = 16384.0 local deathCounts = {} local waveActive = false TextDisplay = -1 Gamerules = ents.FindByClass("tf_gamerules") function OnPlayerDisconnected(player) deathCounts[player:GetHandleIndex()] = nil end function OnWaveInit() waveActive = false DoublePointsText = "" FireSaleText = "" InstakillText = "" InstaKillTextUser = "" DoublePointsDuration = 0 FireSaleDuration = 0 InstakillDuration = 0 DumpsterCost = 950 end function rejuvenatorHit(damage, activator, caller) local damageThreshold = 1 if damage < damageThreshold then return end caller:AddCond(TF_COND_REPROGRAMMED, 5, activator) timer.Simple(5, function() caller:Suicide() end) end function chargerLogic(_, activator) local callbacks = {} local function removeCallbacks() for _, callbackData in pairs(callbacks) do activator:RemoveCallback(callbackData.Type, callbackData.ID) end end callbacks.keypress = { -- Apply animation when bot pushes M2 Type = 7, ID = activator:AddCallback(ON_KEY_PRESSED, function(_, key) if key ~= IN_ATTACK2 then return end if activator.m_flChargeMeter < 95 then -- from 100, so the chargers have a bit of a 'tell' when they're getting ready to charge return end activator:PlaySequence("Charger_Charge") end), } callbacks.spawned = { Type = 1, ID = activator:AddCallback(ON_SPAWN, function() removeCallbacks() end), } callbacks.died = { Type = 9, ID = activator:AddCallback(ON_DEATH, function() removeCallbacks() end), } end local function cashforhits(activator) local callbacks = {} local function removeCallbacks() for _, callbackId in pairs(callbacks) do activator:RemoveCallback(callbackId) end end callbacks.damagetype = activator:AddCallback(ON_DAMAGE_RECEIVED_PRE, function(_, damageInfo) -- PrintTable(damageInfo) local mult = (DoublePointsDuration > 0) and 2 or 1 local damage = damageInfo.Damage if damage <= 0 then return end local damageType = damageInfo.DamageType local hitter = damageInfo.Attacker if not hitter or not hitter:IsRealPlayer() then return end if (damageType & DMG_BURN) ~= 0 then return end local isCrit = (damageType & DMG_CRITICAL) ~= 0 if isCrit then damage = damage * 3 end local curHealth = activator.m_iHealth if InstakillDuration > 0 and hitter:InCond(TF_COND_CRITBOOSTED_CARD_EFFECT) and activator.CanBeInstakilled then --instakill functionality -washy damage = curHealth activator.m_iHealth = 0 end if damage > curHealth and activator.m_szNetname == "Tank" then -- snuck in here so we don't need a separate function for it hitter:SpeakResponseConcept("TLK_MVM_TANK_DEAD") -- ding dong the tank is dead end if activator.CanBeInstakilled and hitter.m_szNetname == "Tank" then damage = curHealth activator.m_iHealth = 0 -- if converted zombie is hit by Tank, treat it as Instakill end --local isLethal = curHealth - (damage + 1) <= 0 local function addCurrency(amount) hitter:AddCurrency(amount * mult) end --[[ if not isLethal then ]] addCurrency(10) --[[ return end if IsLethal then addCurrency(75) return end if (damageType & DMG_BLAST) ~= 0 then addCurrency(75) -- used to be 50 -- print("explosive?") elseif (damageType & DMG_MELEE) ~= 0 then addCurrency(150) -- print("melee?") elseif (damageType & DMG_MELEE) == 0 and (damageType & DMG_CRITICAL) ~= 0 then -- this is used for headshots, may overlap with Instakill addCurrency(100) -- print("crit?") elseif (damageType & DMG_BULLET) ~= 0 then addCurrency(75) -- print("bullet?") elseif (damageType & DMG_USE_HITLOCATIONS) ~= 0 then addCurrency(75) -- print("fancier bullet?") else addCurrency(75) -- print("hell if I know") end ]] end) callbacks.killed = activator:AddCallback(ON_DEATH, function(_, damageInfo) -- PrintTable(damageInfo) local mult = (DoublePointsDuration > 0) and 2 or 1 local damage = damageInfo.Damage if damage <= 0 then return end local damageType = damageInfo.DamageType local hitter = damageInfo.Attacker if (damageType & DMG_BURN) ~= 0 then return end local isCrit = (damageType & DMG_CRITICAL) ~= 0 if isCrit then damage = damage * 3 end local curHealth = activator.m_iHealth if InstakillDuration > 0 and activator.CanBeInstakilled and hitter:InCond(TF_COND_CRITBOOSTED_CARD_EFFECT) then --instakill functionality -washy damage = curHealth activator.m_iHealth = 0 end if damage > curHealth and activator.m_szNetname == "Tank" then -- snuck in here so we don't need a separate function for it hitter:SpeakResponseConcept("TLK_MVM_TANK_DEAD") -- ding dong the tank is dead end local function addCurrency(amount) hitter:AddCurrency(amount * mult) end if (damageType & DMG_BLAST) ~= 0 then addCurrency(65) -- used to be 50 -- print("explosive?") elseif (damageType & DMG_MELEE) ~= 0 then addCurrency(140) -- print("melee?") elseif (damageType & DMG_MELEE) == 0 and (damageType & DMG_CRITICAL) ~= 0 then -- this is used for headshots, may overlap with Instakill addCurrency(90) -- print("crit?") elseif (damageType & DMG_BULLET) ~= 0 then addCurrency(65) -- print("bullet?") elseif (damageType & DMG_USE_HITLOCATIONS) ~= 0 then addCurrency(65) -- print("fancier bullet?") else addCurrency(65) -- print("hell if I know") end end) callbacks.spawned = activator:AddCallback(ON_SPAWN, function() removeCallbacks() end) callbacks.died = activator:AddCallback(ON_DEATH, function() removeCallbacks() end) end function OnWaveSpawnBot(bot, wave, tags) bot.CanBeInstakilled = true for _, tag in pairs(tags) do if tag == "bigguyalert" then bot.CanBeInstakilled = false break end end timer.Simple(1, function() cashforhits(bot) end) end function playertracker(_, activator) -- the only other thing here made by Sntr local callbacks = {} local function removeCallbacks() for _, callbackId in pairs(callbacks) do activator:RemoveCallback(callbackId) end end local function DeathCounter() if not waveActive then return end local deathcount = deathCounts[activator:GetHandleIndex()] if deathcount >= 3 and deathcount < 4 then util.PrintToChat(activator,"You have received a $750 comeback bonus.") activator:AddCurrency(750) end if deathcount >= 5 and deathcount < 6 then util.PrintToChat(activator,"You have received a $1500 comeback bonus.") activator:AddCurrency(1500) end if deathcount > 7 and deathcount < 8 then util.PrintToChat(activator,"You have received a $3000 comeback bonus.") activator:AddCurrency(3000) end end callbacks.damagetype = activator:AddCallback(ON_DAMAGE_RECEIVED_PRE, function(_, damageInfo) if activator:InCond(TF_COND_INVULNERABLE) then return end -- disallow friendly fire, allow self damage if damageInfo.Attacker:GetHandleIndex() ~= activator:GetHandleIndex() then if damageInfo.Attacker.m_iTeamNum == activator.m_iTeamNum then return end end local damage = damageInfo.Damage local curHealth = activator.m_iHealth if damage > curHealth and activator:InCond(TF_COND_POWERUPMODE_DOMINANT) then -- give full heal + uber when condition 70 is removed activator:AddCond(TF_COND_INVULNERABLE, 2.5) activator:AddHealth(300,1) activator:PlaySoundToSelf("misc/halloween/merasmus_stun.wav") activator:RemoveCond(129) activator:RemoveCond(70) -- so people can't be undying forever activator.vm_quickrev = false -- added this for compatibility -washy end end) -- callbacks.output = activator:AddCallback(ON_INPUT, function(_, medicbonus_relay) -- -- local playerclass = activator.m_iClass -- local playercount = math_counter.m_OutValue -- -- if playerclass == 5 -- then -- activator:AddCurrency( playercount * 75 ) -- end -- end) callbacks.spawned = activator:AddCallback(ON_SPAWN, function() removeCallbacks() end) callbacks.died = activator:AddCallback(ON_DEATH, function() removeCallbacks() DeathCounter() end) end -- and here's the stuff made by Washy -- likewise, plenty of kudos function OnWaveReset() for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() then for weapon = 0, 3, 1 do player.loadout[weapon] = "Default" end end end if TextDisplay > -1 then timer.Stop(TextDisplay) TextDisplay = -1 end end function OnGameTick() for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() then if not player.HasEverSelectedClass and player.m_iDesiredPlayerClass ~= TF_CLASS_UNDEFINED then if Gamerules.m_iRoundState ~= GR_STATE_BETWEEN_RNDS then player:Print(PRINT_TARGET_CENTER, "You will spawn when the round ends.") end player.HasEverSelectedClass = true end if player.m_bUsingActionSlot == 1 and player.InteractCooldown ~= true then player.HoldTime = player.HoldTime + 1 if player.HoldTime > 13 and player.InteractWith ~= "nothing" then Interact(player) player.InteractCooldown = true player.HoldTime = 0 timer.Simple(1, function() player.InteractCooldown = false end) end else player.holdTime = 0 end player:GetUserId() for k, v in pairs(ents.FindByClass("tf_player_manager"):DumpProperties().m_iUserID) do if v == player:GetUserId() then ents.FindByClass("tf_player_manager"):AcceptInput("$SetProp$m_iCurrencyCollected$" .. k-1, player.m_nCurrency) end end if player.m_nCurrencyDiff ~= player.m_nCurrency then if player.m_nCurrency - player.m_nCurrencyDiff > 0 then player.CashText = 132 player:ShowHudText({channel = 4, x = 0.04, y = 0.91, b1 = 0, b2 = 0}, "+"..player.m_nCurrency - player.m_nCurrencyDiff) else player.CashText = 132 player:ShowHudText({channel = 4, x = 0.04, y = 0.91, g1 = 25, g2 = 25, b1 = 0, b2 = 0,}, player.m_nCurrency - player.m_nCurrencyDiff) end end player.m_nCurrencyDiff = player.m_nCurrency player.CashText = player.CashText - 1 if player.CashText == 0 then player:ShowHudText({channel = 4}, "") end end end if DoublePointsDuration > 0 then DoublePointsDuration = DoublePointsDuration - 1 DoublePointsText = "Double Points: ".. math.floor(DoublePointsDuration/66+1) else DoublePointsText = "" end if FireSaleDuration > 0 then FireSaleDuration = FireSaleDuration - 1 FireSaleText = "Fire Sale: ".. math.floor(FireSaleDuration/66+1) else FireSaleText = "" end if InstakillDuration > 0 then InstakillDuration = InstakillDuration - 1 InstakillText = "Instakill (" .. InstakillTextUser .. "): " .. math.floor(InstakillDuration / 66 + 1) else InstakillText = "" InstakillTextUser = "" end end function OnPlayerConnected(player) if player:IsRealPlayer() then player.HasEverSelectedClass = player.m_iDesiredPlayerClass ~= TF_CLASS_UNDEFINED player.HoldTime = 0 player.InteractWith = "nothing" player.TouchingReviveMarker = nil player.InteractCooldown = false player.loadout = {[0] = "Default", [1] = "Default", [2] = "Default"} player.m_nCurrencyDiff = 0 local handle = player:GetHandleIndex() deathCounts[handle] = 0 player:AddCallback(ON_DEATH, function() deathCounts[handle] = deathCounts[handle] + 1 end) player:AddCallback(ON_SPAWN, function() for weapon = 0, 3, 1 do if player.loadout[weapon] ~= "Default" then player:GiveItem(player.loadout[weapon]) end end end) else player:AddCallback(ON_DEATH, function() local number = math.random(1,100) if number <= 3 then -- 3% chance DropPowerup(player) end end); end end function ShuffleInPlace(t) --copied from stack overflow for i = #t, 2, -1 do local j = math.random(i) t[i], t[j] = t[j], t[i] end end function OnWaveStart() ents.FindByName("red_respawnroom1"):Remove() BoxTable = {} waveActive = true ThunderGunTaken = false RejuvenatorTaken = false DumpsterRoulette = {1,2,3,4,5} DumpsterRouletteIndex = 1 PowerupTable = {[1] = "DoublePoints", [2] = "FireSale", [3] = "Instakill", [4] = "Nuke", [5] = "MaxAmmo", [6] = "BonusPoints"} PowerupTableIndex = 1 ShuffleInPlace(DumpsterRoulette) ShuffleInPlace(PowerupTable) for box = 1, 5, 1 do ents.FindByName("dumpster_spawner"..box):Teleport(ents.FindByName("dumpster_tele_out"):GetAbsOrigin()) ents.FindByName("dumpster_spawner"..box):AcceptInput("ForceSpawn") BoxTable[box] = {message = 0, weapon = "", text = "", slot = "", response = "", firesale = false, dud = true, timer = 0, count = 0, spawned = false, opened = false} end SpawnDumpsterBox(DumpsterRoulette[DumpsterRouletteIndex]) timer.Simple(0.5,function() ents.FindByName("vm_jugmsg"):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() and player.m_nCurrency >= 2500 then player.InteractWith = "vm_jugbutton" end end) ents.FindByName("vm_jugmsg"):AddCallback(ON_END_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "nothing" player:Print(PRINT_TARGET_CENTER, "") end end) ents.FindByName("vm_quickrevmsg"):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() and player.m_nCurrency >= 1500 then player.InteractWith = "vm_quickrevbutton" end end) ents.FindByName("vm_quickrevmsg"):AddCallback(ON_END_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "nothing" player:Print(PRINT_TARGET_CENTER, "") end end) ents.FindByName("vm_speedmsg"):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() and player.m_nCurrency >= 3000 then player.InteractWith = "vm_speedbutton" end end) ents.FindByName("vm_speedmsg"):AddCallback(ON_END_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "nothing" player:Print(PRINT_TARGET_CENTER, "") end end) ents.FindByName("vm_blastermsg"):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() and player.m_nCurrency >= 1500 then player.InteractWith = "vm_blasterbutton" end end) ents.FindByName("vm_blastermsg"):AddCallback(ON_END_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "nothing" player:Print(PRINT_TARGET_CENTER, "") end end) ents.FindByName("vm_dtmsg"):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() and player.m_nCurrency >= 2000 then player.InteractWith = "vm_dtbutton" end end) ents.FindByName("vm_dtmsg"):AddCallback(ON_END_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "nothing" player:Print(PRINT_TARGET_CENTER, "") end end) end) TextDisplay = timer.Create(1, function() local poweruptext = ents.FindByName("poweruptext") poweruptext.m_iszMessage = FireSaleText .. "\n" ..InstakillText .. "\n" ..DoublePointsText poweruptext:AcceptInput("Display") ents.FindByName("enemytext"):AcceptInput("Display") -- ents.FindByName("roundtext"):AcceptInput("Display") end, 0) end function Interact(player) if player.InteractWith == "revive_button" then -- trigger_multiple attached to reanimator ents.FindByName("revive_button"):AcceptInput("Press", _, player) timer.Simple(1, function() player.InteractCooldown = true end) -- put way in the start because I hope I don't break the rest of this function timer.Simple(2.3, function() player.InteractCooldown = false end) end if player.InteractWith == "dumpsterbutton1" and player.m_nCurrency >= DumpsterCost and ents.FindByName("dumpster_light1").m_On == false then OpenDumpsterBox(player, 1) player.m_nCurrency = player.m_nCurrency - DumpsterCost elseif player.InteractWith == "tradeweapon1" then DumpsterBoxTakeWeapon(player, 1) elseif player.InteractWith == "dumpsterbutton2" and player.m_nCurrency >= DumpsterCost and ents.FindByName("dumpster_light2").m_On == false then OpenDumpsterBox(player, 2) player.m_nCurrency = player.m_nCurrency - DumpsterCost elseif player.InteractWith == "tradeweapon2" then DumpsterBoxTakeWeapon(player, 2) elseif player.InteractWith == "dumpsterbutton3" and player.m_nCurrency >= DumpsterCost and ents.FindByName("dumpster_light3").m_On == false then OpenDumpsterBox(player, 3) player.m_nCurrency = player.m_nCurrency - DumpsterCost elseif player.InteractWith == "tradeweapon3" then DumpsterBoxTakeWeapon(player, 3) elseif player.InteractWith == "dumpsterbutton4" and player.m_nCurrency >= DumpsterCost and ents.FindByName("dumpster_light4").m_On == false then OpenDumpsterBox(player, 4) player.m_nCurrency = player.m_nCurrency - DumpsterCost elseif player.InteractWith == "tradeweapon4" then DumpsterBoxTakeWeapon(player, 4) elseif player.InteractWith == "dumpsterbutton5" and player.m_nCurrency >= DumpsterCost and ents.FindByName("dumpster_light5").m_On == false then OpenDumpsterBox(player, 5) player.m_nCurrency = player.m_nCurrency - DumpsterCost elseif player.InteractWith == "tradeweapon5" then DumpsterBoxTakeWeapon(player, 5) elseif player.InteractWith == "vm_jugbutton" and player.m_nCurrency >= 2500 then if player:GetAttributeValue("max health additive bonus") == nil then ents.FindByName("vm_jugbutton"):AcceptInput("Press",_,player) if player:GetPlayerItemBySlot(1):GetClassname() ~= "tf_weapon_pipebomblauncher" then PlayViewmodelSequence(player) end timer.Simple(1, function() player.InteractCooldown = true end) timer.Simple(2.3, function() player.InteractCooldown = false end) else player:Print(PRINT_TARGET_CENTER, "You already have this perk!") end elseif player.InteractWith == "vm_quickrevbutton" and player.m_nCurrency >= 1500 then if not player:InCond(TF_COND_PREVENT_DEATH) then ents.FindByName("vm_quickrevbutton"):AcceptInput("Press",_,player) if player:GetPlayerItemBySlot(1):GetClassname() ~= "tf_weapon_pipebomblauncher" then PlayViewmodelSequence(player) end timer.Simple(1, function() player.InteractCooldown = true end) timer.Simple(2.3, function() player.InteractCooldown = false end) elseif player:InCond(TF_COND_PREVENT_DEATH) then player:Print(PRINT_TARGET_CENTER, "You already have this perk!") end elseif player.InteractWith == "vm_speedbutton" and player.m_nCurrency >= 3000 then if player:GetAttributeValue("move speed bonus") == nil then ents.FindByName("vm_speedbutton"):AcceptInput("Press",_,player) if player:GetPlayerItemBySlot(1):GetClassname() ~= "tf_weapon_pipebomblauncher" then PlayViewmodelSequence(player) end timer.Simple(1, function() player.InteractCooldown = true end) timer.Simple(2.3, function() player.InteractCooldown = false end) else player:Print(PRINT_TARGET_CENTER, "You already have this perk!") end elseif player.InteractWith == "vm_blasterbutton" and player.m_nCurrency >= 1500 then if player:GetAttributeValue("explosive sniper shot") == nil then ents.FindByName("vm_blasterbutton"):AcceptInput("Press",_,player) if player:GetPlayerItemBySlot(1):GetClassname() ~= "tf_weapon_pipebomblauncher" then PlayViewmodelSequence(player) end timer.Simple(1, function() player.InteractCooldown = true end) timer.Simple(2.3, function() player.InteractCooldown = false end) else player:Print(PRINT_TARGET_CENTER, "You already have this perk!") end elseif player.InteractWith == "vm_dtbutton" and player.m_nCurrency >= 2000 then if player:GetAttributeValue("fire rate bonus") == nil then ents.FindByName("vm_dtbutton"):AcceptInput("Press",_,player) if player:GetPlayerItemBySlot(1):GetClassname() ~= "tf_weapon_pipebomblauncher" then PlayViewmodelSequence(player) end timer.Simple(1, function() player.InteractCooldown = true end) timer.Simple(2.3, function() player.InteractCooldown = false end) else player:Print(PRINT_TARGET_CENTER, "You already have this perk!") end end end function PlayViewmodelSequence(player) for k,v in pairs(ents.FindAllByClass("tf_viewmodel")) do if v.m_hOwner == player then local PreviousPrimary = player:GetPlayerItemBySlot(0) local PreviousSecondary = player:GetPlayerItemBySlot(1) if player:GetPlayerItemBySlot(0) ~= nil then PreviousPrimary = player:GetPlayerItemBySlot(0):GetItemName() end if player:GetPlayerItemBySlot(1) ~= nil then PreviousSecondary = player:GetPlayerItemBySlot(1):GetItemName() if player:GetPlayerItemBySlot(1).m_flChargeLevel ~= nil then PreviousUbercharge = player:GetPlayerItemBySlot(1).m_flChargeLevel end end local PreviousMelee = player:GetPlayerItemBySlot(2):GetItemName() player:WeaponStripSlot(0) player:WeaponStripSlot(2) player:GiveItem("Bonk! Atomic Punch") player:WeaponSwitchSlot(1) v.m_flPlaybackRate = 0.8 if player.m_iClass == 1 then v.m_nSequence = 41 elseif player.m_iClass == 2 then v.m_nSequence = 34 elseif player.m_iClass == 3 then v.m_nSequence = 52 elseif player.m_iClass == 4 then v.m_nSequence = 34 elseif player.m_iClass == 5 then v.m_nSequence = 23 elseif player.m_iClass == 6 then v.m_nSequence = 32 elseif player.m_iClass == 7 then v.m_nSequence = 29 elseif player.m_iClass == 9 then --spy skipped v.m_nSequence = 52 end timer.Simple(2.2, function() player:WeaponStripSlot(1) if PreviousPrimary ~= nil then player:GiveItem(PreviousPrimary) end if PreviousSecondary ~= nil then player:GiveItem(PreviousSecondary) if player:GetPlayerItemBySlot(1).m_flChargeLevel ~= nil then player:GetPlayerItemBySlot(1).m_flChargeLevel = PreviousUbercharge end end player:GiveItem(PreviousMelee) end) end end end function DropPowerup(player) ents.FindByName(PowerupTable[PowerupTableIndex] .. "_spawner"):Teleport(player:GetAbsOrigin()) ents.FindByName(PowerupTable[PowerupTableIndex] .. "_spawner"):AcceptInput("ForceSpawn") if PowerupTableIndex == 6 then ShuffleInPlace(PowerupTable) PowerupTableIndex = 0 end PowerupTableIndex = PowerupTableIndex + 1 end function ActivateDoublePoints() DoublePointsDuration = 1980 -- 1980 ticks divided by 66 tick rate = 30 seconds for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() then player:Print(PRINT_TARGET_CENTER, "Double Points!") player:PlaySoundToSelf("shadows/powerup_doublepoints.mp3") player:PlaySoundToSelf("ui/quest_status_tick_advanced.wav") end end end function ActivateFireSale() for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() then player:Print(PRINT_TARGET_CENTER, "Fire Sale!") player:PlaySoundToSelf("shadows/powerup_firesale01.mp3") player:PlaySoundToSelf("mvm/mvm_bought_upgrade.wav") if FireSaleDuration <= 0 then timer.Simple(1,function() ents.FindByName("firesale_music"):AcceptInput("PlaySound") end) end end end FireSaleDuration = FireSaleDuration + 1980 -- 1980 ticks divided by 66 tick rate = 30 seconds DumpsterCost = 10 for box = 1, 5, 1 do if BoxTable[box].spawned == false then SpawnDumpsterBox(box) end BoxTable[box].firesale = true BoxTable[box].dud = false end BoxTable[DumpsterRouletteIndex].firesale = false timer.Create(1, function() if FireSaleDuration <= 0 then DumpsterCost = 950 for box = 1, 5, 1 do if BoxTable[box].firesale == true and BoxTable[box].opened == false then ents.FindByName("dumpster_warp_eff"..box):AcceptInput("Start") ents.FindByName("dumpster_warp_beam"..box):AcceptInput("Stop") ents.FindByName("dumpster_disappear"..box):AcceptInput("PlaySound") timer.Simple(1, function() ents.FindByName("dumpster_prop"..box):AcceptInput("$TeleportToEntity","dumpster_tele_out") end) ents.FindByName("dumpster_msg"..box):AcceptInput("DisableAndEndTouch") BoxTable[box].spawned = false BoxTable[DumpsterRouletteIndex].dud = true end end return false end end, 0) end function ActivateInstakill(_,player) InstakillDuration = 1980 -- 1980 ticks divided by 66 tick rate = 30 seconds InstakillTextUser = player.m_szNetname -- This is a bad way of truncating, but string.len() seems broken in raflua (always returns 0). local truncate = InstakillTextUser:sub(10) if truncate ~= "" then InstakillTextUser = InstakillTextUser:sub(1, 10) .. "..." end player:Print(PRINT_TARGET_CENTER, "Instakill!") player:PlaySoundToSelf("items/powerup_pickup_crits.wav") player:PlaySoundToSelf("shadows/powerup_instagib.mp3") player:AddCond(TF_COND_CRITBOOSTED_CARD_EFFECT, 30) end function ActivateNuke() for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() then timer.Simple(1,function() player:PlaySoundToSelf("shadows/powerup_nuke_01.mp3") end) elseif player.m_iTeamNum == 3 then player:TakeDamage({Attacker = player, Damage = 4500}) end end end function ActivateMaxAmmo() for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() then player:Print(PRINT_TARGET_CENTER, "Max Ammo!") player:PlaySoundToSelf("items/powerup_pickup_agility.wav") player:PlaySoundToSelf("shadows/powerup_resupply_01.mp3") player:PlaySoundToSelf("weapons/dispenser_generate_metal.wav") player:RefillAmmo() end end end function ActivateBonusPoints() for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() then player:Print(PRINT_TARGET_CENTER, "Bonus Points!") player:AcceptInput("$AddCurrency",2000) player:PlaySoundToSelf("shadows/powerup_money_01.mp3") player:PlaySoundToSelf("mvm/mvm_money_pickup.wav") end end end BoxRoulette = { [1] = { {text = "The Shortstop", itemname = "The Shortstop", model = "models/weapons/c_models/c_shortstop/c_shortstop.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Shortstop", itemname = "The Shortstop", model = "models/weapons/c_models/c_shortstop/c_shortstop.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Stickybomb Launcher", itemname = "TF_WEAPON_PIPEBOMBLAUNCHER", model = "models/weapons/w_models/w_stickybomb_launcher.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Stickybomb Launcher", itemname = "TF_WEAPON_PIPEBOMBLAUNCHER", model = "models/weapons/w_models/w_stickybomb_launcher.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Force-A-Nature", itemname = "The Force-a-Nature", model = "models/weapons/c_models/c_double_barrel.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Force-A-Nature", itemname = "The Force-a-Nature", model = "models/weapons/c_models/c_double_barrel.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Scattergun", itemname = "TF_WEAPON_SCATTERGUN", model = "models/weapons/w_models/w_scattergun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Scattergun", itemname = "TF_WEAPON_SCATTERGUN", model = "models/weapons/w_models/w_scattergun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Punch Packer", itemname = "The Punch Packer", model = "models/weapons/c_models/c_packer.mdl", slot = "primary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Punch Packer", itemname = "The Punch Packer", model = "models/weapons/c_models/c_packer.mdl", slot = "primary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Ray Gun", itemname = "The Ray Gun", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "a dud", itemname = "Dud", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl"}, }, [2] = { -- {text = "The Shotgun", itemname = "TF_WEAPON_SHOTGUN_PYRO", model = "models/weapons/w_models/w_shotgun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, -- no more sniper shotgun -- {text = "The Shotgun", itemname = "TF_WEAPON_SHOTGUN_PYRO", model = "models/weapons/w_models/w_shotgun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, -- uberupgrade makes this overtake Primary weapon {text = "The Scattergun", itemname = "TF_WEAPON_SCATTERGUN", model = "models/weapons/w_models/w_scattergun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Scattergun", itemname = "TF_WEAPON_SCATTERGUN", model = "models/weapons/w_models/w_scattergun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Stickybomb Launcher", itemname = "TF_WEAPON_PIPEBOMBLAUNCHER", model = "models/weapons/w_models/w_stickybomb_launcher.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Stickybomb Launcher", itemname = "TF_WEAPON_PIPEBOMBLAUNCHER", model = "models/weapons/w_models/w_stickybomb_launcher.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Crusader's Crossbow", itemname = "The Crusader's Crossbow", model = "models/weapons/c_models/c_crusaders_crossbow/c_crusaders_crossbow.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Crusader's Crossbow", itemname = "The Crusader's Crossbow", model = "models/weapons/c_models/c_crusaders_crossbow/c_crusaders_crossbow.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Beam Rifle", itemname = "Beam Rifle", model = "models/workshop/weapons/c_models/c_drg_pomson/c_drg_pomson.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Punch Packer", itemname = "The Punch Packer", model = "models/weapons/c_models/c_packer.mdl", slot = "primary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Ray Gun", itemname = "The Ray Gun", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Cleaner's Carbine", itemname = "The Cleaner's Carbine", model = "models/workshop/weapons/c_models/c_pro_smg/c_pro_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "a dud", itemname = "Dud", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl"}, }, [3] = { {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Rocket Launcher", itemname = "TF_WEAPON_ROCKETLAUNCHER", model = "models/weapons/w_models/w_rocketlauncher.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Rocket Launcher", itemname = "TF_WEAPON_ROCKETLAUNCHER", model = "models/weapons/w_models/w_rocketlauncher.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Beam Rifle", itemname = "Beam Rifle", model = "models/workshop/weapons/c_models/c_drg_pomson/c_drg_pomson.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Tactigatling", itemname = "Tactigatling", model = "models/weapons/c_models/c_tgat/c_tgat.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Ray Gun", itemname = "The Ray Gun", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Cleaner's Carbine", itemname = "The Cleaner's Carbine", model = "models/workshop/weapons/c_models/c_pro_smg/c_pro_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Cleaner's Carbine", itemname = "The Cleaner's Carbine", model = "models/workshop/weapons/c_models/c_pro_smg/c_pro_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Thunder Gun", itemname = "Thunder Gun", model = "models/weapons/c_models/c_drg_phlogistinator/c_drg_phlogistinator.mdl", slot = "secondary", response = "TLK_MVM_LOOT_ULTRARARE"}, {text = "a dud", itemname = "Dud", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl"}, }, [4] = { -- {text = "The Shotgun", itemname = "TF_WEAPON_SHOTGUN_PYRO", model = "models/weapons/w_models/w_shotgun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, -- removed due to loadout issues -- {text = "The Shotgun", itemname = "TF_WEAPON_SHOTGUN_PYRO", model = "models/weapons/w_models/w_shotgun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, -- uberupgrade takes away Primary weapon {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Stickybomb Launcher", itemname = "TF_WEAPON_PIPEBOMBLAUNCHER", model = "models/weapons/w_models/w_stickybomb_launcher.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Stickybomb Launcher", itemname = "TF_WEAPON_PIPEBOMBLAUNCHER", model = "models/weapons/w_models/w_stickybomb_launcher.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Beam Rifle", itemname = "Beam Rifle", model = "models/workshop/weapons/c_models/c_drg_pomson/c_drg_pomson.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Tactigatling", itemname = "Tactigatling", model = "models/weapons/c_models/c_tgat/c_tgat.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Ray Gun", itemname = "The Ray Gun", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "a dud", itemname = "Dud", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl"}, }, [5] = { {text = "The Scattergun", itemname = "TF_WEAPON_SCATTERGUN", model = "models/weapons/w_models/w_scattergun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Scattergun", itemname = "TF_WEAPON_SCATTERGUN", model = "models/weapons/w_models/w_scattergun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Flamethrower", itemname = "TF_WEAPON_FLAMETHROWER", model = "models/weapons/c_models/c_flamethrower/c_flamethrower.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Flamethrower", itemname = "TF_WEAPON_FLAMETHROWER", model = "models/weapons/c_models/c_flamethrower/c_flamethrower.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Punch Packer", itemname = "The Punch Packer", model = "models/weapons/c_models/c_packer.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Punch Packer", itemname = "The Punch Packer", model = "models/weapons/c_models/c_packer.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "Primary SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "Primary SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Crusader's Crossbow", itemname = "The Crusader's Crossbow", model = "models/weapons/c_models/c_crusaders_crossbow/c_crusaders_crossbow.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Crusader's Crossbow", itemname = "The Crusader's Crossbow", model = "models/weapons/c_models/c_crusaders_crossbow/c_crusaders_crossbow.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The DNA Rejuvenator", itemname = "DNA Rejuvenator", model = "models/workshop/weapons/c_models/c_uberneedle/c_uberneedle.mdl", slot = "melee", response = "TLK_MVM_LOOT_ULTRARARE"}, {text = "Das Maschinenpistole", itemname = "Das Maschinenpistole", model = "models/weapons/c_models/c_mp40/c_mp40.mdl", slot = "primary", response = "TLK_MVM_LOOT_RARE"}, {text = "Das Maschinenpistole", itemname = "Das Maschinenpistole", model = "models/weapons/c_models/c_mp40/c_mp40.mdl", slot = "primary", response = "TLK_MVM_LOOT_RARE"}, {text = "a dud", itemname = "Dud", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl"}, }, [6] = { {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Flamethrower", itemname = "TF_WEAPON_FLAMETHROWER", model = "models/weapons/c_models/c_flamethrower/c_flamethrower.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Flamethrower", itemname = "TF_WEAPON_FLAMETHROWER", model = "models/weapons/c_models/c_flamethrower/c_flamethrower.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Minigun", itemname = "TF_WEAPON_MINIGUN", model = "models/weapons/w_models/w_minigun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Minigun", itemname = "TF_WEAPON_MINIGUN", model = "models/weapons/w_models/w_minigun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Beam Rifle", itemname = "Beam Rifle", model = "models/workshop/weapons/c_models/c_drg_pomson/c_drg_pomson.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Tactigatling", itemname = "Tactigatling", model = "models/weapons/c_models/c_tgat/c_tgat.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Ray Gun", itemname = "The Ray Gun", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Thunder Gun", itemname = "Thunder Gun", model = "models/weapons/c_models/c_drg_phlogistinator/c_drg_phlogistinator.mdl", slot = "secondary", response = "TLK_MVM_LOOT_ULTRARARE"}, {text = "a dud", itemname = "Dud", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl"}, }, [7] = { {text = "The Dragon's Fury", itemname = "The Dragon's Fury", model = "models/weapons/c_models/c_flameball/c_flameball.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Dragon's Fury", itemname = "The Dragon's Fury", model = "models/weapons/c_models/c_flameball/c_flameball.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Double Barrel", itemname = "Double Barrel", model = "models/weapons/c_models/c_shotfun/c_shotfun.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Flamethrower", itemname = "TF_WEAPON_FLAMETHROWER", model = "models/weapons/c_models/c_flamethrower/c_flamethrower.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Flamethrower", itemname = "TF_WEAPON_FLAMETHROWER", model = "models/weapons/c_models/c_flamethrower/c_flamethrower.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Minigun", itemname = "TF_WEAPON_MINIGUN", model = "models/weapons/w_models/w_minigun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Minigun", itemname = "TF_WEAPON_MINIGUN", model = "models/weapons/w_models/w_minigun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Tactigatling", itemname = "Tactigatling", model = "models/weapons/c_models/c_tgat/c_tgat.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Ray Gun", itemname = "The Ray Gun", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Thunder Gun", itemname = "Thunder Gun", model = "models/weapons/c_models/c_drg_phlogistinator/c_drg_phlogistinator.mdl", slot = "secondary", response = "TLK_MVM_LOOT_ULTRARARE"}, {text = "a dud", itemname = "Dud", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl"}, }, --[8]spy excluded because he is unplayable [9] = { {text = "The Shotgun", itemname = "TF_WEAPON_SHOTGUN_PRIMARY", model = "models/weapons/w_models/w_shotgun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Shotgun", itemname = "TF_WEAPON_SHOTGUN_PRIMARY", model = "models/weapons/w_models/w_shotgun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Scattergun", itemname = "TF_WEAPON_SCATTERGUN", model = "models/weapons/w_models/w_scattergun.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The SMG", itemname = "TF_WEAPON_SMG", model = "models/weapons/w_models/w_smg.mdl", slot = "secondary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The B.M.M.H", itemname = "The B.M.M.H", model = "models/weapons/c_models/c_bmmh/c_bmmh.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The B.M.M.H", itemname = "The B.M.M.H", model = "models/weapons/c_models/c_bmmh/c_bmmh.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Nostromo Napalmer", itemname = "The Nostromo Napalmer", model = "models/workshop_partner/weapons/c_models/c_ai_flamethrower/c_ai_flamethrower.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Nostromo Napalmer", itemname = "The Nostromo Napalmer", model = "models/workshop_partner/weapons/c_models/c_ai_flamethrower/c_ai_flamethrower.mdl", slot = "primary", response = "TLK_MVM_LOOT_COMMON"}, {text = "The Punch Packer", itemname = "The Punch Packer", model = "models/weapons/c_models/c_packer.mdl", slot = "primary", response = "TLK_MVM_LOOT_RARE"}, {text = "The Ray Gun", itemname = "The Ray Gun", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl", slot = "secondary", response = "TLK_MVM_LOOT_RARE"}, {text = "a dud", itemname = "Dud", model = "models/workshop/weapons/c_models/c_invasion_pistol/c_invasion_pistol.mdl"}, } } function SpawnDumpsterBox(box) if FireSaleDuration <= 0 then BoxTable[box].firesale = false BoxTable[box].dud = true end if BoxTable[box].spawned == false then BoxTable[box].spawned = true ents.FindByName("dumpster_push"..box):AcceptInput("$TeleportToEntity","dumpster_tele_"..box) ents.FindByName("dumpster_push"..box):AcceptInput("Enable") ents.FindByName("dumpster_lid"..box):AcceptInput("TurnOff") ents.FindByName("dumpster_weapon"..box):AcceptInput("TurnOff") ents.FindByName("dumpster_prop"..box):AcceptInput("TurnOff") ents.FindByName("dumpster_light"..box):AcceptInput("TurnOff") ents.FindByName("dumpster_msg"..box):AcceptInput("Disable") ents.FindByName("dumpster_weapon"..box):AcceptInput("SetParent","dumpster_train"..box) timer.Simple(1, function() ents.FindByName("dumpster_prop"..box):AcceptInput("$TeleportToEntity","dumpster_tele_"..box) end) timer.Simple(1, function() ents.FindByName("dumpster_warp_eff"..box):AcceptInput("Start") end) timer.Simple(1, function() ents.FindByName("dumpster_warp_beam"..box):AcceptInput("Start") end) timer.Simple(1.5, function() ents.FindByName("dumpster_appear"..box):AcceptInput("PlaySound") end) timer.Simple(2, function() ents.FindByName("dumpster_lid"..box):AcceptInput("TurnOn") end) timer.Simple(2, function() ents.FindByName("dumpster_prop"..box):AcceptInput("TurnOn") end) timer.Simple(2, function() ents.FindByName("dumpster_msg"..box):AcceptInput("Enable") end) timer.Simple(2, function() ents.FindByName("dumpster_push"..box):AcceptInput("Disable") end) timer.Simple(3.2, function() ents.FindByName("dumpster_warp_eff"..box):AcceptInput("Stop") end) BoxTable[box].message = ents.FindByName("dumpster_msg"..box):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "dumpsterbutton"..box player:Print(PRINT_TARGET_CENTER, "Hold Action key to receive a weapon for $"..DumpsterCost) end end) ents.FindByName("dumpster_msg"..box):AddCallback(ON_END_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "nothing" player:Print(PRINT_TARGET_CENTER, "") end end) end end function OpenDumpsterBox(player, box) local owner = player BoxTable[box].count = BoxTable[box].count + 1 BoxTable[box].opened = true ents.FindByName("dumpster_rotdoor"..box):AcceptInput("Open") ents.FindByName("dumpster_light"..box):AcceptInput("TurnOn") ents.FindByName("dumpster_msg"..box):AcceptInput("Disable") ents.FindByName("dumpster_train"..box):AcceptInput("SetSpeed", "0.2") ents.FindByName("dumpster_jingle"..box):AcceptInput("PlaySound") ents.FindByName("dumpster_weapon"..box):AcceptInput("Enable") ents.FindByName("dumpster_particles"..box):AcceptInput("Start") ents.FindByName("dumpster_train"..box):AcceptInput("TeleportToPathTrack", "dumpster_track1"..box) ents.FindByName("dumpster_msg"..box):RemoveCallback(14,BoxTable[box].message) local ChangeWeapon = timer.Create(0.1, function() local number = math.random(1, #BoxRoulette[player.m_iClass]) ents.FindByName("dumpster_weapon"..box):AcceptInput("$SetModel", BoxRoulette[player.m_iClass][number].model) BoxTable[box].weapon = BoxRoulette[player.m_iClass][number].itemname BoxTable[box].text = BoxRoulette[player.m_iClass][number].text BoxTable[box].slot = BoxRoulette[player.m_iClass][number].slot BoxTable[box].response = BoxRoulette[player.m_iClass][number].response end, 0 ) timer.Simple(4, function() timer.Stop(ChangeWeapon) if BoxTable[box].weapon == "Dud" then if BoxTable[box].dud == true and BoxTable[box].firesale == false and BoxTable[box].count >= 4 then BoxTable[box].count = 0 if DumpsterRouletteIndex == 5 then ShuffleInPlace(DumpsterRoulette) DumpsterRouletteIndex = 0 end DumpsterRouletteIndex = DumpsterRouletteIndex+1 ents.FindByName("dumpster_dudprop"..box):AcceptInput("Enable") ents.FindByName("dumpster_weapon"..box):AcceptInput("Disable") player:AddCurrency("950") player:PlaySoundToSelf("misc/happy_birthday_tf_10.wav") timer.Simple(1, function() player:PlaySoundToSelf("shadows/powerup_dud_03.mp3") end) timer.Simple(3, function() ents.FindByName("dumpster_warp_eff"..box):AcceptInput("Start") end) timer.Simple(3, function() ents.FindByName("dumpster_warp_beam"..box):AcceptInput("Stop") end) timer.Simple(3, function() ents.FindByName("dumpster_disappear"..box):AcceptInput("PlaySound") end) timer.Simple(4, function() ents.FindByName("dumpster_prop"..box):AcceptInput("$TeleportToEntity","dumpster_tele_out") end) timer.Simple(4, function() ents.FindByName("dumpster_dudprop"..box):AcceptInput("Disable") end) timer.Simple(4, function() BoxTable[box].spawned = false end) timer.Simple(24, function() SpawnDumpsterBox(DumpsterRouletteIndex) end) else number = math.random(1, #BoxRoulette[player.m_iClass]-1) ents.FindByName("dumpster_weapon"..box):AcceptInput("$SetModel", BoxRoulette[player.m_iClass][number].model) BoxTable[box].weapon = BoxRoulette[player.m_iClass][number].itemname BoxTable[box].text = BoxRoulette[player.m_iClass][number].text BoxTable[box].slot = BoxRoulette[player.m_iClass][number].slot BoxTable[box].response = BoxRoulette[player.m_iClass][number].response BoxTable[box].message = ents.FindByName("dumpster_msg"..box):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() and player == owner then player.InteractWith = "tradeweapon"..box player:Print(PRINT_TARGET_CENTER, "Hold Action key to trade your " .. BoxTable[box].slot .. " weapon with " .. BoxTable[box].text) end end) ents.FindByName("dumpster_msg"..box):AcceptInput("Enable") ents.FindByName("dumpster_train"..box):AcceptInput("TeleportToPathTrack", "dumpster_track2"..box) ents.FindByName("dumpster_train"..box):AcceptInput("SetSpeedDir", "0.02") end elseif BoxTable[box].weapon == "Thunder Gun" and ThunderGunTaken == true then ents.FindByName("dumpster_weapon"..box):AcceptInput("$SetModel", "models/weapons/c_models/c_shotfun/c_shotfun.mdl") BoxTable[box].weapon = "Double Barrel" BoxTable[box].text = "The Double Barrel" BoxTable[box].slot = "secondary" BoxTable[box].response = "TLK_MVM_LOOT_COMMON" elseif BoxTable[box].weapon == "DNA Rejuvenator" and RejuvenatorTaken == true then ents.FindByName("dumpster_weapon"..box):AcceptInput("$SetModel", "models/weapons/w_models/w_smg.mdl") BoxTable[box].weapon = "Primary SMG" BoxTable[box].text = "The SMG" BoxTable[box].slot = "primary" BoxTable[box].response = "TLK_MVM_LOOT_COMMON" BoxTable[box].message = ents.FindByName("dumpster_msg"..box):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() and player == owner then player.InteractWith = "tradeweapon"..box player:Print(PRINT_TARGET_CENTER, "Hold Action key to trade your " .. BoxTable[box].slot .. " weapon with " .. BoxTable[box].text) end end) else BoxTable[box].message = ents.FindByName("dumpster_msg"..box):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() and player == owner then player.InteractWith = "tradeweapon"..box player:Print(PRINT_TARGET_CENTER, "Hold Action key to trade your " .. BoxTable[box].slot .. " weapon with " .. BoxTable[box].text) end end) ents.FindByName("dumpster_msg"..box):AcceptInput("Enable") ents.FindByName("dumpster_train"..box):AcceptInput("TeleportToPathTrack", "dumpster_track2"..box) ents.FindByName("dumpster_train"..box):AcceptInput("SetSpeedDir", "0.02") end end) BoxTable[box].timer = timer.Simple(14, function() ents.FindByName("dumpster_msg"..box):AcceptInput("Disable") ents.FindByName("dumpster_msg"..box):RemoveCallback(14,BoxTable[box].message) BoxTable[box].message = ents.FindByName("dumpster_msg"..box):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "dumpsterbutton"..box player:Print(PRINT_TARGET_CENTER, "Hold Action key to receive a weapon for $"..DumpsterCost) end end) timer.Simple(1, function() ents.FindByName("dumpster_msg"..box):AcceptInput("Enable") end) timer.Simple(1, function() BoxTable[box].opened = false end) ents.FindByName("dumpster_rotdoor"..box):AcceptInput("Close") ents.FindByName("dumpster_particles"..box):AcceptInput("Stop") ents.FindByName("dumpster_light"..box):AcceptInput("TurnOff") ents.FindByName("dumpster_weapon"..box):AcceptInput("Disable") if BoxTable[box].firesale == true and FireSaleDuration <= 0 then ents.FindByName("dumpster_warp_eff"..box):AcceptInput("Start") ents.FindByName("dumpster_warp_beam"..box):AcceptInput("Stop") ents.FindByName("dumpster_disappear"..box):AcceptInput("PlaySound") timer.Simple(1, function() ents.FindByName("dumpster_prop"..box):AcceptInput("$TeleportToEntity","dumpster_tele_out") end) timer.Simple(1, function() ents.FindByName("dumpster_msg"..box):AcceptInput("Disable") end) BoxTable[box].spawned = false end end) end function DumpsterBoxTakeWeapon(player, box) ents.FindByName("dumpster_msg"..box):AcceptInput("Disable") ents.FindByName("dumpster_particles"..box):AcceptInput("Stop") ents.FindByName("dumpster_rotdoor"..box):AcceptInput("Close") ents.FindByName("dumpster_light"..box):AcceptInput("TurnOff") ents.FindByName("dumpster_weapon"..box):AcceptInput("Disable") player:GiveItem(BoxTable[box].weapon) if BoxTable[box].weapon == "Thunder Gun" then ThunderGunTaken = true end if BoxTable[box].weapon == "DNA Rejuvenator" then RejuvenatorTaken = true end -- nuh uh you get only one of these like tgun if BoxTable[box].slot == "primary" then player.loadout[0] = BoxTable[box].weapon end if BoxTable[box].slot == "secondary" then player.loadout[1] = BoxTable[box].weapon end if BoxTable[box].slot == "melee" then player.loadout[2] = BoxTable[box].weapon end -- this line is for a single weapon :^) player:RefillAmmo() player:SpeakResponseConcept(BoxTable[box].response, 0.6) player:PlaySoundToSelf("items/gunpickup2.wav") player:DisplayTextChat("You've received: " .. BoxTable[box].text .. "!") timer.Stop(BoxTable[box].timer) ents.FindByName("dumpster_msg"..box):RemoveCallback(14,BoxTable[box].message) BoxTable[box].message = ents.FindByName("dumpster_msg"..box):AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "dumpsterbutton"..box player:Print(PRINT_TARGET_CENTER, "Hold Action key to receive a weapon for $"..DumpsterCost) end end) timer.Simple(1, function() ents.FindByName("dumpster_msg"..box):AcceptInput("Enable") end) timer.Simple(1, function() BoxTable[box].opened = false end) if BoxTable[box].firesale == true and FireSaleDuration <= 0 then ents.FindByName("dumpster_warp_eff"..box):AcceptInput("Start") ents.FindByName("dumpster_warp_beam"..box):AcceptInput("Stop") ents.FindByName("dumpster_disappear"..box):AcceptInput("PlaySound") timer.Simple(1, function() ents.FindByName("dumpster_prop"..box):AcceptInput("$TeleportToEntity","dumpster_tele_out") end) timer.Simple(1, function() ents.FindByName("dumpster_msg"..box):AcceptInput("Disable") end) BoxTable[box].spawned = false end end function GiveSuperShank(_,player) player:GiveItem("Super Shank") player.loadout[2] = "Super Shank" end -- return of Sntr, the logic below is a portover from Titanium Thieves function spawn_revive_marker(_, activator) local revive_marker = nil for _, marker in pairs(ents.FindAllByClass("entity_revive_marker")) do if marker.m_hOwner == activator then revive_marker = marker end end if (not revive_marker) then return end if Gamerules.m_iRoundState == GR_STATE_BETWEEN_RNDS then timer.Simple(5.0, function() if (not activator:IsAlive()) then activator:ForceRespawnDead() end end) end local template_ents = ents.SpawnTemplate("Revivemarker", {parent = revive_marker}) local revive_trigger = template_ents[1] revive_trigger:AddCallback(ON_START_TOUCH, function(_, player) if player:IsRealPlayer() then player.InteractWith = "revive_button" player.TouchingReviveMarker = revive_marker end end) revive_trigger:AddCallback(ON_END_TOUCH, function(_, player) if player:IsRealPlayer() then -- TODO: Clearing InteractWith like this will introduce targeting issues -- for multiple overlapping triggers. -- Should use some kind of queue that tracks all of these and sets -- InteractWith based on priority in that queue and touch recency. player:Print(PRINT_TARGET_CENTER, "") player.InteractWith = "nothing" player.TouchingReviveMarker = nil end end) end function revivelogic(_, activator) -- haw haw now start living -- There's now Mince in here as well, everyone's invited to Shadows -- still has the thing where it stays active!! if (not IsValid(activator) or not activator:IsAlive()) then return end -- No reviving while midair. if (not activator.m_hGroundEntity) then return end local reanimator = activator.TouchingReviveMarker activator:SetAttributeValue("always allow taunt", 1) activator:TauntFromItem("Laugh Taunt") think_timer = timer.Simple(0.65, function() if (not IsValid(activator) or not activator:IsAlive()) then return end activator:SetAttributeValue("always allow taunt", 0) activator:StunPlayer(0, 1, TF_STUNFLAG_BONKSTUCK) activator.m_hActiveWeapon:RemoveEffects(EF_NODRAW) -- The revive marker may be removed in the time it takes us to complete -- the revive process. if (reanimator:IsValid()) then reanimator.m_hOwner:ForceRespawnDead() reanimator.m_hOwner:Teleport(activator:GetAbsOrigin()) reanimator.m_hOwner:AddCond(TF_COND_INVULNERABLE_HIDE_UNLESS_DAMAGED, 2) reanimator.m_hOwner:PlaySound("MVM.PlayerRevived") reanimator.m_hOwner:SpeakResponseConcept("TLK_RESURRECTED") end end) end function AddLateJoiners(_) for _, player in pairs(ents.GetAllPlayers()) do if player:IsRealPlayer() and player.m_iTeamNum == TEAM_RED and player.m_iClass == TF_CLASS_UNDEFINED then player:SwitchClassInPlace(player.m_iDesiredPlayerClass) -- SwitchClass does not work but this arrangement does. player:ForceRespawn() end end end function AddSnapToGroundCallback(targetname) prop = ents.FindByName(targetname) prop:AddCallback(ON_INPUT, function(entity, inputName, value, activator, caller) if (inputName:lower() ~= "enable") then return end local result = util.Trace( { start = entity:GetAbsOrigin(), distance = MAX_COORD_FLOAT, angles = Vector(90.0, 0.0, 0.0), mask = MASK_PLAYERSOLID_BRUSHONLY }) if result.Hit then entity:SetAbsOrigin(result.HitPos) end end) end TutorialAnnotations = { "Money is earned by dealing damage and killing enemies.", "Enemies become faster and stronger each round.", "You can revive teammates by holding the Action key at their reanimator.", "You can purchase Perk Bonuses from vending machines around the map.", "Perk Bonuses are not permanent and are lost on death.", "Perk Bonuses stack with your weapon upgrades.", "Perk Bonuses cannot be purchased multiple times per life.", "You can also receive random weapons from your local Weapons Dumpster.", "Dumpster Weapons are returned to you after respawning.", "Medics supply ammo and health to nearby teammates.", "Moving and crouching both affect your accuracy.", "Powerups have a chance to drop from zombies during waves.", "Powerups despawn 30 seconds after being dropped." } CurrentTutorialAnnotation = 1 TutorialTimer = -1 function StartTutorial() if Gamerules.m_iRoundState ~= GR_STATE_BETWEEN_RNDS then return end FireEvent("show_annotation", { text = TutorialAnnotations[CurrentTutorialAnnotation], lifetime = 4, worldPosX = 328, worldPosY = -150, worldPosZ = 52, play_sound = "misc/null.wav" }) if CurrentTutorialAnnotation >= #TutorialAnnotations then CurrentTutorialAnnotation = 1 else CurrentTutorialAnnotation = CurrentTutorialAnnotation + 1 end TutorialTimer = timer.Create(4.0, StartTutorial) end function StopTutorial() FireEvent("hide_annotation", {}) if TutorialTimer ~= -1 then timer.Stop(TutorialTimer) TutorialTimer = -1 end end precache.PrecacheSound("ui/hint.wav") function ShowDumpsterAnnotation() FireEvent("show_annotation", { text = "Follow the beam of light to find the Weapons Dumpster!", lifetime = 5, play_sound = "ui/hint.wav", follow_entindex = ents.FindByName("dumpster_prop" .. DumpsterRoulette[1]):GetNetIndex() }) end