189 lines
4.8 KiB
Lua
189 lines
4.8 KiB
Lua
--[[
|
|
Copyright (c) The OpenRA Developers and Contributors
|
|
This file is part of OpenRA, which is free software. It is made
|
|
available to you under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation, either version 3 of
|
|
the License, or (at your option) any later version. For more
|
|
information, see COPYING.
|
|
]]
|
|
|
|
AIPlayers = { }
|
|
AIBarracks = { }
|
|
AIDerricks = { }
|
|
AIBaseLocation = { }
|
|
IdlingAIActors = { }
|
|
IdlingAISupportActors = { }
|
|
AIOnDefense = { }
|
|
|
|
-- It's good to start with 10 rifle man, one medic and 5 rocket soldiers
|
|
InitialUnitsToBuild = { "e1", "e1", "e1", "e1", "e1", "medi", "e1", "e1", "e1", "e1", "e1", "e3", "e3", "e3", "e3", "e3" }
|
|
UnitsToBuild = { "e1", "e1", "e1", "e1", "e1", "e3", "e3", "e3", "medi" }
|
|
|
|
ActivateAI = function(player, id)
|
|
AIPlayers[id] = player
|
|
|
|
Trigger.AfterDelay(0, function()
|
|
local barracks = player.GetActorsByType("tent")
|
|
if #barracks > 0 then
|
|
AIBarracks[id] = barracks[1]
|
|
AIBaseLocation[id] = barracks[1].Location + CVec.New(2, 1)
|
|
IdlingAIActors[id] = { }
|
|
IdlingAISupportActors[id] = { }
|
|
InitialInfantryProduction(id, InitialUnitsToBuild)
|
|
DefendActor(id, barracks[1])
|
|
RepairBarracks(id)
|
|
SellWalls(id)
|
|
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() LookOutForCrates(id) end)
|
|
end
|
|
|
|
local derricks = player.GetActorsByType("oilb")
|
|
if #derricks > 0 then
|
|
AIDerricks[id] = derricks[1]
|
|
DefendActor(id, derricks[1])
|
|
end
|
|
end)
|
|
end
|
|
|
|
InitialInfantryProduction = function(id, units)
|
|
local productionComplete = AIPlayers[id].Build(units, function(actors)
|
|
ProduceInfantry(id)
|
|
end)
|
|
|
|
Trigger.OnProduction(AIBarracks[id], function(producer, produced)
|
|
BuildComplete(id, produced)
|
|
end)
|
|
end
|
|
|
|
ProduceInfantry = function(id)
|
|
local productionComplete = AIPlayers[id].Build({ Utils.Random(UnitsToBuild) }, function(actors)
|
|
Trigger.AfterDelay(0, function() ProduceInfantry(id) end)
|
|
end)
|
|
|
|
if not productionComplete then
|
|
Trigger.AfterDelay(0, function() ProduceInfantry(id) end)
|
|
end
|
|
end
|
|
|
|
BuildComplete = function(id, actor)
|
|
if actor.Type == "medi" then
|
|
local number = #IdlingAISupportActors[id] + 1
|
|
IdlingAISupportActors[id][number] = actor
|
|
|
|
Trigger.OnKilled(actor, function()
|
|
table.remove(IdlingAISupportActors[id], number)
|
|
end)
|
|
else
|
|
local number = #IdlingAIActors[id] + 1
|
|
IdlingAIActors[id][number] = actor
|
|
|
|
Trigger.OnKilled(actor, function()
|
|
table.remove(IdlingAIActors[id], number)
|
|
end)
|
|
end
|
|
|
|
Trigger.AfterDelay(0, function() DefendActor(id, actor) end)
|
|
end
|
|
|
|
AttackGroupSize = 5
|
|
SetupAttackGroup = function(id)
|
|
local units = { }
|
|
|
|
for i = 0, AttackGroupSize, 1 do
|
|
if (#IdlingAIActors[id] == 0) then
|
|
return units
|
|
end
|
|
|
|
local number = Utils.RandomInteger(0, #IdlingAIActors[id]) + 1
|
|
units[#units + 1] = IdlingAIActors[id][number]
|
|
table.remove(IdlingAIActors[id], number)
|
|
end
|
|
|
|
return units
|
|
end
|
|
|
|
DefendActor = function(id, actorToDefend)
|
|
if not actorToDefend or actorToDefend.IsDead or not actorToDefend.IsInWorld then
|
|
return
|
|
end
|
|
|
|
Trigger.OnDamaged(actorToDefend, function(self, attacker)
|
|
if AIOnDefense[id] or not attacker or attacker.IsDead then
|
|
return
|
|
end
|
|
|
|
-- Don't try to kill something you can't kill
|
|
if attacker.Type == "sniper.soviets" then
|
|
return
|
|
end
|
|
|
|
AIOnDefense[id] = true
|
|
local attackLoc = attacker.Location
|
|
|
|
local defenders = SetupAttackGroup(id)
|
|
if not defenders or #defenders == 0 then
|
|
Trigger.AfterDelay(DateTime.Seconds(30), function() AIOnDefense[id] = false end)
|
|
return
|
|
end
|
|
|
|
Utils.Do(defenders, function(unit)
|
|
if unit.IsDead then
|
|
return
|
|
end
|
|
|
|
unit.AttackMove(attackLoc)
|
|
|
|
local home = AIBaseLocation[id]
|
|
Trigger.OnIdle(unit, function()
|
|
if unit.Location == home then
|
|
IdlingAIActors[id][#IdlingAIActors[id] + 1] = unit
|
|
Trigger.Clear(unit, "OnIdle")
|
|
AIOnDefense[id] = false
|
|
else
|
|
unit.AttackMove(home)
|
|
end
|
|
end)
|
|
end)
|
|
end)
|
|
end
|
|
|
|
RepairBarracks = function(id)
|
|
Trigger.OnDamaged(AIBarracks[id], function(self, attacker)
|
|
self.StartBuildingRepairs(AIPlayers[id])
|
|
end)
|
|
end
|
|
|
|
SellWalls = function(id)
|
|
Media.DisplayMessage(UserInterface.Translate("lonestar-ai-sold-its-walls", { ["id"] = id }))
|
|
|
|
local walls = AIPlayers[id].GetActorsByType("brik")
|
|
Utils.Do(walls, function(wall)
|
|
wall.Sell()
|
|
end)
|
|
end
|
|
|
|
LookOutForCrates = function(id)
|
|
Trigger.OnEnteredProximityTrigger(AIBarracks[id].CenterPosition, WDist.New(12 * 1024), function(actor)
|
|
if actor.Type ~= "fortcrate" or #IdlingAIActors[id] == 0 then
|
|
return
|
|
end
|
|
|
|
local unit = Utils.Random(IdlingAIActors[id])
|
|
local home = AIBaseLocation[id]
|
|
local aim = actor.Location
|
|
if unit.IsDead then
|
|
return
|
|
end
|
|
|
|
unit.AttackMove(aim)
|
|
Trigger.OnIdle(unit, function()
|
|
if unit.Location == aim or not actor.IsInWorld then
|
|
unit.AttackMove(home)
|
|
Trigger.Clear(unit, "OnIdle")
|
|
else
|
|
unit.AttackMove(aim)
|
|
end
|
|
end)
|
|
end)
|
|
end
|