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 0000000000..30e6f0da2e Binary files /dev/null and b/mods/ra/maps/mousetrap/map.bin differ diff --git a/mods/ra/maps/mousetrap/map.png b/mods/ra/maps/mousetrap/map.png new file mode 100644 index 0000000000..dc774179f2 Binary files /dev/null and b/mods/ra/maps/mousetrap/map.png differ 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: