283 lines
9.2 KiB
Lua
283 lines
9.2 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.
|
|
]]
|
|
|
|
StartingCash = 15000
|
|
|
|
InfantryAttackPaths = { WaypointGroupBaseFrontal, WaypointGroupRightFlankInf, WaypointGroupVillageRight }
|
|
VehicleAttackPaths = { WaypointGroupBaseFrontal, WaypointGroupRightFlank, WaypointGroupVillageRight }
|
|
ArtyAttackPaths = { WaypointGroupBaseFrontal, ArtyWaypoints1, ArtyWaypoints2 }
|
|
|
|
InfantryProductionTypes = { "e1", "e3", "e3", "e3", "e4", "e4", "e4" }
|
|
VehicleProductionTypes = { "bggy", "ltnk" }
|
|
ArtyProductionType = { "arty" }
|
|
VehicleAutoProductionTypes = { "bggy", "bggy", "ltnk", "ltnk", "arty" }
|
|
HarvesterProductionType = { "harv" }
|
|
|
|
InfantryGroupSize = { hard = 8, normal = 6, easy = 4 }
|
|
InfantryAttackGroup = { }
|
|
InfantryProductionCooldown = { hard = DateTime.Seconds(40), normal = DateTime.Seconds(60), easy = DateTime.Seconds(80) }
|
|
|
|
VehicleGroupSize = { hard = 4, normal = 3, easy = 2 }
|
|
VehicleAttackGroup = { }
|
|
VehicleProductionCooldown = { hard = DateTime.Seconds(60), normal = DateTime.Seconds(90), easy = DateTime.Seconds(120) }
|
|
|
|
ArtyGroupSize = { hard = 2, normal = 1, easy = 1 }
|
|
ArtyAttackGroup = { }
|
|
ArtyProductionCooldown = { hard = DateTime.Seconds(60), normal = DateTime.Seconds(75), easy = DateTime.Seconds(100) }
|
|
|
|
NodBase = { handofnod, nodairfield, nodrefinery, nodradar, NodYard, nodpower1, nodpower2, nodpower3, nodpower4, nodpower5, gun1, gun2, gun3, gun4, nodsilo1, nodsilo2, nodsilo3}
|
|
|
|
BaseRadar = { type = "hq", pos = CPos.New(5, 6), cost = 1000 }
|
|
BaseRefinery = { type = "proc", pos = CPos.New(8, 7), cost = 1500 }
|
|
BaseSilo1 = { type = "silo", pos = CPos.New(6, 5), cost = 100 }
|
|
BaseSilo2 = { type = "silo", pos = CPos.New(8, 5), cost = 100 }
|
|
BaseSilo3 = { type = "silo", pos = CPos.New(10, 5), cost = 100 }
|
|
BaseGun1 = { type = "gun", pos = CPos.New( 7, 18), cost = 600 }
|
|
BaseGun2 = { type = "gun", pos = CPos.New( 11, 18), cost = 600 }
|
|
BaseGun3 = { type = "gun", pos = CPos.New( 45, 16), cost = 600 }
|
|
BaseGun4 = { type = "gun", pos = CPos.New( 50, 16), cost = 600 }
|
|
BaseNuke1 = { type = "nuke", pos = CPos.New( 13, 13), cost = 500 }
|
|
BaseNuke2 = { type = "nuke", pos = CPos.New( 50, 5), cost = 500 }
|
|
BaseNuke3 = { type = "nuke", pos = CPos.New( 5, 9), cost = 500 }
|
|
BaseNuke4 = { type = "nuke", pos = CPos.New( 52, 5), cost = 500 }
|
|
BaseNuke5 = { type = "nuke", pos = CPos.New( 48, 5), cost = 500 }
|
|
InfantryProduction = { type = "hand", pos = CPos.New(5, 12), cost = 500 }
|
|
VehicleProduction = { type = "afld", pos = CPos.New(52, 8), cost = 2000 }
|
|
|
|
BaseBuildings = { BaseRadar, BaseRefinery, BaseNuke1, BaseNuke2, BaseNuke3, BaseNuke4, BaseNuke5, InfantryProduction, VehicleProduction, BaseGun1, BaseGun2, BaseGun3, BaseGun4, BaseSilo1, BaseSilo2, BaseSilo3 }
|
|
|
|
BuildBuilding = function(building, cyard)
|
|
if CyardIsBuilding or Nod.Cash < building.cost then
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() BuildBuilding(building, cyard) end)
|
|
return
|
|
end
|
|
|
|
CyardIsBuilding = true
|
|
|
|
Nod.Cash = Nod.Cash - building.cost
|
|
Trigger.AfterDelay(Actor.BuildTime(building.type), function()
|
|
CyardIsBuilding = false
|
|
|
|
if cyard.IsDead or cyard.Owner ~= Nod then
|
|
Nod.Cash = Nod.Cash + building.cost
|
|
return
|
|
end
|
|
|
|
local actor = Actor.Create(building.type, true, { Owner = Nod, Location = building.pos })
|
|
|
|
if actor.Type == 'hand' or actor.Type == 'pyle' then
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(actor) end)
|
|
elseif actor.Type == 'afld' or actor.Type == 'weap' then
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(actor) end)
|
|
end
|
|
|
|
Trigger.OnKilled(actor, function()
|
|
BuildBuilding(building, cyard)
|
|
end)
|
|
|
|
RepairBuilding(GDI, actor, 0.75)
|
|
end)
|
|
end
|
|
|
|
CheckForHarvester = function()
|
|
local harv = Nod.GetActorsByType("harv")
|
|
return #harv > 0
|
|
end
|
|
|
|
ProduceHarvester = function(building)
|
|
if building.IsDead or building.Owner ~= Nod then
|
|
return
|
|
end
|
|
if not BuildingHarvester then
|
|
BuildingHarvester = true
|
|
building.Build(HarvesterProductionType, function()
|
|
BuildingHarvester = false
|
|
end)
|
|
end
|
|
end
|
|
|
|
ProduceInfantry = function(building)
|
|
if building.IsDead or building.Owner ~= Nod then
|
|
return
|
|
elseif not CheckForHarvester() then
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(building) end)
|
|
return
|
|
end
|
|
|
|
local delay = Utils.RandomInteger(DateTime.Seconds(3), DateTime.Seconds(9))
|
|
local toBuild = { Utils.Random(InfantryProductionTypes) }
|
|
local Path = Utils.Random(InfantryAttackPaths)
|
|
building.Build(toBuild, function(unit)
|
|
InfantryAttackGroup[#InfantryAttackGroup + 1] = unit[1]
|
|
|
|
if #InfantryAttackGroup >= InfantryGroupSize[Difficulty] then
|
|
MoveAndHunt(InfantryAttackGroup, Path)
|
|
InfantryAttackGroup = { }
|
|
Trigger.AfterDelay(InfantryProductionCooldown[Difficulty], function() ProduceInfantry(building) end)
|
|
else
|
|
Trigger.AfterDelay(delay, function() ProduceAutocreateInfantry(building) end)
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- We want every 2nd produced infantry to be free for the Auto attack teams
|
|
ProduceAutocreateInfantry = function(building)
|
|
if building.IsDead or building.Owner ~= Nod then
|
|
return
|
|
elseif not CheckForHarvester() then
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceInfantry(building) end)
|
|
return
|
|
end
|
|
|
|
local delay = Utils.RandomInteger(DateTime.Seconds(3), DateTime.Seconds(9))
|
|
local toBuild = { Utils.Random(InfantryProductionTypes) }
|
|
building.Build(toBuild, function(unit)
|
|
Trigger.AfterDelay(delay, function() ProduceInfantry(building) end)
|
|
end)
|
|
end
|
|
|
|
ProduceVehicle = function(building)
|
|
if building.IsDead or building.Owner ~= Nod then
|
|
return
|
|
elseif not CheckForHarvester() then
|
|
ProduceHarvester(building)
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(building) end)
|
|
return
|
|
end
|
|
|
|
local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17))
|
|
local toBuild = { Utils.Random(VehicleProductionTypes) }
|
|
local Path = Utils.Random(VehicleAttackPaths)
|
|
building.Build(toBuild, function(unit)
|
|
VehicleAttackGroup[#VehicleAttackGroup + 1] = unit[1]
|
|
|
|
if #VehicleAttackGroup >= VehicleGroupSize[Difficulty] then
|
|
MoveAndHunt(VehicleAttackGroup, Path)
|
|
VehicleAttackGroup = { }
|
|
Trigger.AfterDelay(VehicleProductionCooldown[Difficulty], function() ProduceArty(building) end)
|
|
else
|
|
Trigger.AfterDelay(delay, function() ProduceAutocreateVehicle(building) end)
|
|
end
|
|
end)
|
|
end
|
|
|
|
-- We want every 2nd produced vehicle to be free for the Auto attack teams
|
|
ProduceAutocreateVehicle = function(building)
|
|
if building.IsDead or building.Owner ~= Nod then
|
|
return
|
|
elseif not CheckForHarvester() then
|
|
ProduceHarvester(building)
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceVehicle(building) end)
|
|
return
|
|
end
|
|
|
|
local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17))
|
|
local toBuild = { Utils.Random(VehicleProductionTypes) }
|
|
building.Build(toBuild, function(unit)
|
|
Trigger.AfterDelay(delay, function() ProduceVehicle(building) end)
|
|
end)
|
|
end
|
|
|
|
ProduceArty = function(building)
|
|
if building.IsDead or building.Owner ~= Nod then
|
|
return
|
|
elseif not CheckForHarvester() then
|
|
ProduceHarvester(building)
|
|
Trigger.AfterDelay(DateTime.Seconds(10), function() ProduceArty(building) end)
|
|
return
|
|
end
|
|
|
|
local delay = Utils.RandomInteger(DateTime.Seconds(12), DateTime.Seconds(17))
|
|
local toBuild = { Utils.Random(ArtyProductionType) }
|
|
local Path = Utils.Random(ArtyAttackPaths)
|
|
building.Build(toBuild, function(unit)
|
|
ArtyAttackGroup[#ArtyAttackGroup + 1] = unit[1]
|
|
|
|
if #ArtyAttackGroup >= ArtyGroupSize[Difficulty] then
|
|
MoveAndHunt(ArtyAttackGroup, Path)
|
|
ArtyAttackGroup = { }
|
|
Trigger.AfterDelay(ArtyProductionCooldown[Difficulty], function() ProduceVehicle(building) end)
|
|
else
|
|
Trigger.AfterDelay(delay, function() ProduceArty(building) end)
|
|
end
|
|
end)
|
|
end
|
|
|
|
StartAI = function()
|
|
Nod.Cash = StartingCash
|
|
end
|
|
|
|
Trigger.OnAllKilledOrCaptured(NodBase, function()
|
|
Utils.Do(Nod.GetGroundAttackers(), IdleHunt)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodrefinery, function()
|
|
BuildBuilding(BaseRefinery, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodradar, function()
|
|
BuildBuilding(BaseRadar, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodpower1, function()
|
|
BuildBuilding(BaseNuke1, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodpower2, function()
|
|
BuildBuilding(BaseNuke2, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodpower3, function()
|
|
BuildBuilding(BaseNuke3, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodpower4, function()
|
|
BuildBuilding(BaseNuke4, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodpower5, function()
|
|
BuildBuilding(BaseNuke5, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(gun1, function()
|
|
BuildBuilding(BaseGun1, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(gun2, function()
|
|
BuildBuilding(BaseGun2, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(gun3, function()
|
|
BuildBuilding(BaseGun3, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(gun4, function()
|
|
BuildBuilding(BaseGun4, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodsilo1, function()
|
|
BuildBuilding(BaseSilo1, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodsilo2, function()
|
|
BuildBuilding(BaseSilo2, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodsilo3, function()
|
|
BuildBuilding(BaseSilo3, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(handofnod, function()
|
|
BuildBuilding(InfantryProduction, NodYard)
|
|
end)
|
|
|
|
Trigger.OnKilled(nodairfield, function()
|
|
BuildBuilding(VehicleProduction, NodYard)
|
|
end)
|