local missionInfo = { SentryBusterWaitBeforeStarting = 20, SentryBusterWaitBetweenSpawns = 20, } local Soldier_BurstFire = { Class = CLASSES.Soldier, Name = "Giga Burst Fire Soldier", ClassIcon = "soldier_burstfire", Health = 4200, Skill = BOT_SKILL.EXPERT, WeaponRestrictions = WEAPON_RESTRICTIONS.PRIMARY_ONLY, Attributes = { BOT_ATTRIBUTES.MINIBOSS, BOT_ATTRIBUTES.HOLD_FIRE_UNTIL_FULL_RELOAD, BOT_ATTRIBUTES.ALWAYS_CRIT, }, Items = { "Armored Authority" }, ItemAttributes = { ["TF_WEAPON_ROCKETLAUNCHER"] = { ["damage bonus"] = 2.0, ["faster reload rate"] = 0.4, ["fire rate bonus"] = 0.2, ["clip size upgrade atomic"] = 5.0, }, }, CharacterAttributes = { ["move speed bonus"] = 0.5, ["damage force reduction"] = 0.4, ["airblast vulnerability multiplier"] = 0.4, ["override footstep sound set"] = 3, ["Projectile speed increased"] = 0.9, }, } local function makeEngineerMission(wave, waitBeforeStarting, waitBetweenSpawnsAfterDeath) return { Name = "engineer_mission_w" .. tostring(wave), Where = "spawnbot", WaitBeforeStarting = waitBeforeStarting, WaitBetweenSpawnsAfterDeath = waitBetweenSpawnsAfterDeath, SupportInfinite = true, IsMission = true, TotalCount = 1, SpawnCount = 1, MaxActive = 1, TotalCurrency = 0, Templates = { ROBOT_STANDARD.Engineer_Sentry_Teleporter, }, } end --======================================================== -- SUPPORT MISSIONS (converted → SupportInfinite waves) --======================================================== local mission_spy_w1 = { Name = "spy_mission_w1", Where = "spawnbot_mission_spy", WaitBeforeStarting = 90, WaitBetweenSpawnsAfterDeath = 60, SupportInfinite = true, IsMission = true, TotalCount = 4, SpawnCount = 4, MaxActive = 4, TotalCurrency = 0, SendSpyAnnouncement = true, Templates = { { Class = CLASSES.Spy, Skill = BOT_SKILL.EXPERT, Name = "Spy", }, }, } local mission_spy_w7 = { Name = "spy_mission_w7", Where = "spawnbot_mission_spy", WaitBeforeStarting = 5, WaitBetweenSpawnsAfterDeath = 35, SupportInfinite = true, IsMission = true, TotalCount = 10, SpawnCount = 10, MaxActive = 10, TotalCurrency = 0, SendSpyAnnouncement = true, Templates = { { Class = CLASSES.Spy, Skill = BOT_SKILL.EXPERT, Name = "Spy", }, }, } local mission_sniper_w1 = { Name = "sniper_mission_w1", Where = "spawnbot_mission_sniper", WaitBeforeStarting = 120, WaitBetweenSpawnsAfterDeath = 60, SupportInfinite = true, IsMission = true, TotalCount = 2, SpawnCount = 2, MaxActive = 2, TotalCurrency = 0, SendSniperAnnouncement = true, Templates = { { Class = CLASSES.Sniper, Skill = BOT_SKILL.HARD, Name = "Sniper", MaxVisionRange = 3000, }, }, } local mission_sniper_w5 = { Name = "sniper_mission_w5", Where = "spawnbot_mission_sniper", WaitBeforeStarting = 60, WaitBetweenSpawnsAfterDeath = 10, SupportInfinite = true, IsMission = true, TotalCount = 4, SpawnCount = 4, MaxActive = 4, TotalCurrency = 0, SendSniperAnnouncement = true, Templates = { Extend(ROBOT_STANDARD.Sniper_Sydney_Sleeper, { Name = "Sydney sniper", Items = { "The Razorback" }, }), }, } local mission_sniper_w6 = { Name = "sniper_mission_w6", Where = "spawnbot_mission_sniper", WaitBeforeStarting = 60, WaitBetweenSpawnsAfterDeath = 30, SupportInfinite = true, IsMission = true, TotalCount = 2, SpawnCount = 2, MaxActive = 2, TotalCurrency = 0, SendSniperAnnouncement = true, Templates = { { Class = CLASSES.Sniper, Skill = BOT_SKILL.HARD, Name = "Sniper", MaxVisionRange = 3000, }, }, } local mission_sniper_w7 = { Name = "sniper_mission_w7", Where = "spawnbot_mission_sniper", WaitBeforeStarting = 20, WaitBetweenSpawnsAfterDeath = 20, SupportInfinite = true, IsMission = true, TotalCount = 6, SpawnCount = 6, MaxActive = 6, TotalCurrency = 0, SendSniperAnnouncement = true, Templates = { ROBOT_STANDARD.Sniper, }, } --======================================================== -- WAVE 1 --======================================================== local wave1 = { mission_spy_w1, mission_sniper_w1, makeEngineerMission(1, 60, 60), { Name = "wave01a", Where = "spawnbot", WaitBeforeStarting = 4, WaitBetweenSpawns = 5, TotalCount = 36, SpawnCount = 6, MaxActive = 18, TotalCurrency = 300, IsSquad = true, Templates = { { Class = CLASSES.Scout, Skill = BOT_SKILL.EASY, }, { Class = CLASSES.Scout, Skill = BOT_SKILL.EASY, }, ROBOT_STANDARD.Scout_Bonk, ROBOT_STANDARD.Scout_Bonk, ROBOT_STANDARD.Scout_Bonk, { Class = CLASSES.Soldier, Skill = BOT_SKILL.EXPERT, Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, ItemAttributes = { ["TF_WEAPON_ROCKETLAUNCHER"] = { ["faster reload rate"] = -0.8, ["fire rate bonus"] = 0.6, }, }, }, }, }, { Name = "wave01b", Where = "spawnbot", WaitBeforeStarting = 45, WaitBetweenSpawns = 60, TotalCount = 4, SpawnCount = 1, MaxActive = 4, TotalCurrency = 300, Templates = { ROBOT_GIANT.Giant_Soldier_Spammer, }, }, { Name = "wave01c", Where = "spawnbot", WaitForAllDead = "wave01a", WaitBeforeStarting = 30, WaitBetweenSpawns = 15, TotalCount = 40, SpawnCount = 5, MaxActive = 20, TotalCurrency = 350, IsSquad = true, Templates = { { Class = CLASSES.Heavyweapons, Skill = BOT_SKILL.EASY, Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, }, ROBOT_STANDARD.Medic_QuickUber, { Class = CLASSES.Pyro, Skill = BOT_SKILL.EASY, }, { Class = CLASSES.Pyro, Skill = BOT_SKILL.EASY, }, { Class = CLASSES.Pyro, Skill = BOT_SKILL.EASY, }, }, }, { Name = "wave01d", Where = "spawnbot", WaitForAllSpawned = "wave01c", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, TotalCount = 40, SpawnCount = 8, MaxActive = 22, TotalCurrency = 350, Templates = { { Class = CLASSES.Scout, Skill = BOT_SKILL.EASY, WeaponRestrictions = WEAPON_RESTRICTIONS.MELEE_ONLY, Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, }, }, }, } --======================================================== -- WAVE 2 --======================================================== local wave2 = { makeEngineerMission(2, 60, 60), { Name = "wave02a", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 2, TotalCount = 48, SpawnCount = 6, MaxActive = 12, TotalCurrency = 250, Templates = { ROBOT_STANDARD.Sniper_Huntsman, }, }, { Name = "wave02b", Where = "", WaitBeforeStarting = 25, TotalCount = 1, SpawnCount = 1, MaxActive = 1, TotalCurrency = 300, Templates = { { IsTank = true, Name = "tankboss", Health = 40000, Speed = 75, StartingPathTrackNode = "boss_path_a1", }, }, }, { Name = "wave02c", Where = "spawnbot", WaitBeforeStarting = 45, WaitBetweenSpawns = 30, TotalCount = 3, SpawnCount = 1, MaxActive = 3, TotalCurrency = 100, Templates = { ROBOT_GIANT.Giant_Scout_Fast, }, }, { Name = "wave02d", Where = "spawnbot", WaitForAllSpawned = "wave02a", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, TotalCount = 2, SpawnCount = 2, MaxActive = 2, TotalCurrency = 150, IsSquad = true, Templates = { ROBOT_GIANT.Giant_Heavyweapons_Deflector, ROBOT_GIANT.Giant_Medic, }, }, { Name = "wave02ef", Where = "spawnbot", WaitForAllDead = "wave02b", WaitBeforeStarting = 3, WaitBetweenSpawns = 5, TotalCount = 40, SpawnCount = 10, MaxActive = 10, TotalCurrency = 300, Templates = { { Class = CLASSES.Soldier, Skill = BOT_SKILL.HARD, }, }, }, { Name = "wave02ef", Where = "spawnbot", WaitForAllDead = "wave02b", WaitBeforeStarting = 10, WaitBetweenSpawns = 20, TotalCount = 10, SpawnCount = 2, MaxActive = 10, TotalCurrency = 400, IsSquad = true, Templates = { ROBOT_GIANT.Giant_Soldier_Crit, ROBOT_STANDARD.Medic_QuickUber, }, }, { Name = "wave02g", Where = "spawnbot", WaitForAllSpawned = "wave02ef", WaitBeforeStarting = 0, WaitBetweenSpawns = 30, TotalCount = 3, SpawnCount = 3, MaxActive = 3, TotalCurrency = 100, Templates = { ROBOT_GIANT.Giant_Scout_Fast, }, }, } --======================================================== -- WAVE 3 --======================================================== local wave3 = { makeEngineerMission(3, 60, 60), { Name = "wave03a", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 2, TotalCount = 20, SpawnCount = 4, MaxActive = 20, TotalCurrency = 200, IsSquad = true, Templates = { { Class = CLASSES.Pyro, Skill = BOT_SKILL.HARD, }, ROBOT_STANDARD.Medic_QuickUber, }, }, { Name = "wave03a_burstfire", Where = "spawnbot", WaitBeforeStarting = 10, WaitBetweenSpawns = 1, TotalCount = 1, SpawnCount = 1, MaxActive = 1, TotalCurrency = 50, Templates = { Soldier_BurstFire, }, }, { Name = "wave03b", Where = "_random", WaitForAllDead = "wave03a", WaitBeforeStarting = 0, WaitBetweenSpawns = 1, TotalCount = 45, SpawnCount = 9, MaxActive = 18, TotalCurrency = 250, Templates = { Extend(ROBOT_STANDARD.Sniper_Huntsman, { Skill = BOT_SKILL.EXPERT, Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, ItemAttributes = { ["The Huntsman"] = { ["faster reload rate"] = 0.2, }, }, }), }, }, { Name = "wave03c", Where = "spawnbot", WaitForAllDead = "wave03a", WaitBeforeStarting = 10, WaitBetweenSpawns = 13, TotalCount = 12, SpawnCount = 3, MaxActive = 12, TotalCurrency = 200, Templates = { ROBOT_GIANT.Giant_Demo_RapidFire, }, }, { Name = "wave03d", Where = "spawnbot", WaitForAllDead = "wave03b", WaitBeforeStarting = 0, WaitBetweenSpawns = 7, TotalCount = 16, SpawnCount = 2, MaxActive = 10, TotalCurrency = 200, IsSquad = true, Templates = { { Class = CLASSES.Heavyweapons, Skill = BOT_SKILL.EXPERT, Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, ItemAttributes = { ["TF_WEAPON_MINIGUN"] = { ["damage bonus"] = 1.5, }, }, }, ROBOT_STANDARD.Medic_QuickUber, }, }, { Name = "wave03e", Where = "", WaitForAllSpawned = "wave03c", WaitBeforeStarting = 0, TotalCount = 1, SpawnCount = 1, MaxActive = 1, TotalCurrency = 200, Templates = { { IsTank = true, Name = "tankboss", Health = 30000, Speed = 75, StartingPathTrackNode = "boss_path_a1", }, }, }, { Name = "wave03f", Where = "spawnbot", WaitForAllSpawned = "wave03c", WaitBeforeStarting = 5, WaitBetweenSpawns = 10, SupportInfinite = true, TotalCount = 66, SpawnCount = 11, MaxActive = 22, TotalCurrency = 200, Templates = { { Class = CLASSES.Scout, Skill = BOT_SKILL.EASY, }, }, }, } --======================================================== -- WAVE 4 --======================================================== local wave4 = { makeEngineerMission(4, 60, 60), { Name = "wave04a", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 2, TotalCount = 100, SpawnCount = 8, MaxActive = 14, TotalCurrency = 300, Templates = { { Class = CLASSES.Spy, Skill = BOT_SKILL.EXPERT, }, }, }, { Name = "wave04b", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, SupportInfinite = true, TotalCount = 128, SpawnCount = 8, MaxActive = 8, TotalCurrency = 400, Templates = { { Class = CLASSES.Scout, Skill = BOT_SKILL.HARD, Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, }, }, }, { Name = "wave04c", Where = "spawnbot", WaitForAllSpawned = "wave04a", WaitBeforeStarting = 0, WaitBetweenSpawns = 20, TotalCount = 8, SpawnCount = 2, MaxActive = 8, TotalCurrency = 300, IsSquad = true, Templates = { Extend(ROBOT_GIANT.Giant_Heavyweapons, { Tags = { "flank_right" }, }), Extend(ROBOT_STANDARD.Medic_QuickUber, { ItemAttributes = { ["TF_WEAPON_MEDIGUN"] = { ["uber duration bonus"] = 4, }, }, }), }, }, { Name = "wave04c", Where = "spawnbot", WaitForAllSpawned = "wave04a", WaitBeforeStarting = 10, WaitBetweenSpawns = 20, TotalCount = 8, SpawnCount = 2, MaxActive = 8, TotalCurrency = 300, IsSquad = true, Templates = { Extend(ROBOT_GIANT.Giant_Heavyweapons, { Tags = { "flank_left" }, }), Extend(ROBOT_STANDARD.Medic_QuickUber, { ItemAttributes = { ["TF_WEAPON_MEDIGUN"] = { ["uber duration bonus"] = 4, }, }, }), }, }, } --======================================================== -- WAVE 5 --======================================================== local wave5 = { mission_sniper_w5, makeEngineerMission(5, 60, 11), { Name = "wave05a", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 15, TotalCount = 64, SpawnCount = 4, MaxActive = 12, TotalCurrency = 300, Templates = { ROBOT_STANDARD.Heavyweapons_Fist, }, }, { Name = "wave05b", Where = "spawnbot", WaitBeforeStarting = 10, WaitBetweenSpawns = 15, TotalCount = 64, SpawnCount = 3, MaxActive = 6, TotalCurrency = 300, Templates = { { Class = CLASSES.Soldier, Skill = BOT_SKILL.EXPERT, Name = "Crit Soldier", Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, ItemAttributes = { ["TF_WEAPON_ROCKETLAUNCHER"] = { ["damage bonus"] = 2.0, ["faster reload rate"] = -0.8, ["fire rate bonus"] = 0.6, }, }, }, }, }, { Name = "wave05c", Where = "spawnbot", WaitBeforeStarting = 30, WaitBetweenSpawns = 12, TotalCount = 22, SpawnCount = 2, MaxActive = 2, TotalCurrency = 50, IsSquad = true, Templates = { ROBOT_STANDARD.Heavyweapons_Fist, ROBOT_STANDARD.Medic_QuickUber, }, }, } --======================================================== -- WAVE 6 --======================================================== local wave6 = { mission_sniper_w6, { Name = "wave06abcde", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, TotalCount = 32, SpawnCount = 4, MaxActive = 4, TotalCurrency = 100, Templates = { { Class = CLASSES.Soldier, Skill = BOT_SKILL.EXPERT, Name = "Crit Soldier", Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, ItemAttributes = { ["TF_WEAPON_ROCKETLAUNCHER"] = { ["damage bonus"] = 2.0, ["faster reload rate"] = -0.8, ["fire rate bonus"] = 0.6, }, }, }, }, }, { Name = "wave06abcde", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, TotalCount = 32, SpawnCount = 4, MaxActive = 4, TotalCurrency = 100, Templates = { { Class = CLASSES.Heavyweapons, Skill = BOT_SKILL.EXPERT, Name = "Crit Heavy", Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, }, }, }, { Name = "wave06abcde", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, TotalCount = 32, SpawnCount = 4, MaxActive = 4, TotalCurrency = 150, Templates = { { Class = CLASSES.Pyro, Skill = BOT_SKILL.EXPERT, Name = "Crit Pyro", Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, ItemAttributes = { ["TF_WEAPON_FLAMETHROWER"] = { ["damage bonus"] = 2.0, }, }, CharacterAttributes = { ["move speed bonus"] = 1.5, }, }, }, }, { Name = "wave06abcde", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, TotalCount = 24, SpawnCount = 4, MaxActive = 4, TotalCurrency = 150, Templates = { { Class = CLASSES.Scout, Skill = BOT_SKILL.EXPERT, Name = "Crit Scout", Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, }, }, }, { Name = "wave06abcde", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, TotalCount = 24, SpawnCount = 4, MaxActive = 4, TotalCurrency = 150, Templates = { { Class = CLASSES.Demoman, Skill = BOT_SKILL.EXPERT, Name = "Crit Demo", Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, ItemAttributes = { ["TF_WEAPON_GRENADELAUNCHER"] = { ["Projectile speed increased"] = 2.0, ["faster reload rate"] = -0.8, ["damage bonus"] = 2.0, }, }, }, }, }, { Name = "wave06f", Where = "", WaitForAllSpawned = "wave06abcde", WaitBeforeStarting = 0, WaitBetweenSpawns = 30, TotalCount = 2, SpawnCount = 1, MaxActive = 2, TotalCurrency = 200, Templates = { { IsTank = true, Name = "tankboss", Health = 35000, Speed = 75, StartingPathTrackNode = "boss_path_a1", }, }, }, { Name = "wave06g", Where = "spawnbot", WaitForAllSpawned = "wave06abcde", WaitBeforeStarting = 45, WaitBetweenSpawns = 20, TotalCount = 8, SpawnCount = 2, MaxActive = 8, TotalCurrency = 50, Templates = { ROBOT_GIANT.Giant_Scout_Fast, }, }, { Name = "wave06h", Where = "spawnbot", WaitForAllDead = "wave06abcde", WaitBeforeStarting = 0, WaitBetweenSpawns = 40, TotalCount = 6, SpawnCount = 2, MaxActive = 6, TotalCurrency = 50, IsSquad = true, Templates = { Extend(ROBOT_GIANT.Giant_Heavyweapons_Deflector, { Attributes = { BOT_ATTRIBUTES.ALWAYS_CRIT }, Items = { "The Crone's Dome" }, }), Extend(ROBOT_GIANT.Giant_Medic, { Items = { "The Warsworn Helmet" }, }), }, }, { Name = "wave06i", Where = "spawnbot", WaitForAllSpawned = "wave06h", WaitBeforeStarting = 5, WaitBetweenSpawns = 10, TotalCount = 10, SpawnCount = 2, MaxActive = 10, TotalCurrency = 50, RandomChoice = { Extend(ROBOT_GIANT.Giant_Soldier_Spammer, { Tags = { "special_main_right" }, }), Extend(ROBOT_GIANT.Giant_Soldier_Spammer, { Tags = { "special_main_left" }, }), }, }, { Name = "wave06j", Where = "", WaitForAllSpawned = "wave06h", WaitBeforeStarting = 25, WaitBetweenSpawns = 0, TotalCount = 1, SpawnCount = 1, MaxActive = 1, TotalCurrency = 200, Templates = { { IsTank = true, Name = "tankboss", Health = 60000, Speed = 75, Skin = 1, StartingPathTrackNode = "boss_path_1", }, }, }, } --======================================================== -- WAVE 7 --======================================================== local wave7 = { mission_spy_w7, mission_sniper_w7, { Name = "wave07a", Where = "spawnbot", WaitBeforeStarting = 0, WaitBetweenSpawns = 0, TotalCount = 1, SpawnCount = 1, MaxActive = 1, TotalCurrency = 0, Templates = { ROBOT_GIANT.Giant_Chief_Soldier, }, }, } --======================================================== -- ALL WAVES --======================================================== local allWaves = { [1] = wave1, [2] = wave2, [3] = wave3, [4] = wave4, [5] = wave5, [6] = wave6, [7] = wave7, } local function waveStart(wave) util.PrintToChatAll("[TEST-WAVE]: " .. "STARTING TEST WAVE") if allWaves[wave] then RunWave(allWaves[wave]) end end local function waveInit(wave) InitMission(missionInfo) local waveData = allWaves[wave] if waveData then ParseWave(waveData, false) WaveBarGen(waveData) end end if OnWaveStartFuncs then table.insert(OnWaveStartFuncs, waveStart) else function OnWaveStart(wave) waveStart(wave) end end if OnWaveInitFuncs then table.insert(OnWaveInitFuncs, waveInit) else function OnWaveInit(wave) waveInit(wave) end end