diff --git a/mods/d2k/maps/ordos-01a/map.bin b/mods/d2k/maps/ordos-01a/map.bin new file mode 100644 index 0000000000..9405c47fb1 Binary files /dev/null and b/mods/d2k/maps/ordos-01a/map.bin differ diff --git a/mods/d2k/maps/ordos-01a/map.png b/mods/d2k/maps/ordos-01a/map.png new file mode 100644 index 0000000000..a4a6fccea2 Binary files /dev/null and b/mods/d2k/maps/ordos-01a/map.png differ diff --git a/mods/d2k/maps/ordos-01a/map.yaml b/mods/d2k/maps/ordos-01a/map.yaml new file mode 100644 index 0000000000..dacd34c526 --- /dev/null +++ b/mods/d2k/maps/ordos-01a/map.yaml @@ -0,0 +1,104 @@ +MapFormat: 11 + +RequiresMod: d2k + +Title: Ordos 01a + +Author: Westwood Studios + +Tileset: ARRAKIS + +MapSize: 32,28 + +Bounds: 2,2,28,24 + +Visibility: MissionSelector + +Categories: Campaign + +LockPreview: True + +Players: + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Faction: Random + PlayerReference@Creeps: + Name: Creeps + NonCombatant: True + Faction: Random + Enemies: Ordos, Harkonnen + PlayerReference@Ordos: + Name: Ordos + Playable: True + LockFaction: True + Faction: ordos + LockColor: True + Color: B3EAA5 + Enemies: Harkonnen, Creeps + PlayerReference@Harkonnen: + Name: Harkonnen + LockFaction: True + Faction: harkonnen + LockColor: True + Color: FE0000 + Enemies: Ordos + +Actors: + Actor0: light_inf + Location: 2,2 + Owner: Harkonnen + Actor1: light_inf + Location: 14,3 + Owner: Harkonnen + Actor2: wormspawner + Location: 21,4 + Owner: Creeps + Actor3: light_inf + Location: 18,5 + Owner: Harkonnen + Actor4: light_inf + Location: 21,7 + Owner: Harkonnen + Actor5: light_inf + Location: 7,10 + Owner: Ordos + Actor6: light_inf + Location: 12,11 + Owner: Ordos + Actor7: raider + Location: 5,12 + Owner: Ordos + Actor8: raider + Location: 10,12 + Owner: Ordos + OrdosConyard: construction_yard + Location: 9,13 + Owner: Ordos + Actor10: light_inf + Location: 6,15 + Owner: Ordos + Actor11: light_inf + Location: 12,15 + Owner: Ordos + Actor12: light_inf + Location: 26,17 + Owner: Harkonnen + OrdosRally: waypoint + Owner: Neutral + Location: 13,14 + OrdosWaypoint: waypoint + Owner: Neutral + Location: 2,14 + HarkonnenWaypoint1: waypoint + Owner: Neutral + Location: 2,2 + HarkonnenWaypoint2: waypoint + Owner: Neutral + Location: 20,2 + HarkonnenWaypoint3: waypoint + Owner: Neutral + Location: 29,15 + +Rules: d2k|rules/campaign-rules.yaml, rules.yaml diff --git a/mods/d2k/maps/ordos-01a/ordos01a.lua b/mods/d2k/maps/ordos-01a/ordos01a.lua new file mode 100644 index 0000000000..57f6a196be --- /dev/null +++ b/mods/d2k/maps/ordos-01a/ordos01a.lua @@ -0,0 +1,157 @@ + +HarkonnenReinforcements = { } +HarkonnenReinforcements["easy"] = +{ + { "light_inf", "light_inf" } +} + +HarkonnenReinforcements["normal"] = +{ + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, +} + +HarkonnenReinforcements["hard"] = +{ + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } +} + +HarkonnenEntryWaypoints = { HarkonnenWaypoint1.Location, HarkonnenWaypoint2.Location, HarkonnenWaypoint3.Location } +HarkonnenAttackDelay = DateTime.Seconds(30) + +HarkonnenAttackWaves = { } +HarkonnenAttackWaves["easy"] = 1 +HarkonnenAttackWaves["normal"] = 5 +HarkonnenAttackWaves["hard"] = 12 + +ToHarvest = { } +ToHarvest["easy"] = 2500 +ToHarvest["normal"] = 3000 +ToHarvest["hard"] = 3500 + +OrdosReinforcements = { "light_inf", "light_inf", "light_inf", "light_inf", "raider" } +OrdosEntryPath = { OrdosWaypoint.Location, OrdosRally.Location } + +Messages = +{ + "Build a concrete foundation before placing your buildings.", + "Build a Wind Trap for power.", + "Build a Refinery to collect Spice.", + "Build a Silo to store additional Spice." +} + + +IdleHunt = function(actor) + if not actor.IsDead then + Trigger.OnIdle(actor, actor.Hunt) + end +end + +Tick = function() + if HarkonnenArrived and harkonnen.HasNoRequiredUnits() then + player.MarkCompletedObjective(KillHarkonnen) + end + + if player.Resources > ToHarvest[Map.LobbyOption("difficulty")] - 1 then + player.MarkCompletedObjective(GatherSpice) + end + + -- player has no Wind Trap + if (player.PowerProvided <= 20 or player.PowerState ~= "Normal") and DateTime.GameTime % DateTime.Seconds(32) == 0 then + HasPower = false + Media.DisplayMessage(Messages[2], "Mentat") + else + HasPower = true + end + + -- player has no Refinery and no Silos + if HasPower and player.ResourceCapacity == 0 and DateTime.GameTime % DateTime.Seconds(32) == 0 then + Media.DisplayMessage(Messages[3], "Mentat") + end + + if HasPower and player.Resources > player.ResourceCapacity * 0.8 and DateTime.GameTime % DateTime.Seconds(32) == 0 then + Media.DisplayMessage(Messages[4], "Mentat") + end + + UserInterface.SetMissionText("Harvested resources: " .. player.Resources .. "/" .. ToHarvest[Map.LobbyOption("difficulty")], player.Color) +end + +WorldLoaded = function() + player = Player.GetPlayer("Ordos") + harkonnen = Player.GetPlayer("Harkonnen") + + InitObjectives() + + Trigger.OnRemovedFromWorld(OrdosConyard, function() + local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" end) + + if #refs == 0 then + harkonnen.MarkCompletedObjective(KillOrdos) + else + Trigger.OnAllRemovedFromWorld(refs, function() + harkonnen.MarkCompletedObjective(KillOrdos) + end) + end + end) + + Media.DisplayMessage(Messages[1], "Mentat") + + Trigger.AfterDelay(DateTime.Seconds(25), function() + Media.PlaySpeechNotification(player, "Reinforce") + Reinforcements.Reinforce(player, OrdosReinforcements, OrdosEntryPath) + end) + + WavesLeft = HarkonnenAttackWaves[Map.LobbyOption("difficulty")] + SendReinforcements() +end + +SendReinforcements = function() + local units = HarkonnenReinforcements[Map.LobbyOption("difficulty")] + local delay = Utils.RandomInteger(HarkonnenAttackDelay - DateTime.Seconds(2), HarkonnenAttackDelay) + HarkonnenAttackDelay = HarkonnenAttackDelay - (#units * 3 - 3 - WavesLeft) * DateTime.Seconds(1) + if HarkonnenAttackDelay < 0 then HarkonnenAttackDelay = 0 end + + Trigger.AfterDelay(delay, function() + Reinforcements.Reinforce(harkonnen, Utils.Random(units), { Utils.Random(HarkonnenEntryWaypoints) }, 10, IdleHunt) + + WavesLeft = WavesLeft - 1 + if WavesLeft == 0 then + Trigger.AfterDelay(DateTime.Seconds(1), function() HarkonnenArrived = true end) + else + SendReinforcements() + end + end) +end + +InitObjectives = function() + Trigger.OnObjectiveAdded(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "New " .. string.lower(p.GetObjectiveType(id)) .. " objective") + end) + + KillOrdos = harkonnen.AddPrimaryObjective("Kill all Ordos units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") + KillHarkonnen = player.AddSecondaryObjective("Eliminate all Harkonnen units and reinforcements\nin the area.") + + Trigger.OnObjectiveCompleted(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") + end) + Trigger.OnObjectiveFailed(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") + end) + + Trigger.OnPlayerLost(player, function() + Trigger.AfterDelay(DateTime.Seconds(1), function() + Media.PlaySpeechNotification(player, "Lose") + end) + end) + Trigger.OnPlayerWon(player, function() + Trigger.AfterDelay(DateTime.Seconds(1), function() + Media.PlaySpeechNotification(player, "Win") + end) + end) +end diff --git a/mods/d2k/maps/ordos-01a/rules.yaml b/mods/d2k/maps/ordos-01a/rules.yaml new file mode 100644 index 0000000000..39fbd235e9 --- /dev/null +++ b/mods/d2k/maps/ordos-01a/rules.yaml @@ -0,0 +1,48 @@ +Player: + PlayerResources: + DefaultCash: 2300 + +World: + LuaScript: + Scripts: ordos01a.lua + MissionData: + Briefing: Spice is wealth. Serve the Ordos by harvesting Spice in the Imperial Basin. If Harkonnen forces attempt to interrupt the flow of the Spice - neutralize them.\n\nEfficiency dictates that Silos must be built to avoid loss of Spice. Build concrete foundations to avoid unnecessary damage from the elements. To do otherwise is wasteful. + BriefingVideo: O_BR01_E.VQA + MapOptions: + TechLevel: low + ScriptLobbyDropdown@difficulty: + ID: difficulty + Label: Difficulty + Values: + easy: Easy + normal: Normal + hard: Hard + Default: easy + +construction_yard: + Production: + Produces: Building + +concreteb: + Buildable: + Prerequisites: ~disabled + +barracks: + Buildable: + Prerequisites: ~disabled + +light_factory: + Buildable: + Prerequisites: ~disabled + +heavy_factory: + Buildable: + Prerequisites: ~disabled + +medium_gun_turret: + Buildable: + Prerequisites: ~disabled + +wall: + Buildable: + Prerequisites: ~disabled diff --git a/mods/d2k/missions.yaml b/mods/d2k/missions.yaml index f4724468cb..aa09c0c8e8 100644 --- a/mods/d2k/missions.yaml +++ b/mods/d2k/missions.yaml @@ -5,3 +5,6 @@ Atreides Campaign: ./mods/d2k/maps/atreides-02b ./mods/d2k/maps/atreides-03a ./mods/d2k/maps/atreides-03b + +Ordos Campaign: + ./mods/d2k/maps/ordos-01a \ No newline at end of file