From 3294415e8ec3d5928f01bc3e4eed3cd493b6fc9d Mon Sep 17 00:00:00 2001 From: abcdefg30 Date: Sun, 3 Apr 2016 01:55:11 +0200 Subject: [PATCH] Add an "Lonestar AI" to Fort Lonestar --- OpenRA.sln | 1 + .../maps/fort-lonestar/fort-lonestar-AI.lua | 180 ++++++++++++++++++ mods/ra/maps/fort-lonestar/fort-lonestar.lua | 6 +- mods/ra/maps/fort-lonestar/map.yaml | 4 - mods/ra/maps/fort-lonestar/rules.yaml | 8 +- 5 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 mods/ra/maps/fort-lonestar/fort-lonestar-AI.lua diff --git a/OpenRA.sln b/OpenRA.sln index a1e627ecd7..62649d2044 100644 --- a/OpenRA.sln +++ b/OpenRA.sln @@ -82,6 +82,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Red Alert Lua scripts", "Re mods\ra\maps\soviet-07\soviet07.lua = mods\ra\maps\soviet-07\soviet07.lua mods\ra\maps\survival01\survival01.lua = mods\ra\maps\survival01\survival01.lua mods\ra\maps\survival02\survival02.lua = mods\ra\maps\survival02\survival02.lua + mods\ra\maps\fort-lonestar\fort-lonestar-AI.lua = mods\ra\maps\fort-lonestar\fort-lonestar-AI.lua EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dune 2000 Lua scripts", "Dune 2000 Lua scripts", "{06B1AE07-DDB0-4287-8700-A8CD9A0E652E}" diff --git a/mods/ra/maps/fort-lonestar/fort-lonestar-AI.lua b/mods/ra/maps/fort-lonestar/fort-lonestar-AI.lua new file mode 100644 index 0000000000..ce39e1623f --- /dev/null +++ b/mods/ra/maps/fort-lonestar/fort-lonestar-AI.lua @@ -0,0 +1,180 @@ + +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) + InfantryProduction(id) + end) + + Trigger.OnProduction(AIBarracks[id], function(producer, produced) + BuildComplete(id, produced) + end) +end + +InfantryProduction = function(id) + local productionComplete = AIPlayers[id].Build({ Utils.Random(UnitsToBuild) }, function(actors) + Trigger.AfterDelay(0, function() InfantryProduction(id) end) + end) + + if not productionComplete then + Trigger.AfterDelay(0, function() InfantryProduction(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("Lonestar AI " .. id .. " sold its walls for better combat experience.") + + local walls = AIPlayers[id].GetActorsByType("brik") + Utils.Do(walls, function(wall) + wall.Destroy() + 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 diff --git a/mods/ra/maps/fort-lonestar/fort-lonestar.lua b/mods/ra/maps/fort-lonestar/fort-lonestar.lua index 0717c3d8e0..6c0ba9bfa0 100644 --- a/mods/ra/maps/fort-lonestar/fort-lonestar.lua +++ b/mods/ra/maps/fort-lonestar/fort-lonestar.lua @@ -197,9 +197,13 @@ end WorldLoaded = function() soviets = Player.GetPlayer("Soviets") players = { } - for i = 0, 4, 1 do + for i = 0, 4 do local player = Player.GetPlayer("Multi" ..i) players[i] = player + + if players[i] and players[i].IsBot then + ActivateAI(players[i], i) + end end Media.DisplayMessage("Defend Fort Lonestar at all costs!") diff --git a/mods/ra/maps/fort-lonestar/map.yaml b/mods/ra/maps/fort-lonestar/map.yaml index 442dca4c1b..fcdb8fa595 100644 --- a/mods/ra/maps/fort-lonestar/map.yaml +++ b/mods/ra/maps/fort-lonestar/map.yaml @@ -25,7 +25,6 @@ Players: PlayerReference@Multi0: Name: Multi0 Playable: True - AllowBots: False LockTeam: True Team: 1 LockFaction: True @@ -35,7 +34,6 @@ Players: PlayerReference@Multi1: Name: Multi1 Playable: True - AllowBots: False LockTeam: True Team: 1 LockFaction: True @@ -45,7 +43,6 @@ Players: PlayerReference@Multi2: Name: Multi2 Playable: True - AllowBots: False LockTeam: True Team: 1 LockFaction: True @@ -55,7 +52,6 @@ Players: PlayerReference@Multi3: Name: Multi3 Playable: True - AllowBots: False LockTeam: True Team: 1 LockFaction: True diff --git a/mods/ra/maps/fort-lonestar/rules.yaml b/mods/ra/maps/fort-lonestar/rules.yaml index c2717eb3ef..bc13d43edf 100644 --- a/mods/ra/maps/fort-lonestar/rules.yaml +++ b/mods/ra/maps/fort-lonestar/rules.yaml @@ -27,7 +27,7 @@ World: FlashPaletteEffect@LIGHTNINGSTRIKE: Type: LightningStrike LuaScript: - Scripts: fort-lonestar.lua + Scripts: fort-lonestar.lua, fort-lonestar-AI.lua ScriptUpgradesCache: Upgrades: invulnerability MapBuildRadius: @@ -86,6 +86,12 @@ Player: PlayerResources: DefaultCashLocked: True DefaultCash: 50 + -HackyAI@RushAI: + -HackyAI@NormalAI: + -HackyAI@NavalAI: + -HackyAI@TurtleAI: + DummyAI@LonestarAI: + Name: Lonestar AI ^Infantry: Inherits@IC: ^IronCurtainable