diff --git a/mods/vinylgod/fluent/lua.ftl b/mods/vinylgod/fluent/lua.ftl new file mode 100644 index 0000000..55344e7 --- /dev/null +++ b/mods/vinylgod/fluent/lua.ftl @@ -0,0 +1,7 @@ +new-objective = New objective +objective-completed = Objective completed +objective-failed = Objective failed + +press-first-records = Build a Pressing Plant and bank 2000 records +survive-the-probe = Survive the Stream's survey probe +keep-the-van-alive = Do not lose the Pop-Up Shop diff --git a/mods/vinylgod/maps/m01/m01.lua b/mods/vinylgod/maps/m01/m01.lua new file mode 100644 index 0000000..56b1db6 --- /dev/null +++ b/mods/vinylgod/maps/m01/m01.lua @@ -0,0 +1,46 @@ +-- 01: FIRST PRESSING + +TARGET_RECORDS = 2000 +PROBE_DELAY = DateTime.Minutes(4) + +WorldLoaded = function() + -- do NOT shadow the `Player` global: Player.GetPlayer is still needed below + Mrp = Player.GetPlayer("Player") + Stream = Player.GetPlayer("Enemy") + InitObjectives(Mrp) + + PressObjective = Mrp.AddPrimaryObjective("press-first-records") + VanObjective = Mrp.AddSecondaryObjective("keep-the-van-alive") + + -- lose the HQ, lose the secondary + local hq = Utils.Where(Map.ActorsInWorld, function(a) + return a.Owner == Mrp and (a.Type == "popupvan" or a.Type == "popupshop") + end) + if #hq > 0 then + Trigger.OnAllKilled(hq, function() + Mrp.MarkFailedObjective(VanObjective) + end) + end + + -- the probe + Trigger.AfterDelay(PROBE_DELAY, function() + Media.PlaySpeechNotification(Mrp, "BaseAttack") + Utils.Do(Map.ActorsInWorld, function(a) + if a.Owner == Stream and a.HasProperty("Hunt") then + a.Hunt() + end + end) + end) +end + +Tick = function() + if PressObjective ~= nil and not Mrp.IsObjectiveCompleted(PressObjective) then + local banked = Mrp.Cash + Mrp.Resources + local plants = Utils.Where(Map.ActorsInWorld, function(a) + return a.Owner == Mrp and a.Type == "pressplant" + end) + if #plants > 0 and banked >= TARGET_RECORDS then + Mrp.MarkCompletedObjective(PressObjective) + end + end +end diff --git a/mods/vinylgod/maps/m01/map.bin b/mods/vinylgod/maps/m01/map.bin new file mode 100644 index 0000000..c452a99 Binary files /dev/null and b/mods/vinylgod/maps/m01/map.bin differ diff --git a/mods/vinylgod/maps/m01/map.png b/mods/vinylgod/maps/m01/map.png new file mode 100644 index 0000000..732388a Binary files /dev/null and b/mods/vinylgod/maps/m01/map.png differ diff --git a/mods/vinylgod/maps/m01/map.yaml b/mods/vinylgod/maps/m01/map.yaml new file mode 100644 index 0000000..b490ef0 --- /dev/null +++ b/mods/vinylgod/maps/m01/map.yaml @@ -0,0 +1,94 @@ +MapFormat: 12 + +RequiresMod: vinylgod + +Title: 01 - First Pressing + +Author: Monster Robot Party + +Tileset: VINYLGOD + +MapSize: 50,50 + +Bounds: 1,1,48,48 + +Visibility: MissionSelector + +Categories: Campaign + +LockPreview: True + +Players: + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Faction: vinylgod + PlayerReference@Player: + Name: Player + Playable: True + Required: True + AllowBots: False + LockFaction: True + Faction: vinylgod + LockSpawn: True + LockTeam: True + Enemies: Enemy + PlayerReference@Enemy: + Name: Enemy + Faction: stream + Enemies: Player + +Actors: + spawn0: mpspawn + Owner: Neutral + Location: 9,38 + van: popupvan + Owner: Player + Location: 9,38 + dig: digger + Owner: Player + Location: 12,38 + grunt1: djgrunt + Owner: Player + Location: 11,41 + grunt2: djgrunt + Owner: Player + Location: 12,41 + outpost: transcoder + Owner: Enemy + Location: 38,9 + pods: podfarm + Owner: Enemy + Location: 41,12 + node: datacentre + Owner: Enemy + Location: 36,12 + probe1: bufferbot + Owner: Enemy + Location: 38,14 + probe2: bufferbot + Owner: Enemy + Location: 39,14 + probe3: bufferbot + Owner: Enemy + Location: 40,14 + probe4: crawler + Owner: Enemy + Location: 37,15 + waxseed0: waxseed + Owner: Neutral + Location: 9,43 + waxseed1: waxseed + Owner: Neutral + Location: 14,34 + waxseed2: waxseed + Owner: Neutral + Location: 25,25 + waxseed3: waxseed + Owner: Neutral + Location: 40,14 + +Rules: vinylgod|rules/campaign.yaml, rules.yaml + +FluentMessages: vinylgod|fluent/lua.ftl diff --git a/mods/vinylgod/maps/m01/rules.yaml b/mods/vinylgod/maps/m01/rules.yaml new file mode 100644 index 0000000..087279c --- /dev/null +++ b/mods/vinylgod/maps/m01/rules.yaml @@ -0,0 +1,5 @@ +world: + LuaScript: + Scripts: campaign.lua, m01.lua + MissionData: + Briefing: The Party wakes up in the landfill with a van, a digger and a wax field.\n\nGet a Pressing Plant running and bank 2000 records before the Stream finishes counting what is down here.\n\nThey will send a probe. They always send a probe. diff --git a/mods/vinylgod/missions/vinylgod.yaml b/mods/vinylgod/missions/vinylgod.yaml index e69de29..0ad0cfb 100644 --- a/mods/vinylgod/missions/vinylgod.yaml +++ b/mods/vinylgod/missions/vinylgod.yaml @@ -0,0 +1,2 @@ +SIDE A - Monster Robot Party: + m01 diff --git a/mods/vinylgod/mod.yaml b/mods/vinylgod/mod.yaml index 86c0dab..f0b997c 100644 --- a/mods/vinylgod/mod.yaml +++ b/mods/vinylgod/mod.yaml @@ -8,6 +8,7 @@ FileSystem: DefaultFileSystem ^EngineDir $vinylgod: vinylgod ^EngineDir|mods/common: common + vinylgod|scripts MapFolders: vinylgod|maps: System diff --git a/mods/vinylgod/rules/campaign.yaml b/mods/vinylgod/rules/campaign.yaml new file mode 100644 index 0000000..902df9c --- /dev/null +++ b/mods/vinylgod/rules/campaign.yaml @@ -0,0 +1,10 @@ +# Applied by campaign maps on top of the standard rules. +player: + -ConquestVictoryConditions: + MissionObjectives: + EarlyGameOver: true + GameOverDelay: 3000 + +world: + ObjectivesPanel: + PanelName: MISSION_OBJECTIVES diff --git a/mods/vinylgod/rules/world.yaml b/mods/vinylgod/rules/world.yaml index f95520a..b0cd3e9 100644 --- a/mods/vinylgod/rules/world.yaml +++ b/mods/vinylgod/rules/world.yaml @@ -46,6 +46,8 @@ world: PathFinder: MapOptions: ScriptTriggers: + ObjectivesPanel: + PanelName: SKIRMISH_STATS Locomotor@WHEELED: Name: wheeled TerrainSpeeds: diff --git a/mods/vinylgod/scripts/campaign.lua b/mods/vinylgod/scripts/campaign.lua new file mode 100644 index 0000000..e2c8508 --- /dev/null +++ b/mods/vinylgod/scripts/campaign.lua @@ -0,0 +1,26 @@ +-- Shared campaign helpers for SIDE A. Mirrors the engine's campaign.lua shape. + +InitObjectives = function(player) + Trigger.OnObjectiveAdded(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), + UserInterface.GetFluentMessage("new-objective")) + end) + Trigger.OnObjectiveCompleted(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), + UserInterface.GetFluentMessage("objective-completed")) + end) + Trigger.OnObjectiveFailed(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), + UserInterface.GetFluentMessage("objective-failed")) + end) + Trigger.OnPlayerWon(player, function() + Trigger.AfterDelay(DateTime.Seconds(1), function() + Media.PlaySpeechNotification(player, "Win") + end) + end) + Trigger.OnPlayerLost(player, function() + Trigger.AfterDelay(DateTime.Seconds(1), function() + Media.PlaySpeechNotification(player, "Lose") + end) + end) +end diff --git a/tools/gen_mission.py b/tools/gen_mission.py new file mode 100644 index 0000000..6776b57 --- /dev/null +++ b/tools/gen_mission.py @@ -0,0 +1,102 @@ +#!/usr/bin/env python3 +"""Generate campaign mission 01 — FIRST PRESSING (map.bin + map.yaml + preview).""" +import os, struct +from PIL import Image + +SIZE = 48 +W = H = SIZE + 2 +MAP = os.path.join(os.path.dirname(__file__), '..', 'mods', 'vinylgod', 'maps', 'm01') +os.makedirs(MAP, exist_ok=True) + +WAX = [(14, 34, 5), (9, 43, 4), (25, 25, 5), (40, 14, 4)] + +data = bytearray() +data += struct.pack('