mirror of
https://gitlab.com/the-no-frauds-club/cosmonarchy-bw-prerelease.git
synced 2026-09-17 01:01:12 +00:00
Add support for lua-based aiscripts
This commit is contained in:
parent
eb4319fe4f
commit
5d34cfd887
1
mpq/lua/.gitignore
vendored
Normal file
1
mpq/lua/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.luarc.json
|
||||
151
mpq/lua/examples/basic_ai.lua
Normal file
151
mpq/lua/examples/basic_ai.lua
Normal file
@ -0,0 +1,151 @@
|
||||
-- Setup main variables
|
||||
local player = Player()
|
||||
if player.type ~= PlayerType.Computer then
|
||||
return
|
||||
end
|
||||
local ai = AI()
|
||||
local config = PlayerVars().ai_config or {}
|
||||
|
||||
local main_town = ai:start_town()
|
||||
|
||||
-- Neat way to organize stuff is to use a table
|
||||
local brain = {
|
||||
saw_air_units = false,
|
||||
}
|
||||
|
||||
---@param town Town
|
||||
local function flyer_watch(town)
|
||||
wait_until(function() return brain.saw_air_units end)
|
||||
for i = 1, 5 do
|
||||
town:build(i, UnitId.TerranWatchdog, 70-i)
|
||||
wait(secs(30 + 5 * i))
|
||||
end
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
local function build_main_town(town)
|
||||
town:build(20, UnitId.TerranMason, 90)
|
||||
wait(secs(30))
|
||||
town:build(1, UnitId.TerranStockade, 100)
|
||||
wait(secs(90))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
wait(secs(5))
|
||||
town:build(3, UnitId.TerranStockade, 70)
|
||||
wait(mins(1))
|
||||
town:multirun(flyer_watch)
|
||||
town:build(4, UnitId.TerranStockade, 70)
|
||||
end
|
||||
|
||||
---@param town Town
|
||||
local function build_expo(town)
|
||||
cprint(TextColor.Orange, "Expanding:")
|
||||
print(town)
|
||||
town:build(1, UnitId.TerranMinistry, 90)
|
||||
town:wait_build(1, UnitId.TerranMinistry)
|
||||
town:transfer_workers(4)
|
||||
town:build(20, UnitId.TerranMason, 85)
|
||||
town:wait_build(10, UnitId.TerranMason)
|
||||
town:multirun(flyer_watch)
|
||||
town:build(1, UnitId.TerranStockade, 80)
|
||||
wait(secs(30))
|
||||
town:build(2, UnitId.TerranStockade, 70)
|
||||
-- TODO: town:build_at(UnitId.TerranStockage, Point(69, 69), 90)
|
||||
-- TODO: town:new_guard(...)
|
||||
end
|
||||
|
||||
local function expand_loop()
|
||||
wait(secs(90))
|
||||
while true do
|
||||
local town = ai:expand()
|
||||
town:multirun(build_expo) -- town:multirun manages script lifetime based on town alive state
|
||||
if town.is_alive then
|
||||
wait(math.random(mins(3), mins(4)))
|
||||
else
|
||||
wait(math.random(secs(30), mins(1))) -- if town didn't create we wait for shorter
|
||||
end
|
||||
|
||||
-- NOTE: if we didn't need the town.is_alive check we can use nice shorthand:
|
||||
-- ai:expand:multirun(build_expo)
|
||||
end
|
||||
end
|
||||
|
||||
local function attack_waves()
|
||||
main_town:wait_build(1, UnitId.TerranStockade)
|
||||
while true do
|
||||
-- Classic attack wave with counts
|
||||
--[[
|
||||
local attack = ai:new_attack()
|
||||
attack.from = Point(3800, 500)
|
||||
if Time.elapsed <= mins(5) then
|
||||
attack:add(5 + (Time.elapsed // mins(2)), UnitId.TerranMaverick)
|
||||
else
|
||||
attack:add(4 + (Time.elapsed // mins(4)), UnitId.TerranMaverick)
|
||||
attack:add(2 + (Time.elapsed // mins(4)), UnitId.TerranHarakan)
|
||||
end
|
||||
]]
|
||||
|
||||
-- Composing attack wave from power value
|
||||
local attack_budget = player:unit_count(UnitId.TerranMason) * 50
|
||||
+ (player.minerals + player.gas) // 2
|
||||
local attack = ai:new_attack(attack_budget)
|
||||
attack.budget = attack_budget
|
||||
attack.timeout = 120
|
||||
-- attack.from = Point(3800, 500)
|
||||
if player:unit_count(UnitId.TerranStockade) > 0 then
|
||||
attack:compose(config.pref_maverick or 1, UnitId.TerranMaverick)
|
||||
attack:compose(config.pref_harakan or 1, UnitId.TerranHarakan)
|
||||
attack:compose(config.pref_cyprian or 1, UnitId.TerranCyprian)
|
||||
end
|
||||
|
||||
cprint(TextColor.Red, "Sending attack:")
|
||||
print(attack)
|
||||
attack:send()
|
||||
wait(math.random(secs(5), secs(15)))
|
||||
end
|
||||
end
|
||||
|
||||
local function dump_defenses()
|
||||
cprint(TextColor.Yellow3, "Defenses:")
|
||||
print("build.gg:", ai.defense.build.gg)
|
||||
print("use.gg:", ai.defense.use.gg)
|
||||
print("build.ag:", ai.defense.build.ag)
|
||||
print("use.ag:", ai.defense.use.ag)
|
||||
print("build.ga:", ai.defense.build.ga)
|
||||
print("use.ga:", ai.defense.use.ga)
|
||||
print("build.aa:", ai.defense.build.aa)
|
||||
print("use.aa:", ai.defense.use.aa)
|
||||
end
|
||||
|
||||
---@param unit_id UnitId
|
||||
---@param cond fun(): boolean
|
||||
local function defense_watch_impl(unit_id, cond)
|
||||
while true do
|
||||
wait_until(cond, secs(1))
|
||||
ai.defense:auto_set(unit_id)
|
||||
-- dump_defenses()
|
||||
wait_while(cond, secs(1))
|
||||
ai.defense:auto_remove(unit_id)
|
||||
-- dump_defenses()
|
||||
end
|
||||
end
|
||||
|
||||
---@param factory_id UnitId
|
||||
---@param unit_id UnitId
|
||||
local function defense_watch(factory_id, unit_id)
|
||||
defense_watch_impl(unit_id, function()
|
||||
return player:unit_count(factory_id) > 0
|
||||
end)
|
||||
end
|
||||
|
||||
-- Run all the functions
|
||||
|
||||
-- Special kind of multirun, this script will die when town dies
|
||||
-- Equivalent to `multirun(function(town) town:auto_kill() ... end, town)`
|
||||
main_town:multirun(build_main_town)
|
||||
multirun(expand_loop)
|
||||
multirun(attack_waves)
|
||||
multirun(defense_watch, UnitId.TerranStockade, UnitId.TerranMaverick)
|
||||
multirun(defense_watch, UnitId.TerranStockade, UnitId.TerranHarakan)
|
||||
|
||||
wait(mins(8))
|
||||
brain.saw_air_units = true -- let's pretend, since we don't have api for detecting units yet
|
||||
235
mpq/lua/melee/melee_ai.lua
Normal file
235
mpq/lua/melee/melee_ai.lua
Normal file
@ -0,0 +1,235 @@
|
||||
require("melee.melee_common")
|
||||
require("melee.personalities")
|
||||
|
||||
---@class AIPersonality
|
||||
---@field name string
|
||||
---@field unit_composition table<UnitId, number>
|
||||
---@field main_build_order fun(melee_ai: MeleeAI, town: Town)[]
|
||||
---@field expansion_build_order fun(melee_ai: MeleeAI, town: Town)[]
|
||||
---@field build_anti_ground_defenses fun(melee_ai: MeleeAI, town: Town)
|
||||
---@field build_anti_air_defenses fun(melee_ai: MeleeAI, town: Town)
|
||||
---@field expand_rate? number Default is 3 minutes 30 seconds
|
||||
---@field expand_wait_after_fail? number Default is 30 seconds
|
||||
---@field attack_wave_budget_scaling? number Default is 1.0
|
||||
---@field attack_wave_cost_bias? number Default derived from AI:new_attack()
|
||||
|
||||
---@class TownState
|
||||
---@field started_anti_ground_defenses boolean
|
||||
---@field started_anti_air_defenses boolean
|
||||
|
||||
---@class MeleeAI
|
||||
---@field debugging {enabled: boolean, last_tick: number, last_script_id: number}
|
||||
---@field player Player
|
||||
---@field personality AIPersonality
|
||||
---@field ai AI
|
||||
---@field main_town Town
|
||||
---@field towns table<Town, TownState>
|
||||
---@field started_expanding boolean
|
||||
---@field started_attacking boolean
|
||||
---@field seen_air_threats boolean
|
||||
MeleeAI = {}
|
||||
MeleeAI.__index = MeleeAI
|
||||
|
||||
setmetatable(MeleeAI, {
|
||||
__call = function(cls, ...)
|
||||
return cls.new(...)
|
||||
end,
|
||||
})
|
||||
|
||||
---@param config? table
|
||||
---@param player? Player
|
||||
function MeleeAI.new(config, player)
|
||||
local self = setmetatable({}, MeleeAI)
|
||||
self.debugging = {
|
||||
enabled = PlayerVars(player).ai_debug or false,
|
||||
last_tick = -1,
|
||||
last_script_id = -1,
|
||||
}
|
||||
self.player = player or Player()
|
||||
self.personality = config or Personalities.pick_random(player)
|
||||
self.ai = AI(self.player.id)
|
||||
self.main_town = self.ai:start_town()
|
||||
self.towns = {
|
||||
[self.main_town] = {
|
||||
started_anti_ground_defenses = false,
|
||||
started_anti_air_defenses = false,
|
||||
},
|
||||
}
|
||||
self.started_expanding = false
|
||||
self.started_attacking = false
|
||||
self.seen_air_threats = true -- TODO: detect dynamically or after timeout
|
||||
-- TODO: maybe have a dynamic unit loss threshold check that triggers a stronger defense response
|
||||
|
||||
self:cdebug(TextColor.Yellow3, "Starting AI with personality: " .. self.personality.name)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function MeleeAI:debug_header()
|
||||
if self.debugging.last_tick ~= Time.elapsed or self.debugging.last_script_id ~= Script.id then
|
||||
self.debugging.last_tick = Time.elapsed
|
||||
self.debugging.last_script_id = Script.id
|
||||
print()
|
||||
cprint(TextColor.Yellow3, "-- " .. tostring(self.player.name) .. " (P" .. tostring(self.player.id) .. "):\n")
|
||||
end
|
||||
end
|
||||
|
||||
function MeleeAI:debug(...)
|
||||
if self.debugging.enabled then
|
||||
self:debug_header()
|
||||
print(...)
|
||||
end
|
||||
end
|
||||
|
||||
function MeleeAI:cdebug(color, ...)
|
||||
if self.debugging.enabled then
|
||||
self:debug_header()
|
||||
cprint(color, ...)
|
||||
end
|
||||
end
|
||||
|
||||
-- How often the banked-resource snapshot is refreshed while a dynamic_wait is
|
||||
-- in progress, so a long wait reacts to resources changing mid-wait instead
|
||||
-- of freezing the scale from a single sample taken at the start.
|
||||
local DYNAMIC_WAIT_RESAMPLE_INTERVAL = secs(2)
|
||||
|
||||
---@param duration integer
|
||||
function MeleeAI:dynamic_wait(duration)
|
||||
local elapsed = 0
|
||||
while elapsed < duration do
|
||||
local chunk = math.min(DYNAMIC_WAIT_RESAMPLE_INTERVAL, duration - elapsed)
|
||||
local resources = self.player.minerals + self.player.gas
|
||||
local resource_scale = math.max(0, math.min(1, (1100 - resources) / 600))
|
||||
local scaled_chunk = math.floor(chunk * resource_scale)
|
||||
if scaled_chunk > 0 then
|
||||
wait(scaled_chunk)
|
||||
end
|
||||
elapsed = elapsed + chunk
|
||||
end
|
||||
end
|
||||
|
||||
---@protected
|
||||
---@return table<UnitId, number>
|
||||
function MeleeAI:get_final_unit_composition()
|
||||
local unit_composition = {}
|
||||
for unit_id, preference in pairs(self.personality.unit_composition) do
|
||||
unit_composition[unit_id] = preference
|
||||
end
|
||||
return unit_composition
|
||||
end
|
||||
|
||||
function MeleeAI:run()
|
||||
for unit_id, preference in pairs(self:get_final_unit_composition()) do
|
||||
if preference > 0 then
|
||||
multirun(function()
|
||||
wait_until(function() return self.player:can_make(unit_id) end, secs(1))
|
||||
self:cdebug(TextColor.Teal, "Added " .. UnitId.name(unit_id) .. " to defense")
|
||||
self.ai.defense:auto_set(unit_id)
|
||||
wait_while(function() return self.player:can_make(unit_id) end, secs(1))
|
||||
self:cdebug(TextColor.Teal, "Added " .. UnitId.name(unit_id) .. " to defense")
|
||||
self.ai.defense:auto_remove(unit_id)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
multirun(function()
|
||||
self.main_town:auto_kill_script()
|
||||
self.main_town:build(1, MeleeCommon.default_town_building(self.player.race), 120)
|
||||
self.main_town:build(self.main_town.max_workers, MeleeCommon.default_worker(self.player.race), 100)
|
||||
for i, build_order_step in ipairs(self.personality.main_build_order) do
|
||||
build_order_step(self, self.main_town)
|
||||
if i == 1 then
|
||||
-- If opener didn't enable this, we now should
|
||||
self:start_attacking()
|
||||
self:start_expanding()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function MeleeAI:start_expanding()
|
||||
if self.started_expanding then
|
||||
return
|
||||
end
|
||||
self.started_expanding = true
|
||||
multirun(function()
|
||||
while true do
|
||||
local town = self.ai:expand()
|
||||
self:cdebug(TextColor.Green, "Expanding:")
|
||||
self:debug(town)
|
||||
if town.is_alive then
|
||||
self.towns[town] = {
|
||||
started_anti_ground_defenses = false,
|
||||
started_anti_air_defenses = false,
|
||||
}
|
||||
town:multirun(function()
|
||||
for i, build_order_step in ipairs(self.personality.expansion_build_order) do
|
||||
build_order_step(self, town)
|
||||
if i == 1 then
|
||||
self:start_anti_ground_defenses(town)
|
||||
self:start_anti_air_defenses(town)
|
||||
end
|
||||
end
|
||||
end)
|
||||
wait(self.personality.expand_rate or (mins(3) + secs(30)))
|
||||
else
|
||||
wait(self.personality.expand_wait_after_fail or secs(30))
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function MeleeAI:start_attacking()
|
||||
if self.started_attacking then
|
||||
return
|
||||
end
|
||||
self.started_attacking = true
|
||||
multirun(function()
|
||||
while true do
|
||||
local budget = self.player:unit_count(MeleeCommon.default_worker(self.player.race)) * 50
|
||||
+ (self.player.minerals + self.player.gas) / 2
|
||||
budget = budget * (self.personality.attack_wave_budget_scaling or 1.0)
|
||||
|
||||
local attack = self.ai:new_attack(budget, self.personality.attack_wave_cost_bias or nil)
|
||||
for unit_id, preference in pairs(self:get_final_unit_composition()) do
|
||||
if preference > 0 and self.player:can_make(unit_id) then
|
||||
attack:compose(preference, unit_id)
|
||||
end
|
||||
end
|
||||
|
||||
self:cdebug(TextColor.Orange, "Sending attack:")
|
||||
self:debug(attack)
|
||||
attack:send()
|
||||
wait(secs(5))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function MeleeAI:start_anti_ground_defenses(town)
|
||||
if self.personality.build_anti_ground_defenses == nil then
|
||||
return
|
||||
end
|
||||
if self.towns[town].started_anti_ground_defenses then
|
||||
return
|
||||
end
|
||||
self.towns[town].started_anti_ground_defenses = true
|
||||
|
||||
multirun(function()
|
||||
self.personality.build_anti_ground_defenses(self, town)
|
||||
end)
|
||||
end
|
||||
|
||||
function MeleeAI:start_anti_air_defenses(town)
|
||||
if self.personality.build_anti_air_defenses == nil then
|
||||
return
|
||||
end
|
||||
if self.towns[town].started_anti_air_defenses then
|
||||
return
|
||||
end
|
||||
self.towns[town].started_anti_air_defenses = true
|
||||
|
||||
multirun(function()
|
||||
wait_until(function() return self.seen_air_threats end, secs(1))
|
||||
self.personality.build_anti_air_defenses(self, town)
|
||||
end)
|
||||
end
|
||||
33
mpq/lua/melee/melee_common.lua
Normal file
33
mpq/lua/melee/melee_common.lua
Normal file
@ -0,0 +1,33 @@
|
||||
MeleeCommon = {}
|
||||
|
||||
---@param race RaceId
|
||||
---@return UnitId worker_unit_id
|
||||
function MeleeCommon.default_worker(race)
|
||||
if race == RaceId.Terran then
|
||||
return UnitId.TerranMason
|
||||
elseif race == RaceId.Zerg then
|
||||
return UnitId.ZergDroleth
|
||||
elseif race == RaceId.Protoss then
|
||||
return UnitId.ProtossScribe
|
||||
elseif race == RaceId.Askosi then
|
||||
return UnitId.AskosiPilgrim
|
||||
end
|
||||
error("Race " .. tostring(race) .. " has no default worker set")
|
||||
end
|
||||
|
||||
---@param race RaceId
|
||||
---@return UnitId town_building_unit_id
|
||||
function MeleeCommon.default_town_building(race)
|
||||
if race == RaceId.Terran then
|
||||
return UnitId.TerranMinistry
|
||||
elseif race == RaceId.Zerg then
|
||||
return UnitId.ZergHachirosk
|
||||
elseif race == RaceId.Protoss then
|
||||
return UnitId.ProtossNexus
|
||||
elseif race == RaceId.Askosi then
|
||||
return UnitId.AskosiLandlock
|
||||
end
|
||||
error("Race " .. tostring(race) .. " has no default town set")
|
||||
end
|
||||
|
||||
return MeleeCommon
|
||||
141
mpq/lua/melee/personalities.lua
Normal file
141
mpq/lua/melee/personalities.lua
Normal file
@ -0,0 +1,141 @@
|
||||
local TerranArmor = require("melee.terran.armor")
|
||||
local TerranRaider = require("melee.terran.raider")
|
||||
local TerranOrbital = require("melee.terran.orbital")
|
||||
local TerranGeneral = require("melee.terran.general")
|
||||
|
||||
local ZergAssault = require("melee.zerg.assault")
|
||||
local ZergSwarm = require("melee.zerg.swarm")
|
||||
local ZergSunblot = require("melee.zerg.sunblot")
|
||||
local ZergGeneral = require("melee.zerg.general")
|
||||
|
||||
local ProtossRanger = require("melee.protoss.ranger")
|
||||
local ProtossTemplar = require("melee.protoss.templar")
|
||||
local ProtossSkylord = require("melee.protoss.skylord")
|
||||
local ProtossGeneral = require("melee.protoss.general")
|
||||
|
||||
---@class Personalities
|
||||
Personalities = {
|
||||
Terran = {
|
||||
ArmorTankPush = TerranArmor.tank_push,
|
||||
ArmorFeFiveFulc = TerranArmor.fe_five_fulc,
|
||||
ArmorTwoFulcVulture = TerranArmor.two_fulc_vulture,
|
||||
ArmorWalkerPower = TerranArmor.walker_power,
|
||||
ArmorIronCrusade = TerranArmor.iron_crusade,
|
||||
ArmorDavidAndGoliath = TerranArmor.david_and_goliath,
|
||||
RaiderEightRax = TerranRaider.eight_rax,
|
||||
RaiderThreeRaxBio = TerranRaider.three_rax_bio,
|
||||
RaiderFastAnvil = TerranRaider.fast_anvil,
|
||||
RaiderFourRaxPressure = TerranRaider.four_rax_pressure,
|
||||
RaiderUprising = TerranRaider.uprising,
|
||||
RaiderHolyAckmeds = TerranRaider.holy_ackmeds,
|
||||
OrbitalRapidStarpads = TerranOrbital.rapid_starpads,
|
||||
OrbitalTheDon = TerranOrbital.the_don,
|
||||
OrbitalWraithBio = TerranOrbital.wraith_bio,
|
||||
OrbitalHotdrop = TerranOrbital.hotdrop,
|
||||
OrbitalSuddenStarport = TerranOrbital.sudden_starport,
|
||||
OrbitalAcesHigh = TerranOrbital.aces_high,
|
||||
GeneralTwoFulcrumMech = TerranGeneral.two_fulcrum_mech,
|
||||
GeneralEarlyRiser = TerranGeneral.early_riser,
|
||||
GeneralTheCube = TerranGeneral.the_cube,
|
||||
GeneralDoublingUp = TerranGeneral.doubling_up,
|
||||
GeneralMechIntoAir = TerranGeneral.mech_into_air,
|
||||
GeneralObservant = TerranGeneral.observant,
|
||||
},
|
||||
Zerg = {
|
||||
AssaultThreeBaseHydrith = ZergAssault.three_base_hydrith,
|
||||
AssaultTwoBaseZorkiz = ZergAssault.two_base_zorkiz,
|
||||
AssaultTwoBaseHydrithQuazeth = ZergAssault.two_base_hydrith_quazeth,
|
||||
AssaultTwoBaseAlkag = ZergAssault.two_base_alkag,
|
||||
AssaultPotency = ZergAssault.potency,
|
||||
AssaultEarthenTides = ZergAssault.earthen_tides,
|
||||
SwarmThreeBaseFlood = ZergSwarm.three_base_flood,
|
||||
SwarmThreeBaseUltrav = ZergSwarm.three_base_ultrav,
|
||||
SwarmInstantQuazeth = ZergSwarm.instant_quazeth,
|
||||
SwarmThreeBaseOthstol = ZergSwarm.three_base_othstol,
|
||||
SwarmGatesOfHell = ZergSwarm.gates_of_hell,
|
||||
SwarmPrimitivePressure = ZergSwarm.primitive_pressure,
|
||||
SunblotBigAndLittle = ZergSunblot.big_and_little,
|
||||
SunblotTheTriad = ZergSunblot.the_triad,
|
||||
SunblotSkitteringDuo = ZergSunblot.skittering_duo,
|
||||
SunblotEarlyBirds = ZergSunblot.early_birds,
|
||||
SunblotFlyingFeint = ZergSunblot.flying_feint,
|
||||
SunblotDescendingHorizon = ZergSunblot.descending_horizon,
|
||||
GeneralSleepingGiant = ZergGeneral.sleeping_giant,
|
||||
GeneralShriekingSwarm = ZergGeneral.shrieking_swarm,
|
||||
GeneralSubjugation = ZergGeneral.subjugation,
|
||||
GeneralBeforeTheStorm = ZergGeneral.before_the_storm,
|
||||
GeneralTimeAfterTime = ZergGeneral.time_after_time,
|
||||
GeneralConstrainedCoil = ZergGeneral.constrained_coil,
|
||||
},
|
||||
Protoss = {
|
||||
RangerTwoGateStrider = ProtossRanger.two_gate_strider,
|
||||
RangerEmissarySquared = ProtossRanger.emissary_squared,
|
||||
RangerOneGateAuthority = ProtossRanger.one_gate_authority,
|
||||
RangerLatticeExpo = ProtossRanger.lattice_expo,
|
||||
RangerSimulantSwarm = ProtossRanger.simulant_swarm,
|
||||
RangerTheRegistry = ProtossRanger.the_registry,
|
||||
TemplarThreeGateStrider = ProtossTemplar.three_gate_strider,
|
||||
TemplarSuffocatingShadow = ProtossTemplar.suffocating_shadow,
|
||||
TemplarLegion = ProtossTemplar.legion,
|
||||
TemplarInitiates = ProtossTemplar.initiates,
|
||||
TemplarMartyrdom = ProtossTemplar.martyrdom,
|
||||
TemplarLegionsHeralds = ProtossTemplar.legions_heralds,
|
||||
SkylordSolarEscort = ProtossSkylord.solar_escort,
|
||||
SkylordDeadlyOmen = ProtossSkylord.deadly_omen,
|
||||
SkylordTwoGatePanoptus = ProtossSkylord.two_gate_panoptus,
|
||||
SkylordExalted = ProtossSkylord.exalted,
|
||||
SkylordSorrowFleet = ProtossSkylord.sorrow_fleet,
|
||||
SkylordShipsAndSwords = ProtossSkylord.ships_and_swords,
|
||||
GeneralLunaticLegion = ProtossGeneral.lunatic_legion,
|
||||
GeneralStridentStriders = ProtossGeneral.strident_striders,
|
||||
GeneralWorship = ProtossGeneral.worship,
|
||||
GeneralRoboticsFe = ProtossGeneral.robotics_fe,
|
||||
GeneralTheSwordsmiths = ProtossGeneral.the_swordsmiths,
|
||||
GeneralMatriarchy = ProtossGeneral.matriarchy,
|
||||
},
|
||||
Askosi = {},
|
||||
}
|
||||
|
||||
---@class RacePersonalities
|
||||
|
||||
---@param race RaceId
|
||||
---@return RacePersonalities
|
||||
local function by_race(race)
|
||||
if race == RaceId.Terran then
|
||||
return Personalities.Terran
|
||||
elseif race == RaceId.Zerg then
|
||||
return Personalities.Zerg
|
||||
elseif race == RaceId.Protoss then
|
||||
return Personalities.Protoss
|
||||
elseif race == RaceId.Askosi then
|
||||
return Personalities.Askosi
|
||||
end
|
||||
error("Race " .. tostring(race) .. " is not a valid AI race")
|
||||
end
|
||||
|
||||
---@param dict table
|
||||
---@return AIPersonality
|
||||
local function pick_random(dict)
|
||||
local keys = {}
|
||||
for key, _ in pairs(dict) do
|
||||
table.insert(keys, key)
|
||||
end
|
||||
local random_key = keys[math.random(#keys)]
|
||||
return dict[random_key]
|
||||
end
|
||||
|
||||
---@param player? Player
|
||||
---@return AIPersonality
|
||||
function Personalities.pick_random(player)
|
||||
player = player or Player()
|
||||
local race_personalities = by_race(player.race)
|
||||
return pick_random(race_personalities)
|
||||
end
|
||||
|
||||
---@param personality AIPersonality
|
||||
---@return AIPersonality
|
||||
function Personalities.copy(personality)
|
||||
error("not implemented yet")
|
||||
end
|
||||
|
||||
return Personalities
|
||||
31
mpq/lua/melee/protoss/build/basic.lua
Normal file
31
mpq/lua/melee/protoss/build/basic.lua
Normal file
@ -0,0 +1,31 @@
|
||||
local Basic = {}
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossNexus, 120)
|
||||
town:wait_build(1, UnitId.ProtossNexus)
|
||||
town:build(town.max_workers, UnitId.ProtossScribe, 100)
|
||||
town:transfer_workers(8)
|
||||
town:wait_build(10, UnitId.ProtossScribe)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_anti_ground(melee_ai, town)
|
||||
for i = 1, 4 do
|
||||
town:build(i, UnitId.ProtossWarden, 70 - i * 5)
|
||||
wait(secs(25 + i * 5))
|
||||
end
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_anti_air(melee_ai, town)
|
||||
for i = 1, 3 do
|
||||
town:build(i, UnitId.ProtossMatrix, 80 - i * 5)
|
||||
wait(secs(25 + i * 5))
|
||||
end
|
||||
end
|
||||
|
||||
return Basic
|
||||
424
mpq/lua/melee/protoss/build/openers.lua
Normal file
424
mpq/lua/melee/protoss/build/openers.lua
Normal file
@ -0,0 +1,424 @@
|
||||
---@class ProtossOpeners
|
||||
local Openers = {}
|
||||
|
||||
-- Ranger
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.two_gate_strider(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.emissary_squared(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossPylon, 90)
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.one_gate_authority(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.lattice_expo(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(3, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.simulant_swarm(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.the_registry(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
-- Templar
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.three_gate_strider(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.suffocating_shadow(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.legion(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
wait(secs(1))
|
||||
town:build(3, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(5, UnitId.ProtossGateway, 90)
|
||||
wait(secs(1))
|
||||
town:build(4, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(6, UnitId.ProtossGateway, 90)
|
||||
wait(secs(1))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.initiates(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
town:wait_build(2, UnitId.ProtossGateway)
|
||||
melee_ai:dynamic_wait(secs(10))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.martyrdom(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(2) + secs(30))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.legions_heralds(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
-- Skylord
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.solar_escort(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.deadly_omen(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossStargate, 90)
|
||||
town:wait_build(1, UnitId.ProtossStargate)
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
town:wait_build(2, UnitId.ProtossPylon)
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.two_gate_panoptus(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.exalted(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
|
||||
town:build(1, UnitId.ProtossWarden, 79)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossWarden, 79)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.sorrow_fleet(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.ships_and_swords(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(2, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
-- General
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.lunatic_legion(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
wait(secs(3))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.matriarchy(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.robotics_fe(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossPylon, 90)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.strident_striders(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.the_swordsmiths(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
town:wait_build(1, UnitId.ProtossGateway)
|
||||
town:wait_build(1, UnitId.ProtossLattice)
|
||||
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.worship(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossPylon, 110)
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
return Openers
|
||||
199
mpq/lua/melee/protoss/build/tier1.lua
Normal file
199
mpq/lua/melee/protoss/build/tier1.lua
Normal file
@ -0,0 +1,199 @@
|
||||
---@class ProtossTier1
|
||||
local Tier1 = {}
|
||||
|
||||
-- Ranger
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.two_gate_strider(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.one_gate_authority(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.simulant_swarm(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(5, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.the_registry(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(2, UnitId.ProtossPylon)
|
||||
town:build(4, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
end
|
||||
|
||||
-- Templar
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.three_gate_strider(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(5, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.suffocating_shadow(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.legion(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(9, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.initiates(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.legions_heralds(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
end
|
||||
|
||||
-- Skylord
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.solar_escort(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.deadly_omen(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(4, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(5, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.two_gate_panoptus(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(35))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.exalted(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.ships_and_swords(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(3, UnitId.ProtossStargate, 90)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
-- General
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.matriarchy(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.robotics_fe(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(1, UnitId.ProtossPylon)
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.strident_striders(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(45))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.the_swordsmiths(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossPylon, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.worship(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.ProtossGateway, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
return Tier1
|
||||
179
mpq/lua/melee/protoss/build/tier2.lua
Normal file
179
mpq/lua/melee/protoss/build/tier2.lua
Normal file
@ -0,0 +1,179 @@
|
||||
---@class ProtossTier2
|
||||
local Tier2 = {}
|
||||
|
||||
--- Requests a Lattice and an extra Gateway. The generic tier-2 scale-up, for
|
||||
--- personalities without bespoke tier-2 content.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.acquire(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossLattice, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.strider_lattice_library_gateway(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(5, UnitId.ProtossGateway, 70)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.emissary_ardent_lattice_gateway(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossLattice, 70)
|
||||
wait(secs(3))
|
||||
town:build(2, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.authority_ardent_gateway_expand_lattice(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ProtossGateway, 70)
|
||||
wait(secs(1))
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(4, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.expo_ardent_authority(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.strider3_library_expand(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(20) + secs(40))
|
||||
town:build(2, UnitId.ProtossGrandLibrary, 70)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.shadow_roguegallery_expand_library(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossRogueGallery, 70)
|
||||
town:build(2, UnitId.ProtossRogueGallery, 70)
|
||||
melee_ai:dynamic_wait(secs(30) + secs(40))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(5))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.legion_library_x2(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGrandLibrary, 70)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.martyrdom_pylon_roguegallery(melee_ai, town)
|
||||
town:build(4, UnitId.ProtossPylon, 70)
|
||||
wait(secs(3))
|
||||
town:build(2, UnitId.ProtossRogueGallery, 70)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.heralds_library_gateway_buildup(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.ProtossPylon, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(40) + mins(1))
|
||||
town:build(5, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(9, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(55))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.escort_stargate_buildup(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(3, UnitId.ProtossStargate, 70)
|
||||
wait(secs(1))
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.legion_stargate_gateway_library(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(40) + secs(5))
|
||||
town:build(3, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(4, UnitId.ProtossGateway, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.matriarchy_library_lattice(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ProtossLattice, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.robotics_ardent_x2(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.swordsmiths_ardent_stargate(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossStargate, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossArdentAuthority, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
return Tier2
|
||||
86
mpq/lua/melee/protoss/build/tier3.lua
Normal file
86
mpq/lua/melee/protoss/build/tier3.lua
Normal file
@ -0,0 +1,86 @@
|
||||
---@class ProtossTier3
|
||||
local Tier3 = {}
|
||||
|
||||
--- Requests a Prostration Stage and waits for it. The generic tier-3 tech
|
||||
--- transition, for personalities without bespoke tier-3 content.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.acquire(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.authority_prostration_ardent2(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.ProtossArdentAuthority, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.martyrdom_prostration_crucible(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossCrucible, 50)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.escort_argosy_buildup(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ProtossArgosy, 50)
|
||||
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.exalted_argosy_crucible(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
town:wait_build(1, UnitId.ProtossArgosy, false)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossCrucible, 50)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.fleet_argosy_buildup(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(2, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ProtossArgosy, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.legion_argosy_only(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossArgosy, 50)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.matriarchy_prostration(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.robotics_prostration(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(20))
|
||||
end
|
||||
|
||||
return Tier3
|
||||
174
mpq/lua/melee/protoss/build/tier4.lua
Normal file
174
mpq/lua/melee/protoss/build/tier4.lua
Normal file
@ -0,0 +1,174 @@
|
||||
---@class ProtossTier4
|
||||
local Tier4 = {}
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.emissary_synthetic_synod(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
end
|
||||
|
||||
--- Generic tier-4 capstone for the Templar category, for personalities
|
||||
--- without bespoke tier-4 content.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.templar_archives_acquire(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
--- Generic tier-4 capstone for the Skylord category, for personalities
|
||||
--- without bespoke tier-4 content.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.skylord_monument_acquire(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.authority_synthetic_synod(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
wait(secs(1))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.ranger_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossLattice, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.ProtossGateway, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossEmbassy, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossArgosy, 50, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.martyrdom_ancestral_archives_scaling(melee_ai, town)
|
||||
town:build(2, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:wait_build(2, UnitId.ProtossAncestralArchives, false)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ProtossAncestralArchives, 45)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.templar_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossGateway, 90, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossLattice, 90, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossEmbassy, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70, true)
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossArgosy, 50, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.exalted_monument_of_sin(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.fleet_monument_of_sin(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(45))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.skylord_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossGateway, 90, true)
|
||||
town:wait_build(1, UnitId.ProtossGateway)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossEmbassy, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossArgosy, 50, true)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(1, UnitId.ProtossStargate)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:wait_build(1, UnitId.ProtossArgosy)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ProtossLattice, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(1, UnitId.ProtossArgosy)
|
||||
town:build(1, UnitId.ProtossMonumentOfSin, 45, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70)
|
||||
town:wait_build(1, UnitId.ProtossGrandLibrary)
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(1, UnitId.ProtossLattice)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossArdentAuthority, 70)
|
||||
town:wait_build(1, UnitId.ProtossArdentAuthority)
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossUnitaryUnion, 50, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossProstrationStage, 65, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.matriarchy_synthetic_synod_x2(melee_ai, town)
|
||||
town:build(2, UnitId.ProtossSyntheticSynod, 45)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.robotics_synthetic_synod(melee_ai, town)
|
||||
town:build(1, UnitId.ProtossSyntheticSynod, 45)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier4.general_expansion(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossGateway, 90, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossEmbassy, 70, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ProtossLattice, 90, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ProtossStargate, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ProtossGrandLibrary, 70, true)
|
||||
town:build(1, UnitId.ProtossAncestralArchives, 45, true)
|
||||
end
|
||||
|
||||
return Tier4
|
||||
164
mpq/lua/melee/protoss/general.lua
Normal file
164
mpq/lua/melee/protoss/general.lua
Normal file
@ -0,0 +1,164 @@
|
||||
local Basic = require("melee.protoss.build.basic")
|
||||
local Openers = require("melee.protoss.build.openers")
|
||||
local Tier1 = require("melee.protoss.build.tier1")
|
||||
local Tier2 = require("melee.protoss.build.tier2")
|
||||
local Tier3 = require("melee.protoss.build.tier3")
|
||||
local Tier4 = require("melee.protoss.build.tier4")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier4.general_expansion,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.5
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
lunatic_legion = {
|
||||
name = "General: Lunatic Legion",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
[UnitId.ProtossSimulacrum] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossAurora] = 1,
|
||||
[UnitId.ProtossMagister] = 1,
|
||||
[UnitId.ProtossDidact] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.lunatic_legion,
|
||||
Tier2.legion_stargate_gateway_library,
|
||||
Tier3.legion_argosy_only,
|
||||
Tier4.robotics_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
matriarchy = {
|
||||
name = "General: Matriarchy",
|
||||
unit_composition = {
|
||||
-- signature units (Prostration Stage / Synthetic Synod)
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
[UnitId.ProtossAmaranth] = 2,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEmpress] = 1,
|
||||
[UnitId.ProtossAnalogue] = 1,
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossMindTyrant] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.matriarchy,
|
||||
Tier1.matriarchy,
|
||||
Tier2.matriarchy_library_lattice,
|
||||
Tier3.matriarchy_prostration,
|
||||
Tier4.matriarchy_synthetic_synod_x2,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
robotics_fe = {
|
||||
name = "General: Robotics FE",
|
||||
unit_composition = {
|
||||
-- signature units (Ardent Authority x2)
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossServitor] = 1,
|
||||
[UnitId.ProtossPositron] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossClarion] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.robotics_fe,
|
||||
Tier1.robotics_fe,
|
||||
Tier2.robotics_ardent_x2,
|
||||
Tier3.robotics_prostration,
|
||||
Tier4.robotics_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
strident_striders = {
|
||||
name = "General: Strident Striders",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossDracadin] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.strident_striders,
|
||||
Tier1.strident_striders,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier4.robotics_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
the_swordsmiths = {
|
||||
name = "General: The Swordsmiths",
|
||||
unit_composition = {
|
||||
-- signature units (Ardent Authority x2)
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
[UnitId.ProtossManifold] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossServitor] = 1,
|
||||
[UnitId.ProtossPositron] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossClarion] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.the_swordsmiths,
|
||||
Tier1.the_swordsmiths,
|
||||
Tier2.swordsmiths_ardent_stargate,
|
||||
Tier3.acquire,
|
||||
Tier4.robotics_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
worship = {
|
||||
name = "General: Worship",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossAmaranth] = 2,
|
||||
[UnitId.ProtossSimulacrum] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossGolem] = 1,
|
||||
[UnitId.ProtossDracadin] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.worship,
|
||||
Tier1.worship,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier4.robotics_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
159
mpq/lua/melee/protoss/ranger.lua
Normal file
159
mpq/lua/melee/protoss/ranger.lua
Normal file
@ -0,0 +1,159 @@
|
||||
local Basic = require("melee.protoss.build.basic")
|
||||
local Openers = require("melee.protoss.build.openers")
|
||||
local Tier1 = require("melee.protoss.build.tier1")
|
||||
local Tier2 = require("melee.protoss.build.tier2")
|
||||
local Tier3 = require("melee.protoss.build.tier3")
|
||||
local Tier4 = require("melee.protoss.build.tier4")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier4.ranger_expansion,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.5
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
two_gate_strider = {
|
||||
name = "Ranger: 2 Gate Strider",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
[UnitId.ProtossDracadin] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.two_gate_strider,
|
||||
Tier1.two_gate_strider,
|
||||
Tier2.strider_lattice_library_gateway,
|
||||
Tier3.acquire,
|
||||
Tier4.emissary_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
emissary_squared = {
|
||||
name = "Ranger: Emissary Squared",
|
||||
unit_composition = {
|
||||
-- signature units (Synthetic Synod)
|
||||
[UnitId.ProtossAnalogue] = 2,
|
||||
[UnitId.ProtossDemiurge] = 2,
|
||||
[UnitId.ProtossEmpress] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossVassal] = 1,
|
||||
[UnitId.ProtossGolem] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossDracadin] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.emissary_squared,
|
||||
Tier2.emissary_ardent_lattice_gateway,
|
||||
Tier3.acquire,
|
||||
Tier4.emissary_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
one_gate_authority = {
|
||||
name = "Ranger: 1 Gate Authority",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossManifold] = 2,
|
||||
-- filler units (Prostration Stage)
|
||||
[UnitId.ProtossPariah] = 1,
|
||||
[UnitId.ProtossPotentate] = 1,
|
||||
[UnitId.ProtossSycophant] = 1,
|
||||
[UnitId.ProtossMindTyrant] = 1,
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.one_gate_authority,
|
||||
Tier1.one_gate_authority,
|
||||
Tier2.authority_ardent_gateway_expand_lattice,
|
||||
Tier3.authority_prostration_ardent2,
|
||||
Tier4.authority_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
lattice_expo = {
|
||||
name = "Ranger: Lattice Expo",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossSimulacrum] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossDracadin] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.lattice_expo,
|
||||
Tier2.expo_ardent_authority,
|
||||
Tier3.acquire,
|
||||
Tier4.emissary_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
simulant_swarm = {
|
||||
name = "Ranger: Simulant Swarm",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossSimulacrum] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.simulant_swarm,
|
||||
Tier1.simulant_swarm,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier4.emissary_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
the_registry = {
|
||||
name = "Ranger: The Registry",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossManifold] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossIdol] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.the_registry,
|
||||
Tier1.the_registry,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier4.emissary_synthetic_synod,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
164
mpq/lua/melee/protoss/skylord.lua
Normal file
164
mpq/lua/melee/protoss/skylord.lua
Normal file
@ -0,0 +1,164 @@
|
||||
local Basic = require("melee.protoss.build.basic")
|
||||
local Openers = require("melee.protoss.build.openers")
|
||||
local Tier1 = require("melee.protoss.build.tier1")
|
||||
local Tier2 = require("melee.protoss.build.tier2")
|
||||
local Tier3 = require("melee.protoss.build.tier3")
|
||||
local Tier4 = require("melee.protoss.build.tier4")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier4.skylord_expansion,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.6
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
solar_escort = {
|
||||
name = "Skylord: Solar Escort",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossSolarion] = 2,
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossPanoptus] = 1,
|
||||
[UnitId.ProtossGladius] = 1,
|
||||
[UnitId.ProtossEmpyrean] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.solar_escort,
|
||||
Tier1.solar_escort,
|
||||
Tier2.escort_stargate_buildup,
|
||||
Tier3.escort_argosy_buildup,
|
||||
Tier4.skylord_monument_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
deadly_omen = {
|
||||
name = "Skylord: Deadly Omen",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossPanoptus] = 1,
|
||||
[UnitId.ProtossExemplar] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.deadly_omen,
|
||||
Tier1.deadly_omen,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier4.skylord_monument_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
two_gate_panoptus = {
|
||||
name = "Skylord: 2 Gate Panoptus",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossPanoptus] = 3,
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossHierophant] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.two_gate_panoptus,
|
||||
Tier1.two_gate_panoptus,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier4.skylord_monument_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
exalted = {
|
||||
name = "Skylord: Exalted",
|
||||
unit_composition = {
|
||||
-- signature units (Monument of Sin)
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
[UnitId.ProtossStarSovereign] = 2,
|
||||
[UnitId.ProtossAnthelion] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossPanoptus] = 1,
|
||||
[UnitId.ProtossExemplar] = 1,
|
||||
[UnitId.ProtossDidact] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.exalted,
|
||||
Tier1.exalted,
|
||||
Tier2.acquire,
|
||||
Tier3.exalted_argosy_crucible,
|
||||
Tier4.exalted_monument_of_sin,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
sorrow_fleet = {
|
||||
name = "Skylord: Sorrow Fleet",
|
||||
unit_composition = {
|
||||
-- signature units (Monument of Sin)
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
[UnitId.ProtossStarSovereign] = 2,
|
||||
[UnitId.ProtossAnthelion] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.ProtossPanoptus] = 1,
|
||||
[UnitId.ProtossGladius] = 1,
|
||||
[UnitId.ProtossEmpyrean] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.sorrow_fleet,
|
||||
Tier2.acquire,
|
||||
Tier3.fleet_argosy_buildup,
|
||||
Tier4.fleet_monument_of_sin,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
ships_and_swords = {
|
||||
name = "Skylord: Ships and Swords",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ProtossVassal] = 2,
|
||||
[UnitId.ProtossAurora] = 1.5,
|
||||
[UnitId.ProtossMagister] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.ProtossGladius] = 1,
|
||||
[UnitId.ProtossStarSovereign] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.ships_and_swords,
|
||||
Tier1.ships_and_swords,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier4.skylord_monument_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
163
mpq/lua/melee/protoss/templar.lua
Normal file
163
mpq/lua/melee/protoss/templar.lua
Normal file
@ -0,0 +1,163 @@
|
||||
local Basic = require("melee.protoss.build.basic")
|
||||
local Openers = require("melee.protoss.build.openers")
|
||||
local Tier1 = require("melee.protoss.build.tier1")
|
||||
local Tier2 = require("melee.protoss.build.tier2")
|
||||
local Tier3 = require("melee.protoss.build.tier3")
|
||||
local Tier4 = require("melee.protoss.build.tier4")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier4.templar_expansion,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.4
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
three_gate_strider = {
|
||||
name = "Templar: 3 Gate Strider",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossDracadin] = 1,
|
||||
[UnitId.ProtossArchon] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.three_gate_strider,
|
||||
Tier1.three_gate_strider,
|
||||
Tier2.strider3_library_expand,
|
||||
Tier3.acquire,
|
||||
Tier4.templar_archives_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
suffocating_shadow = {
|
||||
name = "Templar: Suffocating Shadow",
|
||||
unit_composition = {
|
||||
-- signature units (Rogue Gallery)
|
||||
[UnitId.ProtossVagrant] = 2,
|
||||
[UnitId.ProtossCabalist] = 2,
|
||||
[UnitId.ProtossCharlatan] = 2,
|
||||
[UnitId.ProtossBarghest] = 2,
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.suffocating_shadow,
|
||||
Tier1.suffocating_shadow,
|
||||
Tier2.shadow_roguegallery_expand_library,
|
||||
Tier3.acquire,
|
||||
Tier4.templar_archives_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
legion = {
|
||||
name = "Templar: Legion",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossArchon] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.legion,
|
||||
Tier1.legion,
|
||||
Tier2.legion_library_x2,
|
||||
Tier3.acquire,
|
||||
Tier4.templar_archives_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
initiates = {
|
||||
name = "Templar: Initiates",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossZealot] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossCantavis] = 1,
|
||||
[UnitId.ProtossAccantor] = 1,
|
||||
[UnitId.ProtossArchon] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.initiates,
|
||||
Tier1.initiates,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier4.templar_archives_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
martyrdom = {
|
||||
name = "Templar: Martyrdom",
|
||||
unit_composition = {
|
||||
-- signature units (Ancestral Archives x4)
|
||||
[UnitId.ProtossArchon] = 2,
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
[UnitId.ProtossMindTyrant] = 1,
|
||||
[UnitId.ProtossOptecton] = 1,
|
||||
[UnitId.ProtossPatriarch] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.martyrdom,
|
||||
Tier2.martyrdom_pylon_roguegallery,
|
||||
Tier3.martyrdom_prostration_crucible,
|
||||
Tier4.martyrdom_ancestral_archives_scaling,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
legions_heralds = {
|
||||
name = "Templar: Legion's Heralds",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.ProtossLegionnaire] = 2,
|
||||
-- filler units
|
||||
[UnitId.ProtossEcclesiast] = 1,
|
||||
[UnitId.ProtossAtreus] = 1,
|
||||
[UnitId.ProtossHerald] = 1,
|
||||
[UnitId.ProtossPatriarch] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.legions_heralds,
|
||||
Tier1.legions_heralds,
|
||||
Tier2.heralds_library_gateway_buildup,
|
||||
Tier3.acquire,
|
||||
Tier4.templar_archives_acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
164
mpq/lua/melee/terran/armor.lua
Normal file
164
mpq/lua/melee/terran/armor.lua
Normal file
@ -0,0 +1,164 @@
|
||||
local Basic = require("melee.terran.build.basic")
|
||||
local Openers = require("melee.terran.build.openers")
|
||||
local Tier1 = require("melee.terran.build.tier1")
|
||||
local Tier2 = require("melee.terran.build.tier2")
|
||||
local Tier3 = require("melee.terran.build.tier3")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier2.acquire,
|
||||
Tier2.fulcrum_buildup,
|
||||
Tier3.acquire,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.6
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
tank_push = {
|
||||
name = "Armor: Tank Push",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMatadorTankMode] = 2,
|
||||
[UnitId.TerranPhalanxTankMode] = 2,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1,
|
||||
-- filler units
|
||||
[UnitId.TerranCyprian] = 1,
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranMadrigalImperiosoMode] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.tank_push,
|
||||
Tier2.acquire,
|
||||
Tier2.stockade_requeue,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
two_fulc_vulture = {
|
||||
name = "Armor: 2Fulc Vulture",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranVulture] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranMaverick] = 1,
|
||||
[UnitId.TerranCyclops] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.two_fulc_vulture,
|
||||
Tier1.two_fulc_vulture,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
fe_five_fulc = {
|
||||
name = "Armor: FE 5Fulc",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranVulture] = 2,
|
||||
[UnitId.TerranBlackjack] = 2,
|
||||
[UnitId.TerranPhalanxTankMode] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranMaverick] = 1,
|
||||
[UnitId.TerranAzazel] = 1,
|
||||
[UnitId.TerranSeraph] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.fe_five_fulc,
|
||||
Tier1.fe_five_fulc,
|
||||
Tier2.starport_commandment_buildup,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
david_and_goliath = {
|
||||
name = "Armor: David and Goliath",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranGoliath] = 3,
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranMatadorTankMode] = 1,
|
||||
[UnitId.TerranPhalanxTankMode] = 1,
|
||||
[UnitId.TerranWraith] = 1,
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.david_and_goliath,
|
||||
Tier1.david_and_goliath,
|
||||
Tier2.acquire,
|
||||
Tier2.fulcrum_scaling,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
iron_crusade = {
|
||||
name = "Armor: Iron Crusade",
|
||||
unit_composition = {
|
||||
-- signature units (Iron Foundry x4 is the real investment of this build)
|
||||
[UnitId.TerranPaladin] = 3,
|
||||
[UnitId.TerranCuirassTankMode] = 2,
|
||||
[UnitId.TerranPazuzu] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranVulture] = 1,
|
||||
[UnitId.TerranWraith] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.expand_first,
|
||||
Tier1.iron_crusade,
|
||||
Tier2.acquire,
|
||||
Tier2.fulcrum_buildup,
|
||||
Tier3.acquire,
|
||||
Tier3.iron_foundries,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
walker_power = {
|
||||
name = "Armor: Walker Power",
|
||||
unit_composition = {
|
||||
-- signature units (walkers)
|
||||
[UnitId.TerranGoliath] = 3,
|
||||
[UnitId.TerranCyclops] = 2,
|
||||
[UnitId.TerranBlackjack] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranPhalanxTankMode] = 1,
|
||||
[UnitId.TerranMaverick] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.walker_power,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
31
mpq/lua/melee/terran/build/basic.lua
Normal file
31
mpq/lua/melee/terran/build/basic.lua
Normal file
@ -0,0 +1,31 @@
|
||||
local Basic = {}
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.TerranMinistry, 120)
|
||||
town:wait_build(1, UnitId.TerranMinistry)
|
||||
town:build(town.max_workers, UnitId.TerranMason, 100)
|
||||
town:transfer_workers(8)
|
||||
town:wait_build(10, UnitId.TerranMason)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_anti_ground(melee_ai, town)
|
||||
for i = 1, 2 do
|
||||
town:build(i, UnitId.TerranAnchor, 70 - i * 5)
|
||||
wait(secs(25 + i * 5))
|
||||
end
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_anti_air(melee_ai, town)
|
||||
for i = 1, 4 do
|
||||
town:build(i, UnitId.TerranWatchdog, 80 - i * 5)
|
||||
wait(secs(25 + i * 5))
|
||||
end
|
||||
end
|
||||
|
||||
return Basic
|
||||
416
mpq/lua/melee/terran/build/openers.lua
Normal file
416
mpq/lua/melee/terran/build/openers.lua
Normal file
@ -0,0 +1,416 @@
|
||||
---@class TerranOpeners
|
||||
local Openers = {}
|
||||
|
||||
-- Shared short openers (still used as-is by personalities whose own build
|
||||
-- order never repositions an attack/expand trigger within this phase).
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.expand_first(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.expand_first_slow(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.expand_first_very_slow(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.fulcrum_start_medium(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.stockade_quick_start(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
end
|
||||
|
||||
-- Armor
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.tank_push(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranScrapyard, 90)
|
||||
town:multirun(function()
|
||||
wait(secs(18))
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 89)
|
||||
town:wait_build(4, UnitId.TerranFulcrum)
|
||||
town:build(3, UnitId.TerranPalladium, 89)
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
end)
|
||||
town:wait_build(1, UnitId.TerranScrapyard, false)
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.two_fulc_vulture(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.fe_five_fulc(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:build(1, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.david_and_goliath(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
town:wait_build(2, UnitId.TerranStockade, false)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
town:multirun(function()
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 89)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(5, UnitId.TerranFulcrum)
|
||||
town:build(3, UnitId.TerranPalladium, 89)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.walker_power(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 89)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(10))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
-- Raider
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.eight_rax(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(5, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(6, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:wait_build(6, UnitId.TerranStockade, false)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.three_rax_bio(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(5))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranVestry, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(10))
|
||||
town:wait_build(3, UnitId.TerranStockade, false)
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.fast_anvil(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.four_rax_pressure(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.holy_ackmeds(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(4, UnitId.TerranStockade, false)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
-- Orbital
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.rapid_starpads(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 110)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(5))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.wraith_bio(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.hotdrop(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
town:build(2, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(35))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(3, UnitId.TerranStarpad)
|
||||
town:wait_build(2, UnitId.TerranStockade, false)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.sudden_starport(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:wait_build(3, UnitId.TerranStockade, false)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.aces_high(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(3, UnitId.TerranScrapyard, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
-- General
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.two_fulcrum_mech(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.doubling_up(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
wait(secs(1))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(1, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranScrapyard, 89)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranCovenant, 89)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.mech_into_air(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranFulcrum, 110)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.observant(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 110)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
end
|
||||
|
||||
return Openers
|
||||
238
mpq/lua/melee/terran/build/tier1.lua
Normal file
238
mpq/lua/melee/terran/build/tier1.lua
Normal file
@ -0,0 +1,238 @@
|
||||
---@class TerranTier1
|
||||
local Tier1 = {}
|
||||
|
||||
-- Shared expansion-order helpers (unrelated to the opener/tier1 split).
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.vestry_request(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.covenant_request(melee_ai, town)
|
||||
town:build(1, UnitId.TerranCovenant, 89)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
-- Armor (scale-up after the opener; unlisted personalities fold entirely
|
||||
-- into their opener and skip tier1)
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.two_fulc_vulture(melee_ai, town)
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.fe_five_fulc(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.david_and_goliath(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(20))
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.iron_crusade(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(20))
|
||||
end
|
||||
|
||||
-- Raider
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.eight_rax(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(8, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.fast_anvil(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(3, UnitId.TerranStockade, false)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranCovenant, 89)
|
||||
town:wait_build(1, UnitId.TerranCovenant, false)
|
||||
town:build(1, UnitId.TerranAnvil, 89)
|
||||
town:wait_build(3, UnitId.TerranStockade)
|
||||
town:wait_build(1, UnitId.TerranAnvil, false)
|
||||
town:build(2, UnitId.TerranCovenant, 89)
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:build(3, UnitId.TerranCovenant, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.four_rax_pressure(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranVestry, 89)
|
||||
town:wait_build(3, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranCovenant, 89)
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranCovenant, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.uprising(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranVestry, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:wait_build(2, UnitId.TerranVestry)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
-- Orbital
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.rapid_starpads(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(2, UnitId.TerranStarpad)
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(5))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.orbital_stockade_settle(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.wraith_bio(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:wait_build(3, UnitId.TerranStockade, false)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.aces_high(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(20))
|
||||
end
|
||||
|
||||
-- General
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.two_fulcrum_mech(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(3, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.general_stockade_fulcrum_vestry_palladium_starpad(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.TerranFulcrum, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 89)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 89)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.general_stockade_starpad(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStockade, 90)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.doubling_up(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.TerranStarpad, 90)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
return Tier1
|
||||
322
mpq/lua/melee/terran/build/tier2.lua
Normal file
322
mpq/lua/melee/terran/build/tier2.lua
Normal file
@ -0,0 +1,322 @@
|
||||
---@class TerranTier2
|
||||
local Tier2 = {}
|
||||
|
||||
--- Requests Atlas and waits for it. The generic tier-2 tech transition.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.acquire(melee_ai, town)
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.TerranAtlas, 70, true)
|
||||
end)
|
||||
end
|
||||
|
||||
--- Requests a bare Starport once Atlas exists, for base air units.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.starport(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.TerranStarport, 69, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.stockade_requeue(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.TerranStockade, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.starport_commandment_buildup(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 69)
|
||||
wait(secs(2))
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranCommandment, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(2, UnitId.TerranFulcrum, false)
|
||||
melee_ai:dynamic_wait(secs(70) + secs(25))
|
||||
town:build(5, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.fulcrum_scaling(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(4, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(5, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.fulcrum_buildup(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(3, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:wait_build(3, UnitId.TerranFulcrum, false)
|
||||
wait(secs(1))
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(4, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.raider_vestry_covenant_buildup(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranVestry, 69)
|
||||
town:wait_build(3, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranCovenant, 69)
|
||||
town:wait_build(4, UnitId.TerranStockade)
|
||||
town:build(2, UnitId.TerranCovenant, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.raider_stockade_requeue(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.TerranStockade, 70)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.raider_vestry_starport_rotary(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.orbital_starport_rotary_commandment(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
town:build(2, UnitId.TerranStarport, 70)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranRotary, 69)
|
||||
town:build(3, UnitId.TerranStarport, 70)
|
||||
town:wait_build(3, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranCommandment, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.orbital_covenant_anvil_starport_rotary(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:multirun(function()
|
||||
town:build(1, UnitId.TerranCovenant, 69)
|
||||
town:wait_build(1, UnitId.TerranCovenant)
|
||||
town:build(1, UnitId.TerranAnvil, 69)
|
||||
wait(secs(1))
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
town:build(2, UnitId.TerranStarport, 70)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranRotary, 69)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.orbital_vestry_starport_rotary_x4(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(2, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport, false)
|
||||
town:build(4, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranRotary, 69)
|
||||
town:wait_build(3, UnitId.TerranStarport)
|
||||
town:build(3, UnitId.TerranRotary, 69)
|
||||
town:wait_build(4, UnitId.TerranStarport)
|
||||
town:build(4, UnitId.TerranRotary, 69)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.general_expansion_tail(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.TerranStarpad, 69, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
Tier2.acquire(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranStockade, 69, true)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranCovenant, 69, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.TerranStarport, 69, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.general_scrapyard_palladium_mantle(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(4, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40) + secs(40))
|
||||
town:build(2, UnitId.TerranMantle, 70)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.general_vestry_palladium_starport_rotary(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40) + secs(25) + secs(50))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.general_fulcrum_follow_up(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.general_mega_tech_buildup(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranScrapyard, 69)
|
||||
town:build(1, UnitId.TerranQuarry, 69)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(4, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(2, UnitId.TerranStarport, 70)
|
||||
town:wait_build(1, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranRotary, 69)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranRotary, 69)
|
||||
town:wait_build(5, UnitId.TerranFulcrum)
|
||||
town:build(3, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(6, UnitId.TerranFulcrum)
|
||||
town:build(4, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(3, UnitId.TerranStarport)
|
||||
town:build(3, UnitId.TerranRotary, 69)
|
||||
town:wait_build(4, UnitId.TerranStarport)
|
||||
town:build(4, UnitId.TerranRotary, 69)
|
||||
town:wait_build(5, UnitId.TerranStarport)
|
||||
town:build(5, UnitId.TerranRotary, 69)
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
town:wait_build(6, UnitId.TerranStarport)
|
||||
town:build(1, UnitId.TerranCommandment, 69)
|
||||
town:wait_build(7, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranCommandment, 69)
|
||||
town:wait_build(8, UnitId.TerranStarport)
|
||||
town:build(3, UnitId.TerranCommandment, 69)
|
||||
town:build(2, UnitId.TerranNaniteAssembly, 69)
|
||||
town:wait_build(1, UnitId.TerranNaniteAssembly)
|
||||
town:build(1, UnitId.TerranHadron, 69)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(1, UnitId.TerranStarpad, 70)
|
||||
melee_ai:dynamic_wait(secs(15) + mins(1) + secs(15))
|
||||
town:build(6, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.general_vestry_scrapyard_palladium_starport_commandment(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.TerranStockade)
|
||||
town:build(1, UnitId.TerranVestry, 69)
|
||||
town:wait_build(1, UnitId.TerranFulcrum)
|
||||
town:build(1, UnitId.TerranScrapyard, 69)
|
||||
town:wait_build(2, UnitId.TerranFulcrum)
|
||||
town:build(2, UnitId.TerranPalladium, 69)
|
||||
town:wait_build(3, UnitId.TerranFulcrum)
|
||||
wait(secs(1))
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(2, UnitId.TerranStarport, 70)
|
||||
town:wait_build(2, UnitId.TerranStarport)
|
||||
town:build(2, UnitId.TerranCommandment, 69)
|
||||
town:wait_build(1, UnitId.TerranCommandment)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(5) + secs(35))
|
||||
town:build(1, UnitId.TerranStarpad, 70)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(25) + secs(50))
|
||||
Tier2.acquire(melee_ai, town)
|
||||
town:build(3, UnitId.TerranFulcrum, 70)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
return Tier2
|
||||
49
mpq/lua/melee/terran/build/tier3.lua
Normal file
49
mpq/lua/melee/terran/build/tier3.lua
Normal file
@ -0,0 +1,49 @@
|
||||
---@class TerranTier3
|
||||
local Tier3 = {}
|
||||
|
||||
--- Requests Daedala and waits for it. The generic tier-3 tech transition.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.acquire(melee_ai, town)
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:wait_build(1, UnitId.TerranAtlas)
|
||||
town:build(1, UnitId.TerranDaedala, 65, true)
|
||||
end)
|
||||
wait(secs(1))
|
||||
town:wait_build(1, UnitId.TerranDaedala)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.iron_foundries(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.TerranIronFoundry, 50)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.TerranIronFoundry, 50)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(3, UnitId.TerranIronFoundry, 50)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(4, UnitId.TerranIronFoundry, 50)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.nanite_assembly_buildup(melee_ai, town)
|
||||
town:build(2, UnitId.TerranNaniteAssembly, 50)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(3, UnitId.TerranNaniteAssembly, 50)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.general_starport_scaling(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(4, UnitId.TerranStarport, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(8, UnitId.TerranStarport, 50)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
end
|
||||
|
||||
return Tier3
|
||||
161
mpq/lua/melee/terran/general.lua
Normal file
161
mpq/lua/melee/terran/general.lua
Normal file
@ -0,0 +1,161 @@
|
||||
local Basic = require("melee.terran.build.basic")
|
||||
local Openers = require("melee.terran.build.openers")
|
||||
local Tier1 = require("melee.terran.build.tier1")
|
||||
local Tier2 = require("melee.terran.build.tier2")
|
||||
local Tier3 = require("melee.terran.build.tier3")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier2.general_expansion_tail,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.5
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
two_fulcrum_mech = {
|
||||
name = "General: 2 Fulcrum Mech",
|
||||
unit_composition = {
|
||||
-- signature units (Mantle x2)
|
||||
[UnitId.TerranPhalanxTankMode] = 2,
|
||||
[UnitId.TerranRamesses] = 2,
|
||||
[UnitId.TerranDurendal] = 2,
|
||||
[UnitId.TerranCataphract] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranMadrigalImperiosoMode] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.two_fulcrum_mech,
|
||||
Tier1.two_fulcrum_mech,
|
||||
Tier2.acquire,
|
||||
Tier2.general_scrapyard_palladium_mantle,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
early_riser = {
|
||||
name = "General: Early Riser",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1,
|
||||
-- filler units
|
||||
[UnitId.TerranCyclops] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.expand_first_very_slow,
|
||||
Tier1.general_stockade_fulcrum_vestry_palladium_starpad,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
the_cube = {
|
||||
name = "General: The Cube",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranVulture] = 1,
|
||||
[UnitId.TerranPhalanxTankMode] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.fulcrum_start_medium,
|
||||
Tier1.general_stockade_starpad,
|
||||
Tier2.general_vestry_palladium_starport_rotary,
|
||||
Tier2.acquire,
|
||||
Tier2.general_fulcrum_follow_up,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
doubling_up = {
|
||||
name = "General: Doubling Up",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
[UnitId.TerranGoliath] = 2,
|
||||
-- healers
|
||||
[UnitId.TerranShamanSupportMode] = 1,
|
||||
-- filler units
|
||||
[UnitId.TerranCyclops] = 1,
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.doubling_up,
|
||||
Tier1.doubling_up,
|
||||
Tier2.acquire,
|
||||
Tier2.general_fulcrum_follow_up,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
mech_into_air = {
|
||||
name = "General: Mech into Air",
|
||||
unit_composition = {
|
||||
-- signature units (the mech-into-air transition)
|
||||
[UnitId.TerranPhalanxTankMode] = 2,
|
||||
[UnitId.TerranMinotaur] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranMatadorTankMode] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranSeraph] = 1,
|
||||
[UnitId.TerranHippogriff] = 1,
|
||||
[UnitId.TerranPhobos] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.mech_into_air,
|
||||
Tier2.acquire,
|
||||
Tier2.general_mega_tech_buildup,
|
||||
Tier3.acquire,
|
||||
Tier3.general_starport_scaling,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
observant = {
|
||||
name = "General: Observant",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranCyprian] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranSeraph] = 1,
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.observant,
|
||||
Tier2.general_vestry_scrapyard_palladium_starport_commandment,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
153
mpq/lua/melee/terran/orbital.lua
Normal file
153
mpq/lua/melee/terran/orbital.lua
Normal file
@ -0,0 +1,153 @@
|
||||
local Basic = require("melee.terran.build.basic")
|
||||
local Openers = require("melee.terran.build.openers")
|
||||
local Tier1 = require("melee.terran.build.tier1")
|
||||
local Tier2 = require("melee.terran.build.tier2")
|
||||
local Tier3 = require("melee.terran.build.tier3")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier2.starport,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.6
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
rapid_starpads = {
|
||||
name = "Orbital: 2 Starpad Wraith",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranWraith] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
[UnitId.TerranAzazel] = 1,
|
||||
[UnitId.TerranSeraph] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.rapid_starpads,
|
||||
Tier1.rapid_starpads,
|
||||
Tier2.acquire,
|
||||
Tier2.orbital_starport_rotary_commandment,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
the_don = {
|
||||
name = "Orbital: The Don",
|
||||
unit_composition = {
|
||||
-- signature units (Nanite Assembly x3)
|
||||
[UnitId.TerranMinotaur] = 2,
|
||||
[UnitId.TerranCentaur] = 2,
|
||||
[UnitId.TerranMagnetar] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranGorgon] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.expand_first_slow,
|
||||
Tier1.orbital_stockade_settle,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
Tier3.nanite_assembly_buildup,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
wraith_bio = {
|
||||
name = "Orbital: Wraith Bio",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMaverick] = 3,
|
||||
[UnitId.TerranWraith] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranValkyrie] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.wraith_bio,
|
||||
Tier1.wraith_bio,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
hotdrop = {
|
||||
name = "Orbital: Hotdrop",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranHarakan] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranWraith] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.hotdrop,
|
||||
Tier2.acquire,
|
||||
Tier2.orbital_covenant_anvil_starport_rotary,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
sudden_starport = {
|
||||
name = "Orbital: Sudden Starport",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMaverick] = 2,
|
||||
[UnitId.TerranSundog] = 2,
|
||||
[UnitId.TerranSalamander] = 2,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1.5,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.sudden_starport,
|
||||
Tier2.orbital_vestry_starport_rotary_x4,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
aces_high = {
|
||||
name = "Orbital: Aces High",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranVulture] = 3,
|
||||
[UnitId.TerranWraith] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranBlackjack] = 1,
|
||||
[UnitId.TerranCyclops] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.aces_high,
|
||||
Tier1.aces_high,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
153
mpq/lua/melee/terran/raider.lua
Normal file
153
mpq/lua/melee/terran/raider.lua
Normal file
@ -0,0 +1,153 @@
|
||||
local Basic = require("melee.terran.build.basic")
|
||||
local Openers = require("melee.terran.build.openers")
|
||||
local Tier1 = require("melee.terran.build.tier1")
|
||||
local Tier2 = require("melee.terran.build.tier2")
|
||||
local Tier3 = require("melee.terran.build.tier3")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier1.vestry_request,
|
||||
Tier2.acquire,
|
||||
Tier1.covenant_request,
|
||||
Tier3.acquire,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.4
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
eight_rax = {
|
||||
name = "Raider: 8Rax",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranMaverick] = 3,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.TerranHarakan] = 1,
|
||||
[UnitId.TerranCyprian] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.eight_rax,
|
||||
Tier1.eight_rax,
|
||||
Tier2.acquire,
|
||||
Tier2.raider_vestry_covenant_buildup,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
three_rax_bio = {
|
||||
name = "Raider: 3Rax Maverick & Cleric",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranMaverick] = 3,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranEidolon] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.three_rax_bio,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
fast_anvil = {
|
||||
name = "Raider: Fast Anvil",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranCyprian] = 2,
|
||||
[UnitId.TerranEidolon] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranMaverick] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.fast_anvil,
|
||||
Tier1.fast_anvil,
|
||||
Tier2.acquire,
|
||||
Tier2.raider_stockade_requeue,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
four_rax_pressure = {
|
||||
name = "Raider: 4Rax Pressure",
|
||||
unit_composition = {
|
||||
-- healers
|
||||
[UnitId.TerranShamanSupportMode] = 2,
|
||||
-- filler units
|
||||
[UnitId.TerranSavantEntropyGauntlets] = 1,
|
||||
[UnitId.TerranCyprian] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.four_rax_pressure,
|
||||
Tier1.four_rax_pressure,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
uprising = {
|
||||
name = "Raider: Uprising",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.TerranCyprian] = 3,
|
||||
-- healers
|
||||
[UnitId.TerranCleric] = 1.5,
|
||||
-- filler units
|
||||
[UnitId.TerranEidolon] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.stockade_quick_start,
|
||||
Tier1.uprising,
|
||||
Tier2.acquire,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
holy_ackmeds = {
|
||||
name = "Raider: Holy Ackmeds!",
|
||||
unit_composition = {
|
||||
-- signature unit
|
||||
[UnitId.TerranHarakan] = 3,
|
||||
-- filler units
|
||||
[UnitId.TerranSundog] = 1,
|
||||
[UnitId.TerranSalamander] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.holy_ackmeds,
|
||||
Tier2.acquire,
|
||||
Tier2.raider_vestry_starport_rotary,
|
||||
Tier3.acquire,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
177
mpq/lua/melee/zerg/assault.lua
Normal file
177
mpq/lua/melee/zerg/assault.lua
Normal file
@ -0,0 +1,177 @@
|
||||
local Basic = require("melee.zerg.build.basic")
|
||||
local Openers = require("melee.zerg.build.openers")
|
||||
local Tier1 = require("melee.zerg.build.tier1")
|
||||
local Tier2 = require("melee.zerg.build.tier2")
|
||||
local Tier3 = require("melee.zerg.build.tier3")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier1.saturated_production,
|
||||
Tier3.assault_expansion,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.6
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
three_base_hydrith = {
|
||||
name = "Assault: 3 Base Hydrith",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergHydralisk] = 3,
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.three_base_hydrith,
|
||||
Tier1.three_base_hydrith,
|
||||
Tier2.hydrith_iroliris_hachirosk_zorkiz,
|
||||
Tier3.hydrith_othstol_hachirosk,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
two_base_zorkiz = {
|
||||
name = "Assault: 2 Base Hydrith-Zorkiz",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergHydralisk] = 3,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
[UnitId.ZergZoryusthaleth] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergIzirokor] = 1,
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.two_base_zorkiz,
|
||||
Tier1.two_base_zorkiz,
|
||||
Tier2.zorkiz_iroliris_tethvith,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
two_base_hydrith_quazeth = {
|
||||
name = "Assault: 2 Base Hydrith-Quazeth",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergHydralisk] = 3,
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergQuazilisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.two_base_hydrith_quazeth,
|
||||
Tier1.two_base_hydrith_quazeth,
|
||||
Tier2.hydrith_quazeth_iroliris_vornath_kalkiir,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
two_base_alkag = {
|
||||
name = "Assault: 2 Base Alkag",
|
||||
unit_composition = {
|
||||
-- signature units (Alkag Iteth)
|
||||
[UnitId.ZergKagralisk] = 2,
|
||||
[UnitId.ZergEvigrilisk] = 2,
|
||||
[UnitId.ZergAlmaksalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.two_base_alkag,
|
||||
Tier2.alkag_iroliris_hachirosk,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
potency = {
|
||||
name = "Assault: Potency",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZoryusthaleth] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
[UnitId.ZergKalkalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergKagralisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergEvigrilisk] = 1,
|
||||
[UnitId.ZergAlmaksalisk] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.hydrith_den_start,
|
||||
Tier1.hachirosk_zorkiz_skibact_quazeth_scaleup,
|
||||
Tier2.potency_iroliris_hachirosk_alkag,
|
||||
Tier3.potency_othstol_settle,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
earthen_tides = {
|
||||
name = "Assault: Earthen Tides",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergIzirokor] = 2,
|
||||
[UnitId.ZergLakizilisk] = 2,
|
||||
[UnitId.ZergProtathalor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergKeskathalor] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.hydrith_den_start,
|
||||
Tier1.hachirosk_zorkiz_skibact_quazeth_scaleup,
|
||||
Tier2.earthen_iroliris_hachirosk_vornath_mutath_matravil,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
31
mpq/lua/melee/zerg/build/basic.lua
Normal file
31
mpq/lua/melee/zerg/build/basic.lua
Normal file
@ -0,0 +1,31 @@
|
||||
local Basic = {}
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.ZergHachirosk, 120)
|
||||
town:wait_build(1, UnitId.ZergHachirosk)
|
||||
town:build(town.max_workers, UnitId.ZergDroleth, 100)
|
||||
town:transfer_workers(8)
|
||||
town:wait_build(10, UnitId.ZergDroleth)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_anti_ground(melee_ai, town)
|
||||
for i = 1, 3 do
|
||||
town:build(i, UnitId.ZergSurkithCesiant, 80 - i * 5)
|
||||
wait(secs(25 + i * 5))
|
||||
end
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Basic.build_anti_air(melee_ai, town)
|
||||
for i = 1, 3 do
|
||||
town:build(i, UnitId.ZergSpraithCesiant, 80 - i * 5)
|
||||
wait(secs(25 + i * 5))
|
||||
end
|
||||
end
|
||||
|
||||
return Basic
|
||||
298
mpq/lua/melee/zerg/build/openers.lua
Normal file
298
mpq/lua/melee/zerg/build/openers.lua
Normal file
@ -0,0 +1,298 @@
|
||||
---@class ZergOpeners
|
||||
local Openers = {}
|
||||
|
||||
-- Shared opener still used unmodified by a personality whose own build order
|
||||
-- never repositions an attack/expand trigger within this phase.
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.quazeth_pool_check_then_expand(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 110, true)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool, false)
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
-- Assault
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.three_base_hydrith(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.two_base_zorkiz(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.two_base_hydrith_quazeth(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.two_base_alkag(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 90, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergAlkagIteth, 90, true)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 90, true)
|
||||
end)
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
--- Shared by Potency and Earthen Tides (identical build up to this point).
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.hydrith_den_start(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergHydrithDen, 110, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
-- Swarm
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.three_base_flood(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergQuazethPool, 110, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.three_base_ultrav(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.instant_quazeth(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergQuazethPool, 110, true)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:wait_build(1, UnitId.ZergQuazethPool, false)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:start_attacking()
|
||||
wait(secs(4))
|
||||
town:build(4, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(20))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.three_base_othstol(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(55))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.gates_of_hell(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(55))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.primitive_pressure(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
-- Sunblot
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.big_and_little(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.the_triad(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.skittering_duo(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.early_birds(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(25))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.flying_feint(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergQuazethPool, 110, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
melee_ai:start_expanding()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.descending_horizon(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergQuazethPool, 110, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(50))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
-- General
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.sleeping_giant(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.shrieking_swarm(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.subjugation(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergDroleth, 100)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.before_the_storm(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 110, true)
|
||||
town:wait_build(1, UnitId.ZergQuazethPool, false)
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergDroleth, 100)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
melee_ai:start_attacking()
|
||||
melee_ai:dynamic_wait(mins(2) + secs(30))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Openers.time_after_time(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
melee_ai:start_expanding()
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
melee_ai:start_attacking()
|
||||
end
|
||||
|
||||
return Openers
|
||||
229
mpq/lua/melee/zerg/build/tier1.lua
Normal file
229
mpq/lua/melee/zerg/build/tier1.lua
Normal file
@ -0,0 +1,229 @@
|
||||
---@class ZergTier1
|
||||
local Tier1 = {}
|
||||
|
||||
--- Saturated hatchery/larva production ramp, reused by every category's main build order.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.saturated_production(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(5, UnitId.ZergLarvoskCesiant, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergHachirosk, 90)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergCaphrolosk, 90)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(6, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Assault (scale-up after the opener; unlisted personalities fold entirely
|
||||
-- into their opener and skip tier1)
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.three_base_hydrith(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.two_base_zorkiz(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.two_base_hydrith_quazeth(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
--- Shared by Potency and Earthen Tides (identical build up to this point).
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.hachirosk_zorkiz_skibact_quazeth_scaleup(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
-- Swarm
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.three_base_flood(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.instant_quazeth(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(55))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(45))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.three_base_othstol(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.gates_of_hell(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.primitive_pressure(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
-- Sunblot
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.big_and_little(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(55))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.the_triad(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(10))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.skittering_duo(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(75))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(20))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.early_birds(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.flying_feint(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
-- General
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.sleeping_giant(melee_ai, town)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:wait_build(15, UnitId.ZergDroleth)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.shrieking_swarm(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.subjugation(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.time_after_time(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(75))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(secs(75))
|
||||
town:build(1, UnitId.ZergSkibactScab, 90, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 90, true)
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier1.coil_buildup(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergDroleth, 100)
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.ZergQuazethPool, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergHydrithDen, 90, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 90, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
end
|
||||
|
||||
return Tier1
|
||||
512
mpq/lua/melee/zerg/build/tier2.lua
Normal file
512
mpq/lua/melee/zerg/build/tier2.lua
Normal file
@ -0,0 +1,512 @@
|
||||
---@class ZergTier2
|
||||
local Tier2 = {}
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.hydrith_iroliris_hachirosk_zorkiz(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.zorkiz_iroliris_tethvith(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20) + secs(15))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.hydrith_quazeth_iroliris_vornath_kalkiir(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.alkag_iroliris_hachirosk(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(5))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.potency_iroliris_hachirosk_alkag(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergAlkagIteth, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.earthen_iroliris_hachirosk_vornath_mutath_matravil(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(5))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.flood_vornath_kalkiir_mutath_tosvrol_then_iroliris_caphrolosk_hachirosk(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:wait_build(3, UnitId.ZergHachirosk, false)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
town:wait_build(1, UnitId.ZergMutathSpire)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(20))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.ultrav_iroliris_caphrolosk_buildup(melee_ai, town)
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(55))
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:wait_build(1, UnitId.ZergZorkizShroud)
|
||||
town:wait_build(2, UnitId.ZergHachirosk, false)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergGathtelosk, 50)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(45))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.instant_iroliris_vornath_kalkiir(melee_ai, town)
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(3) + secs(20))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.othstol_iroliris_buildup(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:wait_build(1, UnitId.ZergZorkizShroud)
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergZozarcGorge, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
town:wait_build(1, UnitId.ZergOthstolOviform)
|
||||
town:build(1, UnitId.ZergGathtelosk, 50)
|
||||
town:wait_build(1, UnitId.ZergGathtelosk, false)
|
||||
town:wait_build(2, UnitId.ZergHachirosk, false)
|
||||
end)
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.gates_buildup_vornath_hachirosk_iroliris(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:wait_build(1, UnitId.ZergZorkizShroud)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergZozarcGorge, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(mins(8) + secs(20))
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
end)
|
||||
end)
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.pressure_iroliris_vornath_skibact_tethvith(melee_ai, town)
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.big_little_iroliris_buildup_caphrolosk_hachirosk(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
wait(secs(1))
|
||||
town:multirun(function()
|
||||
wait(secs(1))
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:wait_build(1, UnitId.ZergZorkizShroud)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
town:wait_build(1, UnitId.ZergMutathSpire)
|
||||
melee_ai:dynamic_wait(mins(3) + secs(20))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(45))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.birds_iroliris_alkag(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergAlkagIteth, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(30))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.feint_iroliris_buildup_vornath_hydrith_skibact(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(3) + secs(20))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.horizon_iroliris_buildup(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
town:wait_build(1, UnitId.ZergVornathPond)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
town:wait_build(1, UnitId.ZergMutathSpire)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(2))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.giant_iroliris_caphrolosk_hachirosk_zorkiz_buildup(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15) + secs(5))
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(mins(2) + secs(45))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.swarm_iroliris_vornathkalkiir_zorkiz_caphrolosk_hachirosk(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(mins(1))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.subjugation_quazeth_iroliris_buildup(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:multirun(function()
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergHydrithDen)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergSkibactScab, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
town:wait_build(1, UnitId.ZergIrolIris)
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(45))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.storm_iroliris_hachirosk_vornathkalkiir(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(3, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(4, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.time_iroliris_vornathkalkiir(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:multirun(function()
|
||||
town:wait_build(1, UnitId.ZergQuazethPool)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergVornathPond, 70, true)
|
||||
melee_ai:dynamic_wait(mins(1) + secs(40))
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(30))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier2.coil_iroliris_hachirosk(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(30) + mins(1) + secs(5))
|
||||
town:build(2, UnitId.ZergHachirosk, 115)
|
||||
end
|
||||
|
||||
return Tier2
|
||||
168
mpq/lua/melee/zerg/build/tier3.lua
Normal file
168
mpq/lua/melee/zerg/build/tier3.lua
Normal file
@ -0,0 +1,168 @@
|
||||
---@class ZergTier3
|
||||
local Tier3 = {}
|
||||
|
||||
--- Requests Othstol Oviform and waits for it. The generic tier-3 tech
|
||||
--- transition, for personalities without bespoke tier-3 content.
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.acquire(melee_ai, town)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.hydrith_othstol_hachirosk(melee_ai, town)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(4, UnitId.ZergHachirosk, 115)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.potency_othstol_settle(melee_ai, town)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.horizon_othstol(melee_ai, town)
|
||||
town:multirun(function()
|
||||
melee_ai:dynamic_wait(mins(1) + secs(15))
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
end)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.giant_othstol_gathtelosk(melee_ai, town)
|
||||
town:multirun(function()
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
end)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergGathtelosk, 50)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
end
|
||||
|
||||
-- Category expansion tails: reuse the same shared node-acquisition pattern per
|
||||
-- category, run once a new town is expanded into.
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.assault_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergCaphrolosk, 70)
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergHachirosk, 70)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergGathtelosk, 50)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergAlmakisAntre, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergGeszkathGrotto, 50, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.swarm_expansion(melee_ai, town)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
town:build(1, UnitId.ZergGathtelosk, 50)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergAlmakisAntre, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergGeszkathGrotto, 50, true)
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.sunblot_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergAlmakisAntre, 70, true)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergGathtelosk, 50)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergGeszkathGrotto, 50, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
end
|
||||
|
||||
---@param melee_ai MeleeAI
|
||||
---@param town Town
|
||||
function Tier3.general_expansion(melee_ai, town)
|
||||
town:build(1, UnitId.ZergHydrithDen, 70, true)
|
||||
melee_ai:dynamic_wait(secs(20))
|
||||
town:build(1, UnitId.ZergQuazethPool, 70, true)
|
||||
town:build(1, UnitId.ZergKalkiirLake, 70, true)
|
||||
town:build(1, UnitId.ZergIrolIris, 70, true)
|
||||
melee_ai:dynamic_wait(secs(5))
|
||||
town:build(1, UnitId.ZergMutathSpire, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergZorkizShroud, 70, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergTethvithSwamp, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergOthstolOviform, 65, true)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergGathtelosk, 50)
|
||||
melee_ai:dynamic_wait(secs(15))
|
||||
town:build(1, UnitId.ZergUlgorgCavern, 70, true)
|
||||
melee_ai:dynamic_wait(secs(40))
|
||||
town:build(1, UnitId.ZergTosvrolHaunt, 70, true)
|
||||
melee_ai:dynamic_wait(secs(25))
|
||||
town:build(1, UnitId.ZergMatravilNest, 70, true)
|
||||
town:build(1, UnitId.ZergAlmakisAntre, 70, true)
|
||||
melee_ai:dynamic_wait(secs(50))
|
||||
town:build(1, UnitId.ZergGeszkathGrotto, 50, true)
|
||||
end
|
||||
|
||||
return Tier3
|
||||
176
mpq/lua/melee/zerg/general.lua
Normal file
176
mpq/lua/melee/zerg/general.lua
Normal file
@ -0,0 +1,176 @@
|
||||
local Basic = require("melee.zerg.build.basic")
|
||||
local Openers = require("melee.zerg.build.openers")
|
||||
local Tier1 = require("melee.zerg.build.tier1")
|
||||
local Tier2 = require("melee.zerg.build.tier2")
|
||||
local Tier3 = require("melee.zerg.build.tier3")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier1.saturated_production,
|
||||
Tier3.general_expansion,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.5
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
sleeping_giant = {
|
||||
name = "General: Sleeping Giant",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.sleeping_giant,
|
||||
Tier1.sleeping_giant,
|
||||
Tier2.giant_iroliris_caphrolosk_hachirosk_zorkiz_buildup,
|
||||
Tier3.giant_othstol_gathtelosk,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
shrieking_swarm = {
|
||||
name = "General: Shrieking Swarm",
|
||||
unit_composition = {
|
||||
-- signature units (Vornath Pond)
|
||||
[UnitId.ZergVorvrokor] = 2,
|
||||
[UnitId.ZergNathrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergUltrokor] = 1,
|
||||
[UnitId.ZergHydralisk] = 1,
|
||||
[UnitId.ZergLakizilisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.shrieking_swarm,
|
||||
Tier1.shrieking_swarm,
|
||||
Tier2.swarm_iroliris_vornathkalkiir_zorkiz_caphrolosk_hachirosk,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
subjugation = {
|
||||
name = "General: Subjugation",
|
||||
unit_composition = {
|
||||
-- signature units (Skibact Scab)
|
||||
[UnitId.ZergSkithrokor] = 2,
|
||||
[UnitId.ZergBactalisk] = 2,
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKeskathalor] = 1,
|
||||
[UnitId.ZergHydralisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergVithrilisk] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.subjugation,
|
||||
Tier1.subjugation,
|
||||
Tier2.subjugation_quazeth_iroliris_buildup,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
before_the_storm = {
|
||||
name = "General: Before the Storm",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergKalkalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.before_the_storm,
|
||||
Tier2.storm_iroliris_hachirosk_vornathkalkiir,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
time_after_time = {
|
||||
name = "General: Time After Time",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergSkithrokor] = 2,
|
||||
[UnitId.ZergLakizilisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergLiiralisk] = 1,
|
||||
[UnitId.ZergCikralisk] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.time_after_time,
|
||||
Tier1.time_after_time,
|
||||
Tier2.time_iroliris_vornathkalkiir,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
constrained_coil = {
|
||||
name = "General: Constrained Coil",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergKalkalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.quazeth_pool_check_then_expand,
|
||||
Tier1.coil_buildup,
|
||||
Tier2.coil_iroliris_hachirosk,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
174
mpq/lua/melee/zerg/sunblot.lua
Normal file
174
mpq/lua/melee/zerg/sunblot.lua
Normal file
@ -0,0 +1,174 @@
|
||||
local Basic = require("melee.zerg.build.basic")
|
||||
local Openers = require("melee.zerg.build.openers")
|
||||
local Tier1 = require("melee.zerg.build.tier1")
|
||||
local Tier2 = require("melee.zerg.build.tier2")
|
||||
local Tier3 = require("melee.zerg.build.tier3")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier1.saturated_production,
|
||||
Tier3.sunblot_expansion,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.6
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
big_and_little = {
|
||||
name = "Sunblot: Big and Little",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergNathrokor] = 2,
|
||||
[UnitId.ZergMutalisk] = 2,
|
||||
[UnitId.ZergGorgrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergVilgorokor] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.big_and_little,
|
||||
Tier1.big_and_little,
|
||||
Tier2.big_little_iroliris_buildup_caphrolosk_hachirosk,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
the_triad = {
|
||||
name = "Sunblot: The Triad",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergNathrokor] = 2,
|
||||
[UnitId.ZergGorgrokor] = 2,
|
||||
[UnitId.ZergKalkalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergIsthrathaleth] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.the_triad,
|
||||
Tier1.the_triad,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
skittering_duo = {
|
||||
name = "Sunblot: Skittering Duo",
|
||||
unit_composition = {
|
||||
-- signature units (Skibact Scab)
|
||||
[UnitId.ZergSkithrokor] = 2,
|
||||
[UnitId.ZergBactalisk] = 2,
|
||||
[UnitId.ZergNathrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergGorgrokor] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.skittering_duo,
|
||||
Tier1.skittering_duo,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
early_birds = {
|
||||
name = "Sunblot: Early Birds",
|
||||
unit_composition = {
|
||||
-- signature units (Alkag Iteth)
|
||||
[UnitId.ZergKagralisk] = 2,
|
||||
[UnitId.ZergEvigrilisk] = 2,
|
||||
[UnitId.ZergAlmaksalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergGorgrokor] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.early_birds,
|
||||
Tier1.early_birds,
|
||||
Tier2.birds_iroliris_alkag,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
flying_feint = {
|
||||
name = "Sunblot: Flying Feint",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergNathrokor] = 2,
|
||||
[UnitId.ZergSkithrokor] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergGorgrokor] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.flying_feint,
|
||||
Tier1.flying_feint,
|
||||
Tier2.feint_iroliris_buildup_vornath_hydrith_skibact,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
descending_horizon = {
|
||||
name = "Sunblot: Descending Horizon",
|
||||
unit_composition = {
|
||||
-- signature units (Skibact Scab)
|
||||
[UnitId.ZergSkithrokor] = 2,
|
||||
[UnitId.ZergBactalisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergGorgrokor] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergGeszithalor] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.descending_horizon,
|
||||
Tier2.horizon_iroliris_buildup,
|
||||
Tier3.horizon_othstol,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
185
mpq/lua/melee/zerg/swarm.lua
Normal file
185
mpq/lua/melee/zerg/swarm.lua
Normal file
@ -0,0 +1,185 @@
|
||||
local Basic = require("melee.zerg.build.basic")
|
||||
local Openers = require("melee.zerg.build.openers")
|
||||
local Tier1 = require("melee.zerg.build.tier1")
|
||||
local Tier2 = require("melee.zerg.build.tier2")
|
||||
local Tier3 = require("melee.zerg.build.tier3")
|
||||
|
||||
local expansion_build_order = {
|
||||
Basic.build_expansion,
|
||||
Tier1.saturated_production,
|
||||
Tier3.swarm_expansion,
|
||||
}
|
||||
local attack_wave_cost_bias = 0.4
|
||||
|
||||
return {
|
||||
---@type AIPersonality
|
||||
three_base_flood = {
|
||||
name = "Swarm: 3 Base Flood",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.three_base_flood,
|
||||
Tier1.three_base_flood,
|
||||
Tier2.flood_vornath_kalkiir_mutath_tosvrol_then_iroliris_caphrolosk_hachirosk,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
three_base_ultrav = {
|
||||
name = "Swarm: 3 Base Ultrav",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergUltrokor] = 3,
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergMutalisk] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.three_base_ultrav,
|
||||
Tier2.ultrav_iroliris_caphrolosk_buildup,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
instant_quazeth = {
|
||||
name = "Swarm: Instant Quazeth",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 3,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergQuazilisk] = 1,
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergNathrokor] = 1,
|
||||
[UnitId.ZergVorvrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.instant_quazeth,
|
||||
Tier1.instant_quazeth,
|
||||
Tier2.instant_iroliris_vornath_kalkiir,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
three_base_othstol = {
|
||||
name = "Swarm: 3 Base Othstol",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergIzirokor] = 2,
|
||||
[UnitId.ZergUltrokor] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergZoryusthaleth] = 1,
|
||||
[UnitId.ZergGorgrokor] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
[UnitId.ZergZobriolisk] = 1,
|
||||
[UnitId.ZergZarcavrokor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.three_base_othstol,
|
||||
Tier1.three_base_othstol,
|
||||
Tier2.othstol_iroliris_buildup,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
gates_of_hell = {
|
||||
name = "Swarm: Gates of Hell",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergKeskathalor] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergKalkalisk] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergGorgrokor] = 1,
|
||||
[UnitId.ZergSkithrokor] = 1,
|
||||
[UnitId.ZergBactalisk] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.gates_of_hell,
|
||||
Tier1.gates_of_hell,
|
||||
Tier2.gates_buildup_vornath_hachirosk_iroliris,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
|
||||
---@type AIPersonality
|
||||
primitive_pressure = {
|
||||
name = "Swarm: Primitive Pressure",
|
||||
unit_composition = {
|
||||
-- signature units
|
||||
[UnitId.ZergZethrokor] = 2,
|
||||
[UnitId.ZergHydralisk] = 2,
|
||||
[UnitId.ZergZoryusthaleth] = 2,
|
||||
-- filler units
|
||||
[UnitId.ZergLiiralisk] = 1,
|
||||
[UnitId.ZergProtathalor] = 1,
|
||||
[UnitId.ZergMatraleth] = 1,
|
||||
[UnitId.ZergSovroleth] = 1,
|
||||
[UnitId.ZergKeskathalor] = 1,
|
||||
},
|
||||
main_build_order = {
|
||||
Openers.primitive_pressure,
|
||||
Tier1.primitive_pressure,
|
||||
Tier2.pressure_iroliris_vornath_skibact_tethvith,
|
||||
Tier3.acquire,
|
||||
Tier1.saturated_production,
|
||||
},
|
||||
expansion_build_order = expansion_build_order,
|
||||
build_anti_ground_defenses = Basic.build_anti_ground,
|
||||
build_anti_air_defenses = Basic.build_anti_air,
|
||||
attack_wave_cost_bias = attack_wave_cost_bias,
|
||||
},
|
||||
}
|
||||
10
mpq/lua/start_melee_ai.lua
Normal file
10
mpq/lua/start_melee_ai.lua
Normal file
@ -0,0 +1,10 @@
|
||||
require "melee.melee_ai"
|
||||
|
||||
local player = Player()
|
||||
if player.type == PlayerType.Computer then
|
||||
if player.race == RaceId.Askosi then
|
||||
cprint(TextColor.Orange, "Player " .. player.name .. "(P" .. player.id .. "): Askosi AI is not supported!")
|
||||
return
|
||||
end
|
||||
MeleeAI():run()
|
||||
end
|
||||
Binary file not shown.
@ -10,6 +10,13 @@
|
||||
- **Triggers:**
|
||||
- New custom trigger subcommand for **set_unit_stat**
|
||||
- **transport_capacity** (b. Lucifirius) -- enables transporting via any unit, modifies transport capacity on any transport
|
||||
- **User-defined resource areas:** (c. DF)
|
||||
- Our methodology for user-defined resource areas has changed from the previous system!
|
||||
- **The location-based system has been removed.**
|
||||
- To use the new system:
|
||||
- Select the resource nodes you wish to assign to a specific resarea
|
||||
- Tick **burrowed** (bottom-left-most status flag) in the unit property panel
|
||||
- Set the **HP** field to the intended resarea id (a number between 1 and 255)
|
||||
|
||||
## Bugfixes
|
||||
- **Gameplay:**
|
||||
|
||||
BIN
plugins/gptp.qdp
BIN
plugins/gptp.qdp
Binary file not shown.
Loading…
Reference in New Issue
Block a user