--[[ 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