1--[[ 2 Copyright 2007-2020 The OpenRA Developers (see AUTHORS) 3 This file is part of OpenRA, which is free software. It is made 4 available to you under the terms of the GNU General Public License 5 as published by the Free Software Foundation, either version 3 of 6 the License, or (at your option) any later version. For more 7 information, see COPYING. 8]] 9 10AIPlayers = { } 11AIBarracks = { } 12AIDerricks = { } 13AIBaseLocation = { } 14IdlingAIActors = { } 15IdlingAISupportActors = { } 16AIOnDefense = { } 17 18-- It's good to start with 10 rifle man, one medic and 5 rocket soldiers 19InitialUnitsToBuild = { "e1", "e1", "e1", "e1", "e1", "medi", "e1", "e1", "e1", "e1", "e1", "e3", "e3", "e3", "e3", "e3" } 20UnitsToBuild = { "e1", "e1", "e1", "e1", "e1", "e3", "e3", "e3", "medi" } 21 22ActivateAI = function(player, id) 23 AIPlayers[id] = player 24 25 Trigger.AfterDelay(0, function() 26 local barracks = player.GetActorsByType("tent") 27 if #barracks > 0 then 28 AIBarracks[id] = barracks[1] 29 AIBaseLocation[id] = barracks[1].Location + CVec.New(2, 1) 30 IdlingAIActors[id] = { } 31 IdlingAISupportActors[id] = { } 32 InitialInfantryProduction(id, InitialUnitsToBuild) 33 DefendActor(id, barracks[1]) 34 RepairBarracks(id) 35 SellWalls(id) 36 37 Trigger.AfterDelay(DateTime.Seconds(10), function() LookOutForCrates(id) end) 38 end 39 40 local derricks = player.GetActorsByType("oilb") 41 if #derricks > 0 then 42 AIDerricks[id] = derricks[1] 43 DefendActor(id, derricks[1]) 44 end 45 end) 46end 47 48InitialInfantryProduction = function(id, units) 49 local productionComplete = AIPlayers[id].Build(units, function(actors) 50 InfantryProduction(id) 51 end) 52 53 Trigger.OnProduction(AIBarracks[id], function(producer, produced) 54 BuildComplete(id, produced) 55 end) 56end 57 58InfantryProduction = function(id) 59 local productionComplete = AIPlayers[id].Build({ Utils.Random(UnitsToBuild) }, function(actors) 60 Trigger.AfterDelay(0, function() InfantryProduction(id) end) 61 end) 62 63 if not productionComplete then 64 Trigger.AfterDelay(0, function() InfantryProduction(id) end) 65 end 66end 67 68BuildComplete = function(id, actor) 69 if actor.Type == "medi" then 70 local number = #IdlingAISupportActors[id] + 1 71 IdlingAISupportActors[id][number] = actor 72 73 Trigger.OnKilled(actor, function() 74 table.remove(IdlingAISupportActors[id], number) 75 end) 76 else 77 local number = #IdlingAIActors[id] + 1 78 IdlingAIActors[id][number] = actor 79 80 Trigger.OnKilled(actor, function() 81 table.remove(IdlingAIActors[id], number) 82 end) 83 end 84 85 Trigger.AfterDelay(0, function() DefendActor(id, actor) end) 86end 87 88AttackGroupSize = 5 89SetupAttackGroup = function(id) 90 local units = { } 91 92 for i = 0, AttackGroupSize, 1 do 93 if (#IdlingAIActors[id] == 0) then 94 return units 95 end 96 97 local number = Utils.RandomInteger(0, #IdlingAIActors[id]) + 1 98 units[#units + 1] = IdlingAIActors[id][number] 99 table.remove(IdlingAIActors[id], number) 100 end 101 102 return units 103end 104 105DefendActor = function(id, actorToDefend) 106 if not actorToDefend or actorToDefend.IsDead or not actorToDefend.IsInWorld then 107 return 108 end 109 110 Trigger.OnDamaged(actorToDefend, function(self, attacker) 111 if AIOnDefense[id] or not attacker or attacker.IsDead then 112 return 113 end 114 115 -- Don't try to kill something you can't kill 116 if attacker.Type == "sniper.soviets" then 117 return 118 end 119 120 AIOnDefense[id] = true 121 local attackLoc = attacker.Location 122 123 local defenders = SetupAttackGroup(id) 124 if not defenders or #defenders == 0 then 125 Trigger.AfterDelay(DateTime.Seconds(30), function() AIOnDefense[id] = false end) 126 return 127 end 128 129 Utils.Do(defenders, function(unit) 130 if unit.IsDead then 131 return 132 end 133 134 unit.AttackMove(attackLoc) 135 136 local home = AIBaseLocation[id] 137 Trigger.OnIdle(unit, function() 138 if unit.Location == home then 139 IdlingAIActors[id][#IdlingAIActors[id] + 1] = unit 140 Trigger.Clear(unit, "OnIdle") 141 AIOnDefense[id] = false 142 else 143 unit.AttackMove(home) 144 end 145 end) 146 end) 147 end) 148end 149 150RepairBarracks = function(id) 151 Trigger.OnDamaged(AIBarracks[id], function(self, attacker) 152 self.StartBuildingRepairs(AIPlayers[id]) 153 end) 154end 155 156SellWalls = function(id) 157 Media.DisplayMessage("Lonestar AI " .. id .. " sold its walls for better combat experience.") 158 159 local walls = AIPlayers[id].GetActorsByType("brik") 160 Utils.Do(walls, function(wall) 161 wall.Sell() 162 end) 163end 164 165LookOutForCrates = function(id) 166 Trigger.OnEnteredProximityTrigger(AIBarracks[id].CenterPosition, WDist.New(12 * 1024), function(actor) 167 if actor.Type ~= "fortcrate" or #IdlingAIActors[id] == 0 then 168 return 169 end 170 171 local unit = Utils.Random(IdlingAIActors[id]) 172 local home = AIBaseLocation[id] 173 local aim = actor.Location 174 if unit.IsDead then 175 return 176 end 177 178 unit.AttackMove(aim) 179 Trigger.OnIdle(unit, function() 180 if unit.Location == aim or not actor.IsInWorld then 181 unit.AttackMove(home) 182 Trigger.Clear(unit, "OnIdle") 183 else 184 unit.AttackMove(aim) 185 end 186 end) 187 end) 188end 189