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:
N.N
2026-01-27 10:11:07 +00:00
committed by Gustas Kažukauskas
parent 0a933ba09c
commit 3a86c035b3
107 changed files with 5292 additions and 454 deletions

View File

@@ -76,6 +76,7 @@ smuggler-leader = Smuggler Leader.
were-warned-will-pay = You were warned. Now you will pay. were-warned-will-pay = You were warned. Now you will pay.
destroy-smugglers-mercenaries = Destroy the Smugglers and their mercenaries. destroy-smugglers-mercenaries = Destroy the Smugglers and their mercenaries.
capture-harkonnen-barracks-release-hostages = Capture the Harkonnen barracks to release the hostages. 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 ## harkonnen-01ab, harkonnen-03ab
eliminate-atreides-units-reinforcements = Eliminate all Atreides forces and reinforcements in the area. eliminate-atreides-units-reinforcements = Eliminate all Atreides forces and reinforcements in the area.
@@ -112,6 +113,8 @@ destroy-ordos = Destroy the Ordos.
## harkonnen-06ab ## harkonnen-06ab
ixian-transports-detected = Ixian transports detected. ixian-transports-detected = Ixian transports detected.
capture-destroy-ordos-starport = Capture or destroy the Ordos Starport. 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 ## harkonnen-06ab, harkonnen-09ab
smugglers-now-hostile = The Smugglers are now hostile! smugglers-now-hostile = The Smugglers are now hostile!
@@ -132,6 +135,8 @@ atreides-commander = Atreides Commander
## harkonnen-09ab ## harkonnen-09ab
build-deploy-mcv = Build and deploy an MCV to establish a Construction Yard. 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 ## ordos-01ab, ordos-02ab, ordos-03ab, ordos-04, ordos-05
outpost-not-captured-destroyed = Do not let the Outpost be captured or destroyed. outpost-not-captured-destroyed = Do not let the Outpost be captured or destroyed.

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -25,10 +25,13 @@ HarkonnenInfantryTypes = { "light_inf" }
ActivateAI = function() ActivateAI = function()
IdlingUnits[Harkonnen] = { } IdlingUnits[Harkonnen] = { }
Defending[Harkonnen] = { }
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[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 toBuild = function() return HarkonnenInfantryTypes end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end end

View File

@@ -168,6 +168,13 @@ Actors:
HarkonnenRally4: waypoint HarkonnenRally4: waypoint
Owner: Neutral Owner: Neutral
Location: 30,28 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -25,10 +25,14 @@ HarkonnenInfantryTypes = { "light_inf" }
ActivateAI = function() ActivateAI = function()
IdlingUnits[Harkonnen] = { } IdlingUnits[Harkonnen] = { }
Defending[Harkonnen] = {}
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Harkonnen] = true
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[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 toBuild = function() return HarkonnenInfantryTypes end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end end

View File

@@ -138,6 +138,9 @@ Actors:
HarkonnenRally4: waypoint HarkonnenRally4: waypoint
Owner: Neutral Owner: Neutral
Location: 30,28 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -13,7 +13,8 @@ AttackGroupSize =
normal = 8, normal = 8,
hard = 10 hard = 10
} }
AttackDelays =
ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -33,13 +34,16 @@ InitAIUnits = function()
end end
ActivateAI = function() ActivateAI = function()
Defending[Ordos] = { }
AttackDelay[Ordos] = 12000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Ordos] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Ordos] = true LastHarvesterEaten[Ordos] = true
Trigger.AfterDelay(0, InitAIUnits) Trigger.AfterDelay(0, InitAIUnits)
OConyard.Produce(AtreidesUpgrades[1]) OConyard.Produce(AtreidesUpgrades[1])
OConyard.Produce(AtreidesUpgrades[2]) 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 infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
@@ -49,4 +53,22 @@ ActivateAI = function()
ProduceUnits(Ordos, OBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Ordos, OBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Ordos, OLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end) 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 end

View File

@@ -143,7 +143,6 @@ WorldLoaded = function()
end end
Trigger.OnRemovedFromWorld(AConyard, function() Trigger.OnRemovedFromWorld(AConyard, function()
-- Mission already failed, no need to check the other conditions as well -- Mission already failed, no need to check the other conditions as well
if checkResourceCapacity() then if checkResourceCapacity() then
return return

Binary file not shown.

View File

@@ -135,6 +135,20 @@ Actors:
OrdosRally2: waypoint OrdosRally2: waypoint
Owner: Neutral Owner: Neutral
Location: 39,30 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,33 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 3000 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: World:
LuaScript: LuaScript:

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(7) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -24,6 +24,10 @@ AttackDelays =
OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
InitAIUnits = function() 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]) IdlingUnits[Ordos] = Reinforcements.Reinforce(Ordos, InitialOrdosReinforcements, OrdosPaths[2])
DefendAndRepairBase(Ordos, OrdosBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Ordos, OrdosBase, 0.75, AttackGroupSize[Difficulty])
end end
@@ -34,7 +38,7 @@ ActivateAI = function()
OConyard.Produce(AtreidesUpgrades[1]) 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 toBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
@@ -42,4 +46,29 @@ ActivateAI = function()
Trigger.AfterDelay(DateTime.Seconds(14), function() Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Ordos, OBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Ordos, OBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end) 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 end

View File

@@ -9,6 +9,8 @@
OrdosBase = { OBarracks, OWindTrap1, OWindTrap2, OOutpost, OConyard, ORefinery, OSilo } OrdosBase = { OBarracks, OWindTrap1, OWindTrap2, OOutpost, OConyard, ORefinery, OSilo }
OrdosScouts = { OScout1, OScout2, OScout3 }
OrdosReinforcements = OrdosReinforcements =
{ {
easy = easy =
@@ -143,7 +145,6 @@ WorldLoaded = function()
end end
Trigger.OnRemovedFromWorld(AConyard, function() Trigger.OnRemovedFromWorld(AConyard, function()
-- Mission already failed, no need to check the other conditions as well -- Mission already failed, no need to check the other conditions as well
if checkResourceCapacity() then if checkResourceCapacity() then
return return
@@ -176,4 +177,10 @@ WorldLoaded = function()
Media.PlaySpeechNotification(Atreides, "Reinforce") Media.PlaySpeechNotification(Atreides, "Reinforce")
Reinforcements.ReinforceWithTransport(Atreides, "carryall.reinforce", AtreidesReinforcements, AtreidesPath, { AtreidesPath[1] }) Reinforcements.ReinforceWithTransport(Atreides, "carryall.reinforce", AtreidesReinforcements, AtreidesPath, { AtreidesPath[1] })
end) end)
Trigger.OnDamaged(HarvesterDebris, function(self, attacker)
if self.MaxHealth / 2 > self.Health then
self.Deploy()
end
end)
end end

Binary file not shown.

View File

@@ -48,24 +48,9 @@ Actors:
Actor3: wormspawner Actor3: wormspawner
Location: 27,14 Location: 27,14
Owner: Creeps 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 Actor12: light_inf
Location: 18,37 Location: 18,37
Owner: Ordos Owner: Ordos
Actor13: trooper
Location: 19,39
Owner: Ordos
Actor14: light_inf Actor14: light_inf
Location: 34,50 Location: 34,50
Owner: Ordos Owner: Ordos
@@ -132,6 +117,33 @@ Actors:
OrdosRally2: waypoint OrdosRally2: waypoint
Owner: Neutral Owner: Neutral
Location: 15,34 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,32 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 3000 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: World:
LuaScript: LuaScript:

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(7) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -26,22 +26,28 @@ HarkonnenTankType = { "combat_tank_h" }
-- Overwrite the template function because of the message -- Overwrite the template function because of the message
SendAttack = function(owner, size) SendAttack = function(owner, size)
if Attacking[owner] then if Attacking[owner] then return end
return
end
Attacking[owner] = true Attacking[owner] = true
HoldProduction[owner] = true HoldProduction[owner] = true
local units = SetupAttackGroup(owner, size) local units = SetupAttackGroup(owner, size)
Utils.Do(units, IdleHunt) Utils.Do(units, Trigger.ClearAll)
if #units > 0 then if #units > 0 then
Media.DisplayMessage(UserInterface.GetFluentMessage("harkonnen-units-approaching"), UserInterface.GetFluentMessage("fremen-leader")) Media.DisplayMessage(UserInterface.GetFluentMessage("harkonnen-units-approaching"), UserInterface.GetFluentMessage("fremen-leader"))
end end
Trigger.OnAllRemovedFromWorld(units, function() Trigger.AfterDelay(1, function()
Attacking[owner] = false Utils.Do(units, function(u)
HoldProduction[owner] = false u.Stop()
IdleHunt(u)
end)
Trigger.OnAllRemovedFromWorld(units, function()
Attacking[owner] = false
HoldProduction[owner] = false
end)
end) end)
end end
@@ -52,15 +58,34 @@ InitAIUnits = function()
end end
ActivateAI = function() ActivateAI = function()
Defending[Harkonnen] = {}
HarvesterCount[Harkonnen] = 2
AttackDelay[Harkonnen] = 9000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 9000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Harkonnen] = true LastHarvesterEaten[Harkonnen] = true
InitAIUnits() InitAIUnits()
FremenProduction() 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 infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end
local tanksToBuild = function() return HarkonnenTankType end local tanksToBuild = function() return HarkonnenTankType end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(Harkonnen, HarkonnenBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Harkonnen, HarkonnenBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Harkonnen, HarkonnenHeavyFact, delay, tanksToBuild, 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 end

View File

@@ -48,8 +48,8 @@ HarkonnenReinforcements =
HarkonnenAttackDelay = HarkonnenAttackDelay =
{ {
easy = DateTime.Minutes(3), easy = DateTime.Minutes(3),
normal = DateTime.Minutes(2) + DateTime.Seconds(20), normal = DateTime.Minutes(2) + DateTime.Seconds(30),
hard = DateTime.Minutes(1) hard = DateTime.Minutes(2)
} }
HarkonnenAttackWaves = HarkonnenAttackWaves =
@@ -74,6 +74,7 @@ AtreidesReinforcements =
{ "trike", "combat_tank_a", "combat_tank_a" }, { "trike", "combat_tank_a", "combat_tank_a" },
{ "quad", "combat_tank_a", "combat_tank_a" } { "quad", "combat_tank_a", "combat_tank_a" }
} }
AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location } AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location }
FremenInterval = FremenInterval =
@@ -85,9 +86,9 @@ FremenInterval =
IntegrityLevel = IntegrityLevel =
{ {
easy = 50, easy = 10,
normal = 75, normal = 50,
hard = 100 hard = 90
} }
FremenProduction = function() FremenProduction = function()
@@ -145,7 +146,7 @@ WorldLoaded = function()
ProtectFremen = AddPrimaryObjective(Atreides, "protect-fremen-sietch") ProtectFremen = AddPrimaryObjective(Atreides, "protect-fremen-sietch")
KillHarkonnen = AddPrimaryObjective(Atreides, "destroy-harkonnen") KillHarkonnen = AddPrimaryObjective(Atreides, "destroy-harkonnen")
local keepSietchIntact = UserInterface.GetFluentMessage("keep-sietch-intact", { ["integrity"] = IntegrityLevel[Difficulty] }) local keepSietchIntact = UserInterface.GetFluentMessage("keep-sietch-intact", { ["integrity"] = IntegrityLevel[Difficulty] })
KeepIntegrity = AddPrimaryObjective(Atreides, keepSietchIntact) KeepIntegrity = AddSecondaryObjective(Atreides, keepSietchIntact)
Camera.Position = AConyard.CenterPosition Camera.Position = AConyard.CenterPosition
HarkonnenAttackLocation = AConyard.Location HarkonnenAttackLocation = AConyard.Location
@@ -164,6 +165,7 @@ WorldLoaded = function()
UserInterface.SetMissionText(UserInterface.GetFluentMessage("sietch-destroyed"), Atreides.Color) UserInterface.SetMissionText(UserInterface.GetFluentMessage("sietch-destroyed"), Atreides.Color)
Atreides.MarkFailedObjective(ProtectFremen) Atreides.MarkFailedObjective(ProtectFremen)
end) end)
Trigger.OnDamaged(Sietch, function() Trigger.OnDamaged(Sietch, function()
if AttackNotifier <= 0 then if AttackNotifier <= 0 then
AttackNotifier = DateTime.Seconds(10) AttackNotifier = DateTime.Seconds(10)
@@ -185,6 +187,7 @@ WorldLoaded = function()
unit.AttackMove(HarkonnenAttackLocation) unit.AttackMove(HarkonnenAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end end
SendCarryallReinforcements(Harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty], waveCondition, huntFunction) SendCarryallReinforcements(Harkonnen, 0, HarkonnenAttackWaves[Difficulty], HarkonnenAttackDelay[Difficulty], path, HarkonnenReinforcements[Difficulty], waveCondition, huntFunction)
Actor.Create("upgrade.barracks", true, { Owner = Harkonnen }) Actor.Create("upgrade.barracks", true, { Owner = Harkonnen })
@@ -194,6 +197,7 @@ WorldLoaded = function()
Media.PlaySpeechNotification(Atreides, "Reinforce") Media.PlaySpeechNotification(Atreides, "Reinforce")
Reinforcements.Reinforce(Atreides, AtreidesReinforcements[1], AtreidesPath) Reinforcements.Reinforce(Atreides, AtreidesReinforcements[1], AtreidesPath)
end) end)
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(40), function() Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(40), function()
Media.PlaySpeechNotification(Atreides, "Reinforce") Media.PlaySpeechNotification(Atreides, "Reinforce")
Reinforcements.ReinforceWithTransport(Atreides, "carryall.reinforce", AtreidesReinforcements[2], AtreidesPath, { AtreidesPath[1] }) Reinforcements.ReinforceWithTransport(Atreides, "carryall.reinforce", AtreidesReinforcements[2], AtreidesPath, { AtreidesPath[1] })

Binary file not shown.

View File

@@ -413,7 +413,44 @@ Actors:
Location: 5,23 Location: 5,23
FremenRally: waypoint FremenRally: waypoint
Owner: Neutral 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -7,6 +7,17 @@
information, see COPYING. information, see COPYING.
]] ]]
EarlyGameStage = DateTime.Minutes(5)
InitialProductionDelay = {
HarkonnenMain =
{
easy = DateTime.Seconds(100),
normal = DateTime.Seconds(60),
hard = DateTime.Seconds(30)
}
}
AttackGroupSize = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,7 +25,14 @@ AttackGroupSize =
hard = 10 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) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,7 +40,9 @@ AttackDelays =
} }
HarkonnenInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" } HarkonnenInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
HarkonnenVehicleTypes = { "trike", "trike", "trike", "quad", "quad" } HarkonnenVehicleTypes = { "trike", "trike", "trike", "quad", "quad" }
HarkonnenTankType = { "combat_tank_h" } HarkonnenTankType = { "combat_tank_h" }
InitAIUnits = function() InitAIUnits = function()
@@ -49,7 +69,13 @@ ProduceInfantry = function()
return return
end 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) } local toBuild = { Utils.Random(HarkonnenInfantryTypes) }
Harkonnen.Build(toBuild, function(unit) Harkonnen.Build(toBuild, function(unit)
IdlingUnits[Harkonnen][#IdlingUnits[Harkonnen] + 1] = unit[1] IdlingUnits[Harkonnen][#IdlingUnits[Harkonnen] + 1] = unit[1]
@@ -63,15 +89,56 @@ end
ActivateAI = function() ActivateAI = function()
Harkonnen.Cash = 15000 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 LastHarvesterEaten[Harkonnen] = true
InitAIUnits() InitAIUnits()
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end local delay = function(player)
local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end 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 tanksToBuild = function() return HarkonnenTankType end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceInfantry() Trigger.AfterDelay(InitialProductionDelay["HarkonnenMain"][Difficulty], function()
ProduceUnits(Harkonnen, HarkonnenLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceInfantry()
ProduceUnits(Harkonnen, HarkonnenHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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 end

View File

@@ -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 } 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 } SmugglerBase = { SmugglerWindTrap1, SmugglerWindTrap2 }
HarkonnenReinforcements = 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" } { "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 } InfantryPath = { HarkonnenEntry3.Location }
HarkonnenAttackDelay = HarkonnenAttackDelay =
@@ -139,13 +141,14 @@ HarkonnenPaths =
} }
AtreidesReinforcements = { "trike", "combat_tank_a" } AtreidesReinforcements = { "trike", "combat_tank_a" }
AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location } AtreidesPath = { AtreidesEntry.Location, AtreidesRally.Location }
ContrabandTimes = ContrabandTimes =
{ {
easy = DateTime.Minutes(10), easy = DateTime.Minutes(10),
normal = DateTime.Minutes(5), normal = DateTime.Minutes(9),
hard = DateTime.Minutes(2) + DateTime.Seconds(30) hard = DateTime.Minutes(8)
} }
Wave = 0 Wave = 0
@@ -310,6 +313,10 @@ WorldLoaded = function()
Media.DisplayMessage(contrabandApproaching, Mentat) Media.DisplayMessage(contrabandApproaching, Mentat)
end) end)
Trigger.AfterDelay(500, function()
Media.DisplayMessage(UserInterface.GetFluentMessage("use-engineer-hint"), Mentat)
end)
Trigger.OnAllKilledOrCaptured(HarkonnenBase, function() Trigger.OnAllKilledOrCaptured(HarkonnenBase, function()
Utils.Do(Harkonnen.GetGroundAttackers(), IdleHunt) Utils.Do(Harkonnen.GetGroundAttackers(), IdleHunt)
end) end)
@@ -330,6 +337,7 @@ WorldLoaded = function()
Atreides.MarkFailedObjective(DefendStarport) Atreides.MarkFailedObjective(DefendStarport)
end end
end) end)
Trigger.OnDamaged(Starport, function(_, attacker) Trigger.OnDamaged(Starport, function(_, attacker)
if Starport.Owner ~= Smuggler or attacker.IsDead or attacker.Owner ~= Atreides then if Starport.Owner ~= Smuggler or attacker.IsDead or attacker.Owner ~= Atreides then
return return
@@ -347,6 +355,7 @@ WorldLoaded = function()
end end
end end
end) end)
Trigger.OnCapture(Starport, function() Trigger.OnCapture(Starport, function()
DefendStarport = AddSecondaryObjective(Atreides, "defend-captured-starport") DefendStarport = AddSecondaryObjective(Atreides, "defend-captured-starport")
@@ -366,12 +375,14 @@ WorldLoaded = function()
Trigger.OnKilled(HarkonnenBarracks, function() Trigger.OnKilled(HarkonnenBarracks, function()
Atreides.MarkFailedObjective(CaptureBarracks) Atreides.MarkFailedObjective(CaptureBarracks)
end) end)
Trigger.OnDamaged(HarkonnenBarracks, function() Trigger.OnDamaged(HarkonnenBarracks, function()
if AttackNotifier <= 0 and HarkonnenBarracks.Health < HarkonnenBarracks.MaxHealth * 3/4 then if AttackNotifier <= 0 and HarkonnenBarracks.Health < HarkonnenBarracks.MaxHealth * 3/4 then
AttackNotifier = DateTime.Seconds(10) AttackNotifier = DateTime.Seconds(10)
Media.DisplayMessage(UserInterface.GetFluentMessage("do-not-destroy-barracks"), Mentat) Media.DisplayMessage(UserInterface.GetFluentMessage("do-not-destroy-barracks"), Mentat)
end end
end) end)
Trigger.OnCapture(HarkonnenBarracks, function() Trigger.OnCapture(HarkonnenBarracks, function()
Media.DisplayMessage(UserInterface.GetFluentMessage("hostages-released"), Mentat) 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 if not Warned and a.Owner == Atreides and a.Type ~= "carryall" then
Warned = true Warned = true
Trigger.RemoveFootprintTrigger(id) 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
end) end)
@@ -408,7 +419,7 @@ WorldLoaded = function()
if not Paid and a.Owner == Atreides and a.Type ~= "carryall" then if not Paid and a.Owner == Atreides and a.Type ~= "carryall" then
Paid = true Paid = true
Trigger.RemoveFootprintTrigger(id) 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) Utils.Do(Smuggler.GetGroundAttackers(), function(unit)
unit.AttackMove(SmugglerWaypoint2.Location) unit.AttackMove(SmugglerWaypoint2.Location)
end) end)
@@ -427,4 +438,11 @@ WorldLoaded = function()
StopInfantryProduction = true StopInfantryProduction = true
end end
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 end

Binary file not shown.

View File

@@ -365,6 +365,41 @@ Actors:
HarkonnenRally4: waypoint HarkonnenRally4: waypoint
Owner: Neutral Owner: Neutral
Location: 49,4 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,64 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 7000 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: World:
LuaScript: LuaScript:

View File

@@ -32,6 +32,7 @@ AtreidesReinforcements =
} }
AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location } AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location }
AtreidesAttackDelay = DateTime.Seconds(30) AtreidesAttackDelay = DateTime.Seconds(30)
AtreidesAttackWaves = AtreidesAttackWaves =
@@ -49,6 +50,7 @@ ToHarvest =
} }
HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" } HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" }
HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.Location } HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.Location }
Messages = Messages =
@@ -118,11 +120,8 @@ WorldLoaded = function()
end end
Trigger.OnRemovedFromWorld(HarkonnenConyard, function() Trigger.OnRemovedFromWorld(HarkonnenConyard, function()
-- Mission already failed, no need to check the other conditions as well -- Mission already failed, no need to check the other conditions as well
if checkResourceCapacity() then if checkResourceCapacity() then return end
return
end
local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Harkonnen end) local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Harkonnen end)

View File

@@ -32,6 +32,7 @@ AtreidesReinforcements =
} }
AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location } AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location }
AtreidesAttackDelay = DateTime.Seconds(30) AtreidesAttackDelay = DateTime.Seconds(30)
AtreidesAttackWaves = AtreidesAttackWaves =
@@ -49,6 +50,7 @@ ToHarvest =
} }
HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" } HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" }
HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.Location } HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.Location }
Messages = Messages =
@@ -118,11 +120,8 @@ WorldLoaded = function()
end end
Trigger.OnRemovedFromWorld(HarkonnenConyard, function() Trigger.OnRemovedFromWorld(HarkonnenConyard, function()
-- Mission already failed, no need to check the other conditions as well -- Mission already failed, no need to check the other conditions as well
if checkResourceCapacity() then if checkResourceCapacity() then return end
return
end
local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Harkonnen end) local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Harkonnen end)

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -24,10 +24,13 @@ AttackDelays =
AtreidesInfantryTypes = { "light_inf" } AtreidesInfantryTypes = { "light_inf" }
ActivateAI = function() ActivateAI = function()
Defending[Atreides] = {}
AttackDelay[Atreides] = 3000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Atreides] = 3000 * DifficultyModifier[Difficulty]
IdlingUnits[Atreides] = { } 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 toBuild = function() return AtreidesInfantryTypes end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
ProduceUnits(Atreides, ABarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Atreides, ABarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)

Binary file not shown.

View File

@@ -162,6 +162,12 @@ Actors:
AtreidesRally4: waypoint AtreidesRally4: waypoint
Owner: Neutral Owner: Neutral
Location: 47,4 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,16 +22,20 @@ AttackDelays =
} }
AtreidesInfantryTypes = { "light_inf" } AtreidesInfantryTypes = { "light_inf" }
AtreidesVehicleTypes = { "trike" } AtreidesVehicleTypes = { "trike" }
ActivateAI = function() ActivateAI = function()
Defending[Atreides] = {}
AttackDelay[Atreides] = 3000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Atreides] = 3000 * DifficultyModifier[Difficulty]
IdlingUnits[Atreides] = { } 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 infantryToBuild = function() return AtreidesInfantryTypes end
local vehilcesToBuild = function() return AtreidesVehicleTypes end local vehiclesToBuild = function() return AtreidesVehicleTypes end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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 end

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,9 +22,13 @@ AttackDelays =
} }
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
AtreidesVehicleTypes = { "trike", "trike", "quad" } AtreidesVehicleTypes = { "trike", "trike", "quad" }
ActivateAI = function() ActivateAI = function()
Defending[Atreides] = {}
AttackDelay[Atreides] = 7000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Atreides] = 5000 * DifficultyModifier[Difficulty]
IdlingUnits[Atreides] = { } IdlingUnits[Atreides] = { }
LastHarvesterEaten[Atreides] = true LastHarvesterEaten[Atreides] = true
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
@@ -32,14 +36,31 @@ ActivateAI = function()
AConyard.Produce(HarkonnenUpgrades[1]) AConyard.Produce(HarkonnenUpgrades[1])
AConyard.Produce(HarkonnenUpgrades[2]) 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 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 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
-- Finish the upgrades first before trying to build something -- Finish the upgrades first before trying to build something
Trigger.AfterDelay(DateTime.Seconds(14), function() Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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)
end end

View File

@@ -8,6 +8,7 @@
]] ]]
AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, ALightFactory, AOutpost, AConyard, ARefinery, ASilo } AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, ALightFactory, AOutpost, AConyard, ARefinery, ASilo }
AtreidesBaseAreaTriggers = 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)}, { 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" } HarkonnenReinforcements = { "trike", "trike", "quad" }
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location } HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
HarkonnenBaseBuildings = { "barracks", "light_factory" } HarkonnenBaseBuildings = { "barracks", "light_factory" }
HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" } HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" }
MessageCheck = function(index) MessageCheck = function(index)

Binary file not shown.

View File

@@ -177,6 +177,17 @@ Actors:
HarkonnenEntry: waypoint HarkonnenEntry: waypoint
Owner: Neutral Owner: Neutral
Location: 29,2 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,34 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 5000 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: World:
LuaScript: LuaScript:

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,29 +22,48 @@ AttackDelays =
} }
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
AtreidesVehicleTypes = { "trike", "trike", "quad" } AtreidesVehicleTypes = { "trike", "trike", "quad" }
InitAIUnits = function() InitAIUnits = function()
IdlingUnits[Atreides] = Reinforcements.Reinforce(Atreides, AtreidesInitialReinforcements, AtreidesInitialPath) IdlingUnits[Atreides] = Reinforcements.Reinforce(Atreides, AtreidesInitialReinforcements, AtreidesInitialPath)
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
end end
ActivateAI = function() ActivateAI = function()
Defending[Atreides] = {}
AttackDelay[Atreides] = 7000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Atreides] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Atreides] = true LastHarvesterEaten[Atreides] = true
Trigger.AfterDelay(0, InitAIUnits) Trigger.AfterDelay(0, InitAIUnits)
AConyard.Produce(HarkonnenUpgrades[1]) AConyard.Produce(HarkonnenUpgrades[1])
AConyard.Produce(HarkonnenUpgrades[2]) 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 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 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
-- Finish the upgrades first before trying to build something -- Finish the upgrades first before trying to build something
Trigger.AfterDelay(DateTime.Seconds(14), function() Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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)
end end

View File

@@ -8,6 +8,7 @@
]] ]]
AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, AWindTrap3, ALightFactory, AOutpost, AConyard, ARefinery, ASilo1, ASilo2, ASilo3, ASilo4 } AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, AWindTrap3, ALightFactory, AOutpost, AConyard, ARefinery, ASilo1, ASilo2, ASilo3, ASilo4 }
AtreidesBaseAreaTriggers = 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) }, { 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 } AtreidesInitialPath = { AtreidesEntry2.Location, AtreidesRally2.Location }
AtreidesInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" } AtreidesInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
HarkonnenReinforcements = { "quad", "quad" } HarkonnenReinforcements = { "quad", "quad" }
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location } HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
HarkonnenBaseBuildings = { "barracks", "light_factory" } HarkonnenBaseBuildings = { "barracks", "light_factory" }
HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" } HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" }
MessageCheck = function(index) MessageCheck = function(index)
@@ -150,4 +154,10 @@ WorldLoaded = function()
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[2], AtreidesHunters[2], AtreidesHunterPaths[2]) TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[2], AtreidesHunters[2], AtreidesHunterPaths[2])
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[3], AtreidesHunters[3], AtreidesHunterPaths[3]) TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[3], AtreidesHunters[3], AtreidesHunterPaths[3])
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[4], AtreidesHunters[4], AtreidesHunterPaths[4]) 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 end

View File

@@ -207,6 +207,13 @@ Actors:
HarkonnenEntry: waypoint HarkonnenEntry: waypoint
Owner: Neutral Owner: Neutral
Location: 65,45 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,34 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 5000 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: World:
LuaScript: LuaScript:

View File

@@ -7,6 +7,14 @@
information, see COPYING. information, see COPYING.
]] ]]
EarlyGameStage = DateTime.Minutes(5)
InitialProductionDelay = {
easy = DateTime.Seconds(150),
normal = DateTime.Seconds(100),
hard = DateTime.Seconds(50)
}
AttackGroupSize = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,7 +22,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(7) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,24 +30,71 @@ AttackDelays =
} }
AtreidesInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" } AtreidesInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
AtreidesVehicleTypes = { "trike", "trike", "quad" } AtreidesVehicleTypes = { "trike", "trike", "quad" }
AtreidesTankType = { "combat_tank_a" } AtreidesTankType = { "combat_tank_a" }
local attackThresholdSize = AttackGroupSize[Difficulty] * 2
ActivateAI = function() 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[Fremen] = { }
IdlingUnits[Atreides] = Utils.Concat(Reinforcements.Reinforce(Atreides, InitialAtreidesReinforcements[1], AtreidesPaths[2]), Reinforcements.Reinforce(Atreides, InitialAtreidesReinforcements[2], AtreidesPaths[3])) IdlingUnits[Atreides] = Utils.Concat(Reinforcements.Reinforce(Atreides, InitialAtreidesReinforcements[1], AtreidesPaths[2]), Reinforcements.Reinforce(Atreides, InitialAtreidesReinforcements[2], AtreidesPaths[3]))
FremenProduction() 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(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(Fremen, FremenBase, 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 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 tanksToBuild = function() return AtreidesTankType end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) Trigger.AfterDelay(InitialProductionDelay[Difficulty], function()
ProduceUnits(Atreides, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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 end

View File

@@ -7,7 +7,8 @@
information, see COPYING. 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 } FremenBase = { FGunt1, FGunt2 }
BaseAreaTriggers = BaseAreaTriggers =
@@ -105,6 +106,8 @@ FremenHunterPaths =
{ FremenEntry3.Location, FremenRally3.Location } { FremenEntry3.Location, FremenRally3.Location }
} }
FremenAmbushSquad = { FremenAmbuser1, FremenAmbuser2, FremenAmbuser3, FremenAmbuser4 }
HarkonnenReinforcements = { "combat_tank_h", "combat_tank_h" } HarkonnenReinforcements = { "combat_tank_h", "combat_tank_h" }
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location } HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
@@ -156,7 +159,8 @@ WorldLoaded = function()
Atreides = Player.GetPlayer("Atreides") Atreides = Player.GetPlayer("Atreides")
Fremen = Player.GetPlayer("Fremen") Fremen = Player.GetPlayer("Fremen")
Harkonnen = Player.GetPlayer("Harkonnen") Harkonnen = Player.GetPlayer("Harkonnen")
Defending[Atreides] = {}
Defending[Fremen] = {}
InitObjectives(Harkonnen) InitObjectives(Harkonnen)
KillAtreides = AddPrimaryObjective(Harkonnen, "destroy-atreides") KillAtreides = AddPrimaryObjective(Harkonnen, "destroy-atreides")
KillFremen = AddPrimaryObjective(Harkonnen, "destroy-fremen") KillFremen = AddPrimaryObjective(Harkonnen, "destroy-fremen")
@@ -164,11 +168,7 @@ WorldLoaded = function()
Camera.Position = HConyard.CenterPosition Camera.Position = HConyard.CenterPosition
FremenAttackLocation = HConyard.Location FremenAttackLocation = HConyard.Location
IdleHuntOnBaseDestroyed(Atreides, AtreidesBase)
Trigger.OnAllKilledOrCaptured(AtreidesBase, function()
Utils.Do(Atreides.GetGroundAttackers(), IdleHunt)
end)
Trigger.OnAllKilled(Sietches, function() Trigger.OnAllKilled(Sietches, function()
SietchesAreDestroyed = true SietchesAreDestroyed = true
end) end)
@@ -179,6 +179,7 @@ WorldLoaded = function()
unit.AttackMove(FremenAttackLocation) unit.AttackMove(FremenAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end end
SendCarryallReinforcements(Fremen, 0, FremenAttackWaves[Difficulty], FremenAttackDelay[Difficulty], path, FremenReinforcements[Difficulty], waveCondition, huntFunction) SendCarryallReinforcements(Fremen, 0, FremenAttackWaves[Difficulty], FremenAttackDelay[Difficulty], path, FremenReinforcements[Difficulty], waveCondition, huntFunction)
Actor.Create("upgrade.barracks", true, { Owner = Atreides }) 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[1], FremenHunters[1], FremenHunterPaths[3], fremenCondition)
TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[2], FremenHunters[2], FremenHunterPaths[2], fremenCondition) TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[2], FremenHunters[2], FremenHunterPaths[2], fremenCondition)
TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[3], FremenHunters[3], FremenHunterPaths[1], 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 end

View File

@@ -376,6 +376,54 @@ Actors:
AtreidesEntry3: waypoint AtreidesEntry3: waypoint
Owner: Neutral Owner: Neutral
Location: 22,91 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,68 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 5000 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: World:
LuaScript: LuaScript:

View File

@@ -7,6 +7,24 @@
information, see COPYING. 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 = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,7 +32,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(7) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,28 +40,86 @@ AttackDelays =
} }
OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
OrdosVehicleTypes = { "raider", "raider", "quad" } OrdosVehicleTypes = { "raider", "raider", "quad" }
OrdosTankType = { "combat_tank_o" } OrdosTankType = { "combat_tank_o" }
ActivateAI = function() 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[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[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(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(Corrino, CorrinoBase, 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 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 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) Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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) Trigger.AfterDelay(InitialProductionDelay["OrdosSmall"][Difficulty], function()
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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 end

View File

@@ -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 } 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 } OrdosSmallBase = { ORefinery3, OBarracks3, OLightFactory2, OGunt5, OGunt6, OPower10, OPower11, OPower12, OPower13, OSilo }
CorrinoBase = { CStarport, CPower1, CPower2 } CorrinoBase = { CStarport, CPower1, CPower2 }
ProductionBuildingsOrdosSmallBase = { ORefinery3, OBarracks3, OLightFactory2 }
SmugglerSquad = {Smuggler1, Smuggler2, Smuggler3}
BaseAreaTriggers = BaseAreaTriggers =
{ {
{ CPos.New(68, 70), CPos.New(69, 70), CPos.New(70, 70), CPos.New(71, 70) }, { CPos.New(68, 70), CPos.New(69, 70), CPos.New(70, 70), CPos.New(71, 70) },
@@ -135,6 +141,7 @@ SendStarportReinforcements = function()
return return
end 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] local units = Reinforcements.ReinforceWithTransport(Corrino, "frigate", CorrinoStarportReinforcements[Difficulty], { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2]
Utils.Do(units, function(unit) Utils.Do(units, function(unit)
unit.AttackMove(OrdosAttackLocation) unit.AttackMove(OrdosAttackLocation)
@@ -142,12 +149,6 @@ SendStarportReinforcements = function()
end) end)
SendStarportReinforcements() SendStarportReinforcements()
if Harkonnen.IsObjectiveFailed(GuardOutpost) then
return
end
Media.DisplayMessage(UserInterface.GetFluentMessage("imperial-ships-penetrating-defense-grid"), Mentat)
end) end)
end end
@@ -222,13 +223,28 @@ Tick = function()
end end
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() WorldLoaded = function()
OrdosMain = Player.GetPlayer("Ordos Main Base") OrdosMain = Player.GetPlayer("Ordos Main Base")
OrdosSmall = Player.GetPlayer("Ordos Small Base") OrdosSmall = Player.GetPlayer("Ordos Small Base")
Corrino = Player.GetPlayer("Corrino") Corrino = Player.GetPlayer("Corrino")
Harkonnen = Player.GetPlayer("Harkonnen") Harkonnen = Player.GetPlayer("Harkonnen")
SmugglerNeutral = Player.GetPlayer("Smugglers - Neutral")
SmugglerEnemy = Player.GetPlayer("Smugglers - Enemy")
Defending[OrdosMain] = {}
Defending[OrdosSmall] = {}
Defending[Corrino] = {}
InitObjectives(Harkonnen) InitObjectives(Harkonnen)
KillOrdos = AddPrimaryObjective(Harkonnen, "destroy-ordos") KillOrdos = AddPrimaryObjective(Harkonnen, "destroy-ordos")
KillCorrino = AddPrimaryObjective(Harkonnen, "destroy-imperial-forces") KillCorrino = AddPrimaryObjective(Harkonnen, "destroy-imperial-forces")
GuardOutpost = AddSecondaryObjective(Harkonnen, "keep-modified-outpost-intact") GuardOutpost = AddSecondaryObjective(Harkonnen, "keep-modified-outpost-intact")
@@ -257,17 +273,20 @@ WorldLoaded = function()
Media.DisplayMessage(UserInterface.GetFluentMessage("protect-outpost"), Mentat) Media.DisplayMessage(UserInterface.GetFluentMessage("protect-outpost"), Mentat)
end) end)
Trigger.OnAllKilledOrCaptured({ HOutpost }, function()
SendStarportReinforcements()
end)
local path = function() return Utils.Random(OrdosPaths) end local path = function() return Utils.Random(OrdosPaths) end
local waveCondition = function() return Harkonnen.IsObjectiveCompleted(KillOrdos) end local waveCondition = function() return Harkonnen.IsObjectiveCompleted(KillOrdos) end
local huntFunction = function(unit) local huntFunction = function(unit)
unit.AttackMove(OrdosAttackLocation) unit.AttackMove(OrdosAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end 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)
OrdosReinforcementNotification(0, OrdosAttackWaves[Difficulty]) OrdosReinforcementNotification(0, OrdosAttackWaves[Difficulty])
SendStarportReinforcements()
Actor.Create("upgrade.barracks", true, { Owner = OrdosMain }) Actor.Create("upgrade.barracks", true, { Owner = OrdosMain })
Actor.Create("upgrade.light", true, { Owner = OrdosMain }) Actor.Create("upgrade.light", true, { Owner = OrdosMain })
Actor.Create("upgrade.heavy", true, { Owner = OrdosMain }) Actor.Create("upgrade.heavy", true, { Owner = OrdosMain })

Binary file not shown.

View File

@@ -514,6 +514,18 @@ Actors:
HarkonnenEntry2: waypoint HarkonnenEntry2: waypoint
Owner: Neutral Owner: Neutral
Location: 2,29 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,68 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 6000 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: World:
LuaScript: LuaScript:

View File

@@ -7,6 +7,24 @@
information, see COPYING. 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 = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,7 +32,14 @@ AttackGroupSize =
hard = 10 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) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,29 +47,90 @@ AttackDelays =
} }
OrdosInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" } OrdosInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
OrdosVehicleTypes = { "raider", "raider", "quad" } OrdosVehicleTypes = { "raider", "raider", "quad" }
OrdosTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" } 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 = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
ActivateAI = function() 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[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[OrdosSmall] = Reinforcements.Reinforce(OrdosSmall, InitialOrdosReinforcements[1], InitialOrdosPaths[3])
DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 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 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 tanksToBuild = function() return { Utils.Random(OrdosTankTypes) } end
local unitsToBuy = function() return { Utils.Random(OrdosStarportTypes) } 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) Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OHeavyFactory1, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(OrdosMain, OLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize) 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) Trigger.AfterDelay(InitialProductionDelay["OrdosSmall"][Difficulty], function()
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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 end

View File

@@ -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 } 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 } 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 = OrdosReinforcements =
{ {
easy = easy =
@@ -149,9 +159,62 @@ ChangeOwner = function(old_owner, new_owner)
end) end)
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() CheckSmugglerEnemies = function()
Utils.Do(SmugglerUnits, function(unit) Utils.Do(SmugglerUnits, function(unit)
Trigger.OnDamaged(unit, function(self, attacker) 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 if unit.Owner == SmugglerNeutral and attacker.Owner == Harkonnen then
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen) ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
@@ -197,6 +260,25 @@ CheckSmugglerEnemies = function()
end) end)
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() Tick = function()
if Harkonnen.HasNoRequiredUnits() then if Harkonnen.HasNoRequiredUnits() then
OrdosMain.MarkCompletedObjective(KillHarkonnen1) OrdosMain.MarkCompletedObjective(KillHarkonnen1)
@@ -234,6 +316,8 @@ Tick = function()
ProtectHarvester(units[1], OrdosSmall, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], OrdosSmall, AttackGroupSize[Difficulty])
end end
end end
if IdlingUnits[OrdosMain] == nil and IdlingUnits[OrdosSmall] == nil then return end
end end
WorldLoaded = function() WorldLoaded = function()
@@ -273,6 +357,7 @@ WorldLoaded = function()
unit.AttackMove(OrdosAttackLocation) unit.AttackMove(OrdosAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end 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() SendStarportReinforcements()

View File

@@ -424,12 +424,14 @@ Actors:
OGunt15: medium_gun_turret OGunt15: medium_gun_turret
Location: 7,37 Location: 7,37
Owner: Ordos Small Base Owner: Ordos Small Base
TurretFacing: 512
Actor111: wall Actor111: wall
Location: 11,37 Location: 11,37
Owner: Ordos Small Base Owner: Ordos Small Base
OGunt16: medium_gun_turret OGunt16: medium_gun_turret
Location: 11,38 Location: 11,38
Owner: Ordos Small Base Owner: Ordos Small Base
TurretFacing: 512
Actor113: wall Actor113: wall
Location: 12,38 Location: 12,38
Owner: Ordos Small Base Owner: Ordos Small Base
@@ -568,18 +570,12 @@ Actors:
Actor158: light_inf Actor158: light_inf
Location: 9,72 Location: 9,72
Owner: Harkonnen Owner: Harkonnen
Actor159: light_inf
Location: 77,72
Owner: Smugglers - Neutral
SSilo3: silo SSilo3: silo
Location: 81,72 Location: 81,72
Owner: Smugglers - Neutral Owner: Smugglers - Neutral
Actor161: trike Actor161: trike
Location: 11,73 Location: 11,73
Owner: Harkonnen Owner: Harkonnen
Actor162: trooper
Location: 80,73
Owner: Smugglers - Neutral
Actor163: trooper Actor163: trooper
Location: 7,74 Location: 7,74
Owner: Harkonnen Owner: Harkonnen
@@ -592,15 +588,9 @@ Actors:
SRefinery: refinery SRefinery: refinery
Location: 78,74 Location: 78,74
Owner: Smugglers - Neutral Owner: Smugglers - Neutral
Actor167: light_inf
Location: 82,74
Owner: Smugglers - Neutral
Actor168: combat_tank_h Actor168: combat_tank_h
Location: 10,75 Location: 10,75
Owner: Harkonnen Owner: Harkonnen
Actor169: trooper
Location: 82,75
Owner: Smugglers - Neutral
Actor170: light_inf Actor170: light_inf
Location: 15,76 Location: 15,76
Owner: Harkonnen Owner: Harkonnen
@@ -625,12 +615,6 @@ Actors:
Actor177: spicebloom.spawnpoint Actor177: spicebloom.spawnpoint
Location: 72,77 Location: 72,77
Owner: Neutral Owner: Neutral
Actor178: light_inf
Location: 82,77
Owner: Smugglers - Neutral
Actor179: light_inf
Location: 83,77
Owner: Smugglers - Neutral
Actor180: light_inf Actor180: light_inf
Location: 11,78 Location: 11,78
Owner: Harkonnen Owner: Harkonnen
@@ -715,6 +699,45 @@ Actors:
HarkonnenEntry2: waypoint HarkonnenEntry2: waypoint
Owner: Neutral Owner: Neutral
Location: 2,68 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,66 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 6000 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: World:
LuaScript: LuaScript:

View File

@@ -7,6 +7,23 @@
information, see COPYING. 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 = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,7 +31,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(7) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,29 +39,108 @@ AttackDelays =
} }
OrdosInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" } OrdosInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
OrdosVehicleTypes = { "raider", "raider", "quad" } OrdosVehicleTypes = { "raider", "raider", "quad" }
OrdosTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" } 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() 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[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[OrdosSmall] = Reinforcements.Reinforce(OrdosSmall, InitialOrdosReinforcements[1], InitialOrdosPaths[3])
DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 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 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 tanksToBuild = function() return { Utils.Random(OrdosTankTypes) } end
local unitsToBuy = function() return { Utils.Random(OrdosStarportTypes) } end local unitsToBuy = function()
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 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) local attackThresholdSize = {}
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) attackThresholdSize[OrdosMain] = AttackGroupSize[Difficulty] * 3
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize) attackThresholdSize[OrdosSmall] = AttackGroupSize[Difficulty] * 2
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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 end

View File

@@ -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 } 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 } 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 = OrdosReinforcements =
{ {
easy = easy =
@@ -118,6 +128,53 @@ SendStarportReinforcements = function()
end) end)
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) ChangeOwner = function(old_owner, new_owner)
local units = old_owner.GetActors() local units = old_owner.GetActors()
Utils.Do(units, function(unit) Utils.Do(units, function(unit)
@@ -130,20 +187,47 @@ end
CheckSmugglerEnemies = function() CheckSmugglerEnemies = function()
Utils.Do(SmugglerUnits, function(unit) Utils.Do(SmugglerUnits, function(unit)
Trigger.OnDamaged(unit, function(self, attacker) 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 if unit.Owner == SmugglerNeutral and attacker.Owner == Harkonnen then
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen) ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
-- Ensure that harvesters that was on a carryall switched sides.
Trigger.AfterDelay(DateTime.Seconds(15), function()
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
end)
end end
if unit.Owner == SmugglerOrdos and attacker.Owner == Harkonnen then if unit.Owner == SmugglerOrdos and attacker.Owner == Harkonnen then
ChangeOwner(SmugglerOrdos, SmugglerBoth) ChangeOwner(SmugglerOrdos, SmugglerBoth)
-- Ensure that harvesters that was on a carryall switched sides.
Trigger.AfterDelay(DateTime.Seconds(15), function()
ChangeOwner(SmugglerOrdos, SmugglerBoth)
end)
end end
if unit.Owner == SmugglerNeutral and (attacker.Owner == OrdosMain or attacker.Owner == OrdosSmall) then if unit.Owner == SmugglerNeutral and (attacker.Owner == OrdosMain or attacker.Owner == OrdosSmall) then
ChangeOwner(SmugglerNeutral, SmugglerOrdos) ChangeOwner(SmugglerNeutral, SmugglerOrdos)
-- Ensure that harvesters that was on a carryall switched sides.
Trigger.AfterDelay(DateTime.Seconds(15), function()
ChangeOwner(SmugglerNeutral, SmugglerOrdos)
end)
end end
if unit.Owner == SmugglerHarkonnen and (attacker.Owner == OrdosMain or attacker.Owner == OrdosSmall) then if unit.Owner == SmugglerHarkonnen and (attacker.Owner == OrdosMain or attacker.Owner == OrdosSmall) then
ChangeOwner(SmugglerHarkonnen, SmugglerBoth) ChangeOwner(SmugglerHarkonnen, SmugglerBoth)
-- Ensure that harvesters that was on a carryall switched sides.
Trigger.AfterDelay(DateTime.Seconds(15), function()
ChangeOwner(SmugglerHarkonnen, SmugglerBoth)
end)
end end
if attacker.Owner == Harkonnen and not MessageCheck then if attacker.Owner == Harkonnen and not MessageCheck then
@@ -155,6 +239,13 @@ CheckSmugglerEnemies = function()
end) end)
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() Tick = function()
if Harkonnen.HasNoRequiredUnits() then if Harkonnen.HasNoRequiredUnits() then
OrdosMain.MarkCompletedObjective(KillHarkonnen1) OrdosMain.MarkCompletedObjective(KillHarkonnen1)
@@ -231,8 +322,8 @@ WorldLoaded = function()
unit.AttackMove(OrdosAttackLocation) unit.AttackMove(OrdosAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end 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() SendStarportReinforcements()
Actor.Create("upgrade.barracks", true, { Owner = OrdosMain }) Actor.Create("upgrade.barracks", true, { Owner = OrdosMain })

Binary file not shown.

View File

@@ -394,9 +394,11 @@ Actors:
OGunt6: medium_gun_turret OGunt6: medium_gun_turret
Location: 9,17 Location: 9,17
Owner: Ordos Small Base Owner: Ordos Small Base
TurretFacing: 512
OGunt7: medium_gun_turret OGunt7: medium_gun_turret
Location: 14,17 Location: 14,17
Owner: Ordos Small Base Owner: Ordos Small Base
TurretFacing: 512
Actor102: wall Actor102: wall
Location: 15,17 Location: 15,17
Owner: Ordos Small Base Owner: Ordos Small Base
@@ -463,12 +465,6 @@ Actors:
SSilo3: silo SSilo3: silo
Location: 51,26 Location: 51,26
Owner: Smugglers - Neutral Owner: Smugglers - Neutral
Actor124: trooper
Location: 51,28
Owner: Smugglers - Neutral
Actor125: light_inf
Location: 53,28
Owner: Smugglers - Neutral
Actor126: wormspawner Actor126: wormspawner
Location: 76,28 Location: 76,28
Owner: Creeps Owner: Creeps
@@ -487,24 +483,12 @@ Actors:
SPower2: wind_trap SPower2: wind_trap
Location: 50,30 Location: 50,30
Owner: Smugglers - Neutral Owner: Smugglers - Neutral
Actor132: light_inf
Location: 53,30
Owner: Smugglers - Neutral
SRefinery: refinery SRefinery: refinery
Location: 43,33 Location: 43,33
Owner: Smugglers - Neutral Owner: Smugglers - Neutral
Actor134: light_inf
Location: 50,33
Owner: Smugglers - Neutral
Actor135: harvester Actor135: harvester
Location: 46,35 Location: 46,35
Owner: Smugglers - Neutral Owner: Smugglers - Neutral
Actor136: light_inf
Location: 48,35
Owner: Smugglers - Neutral
Actor137: light_inf
Location: 52,35
Owner: Smugglers - Neutral
Actor138: light_inf Actor138: light_inf
Location: 42,36 Location: 42,36
Owner: Smugglers - Neutral Owner: Smugglers - Neutral
@@ -652,6 +636,42 @@ Actors:
OrdosStarportExit: waypoint OrdosStarportExit: waypoint
Owner: Neutral Owner: Neutral
Location: 2,9 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,136 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 5000 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: World:
LuaScript: LuaScript:

View File

@@ -6,6 +6,30 @@
the License, or (at your option) any later version. For more the License, or (at your option) any later version. For more
information, see COPYING. 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 = AttackGroupSize =
{ {
@@ -14,29 +38,60 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = EarlyProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(7) }, easy = { DateTime.Seconds(11), DateTime.Seconds(15) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(10), DateTime.Seconds(12) },
hard = { DateTime.Seconds(1), DateTime.Seconds(3) } hard = { DateTime.Seconds(8), DateTime.Seconds(10) }
} }
InitialProductionDelay = LateProductionDelays =
{ {
easy = DateTime.Seconds(30), easy = { DateTime.Seconds(6), DateTime.Seconds(10) },
normal = DateTime.Seconds(15), normal = { DateTime.Seconds(4), DateTime.Seconds(6) },
hard = 0 hard = { DateTime.Seconds(2), DateTime.Seconds(4) }
} }
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
AtreidesVehicleTypes = { "trike", "trike", "quad" } 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" } 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" } 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" } CorrinoInfantryTypes = { "light_inf", "trooper", "sardaukar" }
ActivateAI = function() 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[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[AtreidesSmall] = Reinforcements.Reinforce(AtreidesSmall, InitialAtreidesReinforcements[Difficulty][1], InitialAtreidesPaths[3])
IdlingUnits[Corrino] = Reinforcements.Reinforce(Corrino, InitialCorrinoReinforcements, InitialCorrinoPath) IdlingUnits[Corrino] = Reinforcements.Reinforce(Corrino, InitialCorrinoReinforcements, InitialCorrinoPath)
@@ -45,23 +100,77 @@ ActivateAI = function()
DefendAndRepairBase(AtreidesSmall, AtreidesSmallBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(AtreidesSmall, AtreidesSmallBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(Corrino, CorrinoBase, 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 infantryToBuildAtreides = function() return { Utils.Random(AtreidesInfantryTypes) } end
local infantryToBuildCorrino = function() return { Utils.Random(CorrinoInfantryTypes) } end local infantryToBuildCorrino = function() return { Utils.Random(CorrinoInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local tanksToBuildMain = function() return { Utils.Random(AtreidesMainTankTypes) } 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 tanksToBuildSmall = function() return { Utils.Random(AtreidesSmallTankTypes) } end
local unitsToBuy = function() return { Utils.Random(AtreidesStarportTypes) } 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() Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function()
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesMain, ALightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildMain, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildMain, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
ProduceUnits(AtreidesSmall, ABarracks, delay, infantryToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildSmall, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Corrino, CBarracks, delay, infantryToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
end) 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 end

View File

@@ -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 } 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 } AtreidesSmallBase = { AOutpost2, ARefinery3, ABarracks, AHeavyFactory2, AGunt7, AGunt8, APower23, APower24, APower25, APower26, ASilo4, ASilo5, ASilo6, ASilo7 }
CorrinoBase = { CBarracks, COutpost, CPower1, CPower2, CPower3, CRock1, CRock2 } CorrinoBase = { CBarracks, COutpost, CPower1, CPower2, CPower3, CRock1, CRock2 }
EarlyGameStage = DateTime.Minutes(7)
AtreidesReinforcements = AtreidesReinforcements =
{ {
easy = { "sonic_tank" }, easy = { "sonic_tank" },
@@ -41,16 +45,16 @@ CorrinoReinforcements =
EnemyAttackDelay = EnemyAttackDelay =
{ {
easy = DateTime.Minutes(3) + DateTime.Seconds(30), easy = 7000 ,
normal = DateTime.Minutes(2) + DateTime.Seconds(30), normal = 6500 ,
hard = DateTime.Minutes(1) + DateTime.Seconds(30) hard = 6000
} }
CorrinoInitialAttackDelay = CorrinoInitialAttackDelay =
{ {
easy = DateTime.Seconds(45), easy = DateTime.Minutes(4) ,
normal = DateTime.Seconds(30), normal = DateTime.Minutes(3) ,
hard = DateTime.Seconds(15) hard = DateTime.Minutes(2)
} }
InitialAtreidesReinforcements = InitialAtreidesReinforcements =
@@ -112,8 +116,8 @@ HarkonnenReinforcements =
hard = hard =
{ {
{ "trooper", "trooper", "light_inf", "light_inf", "light_inf" }, { "trooper", "trooper", "light_inf", "light_inf", "light_inf", "light_inf" },
{ "quad", "trike", "trike", "combat_tank_h", "combat_tank_h" } { "quad", "trike", "trike", "combat_tank_h", "combat_tank_h", "siege_tank" }
}, },
} }
@@ -147,8 +151,32 @@ SendEnemyReinforcements = function(player, delay, path, unitTypes, customConditi
end) end)
end end
SendAirStrike = function() AirStrikeTimer = 7500
if HiTechIsDead then 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 return
end end
@@ -163,10 +191,32 @@ SendAirStrike = function()
end) end)
if #targets > 0 then if #targets > 0 then
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition) airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end 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 end
Tick = function() Tick = function()
@@ -195,12 +245,12 @@ Tick = function()
HiTechIsDead = true HiTechIsDead = true
end end
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[OrdosMain] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
local units = OrdosMain.GetActorsByType("harvester") local units = AtreidesMain.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[OrdosMain] = false LastHarvesterEaten[AtreidesMain] = false
ProtectHarvester(units[1], OrdosMain, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
end end
end end
@@ -212,15 +262,40 @@ Tick = function()
ProtectHarvester(units[1], OrdosSmall, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], OrdosSmall, AttackGroupSize[Difficulty])
end end
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 end
WorldLoaded = function() WorldLoaded = function()
AtreidesMain = Player.GetPlayer("Atreides Main Base") AtreidesMain = Player.GetPlayer("Atreides Main Base")
AtreidesSmall = Player.GetPlayer("Atreides Small Base") AtreidesSmall = Player.GetPlayer("Atreides Small Base")
Corrino = Player.GetPlayer("Corrino") Corrino = Player.GetPlayer("Corrino")
AtreidesMain.Cash = 5000
AtreidesSmall.Cash = 5000
Corrino.Cash = 5000
Harkonnen = Player.GetPlayer("Harkonnen") Harkonnen = Player.GetPlayer("Harkonnen")
InitObjectives(Harkonnen) InitObjectives(Harkonnen)
CaptureAtreidesConYard = AddPrimaryObjective(Harkonnen, "capture-atreides-construction-yard-south") CaptureAtreidesConYard = AddPrimaryObjective(Harkonnen, "capture-atreides-construction-yard-south")
KillAtreides = AddPrimaryObjective(Harkonnen, "destroy-atreides") KillAtreides = AddPrimaryObjective(Harkonnen, "destroy-atreides")
KillCorrino = AddPrimaryObjective(Harkonnen, "destroy-corrino") KillCorrino = AddPrimaryObjective(Harkonnen, "destroy-corrino")
@@ -232,8 +307,7 @@ WorldLoaded = function()
Camera.Position = HEngineer.CenterPosition Camera.Position = HEngineer.CenterPosition
AtreidesAttackLocation = AConYard2.Location AtreidesAttackLocation = AConYard2.Location
Trigger.AfterDelay(EarlyGameStage,function() AirstrikeLogic(AHiTechFactory) end)
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
Trigger.OnCapture(AConYard2, function() Trigger.OnCapture(AConYard2, function()
Harkonnen.MarkCompletedObjective(CaptureAtreidesConYard) Harkonnen.MarkCompletedObjective(CaptureAtreidesConYard)
@@ -257,7 +331,9 @@ WorldLoaded = function()
unit.AttackMove(AtreidesAttackLocation) unit.AttackMove(AtreidesAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end end
SendEnemyReinforcements(AtreidesMain, EnemyAttackDelay[Difficulty], AtreidesPath, AtreidesReinforcements[Difficulty], atreidesWaveCondition, huntFunction) SendEnemyReinforcements(AtreidesMain, EnemyAttackDelay[Difficulty], AtreidesPath, AtreidesReinforcements[Difficulty], atreidesWaveCondition, huntFunction)
Trigger.AfterDelay(CorrinoInitialAttackDelay[Difficulty], function() Trigger.AfterDelay(CorrinoInitialAttackDelay[Difficulty], function()
SendEnemyReinforcements(Corrino, EnemyAttackDelay[Difficulty], CorrinoPaths[1], CorrinoReinforcements[Difficulty][1], corrinoWaveCondition, huntFunction) SendEnemyReinforcements(Corrino, EnemyAttackDelay[Difficulty], CorrinoPaths[1], CorrinoReinforcements[Difficulty][1], corrinoWaveCondition, huntFunction)
SendEnemyReinforcements(Corrino, EnemyAttackDelay[Difficulty], CorrinoPaths[2], CorrinoReinforcements[Difficulty][2], corrinoWaveCondition, huntFunction) SendEnemyReinforcements(Corrino, EnemyAttackDelay[Difficulty], CorrinoPaths[2], CorrinoReinforcements[Difficulty][2], corrinoWaveCondition, huntFunction)
@@ -273,4 +349,14 @@ WorldLoaded = function()
SendHarkonnenReinforcements(1) SendHarkonnenReinforcements(1)
SendHarkonnenReinforcements(2) 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 end

Binary file not shown.

View File

@@ -298,6 +298,7 @@ Actors:
AGunt1: medium_gun_turret AGunt1: medium_gun_turret
Location: 80,27 Location: 80,27
Owner: Atreides Main Base Owner: Atreides Main Base
TurretFacing: 512
Actor77: wall Actor77: wall
Location: 81,27 Location: 81,27
Owner: Atreides Main Base Owner: Atreides Main Base
@@ -769,6 +770,33 @@ Actors:
AtreidesEntry2: waypoint AtreidesEntry2: waypoint
Owner: Neutral Owner: Neutral
Location: 2,27 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,79 @@
Player: Player:
PlayerResources: 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: World:
LuaScript: LuaScript:

View File

@@ -7,6 +7,31 @@
information, see COPYING. 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 = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,7 +39,14 @@ AttackGroupSize =
hard = 10 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) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -24,16 +56,61 @@ AttackDelays =
EnemyInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" } EnemyInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
OrdosVehicleTypes = { "raider", "raider", "quad" } 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" } 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" } MercenaryTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" }
ActivateAI = function() 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[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[AtreidesEnemy] = Reinforcements.Reinforce(AtreidesEnemy, InitialAtreidesReinforcements, InitialAtreidesPath)
IdlingUnits[AtreidesNeutral] = { } IdlingUnits[AtreidesNeutral] = { }
@@ -44,26 +121,112 @@ ActivateAI = function()
DefendAndRepairBase(AtreidesEnemy, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(AtreidesEnemy, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(MercenaryEnemy, MercenaryBase, 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 infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local vehilcesToBuildOrdos = function() return { Utils.Random(OrdosVehicleTypes) } end local vehiclesToBuildOrdos = function() return { Utils.Random(OrdosVehicleTypes) } end
local vehilcesToBuildAtreides = function() return { Utils.Random(AtreidesVehicleTypes) } end local vehiclesToBuildAtreides = function() return { Utils.Random(AtreidesVehicleTypes) } end
local tanksToBuildOrdos = function() return { Utils.Random(OrdosTankTypes) } end
local tanksToBuildAtreides = function() return { Utils.Random(AtreidesTankTypes) } 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 tanksToBuildMercenary = function() return { Utils.Random(MercenaryTankTypes) } end
local unitsToBuyOrdos = function() return { Utils.Random(OrdosStarportTypes) } end local unitsToBuyOrdos = function()
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end 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 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(Ordos, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) Trigger.AfterDelay(InitialProductionDelay["Ordos"][Difficulty], function ()
ProduceUnits(Ordos, OLightFactory, delay, vehilcesToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Ordos, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OHeavyFactory, delay, tanksToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Ordos, OLightFactory, delay, vehiclesToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OStarport, delay, unitsToBuyOrdos, 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) Trigger.AfterDelay(InitialProductionDelay["AtreidesEnemy"][Difficulty], function ()
ProduceUnits(AtreidesEnemy, ALightFactory, delay, vehilcesToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesEnemy, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesEnemy, AHeavyFactory, delay, tanksToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesEnemy, ALightFactory, delay, vehiclesToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesEnemy, AStarport, delay, unitsToBuyAtreides, 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 end

View File

@@ -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 } 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 } MercenaryBase = { MHeavyFactory, MStarport, MGunt, MPower1, MPower2 }
OrdosReinforcements = OrdosReinforcements =
@@ -56,7 +58,7 @@ OrdosAttackDelay =
hard = DateTime.Minutes(1) hard = DateTime.Minutes(1)
} }
MercenaryStarportDelay = DateTime.Minutes(1) + DateTime.Seconds(20) MercenaryStarportDelay = 4970
OrdosAttackWaves = OrdosAttackWaves =
{ {
@@ -92,7 +94,9 @@ InitialOrdosPaths =
SaboteurPaths = SaboteurPaths =
{ {
{ SaboteurWaypoint1.Location, SaboteurWaypoint2.Location, SaboteurWaypoint3.Location }, { 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 } InitialAtreidesPath = { AStarport.Location, AtreidesRally.Location }
@@ -117,14 +121,36 @@ SendStarportReinforcements = function(faction)
end) end)
end end
SendAirStrike = function() AirStrikeTimer = 7500
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesEnemy then 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 return
end end
local targets = Utils.Where(Harkonnen.GetActors(), function(actor) local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
return return actor.HasProperty("Sell") and
actor.HasProperty("Sell") and
actor.Type ~= "wall" and actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and actor.Type ~= "large_gun_turret" and
@@ -133,16 +159,40 @@ SendAirStrike = function()
end) end)
if #targets > 0 then 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 end
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike) airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end end
GetSaboteurTargets = function(player) GetSaboteurTargets = function(player)
return Utils.Where(player.GetActors(), function(actor) return Utils.Where(player.GetActors(), function(actor)
return return actor.HasProperty("Sell") and
actor.HasProperty("Sell") and
actor.Type ~= "wall" and actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and actor.Type ~= "large_gun_turret" and
@@ -162,14 +212,54 @@ BuildSaboteur = function()
saboteur.Wait(DateTime.Seconds(5)) saboteur.Wait(DateTime.Seconds(5))
local path = Utils.Random(SaboteurPaths) local path = Utils.Random(SaboteurPaths)
saboteur.Move(path[1]) Utils.Do(path, function(waypoint)
saboteur.Move(path[2]) saboteur.Move(waypoint)
saboteur.Move(path[3]) end)
SendSaboteur(saboteur) SendSaboteur(saboteur)
ScanForBetterTargets(saboteur)
end 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 end
SendSaboteur = function(saboteur) SendSaboteur = function(saboteur)
@@ -216,6 +306,21 @@ ChangeOwner = function(old_owner, new_owner)
end) end)
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() Tick = function()
if Harkonnen.HasNoRequiredUnits() then if Harkonnen.HasNoRequiredUnits() then
Ordos.MarkCompletedObjective(KillHarkonnen1) Ordos.MarkCompletedObjective(KillHarkonnen1)
@@ -239,7 +344,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Ordos] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Ordos] then
local units = Ordos.GetActorsByType("harvester") local units = Ordos.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[Ordos] = false LastHarvesterEaten[Ordos] = false
ProtectHarvester(units[1], Ordos, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], Ordos, AttackGroupSize[Difficulty])
@@ -248,7 +352,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesEnemy] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesEnemy] then
local units = AtreidesEnemy.GetActorsByType("harvester") local units = AtreidesEnemy.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[AtreidesEnemy] = false LastHarvesterEaten[AtreidesEnemy] = false
ProtectHarvester(units[1], AtreidesEnemy, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], AtreidesEnemy, AttackGroupSize[Difficulty])
@@ -275,8 +378,8 @@ WorldLoaded = function()
OrdosAttackLocation = HMCV.Location OrdosAttackLocation = HMCV.Location
MercenaryAttackLocation = HMCV.Location MercenaryAttackLocation = HMCV.Location
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike) Trigger.AfterDelay(EarlyGameStage, function() AirstrikeLogic(AHiTechFactory) end)
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(30), BuildSaboteur) Trigger.AfterDelay(EarlyGameStage, BuildSaboteur)
Trigger.OnCapture(MHeavyFactory, function() Trigger.OnCapture(MHeavyFactory, function()
Harkonnen.MarkCompletedObjective(AllyWithMercenaries) Harkonnen.MarkCompletedObjective(AllyWithMercenaries)
@@ -296,7 +399,7 @@ WorldLoaded = function()
end) end)
Trigger.OnKilledOrCaptured(OPalace, function() 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) ChangeOwner(AtreidesEnemy, AtreidesNeutral)
DefendAndRepairBase(AtreidesNeutral, AtreidesBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(AtreidesNeutral, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
@@ -328,8 +431,8 @@ WorldLoaded = function()
unit.AttackMove(OrdosAttackLocation) unit.AttackMove(OrdosAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end 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) SendStarportReinforcements(MercenaryEnemy)
Actor.Create("upgrade.barracks", true, { Owner = Ordos }) Actor.Create("upgrade.barracks", true, { Owner = Ordos })

View File

@@ -643,15 +643,33 @@ Actors:
SaboteurWaypoint4: waypoint SaboteurWaypoint4: waypoint
Owner: Neutral Owner: Neutral
Location: 18,59 Location: 18,59
SaboteurWaypoint5: waypoint
Owner: Neutral
Location: 31,91
SaboteurWaypoint6: waypoint SaboteurWaypoint6: waypoint
Owner: Neutral Owner: Neutral
Location: 64,91 Location: 64,91
MercenaryAttackPoint: waypoint MercenaryAttackPoint: waypoint
Owner: Neutral Owner: Neutral
Location: 53,38 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,150 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 7000 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: World:
LuaScript: LuaScript:

View File

@@ -7,6 +7,8 @@
information, see COPYING. information, see COPYING.
]] ]]
EarlyGameStage = DateTime.Minutes(10)
AttackGroupSize = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,26 +16,117 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = EarlyProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, easy = { DateTime.Seconds(12), DateTime.Seconds(15) },
hard = { DateTime.Seconds(1), DateTime.Seconds(3) } 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" } EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
EnemyVehicleTypes = { "trike", "trike", "quad" } 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" } 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" } 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" } 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() 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[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[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]) IdlingUnits[AtreidesSmall2] = Reinforcements.Reinforce(AtreidesSmall2, InitialAtreidesReinforcements[6], InitialAtreidesPaths[6])
@@ -46,35 +139,118 @@ ActivateAI = function()
DefendAndRepairBase(CorrinoMain, CorrinoMainBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(CorrinoMain, CorrinoMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(CorrinoSmall, CorrinoSmallBase, 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 infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local infantryToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainInfantryTypes) } end local infantryToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuildAtreidesMain = function() return { Utils.Random(AtreidesMainTankTypes) } 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 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 tanksToBuildCorrinoSmall = function() return { Utils.Random(CorrinoSmallTankTypes) } end
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end local attackThresholdSize = AttackGroupSize[Difficulty] * 3
local unitsToBuyCorrino = function() return { Utils.Random(CorrinoStarportTypes) } end local attackThresholdSizeCorrino = AttackGroupSize[Difficulty] * 4
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 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) Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall"][Difficulty], function ()
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesSmall1, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesSmall1, ALightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesSmall1, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
end)
ProduceUnits(AtreidesSmall1, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesSmall2, ABarracks4, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(AtreidesSmall1, ALightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall1, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSize)
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) Trigger.AfterDelay(InitialProductionDelay["CorrinoSmall"][Difficulty], function ()
ProduceUnits(CorrinoMain, CLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(CorrinoSmall, CBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(CorrinoMain, CHeavyFactory1, delay, tanksToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(CorrinoSmall, CLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(CorrinoMain, CStarport, delay, unitsToBuyCorrino, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(CorrinoSmall, CHeavyFactory2, delay, tanksToBuildCorrinoSmall, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
end)
ProduceUnits(CorrinoSmall, CBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) local crusherTypes = { "combat_tank_a", "combat_tank_a.starport", "combat_tank_h", "combat_tank_h.starport" }
ProduceUnits(CorrinoSmall, CLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) local crusherFactories = { AStarport, AHeavyFactory1, AHeavyFactory2, CHeavyFactory1, CHeavyFactory2, CStarport }
ProduceUnits(CorrinoSmall, CHeavyFactory2, delay, tanksToBuildCorrinoSmall, AttackGroupSize[Difficulty], attackThresholdSize) 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 end

View File

@@ -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 } 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 } 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 } 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 } 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 } CorrinoSmallBase = { CConYard, CRefinery2, CHeavyFactory2, CLightFactory2, CRock3, CRock4, CBarracks2, CPower8, CPower9, CPower10, CPower11 }
AtreidesReinforcements = AtreidesReinforcements =
@@ -131,9 +135,13 @@ InitialCorrinoPaths =
{ CorrinoEntry2.Location, CorrinoRally2.Location } { CorrinoEntry2.Location, CorrinoRally2.Location }
} }
HarkonnenReinforcements = { "combat_tank_h", "combat_tank_h", "siege_tank", "siege_tank", "missile_tank" } HarkonnenReinforcements = {
{ "combat_tank_h", "combat_tank_h", "siege_tank", "siege_tank", "missile_tank" },
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location } { "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() SendStarportReinforcements = function()
Trigger.AfterDelay(CorrinoStarportDelay[Difficulty], function() Trigger.AfterDelay(CorrinoStarportDelay[Difficulty], function()
@@ -142,7 +150,6 @@ SendStarportReinforcements = function()
end end
local reinforcements = Utils.Random(CorrinoStarportReinforcements[Difficulty]) local reinforcements = Utils.Random(CorrinoStarportReinforcements[Difficulty])
local units = Reinforcements.ReinforceWithTransport(CorrinoMain, "frigate", reinforcements, { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2] local units = Reinforcements.ReinforceWithTransport(CorrinoMain, "frigate", reinforcements, { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2]
Utils.Do(units, function(unit) Utils.Do(units, function(unit)
unit.AttackMove(AtreidesAttackLocation) unit.AttackMove(AtreidesAttackLocation)
@@ -153,23 +160,56 @@ SendStarportReinforcements = function()
end) end)
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() 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() Trigger.AfterDelay(DateTime.Seconds(5), function()
Media.PlaySpeechNotification(Harkonnen, "Reinforce") Media.PlaySpeechNotification(Harkonnen, "Reinforce")
end) end)
end) end)
end end
SendAirStrike = function() AirStrikeTimer = 7500
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesMain then 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 return
end end
local targets = Utils.Where(Harkonnen.GetActors(), function(actor) local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
return return actor.HasProperty("Sell") and
actor.HasProperty("Sell") and
actor.Type ~= "wall" and actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and actor.Type ~= "large_gun_turret" and
@@ -178,12 +218,86 @@ SendAirStrike = function()
end) end)
if #targets > 0 then 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 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 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() BuildFremen = function()
if APalace.IsDead or APalace.Owner ~= AtreidesMain then if APalace.IsDead or APalace.Owner ~= AtreidesMain then
return return
@@ -194,7 +308,6 @@ BuildFremen = function()
Trigger.AfterDelay(DateTime.Seconds(5), function() Trigger.AfterDelay(DateTime.Seconds(5), function()
IdleFremen = Utils.Where(AtreidesMain.GetActorsByType('fremen'), function(actor) return actor.IsIdle end) IdleFremen = Utils.Where(AtreidesMain.GetActorsByType('fremen'), function(actor) return actor.IsIdle end)
if #IdleFremen >= FremenGroupSize[Difficulty] then if #IdleFremen >= FremenGroupSize[Difficulty] then
SendFremen() SendFremen()
end end
@@ -231,7 +344,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
local units = AtreidesMain.GetActorsByType("harvester") local units = AtreidesMain.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[AtreidesMain] = false LastHarvesterEaten[AtreidesMain] = false
ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
@@ -240,7 +352,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesSmall1] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesSmall1] then
local units = AtreidesSmall1.GetActorsByType("harvester") local units = AtreidesSmall1.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[AtreidesSmall1] = false LastHarvesterEaten[AtreidesSmall1] = false
ProtectHarvester(units[1], AtreidesSmall1, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], AtreidesSmall1, AttackGroupSize[Difficulty])
@@ -249,7 +360,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoMain] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoMain] then
local units = CorrinoMain.GetActorsByType("harvester") local units = CorrinoMain.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[CorrinoMain] = false LastHarvesterEaten[CorrinoMain] = false
ProtectHarvester(units[1], CorrinoMain, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], CorrinoMain, AttackGroupSize[Difficulty])
@@ -258,7 +368,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoSmall] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoSmall] then
local units = CorrinoSmall.GetActorsByType("harvester") local units = CorrinoSmall.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[CorrinoSmall] = false LastHarvesterEaten[CorrinoSmall] = false
ProtectHarvester(units[1], CorrinoSmall, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], CorrinoSmall, AttackGroupSize[Difficulty])
@@ -286,8 +395,8 @@ WorldLoaded = function()
Camera.Position = HMCV.CenterPosition Camera.Position = HMCV.CenterPosition
AtreidesAttackLocation = HarkonnenRally.Location AtreidesAttackLocation = HarkonnenRally.Location
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike) Trigger.AfterDelay(DateTime.Minutes(10), function() AirstrikeLogic(AHiTechFactory) end )
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds (30), BuildFremen) Trigger.AfterDelay(DateTime.Minutes(3) + DateTime.Seconds (30), BuildFremen)
Trigger.OnAllKilledOrCaptured(AtreidesMainBase, function() Trigger.OnAllKilledOrCaptured(AtreidesMainBase, function()
Utils.Do(AtreidesMain.GetGroundAttackers(), IdleHunt) Utils.Do(AtreidesMain.GetGroundAttackers(), IdleHunt)
@@ -315,8 +424,8 @@ WorldLoaded = function()
unit.AttackMove(AtreidesAttackLocation) unit.AttackMove(AtreidesAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end 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() SendStarportReinforcements()
Actor.Create("upgrade.barracks", true, { Owner = AtreidesMain }) Actor.Create("upgrade.barracks", true, { Owner = AtreidesMain })
@@ -335,5 +444,19 @@ WorldLoaded = function()
Actor.Create("upgrade.heavy", true, { Owner = CorrinoSmall }) Actor.Create("upgrade.heavy", true, { Owner = CorrinoSmall })
Trigger.AfterDelay(0, ActivateAI) 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 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.

View File

@@ -562,9 +562,6 @@ Actors:
ARock4: large_gun_turret ARock4: large_gun_turret
Location: 54,27 Location: 54,27
Owner: Atreides Main Base Owner: Atreides Main Base
CPalace: palace
Location: 2,28
Owner: Corrino Main Base
Actor161: wall Actor161: wall
Location: 49,28 Location: 49,28
Owner: Atreides Main Base Owner: Atreides Main Base
@@ -844,6 +841,7 @@ Actors:
ARock6: large_gun_turret ARock6: large_gun_turret
Location: 47,62 Location: 47,62
Owner: Atreides Small Base 1 Owner: Atreides Small Base 1
TurretFacing: 512
AHeavyFactory2: heavy_factory AHeavyFactory2: heavy_factory
Location: 36,63 Location: 36,63
Owner: Atreides Small Base 1 Owner: Atreides Small Base 1
@@ -862,12 +860,10 @@ Actors:
ARock7: large_gun_turret ARock7: large_gun_turret
Location: 44,66 Location: 44,66
Owner: Atreides Small Base 1 Owner: Atreides Small Base 1
TurretFacing: 512
APower21: wind_trap APower21: wind_trap
Location: 38,67 Location: 38,67
Owner: Atreides Small Base 1 Owner: Atreides Small Base 1
ARock8: large_gun_turret
Location: 44,67
Owner: Atreides Small Base 1
ABarracks3: barracks ABarracks3: barracks
Location: 36,68 Location: 36,68
Owner: Atreides Small Base 1 Owner: Atreides Small Base 1
@@ -967,18 +963,12 @@ Actors:
AtreidesRally1: waypoint AtreidesRally1: waypoint
Owner: Neutral Owner: Neutral
Location: 96,87 Location: 96,87
AtreidesEntry1: waypoint
Owner: Neutral
Location: 97,87
AtreidesRally2: waypoint AtreidesRally2: waypoint
Owner: Neutral Owner: Neutral
Location: 76,93 Location: 76,93
AtreidesEntry2: waypoint AtreidesEntry2: waypoint
Owner: Neutral Owner: Neutral
Location: 76,97 Location: 76,97
AtreidesRally3: waypoint
Owner: Neutral
Location: 63,65
AtreidesEntry3: waypoint AtreidesEntry3: waypoint
Owner: Neutral Owner: Neutral
Location: 97,65 Location: 97,65
@@ -1042,6 +1032,85 @@ Actors:
CorrinoStarportExit: waypoint CorrinoStarportExit: waypoint
Owner: Neutral Owner: Neutral
Location: 2,13 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,204 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 7000 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: World:
LuaScript: LuaScript:

View File

@@ -7,6 +7,38 @@
information, see COPYING. 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 = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,25 +46,81 @@ AttackGroupSize =
hard = 10 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) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
hard = { DateTime.Seconds(1), DateTime.Seconds(3) } 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" } 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" } 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" } 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() 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[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[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])) 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(CorrinoMain, CorrinoMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(CorrinoSmall, CorrinoSmallBase, 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 infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local infantryToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainInfantryTypes) } end local infantryToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuildAtreidesMain = function() return { Utils.Random(AtreidesMainTankTypes) } 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 tanksToBuildAtreidesSmall = function() return { Utils.Random(AtreidesSmallTankTypes) } end
local tanksToBuildCorrino = function() return { Utils.Random(CorrinoTankTypes) } end local tanksToBuildCorrino = function()
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end if EarlyGameStage >= DateTime.GameTime then
local unitsToBuyCorrino = function() return { Utils.Random(CorrinoStarportTypes) } end return { Utils.Random(CorrinoTankTypes["EarlyGame"]) }
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 else
return { Utils.Random(CorrinoTankTypes["LateGame"]) }
end
end
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) local attackThresholdSize = AttackGroupSize[Difficulty] * 3
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) local attackThresholdSizeSmall = AttackGroupSize[Difficulty] * 2
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize) local attackThresholdSizeEmperor = AttackGroupSize[Difficulty] * 5
ProduceUnits(AtreidesMain, AStarport1, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function ()
ProduceUnits(AtreidesSmall, ALightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(AtreidesMain, ALightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, AStarport2, delay, unitsToBuyAtreides, 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) Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall"][Difficulty], function ()
ProduceUnits(CorrinoMain, CHeavyFactory, delay, tanksToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSize) 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) Trigger.AfterDelay(InitialProductionDelay["CorrinoMain"][Difficulty], function ()
ProduceUnits(CorrinoSmall, CLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSizeEmperor)
ProduceUnits(CorrinoSmall, CStarport, delay, unitsToBuyCorrino, AttackGroupSize[Difficulty], attackThresholdSize) 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 end

View File

@@ -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 } 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 } 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 } 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 } CorrinoSmallBase = { CRefinery2, CLightFactory, CStarport, CGunt7, CGunt8, CBarracks3, CPower9, CPower10, CPower11, CPower12, CSilo1, CSilo2, CSilo3, CSilo4 }
AtreidesReinforcements = AtreidesReinforcements =
@@ -148,7 +151,6 @@ SendStarportReinforcements = function()
end end
local reinforcements = Utils.Random(CorrinoStarportReinforcements[Difficulty]) local reinforcements = Utils.Random(CorrinoStarportReinforcements[Difficulty])
local units = Reinforcements.ReinforceWithTransport(CorrinoSmall, "frigate", reinforcements, { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2] local units = Reinforcements.ReinforceWithTransport(CorrinoSmall, "frigate", reinforcements, { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2]
Utils.Do(units, function(unit) Utils.Do(units, function(unit)
unit.AttackMove(AtreidesAttackLocation) unit.AttackMove(AtreidesAttackLocation)
@@ -168,14 +170,33 @@ SendHarkonnenReinforcements = function(delay)
end) end)
end end
SendAirStrike = function() AirStrikeTimer = 7500
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesMain then 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 return
end 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) local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
return return actor.HasProperty("Sell") and
actor.HasProperty("Sell") and
actor.Type ~= "wall" and actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and actor.Type ~= "large_gun_turret" and
@@ -184,12 +205,71 @@ SendAirStrike = function()
end) end)
if #targets > 0 then 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)
end 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() BuildFremen = function()
if APalace.IsDead or APalace.Owner ~= AtreidesMain then if APalace.IsDead or APalace.Owner ~= AtreidesMain then
return return
@@ -302,7 +382,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
local units = AtreidesMain.GetActorsByType("harvester") local units = AtreidesMain.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[AtreidesMain] = false LastHarvesterEaten[AtreidesMain] = false
ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
@@ -311,7 +390,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesSmall] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesSmall] then
local units = AtreidesSmall.GetActorsByType("harvester") local units = AtreidesSmall.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[AtreidesSmall] = false LastHarvesterEaten[AtreidesSmall] = false
ProtectHarvester(units[1], AtreidesSmall, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], AtreidesSmall, AttackGroupSize[Difficulty])
@@ -320,7 +398,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoMain] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoMain] then
local units = CorrinoMain.GetActorsByType("harvester") local units = CorrinoMain.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[CorrinoMain] = false LastHarvesterEaten[CorrinoMain] = false
ProtectHarvester(units[1], CorrinoMain, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], CorrinoMain, AttackGroupSize[Difficulty])
@@ -329,7 +406,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoSmall] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoSmall] then
local units = CorrinoSmall.GetActorsByType("harvester") local units = CorrinoSmall.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[CorrinoSmall] = false LastHarvesterEaten[CorrinoSmall] = false
ProtectHarvester(units[1], CorrinoSmall, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], CorrinoSmall, AttackGroupSize[Difficulty])
@@ -366,8 +442,8 @@ WorldLoaded = function()
Camera.Position = HBarracks.CenterPosition Camera.Position = HBarracks.CenterPosition
AtreidesAttackLocation = HBarracks.Location AtreidesAttackLocation = HBarracks.Location
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike) Trigger.AfterDelay(DateTime.Minutes(10), function() AirstrikeLogic(AHiTechFactory) end )
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds (30), BuildFremen) Trigger.AfterDelay(EarlyGameStage, BuildFremen)
Trigger.OnAllKilledOrCaptured(AtreidesMainBase, function() Trigger.OnAllKilledOrCaptured(AtreidesMainBase, function()
Utils.Do(AtreidesMain.GetGroundAttackers(), IdleHunt) Utils.Do(AtreidesMain.GetGroundAttackers(), IdleHunt)
@@ -385,14 +461,22 @@ WorldLoaded = function()
Utils.Do(CorrinoSmall.GetGroundAttackers(), IdleHunt) Utils.Do(CorrinoSmall.GetGroundAttackers(), IdleHunt)
end) 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 path = function() return Utils.Random(AtreidesPaths) end
local waveCondition = function() return Harkonnen.IsObjectiveCompleted(KillAtreides) end local waveCondition = function() return Harkonnen.IsObjectiveCompleted(KillAtreides) end
local huntFunction = function(unit) local huntFunction = function(unit)
unit.AttackMove(AtreidesAttackLocation) unit.AttackMove(AtreidesAttackLocation)
IdleHunt(unit) IdleHunt(unit)
end 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() SendStarportReinforcements()
Actor.Create("upgrade.barracks", true, { Owner = AtreidesMain }) Actor.Create("upgrade.barracks", true, { Owner = AtreidesMain })

Binary file not shown.

View File

@@ -454,9 +454,6 @@ Actors:
COutpost: outpost COutpost: outpost
Location: 79,42 Location: 79,42
Owner: Corrino Main Base Owner: Corrino Main Base
CPalace: palace
Location: 89,42
Owner: Corrino Main Base
Actor116: wall Actor116: wall
Location: 93,42 Location: 93,42
Owner: Corrino Main Base Owner: Corrino Main Base
@@ -1005,6 +1002,68 @@ Actors:
CPower8: wind_trap CPower8: wind_trap
Owner: Corrino Main Base Owner: Corrino Main Base
Location: 90,48 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,208 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 5000 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: World:
LuaScript: LuaScript:
@@ -62,3 +264,28 @@ grenadier:
thumper: thumper:
Buildable: Buildable:
Prerequisites: ~disabled 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

View File

@@ -32,6 +32,7 @@ HarkonnenReinforcements =
} }
HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location } HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location }
HarkonnenAttackDelay = DateTime.Seconds(30) HarkonnenAttackDelay = DateTime.Seconds(30)
HarkonnenAttackWaves = HarkonnenAttackWaves =
@@ -49,6 +50,7 @@ ToHarvest =
} }
OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" } OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" }
OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location } OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location }
Messages = Messages =
@@ -118,14 +120,10 @@ WorldLoaded = function()
end end
Trigger.OnRemovedFromWorld(OrdosConyard, function() Trigger.OnRemovedFromWorld(OrdosConyard, function()
-- Mission already failed, no need to check the other conditions as well -- Mission already failed, no need to check the other conditions as well
if checkResourceCapacity() then if checkResourceCapacity() then return end
return
end
local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Ordos end) local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Ordos end)
if #refs == 0 then if #refs == 0 then
Harkonnen.MarkCompletedObjective(KillOrdos) Harkonnen.MarkCompletedObjective(KillOrdos)
else else

View File

@@ -32,6 +32,7 @@ HarkonnenReinforcements =
} }
HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location, HarkonnenWaypoint4.Location } HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location, HarkonnenWaypoint4.Location }
HarkonnenAttackDelay = DateTime.Seconds(30) HarkonnenAttackDelay = DateTime.Seconds(30)
HarkonnenAttackWaves = HarkonnenAttackWaves =
@@ -49,6 +50,7 @@ ToHarvest =
} }
OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" } OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" }
OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location } OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location }
Messages = Messages =
@@ -118,14 +120,10 @@ WorldLoaded = function()
end end
Trigger.OnRemovedFromWorld(OrdosConyard, function() Trigger.OnRemovedFromWorld(OrdosConyard, function()
-- Mission already failed, no need to check the other conditions as well -- Mission already failed, no need to check the other conditions as well
if checkResourceCapacity() then if checkResourceCapacity() then return end
return
end
local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Ordos end) local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" and actor.Owner == Ordos end)
if #refs == 0 then if #refs == 0 then
Harkonnen.MarkCompletedObjective(KillOrdos) Harkonnen.MarkCompletedObjective(KillOrdos)
else else

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -24,10 +24,13 @@ AttackDelays =
HarkonnenInfantryTypes = { "light_inf" } HarkonnenInfantryTypes = { "light_inf" }
ActivateAI = function() ActivateAI = function()
Defending[Harkonnen] = {}
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
IdlingUnits[Harkonnen] = { } 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 toBuild = function() return HarkonnenInfantryTypes end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)

View File

@@ -8,6 +8,7 @@
]] ]]
HarkonnenBase = { HConyard, HPower1, HPower2, HBarracks, HOutpost } 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) } 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 = HarkonnenReinforcements =
@@ -78,6 +79,7 @@ HarkonnenAttackWaves =
} }
OrdosReinforcements = { "light_inf", "light_inf", "raider" } OrdosReinforcements = { "light_inf", "light_inf", "raider" }
OrdosEntryPath = { OrdosEntry.Location, OrdosRally.Location } OrdosEntryPath = { OrdosEntry.Location, OrdosRally.Location }
Tick = function() Tick = function()

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -24,10 +24,14 @@ AttackDelays =
HarkonnenInfantryTypes = { "light_inf" } HarkonnenInfantryTypes = { "light_inf" }
ActivateAI = function() ActivateAI = function()
Defending[Harkonnen] = {}
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Harkonnen] = true
IdlingUnits[Harkonnen] = { } 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 toBuild = function() return HarkonnenInfantryTypes end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5 attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize) ProduceUnits(Harkonnen, HBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)

Binary file not shown.

View File

@@ -143,6 +143,19 @@ Actors:
HSilo4: silo HSilo4: silo
Owner: Harkonnen Owner: Harkonnen
Location: 4,60 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,9 +22,16 @@ AttackDelays =
} }
HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
HarkonnenVehicleTypes = { "trike", "trike", "quad" } HarkonnenVehicleTypes = { "trike", "trike", "quad" }
InitAIUnits = function() 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) IdlingUnits[Harkonnen] = Reinforcements.Reinforce(Harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath)
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
@@ -37,14 +44,31 @@ ActivateAI = function()
HConyard.Produce(OrdosUpgrades[1]) HConyard.Produce(OrdosUpgrades[1])
HConyard.Produce(OrdosUpgrades[2]) 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 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 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
-- Finish the upgrades first before trying to build something -- Finish the upgrades first before trying to build something
Trigger.AfterDelay(DateTime.Seconds(14), function() Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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)
end end

View File

@@ -8,6 +8,7 @@
]] ]]
HarkonnenBase = { HBarracks, HWindTrap1, HWindTrap2, HLightFactory, HOutpost, HConyard, HRefinery, HSilo1, HSilo2, HSilo3, HSilo4 } 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) } 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 = HarkonnenReinforcements =
@@ -65,15 +66,19 @@ HarkonnenPaths =
} }
HarkonnenHunters = { "light_inf", "light_inf", "trike", "quad" } HarkonnenHunters = { "light_inf", "light_inf", "trike", "quad" }
HarkonnenInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" } HarkonnenInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
HarkonnenHunterPath = { HarkonnenEntry5.Location, HarkonnenRally5.Location } HarkonnenHunterPath = { HarkonnenEntry5.Location, HarkonnenRally5.Location }
HarkonnenInitialPath = { HarkonnenEntry4.Location, HarkonnenRally4.Location } HarkonnenInitialPath = { HarkonnenEntry4.Location, HarkonnenRally4.Location }
OrdosReinforcements = { "quad", "raider" } OrdosReinforcements = { "quad", "raider" }
OrdosPath = { OrdosEntry.Location, OrdosRally.Location } OrdosPath = { OrdosEntry.Location, OrdosRally.Location }
OrdosBaseBuildings = { "barracks", "light_factory" } OrdosBaseBuildings = { "barracks", "light_factory" }
OrdosUpgrades = { "upgrade.barracks", "upgrade.light" } OrdosUpgrades = { "upgrade.barracks", "upgrade.light" }
MessageCheck = function(index) MessageCheck = function(index)

View File

@@ -1,6 +1,32 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 5000 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: World:
LuaScript: LuaScript:

View File

@@ -254,6 +254,16 @@ Actors:
HarkonnenEntry8: waypoint HarkonnenEntry8: waypoint
Owner: Neutral Owner: Neutral
Location: 2,20 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(9) }, easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) }, normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,29 +22,59 @@ AttackDelays =
} }
HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
HarkonnenVehicleTypes = { "trike", "trike", "quad" } HarkonnenVehicleTypes = { "trike", "trike", "quad" }
InitAIUnits = function() InitAIUnits = function()
IdlingUnits[Harkonnen] = Reinforcements.Reinforce(Harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath) IdlingUnits[Harkonnen] = Reinforcements.Reinforce(Harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath)
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
end end
ActivateAI = function() ActivateAI = function()
Defending[Harkonnen] = {}
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Harkonnen] = true 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) Trigger.AfterDelay(0, InitAIUnits)
HConyard.Produce(OrdosUpgrades[1]) HConyard.Produce(OrdosUpgrades[1])
HConyard.Produce(OrdosUpgrades[2]) 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 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 local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
-- Finish the upgrades first before trying to build something -- Finish the upgrades first before trying to build something
Trigger.AfterDelay(DateTime.Seconds(14), function() Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize) 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)
end end

View File

@@ -8,6 +8,7 @@
]] ]]
HarkonnenBase = { HBarracks, HWindTrap1, HWindTrap2, HWindTrap3, HWindTrap4, HLightFactory, HOutpost, HConyard, HRefinery, HSilo1, HSilo2, HSilo3, HSilo4 } 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) } 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 = HarkonnenReinforcements =
@@ -79,6 +80,7 @@ HarkonnenHunterPaths =
} }
HarkonnenInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" } HarkonnenInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
HarkonnenInitialPath = { HarkonnenEntry4.Location, HarkonnenRally4.Location } HarkonnenInitialPath = { HarkonnenEntry4.Location, HarkonnenRally4.Location }
OrdosReinforcements = OrdosReinforcements =
@@ -103,6 +105,7 @@ OrdosReinforcementDelays =
} }
OrdosBaseBuildings = { "barracks", "light_factory" } OrdosBaseBuildings = { "barracks", "light_factory" }
OrdosUpgrades = { "upgrade.barracks", "upgrade.light" } OrdosUpgrades = { "upgrade.barracks", "upgrade.light" }
MessageCheck = function(index) MessageCheck = function(index)
@@ -129,7 +132,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Harkonnen] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Harkonnen] then
local units = Harkonnen.GetActorsByType("harvester") local units = Harkonnen.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[Harkonnen] = false LastHarvesterEaten[Harkonnen] = false
ProtectHarvester(units[1], Harkonnen, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], Harkonnen, AttackGroupSize[Difficulty])

View File

@@ -1,6 +1,32 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 5000 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: World:
LuaScript: LuaScript:

View File

@@ -66,6 +66,7 @@ Actors:
HGunTurret1: medium_gun_turret HGunTurret1: medium_gun_turret
Location: 38,3 Location: 38,3
Owner: Harkonnen Owner: Harkonnen
TurretFacing: 512
Actor3: wall Actor3: wall
Location: 42,3 Location: 42,3
Owner: Smugglers Owner: Smugglers
@@ -87,6 +88,7 @@ Actors:
HGunTurret2: medium_gun_turret HGunTurret2: medium_gun_turret
Location: 38,7 Location: 38,7
Owner: Harkonnen Owner: Harkonnen
TurretFacing: 512
Actor10: trooper Actor10: trooper
Location: 39,7 Location: 39,7
Owner: Harkonnen Owner: Harkonnen
@@ -300,6 +302,7 @@ Actors:
SGunTurret3: medium_gun_turret SGunTurret3: medium_gun_turret
Location: 57,20 Location: 57,20
Owner: Smugglers Owner: Smugglers
TurretFacing: 512
HPower1: wind_trap HPower1: wind_trap
Location: 44,21 Location: 44,21
Owner: Harkonnen Owner: Harkonnen
@@ -330,6 +333,7 @@ Actors:
HGunTurret3: medium_gun_turret HGunTurret3: medium_gun_turret
Location: 47,29 Location: 47,29
Owner: Harkonnen Owner: Harkonnen
TurretFacing: 512
Actor97: wall Actor97: wall
Location: 48,29 Location: 48,29
Owner: Harkonnen Owner: Harkonnen
@@ -348,6 +352,7 @@ Actors:
HGunTurret4: medium_gun_turret HGunTurret4: medium_gun_turret
Location: 11,32 Location: 11,32
Owner: Harkonnen Owner: Harkonnen
TurretFacing: 512
Actor103: light_inf Actor103: light_inf
Location: 12,32 Location: 12,32
Owner: Harkonnen Owner: Harkonnen
@@ -378,15 +383,6 @@ Actors:
Actor112: wall Actor112: wall
Location: 17,36 Location: 17,36
Owner: Harkonnen 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 Actor116: spicebloom.spawnpoint
Location: 7,40 Location: 7,40
Owner: Neutral Owner: Neutral
@@ -396,9 +392,6 @@ Actors:
Actor118: wall Actor118: wall
Location: 38,40 Location: 38,40
Owner: Harkonnen Owner: Harkonnen
Actor119: light_inf
Location: 42,40
Owner: Harkonnen
Actor120: wall Actor120: wall
Location: 37,41 Location: 37,41
Owner: Harkonnen Owner: Harkonnen
@@ -516,6 +509,24 @@ Actors:
Actor152: wall Actor152: wall
Owner: Smugglers Owner: Smugglers
Location: 49,19 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10 hard = 10
} }
AttackDelays = ProductionDelays =
{ {
easy = { DateTime.Seconds(4), DateTime.Seconds(7) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -24,23 +24,42 @@ AttackDelays =
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
HarkonnenVehicleTypes = { "trike", "trike", "quad" } HarkonnenVehicleTypes = { "trike", "trike", "quad" }
HarkonnenTankType = { "combat_tank_h" } HarkonnenTankType = { "combat_tank_h" }
SmugglerVehicleTypes = { "raider", "raider", "quad" } SmugglerVehicleTypes = { "raider", "raider", "quad" }
SmugglerTankType = { "combat_tank_o" } SmugglerTankType = { "combat_tank_o" }
InitAIUnits = function(house) InitAIUnits = function(house)
LastHarvesterEaten[house] = true LastHarvesterEaten[house] = true
IdlingUnits[house] = Reinforcements.Reinforce(house, InitialReinforcements[house.InternalName], InitialReinforcementsPaths[house.InternalName]) IdlingUnits[house] = Reinforcements.Reinforce(house, InitialReinforcements[house.InternalName], InitialReinforcementsPaths[house.InternalName])
DefendAndRepairBase(house, Base[house.InternalName], 0.75, AttackGroupSize[Difficulty]) DefendAndRepairBase(house, Base[house.InternalName], 0.75, AttackGroupSize[Difficulty])
end end
ActivateAI = function() 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(Harkonnen)
InitAIUnits(Smuggler) 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 infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local hVehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end local hVehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
local hTanksToBuild = function() return HarkonnenTankType end local hTanksToBuild = function() return HarkonnenTankType end
@@ -55,4 +74,29 @@ ActivateAI = function()
ProduceUnits(Smuggler, SBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize) ProduceUnits(Smuggler, SBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(Smuggler, SLightFactory, delay, sVehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize) ProduceUnits(Smuggler, SLightFactory, delay, sVehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(Smuggler, SHeavyFactory, delay, sTanksToBuild, 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 end

View File

@@ -73,7 +73,6 @@ end
CheckHarvester = function(house) CheckHarvester = function(house)
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[house] then if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[house] then
local units = house.GetActorsByType("harvester") local units = house.GetActorsByType("harvester")
if #units > 0 then if #units > 0 then
LastHarvesterEaten[house] = false LastHarvesterEaten[house] = false
ProtectHarvester(units[1], house, AttackGroupSize[Difficulty]) ProtectHarvester(units[1], house, AttackGroupSize[Difficulty])
@@ -131,6 +130,7 @@ WorldLoaded = function()
Trigger.OnKilled(SOutpost, function() Trigger.OnKilled(SOutpost, function()
Ordos.MarkFailedObjective(CaptureOutpost) Ordos.MarkFailedObjective(CaptureOutpost)
end) end)
Trigger.OnCapture(SOutpost, function() Trigger.OnCapture(SOutpost, function()
Trigger.AfterDelay(DateTime.Seconds(2), function() Trigger.AfterDelay(DateTime.Seconds(2), function()
Ordos.MarkCompletedObjective(CaptureOutpost) Ordos.MarkCompletedObjective(CaptureOutpost)
@@ -138,6 +138,7 @@ WorldLoaded = function()
end) end)
SOutpost.GrantCondition("modified") SOutpost.GrantCondition("modified")
end) end)
Trigger.OnDamaged(SOutpost, function(_, attacker) Trigger.OnDamaged(SOutpost, function(_, attacker)
if SOutpost.Owner ~= Smuggler or attacker.IsDead or attacker.Owner ~= Ordos then if SOutpost.Owner ~= Smuggler or attacker.IsDead or attacker.Owner ~= Ordos then
return return
@@ -157,4 +158,14 @@ WorldLoaded = function()
Trigger.AfterDelay(HarkonnenAttackDelay[Difficulty], function() Trigger.AfterDelay(HarkonnenAttackDelay[Difficulty], function()
Media.DisplayMessage(UserInterface.GetFluentMessage("warning-large-force-approaching"), Mentat) Media.DisplayMessage(UserInterface.GetFluentMessage("warning-large-force-approaching"), Mentat)
end) 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 end

View File

@@ -1,6 +1,64 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 5000 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: World:
LuaScript: LuaScript:

Binary file not shown.

View File

@@ -570,6 +570,28 @@ Actors:
AtreidesEntry8: waypoint AtreidesEntry8: waypoint
Owner: Neutral Owner: Neutral
Location: 2,58 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 Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -7,6 +7,31 @@
information, see COPYING. 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 = AttackGroupSize =
{ {
easy = 6, easy = 6,
@@ -14,7 +39,14 @@ AttackGroupSize =
hard = 10 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) }, easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) }, normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,7 +54,9 @@ AttackDelays =
} }
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" } EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
EnemyVehicleTypes = { "trike", "trike", "quad" } EnemyVehicleTypes = { "trike", "trike", "quad" }
EnemyTankType = { "combat_tank_a" } EnemyTankType = { "combat_tank_a" }
InitAIUnits = function(house) InitAIUnits = function(house)
@@ -37,21 +71,60 @@ InitAIUnits = function(house)
end end
ActivateAIProduction = function() 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 infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuild = function() return EnemyTankType 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) Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function()
ProduceUnits(AtreidesMain, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize) ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackTresholdSize) 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 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 end
ActivateAI = function() ActivateAI = function()
@@ -59,4 +132,19 @@ ActivateAI = function()
InitAIUnits(AtreidesSmall1) InitAIUnits(AtreidesSmall1)
InitAIUnits(AtreidesSmall2) InitAIUnits(AtreidesSmall2)
InitAIUnits(AtreidesSmall3) 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 end

View File

@@ -109,6 +109,16 @@ CheckHarvester = function(house)
end end
CachedResources = -1 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() Tick = function()
if Ordos.Resources > SpiceToHarvest - 1 then if Ordos.Resources > SpiceToHarvest - 1 then
Ordos.MarkCompletedObjective(GatherSpice) Ordos.MarkCompletedObjective(GatherSpice)
@@ -215,11 +225,13 @@ WorldLoaded = function()
APower9.Sell() APower9.Sell()
end end
end) end)
Trigger.OnKilledOrCaptured(APower8, function() Trigger.OnKilledOrCaptured(APower8, function()
if not AIProductionActivated then if not AIProductionActivated then
ActivateAIProduction() ActivateAIProduction()
end end
end) end)
Trigger.OnKilledOrCaptured(APower9, function() Trigger.OnKilledOrCaptured(APower9, function()
if not AIProductionActivated then if not AIProductionActivated then
ActivateAIProduction() ActivateAIProduction()

View File

@@ -1,6 +1,64 @@
Player: Player:
PlayerResources: PlayerResources:
DefaultCash: 6000 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: World:
LuaScript: LuaScript:

View File

@@ -576,6 +576,25 @@ Actors:
HarkonnenEntry7: waypoint HarkonnenEntry7: waypoint
Owner: Neutral Owner: Neutral
Location: 34,2 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 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