-- Collection of functions for governing AI unit production -- ------------------------------------------------------------------------------------ ------ Unit production activation by factory creation function SetupProductionBuilding (actor, tab) if bdebug then UserInterface.SetMissionText("SetupProductionBuilding() called at tick "..missiontick, MissionPlayer.Color) end if actor.Type == "fact" then return end local productiontypes = MakeProductionTypes(actor.Type, actor.Owner, tab) table.insert(ActiveProductionTable, {factory = actor, types = productiontypes, curr_production = "", progress = 0} ) local newfactory = #ActiveProductionTable SetupFactories(newfactory) UnitProduction(ActiveProductionTable[newfactory], tab) end ------------------------------------------------------------------------------------ ------ Factory setup for passing units to AI control function SetupFactories (i) -- i: index number in ActiveProductionTable, or 0 to activate all. Use 0 only in the beginning! if bdebug then UserInterface.SetMissionText("SetupFactories() called at tick "..missiontick, MissionPlayer.Color) end if i == 0 then Utils.Do(ActiveProductionTable, function(apt) local fty = apt.factory if fty.Type == "fact" then return end --different handling for Construction Yards if not fty.IsDead then Trigger.OnProduction(fty, function(_, a) AddActorToRegistry(a) AddActorToPool(a) end) end end) else local fty = ActiveProductionTable[i].factory if not fty.IsDead then Trigger.OnProduction(fty, function(_, a) AddActorToRegistry(a) AddActorToPool(a) end) end end end ------------------------------------------------------------------------------------ ------ Populate list from MasterTable function MakeProductionTypes (t, s, tab) -- t = factory type, s = owner/side if bdebug then UserInterface.SetMissionText("MakeProductionTypes() called at tick "..missiontick, MissionPlayer.Color) end local ProduceList = { } str = "" Utils.Do(MasterTable.Production[tab], function(mu) Utils.Do(mu.side, function(ms) --Media.Debug("checking type "..mu.type.." for "..t.." "..mu.factory..", "..s.Name.." "..ms..","..mu.weight) if mu.factory == t and ms == s.Name and mu.weight > 0 then table.insert(ProduceList, mu) str = str .." ".. GetName(mu.type) .."x"..mu.weight end end) end) if s ~= "allies" and s ~= "soviet" then Utils.Do(MasterTable.Production[tab], function(mu) Utils.Do(mu.side, function(ms) --Media.Debug("checking type "..mu.type.." for "..t.." "..mu.factory..", "..s.Faction.." "..ms..","..mu.weight) if mu.factory == t and ms == s.Faction and mu.weight > 0 then table.insert(ProduceList, mu) str = str .." ".. GetName(mu.type) .."x"..mu.weight end end) end) end Media.Debug("ActiveProductionTable created for "..s.Name.." "..GetName(t)..": ".. str) return ProduceList end ------------------------------------------------------------------------------------ ------ Cyclic unit production function UnitProduction (productiontable, tab) if bdebug then UserInterface.SetMissionText("UnitProduction() called at tick "..missiontick, MissionPlayer.Color) end local factory = productiontable.factory if factory.Type == "fact" then return end --different handling for Construction Yards if (not factory.IsDead) and #productiontable.types > 0 then --local numproc = 0 --local harvlist = { } -- Check for harvesters --Utils.Do(ExistingBuildings, function(a) -- if a.Owner == factory.Owner and a.Type == "proc" then numproc = numproc + 2 end --was 1 --end) --if numproc > 0 then -- harvlist = factory.Owner.GetActorsByType("harv") --end AIHarvestersPerRefinery = AIHarvestersPerRefinery or 1 local numproc = FindOwnedActorType(factory.Owner, "proc") local numharv = #factory.Owner.GetActorsByType("harv") --FindOwnedActorType(factory.Owner, "harv") -- Build Harvester override local validunitList = { } if numharv < numproc * AIHarvestersPerRefinery and factory.Type == "weap" then validunitList = { { type = "harv", factory = "weap", side = { factory.Owner.Name } } } else if factory.Owner.Cash + factory.Owner.Resources > AIEmergencyCashThreshold then local aifilllist = { } -- check AITeam lists to fill --Media.Debug(GetName(factory.Type).." test to ".. factory.Owner.Name .." "..tablelength(AIGroupToFillStatus).." "..type(AIGroupToFillStatus)) if type(AIGroupToFillStatus) == "table" and AIGroupToFillStatus[factory.Owner.Name] ~= nil then Utils.Do(AIGroupToFillStatus[factory.Owner.Name], function(actornamegroup) Utils.Do(actornamegroup, function(actortype) Utils.Do(productiontable.types, function(tt) if actortype == tt.type then table.insert(aifilllist, tt) end end) end) end) end Media.Debug(GetName(factory.Type).." belonging to ".. factory.Owner.Name .." can choose from "..#aifilllist) if #aifilllist == 0 then if factory.Owner.Cash + factory.Owner.Resources > AILowCashThreshold then aifilllist = productiontable.types end end -- Check prereqs Utils.Do(aifilllist, function(tt) if CheckPrerequisites(factory.Owner, tt.prereq) then for i = 1, tt.weight do validunitList[#validunitList + 1] = tt end end end) end end if #validunitList > 0 then local actorproduced = validunitList[Utils.RandomInteger(1, #validunitList + 1)] local unitType = actorproduced.type Media.Debug(GetName(factory.Type).." belonging to ".. factory.Owner.Name .." decided to build: ".. GetName(unitType)) -- apply multipliers if actorproduced.buildtime == nil then actorproduced.buildtime = Actor.BuildTime(actorproduced.type) end if actorproduced.cost == nil then actorproduced.cost = Actor.Cost(actorproduced.type) end local buildtime = actorproduced.buildtime * GetBuildTimeMultiplier(factory.Owner, actorproduced.tab) * Utils.Random({0.98,0.99,1,1.01,1.02}) local cost = actorproduced.cost * GetCostMultiplier(factory.Owner, actorproduced.tab) BuildActor(actorproduced, factory.Owner, factory, productiontable, tab, buildtime, cost) return end end -- periodic recheck Trigger.AfterDelay(Utils.RandomInteger(200, 1250), function() UnitProduction(productiontable, tab) end) end ------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------ ------ AI unit evaluation to set unit priority (To be implemented)