diff --git a/mods/common/lua/actor.lua b/mods/common/lua/actor.lua index c8acc1dd06..8f17d9c21b 100644 --- a/mods/common/lua/actor.lua +++ b/mods/common/lua/actor.lua @@ -150,6 +150,13 @@ Actor.SetStance = function(actor, stance) Internal.SetUnitStance(actor, stance) end +Actor.RepairBuilding = function(actor) + local rb = Actor.TraitOrDefault(actor, "RepairableBuilding") + if rb ~= nil and rb.Repairer == nil then + rb:RepairBuilding(actor, Actor.Owner(actor)) + end +end + Actor.OnDamaged = function(actor, eh) Actor.Trait(actor, "LuaScriptEvents").OnDamaged:Add(eh) end @@ -207,19 +214,23 @@ Actor.Guard = function(actor, target) end Actor.Patrol = function(actor, waypoints, wait, loop) - Utils.Do(waypoints, function(wpt) - Actor.AttackMove(actor, wpt.Location, 3) - Actor.Wait(actor, wait or 0) - end) - if loop or loop == nil then - Actor.CallFunc(actor, function() Actor.Patrol(actor, waypoints, wait, loop) end) + if not Actor.IsDead(actor) then + Utils.Do(waypoints, function(wpt) + Actor.AttackMove(actor, wpt.Location, 3) + Actor.Wait(actor, wait or 0) + end) + if loop or loop == nil then + Actor.CallFunc(actor, function() Actor.Patrol(actor, waypoints, wait, loop) end) + end end end Actor.PatrolUntil = function(actor, waypoints, wait, func) if func == nil then error("No function specified", 2) end - Actor.Patrol(actor, waypoints, wait, false) - if not func(actor) then - Actor.CallFunc(actor, function() Actor.PatrolUntil(actor, waypoints, wait, func) end) + if not Actor.IsDead(actor) then + Actor.Patrol(actor, waypoints, wait, false) + if not func(actor) then + Actor.CallFunc(actor, function() Actor.PatrolUntil(actor, waypoints, wait, func) end) + end end end diff --git a/mods/common/lua/production.lua b/mods/common/lua/production.lua index d03b129ef0..04d2fdfd75 100644 --- a/mods/common/lua/production.lua +++ b/mods/common/lua/production.lua @@ -1,4 +1,5 @@ Production = { } +Production.EventHandlers = { } Production.BuildWithSharedQueue = function(player, unit, amount) Internal.BuildWithSharedQueue(player, unit, amount or 1) @@ -8,6 +9,17 @@ Production.BuildWithPerFactoryQueue = function(factory, unit, amount) Internal.BuildWithPerFactoryQueue(factory, unit, amount or 1) end +Production.Build = function(factory, unit, amount) + if Actor.HasTrait(factory, "ProductionQueue") then + Production.BuildWithPerFactoryQueue(factory, unit, amount) + elseif Actor.HasTrait(factory, "Production") then + Production.SetPrimaryBuilding(factory) + Production.BuildWithSharedQueue(Actor.Owner(factory), unit, amount) + else + error("Production.Build: not a factory") + end +end + Production.SharedQueueIsBusy = function(player, category) return Internal.SharedQueueIsBusy(player, category) end @@ -17,9 +29,66 @@ Production.PerFactoryQueueIsBusy = function(factory) end Production.SetRallyPoint = function(factory, location) - Actor.Trait(factory, "RallyPoint").rallyPoint = location.Location + local srp = Actor.Trait(factory, "RallyPoint") + if srp ~= nil then + srp.rallyPoint = location.Location + end end Production.SetPrimaryBuilding = function(factory) - Actor.Trait(factory, "PrimaryBuilding"):SetPrimaryProducer(factory, true) + local pb = Actor.TraitOrDefault(factory, "PrimaryBuilding") + if pb ~= nil then + pb:SetPrimaryProducer(factory, true) + end +end + +Production.BuildTeamFromTemplate = function(player, template, func) + local factories = { } + Utils.Do(template, function(t) table.insert(factories, t[1]) end) + + if Utils.Any(factories, Actor.IsDead) then + return + end + + if Utils.Any(factories, function(fact) return Production.EventHandlers[fact] end) then + OpenRA.RunAfterDelay(Utils.Seconds(10), function() Production.BuildTeamFromTemplate(player, template, func) end) + return + end + + local team = Team.New({ }) + local teamSize = 0 + Utils.Do(template, function(t) teamSize = teamSize + #t[2] end) + + local eventHandler = function(unit) + Team.Add(team, unit) + + if #team.Actors >= teamSize then + func(team) + Utils.Do(factories, function(factory) + Production.EventHandlers[factory] = nil + end) + end + end + + Utils.Do(factories, function(factory) + Production.EventHandlers[factory] = eventHandler + end) + + Utils.Do(template, function(t) + Utils.Do(t[2], function(unit) + Production.Build(t[1], unit) + end) + end) +end + +Production.EventHandlers.Setup = function(player) + Utils.Do(Actor.ActorsWithTrait("Production"), function(factory) + if Actor.Owner(factory) == player then + Actor.OnProduced(factory, function(fact, unit) + if Production.EventHandlers[fact] then + Production.EventHandlers[fact](unit) + end + end) + end + end) end diff --git a/mods/common/lua/team.lua b/mods/common/lua/team.lua index f0f9da15c8..909b430137 100644 --- a/mods/common/lua/team.lua +++ b/mods/common/lua/team.lua @@ -7,22 +7,24 @@ Team.New = function(actors) team.OnAnyKilled = { } team.OnAllRemovedFromWorld = { } team.OnAnyRemovedFromWorld = { } - Team.AddActorEventHandlers(team) + Team.Do(team, function(actor) Team.AddActorEventHandlers(team, actor) end) return team end -Team.AddActorEventHandlers = function(team) - Team.Do(team, function(actor) +Team.Add = function(team, actor) + table.insert(team.Actors, actor) + Team.AddActorEventHandlers(team, actor) +end - Actor.OnKilled(actor, function() - Team.InvokeHandlers(team.OnAnyKilled) - if Team.AllAreDead(team) then Team.InvokeHandlers(team.OnAllKilled) end - end) +Team.AddActorEventHandlers = function(team, actor) + Actor.OnKilled(actor, function() + Team.InvokeHandlers(team.OnAnyKilled) + if Team.AllAreDead(team) then Team.InvokeHandlers(team.OnAllKilled) end + end) - Actor.OnRemovedFromWorld(actor, function() - Team.InvokeHandlers(team.OnAnyRemovedFromWorld) - if not Team.AnyAreInWorld(team) then Team.InvokeHandlers(team.OnAllRemovedFromWorld) end - end) + Actor.OnRemovedFromWorld(actor, function() + Team.InvokeHandlers(team.OnAnyRemovedFromWorld) + if not Team.AnyAreInWorld(team) then Team.InvokeHandlers(team.OnAllRemovedFromWorld) end end) end