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.
destroy-smugglers-mercenaries = Destroy the Smugglers and their mercenaries.
capture-harkonnen-barracks-release-hostages = Capture the Harkonnen barracks to release the hostages.
use-engineer-hint = Use engineers to reclaim destroyed vehicles.
## harkonnen-01ab, harkonnen-03ab
eliminate-atreides-units-reinforcements = Eliminate all Atreides forces and reinforcements in the area.
@@ -112,6 +113,8 @@ destroy-ordos = Destroy the Ordos.
## harkonnen-06ab
ixian-transports-detected = Ixian transports detected.
capture-destroy-ordos-starport = Capture or destroy the Ordos Starport.
smuggler-warning-harkonnen = Mind your own business Harkonnen.
smuggler-warning-ordos = Mind your own business Ordos.
## harkonnen-06ab, harkonnen-09ab
smugglers-now-hostile = The Smugglers are now hostile!
@@ -132,6 +135,8 @@ atreides-commander = Atreides Commander
## harkonnen-09ab
build-deploy-mcv = Build and deploy an MCV to establish a Construction Yard.
husk-reclaimed-harkonnen = We reclaimed some Atreides wreckage from battle.
engineers-hint = Our engineers maybe find then useful.
## ordos-01ab, ordos-02ab, ordos-03ab, ordos-04, ordos-05
outpost-not-captured-destroyed = Do not let the Outpost be captured or destroyed.

View File

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

View File

@@ -168,6 +168,13 @@ Actors:
HarkonnenRally4: waypoint
Owner: Neutral
Location: 30,28
Actor5: harvester.debris
Owner: Creeps
Facing: 384
Location: 18,18
Actor25: crate
Owner: Neutral
Location: 42,39
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

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

View File

@@ -138,6 +138,9 @@ Actors:
HarkonnenRally4: waypoint
Owner: Neutral
Location: 30,28
Actor4: crate
Owner: Neutral
Location: 12,21
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -13,7 +13,8 @@ AttackGroupSize =
normal = 8,
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -33,13 +34,16 @@ InitAIUnits = function()
end
ActivateAI = function()
Defending[Ordos] = { }
AttackDelay[Ordos] = 12000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Ordos] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Ordos] = true
Trigger.AfterDelay(0, InitAIUnits)
OConyard.Produce(AtreidesUpgrades[1])
OConyard.Produce(AtreidesUpgrades[2])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
@@ -49,4 +53,22 @@ ActivateAI = function()
ProduceUnits(Ordos, OBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
if Difficulty ~= "easy" then
Ordos.GrantCondition("base-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
}
Trigger.OnBuildingPlaced(Ordos, function(p, building)
table.insert(OrdosBase, building)
DefendAndRepairBase(Ordos, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Ordos, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

View File

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

Binary file not shown.

View File

@@ -135,6 +135,20 @@ Actors:
OrdosRally2: waypoint
Owner: Neutral
Location: 39,30
Actor3: crate_explosion
Owner: Neutral
Location: 17,5
Actor4: carryall.debris
Owner: Neutral
Facing: 384
Location: 44,14
Actor6: combat_tank_h.debris
Facing: 384
Location: 18,52
Owner: Creeps
Actor7: crate_explosion
Owner: Neutral
Location: 4,52
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,33 @@
Player:
PlayerResources:
DefaultCash: 3000
ExternalCondition@AI:
Condition: base-rebuilder
BaseBuilderBotModule@Ordos:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, barracks
SiloTypes: silo
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
wind_trap: 4
light_factory: 1
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
World:
LuaScript:

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -24,6 +24,10 @@ AttackDelays =
OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
InitAIUnits = function()
Defending[Ordos] = {}
AttackDelay[Ordos] = 12000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Ordos] = 5000 * DifficultyModifier[Difficulty]
DefencePerimeter[Ordos] = GetCellsInRectangle(CPos.New(9,6), CPos.New(20,27))
IdlingUnits[Ordos] = Reinforcements.Reinforce(Ordos, InitialOrdosReinforcements, OrdosPaths[2])
DefendAndRepairBase(Ordos, OrdosBase, 0.75, AttackGroupSize[Difficulty])
end
@@ -34,7 +38,7 @@ ActivateAI = function()
OConyard.Produce(AtreidesUpgrades[1])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
local toBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
@@ -42,4 +46,29 @@ ActivateAI = function()
Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Ordos, OBarracks, delay, toBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
if Difficulty ~= "easy" then
Ordos.GrantCondition("base-rebuilder")
end
local productionTypes =
{
barracks = toBuild,
}
Trigger.OnBuildingPlaced(Ordos, function(p, building)
table.insert(OrdosBase, building)
DefendAndRepairBase(Ordos, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Ordos, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
Utils.Do(OrdosScouts, function(a)
Trigger.OnKilled(a, function(self, killer)
if not killer.IsDead then
CheckArea(Ordos, killer.Location, 4)
end
end)
end)
end

View File

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

Binary file not shown.

View File

@@ -48,24 +48,9 @@ Actors:
Actor3: wormspawner
Location: 27,14
Owner: Creeps
Actor8: light_inf
Location: 48,24
Owner: Ordos
Actor9: light_inf
Location: 19,34
Owner: Ordos
Actor10: light_inf
Location: 35,34
Owner: Ordos
Actor11: trooper
Location: 18,35
Owner: Ordos
Actor12: light_inf
Location: 18,37
Owner: Ordos
Actor13: trooper
Location: 19,39
Owner: Ordos
Actor14: light_inf
Location: 34,50
Owner: Ordos
@@ -132,6 +117,33 @@ Actors:
OrdosRally2: waypoint
Owner: Neutral
Location: 15,34
HarvesterDebris: harvester.debris
Owner: Creeps
Facing: 384
Location: 50,12
Actor0: combat_tank_a.debris
Owner: Creeps
Facing: 384
Location: 22,37
Actor1: harvester.debris
Owner: Creeps
Facing: 384
Location: 25,10
OScout1: light_inf
Location: 48,24
Owner: Ordos
OScout2: light_inf
Location: 35,34
Owner: Ordos
Actor13: trooper
Location: 19,39
Owner: Ordos
Actor9: light_inf
Location: 19,34
Owner: Ordos
OScout3: trooper
Location: 18,35
Owner: Ordos
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,32 @@
Player:
PlayerResources:
DefaultCash: 3000
ExternalCondition@AI:
Condition: base-rebuilder
BaseBuilderBotModule@Ordos:
RequiresCondition: base-rebuilder
BuildingQueues: Building
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
wind_trap: 2
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
World:
LuaScript:

View File

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

View File

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

Binary file not shown.

View File

@@ -413,7 +413,44 @@ Actors:
Location: 5,23
FremenRally: waypoint
Owner: Neutral
Location: 56,54
Location: 56,56
Actor27: combat_tank_h.debris
Owner: Creeps
Facing: 384
Location: 58,50
Actor33: frigate.debris
Owner: Creeps
Location: 33,28
Actor34: crate
Owner: Fremen
Location: 39,57
Actor36: crate
Owner: Fremen
Location: 38,57
Actor53: crate
Owner: Fremen
Location: 37,57
Actor54: crate
Owner: Fremen
Location: 37,56
Actor57: crate
Owner: Fremen
Location: 38,56
Actor59: crate
Owner: Fremen
Location: 39,56
Actor62: combat_tank_a.debris
Owner: Creeps
Facing: 384
Location: 14,45
Actor8: combat_tank_h.debris
Owner: Creeps
Facing: 384
Location: 51,57
Actor63: combat_tank_a.debris
Owner: Creeps
Facing: 384
Location: 31,48
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -7,6 +7,17 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(5)
InitialProductionDelay = {
HarkonnenMain =
{
easy = DateTime.Seconds(100),
normal = DateTime.Seconds(60),
hard = DateTime.Seconds(30)
}
}
AttackGroupSize =
{
easy = 6,
@@ -14,7 +25,14 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
EarlyProductionDelays =
{
easy = { DateTime.Seconds(7), DateTime.Seconds(10) },
normal = { DateTime.Seconds(5), DateTime.Seconds(7) },
hard = { DateTime.Seconds(3), DateTime.Seconds(5) }
}
LateProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,7 +40,9 @@ AttackDelays =
}
HarkonnenInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
HarkonnenVehicleTypes = { "trike", "trike", "trike", "quad", "quad" }
HarkonnenTankType = { "combat_tank_h" }
InitAIUnits = function()
@@ -49,7 +69,13 @@ ProduceInfantry = function()
return
end
local delay = Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1)
local delay = 0
if EarlyGameStage >= DateTime.GameTime then
delay = Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
else
delay = Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
end
local toBuild = { Utils.Random(HarkonnenInfantryTypes) }
Harkonnen.Build(toBuild, function(unit)
IdlingUnits[Harkonnen][#IdlingUnits[Harkonnen] + 1] = unit[1]
@@ -63,15 +89,56 @@ end
ActivateAI = function()
Harkonnen.Cash = 15000
Defending[Harkonnen] = {}
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
HarvesterCount[Harkonnen] = 1
PatrolPoints[Harkonnen] = { HPatrolPoint1.Location, HPatrolPoint2.Location,HPatrolPoint3.Location }
DefencePerimeter[Harkonnen] = GetCellsInRectangle(CPos.New(13,13), CPos.New(36,25))
LastHarvesterEaten[Harkonnen] = true
InitAIUnits()
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
if EarlyGameStage >= DateTime.GameTime then
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
else
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
end
end
local vehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
local tanksToBuild = function() return HarkonnenTankType end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceInfantry()
ProduceUnits(Harkonnen, HarkonnenLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Harkonnen, HarkonnenHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["HarkonnenMain"][Difficulty], function()
ProduceInfantry()
ProduceUnits(Harkonnen, HarkonnenLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Harkonnen, HarkonnenHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
ActivateCrushLogic()
if Difficulty == "normal" then
Harkonnen.GrantCondition("base-rebuilder")
end
if Difficulty == "hard" then
Harkonnen.GrantCondition("defense-rebuilder")
end
local productionTypes =
{
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuild
}
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
table.insert(HarkonnenBase, building)
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

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

Binary file not shown.

View File

@@ -365,6 +365,41 @@ Actors:
HarkonnenRally4: waypoint
Owner: Neutral
Location: 49,4
HPatrolPoint1: waypoint
Owner: Neutral
Location: 40,27
HPatrolPoint2: waypoint
Owner: Neutral
Location: 21,38
HPatrolPoint3: waypoint
Owner: Neutral
Location: 24,60
Actor0: repair_pad
Owner: Atreides
Location: 59,59
Actor1: combat_tank_a.debris
Owner: Atreides
Facing: 384
Location: 59,63
Actor2: combat_tank_a.debris
Owner: Atreides
Facing: 384
Location: 62,63
Actor3: combat_tank_a.debris
Owner: Atreides
Facing: 384
Location: 56,62
Actor9: harvester.debris
Owner: Creeps
Facing: 384
Location: 17,47
HarkonnenTankDebris1: combat_tank_h.debris
Owner: Creeps
Facing: 384
Location: 8,58
Trigger1: waypoint
Owner: Neutral
Location: 8,58
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,64 @@
Player:
PlayerResources:
DefaultCash: 7000
ExternalCondition@AI:
Condition: base-rebuilder
ExternalCondition@AIDefense:
Condition: defense-rebuilder
BaseBuilderBotModule@campaign:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 6
silo: 1
BuildingFractions:
wind_trap: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@defense:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory
SiloTypes: silo
DefenseTypes: medium_gun_turret
SellRefineryInterval: -1
BuildingLimits:
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 6
silo: 1
medium_gun_turret: 6
BuildingFractions:
wind_trap: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
medium_gun_turret: 1
World:
LuaScript:

View File

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

View File

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

View File

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

Binary file not shown.

View File

@@ -162,6 +162,12 @@ Actors:
AtreidesRally4: waypoint
Owner: Neutral
Location: 47,4
Actor1: crate
Owner: Neutral
Location: 33,47
Actor3: crate_reveal
Owner: Neutral
Location: 27,16
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

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

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,9 +22,13 @@ AttackDelays =
}
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
AtreidesVehicleTypes = { "trike", "trike", "quad" }
ActivateAI = function()
Defending[Atreides] = {}
AttackDelay[Atreides] = 7000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Atreides] = 5000 * DifficultyModifier[Difficulty]
IdlingUnits[Atreides] = { }
LastHarvesterEaten[Atreides] = true
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
@@ -32,14 +36,31 @@ ActivateAI = function()
AConyard.Produce(HarkonnenUpgrades[1])
AConyard.Produce(HarkonnenUpgrades[2])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
-- Finish the upgrades first before trying to build something
Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Atreides, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
if Difficulty ~= "easy" then
Atreides.GrantCondition("base-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
}
Trigger.OnBuildingPlaced(Atreides, function(p, building)
table.insert(OrdosMainBase, building)
DefendAndRepairBase(Atreides, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Atreides, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

View File

@@ -8,6 +8,7 @@
]]
AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, ALightFactory, AOutpost, AConyard, ARefinery, ASilo }
AtreidesBaseAreaTriggers =
{
{ CPos.New(34, 50), CPos.New(35, 50), CPos.New(36, 50), CPos.New(37, 50), CPos.New(38, 50), CPos.New(39, 50), CPos.New(40, 50), CPos.New(41, 50), CPos.New(14, 57), CPos.New(14, 58), CPos.New(14, 59), CPos.New(14, 60), CPos.New(14, 61), CPos.New(14, 62), CPos.New(14, 63), CPos.New(14, 64), CPos.New(14, 65)},
@@ -88,9 +89,11 @@ AtreidesHunterPaths =
}
HarkonnenReinforcements = { "trike", "trike", "quad" }
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
HarkonnenBaseBuildings = { "barracks", "light_factory" }
HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" }
MessageCheck = function(index)

Binary file not shown.

View File

@@ -177,6 +177,17 @@ Actors:
HarkonnenEntry: waypoint
Owner: Neutral
Location: 29,2
Actor2: carryall.debris
Owner: Creeps
Facing: 384
Location: 24,40
Actor18: crate
Owner: Neutral
Location: 17,33
Actor19: harvester.debris
Owner: Creeps
Facing: 384
Location: 12,61
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,34 @@
Player:
PlayerResources:
DefaultCash: 5000
ExternalCondition@AI:
Condition: base-rebuilder
BaseBuilderBotModule@campaign:
RequiresCondition: base-rebuilder
BuildingQueues: Building
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
wind_trap: 3
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
World:
LuaScript:

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,29 +22,48 @@ AttackDelays =
}
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
AtreidesVehicleTypes = { "trike", "trike", "quad" }
InitAIUnits = function()
IdlingUnits[Atreides] = Reinforcements.Reinforce(Atreides, AtreidesInitialReinforcements, AtreidesInitialPath)
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
end
ActivateAI = function()
Defending[Atreides] = {}
AttackDelay[Atreides] = 7000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Atreides] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Atreides] = true
Trigger.AfterDelay(0, InitAIUnits)
AConyard.Produce(HarkonnenUpgrades[1])
AConyard.Produce(HarkonnenUpgrades[2])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player) return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
-- Finish the upgrades first before trying to build something
Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Atreides, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
if Difficulty ~= "easy" then
Atreides.GrantCondition("base-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
}
Trigger.OnBuildingPlaced(Atreides, function(p, building)
table.insert(OrdosMainBase, building)
DefendAndRepairBase(Atreides, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Atreides, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

View File

@@ -8,6 +8,7 @@
]]
AtreidesBase = { ABarracks, AWindTrap1, AWindTrap2, AWindTrap3, ALightFactory, AOutpost, AConyard, ARefinery, ASilo1, ASilo2, ASilo3, ASilo4 }
AtreidesBaseAreaTriggers =
{
{ CPos.New(10, 53), CPos.New(11, 53), CPos.New(12, 53), CPos.New(13, 53), CPos.New(14, 53), CPos.New(15, 53), CPos.New(16, 53), CPos.New(17, 53), CPos.New(17, 52), CPos.New(17, 51), CPos.New(17, 50), CPos.New(17, 49), CPos.New(17, 48), CPos.New(17, 47), CPos.New(17, 46), CPos.New(17, 45), CPos.New(17, 44), CPos.New(17, 43), CPos.New(17, 42), CPos.New(17, 41), CPos.New(17, 40), CPos.New(17, 39), CPos.New(17, 38), CPos.New(2, 35), CPos.New(3, 35), CPos.New(4, 35), CPos.New(5, 35), CPos.New(6, 35), CPos.New(7, 35), CPos.New(8, 35), CPos.New(9, 35), CPos.New(10, 35), CPos.New(11, 35), CPos.New(12, 35) },
@@ -87,12 +88,15 @@ AtreidesHunterPaths =
}
AtreidesInitialPath = { AtreidesEntry2.Location, AtreidesRally2.Location }
AtreidesInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
HarkonnenReinforcements = { "quad", "quad" }
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
HarkonnenBaseBuildings = { "barracks", "light_factory" }
HarkonnenUpgrades = { "upgrade.barracks", "upgrade.light" }
MessageCheck = function(index)
@@ -150,4 +154,10 @@ WorldLoaded = function()
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[2], AtreidesHunters[2], AtreidesHunterPaths[2])
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[3], AtreidesHunters[3], AtreidesHunterPaths[3])
TriggerCarryallReinforcements(Harkonnen, Atreides, AtreidesBaseAreaTriggers[4], AtreidesHunters[4], AtreidesHunterPaths[4])
Trigger.OnRemovedFromWorld(CrateScript, function()
VisionPoint.GrantCondition("activate", 150)
Media.PlaySound("MULTI1.WAV")
Camera.Position = VisionPoint.CenterPosition
end)
end

View File

@@ -207,6 +207,13 @@ Actors:
HarkonnenEntry: waypoint
Owner: Neutral
Location: 65,45
CrateScript: crate_script
Owner: Neutral
Location: 55,9
VisionPoint: vision_provider
Faction:
Location: 46,8
Owner: Harkonnen
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,34 @@
Player:
PlayerResources:
DefaultCash: 5000
ExternalCondition@AI:
Condition: base-rebuilder
BaseBuilderBotModule@campaign:
RequiresCondition: base-rebuilder
BuildingQueues: Building
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
wind_trap: 3
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
World:
LuaScript:

View File

@@ -7,6 +7,14 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(5)
InitialProductionDelay = {
easy = DateTime.Seconds(150),
normal = DateTime.Seconds(100),
hard = DateTime.Seconds(50)
}
AttackGroupSize =
{
easy = 6,
@@ -14,7 +22,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,24 +30,71 @@ AttackDelays =
}
AtreidesInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
AtreidesVehicleTypes = { "trike", "trike", "quad" }
AtreidesTankType = { "combat_tank_a" }
local attackThresholdSize = AttackGroupSize[Difficulty] * 2
ActivateAI = function()
Defending[Atreides] = { }
Defending[Fremen] = { }
AttackDelay[Atreides] = 5000 * DifficultyModifier[Difficulty]
AttackDelay[Fremen] = 5000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Atreides] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Fremen] = 5000 * DifficultyModifier[Difficulty]
HarvesterCount[Atreides] = 2
HarvesterCount[Fremen] = 2
IdlingUnits[Fremen] = { }
IdlingUnits[Atreides] = Utils.Concat(Reinforcements.Reinforce(Atreides, InitialAtreidesReinforcements[1], AtreidesPaths[2]), Reinforcements.Reinforce(Atreides, InitialAtreidesReinforcements[2], AtreidesPaths[3]))
FremenProduction()
DefencePerimeter[Atreides] = GetCellsInRectangle(CPos.New(4,68), CPos.New(44,82))
Utils.Do(IdlingUnits[Atreides], function(a) SelectRoutine(Atreides, a) end)
PatrolPoints[Atreides] = { APatrolPoint1.Location, APatrolPoint2.Location, APatrolPoint3.Location, APatrolPoint4.Location }
DefendAndRepairBase(Atreides, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(Fremen, FremenBase, 0.75, AttackGroupSize[Difficulty])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
end
local infantryToBuild = function() return { Utils.Random(AtreidesInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local tanksToBuild = function() return AtreidesTankType end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(Atreides, ABarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Atreides, ALightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Atreides, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay[Difficulty], function()
ProduceUnits(Atreides, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Atreides, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
ActivateCrushLogic()
if Difficulty == "normal" then
Atreides.GrantCondition("base-rebuilder")
end
if Difficulty == "hard" then
Atreides.GrantCondition("defense-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuild
}
Trigger.OnBuildingPlaced(Atreides, function(p, building)
table.insert(AtreidesBase, building)
DefendAndRepairBase(Atreides, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Atreides, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

View File

@@ -7,7 +7,8 @@
information, see COPYING.
]]
AtreidesBase = { AConyard, AOutpost, ARefinery, AHeavyFactory, ALightFactory, AGunt1, AGunt2, ABarracks, ASilo, APower1, APower2, APower3, APower4, APower5, APower6 }
AtreidesBase = { AConyard, AOutpost, ARefinery, AHeavyFactory, ALightFactory, AGunt1, AGunt2, ABarracks, APower1, APower2, APower3, APower4, APower5, APower6 }
FremenBase = { FGunt1, FGunt2 }
BaseAreaTriggers =
@@ -105,6 +106,8 @@ FremenHunterPaths =
{ FremenEntry3.Location, FremenRally3.Location }
}
FremenAmbushSquad = { FremenAmbuser1, FremenAmbuser2, FremenAmbuser3, FremenAmbuser4 }
HarkonnenReinforcements = { "combat_tank_h", "combat_tank_h" }
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
@@ -156,7 +159,8 @@ WorldLoaded = function()
Atreides = Player.GetPlayer("Atreides")
Fremen = Player.GetPlayer("Fremen")
Harkonnen = Player.GetPlayer("Harkonnen")
Defending[Atreides] = {}
Defending[Fremen] = {}
InitObjectives(Harkonnen)
KillAtreides = AddPrimaryObjective(Harkonnen, "destroy-atreides")
KillFremen = AddPrimaryObjective(Harkonnen, "destroy-fremen")
@@ -164,11 +168,7 @@ WorldLoaded = function()
Camera.Position = HConyard.CenterPosition
FremenAttackLocation = HConyard.Location
Trigger.OnAllKilledOrCaptured(AtreidesBase, function()
Utils.Do(Atreides.GetGroundAttackers(), IdleHunt)
end)
IdleHuntOnBaseDestroyed(Atreides, AtreidesBase)
Trigger.OnAllKilled(Sietches, function()
SietchesAreDestroyed = true
end)
@@ -179,6 +179,7 @@ WorldLoaded = function()
unit.AttackMove(FremenAttackLocation)
IdleHunt(unit)
end
SendCarryallReinforcements(Fremen, 0, FremenAttackWaves[Difficulty], FremenAttackDelay[Difficulty], path, FremenReinforcements[Difficulty], waveCondition, huntFunction)
Actor.Create("upgrade.barracks", true, { Owner = Atreides })
@@ -201,4 +202,17 @@ WorldLoaded = function()
TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[1], FremenHunters[1], FremenHunterPaths[3], fremenCondition)
TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[2], FremenHunters[2], FremenHunterPaths[2], fremenCondition)
TriggerCarryallReinforcements(Harkonnen, Fremen, BaseAreaTriggers[3], FremenHunters[3], FremenHunterPaths[1], fremenCondition)
Trigger.OnRemovedFromWorld(ExplosionCrate, function()
Utils.Do(FremenAmbushSquad, function(fremen)
fremen.Stance = "AttackAnything"
end)
end)
Trigger.OnAllKilled({AGunt1, AGunt2}, function()
EmergencyBuildRate[Atreides] = true
Trigger.AfterDelay(600, function()
EmergencyBuildRate[Atreides] = false
end)
end)
end

View File

@@ -376,6 +376,54 @@ Actors:
AtreidesEntry3: waypoint
Owner: Neutral
Location: 22,91
APatrolPoint1: waypoint
Owner: Neutral
Location: 56,67
APatrolPoint2: waypoint
Owner: Neutral
Location: 34,43
APatrolPoint3: waypoint
Owner: Neutral
Location: 23,18
APatrolPoint4: waypoint
Owner: Neutral
Location: 60,17
Actor6: crate
Owner: Neutral
Location: 25,12
Actor8: crate
Owner: Neutral
Location: 8,18
ExplosionCrate: crate_explosion
Owner: Neutral
Location: 18,28
FremenAmbuser1: fremen
Owner: Fremen
Location: 15,25
SubCell: 3
Facing: 384
Stance: ReturnFire
FremenAmbuser2: fremen
Owner: Fremen
Location: 20,25
SubCell: 3
Stance: ReturnFire
Facing: 384
FremenAmbuser3: fremen
Owner: Fremen
Location: 15,28
SubCell: 3
Stance: ReturnFire
Facing: 384
FremenAmbuser4: fremen
Owner: Fremen
Location: 15,29
SubCell: 3
Stance: ReturnFire
Facing: 384
Actor32: crate_reveal
Owner: Neutral
Location: 16,47
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,68 @@
Player:
PlayerResources:
DefaultCash: 5000
ExternalCondition@AI:
Condition: base-rebuilder
ExternalCondition@AIDefense:
Condition: defense-rebuilder
BaseBuilderBotModule@AIMainBase:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 7
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@AIMainBaseWithDefense:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 7
silo: 1
medium_gun_turret: 2
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
medium_gun_turret: 2
World:
LuaScript:

View File

@@ -7,6 +7,24 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(6)
InitialProductionDelay = {
OrdosMain =
{
easy = DateTime.Seconds(150),
normal = DateTime.Seconds(100),
hard = DateTime.Seconds(50)
},
OrdosSmall =
{
easy = DateTime.Seconds(120),
normal = DateTime.Seconds(60),
hard = DateTime.Seconds(30)
},
}
AttackGroupSize =
{
easy = 6,
@@ -14,7 +32,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,28 +40,86 @@ AttackDelays =
}
OrdosInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
OrdosVehicleTypes = { "raider", "raider", "quad" }
OrdosTankType = { "combat_tank_o" }
ActivateAI = function()
Defending[OrdosMain] = {}
Defending[OrdosSmall] = {}
AttackDelay[OrdosMain] = 8000 * DifficultyModifier[Difficulty]
AttackDelay[OrdosSmall] = 10000 * DifficultyModifier[Difficulty]
AttackDelay[Corrino] = 1000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[OrdosMain] = 8000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[OrdosSmall] = 7000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Corrino] = 2000 * DifficultyModifier[Difficulty]
HarvesterCount[OrdosMain] = 2
HarvesterCount[OrdosSmall] = 2
Trigger.OnAllKilledOrCaptured(ProductionBuildingsOrdosSmallBase, function()
TimeBetweenAttacks[OrdosMain] = 0
end)
PatrolPoints[OrdosMain] = {OrdosPatrol1.Location, OrdosPatrol2.Location }
PatrolPoints[OrdosSmall] = {OrdosRally1.Location, OrdosRally2.Location, OrdosRally4.Location }
DefencePerimeter[OrdosMain] = GetCellsInRectangle(CPos.New(51,11), CPos.New(67,38))
DefencePerimeter[OrdosSmall] = GetCellsInRectangle(CPos.New(6,69), CPos.New(22,80))
IdlingUnits[OrdosMain] = Utils.Concat(Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[1], InitialOrdosPaths[1]), Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[2], InitialOrdosPaths[2]))
IdlingUnits[OrdosSmall] = Reinforcements.Reinforce(OrdosSmall, InitialOrdosReinforcements[1], InitialOrdosPaths[3])
IdlingUnits[Corrino] = { CSaraukar1, CSaraukar2, CSaraukar3, CSaraukar4, CSaraukar5 }
IdlingUnits[Corrino] = { CSardaukar1, CSardaukar2, CSardaukar3, CSardaukar4, CSardaukar5 }
DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(Corrino, CorrinoBase, 0.75, AttackGroupSize[Difficulty])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
end
local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
local tanksToBuild = function() return OrdosTankType end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
local attackThresholdSize = {}
attackThresholdSize[OrdosMain] = AttackGroupSize[Difficulty] * 3
attackThresholdSize[OrdosSmall] = AttackGroupSize[Difficulty] * 2
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
end)
ProduceUnits(OrdosSmall, OBarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["OrdosSmall"][Difficulty], function()
ProduceUnits(OrdosSmall, OBarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
end)
ActivateCrushLogic()
if Difficulty == "normal" then
OrdosMain.GrantCondition("base-rebuilder")
end
if Difficulty == "hard" then
OrdosMain.GrantCondition("defense-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuild
}
Trigger.OnBuildingPlaced(OrdosMain, function(p, building)
table.insert(OrdosMainBase, building)
DefendAndRepairBase(OrdosMain, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(OrdosMain, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
end)
end

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

Binary file not shown.

View File

@@ -514,6 +514,18 @@ Actors:
HarkonnenEntry2: waypoint
Owner: Neutral
Location: 2,29
OrdosPatrol1: waypoint
Owner: Neutral
Location: 33,19
OrdosPatrol2: waypoint
Owner: Neutral
Location: 37,41
Actor9: crate
Owner: Neutral
Location: 48,54
Actor10: crate
Owner: Neutral
Location: 49,53
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,68 @@
Player:
PlayerResources:
DefaultCash: 6000
ExternalCondition@AI:
Condition: base-rebuilder
ExternalCondition@AIDefense:
Condition: defense-rebuilder
BaseBuilderBotModule@campaign:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 8
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@defense:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 8
silo: 1
medium_gun_turret: 4
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
medium_gun_turret: 1
World:
LuaScript:

View File

@@ -7,6 +7,24 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(6)
InitialProductionDelay = {
OrdosMain =
{
easy = DateTime.Seconds(140),
normal = DateTime.Seconds(80),
hard = DateTime.Seconds(40)
},
OrdosSmall =
{
easy = DateTime.Seconds(120),
normal = DateTime.Seconds(60),
hard = DateTime.Seconds(30)
},
}
AttackGroupSize =
{
easy = 6,
@@ -14,7 +32,14 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
EarlyProductionDelays =
{
easy = { DateTime.Seconds(10), DateTime.Seconds(13) },
normal = { DateTime.Seconds(6), DateTime.Seconds(8) },
hard = { DateTime.Seconds(3), DateTime.Seconds(5) }
}
LateProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,29 +47,90 @@ AttackDelays =
}
OrdosInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
OrdosVehicleTypes = { "raider", "raider", "quad" }
OrdosTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" }
OrdosStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
ActivateAI = function()
Defending[OrdosMain] = {}
Defending[OrdosSmall] = {}
AttackDelay[OrdosMain] = 14000 * DifficultyModifier[Difficulty]
AttackDelay[OrdosSmall] = 14000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[OrdosMain] = 10000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[OrdosSmall] = 8000 * DifficultyModifier[Difficulty]
HarvesterCount[OrdosMain] = 4
HarvesterCount[OrdosSmall] = 2
Trigger.OnAllKilledOrCaptured(ProductionBuildingsOrdosSmallBase, function()
TimeBetweenAttacks[OrdosMain] = 0
end)
PatrolPoints[OrdosMain] = {OrdosRally5.Location, OrdosRally11.Location, OrdosRally12.Location }
PatrolPoints[OrdosSmall] = {OrdosRally5.Location, OrdosRally7.Location, OrdosRally4.Location, OrdosRally5.Location }
DefencePerimeter[OrdosMain] = Utils.Concat( GetCellsInRectangle(CPos.New(37,30), CPos.New(69,50)), GetCellsInRectangle(CPos.New(54,13), CPos.New(70,30)))
DefencePerimeter[OrdosSmall] = GetCellsInRectangle(CPos.New(4,20), CPos.New(15,40))
IdlingUnits[OrdosMain] = Utils.Concat(Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[1], InitialOrdosPaths[1]), Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[2], InitialOrdosPaths[2]))
IdlingUnits[OrdosSmall] = Reinforcements.Reinforce(OrdosSmall, InitialOrdosReinforcements[1], InitialOrdosPaths[3])
DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 0.75, AttackGroupSize[Difficulty])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
if EarlyGameStage >= DateTime.GameTime then
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
else
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
end
end
local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
local tanksToBuild = function() return { Utils.Random(OrdosTankTypes) } end
local unitsToBuy = function() return { Utils.Random(OrdosStarportTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
local attackThresholdSize = {}
attackThresholdSize[OrdosMain] = AttackGroupSize[Difficulty] * 3
attackThresholdSize[OrdosSmall] = AttackGroupSize[Difficulty] * 2
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosMain, OHeavyFactory1, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OHeavyFactory1, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
end)
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["OrdosSmall"][Difficulty], function()
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall] )
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall] )
end)
ActivateCrushLogic()
if Difficulty == "normal" then
OrdosSmall.GrantCondition("base-rebuilder2")
end
if Difficulty == "hard" then
OrdosSmall.GrantCondition("defense-rebuilder2")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuild
}
Trigger.OnBuildingPlaced(OrdosSmall, function(p, building)
table.insert(OrdosSmallBase, building)
DefendAndRepairBase(OrdosSmall, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(OrdosSmall, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
end)
end

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 }
OrdosSmallBase = { OConyard, ORefinery3, OBarracks2, OLightFactory2, OGunt13, OGunt14, OGunt15, OGunt16, OPower11, OPower12, OPower13, OPower14 }
ProductionBuildingsOrdosSmallBase = { OConyard, ORefinery3, OBarracks2, OLightFactory2 }
SmugglerTriggerZone = Utils.Concat(
GetCellsInRectangle(CPos.New(73,67), CPos.New(81,72)),
GetCellsInRectangle(CPos.New(77,73), CPos.New(82,77))
)
SmugglerPatrol = {Smuggler1, Smuggler2, Smuggler3, Smuggler4, Smuggler5, Smuggler6 }
OrdosReinforcements =
{
easy =
@@ -149,9 +159,62 @@ ChangeOwner = function(old_owner, new_owner)
end)
end
Message = {}
StopFollowing = {}
Trigger.OnEnteredFootprint(SmugglerTriggerZone, function(a, id)
if SmugglerNeutral.HasNoRequiredUnits() then
Trigger.RemoveFootprintTrigger(id)
end
if a.Owner == Harkonnen and not Message[Harkonnen] then
Media.DisplayMessage(UserInterface.GetFluentMessage("smuggler-warning-harkonnen"), "Smugglers", HSLColor.FromHex("7B2910"))
Message[Harkonnen] = true
end
if a.Owner == OrdosMain or a.Owner == OrdosSmall and not Message[Ordos] then
Media.DisplayMessage(UserInterface.GetFluentMessage("smuggler-warning-ordos"), "Smugglers", HSLColor.FromHex("7B2910"))
Message[Ordos] = true
end
if a.Owner ~= SmugglerNeutral then
Utils.Do(SmugglerPatrol, function(u)
if not u.IsDead then
StopFollowing[u] = false
FollowIntruder(u,a)
end
end)
end
end)
Trigger.OnExitedFootprint(SmugglerTriggerZone, function(a, id)
if SmugglerNeutral.HasNoRequiredUnits() then
Trigger.RemoveFootprintTrigger(id)
end
if a.Owner ~= SmugglerNeutral then
Utils.Do(SmugglerPatrol, function(u)
if not u.IsDead then StopFollowing[u] = true end
end)
end
end)
FollowIntruder = function(unit, intruder)
if intruder.IsDead or unit.IsDead then return end
if StopFollowing[unit] == true then unit.Stop() return end
unit.Stop()
unit.AttackMove(intruder.Location,1)
Trigger.AfterDelay(100, function() FollowIntruder(unit, intruder) end)
end
CheckSmugglerEnemies = function()
Utils.Do(SmugglerUnits, function(unit)
Trigger.OnDamaged(unit, function(self, attacker)
if Utils.Any(IgnoreDamageFromTypes, function(a) return a == attacker.Type end) then
return
end
if not self.HasProperty("Health") then return end
if self.MaxHealth * 0.9 < self.Health then return end
if unit.Owner == SmugglerNeutral and attacker.Owner == Harkonnen then
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
@@ -197,6 +260,25 @@ CheckSmugglerEnemies = function()
end)
end
EmergencyBehaviour = function(player, target)
if player ~= OrdosSmall then return end
if not OGunt15.IsDead and not OGunt16.IsDead then return end
if #IdlingUnits[OrdosMain] > 10 and Utils.Any(ProductionBuildingsOrdosSmallBase, function(a) return not a.IsDead end) then
local reinforcements = SetupAttackGroup(OrdosMain, Utils.RandomInteger(5, #IdlingUnits[OrdosMain]))
Utils.Do(reinforcements, function(unit)
Trigger.ClearAll(unit)
Trigger.AfterDelay(1, function()
unit.Stop()
unit.Move(OrdosRally13.Location,1)
unit.AttackMove(target)
unit.CallFunc(function()
FindTargetsInArea(player, unit)
end)
end)
end)
end
end
Tick = function()
if Harkonnen.HasNoRequiredUnits() then
OrdosMain.MarkCompletedObjective(KillHarkonnen1)
@@ -234,6 +316,8 @@ Tick = function()
ProtectHarvester(units[1], OrdosSmall, AttackGroupSize[Difficulty])
end
end
if IdlingUnits[OrdosMain] == nil and IdlingUnits[OrdosSmall] == nil then return end
end
WorldLoaded = function()
@@ -273,6 +357,7 @@ WorldLoaded = function()
unit.AttackMove(OrdosAttackLocation)
IdleHunt(unit)
end
SendCarryallReinforcements(OrdosMain, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
SendStarportReinforcements()

View File

@@ -424,12 +424,14 @@ Actors:
OGunt15: medium_gun_turret
Location: 7,37
Owner: Ordos Small Base
TurretFacing: 512
Actor111: wall
Location: 11,37
Owner: Ordos Small Base
OGunt16: medium_gun_turret
Location: 11,38
Owner: Ordos Small Base
TurretFacing: 512
Actor113: wall
Location: 12,38
Owner: Ordos Small Base
@@ -568,18 +570,12 @@ Actors:
Actor158: light_inf
Location: 9,72
Owner: Harkonnen
Actor159: light_inf
Location: 77,72
Owner: Smugglers - Neutral
SSilo3: silo
Location: 81,72
Owner: Smugglers - Neutral
Actor161: trike
Location: 11,73
Owner: Harkonnen
Actor162: trooper
Location: 80,73
Owner: Smugglers - Neutral
Actor163: trooper
Location: 7,74
Owner: Harkonnen
@@ -592,15 +588,9 @@ Actors:
SRefinery: refinery
Location: 78,74
Owner: Smugglers - Neutral
Actor167: light_inf
Location: 82,74
Owner: Smugglers - Neutral
Actor168: combat_tank_h
Location: 10,75
Owner: Harkonnen
Actor169: trooper
Location: 82,75
Owner: Smugglers - Neutral
Actor170: light_inf
Location: 15,76
Owner: Harkonnen
@@ -625,12 +615,6 @@ Actors:
Actor177: spicebloom.spawnpoint
Location: 72,77
Owner: Neutral
Actor178: light_inf
Location: 82,77
Owner: Smugglers - Neutral
Actor179: light_inf
Location: 83,77
Owner: Smugglers - Neutral
Actor180: light_inf
Location: 11,78
Owner: Harkonnen
@@ -715,6 +699,45 @@ Actors:
HarkonnenEntry2: waypoint
Owner: Neutral
Location: 2,68
OrdosRally11: waypoint
Owner: Neutral
Location: 51,66
OrdosRally12: waypoint
Owner: Neutral
Location: 79,40
OrdosRally13: waypoint
Owner: Neutral
Location: 19,16
Actor5: crate
Location: 81,67
Faction:
Owner: Smugglers - Neutral
Actor13: crate
Location: 81,69
Faction:
Owner: Smugglers - Neutral
Actor11: crate
Location: 81,71
Faction:
Owner: Smugglers - Neutral
Smuggler1: light_inf
Location: 77,72
Owner: Smugglers - Neutral
Smuggler2: trooper
Location: 80,73
Owner: Smugglers - Neutral
Smuggler3: light_inf
Location: 82,74
Owner: Smugglers - Neutral
Smuggler4: trooper
Location: 82,75
Owner: Smugglers - Neutral
Smuggler5: light_inf
Location: 82,77
Owner: Smugglers - Neutral
Smuggler6: light_inf
Location: 83,77
Owner: Smugglers - Neutral
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,66 @@
Player:
PlayerResources:
DefaultCash: 6000
ExternalCondition@AISmall:
Condition: base-rebuilder2
ExternalCondition@AISmallDefense:
Condition: defense-rebuilder2
BaseBuilderBotModule@SmallBase:
RequiresCondition: base-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
research_centre: 1
high_tech_factory: 1
wind_trap: 4
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
research_centre: 1
high_tech_factory: 1
BaseBuilderBotModule@SmallBasewithDefence:
RequiresCondition: defense-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret
SellRefineryInterval: -1
PlaceDefenseTowardsEnemyChance: 50
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
wind_trap: 4
silo: 1
medium_gun_turret: 4
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
medium_gun_turret: 1
World:
LuaScript:

View File

@@ -7,6 +7,23 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(7)
InitialProductionDelay = {
OrdosMain =
{
easy = DateTime.Seconds(180),
normal = DateTime.Seconds(120),
hard = DateTime.Seconds(60)
},
OrdosSmall =
{
easy = DateTime.Seconds(120),
normal = DateTime.Seconds(60),
hard = DateTime.Seconds(0)
}
}
AttackGroupSize =
{
easy = 6,
@@ -14,7 +31,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,29 +39,108 @@ AttackDelays =
}
OrdosInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
OrdosVehicleTypes = { "raider", "raider", "quad" }
OrdosTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" }
OrdosStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
OrdosStarportTypes =
{
EarlyGame = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport" },
LateGame = { "trike.starport", "quad.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport", "missile_tank.starport" }
}
ActivateAI = function()
Defending[OrdosMain] = {}
Defending[OrdosSmall] = {}
AttackDelay[OrdosMain] = 14000 * DifficultyModifier[Difficulty]
AttackDelay[OrdosSmall] = 12000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[OrdosMain] = 7000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[OrdosSmall] = 7000 * DifficultyModifier[Difficulty]
HarvesterCount[OrdosMain] = 4
HarvesterCount[OrdosSmall] = 2
Trigger.OnAllKilledOrCaptured(ProductionBuildingsOrdosSmallBase, function()
TimeBetweenAttacks[OrdosMain] = 0
end)
PatrolPoints[OrdosMain] = {OrdosPatrol3.Location, OrdosPatrol4.Location, OrdosPatrol2.Location }
PatrolPoints[OrdosSmall] = {OrdosPatrol1.Location, OrdosPatrol2.Location, OrdosRally1.Location}
DefencePerimeter[OrdosMain] = GetCellsInRectangle(CPos.New(50,3), CPos.New(94,21))
DefencePerimeter[OrdosSmall] = GetCellsInRectangle(CPos.New(3,3), CPos.New(25,20))
IdlingUnits[OrdosMain] = Utils.Concat(Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[1], InitialOrdosPaths[1]), Reinforcements.Reinforce(OrdosMain, InitialOrdosReinforcements[2], InitialOrdosPaths[2]))
IdlingUnits[OrdosSmall] = Reinforcements.Reinforce(OrdosSmall, InitialOrdosReinforcements[1], InitialOrdosPaths[3])
DefendAndRepairBase(OrdosMain, OrdosMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(OrdosSmall, OrdosSmallBase, 0.75, AttackGroupSize[Difficulty])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
end
local infantryToBuild = function() return { Utils.Random(OrdosInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
local vehiclesToBuild = function() return { Utils.Random(OrdosVehicleTypes) } end
local tanksToBuild = function() return { Utils.Random(OrdosTankTypes) } end
local unitsToBuy = function() return { Utils.Random(OrdosStarportTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
local unitsToBuy = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(OrdosStarportTypes["EarlyGame"]) }
else
return { Utils.Random(OrdosStarportTypes["LateGame"]) }
end
end
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosMain, OLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize)
local attackThresholdSize = {}
attackThresholdSize[OrdosMain] = AttackGroupSize[Difficulty] * 3
attackThresholdSize[OrdosSmall] = AttackGroupSize[Difficulty] * 2
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["OrdosMain"][Difficulty], function()
ProduceUnits(OrdosMain, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
ProduceUnits(OrdosMain, OStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
end)
Trigger.AfterDelay(InitialProductionDelay["OrdosSmall"][Difficulty], function()
ProduceUnits(OrdosSmall, OBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
ProduceUnits(OrdosSmall, OLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
end)
local crusherTypes = { "combat_tank_o", "combat_tank_o.starport" }
local crusherFactories = { OHeavyFactory, OStarport }
ActivateCrushLogic()
if Difficulty == "easy" then
OrdosMain.GrantCondition("base-rebuilder")
OrdosMain.GrantCondition("base-rebuilder2")
end
if Difficulty == "hard" then
OrdosMain.GrantCondition("defense-rebuilder")
OrdosMain.GrantCondition("base-rebuilder2")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuild
}
Trigger.OnBuildingPlaced(OrdosMain, function(p, building)
table.insert(OrdosMainBase, building)
DefendAndRepairBase(OrdosMain, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(OrdosMain, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[OrdosMain])
end)
Trigger.OnBuildingPlaced(OrdosSmall, function(p, building)
table.insert(OrdosSmallBase, building)
DefendAndRepairBase(OrdosSmall, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(OrdosSmall, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[OrdosSmall])
end)
end

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 }
OrdosSmallBase = { OConYard2, ORefinery3, OBarracks2, OLightFactory2, OGunt6, OGunt7, ORocket3, ORocket4, OPower11, OPower12, OPower13, OPower14, OSilo7, OSilo8, OSilo9 }
ProductionBuildingsOrdosSmallBase = { OConyard2, ORefinery3, OBarracks2, OLightFactory2 }
SmugglerTriggerZone = Utils.Concat(
GetCellsInRectangle(CPos.New(48,24), CPos.New(53,29)),
GetCellsInRectangle(CPos.New(43,30), CPos.New(53,35))
)
SmugglerPatrol = {Smuggler1, Smuggler2, Smuggler3, Smuggler4, Smuggler5, Smuggler6 }
OrdosReinforcements =
{
easy =
@@ -118,6 +128,53 @@ SendStarportReinforcements = function()
end)
end
Message = {}
StopFollowing = {}
Trigger.OnEnteredFootprint(SmugglerTriggerZone, function(a, id)
if SmugglerNeutral.HasNoRequiredUnits() then
Trigger.RemoveFootprintTrigger(id)
end
if a.Owner == Harkonnen and not Message[Harkonnen] then
Media.DisplayMessage(UserInterface.GetFluentMessage("smuggler-warning-harkonnen"), "Smugglers", HSLColor.FromHex("7B2910"))
Message[Harkonnen] = true
end
if a.Owner == OrdosMain or a.Owner == OrdosSmall and not Message[OrdosMain] then
Media.DisplayMessage(UserInterface.GetFluentMessage("smuggler-warning-ordos"), "Smugglers", HSLColor.FromHex("7B2910"))
Message[OrdosMain] = true
end
if a.Owner ~= SmugglerNeutral then
Utils.Do(SmugglerPatrol, function(u)
if not u.IsDead then
StopFollowing[u] = false
FollowIntruder(u,a)
end
end)
end
end)
Trigger.OnExitedFootprint(SmugglerTriggerZone, function(a, id)
if SmugglerNeutral.HasNoRequiredUnits() then
Trigger.RemoveFootprintTrigger(id)
end
if a.Owner ~= SmugglerNeutral then
Utils.Do(SmugglerPatrol, function(u)
if not u.IsDead then StopFollowing[u] = true end
end)
end
end)
FollowIntruder = function(unit, intruder)
if intruder.IsDead or unit.IsDead then return end
if StopFollowing[unit] == true then unit.Stop() return end
unit.Stop()
unit.AttackMove(intruder.Location,1)
Trigger.AfterDelay(100, function() FollowIntruder(unit, intruder) end)
end
ChangeOwner = function(old_owner, new_owner)
local units = old_owner.GetActors()
Utils.Do(units, function(unit)
@@ -130,20 +187,47 @@ end
CheckSmugglerEnemies = function()
Utils.Do(SmugglerUnits, function(unit)
Trigger.OnDamaged(unit, function(self, attacker)
if Utils.Any(IgnoreDamageFromTypes, function(a) return a == attacker.Type end) then
return
end
if not self.HasProperty("Health") then return end
if self.MaxHealth * 0.9 < self.Health then return end
if unit.Owner == SmugglerNeutral and attacker.Owner == Harkonnen then
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
-- Ensure that harvesters that was on a carryall switched sides.
Trigger.AfterDelay(DateTime.Seconds(15), function()
ChangeOwner(SmugglerNeutral, SmugglerHarkonnen)
end)
end
if unit.Owner == SmugglerOrdos and attacker.Owner == Harkonnen then
ChangeOwner(SmugglerOrdos, SmugglerBoth)
-- Ensure that harvesters that was on a carryall switched sides.
Trigger.AfterDelay(DateTime.Seconds(15), function()
ChangeOwner(SmugglerOrdos, SmugglerBoth)
end)
end
if unit.Owner == SmugglerNeutral and (attacker.Owner == OrdosMain or attacker.Owner == OrdosSmall) then
ChangeOwner(SmugglerNeutral, SmugglerOrdos)
-- Ensure that harvesters that was on a carryall switched sides.
Trigger.AfterDelay(DateTime.Seconds(15), function()
ChangeOwner(SmugglerNeutral, SmugglerOrdos)
end)
end
if unit.Owner == SmugglerHarkonnen and (attacker.Owner == OrdosMain or attacker.Owner == OrdosSmall) then
ChangeOwner(SmugglerHarkonnen, SmugglerBoth)
-- Ensure that harvesters that was on a carryall switched sides.
Trigger.AfterDelay(DateTime.Seconds(15), function()
ChangeOwner(SmugglerHarkonnen, SmugglerBoth)
end)
end
if attacker.Owner == Harkonnen and not MessageCheck then
@@ -155,6 +239,13 @@ CheckSmugglerEnemies = function()
end)
end
EmergencyBehaviour = function(player, target)
if player ~= OrdosSmall then return end
if #IdlingUnits[OrdosMain] > 10 and Utils.Any(OrdosSmallBase, function(a) return not a.IsDead end) then
CheckArea(OrdosMain, target, 10)
end
end
Tick = function()
if Harkonnen.HasNoRequiredUnits() then
OrdosMain.MarkCompletedObjective(KillHarkonnen1)
@@ -231,8 +322,8 @@ WorldLoaded = function()
unit.AttackMove(OrdosAttackLocation)
IdleHunt(unit)
end
SendCarryallReinforcements(OrdosMain, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
SendCarryallReinforcements(OrdosMain, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
SendStarportReinforcements()
Actor.Create("upgrade.barracks", true, { Owner = OrdosMain })

Binary file not shown.

View File

@@ -394,9 +394,11 @@ Actors:
OGunt6: medium_gun_turret
Location: 9,17
Owner: Ordos Small Base
TurretFacing: 512
OGunt7: medium_gun_turret
Location: 14,17
Owner: Ordos Small Base
TurretFacing: 512
Actor102: wall
Location: 15,17
Owner: Ordos Small Base
@@ -463,12 +465,6 @@ Actors:
SSilo3: silo
Location: 51,26
Owner: Smugglers - Neutral
Actor124: trooper
Location: 51,28
Owner: Smugglers - Neutral
Actor125: light_inf
Location: 53,28
Owner: Smugglers - Neutral
Actor126: wormspawner
Location: 76,28
Owner: Creeps
@@ -487,24 +483,12 @@ Actors:
SPower2: wind_trap
Location: 50,30
Owner: Smugglers - Neutral
Actor132: light_inf
Location: 53,30
Owner: Smugglers - Neutral
SRefinery: refinery
Location: 43,33
Owner: Smugglers - Neutral
Actor134: light_inf
Location: 50,33
Owner: Smugglers - Neutral
Actor135: harvester
Location: 46,35
Owner: Smugglers - Neutral
Actor136: light_inf
Location: 48,35
Owner: Smugglers - Neutral
Actor137: light_inf
Location: 52,35
Owner: Smugglers - Neutral
Actor138: light_inf
Location: 42,36
Owner: Smugglers - Neutral
@@ -652,6 +636,42 @@ Actors:
OrdosStarportExit: waypoint
Owner: Neutral
Location: 2,9
Smuggler1: trooper
Location: 51,28
Owner: Smugglers - Neutral
Smuggler2: light_inf
Location: 53,28
Owner: Smugglers - Neutral
Smuggler3: light_inf
Location: 53,30
Owner: Smugglers - Neutral
Smuggler4: light_inf
Location: 50,33
Owner: Smugglers - Neutral
Smuggler5: light_inf
Location: 48,35
Owner: Smugglers - Neutral
Smuggler6: light_inf
Location: 52,35
Owner: Smugglers - Neutral
OrdosPatrol1: waypoint
Owner: Neutral
Location: 26,49
OrdosPatrol2: waypoint
Owner: Neutral
Location: 36,33
OrdosPatrol3: waypoint
Owner: Neutral
Location: 60,29
OrdosPatrol4: waypoint
Owner: Neutral
Location: 82,43
Actor4: crate_reveal
Owner: Neutral
Location: 13,27
Actor5: crate
Owner: Neutral
Location: 82,48
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,136 @@
Player:
PlayerResources:
DefaultCash: 5000
ExternalCondition@AIMain:
Condition: base-rebuilder
ExternalCondition@AISmall:
Condition: base-rebuilder2
ExternalCondition@AIMainWithDefense:
Condition: defense-rebuilder
ExternalCondition@AISmallWithDefense:
Condition: defense-rebuilder2
BaseBuilderBotModule@MainBase:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
wind_trap: 9
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
BaseBuilderBotModule@MainBaseWithDefence:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
PlaceDefenseTowardsEnemyChance: 50
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
wind_trap: 7
silo: 1
medium_gun_turret: 5
large_gun_turret: 2
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
medium_gun_turret: 1
large_gun_turret: 1
BaseBuilderBotModule@SmallBase:
RequiresCondition: base-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
wind_trap: 4
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
BaseBuilderBotModule@SmallBasewithDefence:
RequiresCondition: defense-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret
SellRefineryInterval: -1
PlaceDefenseTowardsEnemyChance: 50
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
wind_trap: 4
silo: 1
medium_gun_turret: 2
large_gun_turret: 2
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
medium_gun_turret: 1
large_gun_turret: 2
World:
LuaScript:

View File

@@ -6,6 +6,30 @@
the License, or (at your option) any later version. For more
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(10)
InitialProductionDelay = {
AtreidesMain =
{
easy = DateTime.Seconds(400),
normal = DateTime.Seconds(300),
hard = DateTime.Seconds(150)
},
AtreidesSmall =
{
easy = DateTime.Seconds(300),
normal = DateTime.Seconds(200),
hard = DateTime.Seconds(100)
},
Corrino =
{
easy = DateTime.Seconds(100),
normal = DateTime.Seconds(120),
hard = DateTime.Seconds(60)
}
}
AttackGroupSize =
{
@@ -14,29 +38,60 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
EarlyProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
hard = { DateTime.Seconds(1), DateTime.Seconds(3) }
easy = { DateTime.Seconds(11), DateTime.Seconds(15) },
normal = { DateTime.Seconds(10), DateTime.Seconds(12) },
hard = { DateTime.Seconds(8), DateTime.Seconds(10) }
}
InitialProductionDelay =
LateProductionDelays =
{
easy = DateTime.Seconds(30),
normal = DateTime.Seconds(15),
hard = 0
easy = { DateTime.Seconds(6), DateTime.Seconds(10) },
normal = { DateTime.Seconds(4), DateTime.Seconds(6) },
hard = { DateTime.Seconds(2), DateTime.Seconds(4) }
}
AtreidesInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
AtreidesVehicleTypes = { "trike", "trike", "quad" }
AtreidesMainTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
AtreidesMainTankTypes =
{
EarlyGame = { "combat_tank_a", "combat_tank_a" },
LateGame = { "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
}
AtreidesSmallTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank" }
AtreidesStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
CorrinoInfantryTypes = { "light_inf", "trooper", "sardaukar" }
ActivateAI = function()
Defending[AtreidesMain] = {}
Defending[AtreidesSmall] = {}
Defending[Corrino] = {}
-- this is also first attack timing
AttackDelay[AtreidesMain] = 10000
AttackDelay[AtreidesSmall] = 8000
AttackDelay[Corrino] = 7000
TimeBetweenAttacks[AtreidesMain] = 12000
TimeBetweenAttacks[AtreidesSmall] = 5000
TimeBetweenAttacks[Corrino] = 11000
HarvesterCount[AtreidesMain] = 2
HarvesterCount[AtreidesSmall] = 2
Trigger.OnAllKilledOrCaptured(AtreidesSmallBase, function()
TimeBetweenAttacks[AtreidesMain] = 0
end)
PatrolPoints[AtreidesMain] = {AtreidesPoint1.Location, AtreidesPoint2.Location, AtreidesPoint3.Location }
PatrolPoints[AtreidesSmall] = {AtreidesPoint4.Location, AtreidesPoint5.Location, AtreidesPoint6.Location }
DefencePerimeter[AtreidesMain] = Utils.Concat( GetCellsInRectangle(CPos.New(73,9), CPos.New(88,26)), GetCellsInRectangle(CPos.New(65,44), CPos.New(82,56)))
DefencePerimeter[AtreidesSmall] = GetCellsInRectangle(CPos.New(5,18), CPos.New(16,32))
DefencePerimeter[Corrino] = GetCellsInRectangle(CPos.New(89,27), CPos.New(95,35))
IdlingUnits[AtreidesMain] = Utils.Concat(Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[Difficulty][1], InitialAtreidesPaths[1]), Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[Difficulty][2], InitialAtreidesPaths[2]))
IdlingUnits[AtreidesSmall] = Reinforcements.Reinforce(AtreidesSmall, InitialAtreidesReinforcements[Difficulty][1], InitialAtreidesPaths[3])
IdlingUnits[Corrino] = Reinforcements.Reinforce(Corrino, InitialCorrinoReinforcements, InitialCorrinoPath)
@@ -45,23 +100,77 @@ ActivateAI = function()
DefendAndRepairBase(AtreidesSmall, AtreidesSmallBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(Corrino, CorrinoBase, 0.75, AttackGroupSize[Difficulty])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
if EarlyGameStage >= DateTime.GameTime then
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
else
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
end
end
local infantryToBuildAtreides = function() return { Utils.Random(AtreidesInfantryTypes) } end
local infantryToBuildCorrino = function() return { Utils.Random(CorrinoInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local tanksToBuildMain = function() return { Utils.Random(AtreidesMainTankTypes) } end
local vehiclesToBuild = function() return { Utils.Random(AtreidesVehicleTypes) } end
local tanksToBuildMain = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(AtreidesMainTankTypes["EarlyGame"]) }
else
return { Utils.Random(AtreidesMainTankTypes["LateGame"]) }
end
end
local tanksToBuildSmall = function() return { Utils.Random(AtreidesSmallTankTypes) } end
local unitsToBuy = function() return { Utils.Random(AtreidesStarportTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
local attackThresholdSize = {}
attackThresholdSize[AtreidesMain] = AttackGroupSize[Difficulty] * 3
attackThresholdSize[AtreidesSmall] = AttackGroupSize[Difficulty] * 2
Trigger.AfterDelay(InitialProductionDelay[Difficulty], function()
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildMain, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, ABarracks, delay, infantryToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildSmall, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Corrino, CBarracks, delay, infantryToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function()
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildMain, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuy, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
end)
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall"][Difficulty], function()
ProduceUnits(AtreidesSmall, ABarracks, delay, infantryToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesSmall])
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildSmall, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesSmall])
end)
Trigger.AfterDelay(InitialProductionDelay["Corrino"][Difficulty], function()
ProduceUnits(Corrino, CBarracks, delay, infantryToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSize[AtreidesSmall])
end)
if Difficulty == "normal" then
AtreidesMain.GrantCondition("base-rebuilder")
end
if Difficulty == "hard" then
AtreidesMain.GrantCondition("defense-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuildAtreides,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuildMain
}
Trigger.OnBuildingPlaced(AtreidesMain, function(p, building)
table.insert(AtreidesMainBase, building)
DefendAndRepairBase(AtreidesMain, {building}, 0.5, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(AtreidesMain, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[AtreidesMain])
end)
Trigger.OnBuildingPlaced(AtreidesSmall, function(p, building)
table.insert(AtreidesSmallBase, building)
DefendAndRepairBase(AtreidesSmall, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(AtreidesSmall, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize[AtreidesSmall])
end)
ActivateCrushLogic()
end

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 }
AtreidesSmallBase = { AOutpost2, ARefinery3, ABarracks, AHeavyFactory2, AGunt7, AGunt8, APower23, APower24, APower25, APower26, ASilo4, ASilo5, ASilo6, ASilo7 }
CorrinoBase = { CBarracks, COutpost, CPower1, CPower2, CPower3, CRock1, CRock2 }
EarlyGameStage = DateTime.Minutes(7)
AtreidesReinforcements =
{
easy = { "sonic_tank" },
@@ -41,16 +45,16 @@ CorrinoReinforcements =
EnemyAttackDelay =
{
easy = DateTime.Minutes(3) + DateTime.Seconds(30),
normal = DateTime.Minutes(2) + DateTime.Seconds(30),
hard = DateTime.Minutes(1) + DateTime.Seconds(30)
easy = 7000 ,
normal = 6500 ,
hard = 6000
}
CorrinoInitialAttackDelay =
{
easy = DateTime.Seconds(45),
normal = DateTime.Seconds(30),
hard = DateTime.Seconds(15)
easy = DateTime.Minutes(4) ,
normal = DateTime.Minutes(3) ,
hard = DateTime.Minutes(2)
}
InitialAtreidesReinforcements =
@@ -112,8 +116,8 @@ HarkonnenReinforcements =
hard =
{
{ "trooper", "trooper", "light_inf", "light_inf", "light_inf" },
{ "quad", "trike", "trike", "combat_tank_h", "combat_tank_h" }
{ "trooper", "trooper", "light_inf", "light_inf", "light_inf", "light_inf" },
{ "quad", "trike", "trike", "combat_tank_h", "combat_tank_h", "siege_tank" }
},
}
@@ -147,8 +151,32 @@ SendEnemyReinforcements = function(player, delay, path, unitTypes, customConditi
end)
end
SendAirStrike = function()
if HiTechIsDead then
AirStrikeTimer = 7500
AirStrikeChargeTime = 7500
AirstrikeLogic = function(airstrikeProvider)
if airstrikeProvider.IsDead then
return
end
if DateTime.GameTime <= AirStrikeTimer then
Trigger.AfterDelay(AirStrikeTimer - DateTime.GameTime + 1, function()
AirstrikeLogic(airstrikeProvider)
end)
return
end
-- randomly choose if wait again or strike. During waiting Airstrike can still be used by DefensiveAirStrike
if Utils.RandomInteger(1, 100) < 30 then
Trigger.AfterDelay(1000, function() AirstrikeLogic(airstrikeProvider)end)
else
AirStrikeVSBuilding(airstrikeProvider)
Trigger.AfterDelay(7500, function() AirstrikeLogic(airstrikeProvider) end)
IsAirstrikeReady = false
end
end
AirStrikeVSBuilding = function(airstrikeProvider)
if airstrikeProvider.IsDead or DateTime.GameTime < AirStrikeTimer then
return
end
@@ -163,10 +191,32 @@ SendAirStrike = function()
end)
if #targets > 0 then
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition)
airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end
end
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
DefensiveAirStrike = function(airstrikeProvider, possibleTargets)
if airstrikeProvider.IsDead or DateTime.GameTime <= AirStrikeTimer then return end
local bestValue = {}
local bestIndex = 1
for i = 1, #possibleTargets, 1 do
local ActorsInCircle = Map.ActorsInCircle(possibleTargets[i].CenterPosition, WDist.FromCells(4), function(a)
return
a.Owner == Harkonnen
and not a.IsDead
and a.HasProperty("Attack")
end)
bestValue[i] = 0
Utils.Do(ActorsInCircle, function(a)
bestValue[i] = bestValue[i] + Actor.Cost(a.Type)
end)
if bestValue[i] > bestValue[bestIndex] then
bestIndex = i
end
end
airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end
Tick = function()
@@ -195,12 +245,12 @@ Tick = function()
HiTechIsDead = true
end
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[OrdosMain] then
local units = OrdosMain.GetActorsByType("harvester")
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
local units = AtreidesMain.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[OrdosMain] = false
ProtectHarvester(units[1], OrdosMain, AttackGroupSize[Difficulty])
LastHarvesterEaten[AtreidesMain] = false
ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
end
end
@@ -212,15 +262,40 @@ Tick = function()
ProtectHarvester(units[1], OrdosSmall, AttackGroupSize[Difficulty])
end
end
if IdlingUnits[AtreidesMain] == nil then return end
end
EmergencyBehaviour = function(player, target)
if HiTechIsDead or not IsAirstrikeReady or player == Corrino then return end
local targets = {}
if player == AtreidesMain then
targets = Map.ActorsInBox(Map.CenterOfCell(CPos.New(73,9)), Map.CenterOfCell(CPos.New(88,26)))
else
targets = Map.ActorsInBox(Map.CenterOfCell(CPos.New(5,18)), Map.CenterOfCell(CPos.New(16,32)))
end
targets = Utils.Where(targets, function(a)
return a.Owner == Harkonnen
and not a.IsDead
and a.HasProperty("Attack")
end)
if targets[1] == nil then return end
DefensiveAirStrike(AHiTechFactory, targets)
end
WorldLoaded = function()
AtreidesMain = Player.GetPlayer("Atreides Main Base")
AtreidesSmall = Player.GetPlayer("Atreides Small Base")
Corrino = Player.GetPlayer("Corrino")
AtreidesMain.Cash = 5000
AtreidesSmall.Cash = 5000
Corrino.Cash = 5000
Harkonnen = Player.GetPlayer("Harkonnen")
InitObjectives(Harkonnen)
CaptureAtreidesConYard = AddPrimaryObjective(Harkonnen, "capture-atreides-construction-yard-south")
KillAtreides = AddPrimaryObjective(Harkonnen, "destroy-atreides")
KillCorrino = AddPrimaryObjective(Harkonnen, "destroy-corrino")
@@ -232,8 +307,7 @@ WorldLoaded = function()
Camera.Position = HEngineer.CenterPosition
AtreidesAttackLocation = AConYard2.Location
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
Trigger.AfterDelay(EarlyGameStage,function() AirstrikeLogic(AHiTechFactory) end)
Trigger.OnCapture(AConYard2, function()
Harkonnen.MarkCompletedObjective(CaptureAtreidesConYard)
@@ -257,7 +331,9 @@ WorldLoaded = function()
unit.AttackMove(AtreidesAttackLocation)
IdleHunt(unit)
end
SendEnemyReinforcements(AtreidesMain, EnemyAttackDelay[Difficulty], AtreidesPath, AtreidesReinforcements[Difficulty], atreidesWaveCondition, huntFunction)
Trigger.AfterDelay(CorrinoInitialAttackDelay[Difficulty], function()
SendEnemyReinforcements(Corrino, EnemyAttackDelay[Difficulty], CorrinoPaths[1], CorrinoReinforcements[Difficulty][1], corrinoWaveCondition, huntFunction)
SendEnemyReinforcements(Corrino, EnemyAttackDelay[Difficulty], CorrinoPaths[2], CorrinoReinforcements[Difficulty][2], corrinoWaveCondition, huntFunction)
@@ -273,4 +349,14 @@ WorldLoaded = function()
SendHarkonnenReinforcements(1)
SendHarkonnenReinforcements(2)
Trigger.AfterDelay(7000, function()
SendHarkonnenReinforcements(1)
end)
Trigger.OnRemovedFromWorld(Crate1, function()
VisionPoint.GrantCondition("activate", 100)
Media.PlaySound("MULTI1.WAV")
Camera.Position = VisionPoint.CenterPosition
end)
end

Binary file not shown.

View File

@@ -298,6 +298,7 @@ Actors:
AGunt1: medium_gun_turret
Location: 80,27
Owner: Atreides Main Base
TurretFacing: 512
Actor77: wall
Location: 81,27
Owner: Atreides Main Base
@@ -769,6 +770,33 @@ Actors:
AtreidesEntry2: waypoint
Owner: Neutral
Location: 2,27
AtreidesPoint2: waypoint
Owner: Neutral
Location: 72,13
AtreidesPoint3: waypoint
Owner: Neutral
Location: 55,53
AtreidesPoint4: waypoint
Owner: Neutral
Location: 24,33
AtreidesPoint5: waypoint
Owner: Neutral
Location: 28,55
AtreidesPoint6: waypoint
Owner: Neutral
Location: 33,9
VisionPoint: vision_provider
Owner: Harkonnen
Location: 64,64
Crate1: crate_script
Owner: Harkonnen
Location: 57,62
AtreidesPoint1: waypoint
Owner: Neutral
Location: 54,6
Actor7: crate
Owner: Neutral
Location: 49,9
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,79 @@
Player:
PlayerResources:
DefaultCash: 6000
DefaultCash: 7000
ExternalCondition@AIMain:
Condition: base-rebuilder
ExternalCondition@AIMainWithDefense:
Condition: defense-rebuilder
BaseBuilderBotModule@MainBase:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
starport: 1
wind_trap: 7
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
starport: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
BaseBuilderBotModule@MainBaseWithDefence:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
PlaceDefenseTowardsEnemyChance: 50
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
starport: 1
wind_trap: 7
silo: 1
medium_gun_turret: 4
large_gun_turret: 4
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
starport: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
medium_gun_turret: 1
large_gun_turret: 1
World:
LuaScript:

View File

@@ -7,6 +7,31 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(7)
InitialProductionDelay = {
Ordos =
{
easy = DateTime.Seconds(150),
normal = DateTime.Seconds(120),
hard = DateTime.Seconds(60)
},
AtreidesEnemy =
{
easy = DateTime.Seconds(180),
normal = DateTime.Seconds(120),
hard = DateTime.Seconds(60)
},
MercenaryEnemy =
{
easy = DateTime.Seconds(160),
normal = DateTime.Seconds(80),
hard = DateTime.Seconds(30)
}
}
AttackGroupSize =
{
easy = 6,
@@ -14,7 +39,14 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
EarlyProductionDelays =
{
easy = { DateTime.Seconds(10), DateTime.Seconds(13) },
normal = { DateTime.Seconds(6), DateTime.Seconds(8) },
hard = { DateTime.Seconds(3), DateTime.Seconds(5) }
}
LateProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -24,16 +56,61 @@ AttackDelays =
EnemyInfantryTypes = { "light_inf", "light_inf", "trooper", "trooper", "trooper" }
OrdosVehicleTypes = { "raider", "raider", "quad" }
OrdosTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank", "deviator" }
OrdosStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
OrdosTankTypes =
{
EarlyGame = { "combat_tank_o", "combat_tank_o", "siege_tank"},
LateGame = { "combat_tank_o", "combat_tank_o", "siege_tank", "deviator" }
}
OrdosStarportTypes =
{
EarlyGame = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport" },
LateGame = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_o.starport", "combat_tank_o.starport", "siege_tank.starport", "missile_tank.starport" }
}
AtreidesVehicleTypes = { "trike", "trike", "quad" }
AtreidesTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank" }
AtreidesStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
AtreidesTankTypes =
{
EarlyGame = { "combat_tank_a" },
LateGame = { "combat_tank_a", "combat_tank_a", "siege_tank" }
}
AtreidesStarportTypes =
{
EarlyGame ={ "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport" },
LateGame ={ "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
}
MercenaryTankTypes = { "combat_tank_o", "combat_tank_o", "siege_tank" }
ActivateAI = function()
Defending[Ordos] = {}
Defending[AtreidesEnemy] = {}
Defending[AtreidesNeutral] = {}
Defending[MercenaryEnemy] = {}
Defending[MercenaryAlly] = {}
-- this is also first attack timing
AttackDelay[Ordos] = 16000
AttackDelay[AtreidesEnemy] = 10000
AttackDelay[MercenaryEnemy] = 7000
TimeBetweenAttacks[Ordos] = 8000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[AtreidesEnemy] = 7000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[MercenaryEnemy] = 7000 * DifficultyModifier[Difficulty]
HarvesterCount[Ordos] = 4
HarvesterCount[AtreidesEnemy] = 4
HarvesterCount[AtreidesNeutral] = 0
HarvesterCount[MercenaryEnemy] = 0
HarvesterCount[MercenaryAlly] = 0
PatrolPoints[Ordos] = {OrdosPatrolPoint1.Location, OrdosPatrolPoint2.Location, OrdosPatrolPoint3.Location, OrdosPatrolPoint4.Location }
PatrolPoints[AtreidesEnemy] = {AtreidesPatrolPoint1.Location, AtreidesPatrolPoint2.Location, OrdosPatrolPoint3.Location }
DefencePerimeter[Ordos] = GetCellsInRectangle(CPos.New(39,36), CPos.New(71,54))
DefencePerimeter[AtreidesEnemy] = Utils.Concat(GetCellsInRectangle(CPos.New(3,3), CPos.New(17,20)), GetCellsInRectangle(CPos.New(18,3), CPos.New(31,9)))
DefencePerimeter[MercenaryEnemy] = GetCellsInRectangle(CPos.New(29,64), CPos.New(40,71))
DefencePerimeter[MercenaryAlly] = DefencePerimeter[MercenaryEnemy]
DefencePerimeter[AtreidesNeutral] = DefencePerimeter[AtreidesEnemy]
IdlingUnits[Ordos] = Utils.Concat(Reinforcements.Reinforce(Ordos, InitialOrdosReinforcements[1], InitialOrdosPaths[1]), Reinforcements.Reinforce(Ordos, InitialOrdosReinforcements[2], InitialOrdosPaths[2]))
IdlingUnits[AtreidesEnemy] = Reinforcements.Reinforce(AtreidesEnemy, InitialAtreidesReinforcements, InitialAtreidesPath)
IdlingUnits[AtreidesNeutral] = { }
@@ -44,26 +121,112 @@ ActivateAI = function()
DefendAndRepairBase(AtreidesEnemy, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(MercenaryEnemy, MercenaryBase, 0.75, AttackGroupSize[Difficulty])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
if EarlyGameStage >= DateTime.GameTime then
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
else
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
end
end
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local vehilcesToBuildOrdos = function() return { Utils.Random(OrdosVehicleTypes) } end
local vehilcesToBuildAtreides = function() return { Utils.Random(AtreidesVehicleTypes) } end
local tanksToBuildOrdos = function() return { Utils.Random(OrdosTankTypes) } end
local tanksToBuildAtreides = function() return { Utils.Random(AtreidesTankTypes) } end
local vehiclesToBuildOrdos = function() return { Utils.Random(OrdosVehicleTypes) } end
local vehiclesToBuildAtreides = function() return { Utils.Random(AtreidesVehicleTypes) } end
local tanksToBuildOrdos = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(OrdosTankTypes["EarlyGame"]) }
else
return { Utils.Random(OrdosTankTypes["LateGame"]) }
end
end
local tanksToBuildAtreides = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(AtreidesTankTypes["EarlyGame"]) }
else
return { Utils.Random(AtreidesTankTypes["LateGame"]) }
end
end
local tanksToBuildMercenary = function() return { Utils.Random(MercenaryTankTypes) } end
local unitsToBuyOrdos = function() return { Utils.Random(OrdosStarportTypes) } end
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end
local unitsToBuyOrdos = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(OrdosStarportTypes["EarlyGame"]) }
else
return { Utils.Random(OrdosStarportTypes["LateGame"]) }
end
end
local unitsToBuyAtreides = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(AtreidesStarportTypes["EarlyGame"]) }
else
return { Utils.Random(AtreidesStarportTypes["LateGame"]) }
end
end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(Ordos, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OLightFactory, delay, vehilcesToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OHeavyFactory, delay, tanksToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OStarport, delay, unitsToBuyOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["Ordos"][Difficulty], function ()
ProduceUnits(Ordos, OBarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OLightFactory, delay, vehiclesToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OHeavyFactory, delay, tanksToBuildOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Ordos, OStarport, delay, unitsToBuyOrdos, AttackGroupSize[Difficulty], attackThresholdSize)
end)
ProduceUnits(AtreidesEnemy, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesEnemy, ALightFactory, delay, vehilcesToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesEnemy, AHeavyFactory, delay, tanksToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesEnemy, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesEnemy"][Difficulty], function ()
ProduceUnits(AtreidesEnemy, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesEnemy, ALightFactory, delay, vehiclesToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesEnemy, AHeavyFactory, delay, tanksToBuildAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesEnemy, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
end)
ProduceUnits(MercenaryEnemy, MHeavyFactory, delay, tanksToBuildMercenary, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesEnemy"][Difficulty], function ()
ProduceUnits(MercenaryEnemy, MHeavyFactory, delay, tanksToBuildMercenary, AttackGroupSize[Difficulty], attackThresholdSize)
end)
ActivateCrushLogic()
if Difficulty == "normal" then
Ordos.GrantCondition("base-rebuilder")
AtreidesEnemy.GrantCondition("base-rebuilder2")
end
if Difficulty == "hard" then
Ordos.GrantCondition("defense-rebuilder")
AtreidesEnemy.GrantCondition("defense-rebuilder2")
end
local productionTypesAtreidis =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuildAtreides,
heavy_factory = tanksToBuildAtreides
}
local productionTypesOrdos =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuildOrdos,
heavy_factory = tanksToBuildOrdos
}
Trigger.OnBuildingPlaced(Ordos, function(p, building)
table.insert(OrdosBase, building)
DefendAndRepairBase(Ordos, {building}, 0.5, AttackGroupSize[Difficulty] )
if productionTypesOrdos[building.Type] == nil then return end
ProduceUnits(Ordos, building, delay, productionTypesOrdos[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
Trigger.OnBuildingPlaced(AtreidesEnemy, function(p, building)
table.insert(AtreidesBase, building)
DefendAndRepairBase(AtreidesEnemy, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypesAtreidis[building.Type] == nil then return end
ProduceUnits(AtreidesEnemy, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

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 }
AtreidesBase = { AConYard, AOutpost, ARefinery1, ARefinery2, AHeavyFactory, ALightFactory, AHiTechFactory, ARepair, AStarport, AGunt1, AGunt2, ARock1, ARock2, APower1, APower2, APower3, APower4, APower5, APower6, APower7, APower8, APower9 }
AtreidesBase = { AConYard,ABarracks1, ABarracks2, AOutpost, ARefinery1, ARefinery2, AHeavyFactory, ALightFactory, AHiTechFactory, ARepair, AStarport, AGunt1, AGunt2, ARock1, ARock2, APower1, APower2, APower3, APower4, APower5, APower6, APower7, APower8, APower9 }
MercenaryBase = { MHeavyFactory, MStarport, MGunt, MPower1, MPower2 }
OrdosReinforcements =
@@ -56,7 +58,7 @@ OrdosAttackDelay =
hard = DateTime.Minutes(1)
}
MercenaryStarportDelay = DateTime.Minutes(1) + DateTime.Seconds(20)
MercenaryStarportDelay = 4970
OrdosAttackWaves =
{
@@ -92,7 +94,9 @@ InitialOrdosPaths =
SaboteurPaths =
{
{ SaboteurWaypoint1.Location, SaboteurWaypoint2.Location, SaboteurWaypoint3.Location },
{ SaboteurWaypoint4.Location, SaboteurWaypoint5.Location, SaboteurWaypoint6.Location }
{ SaboteurWaypoint4.Location, SaboteurWaypoint5.Location, SaboteurWaypoint6.Location },
{ SaboteurWaypoint1.Location, OrdosPatrolPoint2.Location, OrdosRally1.Location, SaboteurWaypoint6.Location },
{ OrdosRally4.Location, OrdosPatrolPoint3.Location, OrdosPatrolPoint2.Location}
}
InitialAtreidesPath = { AStarport.Location, AtreidesRally.Location }
@@ -117,14 +121,36 @@ SendStarportReinforcements = function(faction)
end)
end
SendAirStrike = function()
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesEnemy then
AirStrikeTimer = 7500
AirStrikeChargeTime = 7500
AirstrikeLogic = function(airstrikeProvider)
if airstrikeProvider.IsDead then
return
end
if DateTime.GameTime <= AirStrikeTimer then
Trigger.AfterDelay(AirStrikeTimer - DateTime.GameTime + 1, function()
AirstrikeLogic(airstrikeProvider)
end)
return
end
-- randomly choose if wait again or strike. During waiting Airstrike can still be used by DefensiveAirStrike
if Utils.RandomInteger(1, 100) < 30 then
Trigger.AfterDelay(1000, function() AirstrikeLogic(airstrikeProvider)end)
else
AirStrikeVSBuilding(airstrikeProvider)
Trigger.AfterDelay(7500, function() AirstrikeLogic(airstrikeProvider) end)
IsAirstrikeReady = false
end
end
AirStrikeVSBuilding = function(airstrikeProvider)
if airstrikeProvider.IsDead or DateTime.GameTime < AirStrikeTimer then
return
end
local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
return
actor.HasProperty("Sell") and
return actor.HasProperty("Sell") and
actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and
@@ -133,16 +159,40 @@ SendAirStrike = function()
end)
if #targets > 0 then
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition)
airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end
end
DefensiveAirStrike = function(airstrikeProvider, possibleTargets)
if airstrikeProvider.IsDead or DateTime.GameTime <= AirStrikeTimer then return end
local bestValue = {}
local bestIndex = 1
for i = 1, #possibleTargets, 1 do
local ActorsInCircle = Map.ActorsInCircle(possibleTargets[i].CenterPosition, WDist.FromCells(4), function(a)
return
a.Owner == Harkonnen
and not a.IsDead
and a.HasProperty("Attack")
end)
bestValue[i] = 0
Utils.Do(ActorsInCircle, function(a)
bestValue[i] = bestValue[i] + Actor.Cost(a.Type)
end)
if bestValue[i] > bestValue[bestIndex] then
bestIndex = i
end
end
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end
GetSaboteurTargets = function(player)
return Utils.Where(player.GetActors(), function(actor)
return
actor.HasProperty("Sell") and
return actor.HasProperty("Sell") and
actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and
@@ -162,14 +212,54 @@ BuildSaboteur = function()
saboteur.Wait(DateTime.Seconds(5))
local path = Utils.Random(SaboteurPaths)
saboteur.Move(path[1])
saboteur.Move(path[2])
saboteur.Move(path[3])
Utils.Do(path, function(waypoint)
saboteur.Move(waypoint)
end)
SendSaboteur(saboteur)
ScanForBetterTargets(saboteur)
end
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(30), BuildSaboteur)
Trigger.AfterDelay(DateTime.Minutes(5) + DateTime.Seconds(30), BuildSaboteur)
end
DemolishType = { "harvester", "mcv", "siege_tank", "missile_tank", "sonic_tank", "devastator", "deviator", "combat_tank_a", "combat_tank_h", "combat_tank_o"}
ScanForBetterTargets = function(saboteur)
if saboteur.IsDead or not saboteur.IsInWorld then return end
local possibleTargets = Map.ActorsInCircle(saboteur.CenterPosition, WDist.FromCells(6), function(a)
return not saboteur.Owner.IsAlliedWith(a.Owner) and
Utils.Any(DemolishType, function(d) return d == a.Type end)
end)
if possibleTargets[1] == nil then
Trigger.AfterDelay(200, function()
ScanForBetterTargets(saboteur)
end)
return
end
-- filter out targets where infantry is nearby
for index = #possibleTargets, 1, -1 do
local infantryunits = Map.ActorsInCircle(possibleTargets[index].CenterPosition, WDist.New(1536), function(u) return u.Type == "light_inf" or u.Type == "trooper" end)
if infantryunits[1] ~= nil then
table.remove(possibleTargets, index)
end
end
if possibleTargets[1] ~= nil then
saboteur.Stop()
local dfd = Utils.Random(possibleTargets)
saboteur.Demolish(dfd)
saboteur.CallFunc(function()
ScanForBetterTargets(saboteur)
end)
else
Trigger.AfterDelay(200, function()
ScanForBetterTargets(saboteur)
end)
end
end
SendSaboteur = function(saboteur)
@@ -216,6 +306,21 @@ ChangeOwner = function(old_owner, new_owner)
end)
end
EmergencyBehaviour = function(player, target)
HoldProduction[player] = false
if player == Ordos and not AtreidesEnemy.HasNoRequiredUnits() then
if AHiTechFactory.IsDead then return end
local enemyunits = Map.ActorsInCircle(Map.CenterOfCell(target), WDist.FromCells(15), function(a)
return a.Owner == Harkonnen
and not a.IsDead
and a.HasProperty("Attack")
end)
if enemyunits[1] == nil then return end
DefensiveAirStrike(AHiTechFactory, enemyunits)
end
end
Tick = function()
if Harkonnen.HasNoRequiredUnits() then
Ordos.MarkCompletedObjective(KillHarkonnen1)
@@ -239,7 +344,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Ordos] then
local units = Ordos.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[Ordos] = false
ProtectHarvester(units[1], Ordos, AttackGroupSize[Difficulty])
@@ -248,7 +352,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesEnemy] then
local units = AtreidesEnemy.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[AtreidesEnemy] = false
ProtectHarvester(units[1], AtreidesEnemy, AttackGroupSize[Difficulty])
@@ -275,8 +378,8 @@ WorldLoaded = function()
OrdosAttackLocation = HMCV.Location
MercenaryAttackLocation = HMCV.Location
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds(30), BuildSaboteur)
Trigger.AfterDelay(EarlyGameStage, function() AirstrikeLogic(AHiTechFactory) end)
Trigger.AfterDelay(EarlyGameStage, BuildSaboteur)
Trigger.OnCapture(MHeavyFactory, function()
Harkonnen.MarkCompletedObjective(AllyWithMercenaries)
@@ -296,7 +399,7 @@ WorldLoaded = function()
end)
Trigger.OnKilledOrCaptured(OPalace, function()
Media.DisplayMessage(UserInterface.GetFluentMessage("cannot-stand-harkonnen-must-become-neutral"), UserInterface.GetFluentMessage("atreides-commander"))
Media.DisplayMessage(UserInterface.GetFluentMessage("cannot-stand-harkonnen-must-become-neutral"), UserInterface.GetFluentMessage("atreides-commander"), HSLColor.FromHex("5A7394"))
ChangeOwner(AtreidesEnemy, AtreidesNeutral)
DefendAndRepairBase(AtreidesNeutral, AtreidesBase, 0.75, AttackGroupSize[Difficulty])
@@ -328,8 +431,8 @@ WorldLoaded = function()
unit.AttackMove(OrdosAttackLocation)
IdleHunt(unit)
end
SendCarryallReinforcements(Ordos, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
SendCarryallReinforcements(Ordos, 0, OrdosAttackWaves[Difficulty], OrdosAttackDelay[Difficulty], path, OrdosReinforcements[Difficulty], waveCondition, huntFunction)
SendStarportReinforcements(MercenaryEnemy)
Actor.Create("upgrade.barracks", true, { Owner = Ordos })

View File

@@ -643,15 +643,33 @@ Actors:
SaboteurWaypoint4: waypoint
Owner: Neutral
Location: 18,59
SaboteurWaypoint5: waypoint
Owner: Neutral
Location: 31,91
SaboteurWaypoint6: waypoint
Owner: Neutral
Location: 64,91
MercenaryAttackPoint: waypoint
Owner: Neutral
Location: 53,38
OrdosPatrolPoint1: waypoint
Owner: Neutral
Location: 78,45
OrdosPatrolPoint2: waypoint
Owner: Neutral
Location: 55,63
OrdosPatrolPoint3: waypoint
Owner: Neutral
Location: 30,54
OrdosPatrolPoint4: waypoint
Owner: Neutral
Location: 73,21
AtreidesPatrolPoint1: waypoint
Owner: Neutral
Location: 14,65
AtreidesPatrolPoint2: waypoint
Owner: Neutral
Location: 48,10
SaboteurWaypoint5: waypoint
Owner: Neutral
Location: 31,81
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,150 @@
Player:
PlayerResources:
DefaultCash: 7000
ExternalCondition@AIOrdos:
Condition: base-rebuilder
ExternalCondition@AIOrdosDefense:
Condition: defense-rebuilder
ExternalCondition@AIAtreides:
Condition: base-rebuilder2
ExternalCondition@AIAtreidesDefense:
Condition: defense-rebuilder2
BaseBuilderBotModule@Ordos:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 2
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
starport: 1
wind_trap: 12
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 2
high_tech_factory: 1
starport: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@OrdosDefnse:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 2
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 12
silo: 1
high_tech_factory: 1
starport: 1
medium_gun_turret: 8
large_gun_turret: 4
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
starport: 1
medium_gun_turret: 6
large_gun_turret: 4
BaseBuilderBotModule@Atreides:
RequiresCondition: base-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 2
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
starport: 1
wind_trap: 12
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
high_tech_factory: 1
starport: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@AtreidesDefense:
RequiresCondition: defense-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 2
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 9
silo: 1
high_tech_factory: 1
starport: 1
medium_gun_turret: 6
large_gun_turret: 6
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
high_tech_factory: 1
starport: 1
medium_gun_turret: 1
large_gun_turret: 1
World:
LuaScript:

View File

@@ -7,6 +7,8 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(10)
AttackGroupSize =
{
easy = 6,
@@ -14,26 +16,117 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
EarlyProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
hard = { DateTime.Seconds(1), DateTime.Seconds(3) }
easy = { DateTime.Seconds(12), DateTime.Seconds(15) },
normal = { DateTime.Seconds(10), DateTime.Seconds(13) },
hard = { DateTime.Seconds(9), DateTime.Seconds(10) }
}
LateProductionDelays =
{
easy = { DateTime.Seconds(5), DateTime.Seconds(8) },
normal = { DateTime.Seconds(3), DateTime.Seconds(6) },
hard = { DateTime.Seconds(2), DateTime.Seconds(4) }
}
InitialProductionDelay = {
AtreidesMain =
{
easy = DateTime.Seconds(200),
normal = DateTime.Seconds(150),
hard = DateTime.Seconds(100)
},
AtreidesSmall =
{
easy = DateTime.Seconds(160),
normal = DateTime.Seconds(80),
hard = DateTime.Seconds(50)
},
CorrinoMain =
{
easy = DateTime.Seconds(250),
normal = DateTime.Seconds(200),
hard = DateTime.Seconds(150)
},
CorrinoSmall =
{
easy = DateTime.Seconds(100),
normal = DateTime.Seconds(80),
hard = DateTime.Seconds(60)
}
}
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
EnemyVehicleTypes = { "trike", "trike", "quad" }
AtreidesMainTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
AtreidesMainTankTypes = {
EarlyGame = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank" },
LateGame = {"combat_tank_a", "siege_tank", "missile_tank", "sonic_tank"}
}
AtreidesSmallTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank" }
AtreidesStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
CorrinoMainInfantryTypes = { "light_inf", "light_inf", "trooper", "sardaukar" }
CorrinoMainTankTypes = { "combat_tank_h", "combat_tank_h", "siege_tank", "missile_tank" }
CorrinoMainTankTypes = {
EarlyGame = { "combat_tank_h" },
LateGame = { "combat_tank_h", "combat_tank_h", "siege_tank", "missile_tank" }
}
CorrinoSmallTankTypes = { "combat_tank_h", "combat_tank_h", "siege_tank" }
CorrinoStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_h.starport", "combat_tank_h.starport", "siege_tank.starport", "missile_tank.starport" }
ActivateAI = function()
Defending[AtreidesMain] = {}
Defending[AtreidesSmall1] = {}
Defending[AtreidesSmall2] = {}
Defending[CorrinoMain] = {}
Defending[CorrinoSmall] = {}
-- this is also first attack timing
AttackDelay[AtreidesMain] = 16000
AttackDelay[AtreidesSmall1] = 16000
AttackDelay[AtreidesSmall2] = 16000
AttackDelay[CorrinoMain] = 16000
AttackDelay[CorrinoSmall] = 16000
TimeBetweenAttacks[AtreidesMain] = 13000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[AtreidesSmall1] = 1000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[AtreidesSmall2] = 4000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[CorrinoMain] = 12000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[CorrinoSmall] = 10000 * DifficultyModifier[Difficulty]
Trigger.OnAllKilledOrCaptured(AtreidesSmall1Base, function()
TimeBetweenAttacks[AtreidesMain] = 0
end)
Trigger.OnAllKilledOrCaptured(CorrinoMainBase, function()
TimeBetweenAttacks[CorrinoSmall] = 0
end)
Trigger.OnAllKilledOrCaptured(CorrinoSmallBase, function()
TimeBetweenAttacks[CorrinoMain] = 0
end)
HarvesterCount[AtreidesMain] = 4
HarvesterCount[AtreidesSmall1] = 2
HarvesterCount[AtreidesSmall2] = 2
HarvesterCount[CorrinoMain] = 4
HarvesterCount[CorrinoSmall] = 2
PatrolPoints[AtreidesMain] = {AtreidesPatrolPoint3.Location, AtreidesPatrolPoint4.Location, AtreidesPatrolPoint2.Location, AtreidesRally10.Location, AtreidesPatrolPoint5.Location }
PatrolPoints[AtreidesSmall1] = {AtreidesPatrolPoint1.Location, AtreidesPatrolPoint2.Location, AtreidesRally3.Location }
PatrolPoints[CorrinoMain] = {CorrinoPatrolPoint1.Location, CorrinoPatrolPoint2.Location, AtreidesPatrolPoint5.Location }
PatrolPoints[CorrinoSmall] = {CorrinoPatrolPoint3.Location, AtreidesPatrolPoint3.Location, AtreidesPatrolPoint5.Location }
DefencePerimeter[AtreidesMain] = GetCellsInRectangle(CPos.New(36,15), CPos.New(57,30))
DefencePerimeter[AtreidesSmall1] = GetCellsInRectangle(CPos.New(34,51), CPos.New(46,74))
DefencePerimeter[AtreidesSmall2] = GetCellsInRectangle(CPos.New(18,32), CPos.New(30,37))
DefencePerimeter[CorrinoMain] = GetCellsInRectangle(CPos.New(3,13), CPos.New(24,26))
DefencePerimeter[CorrinoSmall] = GetCellsInRectangle(CPos.New(74,27), CPos.New(96,48))
IdlingUnits[AtreidesMain] = Utils.Concat(Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[1], InitialAtreidesPaths[1]), Utils.Concat(Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[2], InitialAtreidesPaths[2]), Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[3], InitialAtreidesPaths[3])))
IdlingUnits[AtreidesSmall1] = Utils.Concat(Reinforcements.Reinforce(AtreidesSmall1, InitialAtreidesReinforcements[4], InitialAtreidesPaths[4]), Reinforcements.Reinforce(AtreidesSmall1, InitialAtreidesReinforcements[5], InitialAtreidesPaths[5]))
IdlingUnits[AtreidesSmall2] = Reinforcements.Reinforce(AtreidesSmall2, InitialAtreidesReinforcements[6], InitialAtreidesPaths[6])
@@ -46,35 +139,118 @@ ActivateAI = function()
DefendAndRepairBase(CorrinoMain, CorrinoMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(CorrinoSmall, CorrinoSmallBase, 0.75, AttackGroupSize[Difficulty])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
if EarlyGameStage >= DateTime.GameTime then
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
else
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
end
end
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local infantryToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuildAtreidesMain = function() return { Utils.Random(AtreidesMainTankTypes) } end
local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuildAtreidesMain = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(AtreidesMainTankTypes["EarlyGame"]) }
else
return { Utils.Random(AtreidesMainTankTypes["LateGame"]) }
end
end
local tanksToBuildAtreidesSmall = function() return { Utils.Random(AtreidesSmallTankTypes) } end
local tanksToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainTankTypes) } end
local tanksToBuildCorrinoMain = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(CorrinoMainTankTypes["EarlyGame"]) }
else
return { Utils.Random(CorrinoMainTankTypes["LateGame"]) }
end
end
local tanksToBuildCorrinoSmall = function() return { Utils.Random(CorrinoSmallTankTypes) } end
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end
local unitsToBuyCorrino = function() return { Utils.Random(CorrinoStarportTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
local attackThresholdSize = AttackGroupSize[Difficulty] * 3
local attackThresholdSizeCorrino = AttackGroupSize[Difficulty] * 4
local attackThresholdSizeSmallBase = AttackGroupSize[Difficulty] * 2
Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function ()
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize)
--ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], AttackThresholdSize)
end)
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AStarport, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall"][Difficulty], function ()
ProduceUnits(AtreidesSmall1, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(AtreidesSmall1, ALightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(AtreidesSmall1, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
end)
ProduceUnits(AtreidesSmall1, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall1, ALightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall1, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall2, ABarracks4, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(AtreidesSmall2, ABarracks4, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["CorrinoMain"][Difficulty], function ()
ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSizeCorrino)
ProduceUnits(CorrinoMain, CLightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeCorrino)
ProduceUnits(CorrinoMain, CHeavyFactory1, delay, tanksToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSizeCorrino)
--ProduceUnits(CorrinoMain, CStarport, delay, unitsToBuyCorrino, AttackGroupSize[Difficulty], AttackThresholdSize)
end)
ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(CorrinoMain, CLightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(CorrinoMain, CHeavyFactory1, delay, tanksToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(CorrinoMain, CStarport, delay, unitsToBuyCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["CorrinoSmall"][Difficulty], function ()
ProduceUnits(CorrinoSmall, CBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(CorrinoSmall, CLightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
ProduceUnits(CorrinoSmall, CHeavyFactory2, delay, tanksToBuildCorrinoSmall, AttackGroupSize[Difficulty], attackThresholdSizeSmallBase)
end)
ProduceUnits(CorrinoSmall, CBarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(CorrinoSmall, CLightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(CorrinoSmall, CHeavyFactory2, delay, tanksToBuildCorrinoSmall, AttackGroupSize[Difficulty], attackThresholdSize)
local crusherTypes = { "combat_tank_a", "combat_tank_a.starport", "combat_tank_h", "combat_tank_h.starport" }
local crusherFactories = { AStarport, AHeavyFactory1, AHeavyFactory2, CHeavyFactory1, CHeavyFactory2, CStarport }
ActivateCrusherLogic(crusherTypes, crusherFactories)
if Difficulty == "normal" then
AtreidesMain.GrantCondition("base-rebuilder")
AtreidesSmall1.GrantCondition("base-rebuilder2")
CorrinoSmall.GrantCondition("base-rebuilder3")
end
if Difficulty == "hard" then
AtreidesMain.GrantCondition("defense-rebuilder")
AtreidesSmall1.GrantCondition("defense-rebuilder2")
CorrinoSmall.GrantCondition("defense-rebuilder3")
end
local productionTypesAtreidis =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuildAtreidesMain
}
local productionTypesCorrino =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuildCorrinoSmall
}
Trigger.OnBuildingPlaced(AtreidesMain, function(p, building)
table.insert(AtreidesMainBase, building)
DefendAndRepairBase(AtreidesMain, {building}, 0.5, AttackGroupSize[Difficulty] )
if productionTypesAtreidis[building.Type] == nil then return end
ProduceUnits(AtreidesMain, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
Trigger.OnBuildingPlaced(AtreidesSmall1, function(p, building)
table.insert(AtreidesSmallBase, building)
DefendAndRepairBase(AtreidesSmall1, {building}, 0.5, AttackGroupSize[Difficulty] )
if productionTypesAtreidis[building.Type] == nil then return end
ProduceUnits(AtreidesSmall1, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
Trigger.OnBuildingPlaced(CorrinoMain, function(p, building)
table.insert(CorrinoMainBase, building)
DefendAndRepairBase(CorrinoMain, {building}, 0.5, AttackGroupSize[Difficulty] )
if productionTypesCorrino[building.Type] == nil then return end
ProduceUnits(CorrinoMain, building, delay, productionTypesCorrino[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

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 }
AtreidesSmall1Base = { AConYard2, ARefinery4, ABarracks3, AHeavyFactory2, ALightFactory2, ARepair, ARock5, ARock6, ARock7, ARock8, ARock9, APower15, APower16, APower17, APower18, APower19, APower20, APower21 }
AtreidesSmall2Base = { AOutpost2, ABarracks4, AGunt6, AGunt7, AGunt8, ARock10, APower22, APower23 }
CorrinoMainBase = { COutpost, CPalace, CRefinery1, CHeavyFactory1, CLightFactory1, CStarport, CResearch, CGunt1, CGunt2, CRock1, CRock2, CBarracks1, CPower1, CPower2, CPower3, CPower4, CPower5, CPower6, CPower7 }
CorrinoSmallBase = { CConYard, CRefinery2, CHeavyFactory2, CLightFactory2, CRock3, CRock4, CBarracks2, CPower8, CPower9, CPower10, CPower11 }
AtreidesReinforcements =
@@ -131,9 +135,13 @@ InitialCorrinoPaths =
{ CorrinoEntry2.Location, CorrinoRally2.Location }
}
HarkonnenReinforcements = { "combat_tank_h", "combat_tank_h", "siege_tank", "siege_tank", "missile_tank" }
HarkonnenPath = { HarkonnenEntry.Location, HarkonnenRally.Location }
HarkonnenReinforcements = {
{ "combat_tank_h", "combat_tank_h", "siege_tank", "siege_tank", "missile_tank" },
{ "trooper", "light_inf", "light_inf", "light_inf", "trooper", "light_inf", "trooper", "light_inf", "trooper", "light_inf", "trooper" },
{ "trooper", "light_inf", "quad", "trike", "quad" },
{ "devastator", "light_inf", "quad", "trike", "quad" },
{ "trooper", "combat_tank_h", "combat_tank_h", "combat_tank_h", "quad" }
}
SendStarportReinforcements = function()
Trigger.AfterDelay(CorrinoStarportDelay[Difficulty], function()
@@ -142,7 +150,6 @@ SendStarportReinforcements = function()
end
local reinforcements = Utils.Random(CorrinoStarportReinforcements[Difficulty])
local units = Reinforcements.ReinforceWithTransport(CorrinoMain, "frigate", reinforcements, { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2]
Utils.Do(units, function(unit)
unit.AttackMove(AtreidesAttackLocation)
@@ -153,23 +160,56 @@ SendStarportReinforcements = function()
end)
end
SendHarkonnenReinforcements = function(delay)
HarkonnenPaths =
{
{ HarkonnenEntry.Location, HarkonnenRally.Location },
{ AtreidesEntry3.Location, HarkonnenRally1.Location },
{ HarkonnenEntry.Location, HarkonnenRally2.Location },
{ AtreidesEntry3.Location, AtreidesRally3.Location },
{ HarkonnenRally3.Location, AtreidesRally9.Location },
{ HarkonnenRally4.Location, AtreidesRally8.Location }
}
SendHarkonnenReinforcements = function(delay, number)
Trigger.AfterDelay(delay, function()
Reinforcements.ReinforceWithTransport(Harkonnen, "carryall.reinforce", HarkonnenReinforcements, HarkonnenPath, { HarkonnenPath[1] })
Reinforcements.ReinforceWithTransport(Harkonnen, "carryall.reinforce", HarkonnenReinforcements[number], HarkonnenPaths[number], { HarkonnenPaths[number][1] })
Trigger.AfterDelay(DateTime.Seconds(5), function()
Media.PlaySpeechNotification(Harkonnen, "Reinforce")
end)
end)
end
SendAirStrike = function()
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesMain then
AirStrikeTimer = 7500
AirStrikeChargeTime = 7500
AirstrikeLogic = function(airstrikeProvider)
if airstrikeProvider.IsDead then
return
end
if DateTime.GameTime <= AirStrikeTimer then
Trigger.AfterDelay(AirStrikeTimer - DateTime.GameTime + 1, function()
AirstrikeLogic(airstrikeProvider)
end)
return
end
-- randomly choose if wait again or strike. During waiting Airstrike can still be used by DefensiveAirStrike
if Utils.RandomInteger(1, 100) < 30 then
Trigger.AfterDelay(1000, function() AirstrikeLogic(airstrikeProvider)end)
else
AirStrikeVSBuilding(airstrikeProvider)
Trigger.AfterDelay(7500, function() AirstrikeLogic(airstrikeProvider) end)
IsAirstrikeReady = false
end
end
AirStrikeVSBuilding = function(airstrikeProvider)
if airstrikeProvider.IsDead or DateTime.GameTime < AirStrikeTimer then
return
end
local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
return
actor.HasProperty("Sell") and
return actor.HasProperty("Sell") and
actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and
@@ -178,12 +218,86 @@ SendAirStrike = function()
end)
if #targets > 0 then
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition)
airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end
end
DefensiveAirStrike = function(airstrikeProvider, possibleTargets)
if airstrikeProvider.IsDead or DateTime.GameTime <= AirStrikeTimer then return end
local bestValue = {}
local bestIndex = 1
for i = 1, #possibleTargets, 1 do
local ActorsInCircle = Map.ActorsInCircle(possibleTargets[i].CenterPosition, WDist.FromCells(4), function(a)
return a.Owner == Harkonnen
and not a.IsDead
and a.HasProperty("Attack")
end)
bestValue[i] = 0
Utils.Do(ActorsInCircle, function(a)
bestValue[i] = bestValue[i] + Actor.Cost(a.Type)
end)
if bestValue[i] > bestValue[bestIndex] then
bestIndex = i
end
end
airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end
EmergencyBehaviour = function(player,target)
if player == AtreidesMain or player == AtreidesSmall1 then
if AHiTechFactory.IsDead then return end
local enemyunits = Map.ActorsInCircle(Map.CenterOfCell(target), WDist.FromCells(15), function(a)
return a.Owner == Harkonnen
and not a.IsDead
and a.HasProperty("Attack")
end)
if enemyunits[1] == nil then return end
DefensiveAirStrike(AHiTechFactory, enemyunits)
end
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
if player == AtreidesSmall1 and #IdlingUnits[AtreidesMain] > 10 then
local reinforcements = SetupAttackGroup(AtreidesMain, Utils.RandomInteger(10, #IdlingUnits[AtreidesMain]))
Utils.Do(reinforcements, function(unit)
Trigger.ClearAll(unit)
Trigger.AfterDelay(1, function()
unit.Stop()
unit.Move(CorrinoPatrolPoint1.Location,1)
unit.AttackMove(target)
unit.CallFunc(function()
FindTargetsInArea(player, unit)
end)
end)
end)
end
if player == AtreidesSmall2 and #IdlingUnits[AtreidesMain] > 10 then
CheckArea(AtreidesMain, target, 10)
end
end
ReleaseSardaukars = true
Trigger.OnDamaged(CPalace, function(self)
if self.Health < self.MaxHealth * 0.8 and ReleaseSardaukars then
local index = 0
while index < 100 do
index = index + 5
Trigger.AfterDelay(index,function()
if self.IsDead then return end
local actor = Actor.Create("sardaukar", true, { Owner = CorrinoMain, Location = CPalace.Location + CVec.New(1,2) })
actor.Move(CPos.New(3,31))
IdlingUnits[CorrinoMain][#IdlingUnits[CorrinoMain] + 1] = actor
end)
end
ReleaseSardaukars = false
end
end)
BuildFremen = function()
if APalace.IsDead or APalace.Owner ~= AtreidesMain then
return
@@ -194,7 +308,6 @@ BuildFremen = function()
Trigger.AfterDelay(DateTime.Seconds(5), function()
IdleFremen = Utils.Where(AtreidesMain.GetActorsByType('fremen'), function(actor) return actor.IsIdle end)
if #IdleFremen >= FremenGroupSize[Difficulty] then
SendFremen()
end
@@ -231,7 +344,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
local units = AtreidesMain.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[AtreidesMain] = false
ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
@@ -240,7 +352,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesSmall1] then
local units = AtreidesSmall1.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[AtreidesSmall1] = false
ProtectHarvester(units[1], AtreidesSmall1, AttackGroupSize[Difficulty])
@@ -249,7 +360,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoMain] then
local units = CorrinoMain.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[CorrinoMain] = false
ProtectHarvester(units[1], CorrinoMain, AttackGroupSize[Difficulty])
@@ -258,7 +368,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoSmall] then
local units = CorrinoSmall.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[CorrinoSmall] = false
ProtectHarvester(units[1], CorrinoSmall, AttackGroupSize[Difficulty])
@@ -286,8 +395,8 @@ WorldLoaded = function()
Camera.Position = HMCV.CenterPosition
AtreidesAttackLocation = HarkonnenRally.Location
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds (30), BuildFremen)
Trigger.AfterDelay(DateTime.Minutes(10), function() AirstrikeLogic(AHiTechFactory) end )
Trigger.AfterDelay(DateTime.Minutes(3) + DateTime.Seconds (30), BuildFremen)
Trigger.OnAllKilledOrCaptured(AtreidesMainBase, function()
Utils.Do(AtreidesMain.GetGroundAttackers(), IdleHunt)
@@ -315,8 +424,8 @@ WorldLoaded = function()
unit.AttackMove(AtreidesAttackLocation)
IdleHunt(unit)
end
SendCarryallReinforcements(AtreidesMain, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition, huntFunction)
SendCarryallReinforcements(AtreidesMain, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition, huntFunction)
SendStarportReinforcements()
Actor.Create("upgrade.barracks", true, { Owner = AtreidesMain })
@@ -335,5 +444,19 @@ WorldLoaded = function()
Actor.Create("upgrade.heavy", true, { Owner = CorrinoSmall })
Trigger.AfterDelay(0, ActivateAI)
SendHarkonnenReinforcements(DateTime.Minutes(2) + DateTime.Seconds(30))
SendHarkonnenReinforcements(DateTime.Minutes(2) + DateTime.Seconds(30), 1)
SendHarkonnenReinforcements(17030,2)
SendHarkonnenReinforcements(17020,3)
Trigger.OnAllKilled({ARock6, ARock7, ARock8}, function()
SendHarkonnenReinforcements(0,4)
SendHarkonnenReinforcements(10,5)
end)
end
Trigger.OnDamaged(DebrisHarvester2, function(self)
if self.Health < self.MaxHealth * 0.6 then
self.Deploy()
Trigger.ClearAll(self)
end
end)

Binary file not shown.

View File

@@ -562,9 +562,6 @@ Actors:
ARock4: large_gun_turret
Location: 54,27
Owner: Atreides Main Base
CPalace: palace
Location: 2,28
Owner: Corrino Main Base
Actor161: wall
Location: 49,28
Owner: Atreides Main Base
@@ -844,6 +841,7 @@ Actors:
ARock6: large_gun_turret
Location: 47,62
Owner: Atreides Small Base 1
TurretFacing: 512
AHeavyFactory2: heavy_factory
Location: 36,63
Owner: Atreides Small Base 1
@@ -862,12 +860,10 @@ Actors:
ARock7: large_gun_turret
Location: 44,66
Owner: Atreides Small Base 1
TurretFacing: 512
APower21: wind_trap
Location: 38,67
Owner: Atreides Small Base 1
ARock8: large_gun_turret
Location: 44,67
Owner: Atreides Small Base 1
ABarracks3: barracks
Location: 36,68
Owner: Atreides Small Base 1
@@ -967,18 +963,12 @@ Actors:
AtreidesRally1: waypoint
Owner: Neutral
Location: 96,87
AtreidesEntry1: waypoint
Owner: Neutral
Location: 97,87
AtreidesRally2: waypoint
Owner: Neutral
Location: 76,93
AtreidesEntry2: waypoint
Owner: Neutral
Location: 76,97
AtreidesRally3: waypoint
Owner: Neutral
Location: 63,65
AtreidesEntry3: waypoint
Owner: Neutral
Location: 97,65
@@ -1042,6 +1032,85 @@ Actors:
CorrinoStarportExit: waypoint
Owner: Neutral
Location: 2,13
AtreidesPatrolPoint2: waypoint
Owner: Neutral
Location: 16,63
AtreidesPatrolPoint3: waypoint
Owner: Neutral
Location: 62,47
AtreidesPatrolPoint4: waypoint
Owner: Neutral
Location: 72,28
CorrinoPatrolPoint1: waypoint
Owner: Neutral
Location: 13,39
CorrinoPatrolPoint2: waypoint
Owner: Neutral
Location: 32,29
AtreidesPatrolPoint5: waypoint
Owner: Neutral
Location: 44,42
CorrinoPatrolPoint3: waypoint
Owner: Neutral
Location: 72,50
Actor5: combat_tank_a.debris
Owner: Creeps
Facing: 384
Location: 93,53
Actor8: frigate.debris
Owner: Creeps
Location: 86,54
Actor1: harvester.debris
Owner: Creeps
Facing: 384
Location: 77,63
Actor9: carryall.debris
Owner: Creeps
Facing: 384
Location: 48,75
Actor6: siege_tank.debris
Owner: Creeps
Facing: 384
Location: 92,58
Actor10: combat_tank_h.debris
Owner: Creeps
Facing: 384
Location: 88,54
HarkonnenRally1: waypoint
Owner: Neutral
Location: 74,71
HarkonnenRally2: waypoint
Owner: Neutral
Location: 68,79
AtreidesEntry1: waypoint
Owner: Neutral
Location: 97,87
Actor11: crate
Owner: Neutral
Location: 6,76
ARock8: large_gun_turret
Owner: Atreides Small Base 1
Location: 44,67
TurretFacing: 512
HarkonnenRally4: waypoint
Owner: Neutral
Location: 97,57
HarkonnenRally3: waypoint
Owner: Neutral
Location: 97,70
AtreidesRally3: waypoint
Owner: Neutral
Location: 51,65
AtreidesPatrolPoint1: waypoint
Owner: Neutral
Location: 46,84
DebrisHarvester2: harvester.debris
Owner: Creeps
Facing: 384
Location: 58,39
CPalace: palace
Owner: Corrino Main Base
Location: 2,26
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,204 @@
Player:
PlayerResources:
DefaultCash: 7000
ExternalCondition@AIAMail:
Condition: base-rebuilder
ExternalCondition@AIASmall:
Condition: base-rebuilder2
ExternalCondition@AICSmall:
Condition: base-rebuilder3
ExternalCondition@AIAMail-defense:
Condition: defense-rebuilder
ExternalCondition@AIASmall-defense:
Condition: defense-rebuilder2
ExternalCondition@AICSmall-defense:
Condition: defense-rebuilder3
BaseBuilderBotModule@AIAMainBase:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 3
outpost: 1
light_factory: 1
starport: 1
palace: 1
heavy_factory: 1
high_tech_factory: 1
wind_trap: 11
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
starport: 1
high_tech_factory: 1
palace: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@AIASmallBase:
RequiresCondition: base-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
palace: 1
heavy_factory: 1
wind_trap: 7
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@AIAMainCorrino:
RequiresCondition: base-rebuilder3
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 3
outpost: 1
light_factory: 1
heavy_factory: 1
wind_trap: 4
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@AIAMainDefense:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 3
outpost: 1
light_factory: 1
starport: 1
palace: 1
heavy_factory: 1
high_tech_factory: 1
wind_trap: 11
silo: 1
medium_gun_turret: 5
large_gun_turret: 4
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
starport: 1
high_tech_factory: 1
palace: 1
light_factory: 1
heavy_factory: 1
medium_gun_turret: 1
large_gun_turret: 1
BaseBuilderBotModule@AIASmallDefense:
RequiresCondition: defense-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
palace: 1
heavy_factory: 1
wind_trap: 7
silo: 1
large_gun_turret: 5
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
large_gun_turret: 1
BaseBuilderBotModule@AISmallCorrino:
RequiresCondition: defense-rebuilder3
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
wind_trap: 4
silo: 1
large_gun_turret: 2
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
large_gun_turret: 2
World:
LuaScript:

View File

@@ -7,6 +7,38 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(7)
InitialProductionDelay = {
AtreidesMain =
{
easy = DateTime.Seconds(180),
normal = DateTime.Seconds(120),
hard = DateTime.Seconds(60)
},
AtreidesSmall =
{
easy = DateTime.Seconds(120),
normal = DateTime.Seconds(60),
hard = DateTime.Seconds(0)
},
CorrinoMain =
{
easy = DateTime.Seconds(160),
normal = DateTime.Seconds(120),
hard = DateTime.Seconds(80)
},
CorrinoSmall =
{
easy = DateTime.Seconds(80),
normal = DateTime.Seconds(60),
hard = DateTime.Seconds(30)
}
}
AttackGroupSize =
{
easy = 6,
@@ -14,25 +46,81 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
EarlyProductionDelays =
{
easy = { DateTime.Seconds(9), DateTime.Seconds(12) },
normal = { DateTime.Seconds(6), DateTime.Seconds(8) },
hard = { DateTime.Seconds(4), DateTime.Seconds(7) }
}
LateProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
hard = { DateTime.Seconds(1), DateTime.Seconds(3) }
}
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
EnemyVehicleTypes = { "trike", "trike", "quad" }
AtreidesMainTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
AtreidesMainTankTypes = {
EarlyGame = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank" },
LateGame = { "combat_tank_a", "combat_tank_a", "siege_tank", "missile_tank", "sonic_tank" }
}
AtreidesSmallTankTypes = { "combat_tank_a", "combat_tank_a", "siege_tank" }
AtreidesStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_a.starport", "combat_tank_a.starport", "siege_tank.starport", "missile_tank.starport" }
CorrinoMainInfantryTypes = { "light_inf", "light_inf", "trooper", "sardaukar" }
CorrinoTankTypes = { "combat_tank_h", "combat_tank_h", "siege_tank", "missile_tank" }
CorrinoStarportTypes = { "trike.starport", "trike.starport", "quad.starport", "combat_tank_h.starport", "combat_tank_h.starport", "siege_tank.starport", "missile_tank.starport" }
CorrinoTankTypes = {
EarlyGame = { "combat_tank_h" },
LateGame = { "combat_tank_h", "combat_tank_h", "siege_tank", "missile_tank" }
}
ActivateAI = function()
Defending[AtreidesMain] = {}
Defending[AtreidesSmall] = {}
Defending[CorrinoMain] = {}
Defending[CorrinoSmall] = {}
-- this is also first attack timing
AttackDelay[AtreidesMain] = 15000 * DifficultyModifier[Difficulty]
AttackDelay[AtreidesSmall] = 10000 * DifficultyModifier[Difficulty]
AttackDelay[CorrinoMain] = 15000 * DifficultyModifier[Difficulty]
AttackDelay[CorrinoSmall] = 15000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[AtreidesMain] = 13000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[AtreidesSmall] = 4000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[CorrinoMain] = 8600 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[CorrinoSmall] = 8600 * DifficultyModifier[Difficulty]
Trigger.OnKilledOrCaptured(AConYard1, function()
TimeBetweenAttacks[AtreidesMain] = 0
TimeBetweenAttacks[CorrinoMain] = 0
end)
Trigger.OnAllKilledOrCaptured(CorrinoMainBase, function()
TimeBetweenAttacks[CorrinoSmall] = 0
TimeBetweenAttacks[AtreidesMain] = 0
end)
Trigger.OnAllKilledOrCaptured(CorrinoSmallBase, function()
TimeBetweenAttacks[CorrinoMain] = 0
end)
HarvesterCount[AtreidesMain] = 4
HarvesterCount[AtreidesSmall] = 2
HarvesterCount[CorrinoMain] = 4
HarvesterCount[CorrinoSmall] = 1
PatrolPoints[AtreidesMain] = {APatrolPoint1.Location, APatrolPoint2.Location, APatrolPoint3.Location, APatrolPoint4.Location }
PatrolPoints[AtreidesSmall] = {APatrolPoint5.Location, APatrolPoint6.Location, APatrolPoint7.Location }
PatrolPoints[CorrinoMain] = {APatrolPoint7.Location, AtreidesRally5.Location, CPatrolPoint1.Location }
PatrolPoints[CorrinoSmall] = {CPatrolPoint2.Location, AtreidesRally4.Location, APatrolPoint4.Location }
DefencePerimeter[AtreidesMain] = GetCellsInRectangle(CPos.New(25,58), CPos.New(47,70))
DefencePerimeter[AtreidesSmall] = GetCellsInRectangle(CPos.New(103,5), CPos.New(119,18))
DefencePerimeter[CorrinoMain] = GetCellsInRectangle(CPos.New(65,38), CPos.New(91,55))
DefencePerimeter[CorrinoSmall] = GetCellsInRectangle(CPos.New(33,35), CPos.New(49,52))
IdlingUnits[AtreidesMain] = Utils.Concat(Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[1], InitialAtreidesPaths[1]), Reinforcements.Reinforce(AtreidesMain, InitialAtreidesReinforcements[2], InitialAtreidesPaths[2]))
IdlingUnits[AtreidesSmall] = Reinforcements.Reinforce(AtreidesSmall, InitialAtreidesReinforcements[3], InitialAtreidesPaths[3])
IdlingUnits[CorrinoMain] = Utils.Concat(Reinforcements.Reinforce(CorrinoMain, InitialCorrinoReinforcements[1], InitialCorrinoPaths[1]), Reinforcements.Reinforce(CorrinoMain, InitialCorrinoReinforcements[2], InitialCorrinoPaths[2]))
@@ -43,31 +131,109 @@ ActivateAI = function()
DefendAndRepairBase(CorrinoMain, CorrinoMainBase, 0.75, AttackGroupSize[Difficulty])
DefendAndRepairBase(CorrinoSmall, CorrinoSmallBase, 0.75, AttackGroupSize[Difficulty])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
if EarlyGameStage >= DateTime.GameTime then
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
else
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
end
end
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local infantryToBuildCorrinoMain = function() return { Utils.Random(CorrinoMainInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuildAtreidesMain = function() return { Utils.Random(AtreidesMainTankTypes) } end
local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuildAtreidesMain = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(AtreidesMainTankTypes["EarlyGame"]) }
else
return { Utils.Random(AtreidesMainTankTypes["LateGame"]) }
end
end
local tanksToBuildAtreidesSmall = function() return { Utils.Random(AtreidesSmallTankTypes) } end
local tanksToBuildCorrino = function() return { Utils.Random(CorrinoTankTypes) } end
local unitsToBuyAtreides = function() return { Utils.Random(AtreidesStarportTypes) } end
local unitsToBuyCorrino = function() return { Utils.Random(CorrinoStarportTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
local tanksToBuildCorrino = function()
if EarlyGameStage >= DateTime.GameTime then
return { Utils.Random(CorrinoTankTypes["EarlyGame"]) }
else
return { Utils.Random(CorrinoTankTypes["LateGame"]) }
end
end
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AStarport1, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
local attackThresholdSize = AttackGroupSize[Difficulty] * 3
local attackThresholdSizeSmall = AttackGroupSize[Difficulty] * 2
local attackThresholdSizeEmperor = AttackGroupSize[Difficulty] * 5
ProduceUnits(AtreidesSmall, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, ALightFactory2, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesSmall, AStarport2, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function ()
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, ALightFactory1, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AHeavyFactory1, delay, tanksToBuildAtreidesMain, AttackGroupSize[Difficulty], attackThresholdSize)
--ProduceUnits(AtreidesMain, AStarport1, delay, unitsToBuyAtreides, AttackGroupSize[Difficulty], AttackThresholdSize)
end)
ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(CorrinoMain, CHeavyFactory, delay, tanksToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall"][Difficulty], function ()
ProduceUnits(AtreidesSmall, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
ProduceUnits(AtreidesSmall, ALightFactory2, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
ProduceUnits(AtreidesSmall, AHeavyFactory2, delay, tanksToBuildAtreidesSmall, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
end)
ProduceUnits(CorrinoSmall, CBarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(CorrinoSmall, CLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(CorrinoSmall, CStarport, delay, unitsToBuyCorrino, AttackGroupSize[Difficulty], attackThresholdSize)
Trigger.AfterDelay(InitialProductionDelay["CorrinoMain"][Difficulty], function ()
ProduceUnits(CorrinoMain, CBarracks1, delay, infantryToBuildCorrinoMain, AttackGroupSize[Difficulty], attackThresholdSizeEmperor)
ProduceUnits(CorrinoMain, CHeavyFactory, delay, tanksToBuildCorrino, AttackGroupSize[Difficulty], attackThresholdSizeEmperor)
end)
Trigger.AfterDelay(InitialProductionDelay["CorrinoSmall"][Difficulty], function ()
ProduceUnits(CorrinoSmall, CBarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
ProduceUnits(CorrinoSmall, CLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSizeSmall)
end)
local productionTypesAtreidis =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuildAtreidesMain
}
local productionTypesCorrino =
{
barracks = infantryToBuildCorrinoMain,
heavy_factory = tanksToBuildCorrino
}
if Difficulty == "normal" then
AtreidesMain.GrantCondition("base-rebuilder")
AtreidesSmall.GrantCondition("base-rebuilder2")
CorrinoMain.GrantCondition("base-rebuilder3")
end
if Difficulty == "hard" then
AtreidesMain.GrantCondition("defense-rebuilder")
AtreidesSmall.GrantCondition("defense-rebuilder2")
CorrinoMain.GrantCondition("defense-rebuilder3")
end
Trigger.OnBuildingPlaced(AtreidesMain, function(p, building)
table.insert(AtreidesMainBase, building)
DefendAndRepairBase(AtreidesMain, {building}, 0.5, AttackGroupSize[Difficulty] )
if productionTypesAtreidis[building.Type] == nil then return end
ProduceUnits(AtreidesMain, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
Trigger.OnBuildingPlaced(AtreidesSmall, function(p, building)
table.insert(AtreidesSmallBase, building)
DefendAndRepairBase(AtreidesSmall, {building}, 0.5, AttackGroupSize[Difficulty] )
if productionTypesAtreidis[building.Type] == nil then return end
ProduceUnits(AtreidesSmall, building, delay, productionTypesAtreidis[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
Trigger.OnBuildingPlaced(CorrinoMain, function(p, building)
table.insert(CorrinoMainBase, building)
DefendAndRepairBase(CorrinoMain, {building}, 0.5, AttackGroupSize[Difficulty] )
if productionTypesCorrino[building.Type] == nil then return end
ProduceUnits(CorrinoMain, building, delay, productionTypesCorrino[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
ActivateCrushLogic()
end

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 }
AtreidesSmallBase = { AConYard2, ARefinery3, ABarracks3, AHeavyFactory2, ALightFactory2, ARepair2, AGunt1, AGunt2, ARock11, APower12, APower13, APower14, APower15, APower16, APower17, APower18, APower19, APower20 }
CorrinoMainBase = { CConYard, COutpost, CPalace, CRefinery1, CHeavyFactory, CResearch, CGunt1, CGunt2, CGunt3, CGunt4, CGunt5, CGunt6, CRock1, CRock2, CRock3, CRock4, CBarracks1, CBarracks2, CPower1, CPower2, CPower3, CPower4, CPower5, CPower6, CPower7, CPower8 }
CorrinoSmallBase = { CRefinery2, CLightFactory, CStarport, CGunt7, CGunt8, CBarracks3, CPower9, CPower10, CPower11, CPower12, CSilo1, CSilo2, CSilo3, CSilo4 }
AtreidesReinforcements =
@@ -148,7 +151,6 @@ SendStarportReinforcements = function()
end
local reinforcements = Utils.Random(CorrinoStarportReinforcements[Difficulty])
local units = Reinforcements.ReinforceWithTransport(CorrinoSmall, "frigate", reinforcements, { CorrinoStarportEntry.Location, CStarport.Location + CVec.New(1, 1) }, { CorrinoStarportExit.Location })[2]
Utils.Do(units, function(unit)
unit.AttackMove(AtreidesAttackLocation)
@@ -168,14 +170,33 @@ SendHarkonnenReinforcements = function(delay)
end)
end
SendAirStrike = function()
if AHiTechFactory.IsDead or AHiTechFactory.Owner ~= AtreidesMain then
AirStrikeTimer = 7500
AirStrikeChargeTime = 7500
AirstrikeLogic = function(airstrikeProvider)
if airstrikeProvider.IsDead then return end
if DateTime.GameTime <= AirStrikeTimer then
Trigger.AfterDelay(AirStrikeTimer - DateTime.GameTime + 1, function()
AirstrikeLogic(airstrikeProvider)
end)
return
end
-- randomly choose if wait again or strike. During waiting Airstrike can still be used by DefensiveAirStrike
if Utils.RandomInteger(1, 100) < 30 then
Trigger.AfterDelay(1501, function() AirstrikeLogic(airstrikeProvider)end)
else
AirStrikeVSBuilding(airstrikeProvider)
Trigger.AfterDelay(7500, function() AirstrikeLogic(airstrikeProvider) end)
IsAirstrikeReady = false
end
end
AirStrikeVSBuilding = function(airstrikeProvider)
if airstrikeProvider.IsDead then return end
local targets = Utils.Where(Harkonnen.GetActors(), function(actor)
return
actor.HasProperty("Sell") and
return actor.HasProperty("Sell") and
actor.Type ~= "wall" and
actor.Type ~= "medium_gun_turret" and
actor.Type ~= "large_gun_turret" and
@@ -184,12 +205,71 @@ SendAirStrike = function()
end)
if #targets > 0 then
AHiTechFactory.TargetAirstrike(Utils.Random(targets).CenterPosition)
airstrikeProvider.TargetAirstrike(Utils.Random(targets).CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
end
DefensiveAirStrike = function(airstrikeProvider, possibleTargets)
if airstrikeProvider.IsDead then return end
local bestValue = {}
local bestIndex = 1
for i = 1, #possibleTargets, 1 do
local ActorsInCircle = Map.ActorsInCircle(possibleTargets[i].CenterPosition, WDist.FromCells(4), function(a)
return
a.Owner == Harkonnen
and not a.IsDead
and a.HasProperty("Attack")
end)
bestValue[i] = 0
Utils.Do(ActorsInCircle, function(a)
bestValue[i] = bestValue[i] + Actor.Cost(a.Type)
end)
if bestValue[i] > bestValue[bestIndex] then
bestIndex = i
end
end
airstrikeProvider.TargetAirstrike(possibleTargets[bestIndex].CenterPosition)
AirStrikeTimer = DateTime.GameTime + AirStrikeChargeTime
end
EmergencyBehaviour = function(player,target)
if player == AtreidesMain or player == AtreidesSmall then
if AHiTechFactory.IsDead then return end
local enemyunits = Map.ActorsInCircle(Map.CenterOfCell(target), WDist.FromCells(15), function(a)
return a.Owner == Harkonnen
and not a.IsDead
and a.HasProperty("Attack")
end)
if enemyunits[1] == nil then return end
DefensiveAirStrike(AHiTechFactory, enemyunits)
end
if player == CorrinoSmall then
player.Cash = player.Cash + 2000
end
end
ReleaseSardaukars = true
Trigger.OnDamaged(CPalace, function(self)
if self.Health < self.MaxHealth * 0.8 and ReleaseSardaukars then
local index = 0
while index < 100 do
index = index + 5
Trigger.AfterDelay(index,function()
if self.IsDead then return end
local actor = Actor.Create("sardaukar", true, {Owner = CorrinoMain, Location = CPalace.Location + CVec.New(1,2)})
actor.Move(CPos.New(90,45))
IdlingUnits[CorrinoMain][#IdlingUnits[CorrinoMain] + 1] = actor
end)
end
ReleaseSardaukars = false
end
end)
BuildFremen = function()
if APalace.IsDead or APalace.Owner ~= AtreidesMain then
return
@@ -302,7 +382,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesMain] then
local units = AtreidesMain.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[AtreidesMain] = false
ProtectHarvester(units[1], AtreidesMain, AttackGroupSize[Difficulty])
@@ -311,7 +390,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[AtreidesSmall] then
local units = AtreidesSmall.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[AtreidesSmall] = false
ProtectHarvester(units[1], AtreidesSmall, AttackGroupSize[Difficulty])
@@ -320,7 +398,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoMain] then
local units = CorrinoMain.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[CorrinoMain] = false
ProtectHarvester(units[1], CorrinoMain, AttackGroupSize[Difficulty])
@@ -329,7 +406,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[CorrinoSmall] then
local units = CorrinoSmall.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[CorrinoSmall] = false
ProtectHarvester(units[1], CorrinoSmall, AttackGroupSize[Difficulty])
@@ -366,8 +442,8 @@ WorldLoaded = function()
Camera.Position = HBarracks.CenterPosition
AtreidesAttackLocation = HBarracks.Location
Trigger.AfterDelay(DateTime.Minutes(5), SendAirStrike)
Trigger.AfterDelay(DateTime.Minutes(1) + DateTime.Seconds (30), BuildFremen)
Trigger.AfterDelay(DateTime.Minutes(10), function() AirstrikeLogic(AHiTechFactory) end )
Trigger.AfterDelay(EarlyGameStage, BuildFremen)
Trigger.OnAllKilledOrCaptured(AtreidesMainBase, function()
Utils.Do(AtreidesMain.GetGroundAttackers(), IdleHunt)
@@ -385,14 +461,22 @@ WorldLoaded = function()
Utils.Do(CorrinoSmall.GetGroundAttackers(), IdleHunt)
end)
Trigger.AfterDelay(300, function()
Media.DisplayMessage(UserInterface.GetFluentMessage("husk-reclaimed-harkonnen"), Mentat)
end)
Trigger.AfterDelay(350, function()
Media.DisplayMessage(UserInterface.GetFluentMessage("engineers-hint"), Mentat)
end)
local path = function() return Utils.Random(AtreidesPaths) end
local waveCondition = function() return Harkonnen.IsObjectiveCompleted(KillAtreides) end
local huntFunction = function(unit)
unit.AttackMove(AtreidesAttackLocation)
IdleHunt(unit)
end
SendCarryallReinforcements(AtreidesMain, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition, huntFunction)
SendCarryallReinforcements(AtreidesMain, 0, AtreidesAttackWaves[Difficulty], AtreidesAttackDelay[Difficulty], path, AtreidesReinforcements[Difficulty], waveCondition, huntFunction)
SendStarportReinforcements()
Actor.Create("upgrade.barracks", true, { Owner = AtreidesMain })

Binary file not shown.

View File

@@ -454,9 +454,6 @@ Actors:
COutpost: outpost
Location: 79,42
Owner: Corrino Main Base
CPalace: palace
Location: 89,42
Owner: Corrino Main Base
Actor116: wall
Location: 93,42
Owner: Corrino Main Base
@@ -1005,6 +1002,68 @@ Actors:
CPower8: wind_trap
Owner: Corrino Main Base
Location: 90,48
APatrolPoint1: waypoint
Owner: Neutral
Location: 10,60
APatrolPoint2: waypoint
Owner: Neutral
Location: 38,85
APatrolPoint3: waypoint
Owner: Neutral
Location: 75,73
APatrolPoint4: waypoint
Owner: Neutral
Location: 44,32
APatrolPoint5: waypoint
Owner: Neutral
Location: 99,33
APatrolPoint6: waypoint
Owner: Neutral
Location: 82,17
APatrolPoint7: waypoint
Owner: Neutral
Location: 65,30
CPatrolPoint1: waypoint
Owner: Neutral
Location: 49,13
CPatrolPoint2: waypoint
Owner: Neutral
Location: 15,47
Actor6: combat_tank_h.debris
Owner: Harkonnen
Facing: 384
Location: 17,3
Actor7: siege_tank.debris
Owner: Harkonnen
Facing: 384
Location: 16,3
Actor5: combat_tank_a.debris
Facing: 384
Faction:
Owner: Atreides Small Base
Location: 14,3
CPalace: palace
Owner: Corrino Main Base
Location: 89,41
Actor10: light_inf
Owner: Smugglers - Neutral
Facing: 384
Location: 12,89
SubCell: 3
Actor9: trooper
Owner: Smugglers - Neutral
Facing: 384
Location: 11,88
SubCell: 3
Actor15: siege_tank.debris
Owner: Smugglers - Neutral
Facing: 384
Location: 10,88
Actor8: engineer
Owner: Smugglers - Neutral
Facing: 384
Location: 9,88
SubCell: 3
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -1,6 +1,208 @@
Player:
PlayerResources:
DefaultCash: 5000
ExternalCondition@AIAMail:
Condition: base-rebuilder
ExternalCondition@AIASmall:
Condition: base-rebuilder2
ExternalCondition@AICSmall:
Condition: base-rebuilder3
ExternalCondition@AIAMail-defense:
Condition: defense-rebuilder
ExternalCondition@AIASmall-defense:
Condition: defense-rebuilder2
ExternalCondition@AICSmall-defense:
Condition: defense-rebuilder3
BaseBuilderBotModule@AtreidesMain:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 3
outpost: 1
light_factory: 1
starport: 1
palace: 1
heavy_factory: 1
high_tech_factory: 1
wind_trap: 11
research_centre: 1
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
research_centre: 1
outpost: 1
starport: 1
high_tech_factory: 1
palace: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@AtreidesSmallBase:
RequiresCondition: base-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
palace: 1
heavy_factory: 1
wind_trap: 7
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@CorrinoMain:
RequiresCondition: base-rebuilder3
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 3
outpost: 1
heavy_factory: 1
wind_trap: 4
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
heavy_factory: 1
BaseBuilderBotModule@AtreidesMainDefense:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 3
outpost: 1
light_factory: 1
starport: 1
palace: 1
heavy_factory: 1
high_tech_factory: 1
wind_trap: 11
silo: 1
research_centre: 1
large_gun_turret: 10
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
starport: 1
high_tech_factory: 1
palace: 1
light_factory: 1
research_centre: 1
heavy_factory: 1
large_gun_turret: 1
BaseBuilderBotModule@AtreidesSmallBaseDefense:
RequiresCondition: defense-rebuilder2
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
palace: 1
heavy_factory: 1
wind_trap: 7
silo: 1
large_gun_turret: 1
medium_gun_turret: 2
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
light_factory: 1
heavy_factory: 1
large_gun_turret: 1
medium_gun_turret: 1
BaseBuilderBotModule@CorrinoMainDefense:
RequiresCondition: defense-rebuilder3
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: heavy_factory, barracks, starport
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 3
outpost: 1
heavy_factory: 1
wind_trap: 4
silo: 1
large_gun_turret: 2
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
outpost: 1
heavy_factory: 1
large_gun_turret: 2
World:
LuaScript:
@@ -62,3 +264,28 @@ grenadier:
thumper:
Buildable:
Prerequisites: ~disabled
palace:
ProduceActorPower@ReleaseSardaukars:
Name: actor-palace.produceactorpower-fremen-name
Description: actor-palace.produceactorpower-fremen-description
Icon: fremen
PauseOnCondition: disabled
RequiresCondition: corrino
Prerequisites: ~techlevel.superweapons, ~palace.sardaukar
Actors: mpsardaukar, mpsardaukar, mpsardaukar, mpsardaukar, mpsardaukar
Type: sardaukar
ChargeInterval: 2250
EndChargeTextNotification: notification-fremen-ready
ReadyAudio: Reinforce
ReadyTextNotification: notification-reinforcements-have-arrived
BlockedAudio: NoRoom
BlockedTextNotification: notification-no-room-for-new-unit
OrderName: ProduceActorPower.Fremen
SupportPowerPaletteOrder: 2040
GrantConditionOnFaction@corrino:
Condition: corrino
Factions: corrino
Production@Corrino:
Produces: sardaukar
RequiresCondition: corrino

View File

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

View File

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

View File

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

View File

@@ -8,6 +8,7 @@
]]
HarkonnenBase = { HConyard, HPower1, HPower2, HBarracks, HOutpost }
HarkonnenBaseAreaTrigger = { CPos.New(31, 37), CPos.New(32, 37), CPos.New(33, 37), CPos.New(34, 37), CPos.New(35, 37), CPos.New(36, 37), CPos.New(37, 37), CPos.New(38, 37), CPos.New(39, 37), CPos.New(40, 37), CPos.New(41, 37), CPos.New(42, 37), CPos.New(42, 38), CPos.New(42, 39), CPos.New(42, 40), CPos.New(42, 41), CPos.New(42, 42), CPos.New(42, 43), CPos.New(42, 44), CPos.New(42, 45), CPos.New(42, 46), CPos.New(42, 47), CPos.New(42, 48), CPos.New(42, 49) }
HarkonnenReinforcements =
@@ -78,6 +79,7 @@ HarkonnenAttackWaves =
}
OrdosReinforcements = { "light_inf", "light_inf", "raider" }
OrdosEntryPath = { OrdosEntry.Location, OrdosRally.Location }
Tick = function()

View File

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

Binary file not shown.

View File

@@ -143,6 +143,19 @@ Actors:
HSilo4: silo
Owner: Harkonnen
Location: 4,60
Actor3: crate
Owner: Neutral
Location: 53,25
Actor9: harvester.debris
Owner: Creeps
Facing: 384
Location: 63,64
Actor10: crate_reveal
Owner: Neutral
Location: 11,35
HPatrolPoint1: waypoint
Owner: Neutral
Location: 32,17
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,9 +22,16 @@ AttackDelays =
}
HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
HarkonnenVehicleTypes = { "trike", "trike", "quad" }
InitAIUnits = function()
Defending[Harkonnen] = { }
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Harkonnen] = true
PatrolPoints[Harkonnen] = { HarkonnenRally3.Location, HPatrolPoint1.Location, Actor6.Location }
DefencePerimeter[Harkonnen] = GetCellsInRectangle(CPos.New(3,42), CPos.New(13,63))
IdlingUnits[Harkonnen] = Reinforcements.Reinforce(Harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath)
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
@@ -37,14 +44,31 @@ ActivateAI = function()
HConyard.Produce(OrdosUpgrades[1])
HConyard.Produce(OrdosUpgrades[2])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function() return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1) end
local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
local vehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
-- Finish the upgrades first before trying to build something
Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Harkonnen, HLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Harkonnen, HLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
if Difficulty ~= "easy" then
Harkonnen.GrantCondition("base-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
}
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
table.insert(HarkonnenBase, building)
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

View File

@@ -8,6 +8,7 @@
]]
HarkonnenBase = { HBarracks, HWindTrap1, HWindTrap2, HLightFactory, HOutpost, HConyard, HRefinery, HSilo1, HSilo2, HSilo3, HSilo4 }
HarkonnenBaseAreaTrigger = { CPos.New(2, 58), CPos.New(3, 58), CPos.New(4, 58), CPos.New(5, 58), CPos.New(6, 58), CPos.New(7, 58), CPos.New(8, 58), CPos.New(9, 58), CPos.New(10, 58), CPos.New(11, 58), CPos.New(12, 58), CPos.New(13, 58), CPos.New(14, 58), CPos.New(15, 58), CPos.New(16, 58), CPos.New(16, 59), CPos.New(16, 60) }
HarkonnenReinforcements =
@@ -65,15 +66,19 @@ HarkonnenPaths =
}
HarkonnenHunters = { "light_inf", "light_inf", "trike", "quad" }
HarkonnenInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
HarkonnenHunterPath = { HarkonnenEntry5.Location, HarkonnenRally5.Location }
HarkonnenInitialPath = { HarkonnenEntry4.Location, HarkonnenRally4.Location }
OrdosReinforcements = { "quad", "raider" }
OrdosPath = { OrdosEntry.Location, OrdosRally.Location }
OrdosBaseBuildings = { "barracks", "light_factory" }
OrdosUpgrades = { "upgrade.barracks", "upgrade.light" }
MessageCheck = function(index)

View File

@@ -1,6 +1,32 @@
Player:
PlayerResources:
DefaultCash: 5000
ExternalCondition@AIMain:
Condition: base-rebuilder
BaseBuilderBotModule@Harkonnen:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
wind_trap: 4
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
World:
LuaScript:

View File

@@ -254,6 +254,16 @@ Actors:
HarkonnenEntry8: waypoint
Owner: Neutral
Location: 2,20
Actor1: harvester.debris
Owner: Creeps
Facing: 384
Location: 30,41
HPatrolPoint1: waypoint
Owner: Neutral
Location: 18,38
HPatrolPoint2: waypoint
Owner: Neutral
Location: 47,21
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(9) },
normal = { DateTime.Seconds(2), DateTime.Seconds(7) },
@@ -22,29 +22,59 @@ AttackDelays =
}
HarkonnenInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
HarkonnenVehicleTypes = { "trike", "trike", "quad" }
InitAIUnits = function()
IdlingUnits[Harkonnen] = Reinforcements.Reinforce(Harkonnen, HarkonnenInitialReinforcements, HarkonnenInitialPath)
DefendAndRepairBase(Harkonnen, HarkonnenBase, 0.75, AttackGroupSize[Difficulty])
end
ActivateAI = function()
Defending[Harkonnen] = {}
AttackDelay[Harkonnen] = 6000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Harkonnen] = 5000 * DifficultyModifier[Difficulty]
LastHarvesterEaten[Harkonnen] = true
HarvesterCount[Harkonnen] = 0
PatrolPoints[Harkonnen] = { HPatrolPoint1.Location, HPatrolPoint2.Location, HarkonnenRally7.Location }
DefencePerimeter[Harkonnen] = Utils.Concat(GetCellsInRectangle(CPos.New(35,37), CPos.New(54,51)), GetCellsInRectangle(CPos.New(45,28), CPos.New(58,36)))
Trigger.AfterDelay(0, InitAIUnits)
HConyard.Produce(OrdosUpgrades[1])
HConyard.Produce(OrdosUpgrades[2])
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
else
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
end
end
local infantryToBuild = function() return { Utils.Random(HarkonnenInfantryTypes) } end
local vehilcesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
local vehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
-- Finish the upgrades first before trying to build something
Trigger.AfterDelay(DateTime.Seconds(14), function()
ProduceUnits(Harkonnen, HBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Harkonnen, HLightFactory, delay, vehilcesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(Harkonnen, HLightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
if Difficulty ~= "easy" then
Harkonnen.GrantCondition("base-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
}
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
table.insert(HarkonnenBase, building)
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

View File

@@ -8,6 +8,7 @@
]]
HarkonnenBase = { HBarracks, HWindTrap1, HWindTrap2, HWindTrap3, HWindTrap4, HLightFactory, HOutpost, HConyard, HRefinery, HSilo1, HSilo2, HSilo3, HSilo4 }
HarkonnenBaseAreaTrigger = { CPos.New(2, 58), CPos.New(3, 58), CPos.New(4, 58), CPos.New(5, 58), CPos.New(6, 58), CPos.New(7, 58), CPos.New(8, 58), CPos.New(9, 58), CPos.New(10, 58), CPos.New(11, 58), CPos.New(12, 58), CPos.New(13, 58), CPos.New(14, 58), CPos.New(15, 58), CPos.New(16, 58), CPos.New(16, 59), CPos.New(16, 60) }
HarkonnenReinforcements =
@@ -79,6 +80,7 @@ HarkonnenHunterPaths =
}
HarkonnenInitialReinforcements = { "light_inf", "light_inf", "quad", "quad", "trike", "trike", "trooper", "trooper" }
HarkonnenInitialPath = { HarkonnenEntry4.Location, HarkonnenRally4.Location }
OrdosReinforcements =
@@ -103,6 +105,7 @@ OrdosReinforcementDelays =
}
OrdosBaseBuildings = { "barracks", "light_factory" }
OrdosUpgrades = { "upgrade.barracks", "upgrade.light" }
MessageCheck = function(index)
@@ -129,7 +132,6 @@ Tick = function()
if DateTime.GameTime % DateTime.Seconds(10) == 0 and LastHarvesterEaten[Harkonnen] then
local units = Harkonnen.GetActorsByType("harvester")
if #units > 0 then
LastHarvesterEaten[Harkonnen] = false
ProtectHarvester(units[1], Harkonnen, AttackGroupSize[Difficulty])

View File

@@ -1,6 +1,32 @@
Player:
PlayerResources:
DefaultCash: 5000
ExternalCondition@AIMain:
Condition: base-rebuilder
BaseBuilderBotModule@Harkonnen:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
wind_trap: 4
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
World:
LuaScript:

View File

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

View File

@@ -14,7 +14,7 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
ProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -24,23 +24,42 @@ AttackDelays =
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
HarkonnenVehicleTypes = { "trike", "trike", "quad" }
HarkonnenTankType = { "combat_tank_h" }
SmugglerVehicleTypes = { "raider", "raider", "quad" }
SmugglerTankType = { "combat_tank_o" }
InitAIUnits = function(house)
LastHarvesterEaten[house] = true
IdlingUnits[house] = Reinforcements.Reinforce(house, InitialReinforcements[house.InternalName], InitialReinforcementsPaths[house.InternalName])
DefendAndRepairBase(house, Base[house.InternalName], 0.75, AttackGroupSize[Difficulty])
end
ActivateAI = function()
Defending[Harkonnen] = { }
Defending[Smuggler] = { }
AttackDelay[Harkonnen] = 7000
AttackDelay[Smuggler] = 7000
TimeBetweenAttacks[Harkonnen] = 8000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[Smuggler] = 15000 * DifficultyModifier[Difficulty]
HarvesterCount[Harkonnen] = 2
HarvesterCount[Smuggler] = 0
PatrolPoints[Harkonnen] = { HPatrolPoint1.Location, HPatrolPoint2.Location, HarkonnenRally2.Location }
DefencePerimeter[Harkonnen] = GetCellsInRectangle(CPos.New(23,3), CPos.New(41,22))
DefencePerimeter[Smuggler] = Utils.Concat(GetCellsInRectangle(CPos.New(57,15), CPos.New(65, 24)), GetCellsInRectangle(CPos.New(43,4), CPos.New(54, 16)))
InitAIUnits(Harkonnen)
InitAIUnits(Smuggler)
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
else
return Utils.RandomInteger(ProductionDelays[Difficulty][1], ProductionDelays[Difficulty][2] + 1)
end
end
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local hVehiclesToBuild = function() return { Utils.Random(HarkonnenVehicleTypes) } end
local hTanksToBuild = function() return HarkonnenTankType end
@@ -55,4 +74,29 @@ ActivateAI = function()
ProduceUnits(Smuggler, SBarracks, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(Smuggler, SLightFactory, delay, sVehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(Smuggler, SHeavyFactory, delay, sTanksToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ActivateCrushLogic()
AIProductionActivated = true
if Difficulty == "normal" then
Harkonnen.GrantCondition("base-rebuilder")
end
if Difficulty == "hard" then
Harkonnen.GrantCondition("defense-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = hVehiclesToBuild,
heavy_factory = hTanksToBuild
}
Trigger.OnBuildingPlaced(Harkonnen, function(p, building)
table.insert(Base[Harkonnen], building)
DefendAndRepairBase(Harkonnen, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(Harkonnen, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end

View File

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

View File

@@ -1,6 +1,64 @@
Player:
PlayerResources:
DefaultCash: 5000
ExternalCondition@AIMain:
Condition: base-rebuilder
ExternalCondition@AIMainDefense:
Condition: defense-rebuilder
BaseBuilderBotModule@Harkonnen:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
wind_trap: 4
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@HarkonnenDefense:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
wind_trap: 4
silo: 1
medium_gun_turret: 3
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
medium_gun_turret: 1
World:
LuaScript:

Binary file not shown.

View File

@@ -570,6 +570,28 @@ Actors:
AtreidesEntry8: waypoint
Owner: Neutral
Location: 2,58
APatrolPoint1: waypoint
Owner: Neutral
Location: 51,17
APatrolPoint2: waypoint
Owner: Neutral
Location: 52,44
Actor1: carryall.debris
Owner: Creeps
Facing: 384
Location: 60,41
Actor2: crate_explosion
Owner: Neutral
Location: 41,60
Actor6: crate_explosion
Owner: Neutral
Location: 42,60
Actor8: crate_explosion
Owner: Neutral
Location: 42,59
Actor7: crate_explosion
Owner: Neutral
Location: 41,59
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

View File

@@ -7,6 +7,31 @@
information, see COPYING.
]]
EarlyGameStage = DateTime.Minutes(5)
InitialProductionDelay = {
AtreidesMain =
{
easy = DateTime.Seconds(130),
normal = DateTime.Seconds(80),
hard = DateTime.Seconds(50)
},
AtreidesSmall1 =
{
easy = DateTime.Seconds(120),
normal = DateTime.Seconds(60),
hard = DateTime.Seconds(30)
},
AtreidesSmall2 =
{
easy = DateTime.Seconds(60),
normal = DateTime.Seconds(30),
hard = DateTime.Seconds(0)
},
}
AttackGroupSize =
{
easy = 6,
@@ -14,7 +39,14 @@ AttackGroupSize =
hard = 10
}
AttackDelays =
EarlyProductionDelays =
{
easy = { DateTime.Seconds(7), DateTime.Seconds(11) },
normal = { DateTime.Seconds(5), DateTime.Seconds(7) },
hard = { DateTime.Seconds(3), DateTime.Seconds(5) }
}
LateProductionDelays =
{
easy = { DateTime.Seconds(4), DateTime.Seconds(7) },
normal = { DateTime.Seconds(2), DateTime.Seconds(5) },
@@ -22,7 +54,9 @@ AttackDelays =
}
EnemyInfantryTypes = { "light_inf", "light_inf", "light_inf", "trooper", "trooper" }
EnemyVehicleTypes = { "trike", "trike", "quad" }
EnemyTankType = { "combat_tank_a" }
InitAIUnits = function(house)
@@ -37,21 +71,60 @@ InitAIUnits = function(house)
end
ActivateAIProduction = function()
local delay = function() return Utils.RandomInteger(AttackDelays[Difficulty][1], AttackDelays[Difficulty][2] + 1) end
local delay = function(player)
if EmergencyBuildRate[player] and Difficulty ~= "easy" then
return 1
end
if EarlyGameStage >= DateTime.GameTime then
return Utils.RandomInteger(EarlyProductionDelays[Difficulty][1], EarlyProductionDelays[Difficulty][2] + 1)
else
return Utils.RandomInteger(LateProductionDelays[Difficulty][1], LateProductionDelays[Difficulty][2] + 1)
end
end
local infantryToBuild = function() return { Utils.Random(EnemyInfantryTypes) } end
local vehiclesToBuild = function() return { Utils.Random(EnemyVehicleTypes) } end
local tanksToBuild = function() return EnemyTankType end
local attackTresholdSize = AttackGroupSize[Difficulty] * 2.5
local attackThresholdSize = AttackGroupSize[Difficulty] * 2.5
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(AtreidesMain, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
ProduceUnits(AtreidesMain, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesMain"][Difficulty], function()
ProduceUnits(AtreidesMain, ABarracks1, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, ALightFactory, delay, vehiclesToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
ProduceUnits(AtreidesMain, AHeavyFactory, delay, tanksToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
ProduceUnits(AtreidesSmall1, ABarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall1"][Difficulty], function()
ProduceUnits(AtreidesSmall1, ABarracks2, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
ProduceUnits(AtreidesSmall2, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackTresholdSize)
Trigger.AfterDelay(InitialProductionDelay["AtreidesSmall2"][Difficulty], function()
ProduceUnits(AtreidesSmall2, ABarracks3, delay, infantryToBuild, AttackGroupSize[Difficulty], attackThresholdSize)
end)
ActivateCrushLogic()
AIProductionActivated = true
if Difficulty == "normal" then
AtreidesMain.GrantCondition("base-rebuilder")
end
if Difficulty == "hard" then
AtreidesMain.GrantCondition("defense-rebuilder")
end
local productionTypes =
{
barracks = infantryToBuild,
light_factory = vehiclesToBuild,
heavy_factory = tanksToBuild
}
Trigger.OnBuildingPlaced(AtreidesMain, function(p, building)
table.insert(Base[AtreidesMainBase], building)
DefendAndRepairBase(AtreidesMain, {building}, 0.75, AttackGroupSize[Difficulty] )
if productionTypes[building.Type] == nil then return end
ProduceUnits(AtreidesMain, building, delay, productionTypes[building.Type], AttackGroupSize[Difficulty], attackThresholdSize)
end)
end
ActivateAI = function()
@@ -59,4 +132,19 @@ ActivateAI = function()
InitAIUnits(AtreidesSmall1)
InitAIUnits(AtreidesSmall2)
InitAIUnits(AtreidesSmall3)
Defending[AtreidesMain] = {}
Defending[AtreidesSmall1] = {}
Defending[AtreidesSmall2] = {}
Defending[AtreidesSmall3] = {}
AttackDelay[AtreidesMain] = 14000 * DifficultyModifier[Difficulty]
AttackDelay[AtreidesSmall1] = 14000 * DifficultyModifier[Difficulty]
AttackDelay[AtreidesSmall2] = 14000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[AtreidesMain] = 7000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[AtreidesSmall1] = 9000 * DifficultyModifier[Difficulty]
TimeBetweenAttacks[AtreidesSmall2] = 9000 * DifficultyModifier[Difficulty]
HarvesterCount[AtreidesMain] = 2
PatrolPoints[AtreidesMain] = { APatrolPoint1.Location, APatrolPoint2.Location, AtreidesRally8.Location }
DefencePerimeter[AtreidesMain] = GetCellsInRectangle(CPos.New(3,3), CPos.New(18,27))
DefencePerimeter[AtreidesSmall1] = GetCellsInRectangle(CPos.New(29,17), CPos.New(34,29))
DefencePerimeter[AtreidesSmall2] = GetCellsInRectangle(CPos.New(39,46), CPos.New(48,59))
end

View File

@@ -109,6 +109,16 @@ CheckHarvester = function(house)
end
CachedResources = -1
EmergencyBehaviour = function(player, target)
HoldProduction[player] = false
if Difficulty == "hard" then
player.Cash = player.Cash + 2000
end
if player == AtreidesSmall2 and #IdlingUnits[AtreidesMain] > 10 then
CheckArea(AtreidesMain, target, 10)
end
end
Tick = function()
if Ordos.Resources > SpiceToHarvest - 1 then
Ordos.MarkCompletedObjective(GatherSpice)
@@ -215,11 +225,13 @@ WorldLoaded = function()
APower9.Sell()
end
end)
Trigger.OnKilledOrCaptured(APower8, function()
if not AIProductionActivated then
ActivateAIProduction()
end
end)
Trigger.OnKilledOrCaptured(APower9, function()
if not AIProductionActivated then
ActivateAIProduction()

View File

@@ -1,6 +1,64 @@
Player:
PlayerResources:
DefaultCash: 6000
ExternalCondition@AIMain:
Condition: base-rebuilder
ExternalCondition@AIMainDefense:
Condition: defense-rebuilder
BaseBuilderBotModule@AtriedesMain:
RequiresCondition: base-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret,large_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
wind_trap: 3
silo: 1
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
BaseBuilderBotModule@AtriedesMainDefense:
RequiresCondition: defense-rebuilder
BuildingQueues: Building, Upgrade
MinimumExcessPower: 0
MaximumExcessPower: 250
MaxBaseRadius: 40
ConstructionYardTypes: construction_yard
RefineryTypes: refinery
PowerTypes: wind_trap
ProductionTypes: light_factory, heavy_factory, barracks
SiloTypes: silo
DefenseTypes: medium_gun_turret
SellRefineryInterval: -1
BuildingLimits:
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
wind_trap: 3
silo: 1
medium_gun_turret: 5
BuildingFractions:
wind_trap: 1
barracks: 1
refinery: 1
light_factory: 1
heavy_factory: 1
medium_gun_turret: 1
World:
LuaScript:

View File

@@ -576,6 +576,25 @@ Actors:
HarkonnenEntry7: waypoint
Owner: Neutral
Location: 34,2
APatrolPoint1: waypoint
Owner: Neutral
Location: 46,7
APatrolPoint2: waypoint
Owner: Neutral
Location: 10,45
HPatrolPoint1: waypoint
Owner: Neutral
Location: 40,49
HPatrolPoint2: waypoint
Owner: Neutral
Location: 62,76
Actor2: frigate.debris
Owner: Creeps
Location: 73,55
Actor1: missile_tank.debris
Owner: Creeps
Facing: 384
Location: 72,53
Rules: d2k|rules/campaign-rules.yaml, d2k|rules/campaign-tooltips.yaml, d2k|rules/campaign-palettes.yaml, rules.yaml

Some files were not shown because too many files have changed in this diff Show More