diff --git a/mods/d2k/maps/harkonnen-01a/harkonnen01a.lua b/mods/d2k/maps/harkonnen-01a/harkonnen01a.lua new file mode 100644 index 0000000000..d0214bd486 --- /dev/null +++ b/mods/d2k/maps/harkonnen-01a/harkonnen01a.lua @@ -0,0 +1,157 @@ + +AtreidesReinforcements = { } +AtreidesReinforcements["easy"] = +{ + { "light_inf", "light_inf" } +} + +AtreidesReinforcements["normal"] = +{ + { "light_inf", "light_inf" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, +} + +AtreidesReinforcements["hard"] = +{ + { "light_inf", "light_inf" }, + { "trike", "trike" }, + { "light_inf", "light_inf", "light_inf" }, + { "light_inf", "trike" }, + { "trike", "trike" } +} + +AtreidesEntryWaypoints = { AtreidesWaypoint1.Location, AtreidesWaypoint2.Location, AtreidesWaypoint3.Location, AtreidesWaypoint4.Location } +AtreidesAttackDelay = DateTime.Seconds(30) + +AtreidesAttackWaves = { } +AtreidesAttackWaves["easy"] = 1 +AtreidesAttackWaves["normal"] = 5 +AtreidesAttackWaves["hard"] = 12 + +ToHarvest = { } +ToHarvest["easy"] = 2500 +ToHarvest["normal"] = 3000 +ToHarvest["hard"] = 3500 + +HarkonnenReinforcements = { "light_inf", "light_inf", "light_inf", "trike" } +HarkonnenEntryPath = { HarkonnenWaypoint.Location, HarkonnenRally.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 AtreidesArrived and atreides.HasNoRequiredUnits() then + player.MarkCompletedObjective(KillAtreides) + 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("Harkonnen") + atreides = Player.GetPlayer("Atreides") + + InitObjectives() + + Trigger.OnRemovedFromWorld(HarkonnenConyard, function() + local refs = Utils.Where(Map.ActorsInWorld, function(actor) return actor.Type == "refinery" end) + + if #refs == 0 then + atreides.MarkCompletedObjective(KillHarkonnen) + else + Trigger.OnAllRemovedFromWorld(refs, function() + atreides.MarkCompletedObjective(KillHarkonnen) + end) + end + end) + + Media.DisplayMessage(Messages[1], "Mentat") + + Trigger.AfterDelay(DateTime.Seconds(25), function() + Media.PlaySpeechNotification(player, "Reinforce") + Reinforcements.Reinforce(player, HarkonnenReinforcements, HarkonnenEntryPath) + end) + + WavesLeft = AtreidesAttackWaves[Map.LobbyOption("difficulty")] + SendReinforcements() +end + +SendReinforcements = function() + local units = AtreidesReinforcements[Map.LobbyOption("difficulty")] + local delay = Utils.RandomInteger(AtreidesAttackDelay - DateTime.Seconds(2), AtreidesAttackDelay) + AtreidesAttackDelay = AtreidesAttackDelay - (#units * 3 - 3 - WavesLeft) * DateTime.Seconds(1) + if AtreidesAttackDelay < 0 then AtreidesAttackDelay = 0 end + + Trigger.AfterDelay(delay, function() + Reinforcements.Reinforce(atreides, Utils.Random(units), { Utils.Random(AtreidesEntryWaypoints) }, 10, IdleHunt) + + WavesLeft = WavesLeft - 1 + if WavesLeft == 0 then + Trigger.AfterDelay(DateTime.Seconds(1), function() AtreidesArrived = 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) + + KillHarkonnen = atreides.AddPrimaryObjective("Kill all Harkonnen units.") + GatherSpice = player.AddPrimaryObjective("Harvest " .. tostring(ToHarvest[Map.LobbyOption("difficulty")]) .. " Solaris worth of Spice.") + KillAtreides = player.AddSecondaryObjective("Eliminate all Atreides 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/harkonnen-01a/map.bin b/mods/d2k/maps/harkonnen-01a/map.bin new file mode 100644 index 0000000000..a673ff9391 Binary files /dev/null and b/mods/d2k/maps/harkonnen-01a/map.bin differ diff --git a/mods/d2k/maps/harkonnen-01a/map.png b/mods/d2k/maps/harkonnen-01a/map.png new file mode 100644 index 0000000000..e1747f1861 Binary files /dev/null and b/mods/d2k/maps/harkonnen-01a/map.png differ diff --git a/mods/d2k/maps/harkonnen-01a/map.yaml b/mods/d2k/maps/harkonnen-01a/map.yaml new file mode 100644 index 0000000000..8590dba5b0 --- /dev/null +++ b/mods/d2k/maps/harkonnen-01a/map.yaml @@ -0,0 +1,109 @@ +MapFormat: 11 + +RequiresMod: d2k + +Title: Harkonnen 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 + PlayerReference@Harkonnen: + Name: Harkonnen + Playable: True + LockFaction: True + Faction: harkonnen + LockColor: True + Color: FE0000 + Enemies: Atreides, Creeps + PlayerReference@Atreides: + Name: Atreides + LockFaction: True + Faction: atreides + LockColor: True + Color: 9191FF + Enemies: Harkonnen + +Actors: + Actor0: light_inf + Location: 7,2 + Owner: Atreides + Actor1: light_inf + Location: 14,3 + Owner: Atreides + Actor2: light_inf + Location: 21,3 + Owner: Atreides + Actor3: wormspawner + Location: 18,4 + Owner: Creeps + Actor4: light_inf + Location: 21,6 + Owner: Atreides + Actor5: light_inf + Location: 5,10 + Owner: Harkonnen + Actor6: light_inf + Location: 8,12 + Owner: Harkonnen + HarkonnenConyard: construction_yard + Location: 7,14 + Owner: Harkonnen + Actor8: light_inf + Location: 13,14 + Owner: Harkonnen + Actor9: trike + Location: 4,16 + Owner: Harkonnen + Actor10: light_inf + Location: 12,17 + Owner: Harkonnen + Actor11: light_inf + Location: 7,18 + Owner: Harkonnen + Actor12: trike + Location: 11,19 + Owner: Harkonnen + Actor13: light_inf + Location: 28,19 + Owner: Atreides + HarkonnenRally: waypoint + Owner: Neutral + Location: 12,12 + HarkonnenWaypoint: waypoint + Owner: Neutral + Location: 2,12 + AtreidesWaypoint1: waypoint + Owner: Neutral + Location: 20,2 + AtreidesWaypoint2: waypoint + Owner: Neutral + Location: 18,25 + AtreidesWaypoint3: waypoint + Owner: Neutral + Location: 29,21 + AtreidesWaypoint4: waypoint + Owner: Neutral + Location: 29,7 + +Rules: d2k|rules/campaign-rules.yaml, rules.yaml diff --git a/mods/d2k/maps/harkonnen-01a/rules.yaml b/mods/d2k/maps/harkonnen-01a/rules.yaml new file mode 100644 index 0000000000..4b3ea5f422 --- /dev/null +++ b/mods/d2k/maps/harkonnen-01a/rules.yaml @@ -0,0 +1,48 @@ +Player: + PlayerResources: + DefaultCash: 2300 + +World: + LuaScript: + Scripts: harkonnen01a.lua + MissionData: + Briefing: Mine the Spice from the Imperial Basin, before the Atreides try to seize the area. Execute anyone who tries to stop you.\n\nBuild Silos to store the Spice. Remember to place buildings on concrete foundations to prevent erosion and gradual decline. To build without concrete would be inefficient. Inefficiency will not be tolerated.\n + BriefingVideo: H_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 c10b6460ee..b65883a8e6 100644 --- a/mods/d2k/missions.yaml +++ b/mods/d2k/missions.yaml @@ -8,4 +8,7 @@ Atreides Campaign: Ordos Campaign: ./mods/d2k/maps/ordos-01a - ./mods/d2k/maps/ordos-01b \ No newline at end of file + ./mods/d2k/maps/ordos-01b + +Harkonnen Campaign: + ./mods/d2k/maps/harkonnen-01a