From b18c2fe85529d0fb88e2e966d7ce59b9d5223c21 Mon Sep 17 00:00:00 2001 From: JovialFeline Date: Sat, 3 Jun 2023 15:02:37 -0400 Subject: [PATCH] Add Mousetrap (scu33ea). --- mods/ra/languages/lua/en.ftl | 5 + mods/ra/maps/mousetrap/map.bin | Bin 0 -> 81937 bytes mods/ra/maps/mousetrap/map.png | Bin 0 -> 27168 bytes mods/ra/maps/mousetrap/map.yaml | 754 ++++++++++++++++++ mods/ra/maps/mousetrap/mousetrap.lua | 924 ++++++++++++++++++++++ mods/ra/maps/mousetrap/notifications.yaml | 12 + mods/ra/maps/mousetrap/rules.yaml | 142 ++++ mods/ra/maps/mousetrap/weapons.yaml | 11 + mods/ra/missions.yaml | 1 + 9 files changed, 1849 insertions(+) create mode 100644 mods/ra/maps/mousetrap/map.bin create mode 100644 mods/ra/maps/mousetrap/map.png create mode 100644 mods/ra/maps/mousetrap/map.yaml create mode 100644 mods/ra/maps/mousetrap/mousetrap.lua create mode 100644 mods/ra/maps/mousetrap/notifications.yaml create mode 100644 mods/ra/maps/mousetrap/rules.yaml create mode 100644 mods/ra/maps/mousetrap/weapons.yaml diff --git a/mods/ra/languages/lua/en.ftl b/mods/ra/languages/lua/en.ftl index add58940c4..3845d57a0d 100644 --- a/mods/ra/languages/lua/en.ftl +++ b/mods/ra/languages/lua/en.ftl @@ -209,6 +209,11 @@ find-outpost-and-repair = Find our outpost and start repairs on it. evacuate-civilian-hospital = Evacuate all civilians from the hospital. demitri-extracted-super-tanks-destroyed = Dr. Demitri has been extracted and the super tanks have been dealt with. +## mousetrap +all-engineers-killed = All engineers were killed. +kill-stavros = Kill Stavros. +sabotage-facility = Sabotage the facility with our engineers. + ## production-disruption, shock-therapy capture-enemy-radar-dome = Capture the enemy radar dome. diff --git a/mods/ra/maps/mousetrap/map.bin b/mods/ra/maps/mousetrap/map.bin new file mode 100644 index 0000000000000000000000000000000000000000..30e6f0da2eaab9f107ed199f81f77674970a9a88 GIT binary patch literal 81937 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 E1=*f{C;$Ke literal 0 HcmV?d00001 diff --git a/mods/ra/maps/mousetrap/map.png b/mods/ra/maps/mousetrap/map.png new file mode 100644 index 0000000000000000000000000000000000000000..dc774179f296c621a99a786eb1c1fecf3b7d0e1f GIT binary patch literal 27168 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 AG5`Po literal 0 HcmV?d00001 diff --git a/mods/ra/maps/mousetrap/map.yaml b/mods/ra/maps/mousetrap/map.yaml new file mode 100644 index 0000000000..42d6faf5cb --- /dev/null +++ b/mods/ra/maps/mousetrap/map.yaml @@ -0,0 +1,754 @@ +MapFormat: 12 + +RequiresMod: ra + +Title: Mousetrap + +Author: Westwood Studios + +Tileset: INTERIOR + +MapSize: 128,128 + +Bounds: 28,32,82,52 + +Visibility: MissionSelector + +Categories: Mission + +LockPreview: True + +Players: + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Faction: england + PlayerReference@Creeps: + Name: Creeps + NonCombatant: True + Faction: england + Enemies: USSR, Greece, GoodGuy, England + PlayerReference@USSR: + Name: USSR + Playable: True + LockFaction: True + Faction: soviet + LockColor: True + Color: FE1100 + Enemies: Creeps, Greece, GoodGuy + PlayerReference@Greece: + Name: Greece + Bot: campaign + Faction: allies + Color: ABB7E4 + Enemies: Creeps, USSR + PlayerReference@GoodGuy: + Name: GoodGuy + Bot: campaign + Faction: allies + Color: ABB7E4 + Allies: Greece + Enemies: Creeps, USSR + PlayerReference@England: + Name: England + Faction: allies + Color: A1EF8C + +Actors: + Actor0: cycl + Location: 44,34 + Owner: Neutral + Actor1: cycl + Location: 45,34 + Owner: Neutral + Actor2: cycl + Location: 46,34 + Owner: Neutral + Actor3: cycl + Location: 47,34 + Owner: Neutral + Actor4: cycl + Location: 48,34 + Owner: Neutral + Actor5: cycl + Location: 53,34 + Owner: Neutral + Actor6: cycl + Location: 54,34 + Owner: Neutral + Actor7: cycl + Location: 55,34 + Owner: Neutral + Actor8: cycl + Location: 56,34 + Owner: Neutral + Actor9: cycl + Location: 57,34 + Owner: Neutral + Actor10: healcrate + Location: 77,34 + Owner: Neutral + Actor11: healcrate + Location: 78,34 + Owner: Neutral + Actor12: cycl + Location: 44,35 + Owner: Neutral + Actor13: cycl + Location: 48,35 + Owner: Neutral + Actor14: cycl + Location: 53,35 + Owner: Neutral + Actor15: cycl + Location: 57,35 + Owner: Neutral + Actor16: cycl + Location: 44,36 + Owner: Neutral + Actor17: cycl + Location: 48,36 + Owner: Neutral + Actor18: cycl + Location: 53,36 + Owner: Neutral + Actor19: cycl + Location: 57,36 + Owner: Neutral + Actor20: cycl + Location: 44,37 + Owner: Neutral + Actor21: cycl + Location: 48,37 + Owner: Neutral + Actor22: cycl + Location: 53,37 + Owner: Neutral + Actor23: cycl + Location: 57,37 + Owner: Neutral + Actor24: cycl + Location: 44,38 + Owner: Neutral + Actor25: cycl + Location: 48,38 + Owner: Neutral + Actor26: cycl + Location: 53,38 + Owner: Neutral + Actor27: cycl + Location: 57,38 + Owner: Neutral + Actor28: cycl + Location: 44,39 + Owner: Neutral + Actor29: cycl + Location: 48,39 + Owner: Neutral + Actor30: cycl + Location: 53,39 + Owner: Neutral + Actor31: cycl + Location: 57,39 + Owner: Neutral + Actor32: cycl + Location: 44,40 + Owner: Neutral + Actor33: cycl + Location: 48,40 + Owner: Neutral + Actor34: cycl + Location: 53,40 + Owner: Neutral + Actor35: cycl + Location: 57,40 + Owner: Neutral + Actor36: cycl + Location: 44,41 + Owner: Neutral + Actor37: cycl + Location: 45,41 + Owner: Neutral + Actor38: cycl + Location: 46,41 + Owner: Neutral + Actor39: cycl + Location: 47,41 + Owner: Neutral + Actor40: cycl + Location: 48,41 + Owner: Neutral + Actor41: cycl + Location: 53,41 + Owner: Neutral + Actor42: cycl + Location: 54,41 + Owner: Neutral + Actor43: cycl + Location: 55,41 + Owner: Neutral + Actor44: cycl + Location: 56,41 + Owner: Neutral + Actor45: cycl + Location: 57,41 + Owner: Neutral + Actor46: barb + Location: 79,48 + Owner: Neutral + Actor47: barb + Location: 82,48 + Owner: Neutral + Actor48: barb + Location: 80,49 + Owner: Neutral + Actor49: barb + Location: 81,49 + Owner: Neutral + Actor50: ironcrate + Location: 42,50 + Owner: Neutral + Actor51: barb + Location: 106,60 + Owner: Neutral + Actor52: barb + Location: 107,60 + Owner: Neutral + Actor53: barb + Location: 108,61 + Owner: Neutral + Actor54: barb + Location: 108,62 + Owner: Neutral + Actor55: barb + Location: 55,63 + Owner: Neutral + Actor56: barb + Location: 58,63 + Owner: Neutral + Actor57: barb + Location: 106,63 + Owner: Neutral + Actor58: barb + Location: 107,63 + Owner: Neutral + Actor59: barb + Location: 44,65 + Owner: Neutral + Actor60: barb + Location: 47,65 + Owner: Neutral + Actor61: barb + Location: 54,65 + Owner: Neutral + Actor62: barb + Location: 55,65 + Owner: Neutral + Actor63: barb + Location: 58,65 + Owner: Neutral + Actor64: barb + Location: 59,65 + Owner: Neutral + Actor65: barb + Location: 43,67 + Owner: Neutral + Actor66: barb + Location: 48,67 + Owner: Neutral + Actor67: barb + Location: 32,71 + Owner: Neutral + Actor68: barb + Location: 35,71 + Owner: Neutral + Actor69: barb + Location: 31,73 + Owner: Neutral + Actor70: barb + Location: 36,73 + Owner: Neutral + Actor71: barb + Location: 108,73 + Owner: Neutral + Actor72: barb + Location: 108,74 + Owner: Neutral + Actor73: ironcrate + Location: 63,81 + Owner: Neutral + Actor74: boxes01 + Location: 42,47 + Owner: Neutral + Actor75: boxes02 + Location: 43,48 + Owner: Neutral + Actor76: boxes02 + Location: 44,50 + Owner: Neutral + Actor77: boxes03 + Location: 64,82 + Owner: Neutral + Actor78: boxes05 + Location: 62,80 + Owner: Neutral + Actor79: boxes01 + Location: 76,33 + Owner: Neutral + Actor80: boxes02 + Location: 79,35 + Owner: Neutral + Actor81: boxes03 + Location: 79,33 + Owner: Neutral + Actor82: boxes04 + Location: 76,35 + Owner: Neutral + Actor83: boxes01 + Location: 68,79 + Owner: Neutral + Actor84: boxes02 + Location: 66,80 + Owner: Neutral + Actor85: boxes03 + Location: 68,80 + Owner: Neutral + Actor86: boxes04 + Location: 68,82 + Owner: Neutral + Actor87: boxes04 + Location: 67,79 + Owner: Neutral + NorthwestPower: apwr + Location: 45,35 + Owner: Greece + SoutheastPower: apwr + Location: 54,38 + Owner: GoodGuy + SouthwestPower: apwr + Location: 45,38 + Owner: GoodGuy + NortheastPower: apwr + Location: 54,35 + Owner: Greece + StartSphere: pdox + Location: 45,66 + Owner: Greece + SouthwestSphere: pdox + Location: 33,72 + Owner: Greece + ControlSphere: pdox + Location: 73,73 + Owner: Greece + CenterSphere: pdox + Location: 56,64 + Owner: Greece + EastSphere: pdox + Location: 106,61 + Owner: Greece + GasSphere: pdox + Location: 85,67 + Owner: Greece + SoutheastSphere: pdox + Location: 106,73 + Owner: Greece + DamagedSphere: pdox.capturable + Location: 43,59 + Owner: Greece + Health: 12 + NorthwestSphere: pdox + Location: 43,52 + Owner: Greece + NorthSphere: pdox + Location: 80,47 + Owner: Greece + EndingSphereRight: pdox + Location: 102,46 + Owner: Greece + EndingSphereLeft: pdox + Location: 95,46 + Owner: Greece + Actor104: e1 + Location: 45,79 + Owner: USSR + SubCell: 0 + Actor105: e1 + Location: 46,79 + Owner: USSR + SubCell: 0 + Actor106: e4 + Location: 44,80 + Owner: USSR + SubCell: 0 + Actor107: e4 + Location: 47,80 + Owner: USSR + SubCell: 0 + Actor108: e4 + Location: 45,80 + Owner: USSR + SubCell: 0 + Actor109: e4 + Location: 46,80 + Owner: USSR + SubCell: 0 + Stavros: stavros.start + Location: 46,75 + Owner: GoodGuy + SubCell: 1 + Actor111: dog + Location: 48,81 + Owner: USSR + SubCell: 4 + Actor112: dog + Location: 48,80 + Owner: USSR + SubCell: 4 + Actor113: dog + Location: 43,80 + Owner: USSR + SubCell: 4 + Actor114: dog + Location: 43,81 + Owner: USSR + SubCell: 4 + Actor115: e1 + Location: 44,79 + Owner: USSR + SubCell: 0 + Actor116: e1 + Location: 47,79 + Owner: USSR + SubCell: 0 + Actor117: e6 + Location: 45,81 + Owner: USSR + SubCell: 2 + Actor118: e6 + Location: 46,81 + Owner: USSR + SubCell: 1 + Actor119: e1 + Location: 71,35 + Owner: Greece + Facing: 256 + SubCell: 0 + Actor120: e1 + Location: 72,35 + Owner: Greece + Facing: 256 + SubCell: 2 + Actor121: e1 + Location: 71,34 + Owner: Greece + Facing: 256 + SubCell: 4 + Actor122: e1 + Location: 78,46 + Owner: Greece + Facing: 256 + SubCell: 3 + Actor123: e1 + Location: 78,47 + Owner: Greece + Facing: 256 + SubCell: 0 + Actor124: e1 + Location: 65,56 + Owner: Greece + SubCell: 2 + Facing: 512 + Actor125: e1 + Location: 69,56 + Owner: Greece + SubCell: 1 + Facing: 512 + Actor126: e1 + Location: 74,59 + Owner: Greece + Facing: 256 + SubCell: 2 + Actor127: e1 + Location: 74,60 + Owner: Greece + Facing: 256 + SubCell: 4 + Actor128: e1 + Location: 90,61 + Owner: Greece + Facing: 256 + SubCell: 0 + Actor129: e1 + Location: 90,62 + Owner: Greece + Facing: 256 + SubCell: 4 + StartSphereEntrance: waypoint + Location: 45,67 + Owner: Neutral + StartSphereRally: waypoint + Location: 46,70 + Owner: Neutral + waypoint2: waypoint + Location: 34,72 + Owner: Neutral + SouthwestSphereRally: waypoint + Location: 32,75 + Owner: Neutral + ControlReveal: waypoint + Location: 74,74 + Owner: Neutral + ControlNortheast: waypoint + Location: 76,71 + Owner: Neutral + SelfDestructReveal: waypoint + Location: 50,38 + Owner: Neutral + NorthwestGas2: waypoint + Location: 50,43 + Owner: Neutral + NorthwestGas1: waypoint + Location: 51,42 + Owner: Neutral + CenterSphereEntrance: waypoint + Location: 57,64 + Owner: Neutral + ControlNorthwest: waypoint + Location: 71,71 + Owner: Neutral + GasSphereEntrance: waypoint + Location: 85,68 + Owner: Neutral + GasSphereRally: waypoint + Location: 83,63 + Owner: Neutral + GasSphereReveal: camera.small + Location: 83,67 + Owner: Neutral + ScriptTags: Gas + ControlEast: waypoint + Location: 79,73 + Owner: Neutral + EastGas1: waypoint + Location: 92,61 + Owner: Neutral + EastGas2: waypoint + Location: 92,62 + Owner: Neutral + FlamerEntry: waypoint + Location: 45,83 + Owner: Neutral + FlamerRally: waypoint + Location: 44,82 + Owner: Neutral + SovietEntry: waypoint + Location: 46,83 + Owner: Neutral + SovietRally: waypoint + Location: 47,82 + Owner: Neutral + SouthwestSphereEntrance: waypoint + Location: 33,73 + Owner: Neutral + waypoint57: waypoint + Location: 98,74 + Owner: Neutral + waypoint63: waypoint + Location: 103,62 + Owner: Neutral + EastSphereEntrance: waypoint + Location: 106,62 + Owner: Neutral + waypoint65: waypoint + Location: 102,47 + Owner: Neutral + EndingSphereRally: waypoint + Location: 99,53 + Owner: Neutral + waypoint68: waypoint + Location: 33,86 + Owner: Neutral + SoutheastSphereRally: waypoint + Location: 99,70 + Owner: Neutral + EndingIntersection: waypoint + Location: 99,62 + Owner: Neutral + EndingConsole: waypoint + Location: 99,47 + Owner: Neutral + ControlWest: waypoint + Location: 68,73 + Owner: Neutral + waypoint73: waypoint + Location: 96,47 + Owner: Neutral + waypoint74: waypoint + Location: 70,73 + Owner: Neutral + ControlSouth3: waypoint + Location: 80,79 + Owner: Neutral + ControlSouth2: waypoint + Location: 78,79 + Owner: Neutral + ControlSouth1: waypoint + Location: 76,79 + Owner: Neutral + EscapeRally: waypoint + Location: 33,81 + Owner: Neutral + EscapeEntry: waypoint + Location: 33,83 + Owner: Neutral + EscapeGas2: waypoint + Location: 34,81 + Owner: Neutral + EscapeGas1: waypoint + Location: 32,81 + Owner: Neutral + waypoint85: waypoint + Location: 106,73 + Owner: Neutral + NorthwestSphereEntrance: waypoint + Location: 43,53 + Owner: Neutral + NorthwestSphereRally: waypoint + Location: 41,52 + Owner: Neutral + NorthwestSphereReveal: waypoint + Location: 47,54 + Owner: Neutral + waypoint92: waypoint + Location: 66,81 + Owner: Neutral + DefaultCameraPosition: waypoint + Location: 41,79 + Owner: Neutral + ShiftedSovietRally: waypoint + Location: 65,59 + Owner: Neutral + CenterSphereConsole: waypoint + Owner: Neutral + Location: 67,63 + ReinforcementConsole1: waypoint + Owner: Neutral + Location: 64,55 + ReinforcementConsole2: waypoint + Owner: Neutral + Location: 70,55 + SelfDestructConsole1: waypoint + Owner: Neutral + Location: 50,33 + SelfDestructConsole2: waypoint + Owner: Neutral + Location: 51,33 + StartConsole: waypoint + Owner: Neutral + Location: 41,72 + NorthSphereConsole: waypoint + Owner: Neutral + Location: 83,46 + SoutheastSphereEntrance: waypoint + Owner: Neutral + Location: 106,74 + NorthSphereEntrance: waypoint + Owner: Neutral + Location: 80,48 + PillboxSpawn: waypoint + Owner: Neutral + Location: 62,70 + PillboxSpotter2: camera.tiny + Location: 62,74 + Faction: england + Owner: GoodGuy + PillboxSpotter1: camera.tiny + Location: 62,66 + Faction: england + Owner: GoodGuy + NorthSphereRally2: waypoint + Owner: Neutral + Location: 76,46 + DamagedSphereProximity: waypoint + Owner: Neutral + Location: 53,57 + SoutheastSphereProximity: waypoint + Owner: Neutral + Location: 99,67 + EastHallProximity: waypoint + Owner: Neutral + Location: 76,60 + EastHallProximity2: waypoint + Owner: Neutral + Location: 79,60 + SouthHallProximity: waypoint + Owner: Neutral + Location: 62,77 + CenterSphereRally: waypoint + Owner: Neutral + Location: 56,66 + HiddenSphere: pdox + Owner: Neutral + Location: 30,33 + ChronoDummyTarget: waypoint + Owner: Neutral + Location: 33,37 + EscapeGuy: e1 + SubCell: 5 + Owner: Greece + Location: 32,81 + Facing: 384 + StartReveal: camera + Owner: USSR + Location: 46,72 + ScriptTags: Start + Actor204: camera + Owner: Neutral + Location: 29,73 + ScriptTags: Southwest + Actor205: camera + Owner: Neutral + Location: 31,81 + ScriptTags: Southwest + Actor208: camera.small + Owner: Neutral + Location: 77,72 + ScriptTags: Control + Actor209: camera + Owner: Neutral + Location: 81,79 + ScriptTags: Control + Actor210: camera.small + Owner: Neutral + Location: 74,79 + ScriptTags: Control + Actor211: camera.small + Owner: Neutral + Location: 73,71 + ScriptTags: Control + Actor212: camera.small + Owner: Neutral + Location: 69,73 + ScriptTags: Control + Actor213: camera.small + Owner: Neutral + Location: 83,62 + ScriptTags: Gas + ChronoDummyEntry: waypoint + Owner: Neutral + Location: 30,37 + NorthSphereReveal: camera + Owner: Neutral + Location: 82,47 + NorthSphereRally: waypoint + Owner: Neutral + Location: 79,49 + +Rules: ra|rules/campaign-rules.yaml, ra|rules/campaign-tooltips.yaml, ra|rules/campaign-palettes.yaml, rules.yaml + +Notifications: notifications.yaml + +Weapons: weapons.yaml + +Translations: ra|languages/lua/en.ftl, ra|languages/difficulties/en.ftl diff --git a/mods/ra/maps/mousetrap/mousetrap.lua b/mods/ra/maps/mousetrap/mousetrap.lua new file mode 100644 index 0000000000..d7e51dcead --- /dev/null +++ b/mods/ra/maps/mousetrap/mousetrap.lua @@ -0,0 +1,924 @@ +--[[ + Copyright (c) The OpenRA Developers and Contributors + This file is part of OpenRA, which is free software. It is made + available to you under the terms of the GNU General Public License + as published by the Free Software Foundation, either version 3 of + the License, or (at your option) any later version. For more + information, see COPYING. +]] +AlliedReinforcements = +{ + start = { "e1", "e1", "e1" }, + southHall = { "e1", "e1", "e1", "e1", "e1" }, + northHall = { "e1", "e1", "e1" }, + northEnding = { "e1", "e1", "e1", "e1", "e1", "e1", "e1", "e1" }, + southEnding = { "e1", "e1", "e1", "e1", "medi", "medi" }, +} +SovietReinforcements = +{ + constant = { "e1", "e1", "e1" }, + sphere = { "e1", "e1", "e1", "e1", "e1" }, + selfDestructFlamers = { "e4", "e4", "e4", "e4" }, + selfDestructRifles = { "e1", "e1", "e1", "e1" }, +} +USSR = Player.GetPlayer("USSR") +Greece = Player.GetPlayer("Greece") +GoodGuy = Player.GetPlayer("GoodGuy") +England = Player.GetPlayer("England") +Neutral = Player.GetPlayer("Neutral") + +ConsoleTouchDistance = WDist.New(512) +ShiftDelay = DateTime.Seconds(2) +AttackerShiftDelay = DateTime.Seconds(1) +GeneralType = "stavros" +GeneralTypeHard = "stavros.hard" + +EscapeBlocked = false +SelfDestructStarted = false +EngineersKilled = false +EastHallEntered = false +CurrentGeneralSphere = StartSphere + +WorldLoaded = function() + Camera.Position = DefaultCameraPosition.CenterPosition + if Difficulty == "hard" then + GeneralType = GeneralTypeHard + ShiftSouthEndingReinforcements() + SpawnPillbox() + + Trigger.AfterDelay(DateTime.Minutes(1), function() + ShiftNorthReinforcements(DateTime.Minutes(1)) + end) + end + + Trigger.AfterDelay(5, GeneralStart) + SetObjectives() + CheckRequiredUnits() + InitialTriggers() +end + +SetObjectives = function() + InitObjectives(USSR) + DefendStavros = AddPrimaryObjective(Greece, "") + KillStavros = AddPrimaryObjective(USSR, "kill-stavros") + SabotageFacility = AddPrimaryObjective(USSR, "sabotage-facility") +end + +AlliedWin = function() + if AlliesHaveWon then + return + end + + AlliesHaveWon = true + Media.PlaySpeechNotification(USSR, "ObjectiveNotMet") + + Trigger.AfterDelay(DateTime.Seconds(1), function() + Greece.MarkCompletedObjective(DefendStavros) + end) +end + +CheckRequiredUnits = function() + if not SovietsHaveWon and USSR.HasNoRequiredUnits() then + AlliedWin() + return + end + + Trigger.AfterDelay(DateTime.Seconds(2), CheckRequiredUnits) +end + +OnStartingEngineersKilled = function() + EngineersKilled = true + if SelfDestructStarted then + return + end + + Media.PlaySoundNotification(USSR, "AlertBleep") + Media.DisplayMessage(UserInterface.Translate("all-engineers-killed")) + Trigger.AfterDelay(DateTime.Seconds(1), AlliedWin) +end + +OnShiftedEngineerKilled = function() + if not SelfDestructStarted then + USSR.MarkFailedObjective(SabotageFacility) + end +end + +OnStavrosKilled = function() + SovietsHaveWon = true + Media.PlaySpeechNotification(USSR, "ObjectiveMet") + + Trigger.AfterDelay(DateTime.Seconds(1), function() + USSR.MarkCompletedObjective(KillStavros) + end) +end + +-- Sphere movement functions. +EnterSphere = function(actor, sphere, onArrived) + actor = actor or GetGeneral() + -- Nil should only be an issue if self-destruct or escape gas triggers while Stavros shifts. + -- SelfDestructSequence, GeneralControlHiding, and GeneralSouthwest account for this. + if not actor then + return + end + + CurrentGeneralSphere = sphere + actor.Infiltrate(sphere) + + Trigger.OnInfiltrated(sphere, function() + Trigger.Clear(sphere, "OnInfiltrated") + + Trigger.AfterDelay(ShiftDelay, function() + ChronoEffect(sphere) + end) + + Trigger.AfterDelay(ShiftDelay * 2, onArrived) + end) +end + +ReinforceAtSphere = function(sphere, owner, types, onArrived) + if sphere.IsDead then + return { } + end + + local exit = sphere.Location + CVec.New(0, 1) + local troops = Reinforcements.Reinforce(owner, types, { exit }, 10, function(actor) + if onArrived then + onArrived(actor) + end + end) + + return troops +end + +ReinforceGeneralAtSphere = function(sphere, onArrived) + CurrentGeneralSphere = sphere + + local stavros = ReinforceAtSphere(sphere, GoodGuy, { GeneralType }, onArrived)[1] + if sphere == ControlSphere then + -- It's still possible to barely hit him with flamethrower spread damage. + stavros.GrantCondition("invulnerability") + end + Trigger.OnKilled(stavros, OnStavrosKilled) + + return stavros +end + +--[[ + These control Stavros' actions near each sphere. + Start -> Southwest -> Control -> Gas. + From there, different routes depending on the player's actions: + Gas -> Escape. + Gas -> Control (until self-destruct) -> Ending. + Gas -> Ending. +]]-- +GeneralStart = function() + Trigger.AfterDelay(DateTime.Seconds(3), SpawnEscapeVehicle) + + Trigger.AfterDelay(DateTime.Seconds(20), function() + HideCameras("Start") + end) + + Media.PlaySpeechNotification(USSR, "StavrosCommander") + Stavros.Move(StartSphere.Location + CVec.New(0, 2)) + EnterSphere(Stavros, StartSphere, GeneralSouthwest) +end + +GeneralSouthwest = function() + ShowCameras("Southwest") + ReinforceGeneralAtSphere(SouthwestSphere, function(stavros) + stavros.Move(SouthwestSphereRally.Location) + + stavros.CallFunc(function() + if EscapeBlocked then + GeneralSouthwestToControlAndGas() + end + ShiftStartReinforcements() + end) + end) +end + +GeneralSouthwestToControlAndGas = function() + EnterSphere(GetGeneral(), SouthwestSphere, function() + ShowCameras("Control") + ReinforceGeneralAtSphere(ControlSphere, function(stavros) + stavros.Move(ControlNortheast.Location) + stavros.CallFunc(SpawnNorthwestGas) + + if not EscapeBlocked then + stavros.CallFunc(SpawnStartGas) + end + + stavros.Wait(DateTime.Seconds(3)) + stavros.Move(ControlNorthwest.Location) + + stavros.CallFunc(function() + Media.PlaySoundNotification(USSR, "ConsoleBeep") + ShiftCenterReinforcements() + Trigger.AfterDelay(DateTime.Seconds(6), GeneralControlToGas) + end) + end) + end) +end + +GeneralControlToGas = function() + EnterSphere(GetGeneral(), ControlSphere, function() + HideCameras("Control") + ShowCameras("Gas") + + ReinforceGeneralAtSphere(GasSphere, function(stavros) + if EastHallEntered then + GeneralGasToControl() + return + end + stavros.Move(GasSphereReveal.Location) + stavros.Move(GasSphereRally.Location) + + stavros.CallFunc(function() + if EastHallEntered then + GeneralGasToControl() + end + end) + end) + end) +end + +GeneralGasToControl = function() + EnterSphere(GetGeneral(), GasSphere, GeneralControlHiding) +end + +GeneralControlHiding = function() + HideCameras("Gas") + ShowCameras("Control") + ReinforceGeneralAtSphere(ControlSphere, function(stavros) + stavros.Move(ControlWest.Location) + + stavros.CallFunc(function() + if not SelfDestructStarted then + return + end + + GeneralControlToEnding() + end) + end) +end + +GeneralGasToEscape = function() + EnterSphere(GetGeneral(), GasSphere, GeneralEscape) +end + +GeneralEscape = function() + HideCameras("Gas") + ReinforceGeneralAtSphere(SouthwestSphere, function(stavros) + local carrier = GoodGuy.GetActorsByType("apc")[1] + + Trigger.AfterDelay(DateTime.Seconds(1), function() + EscapeGuy.EnterTransport(carrier) + end) + + stavros.CallFunc(function() + Media.PlaySoundNotification(USSR, "AlertBleep") + Camera.Position = EscapeRally.CenterPosition + end) + + stavros.Move(SouthwestSphereRally.Location) + stavros.Move(EscapeGas1.Location) + + stavros.CallFunc(function() + Media.PlaySpeechNotification(USSR, "StavrosMoveOut") + end) + + stavros.EnterTransport(carrier) + end) +end + +GeneralGasToEnding = function() + Trigger.AfterDelay(DateTime.Seconds(2), function() + HideCameras("Gas") + end) + + local stavros = GetGeneral() + stavros.Move(EastGas2.Location) + stavros.AttackMove(EndingIntersection.Location) + stavros.AttackMove(EndingConsole.Location) +end + +GeneralControlToEnding = function() + EnterSphere(GetGeneral(), ControlSphere, function() + HideCameras("Control") + SpawnPlayerCamera(EndingSphereLeft.Location, nil, 0, "camera.small") + ReinforceGeneralAtSphere(EndingSphereLeft, function(stavros) + stavros.AttackMove(EndingConsole.Location) + end) + end) +end + +GeneralEnding = function() + ShiftNorthEndingReinforcements() + Media.PlaySoundNotification(USSR, "ConsoleBeep") + + local stavros = GetGeneral() + SpawnPlayerCamera(stavros.Location) + + stavros.Wait(DateTime.Seconds(1)) + stavros.AttackMove(EndingConsole.Location + CVec.New(0, 1)) + stavros.Stance = "AttackAnything" +end + +-- Reinforcements. +InsertSovietReinforcements = function(team, entry, rally, delay) + Trigger.AfterDelay(delay or 0, function() + Reinforcements.Reinforce(USSR, SovietReinforcements[team], { entry, rally } ) + end) + + if team ~= "constant" then + return + end + + Media.PlaySpeechNotification(USSR, "ReinforcementsArrived") + Trigger.AfterDelay(DateTime.Minutes(4), function() + InsertSovietReinforcements(team, entry, rally) + end) +end + +ShiftSovietReinforcements = function() + if SovietReinforcementsShifted or CenterSphere.IsDead then + return + end + + SovietReinforcementsShifted = true + Media.PlaySoundNotification(USSR, "ConsoleBeep") + ChronoEffect() + + Trigger.AfterDelay(AttackerShiftDelay, function() + ReinforceAtSphere(CenterSphere, USSR, SovietReinforcements.sphere, function(actor) + actor.AttackMove(ShiftedSovietRally.Location) + end) + SpawnPlayerCamera(CenterSphere.Location, DateTime.Seconds(2), 0, "camera.small") + end) +end + +ShiftCenterReinforcements = function() + SpawnPlayerCamera(CenterSphere.Location, nil, 0, "camera.small") + ChronoEffect() + + Trigger.AfterDelay(AttackerShiftDelay, function() + local southHallRifles = ReinforceAtSphere(CenterSphere, Greece, AlliedReinforcements.southHall) + GroupHuntFromRally(southHallRifles, CenterSphereRally.Location, SovietEntry.Location) + end) +end + +ShiftNorthReinforcements = function(interval) + if NorthSphere.IsDead then + return + end + + SpawnPlayerCamera(NorthSphereReveal.Location, nil, 0, "camera.small") + ChronoEffect(NorthSphere) + + Trigger.AfterDelay(AttackerShiftDelay, function() + local northRifles = ReinforceAtSphere(NorthSphere, Greece, AlliedReinforcements.northHall) + GroupHuntFromRally(northRifles, NorthSphereRally.Location) + end) + + Trigger.AfterDelay(interval, function() + ShiftNorthReinforcements(interval) + end) +end + +ShiftStartReinforcements = function() + ChronoEffect() + + Trigger.AfterDelay(AttackerShiftDelay, function() + local startRifles = ReinforceAtSphere(StartSphere, Greece, AlliedReinforcements.start) + GroupHuntFromRally(startRifles, StartSphereRally.Location) + end) +end + +ShiftNorthEndingReinforcements = function() + ChronoEffect() + + Trigger.AfterDelay(AttackerShiftDelay, function() + local norts = ReinforceAtSphere(EndingSphereRight, Greece, AlliedReinforcements.northEnding, function(actor) + actor.AddTag("Ending Group") + actor.AttackMove(EndingSphereRally.Location) + end) + PrepareEndingTeam(norts) + end) + + Trigger.AfterDelay(AttackerShiftDelay + DateTime.Seconds(4), function() + DestroyBuilding(EndingSphereRight, nil, 0, "hidden") + end) +end + +ShiftSouthEndingReinforcements = function() + local southers = ReinforceAtSphere(SoutheastSphere, Greece, AlliedReinforcements.southEnding, function(actor) + actor.AddTag("Ending Group") + actor.Move(SoutheastSphereRally.Location) + if actor.Type == "medi" then + actor.Move(SoutheastSphereRally.Location + CVec.New(0, 1)) + end + end) + PrepareEndingTeam(southers) +end + +-- Supporting actors. +SpawnPlayerCamera = function(location, duration, delay, cameraType) + duration = duration or DateTime.Seconds(6) + cameraType = cameraType or "camera" + + Trigger.AfterDelay(delay or 0, function() + local camera = Actor.Create(cameraType, true, { Owner = USSR, Location = location } ) + if duration < 0 then + return + end + + Trigger.AfterDelay(duration, camera.Destroy) + end) +end + +SetCameraGroupOwner = function(tag, owner) + local cameras = Map.ActorsWithTag(tag) + Utils.Do(cameras, function(camera) + camera.Owner = owner + end) +end + +ShowCameras = function(tag) + SetCameraGroupOwner(tag, USSR) +end + +HideCameras = function(tag) + SetCameraGroupOwner(tag, Neutral) +end + +SpawnGas = function(waypoint, delay, sound) + Trigger.AfterDelay(delay or 0, function() + Actor.Create("flare", true, { Owner = England, Location = waypoint.Location } ) + end) + + if sound then + Media.PlaySoundNotification(USSR, sound) + end +end + +SpawnEastGas = function() + SpawnGas(EastGas1, 15, "GasHiss") + SpawnGas(EastGas2) +end + +SpawnNorthwestGas = function() + SpawnPlayerCamera(SelfDestructReveal.Location, DateTime.Seconds(20)) + SpawnGas(NorthwestGas1, 15, "GasHiss") + SpawnGas(NorthwestGas2) +end + +SpawnStartGas = function() + SpawnGas(StartConsole) +end + +SpawnEscapeGas = function() + EscapeBlocked = true + + SpawnGas(EscapeGas1, 0, "GasHiss") + SpawnGas(EscapeGas2, 15) + EscapeGuy.Scatter() + + if IsStavrosIdle() and CurrentGeneralSphere == SouthwestSphere then + GeneralSouthwestToControlAndGas() + end +end + +SpawnEscapeVehicle = function() + local vehiclePath = { EscapeEntry.Location, EscapeRally.Location } + Reinforcements.Reinforce(GoodGuy, { "apc" }, vehiclePath, 0, function(vehicle) + Trigger.OnKilled(EscapeGuy, function() + ExitEscapeVehicle(vehicle) + end) + + Trigger.OnPassengerEntered(vehicle, function(_, passenger) + if not IsStavros(passenger) then + return + end + + ExitEscapeVehicle(vehicle, "stavros") + end) + end) +end + +ExitEscapeVehicle = function(vehicle, stavros) + vehicle.Move(EscapeEntry.Location) + + vehicle.CallFunc(function() + if stavros then + AlliedWin() + end + + Trigger.AfterDelay(DateTime.Seconds(2), function() + HideCameras("Southwest") + end) + end) + + vehicle.Destroy() +end + +-- Hard's spy behavior and pillboxes. +SpawnSpy = function(sphere) + sphere = sphere or StartSphere + if Difficulty ~= "hard" or sphere.IsDead then + return + end + ChronoEffect() + + Trigger.AfterDelay(ShiftDelay, function() + local spy = ReinforceAtSphere(sphere, Greece, { "spy" } )[1] + + Trigger.OnAddedToWorld(spy, function() + spy.DisguiseAsType("e1", USSR) + end) + + Trigger.OnIdle(spy, function() + SpyIdle(spy) + end) + end) +end + +SpyIdle = function(spy) + if SelfDestructStarted then + SpyEscape(spy) + return + end + + local targets = Map.ActorsInCircle(spy.CenterPosition, WDist.FromCells(3), function(nearby) + return nearby.Type == "e6" + end) + + if targets and #targets > 0 then + SpyAttack(spy, targets[1]) + return + end + + SpySearch(spy) +end + +SpyAttack = function(spy, target) + spy.AttackMove(target.Location) + + spy.CallFunc(function() + if EngineersKilled and not SelfDestructStarted then + SpyPostMortem(spy) + end + end) + + spy.Wait(DateTime.Seconds(1)) + + spy.CallFunc(function() + spy.DisguiseAsType(target.Type, target.Owner) + end) + + spy.Wait(DateTime.Seconds(1)) +end + +SpySearch = function(spy) + local targets = Utils.Where(USSR.GetActorsByType("e6"), function(actor) + return not actor.HasTag("shifted") + end) + + if targets and #targets > 0 then + local goal = Utils.Random(targets) + spy.Move(goal.Location, 2) + return + end + + SpyEscape(spy) +end + +SpyEscape = function(spy) + spy.Move(SovietRally.Location, 1) + spy.Move(SovietEntry.Location) + spy.Destroy() +end + +-- Avoid the spy killing both engineers, ending the mission, and being left in fog. +SpyPostMortem = function(spy) + Media.PlaySpeechNotification(USSR, "SpyCommander") + SpawnPlayerCamera(spy.Location, -1, 0, "camera.small") + spy.Stop() + spy.Wait(DateTime.Minutes(1)) +end + +SpawnPillbox = function() + Actor.Create("pbox", true, { Owner = GoodGuy, Location = PillboxSpawn.Location } ) + + CreateProximityOneShot(SouthHallProximity, WDist.FromCells(3), IsSoviet, function() + SpawnPlayerCamera(PillboxSpawn.Location, nil, 0 ,"camera.tiny") + end) +end + +-- Group activities. +IsGroupIdle = function(actors) + return Utils.All(actors, function(actor) + return actor.IsIdle + end) +end + +GroupHunt = function(actors, goal, delay) + Utils.Do(actors, function(actor) + if actor.IsDead then + return + end + + Trigger.Clear(actor, "OnIdle") + actor.Wait(delay) + actor.AttackMove(goal or actor.Location, 1) + actor.Hunt() + end) +end + +GroupHuntFromRally = function(actors, rally, goal, delay) + if not actors or #actors < 1 then + return + end + + delay = delay or 10 + Utils.Do(actors, function(actor) + Trigger.OnIdle(actor, function() + + if actor.Location == rally then + if IsGroupIdle(actors) then + GroupHunt(actors, goal, delay) + end + else + actor.AttackMove(rally) + end + + end) + end) +end + +PrepareEndingTeam = function(actors) + OnAnyDamaged(actors, function() + local defenders = Map.ActorsWithTag("Ending Group") + local path = { EndingIntersection.Location, EndingSphereRally.Location } + + Utils.Do(defenders, function(actor) + if actor.IsDead then + return + end + + Trigger.ClearAll(actor) + actor.Patrol(path, true, DateTime.Seconds(1)) + end) + end) +end + +-- Starting trigger setups. +CreateProximityOneShot = function(waypoint, range, filter, func) + Trigger.OnEnteredProximityTrigger(waypoint.CenterPosition, range, function(actor, id) + if not filter(actor) then + return + end + + Trigger.RemoveProximityTrigger(id) + func(actor) + func = function() + print("Duplicate event at " .. tostring(waypoint) .. " skipped.") + end + end) +end + +InitialTriggers = function() + Trigger.OnAllKilled(USSR.GetActorsByType("e6"), OnStartingEngineersKilled) + + Trigger.AfterDelay(DateTime.Minutes(4), function() + InsertSovietReinforcements("constant", SovietEntry.Location, SovietRally.Location) + end) + + Trigger.OnKilled(NorthSphere, function() + SpawnPlayerCamera(NorthSphereReveal.Location, nil, 0, "camera.small") + end) + + PrepareConsoles() + PrepareOtherProximities() + PrepareDamagedChronosphere() +end + +PrepareConsole = function(waypoint, filter, func) + CreateProximityOneShot(waypoint, ConsoleTouchDistance, filter, func) +end + +PrepareConsoles = function() + PrepareConsole(CenterSphereConsole, IsSovietHuman, function() + DestroyBuilding(CenterSphere, "ConsoleBeep", 10) + end) + + PrepareConsole(NorthSphereConsole, IsSovietHuman, function() + DestroyBuilding(NorthSphere, "ConsoleBeep", 10, "hidden") + end) + + PrepareConsole(StartConsole, IsSovietHuman, SpawnEscapeGas) + PrepareConsole(ReinforcementConsole1, IsSovietHuman, ShiftSovietReinforcements) + PrepareConsole(ReinforcementConsole2, IsSovietHuman, ShiftSovietReinforcements) + PrepareConsole(SelfDestructConsole1, IsSovietHuman, BeginSelfDestruct) + PrepareConsole(SelfDestructConsole2, IsSovietHuman, BeginSelfDestruct) + PrepareConsole(EndingConsole, IsStavros, GeneralEnding) +end + +PrepareOtherProximities= function() + CreateProximityOneShot(DamagedSphereProximity, WDist.FromCells(3), IsSoviet, function() + SpawnPlayerCamera(DamagedSphere.Location) + end) + + CreateProximityOneShot(SoutheastSphereProximity, WDist.FromCells(3), IsSoviet, function() + SpawnPlayerCamera(SoutheastSphereRally.Location) + end) + + CreateProximityOneShot(SouthHallProximity, WDist.FromCells(2), IsSoviet, function() + + if not EscapeBlocked and CurrentGeneralSphere == SouthwestSphere then + GeneralSouthwestToControlAndGas() + end + + Trigger.AfterDelay(DateTime.Seconds(Utils.RandomInteger(60, 91)), SpawnSpy) + end) + + CreateProximityOneShot(EastHallProximity, WDist.FromCells(2), IsSoviet, function() + EastHallEntered = true + + Trigger.AfterDelay(DateTime.Seconds(3), SpawnEastGas) + local stavros = GetGeneral() + if not (IsStavrosIdle(stavros) and stavros.Location == GasSphereRally.Location) then + return + end + if SelfDestructStarted then + GeneralGasToEnding() + return + end + GeneralGasToControl() + end) +end + +PrepareDamagedChronosphere = function() + Trigger.OnCapture(DamagedSphere, function(sphere) + + Trigger.AfterDelay(ShiftDelay, function() + if sphere.IsInWorld then + ChronoEffect(sphere) + end + end) + + Trigger.AfterDelay(ShiftDelay * 2, function() + ReinforceAtSphere(NorthwestSphere, USSR, { "e6" }, function(newEngineer) + Trigger.OnKilled(newEngineer, OnShiftedEngineerKilled) + newEngineer.AddTag("shifted") + + newEngineer.CallFunc(function() + SpawnPlayerCamera(NorthwestSphere.Location) + end) + + newEngineer.Move(NorthwestSphereRally.Location) + end) + end) + + Trigger.AfterDelay(ShiftDelay * 3, function() + if sphere.IsInWorld then + ChronoEffect(sphere) + DestroyBuilding(sphere, nil, DateTime.Seconds(1)) + end + end) + end) +end + +-- Filters, fetchers, and such. +IsSoviet = function(actor) + return actor.Owner == USSR +end + +IsSovietHuman = function(actor) + return actor.Owner == USSR and actor.Type ~= "dog" +end + +IsStavros = function(actor) + return actor.Type == GeneralType +end + +IsStavrosIdle = function(stavros) + stavros = stavros or GetGeneral() + return stavros and stavros.IsIdle +end + +IsEscapePossible = function() + return not EscapeBlocked and CurrentGeneralSphere == GasSphere +end + +GetGeneral = function() + local generals = GoodGuy.GetActorsByType(GeneralType) + if generals and #generals > 0 then + return generals[1] + end +end + +-- Self-destruct and building effects. +BeginSelfDestruct = function() + if SelfDestructStarted then + return + end + + SelfDestructStarted = true + USSR.MarkCompletedObjective(SabotageFacility) + Media.PlaySoundNotification(USSR, "ConsoleBuzz") + + Trigger.AfterDelay(DateTime.Seconds(1), function() + SelfDestructAlarm() + + if IsEscapePossible() then + GeneralGasToEscape() + end + + if IsStavrosIdle() and CurrentGeneralSphere == ControlSphere then + GeneralControlToEnding() + end + end) + + Trigger.AfterDelay(DateTime.Seconds(2), SelfDestructSequence) +end + +SelfDestructSequence = function() + DestroyBuilding(NorthwestPower) + DestroyBuilding(SoutheastPower) + local pillboxes = GoodGuy.GetActorsByType("pbox") + Utils.Do(pillboxes, function(pillbox) + DestroyBuilding(pillbox) + end) + + Trigger.AfterDelay(DateTime.Seconds(3), function() + if IsEscapePossible() then + return + end + + Media.PlaySpeechNotification(USSR, "ReinforcementsArrived") + InsertSovietReinforcements("selfDestructFlamers", FlamerEntry.Location, FlamerRally.Location) + InsertSovietReinforcements("selfDestructRifles", SovietEntry.Location, SovietRally.Location, DateTime.Seconds(1)) + end) + + Trigger.AfterDelay(DateTime.Seconds(9), function() + DestroyBuilding(NortheastPower) + DestroyBuilding(SouthwestPower) + end) + + Trigger.AfterDelay(DateTime.Seconds(15), function() + DestroyBuilding(CenterSphere) + DestroyBuilding(NorthSphere, nil, nil, "hidden") + end) + + Trigger.AfterDelay(DateTime.Seconds(21), function() + DestroyBuilding(NorthwestSphere) + DestroyBuilding(GasSphere) + DestroyBuilding(EndingSphereLeft) + DestroyBuilding(EastSphere) + DestroyBuilding(SoutheastSphere) + DestroyBuilding(ControlSphere) + end) +end + +SelfDestructAlarm = function() + Media.PlaySoundNotification(USSR, "AlertBuzzer") + Trigger.AfterDelay(DateTime.Seconds(6), SelfDestructAlarm) +end + +DestroyBuilding = function(actor, sound, delay, hidden) + if actor.IsDead then + return + end + + delay = delay or Utils.RandomInteger(0, DateTime.Seconds(1)) + + Trigger.AfterDelay(delay, function() + if actor.IsDead then + return + end + + actor.Kill() + if not hidden then + SpawnPlayerCamera(actor.Location, nil, nil, "camera.small") + end + end) + + if sound then + Media.PlaySoundNotification(USSR, sound) + end +end + +ChronoEffect = function(sphere) + Media.PlaySoundNotification(USSR, "Chronoshift") + if not sphere then + return + end + + local units = { } + local target = ChronoDummyTarget.Location + local dummy = Reinforcements.Reinforce(Neutral, { "1tnk" }, { ChronoDummyEntry.Location } )[1] + units[dummy] = target + + sphere.Chronoshift(units, 0) + Trigger.AfterDelay(1, dummy.Destroy) +end diff --git a/mods/ra/maps/mousetrap/notifications.yaml b/mods/ra/maps/mousetrap/notifications.yaml new file mode 100644 index 0000000000..1f5616e5f0 --- /dev/null +++ b/mods/ra/maps/mousetrap/notifications.yaml @@ -0,0 +1,12 @@ +Sounds: + Notifications: + ConsoleBeep: rabeep1 + ConsoleBuzz: buzzy1 + GasHiss: hydrod1 + Chronoshift: chrono2 + +Speech: + Notifications: + SpyCommander: scomnd1 + StavrosMoveOut: stavmov + StavrosCommander: stavcmdr diff --git a/mods/ra/maps/mousetrap/rules.yaml b/mods/ra/maps/mousetrap/rules.yaml new file mode 100644 index 0000000000..9ce276bb1b --- /dev/null +++ b/mods/ra/maps/mousetrap/rules.yaml @@ -0,0 +1,142 @@ +World: + LuaScript: + Scripts: campaign.lua, utils.lua, mousetrap.lua + MissionData: + Briefing: A longtime thorn in our side, the Greek commander Stavros, has finally been cornered. He has taken refuge in an underground bunker full of his Chronosphere technology. Prove to him that no Allied tricks can stop the wrath of the Soviet Union. Track him down, and eliminate him.\n\nReturn with results -- we do not want to hear of his escape... only the creative manner of his demise.\n\nWe have provided you with engineers that, given the opportunity, can use Chronosphere technology. Do not squander them. + BackgroundVideo: sovexp1.vqa + WinVideo: sovexp1w.vqa + LossVideo: apcescpe.vqa + ScriptLobbyDropdown@difficulty: + ID: difficulty + Label: dropdown-difficulty.label + Description: dropdown-difficulty.description + Values: + normal: options-difficulty.normal + hard: options-difficulty.hard + Default: normal + # Stavros' opening line makes this feel redundant. + -StartGameNotification: + # Give our Chrono dummy the ability to move (and be shifted) within the void. + Locomotor@TRACKED: + TerrainSpeeds: + ClearNoSmudges: 100 + +^Palettes: + -ChronoshiftPaletteEffect: + +# Used in ChronoEffect. +1TNK: + Chronoshiftable: + ChronoshiftSound: + +^Soldier: + ScriptTags: + Inherits@IronCurtain: ^IronCurtainable + ExternalCondition@GAS: + Condition: gassed + TotalCap: 1 + DamagedByTerrain: + RequiresCondition: gassed + Damage: 300 + DamageInterval: 1 + DamageTypes: ExplosionDeath + Terrain: Clear + +FLARE: + ProximityExternalCondition@GAS: + Condition: gassed + Range: 1c512 + ValidRelationships: Neutral, Enemy + RevealsShroud: + Range: 1c512 + ValidRelationships: Ally, Neutral, Enemy + Tooltip: + Name: Gas + +IRONCRATE: + Inherits: ^Crate + GrantExternalConditionCrateAction: + SelectionShares: 1 + Sequence: invuln + Sound: ironcur9.aud + Condition: invulnerability + Duration: 600 + Range: 2c512 + RenderSprites: + Image: wcrate + +CAMERA: + ScriptTags: + +CAMERA.tiny: + Inherits: CAMERA + RevealsShroud: + Range: 2c0 + +CAMERA.small: + Inherits: CAMERA + RevealsShroud: + Range: 4c0 + +PBOX: + # Reduced vision to avoid shooting beyond the hallway. + RevealsShroudMultiplier: + Modifier: 50 + +PDOX: + DamageMultiplier: + Modifier: 0 + Power: + Amount: 0 + +# Couldn't avoid engineers falsely reporting they could capture chronospheres under fog. Made a new type. +PDOX.capturable: + Inherits: PDOX + RenderSprites: + Image: PDOX + Capturable: + Types: predamaged + -ChronoshiftPower@chronoshift: + -SpawnActorsOnSell: + +E6: + Captures: + CaptureTypes: predamaged + +STAVROS: + Inherits: GNRL + Inherits@IronCurtain: ^IronCurtainable + -WithColoredOverlay@IRONCURTAIN: + RenderSprites: + Image: GNRL + Tooltip: + Name: Stavros + Infiltrates: + Types: SpyInfiltrate + Voice: Move + ValidRelationships: Ally, Neutral + SpeedMultiplier: + # Original is 8 speed v. E1's 4 speed. + Modifier: 200 + Valued: + Cost: 2000 + +STAVROS.hard: + Inherits: STAVROS + RenderSprites: + Image: GNRL + Armament: + Weapon: Colt45 + AutoTarget: + InitialStanceAI: ReturnFire + RevealsShroud: + Range: 4c0 + +STAVROS.start: + Inherits: STAVROS + RenderSprites: + Image: GNRL + -Targetable: + +BARB: + -Tooltip: diff --git a/mods/ra/maps/mousetrap/weapons.yaml b/mods/ra/maps/mousetrap/weapons.yaml new file mode 100644 index 0000000000..90da0be4e4 --- /dev/null +++ b/mods/ra/maps/mousetrap/weapons.yaml @@ -0,0 +1,11 @@ +Colt45: + ReloadDelay: 21 + Range: 4c0 + Warhead@1Dam: SpreadDamage + Warhead@2Eff: CreateEffect + +M1Carbine: + Range: 4c0 + +Flamer: + Range: 4c0 diff --git a/mods/ra/missions.yaml b/mods/ra/missions.yaml index 1c47f2fd93..bbb9e96855 100644 --- a/mods/ra/missions.yaml +++ b/mods/ra/missions.yaml @@ -41,6 +41,7 @@ Counterstrike Allied Missions: siberian-conflict-1-fresh-tracks siberian-conflict-3-wasteland Counterstrike Soviet Missions: + mousetrap soviet-soldier-volkov-n-chitzkoi top-o-the-world Aftermath Allied Missions: