Rework D2k campaign scripts:
- Add InitialProductionDelay - Different attacksDelays for early game and late game - Adjust T3 unit production for selected missions - Implement InitialAttackDelay, TimeBetweenAttacks - Implement routines for idle units - Emergency mode - Airstrike rework
This commit is contained in:
@@ -76,6 +76,7 @@ smuggler-leader = Smuggler Leader.
|
||||
were-warned-will-pay = You were warned. Now you will pay.
|
||||
destroy-smugglers-mercenaries = Destroy the Smugglers and their mercenaries.
|
||||
capture-harkonnen-barracks-release-hostages = Capture the Harkonnen barracks to release the hostages.
|
||||
use-engineer-hint = Use engineers to reclaim destroyed vehicles.
|
||||
|
||||
## harkonnen-01ab, harkonnen-03ab
|
||||
eliminate-atreides-units-reinforcements = Eliminate all Atreides forces and reinforcements in the area.
|
||||
@@ -112,6 +113,8 @@ destroy-ordos = Destroy the Ordos.
|
||||
## harkonnen-06ab
|
||||
ixian-transports-detected = Ixian transports detected.
|
||||
capture-destroy-ordos-starport = Capture or destroy the Ordos Starport.
|
||||
smuggler-warning-harkonnen = Mind your own business Harkonnen.
|
||||
smuggler-warning-ordos = Mind your own business Ordos.
|
||||
|
||||
## harkonnen-06ab, harkonnen-09ab
|
||||
smugglers-now-hostile = The Smugglers are now hostile!
|
||||
@@ -132,6 +135,8 @@ atreides-commander = Atreides Commander
|
||||
|
||||
## harkonnen-09ab
|
||||
build-deploy-mcv = Build and deploy an MCV to establish a Construction Yard.
|
||||
husk-reclaimed-harkonnen = We reclaimed some Atreides wreckage from battle.
|
||||
engineers-hint = Our engineers maybe find then useful.
|
||||
|
||||
## ordos-01ab, ordos-02ab, ordos-03ab, ordos-04, ordos-05
|
||||
outpost-not-captured-destroyed = Do not let the Outpost be captured or destroyed.
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -25,10 +25,13 @@ HarkonnenInfantryTypes = { "light_inf" }
|
||||
|
||||
ActivateAI = function()
|
||||
IdlingUnits[Harkonnen] = { }
|
||||
Defending[Harkonnen] = { }
|
||||
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
|
||||
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local toBuild = function() return HarkonnenInfantryTypes end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end
|
||||
|
||||
@@ -168,6 +168,13 @@ Actors:
|
||||
HarkonnenRally4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 30,28
|
||||
Actor5: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 18,18
|
||||
Actor25: crate
|
||||
Owner: Neutral
|
||||
Location: 42,39
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -25,10 +25,14 @@ HarkonnenInfantryTypes = { "light_inf" }
|
||||
|
||||
ActivateAI = function()
|
||||
IdlingUnits[Harkonnen] = { }
|
||||
Defending[Harkonnen] = {}
|
||||
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
|
||||
LastHarvesterEaten[Harkonnen] = true
|
||||
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local toBuild = function() return HarkonnenInfantryTypes end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end
|
||||
|
||||
@@ -138,6 +138,9 @@ Actors:
|
||||
HarkonnenRally4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 30,28
|
||||
Actor4: crate
|
||||
Owner: Neutral
|
||||
Location: 12,21
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ AttackGroupSize =
|
||||
normal = 8,
|
||||
hard = 10
|
||||
}
|
||||
AttackDelays =
|
||||
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -33,13 +34,16 @@ InitAIUnits = function()
|
||||
end
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Ordos] = { }
|
||||
AttackDelay[Ordos] = 12000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Ordos] = 5000 * DifficultyModifier[Difficulty]
|
||||
LastHarvesterEaten[Ordos] = true
|
||||
Trigger.AfterDelay(0, InitAIUnits)
|
||||
|
||||
OConyard.Produce(AtreidesUpgrades[1])
|
||||
OConyard.Produce(AtreidesUpgrades[2])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
@@ -49,4 +53,22 @@ ActivateAI = function()
|
||||
ProduceUnits(Ordos, OBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Ordos, OLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
if Difficulty ~= "easy" then
|
||||
Ordos.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Ordos, function(p, building)
|
||||
table.insert(OrdosBase, building)
|
||||
DefendAndRepairBase(Ordos, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Ordos, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
@@ -143,7 +143,6 @@ WorldLoaded = function()
|
||||
end
|
||||
|
||||
Trigger.OnRemovedFromWorld(AConyard, function()
|
||||
|
||||
-- Mission already failed, no need to check the other conditions as well
|
||||
if checkResourceCapacity() then
|
||||
return
|
||||
|
||||
Binary file not shown.
@@ -135,6 +135,20 @@ Actors:
|
||||
OrdosRally2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 39,30
|
||||
Actor3: crate_explosion
|
||||
Owner: Neutral
|
||||
Location: 17,5
|
||||
Actor4: carryall.debris
|
||||
Owner: Neutral
|
||||
Facing: 384
|
||||
Location: 44,14
|
||||
Actor6: combat_tank_h.debris
|
||||
Facing: 384
|
||||
Location: 18,52
|
||||
Owner: Creeps
|
||||
Actor7: crate_explosion
|
||||
Owner: Neutral
|
||||
Location: 4,52
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,33 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 3000
|
||||
ExternalCondition@AI:
|
||||
Condition: base-rebuilder
|
||||
BaseBuilderBotModule@Ordos:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, barracks
|
||||
SiloTypes: silo
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
wind_trap: 4
|
||||
light_factory: 1
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -24,6 +24,10 @@ AttackDelays =
|
||||
OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
InitAIUnits = function()
|
||||
Defending[Ordos] = {}
|
||||
AttackDelay[Ordos] = 12000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Ordos] = 5000 * DifficultyModifier[Difficulty]
|
||||
DefencePerimeter[Ordos] = GetCellsInRectangle(CPos.New(9,6), CPos.New(20,27))
|
||||
IdlingUnits[Ordos] = Reinforcements.Reinforce(Ordos, InitialOrdosReinforcements, OrdosPaths[2])
|
||||
DefendAndRepairBase(Ordos, OrdosBase, 0.75, AttackGroupSize[Difficulty])
|
||||
end
|
||||
@@ -34,7 +38,7 @@ ActivateAI = function()
|
||||
|
||||
OConyard.Produce(AtreidesUpgrades[1])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local toBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
@@ -42,4 +46,29 @@ ActivateAI = function()
|
||||
Trigger.AfterDelay(DateTime.Seconds(14), function()
|
||||
ProduceUnits(Ordos, OBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
if Difficulty ~= "easy" then
|
||||
Ordos.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = toBuild,
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Ordos, function(p, building)
|
||||
table.insert(OrdosBase, building)
|
||||
DefendAndRepairBase(Ordos, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Ordos, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
Utils.Do(OrdosScouts, function(a)
|
||||
Trigger.OnKilled(a, function(self, killer)
|
||||
if not killer.IsDead then
|
||||
CheckArea(Ordos, killer.Location, 4)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
OrdosBase = { OBarracks, OWindTrap1, OWindTrap2, OOutpost, OConyard, ORefinery, OSilo }
|
||||
|
||||
OrdosScouts = { OScout1, OScout2, OScout3 }
|
||||
|
||||
OrdosReinforcements =
|
||||
{
|
||||
easy =
|
||||
@@ -143,7 +145,6 @@ WorldLoaded = function()
|
||||
end
|
||||
|
||||
Trigger.OnRemovedFromWorld(AConyard, function()
|
||||
|
||||
-- Mission already failed, no need to check the other conditions as well
|
||||
if checkResourceCapacity() then
|
||||
return
|
||||
@@ -176,4 +177,10 @@ WorldLoaded = function()
|
||||
Media.PlaySpeechNotification(Atreides, "Reinforce")
|
||||
Reinforcements.ReinforceWithTransport(Atreides, "carryall.reinforce", AtreidesReinforcements, AtreidesPath, { AtreidesPath[1] })
|
||||
end)
|
||||
|
||||
Trigger.OnDamaged(HarvesterDebris, function(self, attacker)
|
||||
if self.MaxHealth / 2 > self.Health then
|
||||
self.Deploy()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Binary file not shown.
@@ -48,24 +48,9 @@ Actors:
|
||||
Actor3: wormspawner
|
||||
Location: 27,14
|
||||
Owner: Creeps
|
||||
Actor8: light_inf
|
||||
Location: 48,24
|
||||
Owner: Ordos
|
||||
Actor9: light_inf
|
||||
Location: 19,34
|
||||
Owner: Ordos
|
||||
Actor10: light_inf
|
||||
Location: 35,34
|
||||
Owner: Ordos
|
||||
Actor11: trooper
|
||||
Location: 18,35
|
||||
Owner: Ordos
|
||||
Actor12: light_inf
|
||||
Location: 18,37
|
||||
Owner: Ordos
|
||||
Actor13: trooper
|
||||
Location: 19,39
|
||||
Owner: Ordos
|
||||
Actor14: light_inf
|
||||
Location: 34,50
|
||||
Owner: Ordos
|
||||
@@ -132,6 +117,33 @@ Actors:
|
||||
OrdosRally2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 15,34
|
||||
HarvesterDebris: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 50,12
|
||||
Actor0: combat_tank_a.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 22,37
|
||||
Actor1: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 25,10
|
||||
OScout1: light_inf
|
||||
Location: 48,24
|
||||
Owner: Ordos
|
||||
OScout2: light_inf
|
||||
Location: 35,34
|
||||
Owner: Ordos
|
||||
Actor13: trooper
|
||||
Location: 19,39
|
||||
Owner: Ordos
|
||||
Actor9: light_inf
|
||||
Location: 19,34
|
||||
Owner: Ordos
|
||||
OScout3: trooper
|
||||
Location: 18,35
|
||||
Owner: Ordos
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 3000
|
||||
ExternalCondition@AI:
|
||||
Condition: base-rebuilder
|
||||
BaseBuilderBotModule@Ordos:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
wind_trap: 2
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -26,22 +26,28 @@ HarkonnenTankType = { "combat_tank_h" }
|
||||
|
||||
-- Overwrite the template function because of the message
|
||||
SendAttack = function(owner, size)
|
||||
if Attacking[owner] then
|
||||
return
|
||||
end
|
||||
if Attacking[owner] then return end
|
||||
|
||||
Attacking[owner] = true
|
||||
HoldProduction[owner] = true
|
||||
|
||||
local units = SetupAttackGroup(owner, size)
|
||||
Utils.Do(units, IdleHunt)
|
||||
Utils.Do(units, Trigger.ClearAll)
|
||||
|
||||
if #units > 0 then
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("harkonnen-units-approaching"), UserInterface.GetFluentMessage("fremen-leader"))
|
||||
end
|
||||
|
||||
Trigger.OnAllRemovedFromWorld(units, function()
|
||||
Attacking[owner] = false
|
||||
HoldProduction[owner] = false
|
||||
Trigger.AfterDelay(1, function()
|
||||
Utils.Do(units, function(u)
|
||||
u.Stop()
|
||||
IdleHunt(u)
|
||||
end)
|
||||
|
||||
Trigger.OnAllRemovedFromWorld(units, function()
|
||||
Attacking[owner] = false
|
||||
HoldProduction[owner] = false
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -52,15 +58,34 @@ InitAIUnits = function()
|
||||
end
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Harkonnen] = {}
|
||||
HarvesterCount[Harkonnen] = 2
|
||||
AttackDelay[Harkonnen] = 9000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Harkonnen] = 9000 * DifficultyModifier[Difficulty]
|
||||
LastHarvesterEaten[Harkonnen] = true
|
||||
InitAIUnits()
|
||||
FremenProduction()
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end
|
||||
local tanksToBuild = function() return HarkonnenTankType end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
ProduceUnits(Harkonnen, HarkonnenBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Harkonnen, HarkonnenHeavyFact, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
|
||||
ActivateCrushLogic()
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
heavy_factory = tanksToBuild
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
|
||||
table.insert(HarkonnenBase, building)
|
||||
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -48,8 +48,8 @@ HarkonnenReinforcements =
|
||||
HarkonnenAttackDelay =
|
||||
{
|
||||
easy = DateTime.Minutes(3),
|
||||
normal = DateTime.Minutes(2) + DateTime.Seconds(20),
|
||||
hard = DateTime.Minutes(1)
|
||||
normal = DateTime.Minutes(2) + DateTime.Seconds(30),
|
||||
hard = DateTime.Minutes(2)
|
||||
}
|
||||
|
||||
HarkonnenAttackWaves =
|
||||
@@ -74,6 +74,7 @@ AtreidesReinforcements =
|
||||
{ "trike", "combat_tank_a", "combat_tank_a" },
|
||||
{ "quad", "combat_tank_a", "combat_tank_a" }
|
||||
}
|
||||
|
||||
AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location }
|
||||
|
||||
FremenInterval =
|
||||
@@ -85,9 +86,9 @@ FremenInterval =
|
||||
|
||||
IntegrityLevel =
|
||||
{
|
||||
easy = 50,
|
||||
normal = 75,
|
||||
hard = 100
|
||||
easy = 10,
|
||||
normal = 50,
|
||||
hard = 90
|
||||
}
|
||||
|
||||
FremenProduction = function()
|
||||
@@ -145,7 +146,7 @@ WorldLoaded = function()
|
||||
ProtectFremen = AddPrimaryObjective(Atreides, "protect-fremen-sietch")
|
||||
KillHarkonnen = AddPrimaryObjective(Atreides, "destroy-harkonnen")
|
||||
local keepSietchIntact = UserInterface.GetFluentMessage("keep-sietch-intact", { ["integrity"] = IntegrityLevel[Difficulty] })
|
||||
KeepIntegrity = AddPrimaryObjective(Atreides, keepSietchIntact)
|
||||
KeepIntegrity = AddSecondaryObjective(Atreides, keepSietchIntact)
|
||||
|
||||
Camera.Position = AConyard.CenterPosition
|
||||
HarkonnenAttackLocation = AConyard.Location
|
||||
@@ -164,6 +165,7 @@ WorldLoaded = function()
|
||||
UserInterface.SetMissionText(UserInterface.GetFluentMessage("sietch-destroyed"), Atreides.Color)
|
||||
Atreides.MarkFailedObjective(ProtectFremen)
|
||||
end)
|
||||
|
||||
Trigger.OnDamaged(Sietch, function()
|
||||
if AttackNotifier <= 0 then
|
||||
AttackNotifier = DateTime.Seconds(10)
|
||||
@@ -185,6 +187,7 @@ WorldLoaded = function()
|
||||
unit.AttackMove(HarkonnenAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
|
||||
SendCarryallReinforcements(Harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
|
||||
Actor.Create("upgrade.barracks", true, { Owner = Harkonnen })
|
||||
@@ -194,6 +197,7 @@ WorldLoaded = function()
|
||||
Media.PlaySpeechNotification(Atreides, "Reinforce")
|
||||
Reinforcements.Reinforce(Atreides, AtreidesReinforcements[1], AtreidesPath)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(40), function()
|
||||
Media.PlaySpeechNotification(Atreides, "Reinforce")
|
||||
Reinforcements.ReinforceWithTransport(Atreides, "carryall.reinforce", AtreidesReinforcements[2], AtreidesPath, { AtreidesPath[1] })
|
||||
|
||||
Binary file not shown.
@@ -413,7 +413,44 @@ Actors:
|
||||
Location: 5,23
|
||||
FremenRally: waypoint
|
||||
Owner: Neutral
|
||||
Location: 56,54
|
||||
Location: 56,56
|
||||
Actor27: combat_tank_h.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 58,50
|
||||
Actor33: frigate.debris
|
||||
Owner: Creeps
|
||||
Location: 33,28
|
||||
Actor34: crate
|
||||
Owner: Fremen
|
||||
Location: 39,57
|
||||
Actor36: crate
|
||||
Owner: Fremen
|
||||
Location: 38,57
|
||||
Actor53: crate
|
||||
Owner: Fremen
|
||||
Location: 37,57
|
||||
Actor54: crate
|
||||
Owner: Fremen
|
||||
Location: 37,56
|
||||
Actor57: crate
|
||||
Owner: Fremen
|
||||
Location: 38,56
|
||||
Actor59: crate
|
||||
Owner: Fremen
|
||||
Location: 39,56
|
||||
Actor62: combat_tank_a.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 14,45
|
||||
Actor8: combat_tank_h.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 51,57
|
||||
Actor63: combat_tank_a.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 31,48
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(5)
|
||||
|
||||
InitialProductionDelay = {
|
||||
HarkonnenMain =
|
||||
{
|
||||
easy = DateTime.Seconds(100),
|
||||
normal = DateTime.Seconds(60),
|
||||
hard = DateTime.Seconds(30)
|
||||
}
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,7 +25,14 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
EarlyProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(7), DateTime.Seconds(10) },
|
||||
normal = { DateTime.Seconds(5), DateTime.Seconds(7) },
|
||||
hard = { DateTime.Seconds(3), DateTime.Seconds(5) }
|
||||
}
|
||||
|
||||
LateProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -22,7 +40,9 @@ AttackDelays =
|
||||
}
|
||||
|
||||
HarkonnenInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
|
||||
|
||||
HarkonnenVehicleTypes = { "trike", "trike", "trike", "quad", "quad" }
|
||||
|
||||
HarkonnenTankType = { "combat_tank_h" }
|
||||
|
||||
InitAIUnits = function()
|
||||
@@ -49,7 +69,13 @@ ProduceInfantry = function()
|
||||
return
|
||||
end
|
||||
|
||||
local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1)
|
||||
local delay = 0
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
delay = Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
|
||||
else
|
||||
delay = Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
|
||||
local toBuild = { Utils.Random(HarkonnenInfantryTypes) }
|
||||
Harkonnen.Build(toBuild, function(unit)
|
||||
IdlingUnits[Harkonnen][#IdlingUnits[Harkonnen] + 1] = unit[1]
|
||||
@@ -63,15 +89,56 @@ end
|
||||
|
||||
ActivateAI = function()
|
||||
Harkonnen.Cash = 15000
|
||||
Defending[Harkonnen] = {}
|
||||
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
|
||||
HarvesterCount[Harkonnen] = 1
|
||||
PatrolPoints[Harkonnen] = { HPatrolPoint1.Location, HPatrolPoint2.Location,HPatrolPoint3.Location }
|
||||
DefencePerimeter[Harkonnen] = GetCellsInRectangle(CPos.New(13,13), CPos.New(36,25))
|
||||
LastHarvesterEaten[Harkonnen] = true
|
||||
InitAIUnits()
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
|
||||
else
|
||||
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local vehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
|
||||
local tanksToBuild = function() return HarkonnenTankType end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
ProduceInfantry()
|
||||
ProduceUnits(Harkonnen, HarkonnenLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Harkonnen, HarkonnenHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["HarkonnenMain"][Difficulty], function()
|
||||
ProduceInfantry()
|
||||
ProduceUnits(Harkonnen, HarkonnenLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Harkonnen, HarkonnenHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ActivateCrushLogic()
|
||||
|
||||
if Difficulty == "normal" then
|
||||
Harkonnen.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
Harkonnen.GrantCondition("defense-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuild
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
|
||||
table.insert(HarkonnenBase, building)
|
||||
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
]]
|
||||
|
||||
HarkonnenBase = { HarkonnenConstructionYard, HarkonnenWindTrap1, HarkonnenWindTrap2, HarkonnenWindTrap3, HarkonnenWindTrap4, HarkonnenWindTrap5, HarkonnenWindTrap6, HarkonnenWindTrap7, HarkonnenWindTrap8, HarkonnenSilo1, HarkonnenSilo2, HarkonnenSilo3, HarkonnenSilo4, HarkonnenGunTurret1, HarkonnenGunTurret2, HarkonnenGunTurret3, HarkonnenGunTurret4, HarkonnenGunTurret5, HarkonnenGunTurret6, HarkonnenGunTurret7, HarkonnenHeavyFactory, HarkonnenRefinery, HarkonnenOutpost, HarkonnenLightFactory }
|
||||
|
||||
SmugglerBase = { SmugglerWindTrap1, SmugglerWindTrap2 }
|
||||
|
||||
HarkonnenReinforcements =
|
||||
@@ -59,6 +60,7 @@ HarkonnenInfantryReinforcements =
|
||||
{ "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "light_inf", "trooper", "trooper", "trooper", "trooper", "trooper" }
|
||||
}
|
||||
}
|
||||
|
||||
InfantryPath = { HarkonnenEntry3.Location }
|
||||
|
||||
HarkonnenAttackDelay =
|
||||
@@ -139,13 +141,14 @@ HarkonnenPaths =
|
||||
}
|
||||
|
||||
AtreidesReinforcements = { "trike", "combat_tank_a" }
|
||||
|
||||
AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location }
|
||||
|
||||
ContrabandTimes =
|
||||
{
|
||||
easy = DateTime.Minutes(10),
|
||||
normal = DateTime.Minutes(5),
|
||||
hard = DateTime.Minutes(2) + DateTime.Seconds(30)
|
||||
normal = DateTime.Minutes(9),
|
||||
hard = DateTime.Minutes(8)
|
||||
}
|
||||
|
||||
Wave = 0
|
||||
@@ -310,6 +313,10 @@ WorldLoaded = function()
|
||||
Media.DisplayMessage(contrabandApproaching, Mentat)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(500, function()
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("use-engineer-hint"), Mentat)
|
||||
end)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(HarkonnenBase, function()
|
||||
Utils.Do(Harkonnen.GetGroundAttackers(), IdleHunt)
|
||||
end)
|
||||
@@ -330,6 +337,7 @@ WorldLoaded = function()
|
||||
Atreides.MarkFailedObjective(DefendStarport)
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnDamaged(Starport, function(_, attacker)
|
||||
if Starport.Owner ~= Smuggler or attacker.IsDead or attacker.Owner ~= Atreides then
|
||||
return
|
||||
@@ -347,6 +355,7 @@ WorldLoaded = function()
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnCapture(Starport, function()
|
||||
DefendStarport = AddSecondaryObjective(Atreides, "defend-captured-starport")
|
||||
|
||||
@@ -366,12 +375,14 @@ WorldLoaded = function()
|
||||
Trigger.OnKilled(HarkonnenBarracks, function()
|
||||
Atreides.MarkFailedObjective(CaptureBarracks)
|
||||
end)
|
||||
|
||||
Trigger.OnDamaged(HarkonnenBarracks, function()
|
||||
if AttackNotifier <= 0 and HarkonnenBarracks.Health < HarkonnenBarracks.MaxHealth * 3/4 then
|
||||
AttackNotifier = DateTime.Seconds(10)
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("do-not-destroy-barracks"), Mentat)
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnCapture(HarkonnenBarracks, function()
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("hostages-released"), Mentat)
|
||||
|
||||
@@ -400,7 +411,7 @@ WorldLoaded = function()
|
||||
if not Warned and a.Owner == Atreides and a.Type ~= "carryall" then
|
||||
Warned = true
|
||||
Trigger.RemoveFootprintTrigger(id)
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("stay-away-from-starport"), UserInterface.GetFluentMessage("smuggler-leader"))
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("stay-away-from-starport"), UserInterface.GetFluentMessage("smuggler-leader"), HSLColor.FromHex("9C8408"))
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -408,7 +419,7 @@ WorldLoaded = function()
|
||||
if not Paid and a.Owner == Atreides and a.Type ~= "carryall" then
|
||||
Paid = true
|
||||
Trigger.RemoveFootprintTrigger(id)
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("were-warned-will-pay"), UserInterface.GetFluentMessage("smuggler-leader"))
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("were-warned-will-pay"), UserInterface.GetFluentMessage("smuggler-leader"), HSLColor.FromHex("9C8408"))
|
||||
Utils.Do(Smuggler.GetGroundAttackers(), function(unit)
|
||||
unit.AttackMove(SmugglerWaypoint2.Location)
|
||||
end)
|
||||
@@ -427,4 +438,11 @@ WorldLoaded = function()
|
||||
StopInfantryProduction = true
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnEnteredProximityTrigger(Trigger1.CenterPosition, WDist.New(2 * 1024), function(a, id)
|
||||
if HarkonnenTankDebris1.IsInWorld and a.Owner == Atreides then
|
||||
HarkonnenTankDebris1.Deploy()
|
||||
Trigger.RemoveProximityTrigger(id)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Binary file not shown.
@@ -365,6 +365,41 @@ Actors:
|
||||
HarkonnenRally4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 49,4
|
||||
HPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 40,27
|
||||
HPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 21,38
|
||||
HPatrolPoint3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 24,60
|
||||
Actor0: repair_pad
|
||||
Owner: Atreides
|
||||
Location: 59,59
|
||||
Actor1: combat_tank_a.debris
|
||||
Owner: Atreides
|
||||
Facing: 384
|
||||
Location: 59,63
|
||||
Actor2: combat_tank_a.debris
|
||||
Owner: Atreides
|
||||
Facing: 384
|
||||
Location: 62,63
|
||||
Actor3: combat_tank_a.debris
|
||||
Owner: Atreides
|
||||
Facing: 384
|
||||
Location: 56,62
|
||||
Actor9: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 17,47
|
||||
HarkonnenTankDebris1: combat_tank_h.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 8,58
|
||||
Trigger1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 8,58
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,64 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 7000
|
||||
ExternalCondition@AI:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIDefense:
|
||||
Condition: defense-rebuilder
|
||||
BaseBuilderBotModule@campaign:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 6
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@defense:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 6
|
||||
silo: 1
|
||||
medium_gun_turret: 6
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
medium_gun_turret: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -32,6 +32,7 @@ AtreidesReinforcements =
|
||||
}
|
||||
|
||||
AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location }
|
||||
|
||||
AtreidesAttackDelay = DateTime.Seconds(30)
|
||||
|
||||
AtreidesAttackWaves =
|
||||
@@ -49,6 +50,7 @@ ToHarvest =
|
||||
}
|
||||
|
||||
HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" }
|
||||
|
||||
HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.Location }
|
||||
|
||||
Messages =
|
||||
@@ -118,11 +120,8 @@ WorldLoaded = function()
|
||||
end
|
||||
|
||||
Trigger.OnRemovedFromWorld(HarkonnenConyard, function()
|
||||
|
||||
-- Mission already failed, no need to check the other conditions as well
|
||||
if checkResourceCapacity() then
|
||||
return
|
||||
end
|
||||
if checkResourceCapacity() then return end
|
||||
|
||||
local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Harkonnen end)
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ AtreidesReinforcements =
|
||||
}
|
||||
|
||||
AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location }
|
||||
|
||||
AtreidesAttackDelay = DateTime.Seconds(30)
|
||||
|
||||
AtreidesAttackWaves =
|
||||
@@ -49,6 +50,7 @@ ToHarvest =
|
||||
}
|
||||
|
||||
HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" }
|
||||
|
||||
HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.Location }
|
||||
|
||||
Messages =
|
||||
@@ -118,11 +120,8 @@ WorldLoaded = function()
|
||||
end
|
||||
|
||||
Trigger.OnRemovedFromWorld(HarkonnenConyard, function()
|
||||
|
||||
-- Mission already failed, no need to check the other conditions as well
|
||||
if checkResourceCapacity() then
|
||||
return
|
||||
end
|
||||
if checkResourceCapacity() then return end
|
||||
|
||||
local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Harkonnen end)
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -24,10 +24,13 @@ AttackDelays =
|
||||
AtreidesInfantryTypes = { "light_inf" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Atreides] = {}
|
||||
AttackDelay[Atreides] = 3000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Atreides] = 3000 * DifficultyModifier[Difficulty]
|
||||
IdlingUnits[Atreides] = { }
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local toBuild = function() return AtreidesInfantryTypes end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
|
||||
ProduceUnits(Atreides, ABarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
|
||||
Binary file not shown.
@@ -162,6 +162,12 @@ Actors:
|
||||
AtreidesRally4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 47,4
|
||||
Actor1: crate
|
||||
Owner: Neutral
|
||||
Location: 33,47
|
||||
Actor3: crate_reveal
|
||||
Owner: Neutral
|
||||
Location: 27,16
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -22,16 +22,20 @@ AttackDelays =
|
||||
}
|
||||
|
||||
AtreidesInfantryTypes = { "light_inf" }
|
||||
|
||||
AtreidesVehicleTypes = { "trike" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Atreides] = {}
|
||||
AttackDelay[Atreides] = 3000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Atreides] = 3000 * DifficultyModifier[Difficulty]
|
||||
IdlingUnits[Atreides] = { }
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local infantryToBuild = function() return AtreidesInfantryTypes end
|
||||
local vehilcesToBuild = function() return AtreidesVehicleTypes end
|
||||
local vehiclesToBuild = function() return AtreidesVehicleTypes end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
|
||||
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -22,9 +22,13 @@ AttackDelays =
|
||||
}
|
||||
|
||||
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
AtreidesVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Atreides] = {}
|
||||
AttackDelay[Atreides] = 7000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Atreides] = 5000 * DifficultyModifier[Difficulty]
|
||||
IdlingUnits[Atreides] = { }
|
||||
LastHarvesterEaten[Atreides] = true
|
||||
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
|
||||
@@ -32,14 +36,31 @@ ActivateAI = function()
|
||||
AConyard.Produce(HarkonnenUpgrades[1])
|
||||
AConyard.Produce(HarkonnenUpgrades[2])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
-- Finish the upgrades first before trying to build something
|
||||
Trigger.AfterDelay(DateTime.Seconds(14), function()
|
||||
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
if Difficulty ~= "easy" then
|
||||
Atreides.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Atreides, function(p, building)
|
||||
table.insert(OrdosMainBase, building)
|
||||
DefendAndRepairBase(Atreides, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Atreides, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
]]
|
||||
|
||||
AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, ALightFactory, AOutpost, AConyard, ARefinery, ASilo }
|
||||
|
||||
AtreidesBaseAreaTriggers =
|
||||
{
|
||||
{ CPos.New(34, 50), CPos.New(35, 50), CPos.New(36, 50), CPos.New(37, 50), CPos.New(38, 50), CPos.New(39, 50), CPos.New(40, 50), CPos.New(41, 50), CPos.New(14, 57), CPos.New(14, 58), CPos.New(14, 59), CPos.New(14, 60), CPos.New(14, 61), CPos.New(14, 62), CPos.New(14, 63), CPos.New(14, 64), CPos.New(14, 65)},
|
||||
@@ -88,9 +89,11 @@ AtreidesHunterPaths =
|
||||
}
|
||||
|
||||
HarkonnenReinforcements = { "trike", "trike", "quad" }
|
||||
|
||||
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
|
||||
|
||||
HarkonnenBaseBuildings = { "barracks", "light_factory" }
|
||||
|
||||
HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" }
|
||||
|
||||
MessageCheck = function(index)
|
||||
|
||||
Binary file not shown.
@@ -177,6 +177,17 @@ Actors:
|
||||
HarkonnenEntry: waypoint
|
||||
Owner: Neutral
|
||||
Location: 29,2
|
||||
Actor2: carryall.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 24,40
|
||||
Actor18: crate
|
||||
Owner: Neutral
|
||||
Location: 17,33
|
||||
Actor19: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 12,61
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,34 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 5000
|
||||
ExternalCondition@AI:
|
||||
Condition: base-rebuilder
|
||||
BaseBuilderBotModule@campaign:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
wind_trap: 3
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -22,29 +22,48 @@ AttackDelays =
|
||||
}
|
||||
|
||||
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
AtreidesVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
InitAIUnits = function()
|
||||
IdlingUnits[Atreides] = Reinforcements.Reinforce(Atreides, AtreidesInitialReinforcements, AtreidesInitialPath)
|
||||
|
||||
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
|
||||
end
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Atreides] = {}
|
||||
AttackDelay[Atreides] = 7000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Atreides] = 5000 * DifficultyModifier[Difficulty]
|
||||
LastHarvesterEaten[Atreides] = true
|
||||
Trigger.AfterDelay(0, InitAIUnits)
|
||||
|
||||
AConyard.Produce(HarkonnenUpgrades[1])
|
||||
AConyard.Produce(HarkonnenUpgrades[2])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player) return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
-- Finish the upgrades first before trying to build something
|
||||
Trigger.AfterDelay(DateTime.Seconds(14), function()
|
||||
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
if Difficulty ~= "easy" then
|
||||
Atreides.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Atreides, function(p, building)
|
||||
table.insert(OrdosMainBase, building)
|
||||
DefendAndRepairBase(Atreides, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Atreides, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
]]
|
||||
|
||||
AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, AWindTrap3, ALightFactory, AOutpost, AConyard, ARefinery, ASilo1, ASilo2, ASilo3, ASilo4 }
|
||||
|
||||
AtreidesBaseAreaTriggers =
|
||||
{
|
||||
{ CPos.New(10, 53), CPos.New(11, 53), CPos.New(12, 53), CPos.New(13, 53), CPos.New(14, 53), CPos.New(15, 53), CPos.New(16, 53), CPos.New(17, 53), CPos.New(17, 52), CPos.New(17, 51), CPos.New(17, 50), CPos.New(17, 49), CPos.New(17, 48), CPos.New(17, 47), CPos.New(17, 46), CPos.New(17, 45), CPos.New(17, 44), CPos.New(17, 43), CPos.New(17, 42), CPos.New(17, 41), CPos.New(17, 40), CPos.New(17, 39), CPos.New(17, 38), CPos.New(2, 35), CPos.New(3, 35), CPos.New(4, 35), CPos.New(5, 35), CPos.New(6, 35), CPos.New(7, 35), CPos.New(8, 35), CPos.New(9, 35), CPos.New(10, 35), CPos.New(11, 35), CPos.New(12, 35) },
|
||||
@@ -87,12 +88,15 @@ AtreidesHunterPaths =
|
||||
}
|
||||
|
||||
AtreidesInitialPath = { AtreidesEntry2.Location, AtreidesRally2.Location }
|
||||
|
||||
AtreidesInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
|
||||
|
||||
HarkonnenReinforcements = { "quad", "quad" }
|
||||
|
||||
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
|
||||
|
||||
HarkonnenBaseBuildings = { "barracks", "light_factory" }
|
||||
|
||||
HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" }
|
||||
|
||||
MessageCheck = function(index)
|
||||
@@ -150,4 +154,10 @@ WorldLoaded = function()
|
||||
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[2], AtreidesHunters[2], AtreidesHunterPaths[2])
|
||||
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[3], AtreidesHunters[3], AtreidesHunterPaths[3])
|
||||
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[4], AtreidesHunters[4], AtreidesHunterPaths[4])
|
||||
|
||||
Trigger.OnRemovedFromWorld(CrateScript, function()
|
||||
VisionPoint.GrantCondition("activate", 150)
|
||||
Media.PlaySound("MULTI1.WAV")
|
||||
Camera.Position = VisionPoint.CenterPosition
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -207,6 +207,13 @@ Actors:
|
||||
HarkonnenEntry: waypoint
|
||||
Owner: Neutral
|
||||
Location: 65,45
|
||||
CrateScript: crate_script
|
||||
Owner: Neutral
|
||||
Location: 55,9
|
||||
VisionPoint: vision_provider
|
||||
Faction:
|
||||
Location: 46,8
|
||||
Owner: Harkonnen
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,34 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 5000
|
||||
ExternalCondition@AI:
|
||||
Condition: base-rebuilder
|
||||
BaseBuilderBotModule@campaign:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
wind_trap: 3
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -7,6 +7,14 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(5)
|
||||
|
||||
InitialProductionDelay = {
|
||||
easy = DateTime.Seconds(150),
|
||||
normal = DateTime.Seconds(100),
|
||||
hard = DateTime.Seconds(50)
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,7 +22,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -22,24 +30,71 @@ AttackDelays =
|
||||
}
|
||||
|
||||
AtreidesInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
|
||||
|
||||
AtreidesVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
AtreidesTankType = { "combat_tank_a" }
|
||||
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Atreides] = { }
|
||||
Defending[Fremen] = { }
|
||||
AttackDelay[Atreides] = 5000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[Fremen] = 5000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Atreides] = 6000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Fremen] = 5000 * DifficultyModifier[Difficulty]
|
||||
HarvesterCount[Atreides] = 2
|
||||
HarvesterCount[Fremen] = 2
|
||||
IdlingUnits[Fremen] = { }
|
||||
IdlingUnits[Atreides] = Utils.Concat(Reinforcements.Reinforce(Atreides, InitialAtreidesReinforcements[1], AtreidesPaths[2]), Reinforcements.Reinforce(Atreides, InitialAtreidesReinforcements[2], AtreidesPaths[3]))
|
||||
FremenProduction()
|
||||
|
||||
DefencePerimeter[Atreides] = GetCellsInRectangle(CPos.New(4,68), CPos.New(44,82))
|
||||
Utils.Do(IdlingUnits[Atreides], function(a) SelectRoutine(Atreides, a) end)
|
||||
PatrolPoints[Atreides] = { APatrolPoint1.Location, APatrolPoint2.Location, APatrolPoint3.Location, APatrolPoint4.Location }
|
||||
|
||||
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(Fremen, FremenBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local tanksToBuild = function() return AtreidesTankType end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay[Difficulty], function()
|
||||
ProduceUnits(Atreides, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Atreides, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ActivateCrushLogic()
|
||||
|
||||
if Difficulty == "normal" then
|
||||
Atreides.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
Atreides.GrantCondition("defense-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuild
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Atreides, function(p, building)
|
||||
table.insert(AtreidesBase, building)
|
||||
DefendAndRepairBase(Atreides, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Atreides, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
AtreidesBase = { AConyard, AOutpost, ARefinery, AHeavyFactory, ALightFactory, AGunt1, AGunt2, ABarracks, ASilo, APower1, APower2, APower3, APower4, APower5, APower6 }
|
||||
AtreidesBase = { AConyard, AOutpost, ARefinery, AHeavyFactory, ALightFactory, AGunt1, AGunt2, ABarracks, APower1, APower2, APower3, APower4, APower5, APower6 }
|
||||
|
||||
FremenBase = { FGunt1, FGunt2 }
|
||||
|
||||
BaseAreaTriggers =
|
||||
@@ -105,6 +106,8 @@ FremenHunterPaths =
|
||||
{ FremenEntry3.Location, FremenRally3.Location }
|
||||
}
|
||||
|
||||
FremenAmbushSquad = { FremenAmbuser1, FremenAmbuser2, FremenAmbuser3, FremenAmbuser4 }
|
||||
|
||||
HarkonnenReinforcements = { "combat_tank_h", "combat_tank_h" }
|
||||
|
||||
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
|
||||
@@ -156,7 +159,8 @@ WorldLoaded = function()
|
||||
Atreides = Player.GetPlayer("Atreides")
|
||||
Fremen = Player.GetPlayer("Fremen")
|
||||
Harkonnen = Player.GetPlayer("Harkonnen")
|
||||
|
||||
Defending[Atreides] = {}
|
||||
Defending[Fremen] = {}
|
||||
InitObjectives(Harkonnen)
|
||||
KillAtreides = AddPrimaryObjective(Harkonnen, "destroy-atreides")
|
||||
KillFremen = AddPrimaryObjective(Harkonnen, "destroy-fremen")
|
||||
@@ -164,11 +168,7 @@ WorldLoaded = function()
|
||||
|
||||
Camera.Position = HConyard.CenterPosition
|
||||
FremenAttackLocation = HConyard.Location
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(AtreidesBase, function()
|
||||
Utils.Do(Atreides.GetGroundAttackers(), IdleHunt)
|
||||
end)
|
||||
|
||||
IdleHuntOnBaseDestroyed(Atreides, AtreidesBase)
|
||||
Trigger.OnAllKilled(Sietches, function()
|
||||
SietchesAreDestroyed = true
|
||||
end)
|
||||
@@ -179,6 +179,7 @@ WorldLoaded = function()
|
||||
unit.AttackMove(FremenAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
|
||||
SendCarryallReinforcements(Fremen, 0, FremenAttackWaves[Difficulty], FremenAttackDelay[Difficulty], path, FremenReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
|
||||
Actor.Create("upgrade.barracks", true, { Owner = Atreides })
|
||||
@@ -201,4 +202,17 @@ WorldLoaded = function()
|
||||
TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[1], FremenHunters[1], FremenHunterPaths[3], fremenCondition)
|
||||
TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[2], FremenHunters[2], FremenHunterPaths[2], fremenCondition)
|
||||
TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[3], FremenHunters[3], FremenHunterPaths[1], fremenCondition)
|
||||
|
||||
Trigger.OnRemovedFromWorld(ExplosionCrate, function()
|
||||
Utils.Do(FremenAmbushSquad, function(fremen)
|
||||
fremen.Stance = "AttackAnything"
|
||||
end)
|
||||
end)
|
||||
|
||||
Trigger.OnAllKilled({AGunt1, AGunt2}, function()
|
||||
EmergencyBuildRate[Atreides] = true
|
||||
Trigger.AfterDelay(600, function()
|
||||
EmergencyBuildRate[Atreides] = false
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -376,6 +376,54 @@ Actors:
|
||||
AtreidesEntry3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 22,91
|
||||
APatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 56,67
|
||||
APatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 34,43
|
||||
APatrolPoint3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 23,18
|
||||
APatrolPoint4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 60,17
|
||||
Actor6: crate
|
||||
Owner: Neutral
|
||||
Location: 25,12
|
||||
Actor8: crate
|
||||
Owner: Neutral
|
||||
Location: 8,18
|
||||
ExplosionCrate: crate_explosion
|
||||
Owner: Neutral
|
||||
Location: 18,28
|
||||
FremenAmbuser1: fremen
|
||||
Owner: Fremen
|
||||
Location: 15,25
|
||||
SubCell: 3
|
||||
Facing: 384
|
||||
Stance: ReturnFire
|
||||
FremenAmbuser2: fremen
|
||||
Owner: Fremen
|
||||
Location: 20,25
|
||||
SubCell: 3
|
||||
Stance: ReturnFire
|
||||
Facing: 384
|
||||
FremenAmbuser3: fremen
|
||||
Owner: Fremen
|
||||
Location: 15,28
|
||||
SubCell: 3
|
||||
Stance: ReturnFire
|
||||
Facing: 384
|
||||
FremenAmbuser4: fremen
|
||||
Owner: Fremen
|
||||
Location: 15,29
|
||||
SubCell: 3
|
||||
Stance: ReturnFire
|
||||
Facing: 384
|
||||
Actor32: crate_reveal
|
||||
Owner: Neutral
|
||||
Location: 16,47
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,68 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 5000
|
||||
ExternalCondition@AI:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIDefense:
|
||||
Condition: defense-rebuilder
|
||||
BaseBuilderBotModule@AIMainBase:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@AIMainBaseWithDefense:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
medium_gun_turret: 2
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
medium_gun_turret: 2
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -7,6 +7,24 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(6)
|
||||
|
||||
InitialProductionDelay = {
|
||||
OrdosMain =
|
||||
{
|
||||
easy = DateTime.Seconds(150),
|
||||
normal = DateTime.Seconds(100),
|
||||
hard = DateTime.Seconds(50)
|
||||
},
|
||||
|
||||
OrdosSmall =
|
||||
{
|
||||
easy = DateTime.Seconds(120),
|
||||
normal = DateTime.Seconds(60),
|
||||
hard = DateTime.Seconds(30)
|
||||
},
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,7 +32,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -22,28 +40,86 @@ AttackDelays =
|
||||
}
|
||||
|
||||
OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
OrdosVehicleTypes = { "raider", "raider", "quad" }
|
||||
|
||||
OrdosTankType = { "combat_tank_o" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[OrdosMain] = {}
|
||||
Defending[OrdosSmall] = {}
|
||||
AttackDelay[OrdosMain] = 8000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[OrdosSmall] = 10000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[Corrino] = 1000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[OrdosMain] = 8000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[OrdosSmall] = 7000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Corrino] = 2000 * DifficultyModifier[Difficulty]
|
||||
HarvesterCount[OrdosMain] = 2
|
||||
HarvesterCount[OrdosSmall] = 2
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(ProductionBuildingsOrdosSmallBase, function()
|
||||
TimeBetweenAttacks[OrdosMain] = 0
|
||||
end)
|
||||
|
||||
PatrolPoints[OrdosMain] = {OrdosPatrol1.Location, OrdosPatrol2.Location }
|
||||
PatrolPoints[OrdosSmall] = {OrdosRally1.Location, OrdosRally2.Location, OrdosRally4.Location }
|
||||
DefencePerimeter[OrdosMain] = GetCellsInRectangle(CPos.New(51,11), CPos.New(67,38))
|
||||
DefencePerimeter[OrdosSmall] = GetCellsInRectangle(CPos.New(6,69), CPos.New(22,80))
|
||||
|
||||
IdlingUnits[OrdosMain] = Utils.Concat(Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[1], InitialOrdosPaths[1]), Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[2], InitialOrdosPaths[2]))
|
||||
IdlingUnits[OrdosSmall] = Reinforcements.Reinforce(OrdosSmall, InitialOrdosReinforcements[1], InitialOrdosPaths[3])
|
||||
IdlingUnits[Corrino] = { CSaraukar1, CSaraukar2, CSaraukar3, CSaraukar4, CSaraukar5 }
|
||||
IdlingUnits[Corrino] = { CSardaukar1, CSardaukar2, CSardaukar3, CSardaukar4, CSardaukar5 }
|
||||
|
||||
DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(Corrino, CorrinoBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local tanksToBuild = function() return OrdosTankType end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
local attackThresholdSize = {}
|
||||
attackThresholdSize[OrdosMain] = AttackGroupSize[Difficulty] * 3
|
||||
attackThresholdSize[OrdosSmall] = AttackGroupSize[Difficulty] * 2
|
||||
|
||||
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
|
||||
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
ProduceUnits(OrdosMain, OLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
end)
|
||||
|
||||
ProduceUnits(OrdosSmall, OBarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["OrdosSmall"][Difficulty], function()
|
||||
ProduceUnits(OrdosSmall, OBarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
|
||||
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
|
||||
end)
|
||||
|
||||
ActivateCrushLogic()
|
||||
|
||||
if Difficulty == "normal" then
|
||||
OrdosMain.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
OrdosMain.GrantCondition("defense-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuild
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(OrdosMain, function(p, building)
|
||||
table.insert(OrdosMainBase, building)
|
||||
DefendAndRepairBase(OrdosMain, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(OrdosMain, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,9 +8,15 @@
|
||||
]]
|
||||
|
||||
OrdosMainBase = { OConYard, OOutpost, ORefinery1, ORefinery2, OHeavyFactory, OLightFactory1, OHiTechFactory, OGunt1, OGunt2, OGunt3, OGunt4, OBarracks1, OBarracks2, OPower1, OPower2, OPower3, OPower4, OPower5, OPower6, OPower7, OPower8, OPower9 }
|
||||
|
||||
OrdosSmallBase = { ORefinery3, OBarracks3, OLightFactory2, OGunt5, OGunt6, OPower10, OPower11, OPower12, OPower13, OSilo }
|
||||
|
||||
CorrinoBase = { CStarport, CPower1, CPower2 }
|
||||
|
||||
ProductionBuildingsOrdosSmallBase = { ORefinery3, OBarracks3, OLightFactory2 }
|
||||
|
||||
SmugglerSquad = {Smuggler1, Smuggler2, Smuggler3}
|
||||
|
||||
BaseAreaTriggers =
|
||||
{
|
||||
{ CPos.New(68, 70), CPos.New(69, 70), CPos.New(70, 70), CPos.New(71, 70) },
|
||||
@@ -135,6 +141,7 @@ SendStarportReinforcements = function()
|
||||
return
|
||||
end
|
||||
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("imperial-ships-penetrating-defense-grid"), Mentat)
|
||||
local units = Reinforcements.ReinforceWithTransport(Corrino, "frigate", CorrinoStarportReinforcements[Difficulty], { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2]
|
||||
Utils.Do(units, function(unit)
|
||||
unit.AttackMove(OrdosAttackLocation)
|
||||
@@ -142,12 +149,6 @@ SendStarportReinforcements = function()
|
||||
end)
|
||||
|
||||
SendStarportReinforcements()
|
||||
|
||||
if Harkonnen.IsObjectiveFailed(GuardOutpost) then
|
||||
return
|
||||
end
|
||||
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("imperial-ships-penetrating-defense-grid"), Mentat)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -222,13 +223,28 @@ Tick = function()
|
||||
end
|
||||
end
|
||||
|
||||
ChangeOwner = function(old_owner, new_owner)
|
||||
local units = old_owner.GetActors()
|
||||
Utils.Do(units, function(unit)
|
||||
if not unit.IsDead then
|
||||
unit.Owner = new_owner
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
WorldLoaded = function()
|
||||
OrdosMain = Player.GetPlayer("Ordos Main Base")
|
||||
OrdosSmall = Player.GetPlayer("Ordos Small Base")
|
||||
Corrino = Player.GetPlayer("Corrino")
|
||||
Harkonnen = Player.GetPlayer("Harkonnen")
|
||||
SmugglerNeutral = Player.GetPlayer("Smugglers - Neutral")
|
||||
SmugglerEnemy = Player.GetPlayer("Smugglers - Enemy")
|
||||
Defending[OrdosMain] = {}
|
||||
Defending[OrdosSmall] = {}
|
||||
Defending[Corrino] = {}
|
||||
|
||||
InitObjectives(Harkonnen)
|
||||
|
||||
KillOrdos = AddPrimaryObjective(Harkonnen, "destroy-ordos")
|
||||
KillCorrino = AddPrimaryObjective(Harkonnen, "destroy-imperial-forces")
|
||||
GuardOutpost = AddSecondaryObjective(Harkonnen, "keep-modified-outpost-intact")
|
||||
@@ -257,17 +273,20 @@ WorldLoaded = function()
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("protect-outpost"), Mentat)
|
||||
end)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured({ HOutpost }, function()
|
||||
SendStarportReinforcements()
|
||||
end)
|
||||
|
||||
local path = function() return Utils.Random(OrdosPaths) end
|
||||
local waveCondition = function() return Harkonnen.IsObjectiveCompleted(KillOrdos) end
|
||||
local huntFunction = function(unit)
|
||||
unit.AttackMove(OrdosAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
|
||||
SendCarryallReinforcements(OrdosMain, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
OrdosReinforcementNotification(0, OrdosAttackWaves[Difficulty])
|
||||
|
||||
SendStarportReinforcements()
|
||||
|
||||
Actor.Create("upgrade.barracks", true, { Owner = OrdosMain })
|
||||
Actor.Create("upgrade.light", true, { Owner = OrdosMain })
|
||||
Actor.Create("upgrade.heavy", true, { Owner = OrdosMain })
|
||||
|
||||
Binary file not shown.
@@ -514,6 +514,18 @@ Actors:
|
||||
HarkonnenEntry2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 2,29
|
||||
OrdosPatrol1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 33,19
|
||||
OrdosPatrol2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 37,41
|
||||
Actor9: crate
|
||||
Owner: Neutral
|
||||
Location: 48,54
|
||||
Actor10: crate
|
||||
Owner: Neutral
|
||||
Location: 49,53
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,68 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 6000
|
||||
ExternalCondition@AI:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIDefense:
|
||||
Condition: defense-rebuilder
|
||||
BaseBuilderBotModule@campaign:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 8
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@defense:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 8
|
||||
silo: 1
|
||||
medium_gun_turret: 4
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
medium_gun_turret: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -7,6 +7,24 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(6)
|
||||
|
||||
InitialProductionDelay = {
|
||||
OrdosMain =
|
||||
{
|
||||
easy = DateTime.Seconds(140),
|
||||
normal = DateTime.Seconds(80),
|
||||
hard = DateTime.Seconds(40)
|
||||
},
|
||||
|
||||
OrdosSmall =
|
||||
{
|
||||
easy = DateTime.Seconds(120),
|
||||
normal = DateTime.Seconds(60),
|
||||
hard = DateTime.Seconds(30)
|
||||
},
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,7 +32,14 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
EarlyProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(10), DateTime.Seconds(13) },
|
||||
normal = { DateTime.Seconds(6), DateTime.Seconds(8) },
|
||||
hard = { DateTime.Seconds(3), DateTime.Seconds(5) }
|
||||
}
|
||||
|
||||
LateProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -22,29 +47,90 @@ AttackDelays =
|
||||
}
|
||||
|
||||
OrdosInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
|
||||
|
||||
OrdosVehicleTypes = { "raider", "raider", "quad" }
|
||||
|
||||
OrdosTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" }
|
||||
|
||||
OrdosStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[OrdosMain] = {}
|
||||
Defending[OrdosSmall] = {}
|
||||
AttackDelay[OrdosMain] = 14000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[OrdosSmall] = 14000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[OrdosMain] = 10000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[OrdosSmall] = 8000 * DifficultyModifier[Difficulty]
|
||||
HarvesterCount[OrdosMain] = 4
|
||||
HarvesterCount[OrdosSmall] = 2
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(ProductionBuildingsOrdosSmallBase, function()
|
||||
TimeBetweenAttacks[OrdosMain] = 0
|
||||
end)
|
||||
|
||||
PatrolPoints[OrdosMain] = {OrdosRally5.Location, OrdosRally11.Location, OrdosRally12.Location }
|
||||
PatrolPoints[OrdosSmall] = {OrdosRally5.Location, OrdosRally7.Location, OrdosRally4.Location, OrdosRally5.Location }
|
||||
DefencePerimeter[OrdosMain] = Utils.Concat( GetCellsInRectangle(CPos.New(37,30), CPos.New(69,50)), GetCellsInRectangle(CPos.New(54,13), CPos.New(70,30)))
|
||||
DefencePerimeter[OrdosSmall] = GetCellsInRectangle(CPos.New(4,20), CPos.New(15,40))
|
||||
|
||||
IdlingUnits[OrdosMain] = Utils.Concat(Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[1], InitialOrdosPaths[1]), Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[2], InitialOrdosPaths[2]))
|
||||
IdlingUnits[OrdosSmall] = Reinforcements.Reinforce(OrdosSmall, InitialOrdosReinforcements[1], InitialOrdosPaths[3])
|
||||
|
||||
DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
|
||||
else
|
||||
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local tanksToBuild = function() return { Utils.Random(OrdosTankTypes) } end
|
||||
local unitsToBuy = function() return { Utils.Random(OrdosStarportTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
local attackThresholdSize = {}
|
||||
attackThresholdSize[OrdosMain] = AttackGroupSize[Difficulty] * 3
|
||||
attackThresholdSize[OrdosSmall] = AttackGroupSize[Difficulty] * 2
|
||||
|
||||
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosMain, OHeavyFactory1, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
|
||||
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
ProduceUnits(OrdosMain, OLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
ProduceUnits(OrdosMain, OHeavyFactory1, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
end)
|
||||
|
||||
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["OrdosSmall"][Difficulty], function()
|
||||
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall] )
|
||||
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall] )
|
||||
end)
|
||||
|
||||
ActivateCrushLogic()
|
||||
|
||||
if Difficulty == "normal" then
|
||||
OrdosSmall.GrantCondition("base-rebuilder2")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
OrdosSmall.GrantCondition("defense-rebuilder2")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuild
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(OrdosSmall, function(p, building)
|
||||
table.insert(OrdosSmallBase, building)
|
||||
DefendAndRepairBase(OrdosSmall, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(OrdosSmall, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,8 +8,18 @@
|
||||
]]
|
||||
|
||||
OrdosMainBase = { OOutpost, ORefinery1, ORefinery2, OHeavyFactory1, OHeavyFactory2, OLightFactory1, OHiTechFactory, OResearch, ORepair, OStarport, OGunt1, OGunt2, OGunt3, OGunt4, OGunt5, OGunt6, OGunt7, OGunt8, OGunt9, OGunt10, OGunt11, OGunt12, OBarracks1, OPower1, OPower2, OPower3, OPower4, OPower5, OPower6, OPower7, OPower8, OPower9, OPower10 }
|
||||
|
||||
OrdosSmallBase = { OConyard, ORefinery3, OBarracks2, OLightFactory2, OGunt13, OGunt14, OGunt15, OGunt16, OPower11, OPower12, OPower13, OPower14 }
|
||||
|
||||
ProductionBuildingsOrdosSmallBase = { OConyard, ORefinery3, OBarracks2, OLightFactory2 }
|
||||
|
||||
SmugglerTriggerZone = Utils.Concat(
|
||||
GetCellsInRectangle(CPos.New(73,67), CPos.New(81,72)),
|
||||
GetCellsInRectangle(CPos.New(77,73), CPos.New(82,77))
|
||||
)
|
||||
|
||||
SmugglerPatrol = {Smuggler1, Smuggler2, Smuggler3, Smuggler4, Smuggler5, Smuggler6 }
|
||||
|
||||
OrdosReinforcements =
|
||||
{
|
||||
easy =
|
||||
@@ -149,9 +159,62 @@ ChangeOwner = function(old_owner, new_owner)
|
||||
end)
|
||||
end
|
||||
|
||||
Message = {}
|
||||
StopFollowing = {}
|
||||
Trigger.OnEnteredFootprint(SmugglerTriggerZone, function(a, id)
|
||||
if SmugglerNeutral.HasNoRequiredUnits() then
|
||||
Trigger.RemoveFootprintTrigger(id)
|
||||
end
|
||||
|
||||
if a.Owner == Harkonnen and not Message[Harkonnen] then
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("smuggler-warning-harkonnen"), "Smugglers", HSLColor.FromHex("7B2910"))
|
||||
Message[Harkonnen] = true
|
||||
end
|
||||
|
||||
if a.Owner == OrdosMain or a.Owner == OrdosSmall and not Message[Ordos] then
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("smuggler-warning-ordos"), "Smugglers", HSLColor.FromHex("7B2910"))
|
||||
Message[Ordos] = true
|
||||
end
|
||||
|
||||
if a.Owner ~= SmugglerNeutral then
|
||||
Utils.Do(SmugglerPatrol, function(u)
|
||||
if not u.IsDead then
|
||||
StopFollowing[u] = false
|
||||
FollowIntruder(u,a)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnExitedFootprint(SmugglerTriggerZone, function(a, id)
|
||||
if SmugglerNeutral.HasNoRequiredUnits() then
|
||||
Trigger.RemoveFootprintTrigger(id)
|
||||
end
|
||||
if a.Owner ~= SmugglerNeutral then
|
||||
Utils.Do(SmugglerPatrol, function(u)
|
||||
if not u.IsDead then StopFollowing[u] = true end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
FollowIntruder = function(unit, intruder)
|
||||
if intruder.IsDead or unit.IsDead then return end
|
||||
if StopFollowing[unit] == true then unit.Stop() return end
|
||||
unit.Stop()
|
||||
unit.AttackMove(intruder.Location,1)
|
||||
Trigger.AfterDelay(100, function() FollowIntruder(unit, intruder) end)
|
||||
end
|
||||
|
||||
CheckSmugglerEnemies = function()
|
||||
Utils.Do(SmugglerUnits, function(unit)
|
||||
Trigger.OnDamaged(unit, function(self, attacker)
|
||||
if Utils.Any(IgnoreDamageFromTypes, function(a) return a == attacker.Type end) then
|
||||
return
|
||||
end
|
||||
|
||||
if not self.HasProperty("Health") then return end
|
||||
if self.MaxHealth * 0.9 < self.Health then return end
|
||||
|
||||
if unit.Owner == SmugglerNeutral and attacker.Owner == Harkonnen then
|
||||
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
|
||||
|
||||
@@ -197,6 +260,25 @@ CheckSmugglerEnemies = function()
|
||||
end)
|
||||
end
|
||||
|
||||
EmergencyBehaviour = function(player, target)
|
||||
if player ~= OrdosSmall then return end
|
||||
if not OGunt15.IsDead and not OGunt16.IsDead then return end
|
||||
if #IdlingUnits[OrdosMain] > 10 and Utils.Any(ProductionBuildingsOrdosSmallBase, function(a) return not a.IsDead end) then
|
||||
local reinforcements = SetupAttackGroup(OrdosMain, Utils.RandomInteger(5, #IdlingUnits[OrdosMain]))
|
||||
Utils.Do(reinforcements, function(unit)
|
||||
Trigger.ClearAll(unit)
|
||||
Trigger.AfterDelay(1, function()
|
||||
unit.Stop()
|
||||
unit.Move(OrdosRally13.Location,1)
|
||||
unit.AttackMove(target)
|
||||
unit.CallFunc(function()
|
||||
FindTargetsInArea(player, unit)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
Tick = function()
|
||||
if Harkonnen.HasNoRequiredUnits() then
|
||||
OrdosMain.MarkCompletedObjective(KillHarkonnen1)
|
||||
@@ -234,6 +316,8 @@ Tick = function()
|
||||
ProtectHarvester(units[1], OrdosSmall, AttackGroupSize[Difficulty])
|
||||
end
|
||||
end
|
||||
|
||||
if IdlingUnits[OrdosMain] == nil and IdlingUnits[OrdosSmall] == nil then return end
|
||||
end
|
||||
|
||||
WorldLoaded = function()
|
||||
@@ -273,6 +357,7 @@ WorldLoaded = function()
|
||||
unit.AttackMove(OrdosAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
|
||||
SendCarryallReinforcements(OrdosMain, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
|
||||
SendStarportReinforcements()
|
||||
|
||||
@@ -424,12 +424,14 @@ Actors:
|
||||
OGunt15: medium_gun_turret
|
||||
Location: 7,37
|
||||
Owner: Ordos Small Base
|
||||
TurretFacing: 512
|
||||
Actor111: wall
|
||||
Location: 11,37
|
||||
Owner: Ordos Small Base
|
||||
OGunt16: medium_gun_turret
|
||||
Location: 11,38
|
||||
Owner: Ordos Small Base
|
||||
TurretFacing: 512
|
||||
Actor113: wall
|
||||
Location: 12,38
|
||||
Owner: Ordos Small Base
|
||||
@@ -568,18 +570,12 @@ Actors:
|
||||
Actor158: light_inf
|
||||
Location: 9,72
|
||||
Owner: Harkonnen
|
||||
Actor159: light_inf
|
||||
Location: 77,72
|
||||
Owner: Smugglers - Neutral
|
||||
SSilo3: silo
|
||||
Location: 81,72
|
||||
Owner: Smugglers - Neutral
|
||||
Actor161: trike
|
||||
Location: 11,73
|
||||
Owner: Harkonnen
|
||||
Actor162: trooper
|
||||
Location: 80,73
|
||||
Owner: Smugglers - Neutral
|
||||
Actor163: trooper
|
||||
Location: 7,74
|
||||
Owner: Harkonnen
|
||||
@@ -592,15 +588,9 @@ Actors:
|
||||
SRefinery: refinery
|
||||
Location: 78,74
|
||||
Owner: Smugglers - Neutral
|
||||
Actor167: light_inf
|
||||
Location: 82,74
|
||||
Owner: Smugglers - Neutral
|
||||
Actor168: combat_tank_h
|
||||
Location: 10,75
|
||||
Owner: Harkonnen
|
||||
Actor169: trooper
|
||||
Location: 82,75
|
||||
Owner: Smugglers - Neutral
|
||||
Actor170: light_inf
|
||||
Location: 15,76
|
||||
Owner: Harkonnen
|
||||
@@ -625,12 +615,6 @@ Actors:
|
||||
Actor177: spicebloom.spawnpoint
|
||||
Location: 72,77
|
||||
Owner: Neutral
|
||||
Actor178: light_inf
|
||||
Location: 82,77
|
||||
Owner: Smugglers - Neutral
|
||||
Actor179: light_inf
|
||||
Location: 83,77
|
||||
Owner: Smugglers - Neutral
|
||||
Actor180: light_inf
|
||||
Location: 11,78
|
||||
Owner: Harkonnen
|
||||
@@ -715,6 +699,45 @@ Actors:
|
||||
HarkonnenEntry2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 2,68
|
||||
OrdosRally11: waypoint
|
||||
Owner: Neutral
|
||||
Location: 51,66
|
||||
OrdosRally12: waypoint
|
||||
Owner: Neutral
|
||||
Location: 79,40
|
||||
OrdosRally13: waypoint
|
||||
Owner: Neutral
|
||||
Location: 19,16
|
||||
Actor5: crate
|
||||
Location: 81,67
|
||||
Faction:
|
||||
Owner: Smugglers - Neutral
|
||||
Actor13: crate
|
||||
Location: 81,69
|
||||
Faction:
|
||||
Owner: Smugglers - Neutral
|
||||
Actor11: crate
|
||||
Location: 81,71
|
||||
Faction:
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler1: light_inf
|
||||
Location: 77,72
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler2: trooper
|
||||
Location: 80,73
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler3: light_inf
|
||||
Location: 82,74
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler4: trooper
|
||||
Location: 82,75
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler5: light_inf
|
||||
Location: 82,77
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler6: light_inf
|
||||
Location: 83,77
|
||||
Owner: Smugglers - Neutral
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,66 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 6000
|
||||
ExternalCondition@AISmall:
|
||||
Condition: base-rebuilder2
|
||||
ExternalCondition@AISmallDefense:
|
||||
Condition: defense-rebuilder2
|
||||
BaseBuilderBotModule@SmallBase:
|
||||
RequiresCondition: base-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
research_centre: 1
|
||||
high_tech_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
research_centre: 1
|
||||
high_tech_factory: 1
|
||||
BaseBuilderBotModule@SmallBasewithDefence:
|
||||
RequiresCondition: defense-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
PlaceDefenseTowardsEnemyChance: 50
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
medium_gun_turret: 4
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
medium_gun_turret: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -7,6 +7,23 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(7)
|
||||
|
||||
InitialProductionDelay = {
|
||||
OrdosMain =
|
||||
{
|
||||
easy = DateTime.Seconds(180),
|
||||
normal = DateTime.Seconds(120),
|
||||
hard = DateTime.Seconds(60)
|
||||
},
|
||||
OrdosSmall =
|
||||
{
|
||||
easy = DateTime.Seconds(120),
|
||||
normal = DateTime.Seconds(60),
|
||||
hard = DateTime.Seconds(0)
|
||||
}
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,7 +31,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -22,29 +39,108 @@ AttackDelays =
|
||||
}
|
||||
|
||||
OrdosInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
|
||||
|
||||
OrdosVehicleTypes = { "raider", "raider", "quad" }
|
||||
|
||||
OrdosTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" }
|
||||
OrdosStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
OrdosStarportTypes =
|
||||
{
|
||||
EarlyGame = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport" },
|
||||
LateGame = { "trike.starport", "quad.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport", "missile_tank.starport" }
|
||||
}
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[OrdosMain] = {}
|
||||
Defending[OrdosSmall] = {}
|
||||
AttackDelay[OrdosMain] = 14000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[OrdosSmall] = 12000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[OrdosMain] = 7000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[OrdosSmall] = 7000 * DifficultyModifier[Difficulty]
|
||||
HarvesterCount[OrdosMain] = 4
|
||||
HarvesterCount[OrdosSmall] = 2
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(ProductionBuildingsOrdosSmallBase, function()
|
||||
TimeBetweenAttacks[OrdosMain] = 0
|
||||
end)
|
||||
|
||||
PatrolPoints[OrdosMain] = {OrdosPatrol3.Location, OrdosPatrol4.Location, OrdosPatrol2.Location }
|
||||
PatrolPoints[OrdosSmall] = {OrdosPatrol1.Location, OrdosPatrol2.Location, OrdosRally1.Location}
|
||||
DefencePerimeter[OrdosMain] = GetCellsInRectangle(CPos.New(50,3), CPos.New(94,21))
|
||||
DefencePerimeter[OrdosSmall] = GetCellsInRectangle(CPos.New(3,3), CPos.New(25,20))
|
||||
IdlingUnits[OrdosMain] = Utils.Concat(Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[1], InitialOrdosPaths[1]), Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[2], InitialOrdosPaths[2]))
|
||||
IdlingUnits[OrdosSmall] = Reinforcements.Reinforce(OrdosSmall, InitialOrdosReinforcements[1], InitialOrdosPaths[3])
|
||||
|
||||
DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local tanksToBuild = function() return { Utils.Random(OrdosTankTypes) } end
|
||||
local unitsToBuy = function() return { Utils.Random(OrdosStarportTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
local unitsToBuy = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(OrdosStarportTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(OrdosStarportTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
local attackThresholdSize = {}
|
||||
attackThresholdSize[OrdosMain] = AttackGroupSize[Difficulty] * 3
|
||||
attackThresholdSize[OrdosSmall] = AttackGroupSize[Difficulty] * 2
|
||||
|
||||
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
|
||||
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
ProduceUnits(OrdosMain, OLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(InitialProductionDelay["OrdosSmall"][Difficulty], function()
|
||||
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
|
||||
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
|
||||
end)
|
||||
|
||||
local crusherTypes = { "combat_tank_o", "combat_tank_o.starport" }
|
||||
local crusherFactories = { OHeavyFactory, OStarport }
|
||||
|
||||
ActivateCrushLogic()
|
||||
|
||||
if Difficulty == "easy" then
|
||||
OrdosMain.GrantCondition("base-rebuilder")
|
||||
OrdosMain.GrantCondition("base-rebuilder2")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
OrdosMain.GrantCondition("defense-rebuilder")
|
||||
OrdosMain.GrantCondition("base-rebuilder2")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuild
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(OrdosMain, function(p, building)
|
||||
table.insert(OrdosMainBase, building)
|
||||
DefendAndRepairBase(OrdosMain, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(OrdosMain, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
|
||||
end)
|
||||
|
||||
Trigger.OnBuildingPlaced(OrdosSmall, function(p, building)
|
||||
table.insert(OrdosSmallBase, building)
|
||||
DefendAndRepairBase(OrdosSmall, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(OrdosSmall, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,8 +8,18 @@
|
||||
]]
|
||||
|
||||
OrdosMainBase = { OConYard1, OOutpost, ORefinery1, ORefinery2, OHeavyFactory, OLightFactory1, OHiTechFactory, ORepair, OStarport, OGunt1, OGunt2, OGunt3, OGunt4, OGunt5, OGunt6, ORocket1, ORocket2, OBarracks1, OPower1, OPower2, OPower3, OPower4, OPower5, OPower6, OPower7, OPower8, OPower9, OPower10, OSilo1, OSilo2, OSilo3, OSilo4, OSilo5, OSilo6 }
|
||||
|
||||
OrdosSmallBase = { OConYard2, ORefinery3, OBarracks2, OLightFactory2, OGunt6, OGunt7, ORocket3, ORocket4, OPower11, OPower12, OPower13, OPower14, OSilo7, OSilo8, OSilo9 }
|
||||
|
||||
ProductionBuildingsOrdosSmallBase = { OConyard2, ORefinery3, OBarracks2, OLightFactory2 }
|
||||
|
||||
SmugglerTriggerZone = Utils.Concat(
|
||||
GetCellsInRectangle(CPos.New(48,24), CPos.New(53,29)),
|
||||
GetCellsInRectangle(CPos.New(43,30), CPos.New(53,35))
|
||||
)
|
||||
|
||||
SmugglerPatrol = {Smuggler1, Smuggler2, Smuggler3, Smuggler4, Smuggler5, Smuggler6 }
|
||||
|
||||
OrdosReinforcements =
|
||||
{
|
||||
easy =
|
||||
@@ -118,6 +128,53 @@ SendStarportReinforcements = function()
|
||||
end)
|
||||
end
|
||||
|
||||
Message = {}
|
||||
StopFollowing = {}
|
||||
Trigger.OnEnteredFootprint(SmugglerTriggerZone, function(a, id)
|
||||
if SmugglerNeutral.HasNoRequiredUnits() then
|
||||
Trigger.RemoveFootprintTrigger(id)
|
||||
end
|
||||
|
||||
if a.Owner == Harkonnen and not Message[Harkonnen] then
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("smuggler-warning-harkonnen"), "Smugglers", HSLColor.FromHex("7B2910"))
|
||||
Message[Harkonnen] = true
|
||||
end
|
||||
|
||||
if a.Owner == OrdosMain or a.Owner == OrdosSmall and not Message[OrdosMain] then
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("smuggler-warning-ordos"), "Smugglers", HSLColor.FromHex("7B2910"))
|
||||
Message[OrdosMain] = true
|
||||
end
|
||||
|
||||
if a.Owner ~= SmugglerNeutral then
|
||||
Utils.Do(SmugglerPatrol, function(u)
|
||||
if not u.IsDead then
|
||||
StopFollowing[u] = false
|
||||
FollowIntruder(u,a)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnExitedFootprint(SmugglerTriggerZone, function(a, id)
|
||||
if SmugglerNeutral.HasNoRequiredUnits() then
|
||||
Trigger.RemoveFootprintTrigger(id)
|
||||
end
|
||||
|
||||
if a.Owner ~= SmugglerNeutral then
|
||||
Utils.Do(SmugglerPatrol, function(u)
|
||||
if not u.IsDead then StopFollowing[u] = true end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
FollowIntruder = function(unit, intruder)
|
||||
if intruder.IsDead or unit.IsDead then return end
|
||||
if StopFollowing[unit] == true then unit.Stop() return end
|
||||
unit.Stop()
|
||||
unit.AttackMove(intruder.Location,1)
|
||||
Trigger.AfterDelay(100, function() FollowIntruder(unit, intruder) end)
|
||||
end
|
||||
|
||||
ChangeOwner = function(old_owner, new_owner)
|
||||
local units = old_owner.GetActors()
|
||||
Utils.Do(units, function(unit)
|
||||
@@ -130,20 +187,47 @@ end
|
||||
CheckSmugglerEnemies = function()
|
||||
Utils.Do(SmugglerUnits, function(unit)
|
||||
Trigger.OnDamaged(unit, function(self, attacker)
|
||||
if Utils.Any(IgnoreDamageFromTypes, function(a) return a == attacker.Type end) then
|
||||
return
|
||||
end
|
||||
|
||||
if not self.HasProperty("Health") then return end
|
||||
if self.MaxHealth * 0.9 < self.Health then return end
|
||||
|
||||
if unit.Owner == SmugglerNeutral and attacker.Owner == Harkonnen then
|
||||
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
|
||||
|
||||
-- Ensure that harvesters that was on a carryall switched sides.
|
||||
Trigger.AfterDelay(DateTime.Seconds(15), function()
|
||||
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
|
||||
end)
|
||||
end
|
||||
|
||||
if unit.Owner == SmugglerOrdos and attacker.Owner == Harkonnen then
|
||||
ChangeOwner(SmugglerOrdos, SmugglerBoth)
|
||||
|
||||
-- Ensure that harvesters that was on a carryall switched sides.
|
||||
Trigger.AfterDelay(DateTime.Seconds(15), function()
|
||||
ChangeOwner(SmugglerOrdos, SmugglerBoth)
|
||||
end)
|
||||
end
|
||||
|
||||
if unit.Owner == SmugglerNeutral and (attacker.Owner == OrdosMain or attacker.Owner == OrdosSmall) then
|
||||
ChangeOwner(SmugglerNeutral, SmugglerOrdos)
|
||||
|
||||
-- Ensure that harvesters that was on a carryall switched sides.
|
||||
Trigger.AfterDelay(DateTime.Seconds(15), function()
|
||||
ChangeOwner(SmugglerNeutral, SmugglerOrdos)
|
||||
end)
|
||||
end
|
||||
|
||||
if unit.Owner == SmugglerHarkonnen and (attacker.Owner == OrdosMain or attacker.Owner == OrdosSmall) then
|
||||
ChangeOwner(SmugglerHarkonnen, SmugglerBoth)
|
||||
|
||||
-- Ensure that harvesters that was on a carryall switched sides.
|
||||
Trigger.AfterDelay(DateTime.Seconds(15), function()
|
||||
ChangeOwner(SmugglerHarkonnen, SmugglerBoth)
|
||||
end)
|
||||
end
|
||||
|
||||
if attacker.Owner == Harkonnen and not MessageCheck then
|
||||
@@ -155,6 +239,13 @@ CheckSmugglerEnemies = function()
|
||||
end)
|
||||
end
|
||||
|
||||
EmergencyBehaviour = function(player, target)
|
||||
if player ~= OrdosSmall then return end
|
||||
if #IdlingUnits[OrdosMain] > 10 and Utils.Any(OrdosSmallBase, function(a) return not a.IsDead end) then
|
||||
CheckArea(OrdosMain, target, 10)
|
||||
end
|
||||
end
|
||||
|
||||
Tick = function()
|
||||
if Harkonnen.HasNoRequiredUnits() then
|
||||
OrdosMain.MarkCompletedObjective(KillHarkonnen1)
|
||||
@@ -231,8 +322,8 @@ WorldLoaded = function()
|
||||
unit.AttackMove(OrdosAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
SendCarryallReinforcements(OrdosMain, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
|
||||
SendCarryallReinforcements(OrdosMain, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
SendStarportReinforcements()
|
||||
|
||||
Actor.Create("upgrade.barracks", true, { Owner = OrdosMain })
|
||||
|
||||
Binary file not shown.
@@ -394,9 +394,11 @@ Actors:
|
||||
OGunt6: medium_gun_turret
|
||||
Location: 9,17
|
||||
Owner: Ordos Small Base
|
||||
TurretFacing: 512
|
||||
OGunt7: medium_gun_turret
|
||||
Location: 14,17
|
||||
Owner: Ordos Small Base
|
||||
TurretFacing: 512
|
||||
Actor102: wall
|
||||
Location: 15,17
|
||||
Owner: Ordos Small Base
|
||||
@@ -463,12 +465,6 @@ Actors:
|
||||
SSilo3: silo
|
||||
Location: 51,26
|
||||
Owner: Smugglers - Neutral
|
||||
Actor124: trooper
|
||||
Location: 51,28
|
||||
Owner: Smugglers - Neutral
|
||||
Actor125: light_inf
|
||||
Location: 53,28
|
||||
Owner: Smugglers - Neutral
|
||||
Actor126: wormspawner
|
||||
Location: 76,28
|
||||
Owner: Creeps
|
||||
@@ -487,24 +483,12 @@ Actors:
|
||||
SPower2: wind_trap
|
||||
Location: 50,30
|
||||
Owner: Smugglers - Neutral
|
||||
Actor132: light_inf
|
||||
Location: 53,30
|
||||
Owner: Smugglers - Neutral
|
||||
SRefinery: refinery
|
||||
Location: 43,33
|
||||
Owner: Smugglers - Neutral
|
||||
Actor134: light_inf
|
||||
Location: 50,33
|
||||
Owner: Smugglers - Neutral
|
||||
Actor135: harvester
|
||||
Location: 46,35
|
||||
Owner: Smugglers - Neutral
|
||||
Actor136: light_inf
|
||||
Location: 48,35
|
||||
Owner: Smugglers - Neutral
|
||||
Actor137: light_inf
|
||||
Location: 52,35
|
||||
Owner: Smugglers - Neutral
|
||||
Actor138: light_inf
|
||||
Location: 42,36
|
||||
Owner: Smugglers - Neutral
|
||||
@@ -652,6 +636,42 @@ Actors:
|
||||
OrdosStarportExit: waypoint
|
||||
Owner: Neutral
|
||||
Location: 2,9
|
||||
Smuggler1: trooper
|
||||
Location: 51,28
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler2: light_inf
|
||||
Location: 53,28
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler3: light_inf
|
||||
Location: 53,30
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler4: light_inf
|
||||
Location: 50,33
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler5: light_inf
|
||||
Location: 48,35
|
||||
Owner: Smugglers - Neutral
|
||||
Smuggler6: light_inf
|
||||
Location: 52,35
|
||||
Owner: Smugglers - Neutral
|
||||
OrdosPatrol1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 26,49
|
||||
OrdosPatrol2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 36,33
|
||||
OrdosPatrol3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 60,29
|
||||
OrdosPatrol4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 82,43
|
||||
Actor4: crate_reveal
|
||||
Owner: Neutral
|
||||
Location: 13,27
|
||||
Actor5: crate
|
||||
Owner: Neutral
|
||||
Location: 82,48
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,136 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 5000
|
||||
ExternalCondition@AIMain:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AISmall:
|
||||
Condition: base-rebuilder2
|
||||
ExternalCondition@AIMainWithDefense:
|
||||
Condition: defense-rebuilder
|
||||
ExternalCondition@AISmallWithDefense:
|
||||
Condition: defense-rebuilder2
|
||||
BaseBuilderBotModule@MainBase:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
wind_trap: 9
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
BaseBuilderBotModule@MainBaseWithDefence:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
PlaceDefenseTowardsEnemyChance: 50
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
medium_gun_turret: 5
|
||||
large_gun_turret: 2
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
medium_gun_turret: 1
|
||||
large_gun_turret: 1
|
||||
BaseBuilderBotModule@SmallBase:
|
||||
RequiresCondition: base-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
BaseBuilderBotModule@SmallBasewithDefence:
|
||||
RequiresCondition: defense-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
PlaceDefenseTowardsEnemyChance: 50
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
medium_gun_turret: 2
|
||||
large_gun_turret: 2
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
medium_gun_turret: 1
|
||||
large_gun_turret: 2
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -6,6 +6,30 @@
|
||||
the License, or (at your option) any later version. For more
|
||||
information, see COPYING.
|
||||
]]
|
||||
EarlyGameStage = DateTime.Minutes(10)
|
||||
|
||||
InitialProductionDelay = {
|
||||
AtreidesMain =
|
||||
{
|
||||
easy = DateTime.Seconds(400),
|
||||
normal = DateTime.Seconds(300),
|
||||
hard = DateTime.Seconds(150)
|
||||
},
|
||||
|
||||
AtreidesSmall =
|
||||
{
|
||||
easy = DateTime.Seconds(300),
|
||||
normal = DateTime.Seconds(200),
|
||||
hard = DateTime.Seconds(100)
|
||||
},
|
||||
|
||||
Corrino =
|
||||
{
|
||||
easy = DateTime.Seconds(100),
|
||||
normal = DateTime.Seconds(120),
|
||||
hard = DateTime.Seconds(60)
|
||||
}
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
@@ -14,29 +38,60 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
EarlyProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
hard = { DateTime.Seconds(1), DateTime.Seconds(3) }
|
||||
easy = { DateTime.Seconds(11), DateTime.Seconds(15) },
|
||||
normal = { DateTime.Seconds(10), DateTime.Seconds(12) },
|
||||
hard = { DateTime.Seconds(8), DateTime.Seconds(10) }
|
||||
}
|
||||
|
||||
InitialProductionDelay =
|
||||
LateProductionDelays =
|
||||
{
|
||||
easy = DateTime.Seconds(30),
|
||||
normal = DateTime.Seconds(15),
|
||||
hard = 0
|
||||
easy = { DateTime.Seconds(6), DateTime.Seconds(10) },
|
||||
normal = { DateTime.Seconds(4), DateTime.Seconds(6) },
|
||||
hard = { DateTime.Seconds(2), DateTime.Seconds(4) }
|
||||
}
|
||||
|
||||
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
AtreidesVehicleTypes = { "trike", "trike", "quad" }
|
||||
AtreidesMainTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
|
||||
|
||||
AtreidesMainTankTypes =
|
||||
{
|
||||
EarlyGame = { "combat_tank_a", "combat_tank_a" },
|
||||
LateGame = { "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
|
||||
}
|
||||
|
||||
AtreidesSmallTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank" }
|
||||
|
||||
AtreidesStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
CorrinoInfantryTypes = { "light_inf", "trooper", "sardaukar" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[AtreidesMain] = {}
|
||||
Defending[AtreidesSmall] = {}
|
||||
Defending[Corrino] = {}
|
||||
-- this is also first attack timing
|
||||
AttackDelay[AtreidesMain] = 10000
|
||||
AttackDelay[AtreidesSmall] = 8000
|
||||
AttackDelay[Corrino] = 7000
|
||||
TimeBetweenAttacks[AtreidesMain] = 12000
|
||||
TimeBetweenAttacks[AtreidesSmall] = 5000
|
||||
TimeBetweenAttacks[Corrino] = 11000
|
||||
HarvesterCount[AtreidesMain] = 2
|
||||
HarvesterCount[AtreidesSmall] = 2
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(AtreidesSmallBase, function()
|
||||
TimeBetweenAttacks[AtreidesMain] = 0
|
||||
end)
|
||||
|
||||
PatrolPoints[AtreidesMain] = {AtreidesPoint1.Location, AtreidesPoint2.Location, AtreidesPoint3.Location }
|
||||
PatrolPoints[AtreidesSmall] = {AtreidesPoint4.Location, AtreidesPoint5.Location, AtreidesPoint6.Location }
|
||||
DefencePerimeter[AtreidesMain] = Utils.Concat( GetCellsInRectangle(CPos.New(73,9), CPos.New(88,26)), GetCellsInRectangle(CPos.New(65,44), CPos.New(82,56)))
|
||||
DefencePerimeter[AtreidesSmall] = GetCellsInRectangle(CPos.New(5,18), CPos.New(16,32))
|
||||
DefencePerimeter[Corrino] = GetCellsInRectangle(CPos.New(89,27), CPos.New(95,35))
|
||||
|
||||
IdlingUnits[AtreidesMain] = Utils.Concat(Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[Difficulty][1], InitialAtreidesPaths[1]), Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[Difficulty][2], InitialAtreidesPaths[2]))
|
||||
IdlingUnits[AtreidesSmall] = Reinforcements.Reinforce(AtreidesSmall, InitialAtreidesReinforcements[Difficulty][1], InitialAtreidesPaths[3])
|
||||
IdlingUnits[Corrino] = Reinforcements.Reinforce(Corrino, InitialCorrinoReinforcements, InitialCorrinoPath)
|
||||
@@ -45,23 +100,77 @@ ActivateAI = function()
|
||||
DefendAndRepairBase(AtreidesSmall, AtreidesSmallBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(Corrino, CorrinoBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
|
||||
else
|
||||
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local infantryToBuildAtreides = function() return { Utils.Random(AtreidesInfantryTypes) } end
|
||||
local infantryToBuildCorrino = function() return { Utils.Random(CorrinoInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local tanksToBuildMain = function() return { Utils.Random(AtreidesMainTankTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local tanksToBuildMain = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(AtreidesMainTankTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(AtreidesMainTankTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
local tanksToBuildSmall = function() return { Utils.Random(AtreidesSmallTankTypes) } end
|
||||
local unitsToBuy = function() return { Utils.Random(AtreidesStarportTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
local attackThresholdSize = {}
|
||||
attackThresholdSize[AtreidesMain] = AttackGroupSize[Difficulty] * 3
|
||||
attackThresholdSize[AtreidesSmall] = AttackGroupSize[Difficulty] * 2
|
||||
|
||||
Trigger.AfterDelay(InitialProductionDelay[Difficulty], function()
|
||||
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildMain, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
|
||||
ProduceUnits(AtreidesSmall, ABarracks, delay, infantryToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildSmall, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
|
||||
ProduceUnits(Corrino, CBarracks, delay, infantryToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function()
|
||||
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
|
||||
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildMain, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
|
||||
ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall"][Difficulty], function()
|
||||
ProduceUnits(AtreidesSmall, ABarracks, delay, infantryToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesSmall])
|
||||
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildSmall, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesSmall])
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(InitialProductionDelay["Corrino"][Difficulty], function()
|
||||
ProduceUnits(Corrino, CBarracks, delay, infantryToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesSmall])
|
||||
end)
|
||||
|
||||
if Difficulty == "normal" then
|
||||
AtreidesMain.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
AtreidesMain.GrantCondition("defense-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuildAtreides,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuildMain
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(AtreidesMain, function(p, building)
|
||||
table.insert(AtreidesMainBase, building)
|
||||
DefendAndRepairBase(AtreidesMain, {building}, 0.5, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(AtreidesMain, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
|
||||
end)
|
||||
|
||||
Trigger.OnBuildingPlaced(AtreidesSmall, function(p, building)
|
||||
table.insert(AtreidesSmallBase, building)
|
||||
DefendAndRepairBase(AtreidesSmall, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(AtreidesSmall, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[AtreidesSmall])
|
||||
end)
|
||||
|
||||
ActivateCrushLogic()
|
||||
end
|
||||
|
||||
@@ -8,9 +8,13 @@
|
||||
]]
|
||||
|
||||
AtreidesMainBase = { AConYard1, AOutpost1, ARefinery1, ARefinery2, AHeavyFactory1, ALightFactory1, ALightFactory2, AHiTechFactory, AResearch, ARepair, AStarport, AGunt1, AGunt2, AGunt3, AGunt4, AGunt5, AGunt6, ARock1, ARock2, ARock3, ARock4, ARock5, ARock6, APower1, APower2, APower3, APower4, APower5, APower6, APower7, APower8, APower9, APower10, APower11, APower12, APower13, APower14, APower15, APower16, APower17, APower18, APower19, APower20, APower21, APower22, ASilo1, ASilo2, ASilo3 }
|
||||
|
||||
AtreidesSmallBase = { AOutpost2, ARefinery3, ABarracks, AHeavyFactory2, AGunt7, AGunt8, APower23, APower24, APower25, APower26, ASilo4, ASilo5, ASilo6, ASilo7 }
|
||||
|
||||
CorrinoBase = { CBarracks, COutpost, CPower1, CPower2, CPower3, CRock1, CRock2 }
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(7)
|
||||
|
||||
AtreidesReinforcements =
|
||||
{
|
||||
easy = { "sonic_tank" },
|
||||
@@ -41,16 +45,16 @@ CorrinoReinforcements =
|
||||
|
||||
EnemyAttackDelay =
|
||||
{
|
||||
easy = DateTime.Minutes(3) + DateTime.Seconds(30),
|
||||
normal = DateTime.Minutes(2) + DateTime.Seconds(30),
|
||||
hard = DateTime.Minutes(1) + DateTime.Seconds(30)
|
||||
easy = 7000 ,
|
||||
normal = 6500 ,
|
||||
hard = 6000
|
||||
}
|
||||
|
||||
CorrinoInitialAttackDelay =
|
||||
{
|
||||
easy = DateTime.Seconds(45),
|
||||
normal = DateTime.Seconds(30),
|
||||
hard = DateTime.Seconds(15)
|
||||
easy = DateTime.Minutes(4) ,
|
||||
normal = DateTime.Minutes(3) ,
|
||||
hard = DateTime.Minutes(2)
|
||||
}
|
||||
|
||||
InitialAtreidesReinforcements =
|
||||
@@ -112,8 +116,8 @@ HarkonnenReinforcements =
|
||||
|
||||
hard =
|
||||
{
|
||||
{ "trooper", "trooper", "light_inf", "light_inf", "light_inf" },
|
||||
{ "quad", "trike", "trike", "combat_tank_h", "combat_tank_h" }
|
||||
{ "trooper", "trooper", "light_inf", "light_inf", "light_inf", "light_inf" },
|
||||
{ "quad", "trike", "trike", "combat_tank_h", "combat_tank_h", "siege_tank" }
|
||||
},
|
||||
}
|
||||
|
||||
@@ -147,8 +151,32 @@ SendEnemyReinforcements = function(player, delay, path, unitTypes, customConditi
|
||||
end)
|
||||
end
|
||||
|
||||
SendAirStrike = function()
|
||||
if HiTechIsDead then
|
||||
AirStrikeTimer = 7500
|
||||
AirStrikeChargeTime = 7500
|
||||
AirstrikeLogic = function(airstrikeProvider)
|
||||
if airstrikeProvider.IsDead then
|
||||
return
|
||||
end
|
||||
|
||||
if DateTime.GameTime <= AirStrikeTimer then
|
||||
Trigger.AfterDelay(AirStrikeTimer - DateTime.GameTime + 1, function()
|
||||
AirstrikeLogic(airstrikeProvider)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
-- randomly choose if wait again or strike. During waiting Airstrike can still be used by DefensiveAirStrike
|
||||
if Utils.RandomInteger(1, 100) < 30 then
|
||||
Trigger.AfterDelay(1000, function() AirstrikeLogic(airstrikeProvider)end)
|
||||
else
|
||||
AirStrikeVSBuilding(airstrikeProvider)
|
||||
Trigger.AfterDelay(7500, function() AirstrikeLogic(airstrikeProvider) end)
|
||||
IsAirstrikeReady = false
|
||||
end
|
||||
end
|
||||
|
||||
AirStrikeVSBuilding = function(airstrikeProvider)
|
||||
if airstrikeProvider.IsDead or DateTime.GameTime < AirStrikeTimer then
|
||||
return
|
||||
end
|
||||
|
||||
@@ -163,10 +191,32 @@ SendAirStrike = function()
|
||||
end)
|
||||
|
||||
if #targets > 0 then
|
||||
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition)
|
||||
airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
|
||||
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
|
||||
end
|
||||
end
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
|
||||
DefensiveAirStrike = function(airstrikeProvider, possibleTargets)
|
||||
if airstrikeProvider.IsDead or DateTime.GameTime <= AirStrikeTimer then return end
|
||||
local bestValue = {}
|
||||
local bestIndex = 1
|
||||
for i = 1, #possibleTargets, 1 do
|
||||
local ActorsInCircle = Map.ActorsInCircle(possibleTargets[i].CenterPosition, WDist.FromCells(4), function(a)
|
||||
return
|
||||
a.Owner == Harkonnen
|
||||
and not a.IsDead
|
||||
and a.HasProperty("Attack")
|
||||
end)
|
||||
bestValue[i] = 0
|
||||
Utils.Do(ActorsInCircle, function(a)
|
||||
bestValue[i] = bestValue[i] + Actor.Cost(a.Type)
|
||||
end)
|
||||
if bestValue[i] > bestValue[bestIndex] then
|
||||
bestIndex = i
|
||||
end
|
||||
end
|
||||
airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
|
||||
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
|
||||
end
|
||||
|
||||
Tick = function()
|
||||
@@ -195,12 +245,12 @@ Tick = function()
|
||||
HiTechIsDead = true
|
||||
end
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[OrdosMain] then
|
||||
local units = OrdosMain.GetActorsByType("harvester")
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
|
||||
local units = AtreidesMain.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[OrdosMain] = false
|
||||
ProtectHarvester(units[1], OrdosMain, AttackGroupSize[Difficulty])
|
||||
LastHarvesterEaten[AtreidesMain] = false
|
||||
ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -212,15 +262,40 @@ Tick = function()
|
||||
ProtectHarvester(units[1], OrdosSmall, AttackGroupSize[Difficulty])
|
||||
end
|
||||
end
|
||||
|
||||
if IdlingUnits[AtreidesMain] == nil then return end
|
||||
end
|
||||
|
||||
EmergencyBehaviour = function(player, target)
|
||||
if HiTechIsDead or not IsAirstrikeReady or player == Corrino then return end
|
||||
|
||||
local targets = {}
|
||||
if player == AtreidesMain then
|
||||
targets = Map.ActorsInBox(Map.CenterOfCell(CPos.New(73,9)), Map.CenterOfCell(CPos.New(88,26)))
|
||||
else
|
||||
targets = Map.ActorsInBox(Map.CenterOfCell(CPos.New(5,18)), Map.CenterOfCell(CPos.New(16,32)))
|
||||
end
|
||||
|
||||
targets = Utils.Where(targets, function(a)
|
||||
return a.Owner == Harkonnen
|
||||
and not a.IsDead
|
||||
and a.HasProperty("Attack")
|
||||
end)
|
||||
|
||||
if targets[1] == nil then return end
|
||||
DefensiveAirStrike(AHiTechFactory, targets)
|
||||
end
|
||||
|
||||
WorldLoaded = function()
|
||||
AtreidesMain = Player.GetPlayer("Atreides Main Base")
|
||||
AtreidesSmall = Player.GetPlayer("Atreides Small Base")
|
||||
Corrino = Player.GetPlayer("Corrino")
|
||||
AtreidesMain.Cash = 5000
|
||||
AtreidesSmall.Cash = 5000
|
||||
Corrino.Cash = 5000
|
||||
Harkonnen = Player.GetPlayer("Harkonnen")
|
||||
|
||||
InitObjectives(Harkonnen)
|
||||
|
||||
CaptureAtreidesConYard = AddPrimaryObjective(Harkonnen, "capture-atreides-construction-yard-south")
|
||||
KillAtreides = AddPrimaryObjective(Harkonnen, "destroy-atreides")
|
||||
KillCorrino = AddPrimaryObjective(Harkonnen, "destroy-corrino")
|
||||
@@ -232,8 +307,7 @@ WorldLoaded = function()
|
||||
|
||||
Camera.Position = HEngineer.CenterPosition
|
||||
AtreidesAttackLocation = AConYard2.Location
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
|
||||
Trigger.AfterDelay(EarlyGameStage,function() AirstrikeLogic(AHiTechFactory) end)
|
||||
|
||||
Trigger.OnCapture(AConYard2, function()
|
||||
Harkonnen.MarkCompletedObjective(CaptureAtreidesConYard)
|
||||
@@ -257,7 +331,9 @@ WorldLoaded = function()
|
||||
unit.AttackMove(AtreidesAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
|
||||
SendEnemyReinforcements(AtreidesMain, EnemyAttackDelay[Difficulty], AtreidesPath, AtreidesReinforcements[Difficulty], atreidesWaveCondition, huntFunction)
|
||||
|
||||
Trigger.AfterDelay(CorrinoInitialAttackDelay[Difficulty], function()
|
||||
SendEnemyReinforcements(Corrino, EnemyAttackDelay[Difficulty], CorrinoPaths[1], CorrinoReinforcements[Difficulty][1], corrinoWaveCondition, huntFunction)
|
||||
SendEnemyReinforcements(Corrino, EnemyAttackDelay[Difficulty], CorrinoPaths[2], CorrinoReinforcements[Difficulty][2], corrinoWaveCondition, huntFunction)
|
||||
@@ -273,4 +349,14 @@ WorldLoaded = function()
|
||||
|
||||
SendHarkonnenReinforcements(1)
|
||||
SendHarkonnenReinforcements(2)
|
||||
|
||||
Trigger.AfterDelay(7000, function()
|
||||
SendHarkonnenReinforcements(1)
|
||||
end)
|
||||
|
||||
Trigger.OnRemovedFromWorld(Crate1, function()
|
||||
VisionPoint.GrantCondition("activate", 100)
|
||||
Media.PlaySound("MULTI1.WAV")
|
||||
Camera.Position = VisionPoint.CenterPosition
|
||||
end)
|
||||
end
|
||||
|
||||
Binary file not shown.
@@ -298,6 +298,7 @@ Actors:
|
||||
AGunt1: medium_gun_turret
|
||||
Location: 80,27
|
||||
Owner: Atreides Main Base
|
||||
TurretFacing: 512
|
||||
Actor77: wall
|
||||
Location: 81,27
|
||||
Owner: Atreides Main Base
|
||||
@@ -769,6 +770,33 @@ Actors:
|
||||
AtreidesEntry2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 2,27
|
||||
AtreidesPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 72,13
|
||||
AtreidesPoint3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 55,53
|
||||
AtreidesPoint4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 24,33
|
||||
AtreidesPoint5: waypoint
|
||||
Owner: Neutral
|
||||
Location: 28,55
|
||||
AtreidesPoint6: waypoint
|
||||
Owner: Neutral
|
||||
Location: 33,9
|
||||
VisionPoint: vision_provider
|
||||
Owner: Harkonnen
|
||||
Location: 64,64
|
||||
Crate1: crate_script
|
||||
Owner: Harkonnen
|
||||
Location: 57,62
|
||||
AtreidesPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 54,6
|
||||
Actor7: crate
|
||||
Owner: Neutral
|
||||
Location: 49,9
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,79 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 6000
|
||||
DefaultCash: 7000
|
||||
ExternalCondition@AIMain:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIMainWithDefense:
|
||||
Condition: defense-rebuilder
|
||||
BaseBuilderBotModule@MainBase:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
starport: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
BaseBuilderBotModule@MainBaseWithDefence:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
PlaceDefenseTowardsEnemyChance: 50
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
medium_gun_turret: 4
|
||||
large_gun_turret: 4
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
starport: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
medium_gun_turret: 1
|
||||
large_gun_turret: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -7,6 +7,31 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(7)
|
||||
|
||||
InitialProductionDelay = {
|
||||
Ordos =
|
||||
{
|
||||
easy = DateTime.Seconds(150),
|
||||
normal = DateTime.Seconds(120),
|
||||
hard = DateTime.Seconds(60)
|
||||
},
|
||||
|
||||
AtreidesEnemy =
|
||||
{
|
||||
easy = DateTime.Seconds(180),
|
||||
normal = DateTime.Seconds(120),
|
||||
hard = DateTime.Seconds(60)
|
||||
},
|
||||
|
||||
MercenaryEnemy =
|
||||
{
|
||||
easy = DateTime.Seconds(160),
|
||||
normal = DateTime.Seconds(80),
|
||||
hard = DateTime.Seconds(30)
|
||||
}
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,7 +39,14 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
EarlyProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(10), DateTime.Seconds(13) },
|
||||
normal = { DateTime.Seconds(6), DateTime.Seconds(8) },
|
||||
hard = { DateTime.Seconds(3), DateTime.Seconds(5) }
|
||||
}
|
||||
|
||||
LateProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -24,16 +56,61 @@ AttackDelays =
|
||||
EnemyInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
|
||||
|
||||
OrdosVehicleTypes = { "raider", "raider", "quad" }
|
||||
OrdosTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank", "deviator" }
|
||||
OrdosStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
OrdosTankTypes =
|
||||
{
|
||||
EarlyGame = { "combat_tank_o", "combat_tank_o", "siege_tank"},
|
||||
LateGame = { "combat_tank_o", "combat_tank_o", "siege_tank", "deviator" }
|
||||
}
|
||||
|
||||
OrdosStarportTypes =
|
||||
{
|
||||
EarlyGame = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport" },
|
||||
LateGame = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
}
|
||||
|
||||
AtreidesVehicleTypes = { "trike", "trike", "quad" }
|
||||
AtreidesTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank" }
|
||||
AtreidesStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
AtreidesTankTypes =
|
||||
{
|
||||
EarlyGame = { "combat_tank_a" },
|
||||
LateGame = { "combat_tank_a", "combat_tank_a", "siege_tank" }
|
||||
}
|
||||
|
||||
AtreidesStarportTypes =
|
||||
{
|
||||
EarlyGame ={ "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport" },
|
||||
LateGame ={ "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
}
|
||||
|
||||
MercenaryTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Ordos] = {}
|
||||
Defending[AtreidesEnemy] = {}
|
||||
Defending[AtreidesNeutral] = {}
|
||||
Defending[MercenaryEnemy] = {}
|
||||
Defending[MercenaryAlly] = {}
|
||||
-- this is also first attack timing
|
||||
AttackDelay[Ordos] = 16000
|
||||
AttackDelay[AtreidesEnemy] = 10000
|
||||
AttackDelay[MercenaryEnemy] = 7000
|
||||
TimeBetweenAttacks[Ordos] = 8000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[AtreidesEnemy] = 7000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[MercenaryEnemy] = 7000 * DifficultyModifier[Difficulty]
|
||||
HarvesterCount[Ordos] = 4
|
||||
HarvesterCount[AtreidesEnemy] = 4
|
||||
HarvesterCount[AtreidesNeutral] = 0
|
||||
HarvesterCount[MercenaryEnemy] = 0
|
||||
HarvesterCount[MercenaryAlly] = 0
|
||||
PatrolPoints[Ordos] = {OrdosPatrolPoint1.Location, OrdosPatrolPoint2.Location, OrdosPatrolPoint3.Location, OrdosPatrolPoint4.Location }
|
||||
PatrolPoints[AtreidesEnemy] = {AtreidesPatrolPoint1.Location, AtreidesPatrolPoint2.Location, OrdosPatrolPoint3.Location }
|
||||
DefencePerimeter[Ordos] = GetCellsInRectangle(CPos.New(39,36), CPos.New(71,54))
|
||||
DefencePerimeter[AtreidesEnemy] = Utils.Concat(GetCellsInRectangle(CPos.New(3,3), CPos.New(17,20)), GetCellsInRectangle(CPos.New(18,3), CPos.New(31,9)))
|
||||
DefencePerimeter[MercenaryEnemy] = GetCellsInRectangle(CPos.New(29,64), CPos.New(40,71))
|
||||
DefencePerimeter[MercenaryAlly] = DefencePerimeter[MercenaryEnemy]
|
||||
DefencePerimeter[AtreidesNeutral] = DefencePerimeter[AtreidesEnemy]
|
||||
|
||||
IdlingUnits[Ordos] = Utils.Concat(Reinforcements.Reinforce(Ordos, InitialOrdosReinforcements[1], InitialOrdosPaths[1]), Reinforcements.Reinforce(Ordos, InitialOrdosReinforcements[2], InitialOrdosPaths[2]))
|
||||
IdlingUnits[AtreidesEnemy] = Reinforcements.Reinforce(AtreidesEnemy, InitialAtreidesReinforcements, InitialAtreidesPath)
|
||||
IdlingUnits[AtreidesNeutral] = { }
|
||||
@@ -44,26 +121,112 @@ ActivateAI = function()
|
||||
DefendAndRepairBase(AtreidesEnemy, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(MercenaryEnemy, MercenaryBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
|
||||
else
|
||||
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
|
||||
local vehilcesToBuildOrdos = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local vehilcesToBuildAtreides = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
local tanksToBuildOrdos = function() return { Utils.Random(OrdosTankTypes) } end
|
||||
local tanksToBuildAtreides = function() return { Utils.Random(AtreidesTankTypes) } end
|
||||
local vehiclesToBuildOrdos = function() return { Utils.Random(OrdosVehicleTypes) } end
|
||||
local vehiclesToBuildAtreides = function() return { Utils.Random(AtreidesVehicleTypes) } end
|
||||
|
||||
local tanksToBuildOrdos = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(OrdosTankTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(OrdosTankTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
local tanksToBuildAtreides = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(AtreidesTankTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(AtreidesTankTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
local tanksToBuildMercenary = function() return { Utils.Random(MercenaryTankTypes) } end
|
||||
local unitsToBuyOrdos = function() return { Utils.Random(OrdosStarportTypes) } end
|
||||
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end
|
||||
local unitsToBuyOrdos = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(OrdosStarportTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(OrdosStarportTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
local unitsToBuyAtreides = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(AtreidesStarportTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(AtreidesStarportTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
ProduceUnits(Ordos, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Ordos, OLightFactory, delay, vehilcesToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Ordos, OHeavyFactory, delay, tanksToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Ordos, OStarport, delay, unitsToBuyOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["Ordos"][Difficulty], function ()
|
||||
ProduceUnits(Ordos, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Ordos, OLightFactory, delay, vehiclesToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Ordos, OHeavyFactory, delay, tanksToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Ordos, OStarport, delay, unitsToBuyOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ProduceUnits(AtreidesEnemy, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesEnemy, ALightFactory, delay, vehilcesToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesEnemy, AHeavyFactory, delay, tanksToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesEnemy, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesEnemy"][Difficulty], function ()
|
||||
ProduceUnits(AtreidesEnemy, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesEnemy, ALightFactory, delay, vehiclesToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesEnemy, AHeavyFactory, delay, tanksToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesEnemy, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ProduceUnits(MercenaryEnemy, MHeavyFactory, delay, tanksToBuildMercenary, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesEnemy"][Difficulty], function ()
|
||||
ProduceUnits(MercenaryEnemy, MHeavyFactory, delay, tanksToBuildMercenary, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ActivateCrushLogic()
|
||||
|
||||
if Difficulty == "normal" then
|
||||
Ordos.GrantCondition("base-rebuilder")
|
||||
AtreidesEnemy.GrantCondition("base-rebuilder2")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
Ordos.GrantCondition("defense-rebuilder")
|
||||
AtreidesEnemy.GrantCondition("defense-rebuilder2")
|
||||
end
|
||||
|
||||
local productionTypesAtreidis =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuildAtreides,
|
||||
heavy_factory = tanksToBuildAtreides
|
||||
}
|
||||
|
||||
local productionTypesOrdos =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuildOrdos,
|
||||
heavy_factory = tanksToBuildOrdos
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Ordos, function(p, building)
|
||||
table.insert(OrdosBase, building)
|
||||
DefendAndRepairBase(Ordos, {building}, 0.5, AttackGroupSize[Difficulty] )
|
||||
if productionTypesOrdos[building.Type] == nil then return end
|
||||
ProduceUnits(Ordos, building, delay, productionTypesOrdos[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
Trigger.OnBuildingPlaced(AtreidesEnemy, function(p, building)
|
||||
table.insert(AtreidesBase, building)
|
||||
DefendAndRepairBase(AtreidesEnemy, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypesAtreidis[building.Type] == nil then return end
|
||||
ProduceUnits(AtreidesEnemy, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
]]
|
||||
|
||||
OrdosBase = { OConYard, OOutpost, OPalace, ORefinery1, ORefinery2, OHeavyFactory, OLightFactory, OHiTechFactory, OResearch, ORepair, OStarport, OGunt1, OGunt2, OGunt3, OGunt4, OGunt5, OGunt6, ORock1, ORock2, ORock3, ORock4, OBarracks1, OBarracks2, OPower1, OPower2, OPower3, OPower4, OPower5, OPower6, OPower7, OPower8, OPower9, OPower10, OPower11, OPower12, OPower13 }
|
||||
AtreidesBase = { AConYard, AOutpost, ARefinery1, ARefinery2, AHeavyFactory, ALightFactory, AHiTechFactory, ARepair, AStarport, AGunt1, AGunt2, ARock1, ARock2, APower1, APower2, APower3, APower4, APower5, APower6, APower7, APower8, APower9 }
|
||||
|
||||
AtreidesBase = { AConYard,ABarracks1, ABarracks2, AOutpost, ARefinery1, ARefinery2, AHeavyFactory, ALightFactory, AHiTechFactory, ARepair, AStarport, AGunt1, AGunt2, ARock1, ARock2, APower1, APower2, APower3, APower4, APower5, APower6, APower7, APower8, APower9 }
|
||||
|
||||
MercenaryBase = { MHeavyFactory, MStarport, MGunt, MPower1, MPower2 }
|
||||
|
||||
OrdosReinforcements =
|
||||
@@ -56,7 +58,7 @@ OrdosAttackDelay =
|
||||
hard = DateTime.Minutes(1)
|
||||
}
|
||||
|
||||
MercenaryStarportDelay = DateTime.Minutes(1) + DateTime.Seconds(20)
|
||||
MercenaryStarportDelay = 4970
|
||||
|
||||
OrdosAttackWaves =
|
||||
{
|
||||
@@ -92,7 +94,9 @@ InitialOrdosPaths =
|
||||
SaboteurPaths =
|
||||
{
|
||||
{ SaboteurWaypoint1.Location, SaboteurWaypoint2.Location, SaboteurWaypoint3.Location },
|
||||
{ SaboteurWaypoint4.Location, SaboteurWaypoint5.Location, SaboteurWaypoint6.Location }
|
||||
{ SaboteurWaypoint4.Location, SaboteurWaypoint5.Location, SaboteurWaypoint6.Location },
|
||||
{ SaboteurWaypoint1.Location, OrdosPatrolPoint2.Location, OrdosRally1.Location, SaboteurWaypoint6.Location },
|
||||
{ OrdosRally4.Location, OrdosPatrolPoint3.Location, OrdosPatrolPoint2.Location}
|
||||
}
|
||||
|
||||
InitialAtreidesPath = { AStarport.Location, AtreidesRally.Location }
|
||||
@@ -117,14 +121,36 @@ SendStarportReinforcements = function(faction)
|
||||
end)
|
||||
end
|
||||
|
||||
SendAirStrike = function()
|
||||
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesEnemy then
|
||||
AirStrikeTimer = 7500
|
||||
AirStrikeChargeTime = 7500
|
||||
AirstrikeLogic = function(airstrikeProvider)
|
||||
if airstrikeProvider.IsDead then
|
||||
return
|
||||
end
|
||||
if DateTime.GameTime <= AirStrikeTimer then
|
||||
Trigger.AfterDelay(AirStrikeTimer - DateTime.GameTime + 1, function()
|
||||
AirstrikeLogic(airstrikeProvider)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
-- randomly choose if wait again or strike. During waiting Airstrike can still be used by DefensiveAirStrike
|
||||
if Utils.RandomInteger(1, 100) < 30 then
|
||||
Trigger.AfterDelay(1000, function() AirstrikeLogic(airstrikeProvider)end)
|
||||
else
|
||||
AirStrikeVSBuilding(airstrikeProvider)
|
||||
Trigger.AfterDelay(7500, function() AirstrikeLogic(airstrikeProvider) end)
|
||||
IsAirstrikeReady = false
|
||||
end
|
||||
end
|
||||
|
||||
AirStrikeVSBuilding = function(airstrikeProvider)
|
||||
if airstrikeProvider.IsDead or DateTime.GameTime < AirStrikeTimer then
|
||||
return
|
||||
end
|
||||
|
||||
local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
|
||||
return
|
||||
actor.HasProperty("Sell") and
|
||||
return actor.HasProperty("Sell") and
|
||||
actor.Type ~= "wall" and
|
||||
actor.Type ~= "medium_gun_turret" and
|
||||
actor.Type ~= "large_gun_turret" and
|
||||
@@ -133,16 +159,40 @@ SendAirStrike = function()
|
||||
end)
|
||||
|
||||
if #targets > 0 then
|
||||
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition)
|
||||
airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
|
||||
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
|
||||
end
|
||||
end
|
||||
|
||||
DefensiveAirStrike = function(airstrikeProvider, possibleTargets)
|
||||
if airstrikeProvider.IsDead or DateTime.GameTime <= AirStrikeTimer then return end
|
||||
local bestValue = {}
|
||||
local bestIndex = 1
|
||||
for i = 1, #possibleTargets, 1 do
|
||||
local ActorsInCircle = Map.ActorsInCircle(possibleTargets[i].CenterPosition, WDist.FromCells(4), function(a)
|
||||
return
|
||||
a.Owner == Harkonnen
|
||||
and not a.IsDead
|
||||
and a.HasProperty("Attack")
|
||||
end)
|
||||
|
||||
bestValue[i] = 0
|
||||
Utils.Do(ActorsInCircle, function(a)
|
||||
bestValue[i] = bestValue[i] + Actor.Cost(a.Type)
|
||||
end)
|
||||
|
||||
if bestValue[i] > bestValue[bestIndex] then
|
||||
bestIndex = i
|
||||
end
|
||||
end
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
|
||||
airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
|
||||
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
|
||||
end
|
||||
|
||||
GetSaboteurTargets = function(player)
|
||||
return Utils.Where(player.GetActors(), function(actor)
|
||||
return
|
||||
actor.HasProperty("Sell") and
|
||||
return actor.HasProperty("Sell") and
|
||||
actor.Type ~= "wall" and
|
||||
actor.Type ~= "medium_gun_turret" and
|
||||
actor.Type ~= "large_gun_turret" and
|
||||
@@ -162,14 +212,54 @@ BuildSaboteur = function()
|
||||
saboteur.Wait(DateTime.Seconds(5))
|
||||
|
||||
local path = Utils.Random(SaboteurPaths)
|
||||
saboteur.Move(path[1])
|
||||
saboteur.Move(path[2])
|
||||
saboteur.Move(path[3])
|
||||
Utils.Do(path, function(waypoint)
|
||||
saboteur.Move(waypoint)
|
||||
end)
|
||||
|
||||
SendSaboteur(saboteur)
|
||||
ScanForBetterTargets(saboteur)
|
||||
end
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(30), BuildSaboteur)
|
||||
Trigger.AfterDelay(DateTime.Minutes(5) + DateTime.Seconds(30), BuildSaboteur)
|
||||
end
|
||||
|
||||
DemolishType = { "harvester", "mcv", "siege_tank", "missile_tank", "sonic_tank", "devastator", "deviator", "combat_tank_a", "combat_tank_h", "combat_tank_o"}
|
||||
|
||||
ScanForBetterTargets = function(saboteur)
|
||||
if saboteur.IsDead or not saboteur.IsInWorld then return end
|
||||
|
||||
local possibleTargets = Map.ActorsInCircle(saboteur.CenterPosition, WDist.FromCells(6), function(a)
|
||||
return not saboteur.Owner.IsAlliedWith(a.Owner) and
|
||||
Utils.Any(DemolishType, function(d) return d == a.Type end)
|
||||
end)
|
||||
|
||||
if possibleTargets[1] == nil then
|
||||
Trigger.AfterDelay(200, function()
|
||||
ScanForBetterTargets(saboteur)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
-- filter out targets where infantry is nearby
|
||||
for index = #possibleTargets, 1, -1 do
|
||||
local infantryunits = Map.ActorsInCircle(possibleTargets[index].CenterPosition, WDist.New(1536), function(u) return u.Type == "light_inf" or u.Type == "trooper" end)
|
||||
if infantryunits[1] ~= nil then
|
||||
table.remove(possibleTargets, index)
|
||||
end
|
||||
end
|
||||
|
||||
if possibleTargets[1] ~= nil then
|
||||
saboteur.Stop()
|
||||
local dfd = Utils.Random(possibleTargets)
|
||||
saboteur.Demolish(dfd)
|
||||
saboteur.CallFunc(function()
|
||||
ScanForBetterTargets(saboteur)
|
||||
end)
|
||||
else
|
||||
Trigger.AfterDelay(200, function()
|
||||
ScanForBetterTargets(saboteur)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
SendSaboteur = function(saboteur)
|
||||
@@ -216,6 +306,21 @@ ChangeOwner = function(old_owner, new_owner)
|
||||
end)
|
||||
end
|
||||
|
||||
EmergencyBehaviour = function(player, target)
|
||||
HoldProduction[player] = false
|
||||
if player == Ordos and not AtreidesEnemy.HasNoRequiredUnits() then
|
||||
if AHiTechFactory.IsDead then return end
|
||||
local enemyunits = Map.ActorsInCircle(Map.CenterOfCell(target), WDist.FromCells(15), function(a)
|
||||
return a.Owner == Harkonnen
|
||||
and not a.IsDead
|
||||
and a.HasProperty("Attack")
|
||||
end)
|
||||
|
||||
if enemyunits[1] == nil then return end
|
||||
DefensiveAirStrike(AHiTechFactory, enemyunits)
|
||||
end
|
||||
end
|
||||
|
||||
Tick = function()
|
||||
if Harkonnen.HasNoRequiredUnits() then
|
||||
Ordos.MarkCompletedObjective(KillHarkonnen1)
|
||||
@@ -239,7 +344,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Ordos] then
|
||||
local units = Ordos.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[Ordos] = false
|
||||
ProtectHarvester(units[1], Ordos, AttackGroupSize[Difficulty])
|
||||
@@ -248,7 +352,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesEnemy] then
|
||||
local units = AtreidesEnemy.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[AtreidesEnemy] = false
|
||||
ProtectHarvester(units[1], AtreidesEnemy, AttackGroupSize[Difficulty])
|
||||
@@ -275,8 +378,8 @@ WorldLoaded = function()
|
||||
OrdosAttackLocation = HMCV.Location
|
||||
MercenaryAttackLocation = HMCV.Location
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
|
||||
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(30), BuildSaboteur)
|
||||
Trigger.AfterDelay(EarlyGameStage, function() AirstrikeLogic(AHiTechFactory) end)
|
||||
Trigger.AfterDelay(EarlyGameStage, BuildSaboteur)
|
||||
|
||||
Trigger.OnCapture(MHeavyFactory, function()
|
||||
Harkonnen.MarkCompletedObjective(AllyWithMercenaries)
|
||||
@@ -296,7 +399,7 @@ WorldLoaded = function()
|
||||
end)
|
||||
|
||||
Trigger.OnKilledOrCaptured(OPalace, function()
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("cannot-stand-harkonnen-must-become-neutral"), UserInterface.GetFluentMessage("atreides-commander"))
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("cannot-stand-harkonnen-must-become-neutral"), UserInterface.GetFluentMessage("atreides-commander"), HSLColor.FromHex("5A7394"))
|
||||
|
||||
ChangeOwner(AtreidesEnemy, AtreidesNeutral)
|
||||
DefendAndRepairBase(AtreidesNeutral, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
|
||||
@@ -328,8 +431,8 @@ WorldLoaded = function()
|
||||
unit.AttackMove(OrdosAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
SendCarryallReinforcements(Ordos, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
|
||||
SendCarryallReinforcements(Ordos, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
SendStarportReinforcements(MercenaryEnemy)
|
||||
|
||||
Actor.Create("upgrade.barracks", true, { Owner = Ordos })
|
||||
|
||||
@@ -643,15 +643,33 @@ Actors:
|
||||
SaboteurWaypoint4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 18,59
|
||||
SaboteurWaypoint5: waypoint
|
||||
Owner: Neutral
|
||||
Location: 31,91
|
||||
SaboteurWaypoint6: waypoint
|
||||
Owner: Neutral
|
||||
Location: 64,91
|
||||
MercenaryAttackPoint: waypoint
|
||||
Owner: Neutral
|
||||
Location: 53,38
|
||||
OrdosPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 78,45
|
||||
OrdosPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 55,63
|
||||
OrdosPatrolPoint3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 30,54
|
||||
OrdosPatrolPoint4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 73,21
|
||||
AtreidesPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 14,65
|
||||
AtreidesPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 48,10
|
||||
SaboteurWaypoint5: waypoint
|
||||
Owner: Neutral
|
||||
Location: 31,81
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,150 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 7000
|
||||
ExternalCondition@AIOrdos:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIOrdosDefense:
|
||||
Condition: defense-rebuilder
|
||||
ExternalCondition@AIAtreides:
|
||||
Condition: base-rebuilder2
|
||||
ExternalCondition@AIAtreidesDefense:
|
||||
Condition: defense-rebuilder2
|
||||
BaseBuilderBotModule@Ordos:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 2
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
wind_trap: 12
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 2
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@OrdosDefnse:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 2
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 12
|
||||
silo: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
medium_gun_turret: 8
|
||||
large_gun_turret: 4
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
medium_gun_turret: 6
|
||||
large_gun_turret: 4
|
||||
BaseBuilderBotModule@Atreides:
|
||||
RequiresCondition: base-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 2
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
wind_trap: 12
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@AtreidesDefense:
|
||||
RequiresCondition: defense-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 2
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 9
|
||||
silo: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
medium_gun_turret: 6
|
||||
large_gun_turret: 6
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
starport: 1
|
||||
medium_gun_turret: 1
|
||||
large_gun_turret: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(10)
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,26 +16,117 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
EarlyProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
hard = { DateTime.Seconds(1), DateTime.Seconds(3) }
|
||||
|
||||
easy = { DateTime.Seconds(12), DateTime.Seconds(15) },
|
||||
normal = { DateTime.Seconds(10), DateTime.Seconds(13) },
|
||||
hard = { DateTime.Seconds(9), DateTime.Seconds(10) }
|
||||
}
|
||||
|
||||
LateProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(5), DateTime.Seconds(8) },
|
||||
normal = { DateTime.Seconds(3), DateTime.Seconds(6) },
|
||||
hard = { DateTime.Seconds(2), DateTime.Seconds(4) }
|
||||
}
|
||||
|
||||
InitialProductionDelay = {
|
||||
AtreidesMain =
|
||||
{
|
||||
easy = DateTime.Seconds(200),
|
||||
normal = DateTime.Seconds(150),
|
||||
hard = DateTime.Seconds(100)
|
||||
},
|
||||
|
||||
AtreidesSmall =
|
||||
{
|
||||
easy = DateTime.Seconds(160),
|
||||
normal = DateTime.Seconds(80),
|
||||
hard = DateTime.Seconds(50)
|
||||
},
|
||||
|
||||
CorrinoMain =
|
||||
{
|
||||
easy = DateTime.Seconds(250),
|
||||
normal = DateTime.Seconds(200),
|
||||
hard = DateTime.Seconds(150)
|
||||
},
|
||||
|
||||
CorrinoSmall =
|
||||
{
|
||||
easy = DateTime.Seconds(100),
|
||||
normal = DateTime.Seconds(80),
|
||||
hard = DateTime.Seconds(60)
|
||||
}
|
||||
}
|
||||
|
||||
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
EnemyVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
AtreidesMainTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
|
||||
AtreidesMainTankTypes = {
|
||||
EarlyGame = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank" },
|
||||
LateGame = {"combat_tank_a", "siege_tank", "missile_tank", "sonic_tank"}
|
||||
}
|
||||
|
||||
AtreidesSmallTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank" }
|
||||
AtreidesStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
CorrinoMainInfantryTypes = { "light_inf", "light_inf", "trooper", "sardaukar" }
|
||||
CorrinoMainTankTypes = { "combat_tank_h", "combat_tank_h", "siege_tank", "missile_tank" }
|
||||
|
||||
CorrinoMainTankTypes = {
|
||||
EarlyGame = { "combat_tank_h" },
|
||||
LateGame = { "combat_tank_h", "combat_tank_h", "siege_tank", "missile_tank" }
|
||||
}
|
||||
|
||||
CorrinoSmallTankTypes = { "combat_tank_h", "combat_tank_h", "siege_tank" }
|
||||
CorrinoStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_h.starport", "combat_tank_h.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[AtreidesMain] = {}
|
||||
Defending[AtreidesSmall1] = {}
|
||||
Defending[AtreidesSmall2] = {}
|
||||
Defending[CorrinoMain] = {}
|
||||
Defending[CorrinoSmall] = {}
|
||||
-- this is also first attack timing
|
||||
AttackDelay[AtreidesMain] = 16000
|
||||
AttackDelay[AtreidesSmall1] = 16000
|
||||
AttackDelay[AtreidesSmall2] = 16000
|
||||
AttackDelay[CorrinoMain] = 16000
|
||||
AttackDelay[CorrinoSmall] = 16000
|
||||
TimeBetweenAttacks[AtreidesMain] = 13000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[AtreidesSmall1] = 1000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[AtreidesSmall2] = 4000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[CorrinoMain] = 12000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[CorrinoSmall] = 10000 * DifficultyModifier[Difficulty]
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(AtreidesSmall1Base, function()
|
||||
TimeBetweenAttacks[AtreidesMain] = 0
|
||||
end)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(CorrinoMainBase, function()
|
||||
TimeBetweenAttacks[CorrinoSmall] = 0
|
||||
end)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(CorrinoSmallBase, function()
|
||||
TimeBetweenAttacks[CorrinoMain] = 0
|
||||
end)
|
||||
|
||||
HarvesterCount[AtreidesMain] = 4
|
||||
HarvesterCount[AtreidesSmall1] = 2
|
||||
HarvesterCount[AtreidesSmall2] = 2
|
||||
HarvesterCount[CorrinoMain] = 4
|
||||
HarvesterCount[CorrinoSmall] = 2
|
||||
|
||||
PatrolPoints[AtreidesMain] = {AtreidesPatrolPoint3.Location, AtreidesPatrolPoint4.Location, AtreidesPatrolPoint2.Location, AtreidesRally10.Location, AtreidesPatrolPoint5.Location }
|
||||
PatrolPoints[AtreidesSmall1] = {AtreidesPatrolPoint1.Location, AtreidesPatrolPoint2.Location, AtreidesRally3.Location }
|
||||
PatrolPoints[CorrinoMain] = {CorrinoPatrolPoint1.Location, CorrinoPatrolPoint2.Location, AtreidesPatrolPoint5.Location }
|
||||
PatrolPoints[CorrinoSmall] = {CorrinoPatrolPoint3.Location, AtreidesPatrolPoint3.Location, AtreidesPatrolPoint5.Location }
|
||||
DefencePerimeter[AtreidesMain] = GetCellsInRectangle(CPos.New(36,15), CPos.New(57,30))
|
||||
DefencePerimeter[AtreidesSmall1] = GetCellsInRectangle(CPos.New(34,51), CPos.New(46,74))
|
||||
DefencePerimeter[AtreidesSmall2] = GetCellsInRectangle(CPos.New(18,32), CPos.New(30,37))
|
||||
DefencePerimeter[CorrinoMain] = GetCellsInRectangle(CPos.New(3,13), CPos.New(24,26))
|
||||
DefencePerimeter[CorrinoSmall] = GetCellsInRectangle(CPos.New(74,27), CPos.New(96,48))
|
||||
|
||||
IdlingUnits[AtreidesMain] = Utils.Concat(Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[1], InitialAtreidesPaths[1]), Utils.Concat(Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[2], InitialAtreidesPaths[2]), Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[3], InitialAtreidesPaths[3])))
|
||||
IdlingUnits[AtreidesSmall1] = Utils.Concat(Reinforcements.Reinforce(AtreidesSmall1, InitialAtreidesReinforcements[4], InitialAtreidesPaths[4]), Reinforcements.Reinforce(AtreidesSmall1, InitialAtreidesReinforcements[5], InitialAtreidesPaths[5]))
|
||||
IdlingUnits[AtreidesSmall2] = Reinforcements.Reinforce(AtreidesSmall2, InitialAtreidesReinforcements[6], InitialAtreidesPaths[6])
|
||||
@@ -46,35 +139,118 @@ ActivateAI = function()
|
||||
DefendAndRepairBase(CorrinoMain, CorrinoMainBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(CorrinoSmall, CorrinoSmallBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
|
||||
else
|
||||
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
|
||||
local infantryToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
|
||||
local tanksToBuildAtreidesMain = function() return { Utils.Random(AtreidesMainTankTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
|
||||
local tanksToBuildAtreidesMain = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(AtreidesMainTankTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(AtreidesMainTankTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
local tanksToBuildAtreidesSmall = function() return { Utils.Random(AtreidesSmallTankTypes) } end
|
||||
local tanksToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainTankTypes) } end
|
||||
|
||||
local tanksToBuildCorrinoMain = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(CorrinoMainTankTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(CorrinoMainTankTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
local tanksToBuildCorrinoSmall = function() return { Utils.Random(CorrinoSmallTankTypes) } end
|
||||
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end
|
||||
local unitsToBuyCorrino = function() return { Utils.Random(CorrinoStarportTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 3
|
||||
local attackThresholdSizeCorrino = AttackGroupSize[Difficulty] * 4
|
||||
local attackThresholdSizeSmallBase = AttackGroupSize[Difficulty] * 2
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function ()
|
||||
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
--ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], AttackThresholdSize)
|
||||
end)
|
||||
|
||||
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall"][Difficulty], function ()
|
||||
ProduceUnits(AtreidesSmall1, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
|
||||
ProduceUnits(AtreidesSmall1, ALightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
|
||||
ProduceUnits(AtreidesSmall1, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
|
||||
end)
|
||||
|
||||
ProduceUnits(AtreidesSmall1, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesSmall1, ALightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesSmall1, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesSmall2, ABarracks4, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
|
||||
|
||||
ProduceUnits(AtreidesSmall2, ABarracks4, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["CorrinoMain"][Difficulty], function ()
|
||||
ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSizeCorrino)
|
||||
ProduceUnits(CorrinoMain, CLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeCorrino)
|
||||
ProduceUnits(CorrinoMain, CHeavyFactory1, delay, tanksToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSizeCorrino)
|
||||
--ProduceUnits(CorrinoMain, CStarport, delay, unitsToBuyCorrino, AttackGroupSize[Difficulty], AttackThresholdSize)
|
||||
end)
|
||||
|
||||
ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(CorrinoMain, CLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(CorrinoMain, CHeavyFactory1, delay, tanksToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(CorrinoMain, CStarport, delay, unitsToBuyCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["CorrinoSmall"][Difficulty], function ()
|
||||
ProduceUnits(CorrinoSmall, CBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
|
||||
ProduceUnits(CorrinoSmall, CLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
|
||||
ProduceUnits(CorrinoSmall, CHeavyFactory2, delay, tanksToBuildCorrinoSmall, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
|
||||
end)
|
||||
|
||||
ProduceUnits(CorrinoSmall, CBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(CorrinoSmall, CLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(CorrinoSmall, CHeavyFactory2, delay, tanksToBuildCorrinoSmall, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
local crusherTypes = { "combat_tank_a", "combat_tank_a.starport", "combat_tank_h", "combat_tank_h.starport" }
|
||||
local crusherFactories = { AStarport, AHeavyFactory1, AHeavyFactory2, CHeavyFactory1, CHeavyFactory2, CStarport }
|
||||
ActivateCrusherLogic(crusherTypes, crusherFactories)
|
||||
|
||||
if Difficulty == "normal" then
|
||||
AtreidesMain.GrantCondition("base-rebuilder")
|
||||
AtreidesSmall1.GrantCondition("base-rebuilder2")
|
||||
CorrinoSmall.GrantCondition("base-rebuilder3")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
AtreidesMain.GrantCondition("defense-rebuilder")
|
||||
AtreidesSmall1.GrantCondition("defense-rebuilder2")
|
||||
CorrinoSmall.GrantCondition("defense-rebuilder3")
|
||||
end
|
||||
|
||||
local productionTypesAtreidis =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuildAtreidesMain
|
||||
}
|
||||
|
||||
local productionTypesCorrino =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuildCorrinoSmall
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(AtreidesMain, function(p, building)
|
||||
table.insert(AtreidesMainBase, building)
|
||||
DefendAndRepairBase(AtreidesMain, {building}, 0.5, AttackGroupSize[Difficulty] )
|
||||
if productionTypesAtreidis[building.Type] == nil then return end
|
||||
ProduceUnits(AtreidesMain, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
Trigger.OnBuildingPlaced(AtreidesSmall1, function(p, building)
|
||||
table.insert(AtreidesSmallBase, building)
|
||||
DefendAndRepairBase(AtreidesSmall1, {building}, 0.5, AttackGroupSize[Difficulty] )
|
||||
if productionTypesAtreidis[building.Type] == nil then return end
|
||||
ProduceUnits(AtreidesSmall1, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
Trigger.OnBuildingPlaced(CorrinoMain, function(p, building)
|
||||
table.insert(CorrinoMainBase, building)
|
||||
DefendAndRepairBase(CorrinoMain, {building}, 0.5, AttackGroupSize[Difficulty] )
|
||||
if productionTypesCorrino[building.Type] == nil then return end
|
||||
ProduceUnits(CorrinoMain, building, delay, productionTypesCorrino[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,9 +8,13 @@
|
||||
]]
|
||||
|
||||
AtreidesMainBase = { AConYard1, AOutpost1, APalace, ARefinery1, ARefinery2, ARefinery3, AHeavyFactory1, ALightFactory1, AStarport, AHiTechFactory, AResearch, AGunt1, AGunt2, AGunt3, AGunt4, AGunt5, ARock1, ARock2, ARock3, ARock4, ABarracks1, ABarracks2, APower1, APower2, APower3, APower4, APower5, APower6, APower7, APower8, APower9, APower10, APower11, APower12, APower13, APower14 }
|
||||
|
||||
AtreidesSmall1Base = { AConYard2, ARefinery4, ABarracks3, AHeavyFactory2, ALightFactory2, ARepair, ARock5, ARock6, ARock7, ARock8, ARock9, APower15, APower16, APower17, APower18, APower19, APower20, APower21 }
|
||||
|
||||
AtreidesSmall2Base = { AOutpost2, ABarracks4, AGunt6, AGunt7, AGunt8, ARock10, APower22, APower23 }
|
||||
|
||||
CorrinoMainBase = { COutpost, CPalace, CRefinery1, CHeavyFactory1, CLightFactory1, CStarport, CResearch, CGunt1, CGunt2, CRock1, CRock2, CBarracks1, CPower1, CPower2, CPower3, CPower4, CPower5, CPower6, CPower7 }
|
||||
|
||||
CorrinoSmallBase = { CConYard, CRefinery2, CHeavyFactory2, CLightFactory2, CRock3, CRock4, CBarracks2, CPower8, CPower9, CPower10, CPower11 }
|
||||
|
||||
AtreidesReinforcements =
|
||||
@@ -131,9 +135,13 @@ InitialCorrinoPaths =
|
||||
{ CorrinoEntry2.Location, CorrinoRally2.Location }
|
||||
}
|
||||
|
||||
HarkonnenReinforcements = { "combat_tank_h", "combat_tank_h", "siege_tank", "siege_tank", "missile_tank" }
|
||||
|
||||
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
|
||||
HarkonnenReinforcements = {
|
||||
{ "combat_tank_h", "combat_tank_h", "siege_tank", "siege_tank", "missile_tank" },
|
||||
{ "trooper", "light_inf", "light_inf", "light_inf", "trooper", "light_inf", "trooper", "light_inf", "trooper", "light_inf", "trooper" },
|
||||
{ "trooper", "light_inf", "quad", "trike", "quad" },
|
||||
{ "devastator", "light_inf", "quad", "trike", "quad" },
|
||||
{ "trooper", "combat_tank_h", "combat_tank_h", "combat_tank_h", "quad" }
|
||||
}
|
||||
|
||||
SendStarportReinforcements = function()
|
||||
Trigger.AfterDelay(CorrinoStarportDelay[Difficulty], function()
|
||||
@@ -142,7 +150,6 @@ SendStarportReinforcements = function()
|
||||
end
|
||||
|
||||
local reinforcements = Utils.Random(CorrinoStarportReinforcements[Difficulty])
|
||||
|
||||
local units = Reinforcements.ReinforceWithTransport(CorrinoMain, "frigate", reinforcements, { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2]
|
||||
Utils.Do(units, function(unit)
|
||||
unit.AttackMove(AtreidesAttackLocation)
|
||||
@@ -153,23 +160,56 @@ SendStarportReinforcements = function()
|
||||
end)
|
||||
end
|
||||
|
||||
SendHarkonnenReinforcements = function(delay)
|
||||
HarkonnenPaths =
|
||||
{
|
||||
{ HarkonnenEntry.Location, HarkonnenRally.Location },
|
||||
{ AtreidesEntry3.Location, HarkonnenRally1.Location },
|
||||
{ HarkonnenEntry.Location, HarkonnenRally2.Location },
|
||||
{ AtreidesEntry3.Location, AtreidesRally3.Location },
|
||||
{ HarkonnenRally3.Location, AtreidesRally9.Location },
|
||||
{ HarkonnenRally4.Location, AtreidesRally8.Location }
|
||||
}
|
||||
|
||||
SendHarkonnenReinforcements = function(delay, number)
|
||||
Trigger.AfterDelay(delay, function()
|
||||
Reinforcements.ReinforceWithTransport(Harkonnen, "carryall.reinforce", HarkonnenReinforcements, HarkonnenPath, { HarkonnenPath[1] })
|
||||
Reinforcements.ReinforceWithTransport(Harkonnen, "carryall.reinforce", HarkonnenReinforcements[number], HarkonnenPaths[number], { HarkonnenPaths[number][1] })
|
||||
Trigger.AfterDelay(DateTime.Seconds(5), function()
|
||||
Media.PlaySpeechNotification(Harkonnen, "Reinforce")
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
SendAirStrike = function()
|
||||
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesMain then
|
||||
AirStrikeTimer = 7500
|
||||
AirStrikeChargeTime = 7500
|
||||
AirstrikeLogic = function(airstrikeProvider)
|
||||
if airstrikeProvider.IsDead then
|
||||
return
|
||||
end
|
||||
|
||||
if DateTime.GameTime <= AirStrikeTimer then
|
||||
Trigger.AfterDelay(AirStrikeTimer - DateTime.GameTime + 1, function()
|
||||
AirstrikeLogic(airstrikeProvider)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
-- randomly choose if wait again or strike. During waiting Airstrike can still be used by DefensiveAirStrike
|
||||
if Utils.RandomInteger(1, 100) < 30 then
|
||||
Trigger.AfterDelay(1000, function() AirstrikeLogic(airstrikeProvider)end)
|
||||
else
|
||||
AirStrikeVSBuilding(airstrikeProvider)
|
||||
Trigger.AfterDelay(7500, function() AirstrikeLogic(airstrikeProvider) end)
|
||||
IsAirstrikeReady = false
|
||||
end
|
||||
end
|
||||
|
||||
AirStrikeVSBuilding = function(airstrikeProvider)
|
||||
if airstrikeProvider.IsDead or DateTime.GameTime < AirStrikeTimer then
|
||||
return
|
||||
end
|
||||
|
||||
local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
|
||||
return
|
||||
actor.HasProperty("Sell") and
|
||||
return actor.HasProperty("Sell") and
|
||||
actor.Type ~= "wall" and
|
||||
actor.Type ~= "medium_gun_turret" and
|
||||
actor.Type ~= "large_gun_turret" and
|
||||
@@ -178,12 +218,86 @@ SendAirStrike = function()
|
||||
end)
|
||||
|
||||
if #targets > 0 then
|
||||
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition)
|
||||
airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
|
||||
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
|
||||
end
|
||||
end
|
||||
|
||||
DefensiveAirStrike = function(airstrikeProvider, possibleTargets)
|
||||
if airstrikeProvider.IsDead or DateTime.GameTime <= AirStrikeTimer then return end
|
||||
local bestValue = {}
|
||||
local bestIndex = 1
|
||||
for i = 1, #possibleTargets, 1 do
|
||||
local ActorsInCircle = Map.ActorsInCircle(possibleTargets[i].CenterPosition, WDist.FromCells(4), function(a)
|
||||
return a.Owner == Harkonnen
|
||||
and not a.IsDead
|
||||
and a.HasProperty("Attack")
|
||||
end)
|
||||
|
||||
bestValue[i] = 0
|
||||
Utils.Do(ActorsInCircle, function(a)
|
||||
bestValue[i] = bestValue[i] + Actor.Cost(a.Type)
|
||||
end)
|
||||
|
||||
if bestValue[i] > bestValue[bestIndex] then
|
||||
bestIndex = i
|
||||
end
|
||||
end
|
||||
airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
|
||||
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
|
||||
end
|
||||
|
||||
EmergencyBehaviour = function(player,target)
|
||||
if player == AtreidesMain or player == AtreidesSmall1 then
|
||||
if AHiTechFactory.IsDead then return end
|
||||
local enemyunits = Map.ActorsInCircle(Map.CenterOfCell(target), WDist.FromCells(15), function(a)
|
||||
return a.Owner == Harkonnen
|
||||
and not a.IsDead
|
||||
and a.HasProperty("Attack")
|
||||
end)
|
||||
|
||||
if enemyunits[1] == nil then return end
|
||||
DefensiveAirStrike(AHiTechFactory, enemyunits)
|
||||
end
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
|
||||
if player == AtreidesSmall1 and #IdlingUnits[AtreidesMain] > 10 then
|
||||
local reinforcements = SetupAttackGroup(AtreidesMain, Utils.RandomInteger(10, #IdlingUnits[AtreidesMain]))
|
||||
Utils.Do(reinforcements, function(unit)
|
||||
Trigger.ClearAll(unit)
|
||||
Trigger.AfterDelay(1, function()
|
||||
unit.Stop()
|
||||
unit.Move(CorrinoPatrolPoint1.Location,1)
|
||||
unit.AttackMove(target)
|
||||
unit.CallFunc(function()
|
||||
FindTargetsInArea(player, unit)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
if player == AtreidesSmall2 and #IdlingUnits[AtreidesMain] > 10 then
|
||||
CheckArea(AtreidesMain, target, 10)
|
||||
end
|
||||
end
|
||||
|
||||
ReleaseSardaukars = true
|
||||
Trigger.OnDamaged(CPalace, function(self)
|
||||
if self.Health < self.MaxHealth * 0.8 and ReleaseSardaukars then
|
||||
local index = 0
|
||||
while index < 100 do
|
||||
index = index + 5
|
||||
Trigger.AfterDelay(index,function()
|
||||
if self.IsDead then return end
|
||||
local actor = Actor.Create("sardaukar", true, { Owner = CorrinoMain, Location = CPalace.Location + CVec.New(1,2) })
|
||||
actor.Move(CPos.New(3,31))
|
||||
IdlingUnits[CorrinoMain][#IdlingUnits[CorrinoMain] + 1] = actor
|
||||
end)
|
||||
end
|
||||
|
||||
ReleaseSardaukars = false
|
||||
end
|
||||
end)
|
||||
|
||||
BuildFremen = function()
|
||||
if APalace.IsDead or APalace.Owner ~= AtreidesMain then
|
||||
return
|
||||
@@ -194,7 +308,6 @@ BuildFremen = function()
|
||||
|
||||
Trigger.AfterDelay(DateTime.Seconds(5), function()
|
||||
IdleFremen = Utils.Where(AtreidesMain.GetActorsByType('fremen'), function(actor) return actor.IsIdle end)
|
||||
|
||||
if #IdleFremen >= FremenGroupSize[Difficulty] then
|
||||
SendFremen()
|
||||
end
|
||||
@@ -231,7 +344,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
|
||||
local units = AtreidesMain.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[AtreidesMain] = false
|
||||
ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
|
||||
@@ -240,7 +352,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesSmall1] then
|
||||
local units = AtreidesSmall1.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[AtreidesSmall1] = false
|
||||
ProtectHarvester(units[1], AtreidesSmall1, AttackGroupSize[Difficulty])
|
||||
@@ -249,7 +360,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoMain] then
|
||||
local units = CorrinoMain.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[CorrinoMain] = false
|
||||
ProtectHarvester(units[1], CorrinoMain, AttackGroupSize[Difficulty])
|
||||
@@ -258,7 +368,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoSmall] then
|
||||
local units = CorrinoSmall.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[CorrinoSmall] = false
|
||||
ProtectHarvester(units[1], CorrinoSmall, AttackGroupSize[Difficulty])
|
||||
@@ -286,8 +395,8 @@ WorldLoaded = function()
|
||||
Camera.Position = HMCV.CenterPosition
|
||||
AtreidesAttackLocation = HarkonnenRally.Location
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
|
||||
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds (30), BuildFremen)
|
||||
Trigger.AfterDelay(DateTime.Minutes(10), function() AirstrikeLogic(AHiTechFactory) end )
|
||||
Trigger.AfterDelay(DateTime.Minutes(3) + DateTime.Seconds (30), BuildFremen)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(AtreidesMainBase, function()
|
||||
Utils.Do(AtreidesMain.GetGroundAttackers(), IdleHunt)
|
||||
@@ -315,8 +424,8 @@ WorldLoaded = function()
|
||||
unit.AttackMove(AtreidesAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
SendCarryallReinforcements(AtreidesMain, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
|
||||
SendCarryallReinforcements(AtreidesMain, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
SendStarportReinforcements()
|
||||
|
||||
Actor.Create("upgrade.barracks", true, { Owner = AtreidesMain })
|
||||
@@ -335,5 +444,19 @@ WorldLoaded = function()
|
||||
Actor.Create("upgrade.heavy", true, { Owner = CorrinoSmall })
|
||||
Trigger.AfterDelay(0, ActivateAI)
|
||||
|
||||
SendHarkonnenReinforcements(DateTime.Minutes(2) + DateTime.Seconds(30))
|
||||
SendHarkonnenReinforcements(DateTime.Minutes(2) + DateTime.Seconds(30), 1)
|
||||
SendHarkonnenReinforcements(17030,2)
|
||||
SendHarkonnenReinforcements(17020,3)
|
||||
|
||||
Trigger.OnAllKilled({ARock6, ARock7, ARock8}, function()
|
||||
SendHarkonnenReinforcements(0,4)
|
||||
SendHarkonnenReinforcements(10,5)
|
||||
end)
|
||||
end
|
||||
|
||||
Trigger.OnDamaged(DebrisHarvester2, function(self)
|
||||
if self.Health < self.MaxHealth * 0.6 then
|
||||
self.Deploy()
|
||||
Trigger.ClearAll(self)
|
||||
end
|
||||
end)
|
||||
|
||||
Binary file not shown.
@@ -562,9 +562,6 @@ Actors:
|
||||
ARock4: large_gun_turret
|
||||
Location: 54,27
|
||||
Owner: Atreides Main Base
|
||||
CPalace: palace
|
||||
Location: 2,28
|
||||
Owner: Corrino Main Base
|
||||
Actor161: wall
|
||||
Location: 49,28
|
||||
Owner: Atreides Main Base
|
||||
@@ -844,6 +841,7 @@ Actors:
|
||||
ARock6: large_gun_turret
|
||||
Location: 47,62
|
||||
Owner: Atreides Small Base 1
|
||||
TurretFacing: 512
|
||||
AHeavyFactory2: heavy_factory
|
||||
Location: 36,63
|
||||
Owner: Atreides Small Base 1
|
||||
@@ -862,12 +860,10 @@ Actors:
|
||||
ARock7: large_gun_turret
|
||||
Location: 44,66
|
||||
Owner: Atreides Small Base 1
|
||||
TurretFacing: 512
|
||||
APower21: wind_trap
|
||||
Location: 38,67
|
||||
Owner: Atreides Small Base 1
|
||||
ARock8: large_gun_turret
|
||||
Location: 44,67
|
||||
Owner: Atreides Small Base 1
|
||||
ABarracks3: barracks
|
||||
Location: 36,68
|
||||
Owner: Atreides Small Base 1
|
||||
@@ -967,18 +963,12 @@ Actors:
|
||||
AtreidesRally1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 96,87
|
||||
AtreidesEntry1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 97,87
|
||||
AtreidesRally2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 76,93
|
||||
AtreidesEntry2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 76,97
|
||||
AtreidesRally3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 63,65
|
||||
AtreidesEntry3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 97,65
|
||||
@@ -1042,6 +1032,85 @@ Actors:
|
||||
CorrinoStarportExit: waypoint
|
||||
Owner: Neutral
|
||||
Location: 2,13
|
||||
AtreidesPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 16,63
|
||||
AtreidesPatrolPoint3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 62,47
|
||||
AtreidesPatrolPoint4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 72,28
|
||||
CorrinoPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 13,39
|
||||
CorrinoPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 32,29
|
||||
AtreidesPatrolPoint5: waypoint
|
||||
Owner: Neutral
|
||||
Location: 44,42
|
||||
CorrinoPatrolPoint3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 72,50
|
||||
Actor5: combat_tank_a.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 93,53
|
||||
Actor8: frigate.debris
|
||||
Owner: Creeps
|
||||
Location: 86,54
|
||||
Actor1: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 77,63
|
||||
Actor9: carryall.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 48,75
|
||||
Actor6: siege_tank.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 92,58
|
||||
Actor10: combat_tank_h.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 88,54
|
||||
HarkonnenRally1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 74,71
|
||||
HarkonnenRally2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 68,79
|
||||
AtreidesEntry1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 97,87
|
||||
Actor11: crate
|
||||
Owner: Neutral
|
||||
Location: 6,76
|
||||
ARock8: large_gun_turret
|
||||
Owner: Atreides Small Base 1
|
||||
Location: 44,67
|
||||
TurretFacing: 512
|
||||
HarkonnenRally4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 97,57
|
||||
HarkonnenRally3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 97,70
|
||||
AtreidesRally3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 51,65
|
||||
AtreidesPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 46,84
|
||||
DebrisHarvester2: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 58,39
|
||||
CPalace: palace
|
||||
Owner: Corrino Main Base
|
||||
Location: 2,26
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,204 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 7000
|
||||
ExternalCondition@AIAMail:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIASmall:
|
||||
Condition: base-rebuilder2
|
||||
ExternalCondition@AICSmall:
|
||||
Condition: base-rebuilder3
|
||||
ExternalCondition@AIAMail-defense:
|
||||
Condition: defense-rebuilder
|
||||
ExternalCondition@AIASmall-defense:
|
||||
Condition: defense-rebuilder2
|
||||
ExternalCondition@AICSmall-defense:
|
||||
Condition: defense-rebuilder3
|
||||
BaseBuilderBotModule@AIAMainBase:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 3
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
starport: 1
|
||||
palace: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
wind_trap: 11
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
starport: 1
|
||||
high_tech_factory: 1
|
||||
palace: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@AIASmallBase:
|
||||
RequiresCondition: base-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
palace: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@AIAMainCorrino:
|
||||
RequiresCondition: base-rebuilder3
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 3
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@AIAMainDefense:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 3
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
starport: 1
|
||||
palace: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
wind_trap: 11
|
||||
silo: 1
|
||||
medium_gun_turret: 5
|
||||
large_gun_turret: 4
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
starport: 1
|
||||
high_tech_factory: 1
|
||||
palace: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
medium_gun_turret: 1
|
||||
large_gun_turret: 1
|
||||
BaseBuilderBotModule@AIASmallDefense:
|
||||
RequiresCondition: defense-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
palace: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
large_gun_turret: 5
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
large_gun_turret: 1
|
||||
BaseBuilderBotModule@AISmallCorrino:
|
||||
RequiresCondition: defense-rebuilder3
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
large_gun_turret: 2
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
large_gun_turret: 2
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -7,6 +7,38 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(7)
|
||||
|
||||
InitialProductionDelay = {
|
||||
AtreidesMain =
|
||||
{
|
||||
easy = DateTime.Seconds(180),
|
||||
normal = DateTime.Seconds(120),
|
||||
hard = DateTime.Seconds(60)
|
||||
},
|
||||
|
||||
AtreidesSmall =
|
||||
{
|
||||
easy = DateTime.Seconds(120),
|
||||
normal = DateTime.Seconds(60),
|
||||
hard = DateTime.Seconds(0)
|
||||
},
|
||||
|
||||
CorrinoMain =
|
||||
{
|
||||
easy = DateTime.Seconds(160),
|
||||
normal = DateTime.Seconds(120),
|
||||
hard = DateTime.Seconds(80)
|
||||
},
|
||||
|
||||
CorrinoSmall =
|
||||
{
|
||||
easy = DateTime.Seconds(80),
|
||||
normal = DateTime.Seconds(60),
|
||||
hard = DateTime.Seconds(30)
|
||||
}
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,25 +46,81 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
EarlyProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(9), DateTime.Seconds(12) },
|
||||
normal = { DateTime.Seconds(6), DateTime.Seconds(8) },
|
||||
hard = { DateTime.Seconds(4), DateTime.Seconds(7) }
|
||||
}
|
||||
|
||||
LateProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
hard = { DateTime.Seconds(1), DateTime.Seconds(3) }
|
||||
}
|
||||
|
||||
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
EnemyVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
AtreidesMainTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
|
||||
AtreidesMainTankTypes = {
|
||||
EarlyGame = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank" },
|
||||
LateGame = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
|
||||
}
|
||||
|
||||
AtreidesSmallTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank" }
|
||||
AtreidesStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
CorrinoMainInfantryTypes = { "light_inf", "light_inf", "trooper", "sardaukar" }
|
||||
CorrinoTankTypes = { "combat_tank_h", "combat_tank_h", "siege_tank", "missile_tank" }
|
||||
CorrinoStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_h.starport", "combat_tank_h.starport", "siege_tank.starport", "missile_tank.starport" }
|
||||
|
||||
CorrinoTankTypes = {
|
||||
EarlyGame = { "combat_tank_h" },
|
||||
LateGame = { "combat_tank_h", "combat_tank_h", "siege_tank", "missile_tank" }
|
||||
}
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[AtreidesMain] = {}
|
||||
Defending[AtreidesSmall] = {}
|
||||
Defending[CorrinoMain] = {}
|
||||
Defending[CorrinoSmall] = {}
|
||||
-- this is also first attack timing
|
||||
AttackDelay[AtreidesMain] = 15000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[AtreidesSmall] = 10000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[CorrinoMain] = 15000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[CorrinoSmall] = 15000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[AtreidesMain] = 13000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[AtreidesSmall] = 4000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[CorrinoMain] = 8600 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[CorrinoSmall] = 8600 * DifficultyModifier[Difficulty]
|
||||
|
||||
Trigger.OnKilledOrCaptured(AConYard1, function()
|
||||
TimeBetweenAttacks[AtreidesMain] = 0
|
||||
TimeBetweenAttacks[CorrinoMain] = 0
|
||||
end)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(CorrinoMainBase, function()
|
||||
TimeBetweenAttacks[CorrinoSmall] = 0
|
||||
TimeBetweenAttacks[AtreidesMain] = 0
|
||||
end)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(CorrinoSmallBase, function()
|
||||
TimeBetweenAttacks[CorrinoMain] = 0
|
||||
end)
|
||||
|
||||
HarvesterCount[AtreidesMain] = 4
|
||||
HarvesterCount[AtreidesSmall] = 2
|
||||
HarvesterCount[CorrinoMain] = 4
|
||||
HarvesterCount[CorrinoSmall] = 1
|
||||
|
||||
PatrolPoints[AtreidesMain] = {APatrolPoint1.Location, APatrolPoint2.Location, APatrolPoint3.Location, APatrolPoint4.Location }
|
||||
PatrolPoints[AtreidesSmall] = {APatrolPoint5.Location, APatrolPoint6.Location, APatrolPoint7.Location }
|
||||
PatrolPoints[CorrinoMain] = {APatrolPoint7.Location, AtreidesRally5.Location, CPatrolPoint1.Location }
|
||||
PatrolPoints[CorrinoSmall] = {CPatrolPoint2.Location, AtreidesRally4.Location, APatrolPoint4.Location }
|
||||
DefencePerimeter[AtreidesMain] = GetCellsInRectangle(CPos.New(25,58), CPos.New(47,70))
|
||||
DefencePerimeter[AtreidesSmall] = GetCellsInRectangle(CPos.New(103,5), CPos.New(119,18))
|
||||
DefencePerimeter[CorrinoMain] = GetCellsInRectangle(CPos.New(65,38), CPos.New(91,55))
|
||||
DefencePerimeter[CorrinoSmall] = GetCellsInRectangle(CPos.New(33,35), CPos.New(49,52))
|
||||
|
||||
IdlingUnits[AtreidesMain] = Utils.Concat(Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[1], InitialAtreidesPaths[1]), Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[2], InitialAtreidesPaths[2]))
|
||||
IdlingUnits[AtreidesSmall] = Reinforcements.Reinforce(AtreidesSmall, InitialAtreidesReinforcements[3], InitialAtreidesPaths[3])
|
||||
IdlingUnits[CorrinoMain] = Utils.Concat(Reinforcements.Reinforce(CorrinoMain, InitialCorrinoReinforcements[1], InitialCorrinoPaths[1]), Reinforcements.Reinforce(CorrinoMain, InitialCorrinoReinforcements[2], InitialCorrinoPaths[2]))
|
||||
@@ -43,31 +131,109 @@ ActivateAI = function()
|
||||
DefendAndRepairBase(CorrinoMain, CorrinoMainBase, 0.75, AttackGroupSize[Difficulty])
|
||||
DefendAndRepairBase(CorrinoSmall, CorrinoSmallBase, 0.75, AttackGroupSize[Difficulty])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
|
||||
else
|
||||
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
|
||||
local infantryToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
|
||||
local tanksToBuildAtreidesMain = function() return { Utils.Random(AtreidesMainTankTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
|
||||
local tanksToBuildAtreidesMain = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(AtreidesMainTankTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(AtreidesMainTankTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
local tanksToBuildAtreidesSmall = function() return { Utils.Random(AtreidesSmallTankTypes) } end
|
||||
local tanksToBuildCorrino = function() return { Utils.Random(CorrinoTankTypes) } end
|
||||
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end
|
||||
local unitsToBuyCorrino = function() return { Utils.Random(CorrinoStarportTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
local tanksToBuildCorrino = function()
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return { Utils.Random(CorrinoTankTypes["EarlyGame"]) }
|
||||
else
|
||||
return { Utils.Random(CorrinoTankTypes["LateGame"]) }
|
||||
end
|
||||
end
|
||||
|
||||
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AStarport1, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 3
|
||||
local attackThresholdSizeSmall = AttackGroupSize[Difficulty] * 2
|
||||
local attackThresholdSizeEmperor = AttackGroupSize[Difficulty] * 5
|
||||
|
||||
ProduceUnits(AtreidesSmall, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesSmall, ALightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesSmall, AStarport2, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function ()
|
||||
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
--ProduceUnits(AtreidesMain, AStarport1, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], AttackThresholdSize)
|
||||
end)
|
||||
|
||||
ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(CorrinoMain, CHeavyFactory, delay, tanksToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall"][Difficulty], function ()
|
||||
ProduceUnits(AtreidesSmall, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
|
||||
ProduceUnits(AtreidesSmall, ALightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
|
||||
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
|
||||
end)
|
||||
|
||||
ProduceUnits(CorrinoSmall, CBarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(CorrinoSmall, CLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(CorrinoSmall, CStarport, delay, unitsToBuyCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["CorrinoMain"][Difficulty], function ()
|
||||
ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSizeEmperor)
|
||||
ProduceUnits(CorrinoMain, CHeavyFactory, delay, tanksToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSizeEmperor)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(InitialProductionDelay["CorrinoSmall"][Difficulty], function ()
|
||||
ProduceUnits(CorrinoSmall, CBarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
|
||||
ProduceUnits(CorrinoSmall, CLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
|
||||
end)
|
||||
|
||||
local productionTypesAtreidis =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuildAtreidesMain
|
||||
}
|
||||
|
||||
local productionTypesCorrino =
|
||||
{
|
||||
barracks = infantryToBuildCorrinoMain,
|
||||
heavy_factory = tanksToBuildCorrino
|
||||
}
|
||||
|
||||
if Difficulty == "normal" then
|
||||
AtreidesMain.GrantCondition("base-rebuilder")
|
||||
AtreidesSmall.GrantCondition("base-rebuilder2")
|
||||
CorrinoMain.GrantCondition("base-rebuilder3")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
AtreidesMain.GrantCondition("defense-rebuilder")
|
||||
AtreidesSmall.GrantCondition("defense-rebuilder2")
|
||||
CorrinoMain.GrantCondition("defense-rebuilder3")
|
||||
end
|
||||
|
||||
Trigger.OnBuildingPlaced(AtreidesMain, function(p, building)
|
||||
table.insert(AtreidesMainBase, building)
|
||||
DefendAndRepairBase(AtreidesMain, {building}, 0.5, AttackGroupSize[Difficulty] )
|
||||
if productionTypesAtreidis[building.Type] == nil then return end
|
||||
ProduceUnits(AtreidesMain, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
Trigger.OnBuildingPlaced(AtreidesSmall, function(p, building)
|
||||
table.insert(AtreidesSmallBase, building)
|
||||
DefendAndRepairBase(AtreidesSmall, {building}, 0.5, AttackGroupSize[Difficulty] )
|
||||
if productionTypesAtreidis[building.Type] == nil then return end
|
||||
ProduceUnits(AtreidesSmall, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
Trigger.OnBuildingPlaced(CorrinoMain, function(p, building)
|
||||
table.insert(CorrinoMainBase, building)
|
||||
DefendAndRepairBase(CorrinoMain, {building}, 0.5, AttackGroupSize[Difficulty] )
|
||||
if productionTypesCorrino[building.Type] == nil then return end
|
||||
ProduceUnits(CorrinoMain, building, delay, productionTypesCorrino[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ActivateCrushLogic()
|
||||
end
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
]]
|
||||
|
||||
AtreidesMainBase = { AConYard1, AOutpost1, APalace, ARefinery1, ARefinery2, AHeavyFactory1, ALightFactory1, ARepair1, AStarport1, AHiTechFactory, AResearch, ARock1, ARock2, ARock3, ARock4, ARock5, ARock6, ARock7, ARock8, ARock9, ARock10, ABarracks1, ABarracks2, APower1, APower2, APower3, APower4, APower5, APower6, APower7, APower8, APower9, APower10, APower11, ASilo1, ASilo2, ASilo3 }
|
||||
|
||||
AtreidesSmallBase = { AConYard2, ARefinery3, ABarracks3, AHeavyFactory2, ALightFactory2, ARepair2, AGunt1, AGunt2, ARock11, APower12, APower13, APower14, APower15, APower16, APower17, APower18, APower19, APower20 }
|
||||
|
||||
CorrinoMainBase = { CConYard, COutpost, CPalace, CRefinery1, CHeavyFactory, CResearch, CGunt1, CGunt2, CGunt3, CGunt4, CGunt5, CGunt6, CRock1, CRock2, CRock3, CRock4, CBarracks1, CBarracks2, CPower1, CPower2, CPower3, CPower4, CPower5, CPower6, CPower7, CPower8 }
|
||||
|
||||
CorrinoSmallBase = { CRefinery2, CLightFactory, CStarport, CGunt7, CGunt8, CBarracks3, CPower9, CPower10, CPower11, CPower12, CSilo1, CSilo2, CSilo3, CSilo4 }
|
||||
|
||||
AtreidesReinforcements =
|
||||
@@ -148,7 +151,6 @@ SendStarportReinforcements = function()
|
||||
end
|
||||
|
||||
local reinforcements = Utils.Random(CorrinoStarportReinforcements[Difficulty])
|
||||
|
||||
local units = Reinforcements.ReinforceWithTransport(CorrinoSmall, "frigate", reinforcements, { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2]
|
||||
Utils.Do(units, function(unit)
|
||||
unit.AttackMove(AtreidesAttackLocation)
|
||||
@@ -168,14 +170,33 @@ SendHarkonnenReinforcements = function(delay)
|
||||
end)
|
||||
end
|
||||
|
||||
SendAirStrike = function()
|
||||
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesMain then
|
||||
AirStrikeTimer = 7500
|
||||
AirStrikeChargeTime = 7500
|
||||
AirstrikeLogic = function(airstrikeProvider)
|
||||
if airstrikeProvider.IsDead then return end
|
||||
|
||||
if DateTime.GameTime <= AirStrikeTimer then
|
||||
Trigger.AfterDelay(AirStrikeTimer - DateTime.GameTime + 1, function()
|
||||
AirstrikeLogic(airstrikeProvider)
|
||||
end)
|
||||
return
|
||||
end
|
||||
|
||||
-- randomly choose if wait again or strike. During waiting Airstrike can still be used by DefensiveAirStrike
|
||||
if Utils.RandomInteger(1, 100) < 30 then
|
||||
Trigger.AfterDelay(1501, function() AirstrikeLogic(airstrikeProvider)end)
|
||||
else
|
||||
AirStrikeVSBuilding(airstrikeProvider)
|
||||
Trigger.AfterDelay(7500, function() AirstrikeLogic(airstrikeProvider) end)
|
||||
IsAirstrikeReady = false
|
||||
end
|
||||
end
|
||||
|
||||
AirStrikeVSBuilding = function(airstrikeProvider)
|
||||
if airstrikeProvider.IsDead then return end
|
||||
|
||||
local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
|
||||
return
|
||||
actor.HasProperty("Sell") and
|
||||
return actor.HasProperty("Sell") and
|
||||
actor.Type ~= "wall" and
|
||||
actor.Type ~= "medium_gun_turret" and
|
||||
actor.Type ~= "large_gun_turret" and
|
||||
@@ -184,12 +205,71 @@ SendAirStrike = function()
|
||||
end)
|
||||
|
||||
if #targets > 0 then
|
||||
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition)
|
||||
airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
|
||||
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
|
||||
end
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
|
||||
end
|
||||
|
||||
DefensiveAirStrike = function(airstrikeProvider, possibleTargets)
|
||||
if airstrikeProvider.IsDead then return end
|
||||
local bestValue = {}
|
||||
local bestIndex = 1
|
||||
for i = 1, #possibleTargets, 1 do
|
||||
local ActorsInCircle = Map.ActorsInCircle(possibleTargets[i].CenterPosition, WDist.FromCells(4), function(a)
|
||||
return
|
||||
a.Owner == Harkonnen
|
||||
and not a.IsDead
|
||||
and a.HasProperty("Attack")
|
||||
end)
|
||||
|
||||
bestValue[i] = 0
|
||||
Utils.Do(ActorsInCircle, function(a)
|
||||
bestValue[i] = bestValue[i] + Actor.Cost(a.Type)
|
||||
end)
|
||||
|
||||
if bestValue[i] > bestValue[bestIndex] then
|
||||
bestIndex = i
|
||||
end
|
||||
end
|
||||
airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
|
||||
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
|
||||
end
|
||||
|
||||
EmergencyBehaviour = function(player,target)
|
||||
if player == AtreidesMain or player == AtreidesSmall then
|
||||
if AHiTechFactory.IsDead then return end
|
||||
|
||||
local enemyunits = Map.ActorsInCircle(Map.CenterOfCell(target), WDist.FromCells(15), function(a)
|
||||
return a.Owner == Harkonnen
|
||||
and not a.IsDead
|
||||
and a.HasProperty("Attack")
|
||||
end)
|
||||
|
||||
if enemyunits[1] == nil then return end
|
||||
DefensiveAirStrike(AHiTechFactory, enemyunits)
|
||||
end
|
||||
if player == CorrinoSmall then
|
||||
player.Cash = player.Cash + 2000
|
||||
end
|
||||
end
|
||||
|
||||
ReleaseSardaukars = true
|
||||
Trigger.OnDamaged(CPalace, function(self)
|
||||
if self.Health < self.MaxHealth * 0.8 and ReleaseSardaukars then
|
||||
local index = 0
|
||||
while index < 100 do
|
||||
index = index + 5
|
||||
Trigger.AfterDelay(index,function()
|
||||
if self.IsDead then return end
|
||||
local actor = Actor.Create("sardaukar", true, {Owner = CorrinoMain, Location = CPalace.Location + CVec.New(1,2)})
|
||||
actor.Move(CPos.New(90,45))
|
||||
IdlingUnits[CorrinoMain][#IdlingUnits[CorrinoMain] + 1] = actor
|
||||
end)
|
||||
end
|
||||
ReleaseSardaukars = false
|
||||
end
|
||||
end)
|
||||
|
||||
BuildFremen = function()
|
||||
if APalace.IsDead or APalace.Owner ~= AtreidesMain then
|
||||
return
|
||||
@@ -302,7 +382,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
|
||||
local units = AtreidesMain.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[AtreidesMain] = false
|
||||
ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
|
||||
@@ -311,7 +390,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesSmall] then
|
||||
local units = AtreidesSmall.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[AtreidesSmall] = false
|
||||
ProtectHarvester(units[1], AtreidesSmall, AttackGroupSize[Difficulty])
|
||||
@@ -320,7 +398,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoMain] then
|
||||
local units = CorrinoMain.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[CorrinoMain] = false
|
||||
ProtectHarvester(units[1], CorrinoMain, AttackGroupSize[Difficulty])
|
||||
@@ -329,7 +406,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoSmall] then
|
||||
local units = CorrinoSmall.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[CorrinoSmall] = false
|
||||
ProtectHarvester(units[1], CorrinoSmall, AttackGroupSize[Difficulty])
|
||||
@@ -366,8 +442,8 @@ WorldLoaded = function()
|
||||
Camera.Position = HBarracks.CenterPosition
|
||||
AtreidesAttackLocation = HBarracks.Location
|
||||
|
||||
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
|
||||
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds (30), BuildFremen)
|
||||
Trigger.AfterDelay(DateTime.Minutes(10), function() AirstrikeLogic(AHiTechFactory) end )
|
||||
Trigger.AfterDelay(EarlyGameStage, BuildFremen)
|
||||
|
||||
Trigger.OnAllKilledOrCaptured(AtreidesMainBase, function()
|
||||
Utils.Do(AtreidesMain.GetGroundAttackers(), IdleHunt)
|
||||
@@ -385,14 +461,22 @@ WorldLoaded = function()
|
||||
Utils.Do(CorrinoSmall.GetGroundAttackers(), IdleHunt)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(300, function()
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("husk-reclaimed-harkonnen"), Mentat)
|
||||
end)
|
||||
|
||||
Trigger.AfterDelay(350, function()
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("engineers-hint"), Mentat)
|
||||
end)
|
||||
|
||||
local path = function() return Utils.Random(AtreidesPaths) end
|
||||
local waveCondition = function() return Harkonnen.IsObjectiveCompleted(KillAtreides) end
|
||||
local huntFunction = function(unit)
|
||||
unit.AttackMove(AtreidesAttackLocation)
|
||||
IdleHunt(unit)
|
||||
end
|
||||
SendCarryallReinforcements(AtreidesMain, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
|
||||
SendCarryallReinforcements(AtreidesMain, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition, huntFunction)
|
||||
SendStarportReinforcements()
|
||||
|
||||
Actor.Create("upgrade.barracks", true, { Owner = AtreidesMain })
|
||||
|
||||
Binary file not shown.
@@ -454,9 +454,6 @@ Actors:
|
||||
COutpost: outpost
|
||||
Location: 79,42
|
||||
Owner: Corrino Main Base
|
||||
CPalace: palace
|
||||
Location: 89,42
|
||||
Owner: Corrino Main Base
|
||||
Actor116: wall
|
||||
Location: 93,42
|
||||
Owner: Corrino Main Base
|
||||
@@ -1005,6 +1002,68 @@ Actors:
|
||||
CPower8: wind_trap
|
||||
Owner: Corrino Main Base
|
||||
Location: 90,48
|
||||
APatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 10,60
|
||||
APatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 38,85
|
||||
APatrolPoint3: waypoint
|
||||
Owner: Neutral
|
||||
Location: 75,73
|
||||
APatrolPoint4: waypoint
|
||||
Owner: Neutral
|
||||
Location: 44,32
|
||||
APatrolPoint5: waypoint
|
||||
Owner: Neutral
|
||||
Location: 99,33
|
||||
APatrolPoint6: waypoint
|
||||
Owner: Neutral
|
||||
Location: 82,17
|
||||
APatrolPoint7: waypoint
|
||||
Owner: Neutral
|
||||
Location: 65,30
|
||||
CPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 49,13
|
||||
CPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 15,47
|
||||
Actor6: combat_tank_h.debris
|
||||
Owner: Harkonnen
|
||||
Facing: 384
|
||||
Location: 17,3
|
||||
Actor7: siege_tank.debris
|
||||
Owner: Harkonnen
|
||||
Facing: 384
|
||||
Location: 16,3
|
||||
Actor5: combat_tank_a.debris
|
||||
Facing: 384
|
||||
Faction:
|
||||
Owner: Atreides Small Base
|
||||
Location: 14,3
|
||||
CPalace: palace
|
||||
Owner: Corrino Main Base
|
||||
Location: 89,41
|
||||
Actor10: light_inf
|
||||
Owner: Smugglers - Neutral
|
||||
Facing: 384
|
||||
Location: 12,89
|
||||
SubCell: 3
|
||||
Actor9: trooper
|
||||
Owner: Smugglers - Neutral
|
||||
Facing: 384
|
||||
Location: 11,88
|
||||
SubCell: 3
|
||||
Actor15: siege_tank.debris
|
||||
Owner: Smugglers - Neutral
|
||||
Facing: 384
|
||||
Location: 10,88
|
||||
Actor8: engineer
|
||||
Owner: Smugglers - Neutral
|
||||
Facing: 384
|
||||
Location: 9,88
|
||||
SubCell: 3
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -1,6 +1,208 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 5000
|
||||
ExternalCondition@AIAMail:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIASmall:
|
||||
Condition: base-rebuilder2
|
||||
ExternalCondition@AICSmall:
|
||||
Condition: base-rebuilder3
|
||||
ExternalCondition@AIAMail-defense:
|
||||
Condition: defense-rebuilder
|
||||
ExternalCondition@AIASmall-defense:
|
||||
Condition: defense-rebuilder2
|
||||
ExternalCondition@AICSmall-defense:
|
||||
Condition: defense-rebuilder3
|
||||
BaseBuilderBotModule@AtreidesMain:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 3
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
starport: 1
|
||||
palace: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
wind_trap: 11
|
||||
research_centre: 1
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
research_centre: 1
|
||||
outpost: 1
|
||||
starport: 1
|
||||
high_tech_factory: 1
|
||||
palace: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@AtreidesSmallBase:
|
||||
RequiresCondition: base-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
palace: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@CorrinoMain:
|
||||
RequiresCondition: base-rebuilder3
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 3
|
||||
outpost: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@AtreidesMainDefense:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 3
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
starport: 1
|
||||
palace: 1
|
||||
heavy_factory: 1
|
||||
high_tech_factory: 1
|
||||
wind_trap: 11
|
||||
silo: 1
|
||||
research_centre: 1
|
||||
large_gun_turret: 10
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
starport: 1
|
||||
high_tech_factory: 1
|
||||
palace: 1
|
||||
light_factory: 1
|
||||
research_centre: 1
|
||||
heavy_factory: 1
|
||||
large_gun_turret: 1
|
||||
BaseBuilderBotModule@AtreidesSmallBaseDefense:
|
||||
RequiresCondition: defense-rebuilder2
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
palace: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 7
|
||||
silo: 1
|
||||
large_gun_turret: 1
|
||||
medium_gun_turret: 2
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
large_gun_turret: 1
|
||||
medium_gun_turret: 1
|
||||
BaseBuilderBotModule@CorrinoMainDefense:
|
||||
RequiresCondition: defense-rebuilder3
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: heavy_factory, barracks, starport
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 3
|
||||
outpost: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
large_gun_turret: 2
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
outpost: 1
|
||||
heavy_factory: 1
|
||||
large_gun_turret: 2
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
@@ -62,3 +264,28 @@ grenadier:
|
||||
thumper:
|
||||
Buildable:
|
||||
Prerequisites: ~disabled
|
||||
|
||||
palace:
|
||||
ProduceActorPower@ReleaseSardaukars:
|
||||
Name: actor-palace.produceactorpower-fremen-name
|
||||
Description: actor-palace.produceactorpower-fremen-description
|
||||
Icon: fremen
|
||||
PauseOnCondition: disabled
|
||||
RequiresCondition: corrino
|
||||
Prerequisites: ~techlevel.superweapons, ~palace.sardaukar
|
||||
Actors: mpsardaukar, mpsardaukar, mpsardaukar, mpsardaukar, mpsardaukar
|
||||
Type: sardaukar
|
||||
ChargeInterval: 2250
|
||||
EndChargeTextNotification: notification-fremen-ready
|
||||
ReadyAudio: Reinforce
|
||||
ReadyTextNotification: notification-reinforcements-have-arrived
|
||||
BlockedAudio: NoRoom
|
||||
BlockedTextNotification: notification-no-room-for-new-unit
|
||||
OrderName: ProduceActorPower.Fremen
|
||||
SupportPowerPaletteOrder: 2040
|
||||
GrantConditionOnFaction@corrino:
|
||||
Condition: corrino
|
||||
Factions: corrino
|
||||
Production@Corrino:
|
||||
Produces: sardaukar
|
||||
RequiresCondition: corrino
|
||||
|
||||
@@ -32,6 +32,7 @@ HarkonnenReinforcements =
|
||||
}
|
||||
|
||||
HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location }
|
||||
|
||||
HarkonnenAttackDelay = DateTime.Seconds(30)
|
||||
|
||||
HarkonnenAttackWaves =
|
||||
@@ -49,6 +50,7 @@ ToHarvest =
|
||||
}
|
||||
|
||||
OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" }
|
||||
|
||||
OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location }
|
||||
|
||||
Messages =
|
||||
@@ -118,14 +120,10 @@ WorldLoaded = function()
|
||||
end
|
||||
|
||||
Trigger.OnRemovedFromWorld(OrdosConyard, function()
|
||||
|
||||
-- Mission already failed, no need to check the other conditions as well
|
||||
if checkResourceCapacity() then
|
||||
return
|
||||
end
|
||||
if checkResourceCapacity() then return end
|
||||
|
||||
local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Ordos end)
|
||||
|
||||
if #refs == 0 then
|
||||
Harkonnen.MarkCompletedObjective(KillOrdos)
|
||||
else
|
||||
|
||||
@@ -32,6 +32,7 @@ HarkonnenReinforcements =
|
||||
}
|
||||
|
||||
HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location, HarkonnenWaypoint4.Location }
|
||||
|
||||
HarkonnenAttackDelay = DateTime.Seconds(30)
|
||||
|
||||
HarkonnenAttackWaves =
|
||||
@@ -49,6 +50,7 @@ ToHarvest =
|
||||
}
|
||||
|
||||
OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" }
|
||||
|
||||
OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location }
|
||||
|
||||
Messages =
|
||||
@@ -118,14 +120,10 @@ WorldLoaded = function()
|
||||
end
|
||||
|
||||
Trigger.OnRemovedFromWorld(OrdosConyard, function()
|
||||
|
||||
-- Mission already failed, no need to check the other conditions as well
|
||||
if checkResourceCapacity() then
|
||||
return
|
||||
end
|
||||
if checkResourceCapacity() then return end
|
||||
|
||||
local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Ordos end)
|
||||
|
||||
if #refs == 0 then
|
||||
Harkonnen.MarkCompletedObjective(KillOrdos)
|
||||
else
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -24,10 +24,13 @@ AttackDelays =
|
||||
HarkonnenInfantryTypes = { "light_inf" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Harkonnen] = {}
|
||||
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
|
||||
IdlingUnits[Harkonnen] = { }
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local toBuild = function() return HarkonnenInfantryTypes end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
|
||||
ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
]]
|
||||
|
||||
HarkonnenBase = { HConyard, HPower1, HPower2, HBarracks, HOutpost }
|
||||
|
||||
HarkonnenBaseAreaTrigger = { CPos.New(31, 37), CPos.New(32, 37), CPos.New(33, 37), CPos.New(34, 37), CPos.New(35, 37), CPos.New(36, 37), CPos.New(37, 37), CPos.New(38, 37), CPos.New(39, 37), CPos.New(40, 37), CPos.New(41, 37), CPos.New(42, 37), CPos.New(42, 38), CPos.New(42, 39), CPos.New(42, 40), CPos.New(42, 41), CPos.New(42, 42), CPos.New(42, 43), CPos.New(42, 44), CPos.New(42, 45), CPos.New(42, 46), CPos.New(42, 47), CPos.New(42, 48), CPos.New(42, 49) }
|
||||
|
||||
HarkonnenReinforcements =
|
||||
@@ -78,6 +79,7 @@ HarkonnenAttackWaves =
|
||||
}
|
||||
|
||||
OrdosReinforcements = { "light_inf", "light_inf", "raider" }
|
||||
|
||||
OrdosEntryPath = { OrdosEntry.Location, OrdosRally.Location }
|
||||
|
||||
Tick = function()
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -24,10 +24,14 @@ AttackDelays =
|
||||
HarkonnenInfantryTypes = { "light_inf" }
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Harkonnen] = {}
|
||||
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
|
||||
LastHarvesterEaten[Harkonnen] = true
|
||||
IdlingUnits[Harkonnen] = { }
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local toBuild = function() return HarkonnenInfantryTypes end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
|
||||
ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
|
||||
Binary file not shown.
@@ -143,6 +143,19 @@ Actors:
|
||||
HSilo4: silo
|
||||
Owner: Harkonnen
|
||||
Location: 4,60
|
||||
Actor3: crate
|
||||
Owner: Neutral
|
||||
Location: 53,25
|
||||
Actor9: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 63,64
|
||||
Actor10: crate_reveal
|
||||
Owner: Neutral
|
||||
Location: 11,35
|
||||
HPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 32,17
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -22,9 +22,16 @@ AttackDelays =
|
||||
}
|
||||
|
||||
HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
HarkonnenVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
InitAIUnits = function()
|
||||
Defending[Harkonnen] = { }
|
||||
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
|
||||
LastHarvesterEaten[Harkonnen] = true
|
||||
PatrolPoints[Harkonnen] = { HarkonnenRally3.Location, HPatrolPoint1.Location, Actor6.Location }
|
||||
DefencePerimeter[Harkonnen] = GetCellsInRectangle(CPos.New(3,42), CPos.New(13,63))
|
||||
IdlingUnits[Harkonnen] = Reinforcements.Reinforce(Harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath)
|
||||
|
||||
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
|
||||
@@ -37,14 +44,31 @@ ActivateAI = function()
|
||||
HConyard.Produce(OrdosUpgrades[1])
|
||||
HConyard.Produce(OrdosUpgrades[2])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
|
||||
local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
-- Finish the upgrades first before trying to build something
|
||||
Trigger.AfterDelay(DateTime.Seconds(14), function()
|
||||
ProduceUnits(Harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Harkonnen, HLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Harkonnen, HLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
if Difficulty ~= "easy" then
|
||||
Harkonnen.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
|
||||
table.insert(HarkonnenBase, building)
|
||||
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
]]
|
||||
|
||||
HarkonnenBase = { HBarracks, HWindTrap1, HWindTrap2, HLightFactory, HOutpost, HConyard, HRefinery, HSilo1, HSilo2, HSilo3, HSilo4 }
|
||||
|
||||
HarkonnenBaseAreaTrigger = { CPos.New(2, 58), CPos.New(3, 58), CPos.New(4, 58), CPos.New(5, 58), CPos.New(6, 58), CPos.New(7, 58), CPos.New(8, 58), CPos.New(9, 58), CPos.New(10, 58), CPos.New(11, 58), CPos.New(12, 58), CPos.New(13, 58), CPos.New(14, 58), CPos.New(15, 58), CPos.New(16, 58), CPos.New(16, 59), CPos.New(16, 60) }
|
||||
|
||||
HarkonnenReinforcements =
|
||||
@@ -65,15 +66,19 @@ HarkonnenPaths =
|
||||
}
|
||||
|
||||
HarkonnenHunters = { "light_inf", "light_inf", "trike", "quad" }
|
||||
|
||||
HarkonnenInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
|
||||
|
||||
HarkonnenHunterPath = { HarkonnenEntry5.Location, HarkonnenRally5.Location }
|
||||
|
||||
HarkonnenInitialPath = { HarkonnenEntry4.Location, HarkonnenRally4.Location }
|
||||
|
||||
OrdosReinforcements = { "quad", "raider" }
|
||||
|
||||
OrdosPath = { OrdosEntry.Location, OrdosRally.Location }
|
||||
|
||||
OrdosBaseBuildings = { "barracks", "light_factory" }
|
||||
|
||||
OrdosUpgrades = { "upgrade.barracks", "upgrade.light" }
|
||||
|
||||
MessageCheck = function(index)
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 5000
|
||||
ExternalCondition@AIMain:
|
||||
Condition: base-rebuilder
|
||||
BaseBuilderBotModule@Harkonnen:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -254,6 +254,16 @@ Actors:
|
||||
HarkonnenEntry8: waypoint
|
||||
Owner: Neutral
|
||||
Location: 2,20
|
||||
Actor1: harvester.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 30,41
|
||||
HPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 18,38
|
||||
HPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 47,21
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
|
||||
@@ -22,29 +22,59 @@ AttackDelays =
|
||||
}
|
||||
|
||||
HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
HarkonnenVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
InitAIUnits = function()
|
||||
IdlingUnits[Harkonnen] = Reinforcements.Reinforce(Harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath)
|
||||
|
||||
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
|
||||
end
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Harkonnen] = {}
|
||||
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
|
||||
LastHarvesterEaten[Harkonnen] = true
|
||||
HarvesterCount[Harkonnen] = 0
|
||||
PatrolPoints[Harkonnen] = { HPatrolPoint1.Location, HPatrolPoint2.Location, HarkonnenRally7.Location }
|
||||
DefencePerimeter[Harkonnen] = Utils.Concat(GetCellsInRectangle(CPos.New(35,37), CPos.New(54,51)), GetCellsInRectangle(CPos.New(45,28), CPos.New(58,36)))
|
||||
Trigger.AfterDelay(0, InitAIUnits)
|
||||
|
||||
HConyard.Produce(OrdosUpgrades[1])
|
||||
HConyard.Produce(OrdosUpgrades[2])
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
else
|
||||
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end
|
||||
local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
-- Finish the upgrades first before trying to build something
|
||||
Trigger.AfterDelay(DateTime.Seconds(14), function()
|
||||
ProduceUnits(Harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Harkonnen, HLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(Harkonnen, HLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
if Difficulty ~= "easy" then
|
||||
Harkonnen.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
|
||||
table.insert(HarkonnenBase, building)
|
||||
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
]]
|
||||
|
||||
HarkonnenBase = { HBarracks, HWindTrap1, HWindTrap2, HWindTrap3, HWindTrap4, HLightFactory, HOutpost, HConyard, HRefinery, HSilo1, HSilo2, HSilo3, HSilo4 }
|
||||
|
||||
HarkonnenBaseAreaTrigger = { CPos.New(2, 58), CPos.New(3, 58), CPos.New(4, 58), CPos.New(5, 58), CPos.New(6, 58), CPos.New(7, 58), CPos.New(8, 58), CPos.New(9, 58), CPos.New(10, 58), CPos.New(11, 58), CPos.New(12, 58), CPos.New(13, 58), CPos.New(14, 58), CPos.New(15, 58), CPos.New(16, 58), CPos.New(16, 59), CPos.New(16, 60) }
|
||||
|
||||
HarkonnenReinforcements =
|
||||
@@ -79,6 +80,7 @@ HarkonnenHunterPaths =
|
||||
}
|
||||
|
||||
HarkonnenInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
|
||||
|
||||
HarkonnenInitialPath = { HarkonnenEntry4.Location, HarkonnenRally4.Location }
|
||||
|
||||
OrdosReinforcements =
|
||||
@@ -103,6 +105,7 @@ OrdosReinforcementDelays =
|
||||
}
|
||||
|
||||
OrdosBaseBuildings = { "barracks", "light_factory" }
|
||||
|
||||
OrdosUpgrades = { "upgrade.barracks", "upgrade.light" }
|
||||
|
||||
MessageCheck = function(index)
|
||||
@@ -129,7 +132,6 @@ Tick = function()
|
||||
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Harkonnen] then
|
||||
local units = Harkonnen.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[Harkonnen] = false
|
||||
ProtectHarvester(units[1], Harkonnen, AttackGroupSize[Difficulty])
|
||||
|
||||
@@ -1,6 +1,32 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 5000
|
||||
ExternalCondition@AIMain:
|
||||
Condition: base-rebuilder
|
||||
BaseBuilderBotModule@Harkonnen:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -66,6 +66,7 @@ Actors:
|
||||
HGunTurret1: medium_gun_turret
|
||||
Location: 38,3
|
||||
Owner: Harkonnen
|
||||
TurretFacing: 512
|
||||
Actor3: wall
|
||||
Location: 42,3
|
||||
Owner: Smugglers
|
||||
@@ -87,6 +88,7 @@ Actors:
|
||||
HGunTurret2: medium_gun_turret
|
||||
Location: 38,7
|
||||
Owner: Harkonnen
|
||||
TurretFacing: 512
|
||||
Actor10: trooper
|
||||
Location: 39,7
|
||||
Owner: Harkonnen
|
||||
@@ -300,6 +302,7 @@ Actors:
|
||||
SGunTurret3: medium_gun_turret
|
||||
Location: 57,20
|
||||
Owner: Smugglers
|
||||
TurretFacing: 512
|
||||
HPower1: wind_trap
|
||||
Location: 44,21
|
||||
Owner: Harkonnen
|
||||
@@ -330,6 +333,7 @@ Actors:
|
||||
HGunTurret3: medium_gun_turret
|
||||
Location: 47,29
|
||||
Owner: Harkonnen
|
||||
TurretFacing: 512
|
||||
Actor97: wall
|
||||
Location: 48,29
|
||||
Owner: Harkonnen
|
||||
@@ -348,6 +352,7 @@ Actors:
|
||||
HGunTurret4: medium_gun_turret
|
||||
Location: 11,32
|
||||
Owner: Harkonnen
|
||||
TurretFacing: 512
|
||||
Actor103: light_inf
|
||||
Location: 12,32
|
||||
Owner: Harkonnen
|
||||
@@ -378,15 +383,6 @@ Actors:
|
||||
Actor112: wall
|
||||
Location: 17,36
|
||||
Owner: Harkonnen
|
||||
Actor113: trike
|
||||
Location: 37,39
|
||||
Owner: Harkonnen
|
||||
Actor114: trike
|
||||
Location: 39,39
|
||||
Owner: Harkonnen
|
||||
Actor115: trike
|
||||
Location: 41,39
|
||||
Owner: Harkonnen
|
||||
Actor116: spicebloom.spawnpoint
|
||||
Location: 7,40
|
||||
Owner: Neutral
|
||||
@@ -396,9 +392,6 @@ Actors:
|
||||
Actor118: wall
|
||||
Location: 38,40
|
||||
Owner: Harkonnen
|
||||
Actor119: light_inf
|
||||
Location: 42,40
|
||||
Owner: Harkonnen
|
||||
Actor120: wall
|
||||
Location: 37,41
|
||||
Owner: Harkonnen
|
||||
@@ -516,6 +509,24 @@ Actors:
|
||||
Actor152: wall
|
||||
Owner: Smugglers
|
||||
Location: 49,19
|
||||
HPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 13,42
|
||||
HPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 47,40
|
||||
HPatrol1: trike
|
||||
Location: 37,39
|
||||
Owner: Harkonnen
|
||||
HPatrol2: trike
|
||||
Location: 39,39
|
||||
Owner: Harkonnen
|
||||
HPatrol3: trike
|
||||
Location: 41,39
|
||||
Owner: Harkonnen
|
||||
HPatrol4: light_inf
|
||||
Location: 42,40
|
||||
Owner: Harkonnen
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
ProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -24,23 +24,42 @@ AttackDelays =
|
||||
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
HarkonnenVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
HarkonnenTankType = { "combat_tank_h" }
|
||||
|
||||
SmugglerVehicleTypes = { "raider", "raider", "quad" }
|
||||
|
||||
SmugglerTankType = { "combat_tank_o" }
|
||||
|
||||
InitAIUnits = function(house)
|
||||
LastHarvesterEaten[house] = true
|
||||
IdlingUnits[house] = Reinforcements.Reinforce(house, InitialReinforcements[house.InternalName], InitialReinforcementsPaths[house.InternalName])
|
||||
|
||||
DefendAndRepairBase(house, Base[house.InternalName], 0.75, AttackGroupSize[Difficulty])
|
||||
end
|
||||
|
||||
ActivateAI = function()
|
||||
Defending[Harkonnen] = { }
|
||||
Defending[Smuggler] = { }
|
||||
AttackDelay[Harkonnen] = 7000
|
||||
AttackDelay[Smuggler] = 7000
|
||||
TimeBetweenAttacks[Harkonnen] = 8000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[Smuggler] = 15000 * DifficultyModifier[Difficulty]
|
||||
HarvesterCount[Harkonnen] = 2
|
||||
HarvesterCount[Smuggler] = 0
|
||||
PatrolPoints[Harkonnen] = { HPatrolPoint1.Location, HPatrolPoint2.Location, HarkonnenRally2.Location }
|
||||
DefencePerimeter[Harkonnen] = GetCellsInRectangle(CPos.New(23,3), CPos.New(41,22))
|
||||
DefencePerimeter[Smuggler] = Utils.Concat(GetCellsInRectangle(CPos.New(57,15), CPos.New(65, 24)), GetCellsInRectangle(CPos.New(43,4), CPos.New(54, 16)))
|
||||
InitAIUnits(Harkonnen)
|
||||
InitAIUnits(Smuggler)
|
||||
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
else
|
||||
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
|
||||
local hVehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
|
||||
local hTanksToBuild = function() return HarkonnenTankType end
|
||||
@@ -55,4 +74,29 @@ ActivateAI = function()
|
||||
ProduceUnits(Smuggler, SBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
|
||||
ProduceUnits(Smuggler, SLightFactory, delay, sVehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
|
||||
ProduceUnits(Smuggler, SHeavyFactory, delay, sTanksToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
|
||||
|
||||
ActivateCrushLogic()
|
||||
|
||||
AIProductionActivated = true
|
||||
if Difficulty == "normal" then
|
||||
Harkonnen.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
Harkonnen.GrantCondition("defense-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = hVehiclesToBuild,
|
||||
heavy_factory = hTanksToBuild
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
|
||||
table.insert(Base[Harkonnen], building)
|
||||
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -73,7 +73,6 @@ end
|
||||
CheckHarvester = function(house)
|
||||
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[house] then
|
||||
local units = house.GetActorsByType("harvester")
|
||||
|
||||
if #units > 0 then
|
||||
LastHarvesterEaten[house] = false
|
||||
ProtectHarvester(units[1], house, AttackGroupSize[Difficulty])
|
||||
@@ -131,6 +130,7 @@ WorldLoaded = function()
|
||||
Trigger.OnKilled(SOutpost, function()
|
||||
Ordos.MarkFailedObjective(CaptureOutpost)
|
||||
end)
|
||||
|
||||
Trigger.OnCapture(SOutpost, function()
|
||||
Trigger.AfterDelay(DateTime.Seconds(2), function()
|
||||
Ordos.MarkCompletedObjective(CaptureOutpost)
|
||||
@@ -138,6 +138,7 @@ WorldLoaded = function()
|
||||
end)
|
||||
SOutpost.GrantCondition("modified")
|
||||
end)
|
||||
|
||||
Trigger.OnDamaged(SOutpost, function(_, attacker)
|
||||
if SOutpost.Owner ~= Smuggler or attacker.IsDead or attacker.Owner ~= Ordos then
|
||||
return
|
||||
@@ -157,4 +158,14 @@ WorldLoaded = function()
|
||||
Trigger.AfterDelay(HarkonnenAttackDelay[Difficulty], function()
|
||||
Media.DisplayMessage(UserInterface.GetFluentMessage("warning-large-force-approaching"), Mentat)
|
||||
end)
|
||||
|
||||
Trigger.OnKilled(HGunTurret4, function()
|
||||
if #IdlingUnits[Harkonnen] > 10 then
|
||||
CheckArea(Harkonnen, HarkonnenRally1.Location, 10)
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnAnyKilled({HPatrol1, HPatrol2, HPatrol3, HPatrol4}, function()
|
||||
CheckArea(Harkonnen, HPatrolPoint2.Location, 10)
|
||||
end)
|
||||
end
|
||||
|
||||
@@ -1,6 +1,64 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 5000
|
||||
ExternalCondition@AIMain:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIMainDefense:
|
||||
Condition: defense-rebuilder
|
||||
BaseBuilderBotModule@Harkonnen:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@HarkonnenDefense:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 4
|
||||
silo: 1
|
||||
medium_gun_turret: 3
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
medium_gun_turret: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
Binary file not shown.
@@ -570,6 +570,28 @@ Actors:
|
||||
AtreidesEntry8: waypoint
|
||||
Owner: Neutral
|
||||
Location: 2,58
|
||||
APatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 51,17
|
||||
APatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 52,44
|
||||
Actor1: carryall.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 60,41
|
||||
Actor2: crate_explosion
|
||||
Owner: Neutral
|
||||
Location: 41,60
|
||||
Actor6: crate_explosion
|
||||
Owner: Neutral
|
||||
Location: 42,60
|
||||
Actor8: crate_explosion
|
||||
Owner: Neutral
|
||||
Location: 42,59
|
||||
Actor7: crate_explosion
|
||||
Owner: Neutral
|
||||
Location: 41,59
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
@@ -7,6 +7,31 @@
|
||||
information, see COPYING.
|
||||
]]
|
||||
|
||||
EarlyGameStage = DateTime.Minutes(5)
|
||||
|
||||
InitialProductionDelay = {
|
||||
AtreidesMain =
|
||||
{
|
||||
easy = DateTime.Seconds(130),
|
||||
normal = DateTime.Seconds(80),
|
||||
hard = DateTime.Seconds(50)
|
||||
},
|
||||
|
||||
AtreidesSmall1 =
|
||||
{
|
||||
easy = DateTime.Seconds(120),
|
||||
normal = DateTime.Seconds(60),
|
||||
hard = DateTime.Seconds(30)
|
||||
},
|
||||
|
||||
AtreidesSmall2 =
|
||||
{
|
||||
easy = DateTime.Seconds(60),
|
||||
normal = DateTime.Seconds(30),
|
||||
hard = DateTime.Seconds(0)
|
||||
},
|
||||
}
|
||||
|
||||
AttackGroupSize =
|
||||
{
|
||||
easy = 6,
|
||||
@@ -14,7 +39,14 @@ AttackGroupSize =
|
||||
hard = 10
|
||||
}
|
||||
|
||||
AttackDelays =
|
||||
EarlyProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(7), DateTime.Seconds(11) },
|
||||
normal = { DateTime.Seconds(5), DateTime.Seconds(7) },
|
||||
hard = { DateTime.Seconds(3), DateTime.Seconds(5) }
|
||||
}
|
||||
|
||||
LateProductionDelays =
|
||||
{
|
||||
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
|
||||
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
|
||||
@@ -22,7 +54,9 @@ AttackDelays =
|
||||
}
|
||||
|
||||
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
|
||||
|
||||
EnemyVehicleTypes = { "trike", "trike", "quad" }
|
||||
|
||||
EnemyTankType = { "combat_tank_a" }
|
||||
|
||||
InitAIUnits = function(house)
|
||||
@@ -37,21 +71,60 @@ InitAIUnits = function(house)
|
||||
end
|
||||
|
||||
ActivateAIProduction = function()
|
||||
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
|
||||
local delay = function(player)
|
||||
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
|
||||
return 1
|
||||
end
|
||||
if EarlyGameStage >= DateTime.GameTime then
|
||||
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
|
||||
else
|
||||
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
|
||||
end
|
||||
end
|
||||
|
||||
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
|
||||
local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
|
||||
local tanksToBuild = function() return EnemyTankType end
|
||||
local attackTresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
|
||||
|
||||
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
|
||||
ProduceUnits(AtreidesMain, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
|
||||
ProduceUnits(AtreidesMain, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function()
|
||||
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
ProduceUnits(AtreidesMain, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ProduceUnits(AtreidesSmall1, ABarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall1"][Difficulty], function()
|
||||
ProduceUnits(AtreidesSmall1, ABarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ProduceUnits(AtreidesSmall2, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
|
||||
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall2"][Difficulty], function()
|
||||
ProduceUnits(AtreidesSmall2, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
|
||||
ActivateCrushLogic()
|
||||
AIProductionActivated = true
|
||||
|
||||
if Difficulty == "normal" then
|
||||
AtreidesMain.GrantCondition("base-rebuilder")
|
||||
end
|
||||
|
||||
if Difficulty == "hard" then
|
||||
AtreidesMain.GrantCondition("defense-rebuilder")
|
||||
end
|
||||
|
||||
local productionTypes =
|
||||
{
|
||||
barracks = infantryToBuild,
|
||||
light_factory = vehiclesToBuild,
|
||||
heavy_factory = tanksToBuild
|
||||
}
|
||||
|
||||
Trigger.OnBuildingPlaced(AtreidesMain, function(p, building)
|
||||
table.insert(Base[AtreidesMainBase], building)
|
||||
DefendAndRepairBase(AtreidesMain, {building}, 0.75, AttackGroupSize[Difficulty] )
|
||||
if productionTypes[building.Type] == nil then return end
|
||||
ProduceUnits(AtreidesMain, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
|
||||
end)
|
||||
end
|
||||
|
||||
ActivateAI = function()
|
||||
@@ -59,4 +132,19 @@ ActivateAI = function()
|
||||
InitAIUnits(AtreidesSmall1)
|
||||
InitAIUnits(AtreidesSmall2)
|
||||
InitAIUnits(AtreidesSmall3)
|
||||
Defending[AtreidesMain] = {}
|
||||
Defending[AtreidesSmall1] = {}
|
||||
Defending[AtreidesSmall2] = {}
|
||||
Defending[AtreidesSmall3] = {}
|
||||
AttackDelay[AtreidesMain] = 14000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[AtreidesSmall1] = 14000 * DifficultyModifier[Difficulty]
|
||||
AttackDelay[AtreidesSmall2] = 14000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[AtreidesMain] = 7000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[AtreidesSmall1] = 9000 * DifficultyModifier[Difficulty]
|
||||
TimeBetweenAttacks[AtreidesSmall2] = 9000 * DifficultyModifier[Difficulty]
|
||||
HarvesterCount[AtreidesMain] = 2
|
||||
PatrolPoints[AtreidesMain] = { APatrolPoint1.Location, APatrolPoint2.Location, AtreidesRally8.Location }
|
||||
DefencePerimeter[AtreidesMain] = GetCellsInRectangle(CPos.New(3,3), CPos.New(18,27))
|
||||
DefencePerimeter[AtreidesSmall1] = GetCellsInRectangle(CPos.New(29,17), CPos.New(34,29))
|
||||
DefencePerimeter[AtreidesSmall2] = GetCellsInRectangle(CPos.New(39,46), CPos.New(48,59))
|
||||
end
|
||||
|
||||
@@ -109,6 +109,16 @@ CheckHarvester = function(house)
|
||||
end
|
||||
|
||||
CachedResources = -1
|
||||
EmergencyBehaviour = function(player, target)
|
||||
HoldProduction[player] = false
|
||||
if Difficulty == "hard" then
|
||||
player.Cash = player.Cash + 2000
|
||||
end
|
||||
if player == AtreidesSmall2 and #IdlingUnits[AtreidesMain] > 10 then
|
||||
CheckArea(AtreidesMain, target, 10)
|
||||
end
|
||||
end
|
||||
|
||||
Tick = function()
|
||||
if Ordos.Resources > SpiceToHarvest - 1 then
|
||||
Ordos.MarkCompletedObjective(GatherSpice)
|
||||
@@ -215,11 +225,13 @@ WorldLoaded = function()
|
||||
APower9.Sell()
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnKilledOrCaptured(APower8, function()
|
||||
if not AIProductionActivated then
|
||||
ActivateAIProduction()
|
||||
end
|
||||
end)
|
||||
|
||||
Trigger.OnKilledOrCaptured(APower9, function()
|
||||
if not AIProductionActivated then
|
||||
ActivateAIProduction()
|
||||
|
||||
@@ -1,6 +1,64 @@
|
||||
Player:
|
||||
PlayerResources:
|
||||
DefaultCash: 6000
|
||||
ExternalCondition@AIMain:
|
||||
Condition: base-rebuilder
|
||||
ExternalCondition@AIMainDefense:
|
||||
Condition: defense-rebuilder
|
||||
BaseBuilderBotModule@AtriedesMain:
|
||||
RequiresCondition: base-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret,large_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 3
|
||||
silo: 1
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
BaseBuilderBotModule@AtriedesMainDefense:
|
||||
RequiresCondition: defense-rebuilder
|
||||
BuildingQueues: Building, Upgrade
|
||||
MinimumExcessPower: 0
|
||||
MaximumExcessPower: 250
|
||||
MaxBaseRadius: 40
|
||||
ConstructionYardTypes: construction_yard
|
||||
RefineryTypes: refinery
|
||||
PowerTypes: wind_trap
|
||||
ProductionTypes: light_factory, heavy_factory, barracks
|
||||
SiloTypes: silo
|
||||
DefenseTypes: medium_gun_turret
|
||||
SellRefineryInterval: -1
|
||||
BuildingLimits:
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
wind_trap: 3
|
||||
silo: 1
|
||||
medium_gun_turret: 5
|
||||
BuildingFractions:
|
||||
wind_trap: 1
|
||||
barracks: 1
|
||||
refinery: 1
|
||||
light_factory: 1
|
||||
heavy_factory: 1
|
||||
medium_gun_turret: 1
|
||||
|
||||
World:
|
||||
LuaScript:
|
||||
|
||||
@@ -576,6 +576,25 @@ Actors:
|
||||
HarkonnenEntry7: waypoint
|
||||
Owner: Neutral
|
||||
Location: 34,2
|
||||
APatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 46,7
|
||||
APatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 10,45
|
||||
HPatrolPoint1: waypoint
|
||||
Owner: Neutral
|
||||
Location: 40,49
|
||||
HPatrolPoint2: waypoint
|
||||
Owner: Neutral
|
||||
Location: 62,76
|
||||
Actor2: frigate.debris
|
||||
Owner: Creeps
|
||||
Location: 73,55
|
||||
Actor1: missile_tank.debris
|
||||
Owner: Creeps
|
||||
Facing: 384
|
||||
Location: 72,53
|
||||
|
||||
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user