From 2a8efde8e675e68ad303cb41b73bb11ae67e4512 Mon Sep 17 00:00:00 2001 From: ScottNZ Date: Wed, 19 Feb 2014 21:43:54 +1300 Subject: [PATCH 1/5] Add map beacons and radar pings --- OpenRA.Game/GameRules/Settings.cs | 2 + OpenRA.Mods.RA/Effects/Beacon.cs | 64 +++++++++++ OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 3 + OpenRA.Mods.RA/Player/PlaceBeacon.cs | 73 ++++++++++++ OpenRA.Mods.RA/Widgets/Logic/SettingsLogic.cs | 2 + OpenRA.Mods.RA/Widgets/RadarWidget.cs | 41 +++++-- OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs | 12 ++ OpenRA.Mods.RA/World/RadarPings.cs | 106 ++++++++++++++++++ mods/cnc/notifications.yaml | 3 +- mods/cnc/rules/system-player.yaml | 1 + mods/cnc/rules/system-world.yaml | 2 +- mods/cnc/sequences/misc.yaml | 8 ++ mods/d2k/notifications.yaml | 3 +- mods/d2k/rules/system-player.yaml | 2 +- mods/d2k/rules/system-world.yaml | 2 +- mods/d2k/sequences/misc.yaml | 8 ++ mods/ra/notifications.yaml | 3 +- mods/ra/rules/system-player.yaml | 1 + mods/ra/rules/system-world.yaml | 2 +- mods/ra/sequences/misc.yaml | 8 ++ mods/ts/notifications.yaml | 3 +- mods/ts/rules/system-player.yaml | 2 +- mods/ts/rules/system-world.yaml | 2 +- mods/ts/sequences/misc.yaml | 9 ++ 24 files changed, 345 insertions(+), 17 deletions(-) create mode 100644 OpenRA.Mods.RA/Effects/Beacon.cs create mode 100644 OpenRA.Mods.RA/Player/PlaceBeacon.cs create mode 100644 OpenRA.Mods.RA/World/RadarPings.cs diff --git a/OpenRA.Game/GameRules/Settings.cs b/OpenRA.Game/GameRules/Settings.cs index c30a0db04c..c7f67567df 100644 --- a/OpenRA.Game/GameRules/Settings.cs +++ b/OpenRA.Game/GameRules/Settings.cs @@ -150,6 +150,8 @@ namespace OpenRA.GameRules public Hotkey SelectAllUnitsKey = new Hotkey(Keycode.A, Modifiers.Ctrl); public Hotkey SelectUnitsByTypeKey = new Hotkey(Keycode.T, Modifiers.Ctrl); + public Hotkey PlaceBeaconKey = new Hotkey(Keycode.B, Modifiers.Ctrl); + public Hotkey PauseKey = new Hotkey(Keycode.F9, Modifiers.None); public Hotkey SellKey = new Hotkey(Keycode.F10, Modifiers.None); public Hotkey PowerDownKey = new Hotkey(Keycode.F11, Modifiers.None); diff --git a/OpenRA.Mods.RA/Effects/Beacon.cs b/OpenRA.Mods.RA/Effects/Beacon.cs new file mode 100644 index 0000000000..8ae5a4a4e9 --- /dev/null +++ b/OpenRA.Mods.RA/Effects/Beacon.cs @@ -0,0 +1,64 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) + * 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. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using System.Linq; +using OpenRA.Effects; +using OpenRA.Graphics; + +namespace OpenRA.Mods.RA.Effects +{ + public class Beacon : IEffect + { + readonly Player owner; + readonly WPos position; + readonly string palettePrefix; + readonly Animation arrow = new Animation("beacon"); + readonly Animation circles = new Animation("beacon"); + static readonly int maxArrowHeight = 512; + int arrowHeight = maxArrowHeight; + int arrowSpeed = 50; + + public Beacon(Player owner, WPos position, int duration, string palettePrefix) + { + this.owner = owner; + this.position = position; + this.palettePrefix = palettePrefix; + + arrow.Play("arrow"); + circles.Play("circles"); + + owner.World.Add(new DelayedAction(duration, () => owner.World.Remove(this))); + } + + public void Tick(World world) + { + arrowHeight += arrowSpeed; + var clamped = arrowHeight.Clamp(0, maxArrowHeight); + if (arrowHeight != clamped) + { + arrowHeight = clamped; + arrowSpeed *= -1; + } + + arrow.Tick(); + circles.Tick(); + } + + public IEnumerable Render(WorldRenderer r) + { + if (!owner.IsAlliedWith(owner.World.RenderPlayer)) + return SpriteRenderable.None; + + var palette = r.Palette(palettePrefix + owner.InternalName); + return circles.Render(position, palette).Concat(arrow.Render(position + new WVec(0, 0, arrowHeight), palette)); + } + } +} diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index e76aa1ef5c..8496ab0806 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -123,6 +123,8 @@ + + @@ -306,6 +308,7 @@ + diff --git a/OpenRA.Mods.RA/Player/PlaceBeacon.cs b/OpenRA.Mods.RA/Player/PlaceBeacon.cs new file mode 100644 index 0000000000..8e7464744f --- /dev/null +++ b/OpenRA.Mods.RA/Player/PlaceBeacon.cs @@ -0,0 +1,73 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) + * 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. For more information, + * see COPYING. + */ +#endregion + +using OpenRA.Mods.RA.Effects; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + public class PlaceBeaconInfo : ITraitInfo + { + public readonly int Duration = 30 * 25; + public readonly string NotificationType = "Sounds"; + public readonly string Notification = "Beacon"; + public readonly string PalettePrefix = "player"; + + public object Create(ActorInitializer init) { return new PlaceBeacon(init.self, this); } + } + + public class PlaceBeacon : IResolveOrder + { + readonly PlaceBeaconInfo info; + readonly RadarPings radarPings; + + Beacon playerBeacon; + RadarPing playerRadarPing; + + public PlaceBeacon(Actor self, PlaceBeaconInfo info) + { + radarPings = self.World.WorldActor.TraitOrDefault(); + this.info = info; + } + + public void ResolveOrder(Actor self, Order order) + { + if (order.OrderString != "PlaceBeacon") + return; + + var pos = order.TargetLocation.CenterPosition; + + self.World.AddFrameEndTask(w => + { + if (playerBeacon != null) + self.World.Remove(playerBeacon); + + playerBeacon = new Beacon(self.Owner, pos, info.Duration, info.PalettePrefix); + self.World.Add(playerBeacon); + + if (self.Owner.IsAlliedWith(self.World.RenderPlayer)) + Sound.PlayNotification(null, info.NotificationType, info.Notification, + self.World.RenderPlayer != null ? self.World.RenderPlayer.Country.Race : null); + + if (radarPings != null) + { + if (playerRadarPing != null) + radarPings.Remove(playerRadarPing); + + playerRadarPing = radarPings.Add( + () => self.Owner.IsAlliedWith(self.World.RenderPlayer), + pos, + self.Owner.Color.RGB, + info.Duration); + } + }); + } + } +} diff --git a/OpenRA.Mods.RA/Widgets/Logic/SettingsLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/SettingsLogic.cs index 5a39b2584e..d59cc7a376 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/SettingsLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/SettingsLogic.cs @@ -255,6 +255,8 @@ namespace OpenRA.Mods.RA.Widgets.Logic { "SelectAllUnitsKey", "Select all units on screen" }, { "SelectUnitsByTypeKey", "Select units by type" }, + { "PlaceBeaconKey", "Place beacon" }, + { "PauseKey", "Pause / Unpause" }, { "SellKey", "Sell mode" }, { "PowerDownKey", "Power-down mode" }, diff --git a/OpenRA.Mods.RA/Widgets/RadarWidget.cs b/OpenRA.Mods.RA/Widgets/RadarWidget.cs index f5c18abd30..7e5da024ad 100755 --- a/OpenRA.Mods.RA/Widgets/RadarWidget.cs +++ b/OpenRA.Mods.RA/Widgets/RadarWidget.cs @@ -10,6 +10,7 @@ using System; using System.Drawing; +using System.Linq; using OpenRA.Graphics; using OpenRA.Widgets; @@ -22,8 +23,8 @@ namespace OpenRA.Mods.RA.Widgets public string RadarOnlineSound = null; public string RadarOfflineSound = null; public Func IsEnabled = () => true; - public Action AfterOpen = () => {}; - public Action AfterClose = () => {}; + public Action AfterOpen = () => { }; + public Action AfterClose = () => { }; float radarMinimapHeight; int frame; @@ -43,11 +44,14 @@ namespace OpenRA.Mods.RA.Widgets readonly World world; readonly WorldRenderer worldRenderer; + readonly RadarPings radarPings; + [ObjectCreator.UseCtor] public RadarWidget(World world, WorldRenderer worldRenderer) { this.world = world; this.worldRenderer = worldRenderer; + radarPings = world.WorldActor.TraitOrDefault(); } public override void Initialize(WidgetArgs args) @@ -60,8 +64,8 @@ namespace OpenRA.Mods.RA.Widgets var rb = RenderBounds; previewScale = Math.Min(rb.Width * 1f / width, rb.Height * 1f / height); - previewOrigin = new int2((int)(previewScale*(size - width)/2), (int)(previewScale*(size - height)/2)); - mapRect = new Rectangle(previewOrigin.X, previewOrigin.Y, (int)(previewScale*width), (int)(previewScale*height)); + previewOrigin = new int2((int)(previewScale * (size - width) / 2), (int)(previewScale * (size - height) / 2)); + mapRect = new Rectangle(previewOrigin.X, previewOrigin.Y, (int)(previewScale * width), (int)(previewScale * height)); // Only needs to be done once var terrainBitmap = Minimap.TerrainBitmap(world.Map); @@ -95,7 +99,7 @@ namespace OpenRA.Mods.RA.Widgets if (cursor == null) return "default"; - return CursorProvider.HasCursorSequence(cursor+"-minimap") ? cursor+"-minimap" : cursor; + return CursorProvider.HasCursorSequence(cursor + "-minimap") ? cursor + "-minimap" : cursor; } public override bool HandleMouseInput(MouseInput mi) @@ -140,8 +144,8 @@ namespace OpenRA.Mods.RA.Widgets if (world == null) return; - var o = new float2(mapRect.Location.X, mapRect.Location.Y + world.Map.Bounds.Height * previewScale * (1 - radarMinimapHeight)/2); - var s = new float2(mapRect.Size.Width, mapRect.Size.Height*radarMinimapHeight); + var o = new float2(mapRect.Location.X, mapRect.Location.Y + world.Map.Bounds.Height * previewScale * (1 - radarMinimapHeight) / 2); + var s = new float2(mapRect.Size.Width, mapRect.Size.Height * radarMinimapHeight); var rsr = Game.Renderer.RgbaSpriteRenderer; rsr.DrawSprite(terrainSprite, o, s); @@ -156,11 +160,34 @@ namespace OpenRA.Mods.RA.Widgets var br = CellToMinimapPixel(worldRenderer.Position(worldRenderer.Viewport.BottomRight).ToCPos()); Game.Renderer.EnableScissor(mapRect); + DrawRadarPings(); Game.Renderer.LineRenderer.DrawRect(tl, br, Color.White); Game.Renderer.DisableScissor(); } } + void DrawRadarPings() + { + if (radarPings == null) + return; + + var lr = Game.Renderer.LineRenderer; + var oldWidth = lr.LineWidth; + lr.LineWidth = 2; + + foreach (var radarPing in radarPings.Pings.Where(e => e.IsVisible())) + { + var c = radarPing.Color; + var points = radarPing.Points(CellToMinimapPixel(radarPing.Position.ToCPos())).ToArray(); + + lr.DrawLine(points[0], points[1], c, c); + lr.DrawLine(points[1], points[2], c, c); + lr.DrawLine(points[2], points[0], c, c); + } + + lr.LineWidth = oldWidth; + } + public override void Tick() { // Update the radar animation even when its closed diff --git a/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs b/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs index ca05bf27ed..bdc4837c39 100644 --- a/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs +++ b/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs @@ -63,6 +63,9 @@ namespace OpenRA.Mods.RA.Widgets if (key == ks.ToggleStatusBarsKey) return ToggleStatusBars(); + if (key == ks.PlaceBeaconKey) + return PerformPlaceBeacon(); + // Put all functions that aren't unit-specific before this line! if (!world.Selection.Actors.Any()) return false; @@ -180,6 +183,15 @@ namespace OpenRA.Mods.RA.Widgets return true; } + bool PerformPlaceBeacon() + { + if (world.LocalPlayer == null) + return true; + + world.OrderGenerator = new GenericSelectTarget(world.LocalPlayer.PlayerActor, "PlaceBeacon", "ability"); + return true; + } + bool CycleBases() { var bases = world.ActorsWithTrait() diff --git a/OpenRA.Mods.RA/World/RadarPings.cs b/OpenRA.Mods.RA/World/RadarPings.cs new file mode 100644 index 0000000000..a9677f5f18 --- /dev/null +++ b/OpenRA.Mods.RA/World/RadarPings.cs @@ -0,0 +1,106 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 The OpenRA Developers (see AUTHORS) + * 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. For more information, + * see COPYING. + */ +#endregion + +using System; +using System.Collections.Generic; +using System.Drawing; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA +{ + public class RadarPingsInfo : ITraitInfo + { + public readonly int FromRadius = 200; + public readonly int ToRadius = 15; + public readonly int ShrinkSpeed = 4; + public readonly float RotationSpeed = 0.12f; + + public object Create(ActorInitializer init) { return new RadarPings(this); } + } + + public class RadarPings : ITick + { + public readonly List Pings = new List(); + readonly RadarPingsInfo info; + + public RadarPings(RadarPingsInfo info) + { + this.info = info; + } + + public void Tick(Actor self) + { + foreach (var ping in Pings.ToArray()) + if (!ping.Tick()) + Pings.Remove(ping); + } + + public RadarPing Add(Func isVisible, WPos position, Color color, int duration) + { + var ping = new RadarPing(isVisible, position, color, duration, + info.FromRadius, info.ToRadius, info.ShrinkSpeed, info.RotationSpeed); + Pings.Add(ping); + return ping; + } + + public void Remove(RadarPing ping) + { + Pings.Remove(ping); + } + } + + public class RadarPing + { + public Func IsVisible; + public WPos Position; + public Color Color; + public int Duration; + public int FromRadius; + public int ToRadius; + public int ShrinkSpeed; + public float RotationSpeed; + + int radius; + float angle; + int tick; + + public RadarPing(Func isVisible, WPos position, Color color, int duration, + int fromRadius, int toRadius, int shrinkSpeed, float rotationSpeed) + { + IsVisible = isVisible; + Position = position; + Color = color; + Duration = duration; + FromRadius = fromRadius; + ToRadius = toRadius; + ShrinkSpeed = shrinkSpeed; + RotationSpeed = rotationSpeed; + + radius = fromRadius; + } + + public bool Tick() + { + if (++tick == Duration) + return false; + + radius = Math.Max(radius - ShrinkSpeed, ToRadius); + angle -= RotationSpeed; + return true; + } + + public IEnumerable Points(float2 center) + { + yield return center + radius * float2.FromAngle(angle); + yield return center + radius * float2.FromAngle((float)(angle + 2 * Math.PI / 3)); + yield return center + radius * float2.FromAngle((float)(angle + 4 * Math.PI / 3)); + } + } +} diff --git a/mods/cnc/notifications.yaml b/mods/cnc/notifications.yaml index 332fb91e32..0c77532935 100644 --- a/mods/cnc/notifications.yaml +++ b/mods/cnc/notifications.yaml @@ -41,4 +41,5 @@ Sounds: ChatLine: scold1 TabClick: button ClickSound: button - ClickDisabledSound: scold2 \ No newline at end of file + ClickDisabledSound: scold2 + Beacon: bleep2 \ No newline at end of file diff --git a/mods/cnc/rules/system-player.yaml b/mods/cnc/rules/system-player.yaml index 35137a0f78..e069fb86b8 100644 --- a/mods/cnc/rules/system-player.yaml +++ b/mods/cnc/rules/system-player.yaml @@ -16,4 +16,5 @@ Player: Shroud: PlayerStatistics: FrozenActorLayer: + PlaceBeacon: diff --git a/mods/cnc/rules/system-world.yaml b/mods/cnc/rules/system-world.yaml index 45b5f8cc7d..c4e96ebc5e 100644 --- a/mods/cnc/rules/system-world.yaml +++ b/mods/cnc/rules/system-world.yaml @@ -175,4 +175,4 @@ World: DebugPauseState: ConquestObjectivesPanel: ObjectivesPanel: CONQUEST_OBJECTIVES - + RadarPings: diff --git a/mods/cnc/sequences/misc.yaml b/mods/cnc/sequences/misc.yaml index e8416aa33a..cdf291b8af 100644 --- a/mods/cnc/sequences/misc.yaml +++ b/mods/cnc/sequences/misc.yaml @@ -152,6 +152,14 @@ rallypoint: Start: 0 Length: * +beacon: + arrow: mouse2 + Start: 5 + Offset: 1,-12 + circles: fpls + Start: 0 + Length: * + select: repair: Start: 2 diff --git a/mods/d2k/notifications.yaml b/mods/d2k/notifications.yaml index b5f75abadb..56c3dffc63 100644 --- a/mods/d2k/notifications.yaml +++ b/mods/d2k/notifications.yaml @@ -47,4 +47,5 @@ Sounds: BuildPaletteClose: BUTTON1 TabClick: SIDEBAR1 ClickSound: BUTTON1 - ClickDisabledSound: ENDLIST1 \ No newline at end of file + ClickDisabledSound: ENDLIST1 + Beacon: CHAT1 \ No newline at end of file diff --git a/mods/d2k/rules/system-player.yaml b/mods/d2k/rules/system-player.yaml index 1c8a8ba9e7..f77b6564f4 100644 --- a/mods/d2k/rules/system-player.yaml +++ b/mods/d2k/rules/system-player.yaml @@ -51,4 +51,4 @@ Player: FrozenActorLayer: HarvesterAttackNotifier: PlayerStatistics: - + PlaceBeacon: diff --git a/mods/d2k/rules/system-world.yaml b/mods/d2k/rules/system-world.yaml index f406e4b2ae..620fdb5b6a 100644 --- a/mods/d2k/rules/system-world.yaml +++ b/mods/d2k/rules/system-world.yaml @@ -126,4 +126,4 @@ World: PathFinder: ValidateOrder: DebugPauseState: - + RadarPings: diff --git a/mods/d2k/sequences/misc.yaml b/mods/d2k/sequences/misc.yaml index fc9610a36d..c8f3a9c45d 100644 --- a/mods/d2k/sequences/misc.yaml +++ b/mods/d2k/sequences/misc.yaml @@ -130,6 +130,14 @@ rallypoint: Start: 0 Length: * +beacon: + arrow: mouse + Start: 148 + Offset: -24,-24 + circles: fpls + Start: 0 + Length: * + rpg: idle: DATA Start: 3015 diff --git a/mods/ra/notifications.yaml b/mods/ra/notifications.yaml index e906c504a4..7c8a43af9e 100644 --- a/mods/ra/notifications.yaml +++ b/mods/ra/notifications.yaml @@ -42,4 +42,5 @@ Sounds: BuildPaletteClose: bleep13 TabClick: ramenu1 ClickSound: - ClickDisabledSound: \ No newline at end of file + ClickDisabledSound: + Beacon: beepslct \ No newline at end of file diff --git a/mods/ra/rules/system-player.yaml b/mods/ra/rules/system-player.yaml index 79cf0050d8..b58265e0de 100644 --- a/mods/ra/rules/system-player.yaml +++ b/mods/ra/rules/system-player.yaml @@ -56,4 +56,5 @@ Player: FrozenActorLayer: BaseAttackNotifier: PlayerStatistics: + PlaceBeacon: diff --git a/mods/ra/rules/system-world.yaml b/mods/ra/rules/system-world.yaml index 2838fd5d42..16b08f4b59 100644 --- a/mods/ra/rules/system-world.yaml +++ b/mods/ra/rules/system-world.yaml @@ -164,4 +164,4 @@ World: PathFinder: ValidateOrder: DebugPauseState: - + RadarPings: diff --git a/mods/ra/sequences/misc.yaml b/mods/ra/sequences/misc.yaml index 7cd65490c0..245a6fce3a 100644 --- a/mods/ra/sequences/misc.yaml +++ b/mods/ra/sequences/misc.yaml @@ -114,6 +114,14 @@ rallypoint: Start: 0 Length: * +beacon: + arrow: mouse + Start: 5 + Offset: 1,-12 + circles: fpls + Start: 0 + Length: * + smoke_m: idle: Start: 0 diff --git a/mods/ts/notifications.yaml b/mods/ts/notifications.yaml index 8b0e113afd..f6e5c00a4e 100644 --- a/mods/ts/notifications.yaml +++ b/mods/ts/notifications.yaml @@ -39,4 +39,5 @@ Sounds: BuildPaletteClose: TabClick: ClickSound:clicky1 - ClickDisabledSound:wrong1 \ No newline at end of file + ClickDisabledSound:wrong1 + Beacon: message1 \ No newline at end of file diff --git a/mods/ts/rules/system-player.yaml b/mods/ts/rules/system-player.yaml index addcb00bf6..eb6ac74e48 100644 --- a/mods/ts/rules/system-player.yaml +++ b/mods/ts/rules/system-player.yaml @@ -40,4 +40,4 @@ Player: Shroud: BaseAttackNotifier: PlayerStatistics: - + PlaceBeacon: diff --git a/mods/ts/rules/system-world.yaml b/mods/ts/rules/system-world.yaml index 20b439841f..a5e1818a42 100644 --- a/mods/ts/rules/system-world.yaml +++ b/mods/ts/rules/system-world.yaml @@ -96,4 +96,4 @@ World: ValidateOrder: DebugPauseState: ScreenShaker: - + RadarPings: \ No newline at end of file diff --git a/mods/ts/sequences/misc.yaml b/mods/ts/sequences/misc.yaml index d0b62f2f01..bcba708efa 100644 --- a/mods/ts/sequences/misc.yaml +++ b/mods/ts/sequences/misc.yaml @@ -44,6 +44,15 @@ rallypoint: Length: 12 BlendMode: Additive +beacon: + arrow: mouse + Start: 6 + Offset: 1,-12 + circles: ring + Start: 0 + Length: 12 + BlendMode: Additive + rank: # TODO: backfall to RA asset rank: Start: 0 From 06caf7f156e253b65216627bf0189b6010dbd479 Mon Sep 17 00:00:00 2001 From: ScottNZ Date: Thu, 20 Feb 2014 21:14:32 +1300 Subject: [PATCH 2/5] Add radar pings to BaseAttackNotifier and HarvesterAttackNotifier --- OpenRA.Mods.RA/Player/BaseAttackNotifier.cs | 22 +++++++++++++++---- .../Player/HarvesterAttackNotifier.cs | 22 +++++++++++++++---- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs b/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs index a186604049..1a67f6ae84 100644 --- a/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs +++ b/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs @@ -8,6 +8,7 @@ */ #endregion +using System.Drawing; using OpenRA.Mods.RA.Buildings; using OpenRA.Traits; @@ -16,18 +17,26 @@ namespace OpenRA.Mods.RA public class BaseAttackNotifierInfo : ITraitInfo { public readonly int NotifyInterval = 30; // seconds + public readonly Color RadarPingColor = Color.Red; + public readonly int RadarPingDuration = 10 * 25; - public object Create(ActorInitializer init) { return new BaseAttackNotifier(this); } + public object Create(ActorInitializer init) { return new BaseAttackNotifier(init.self, this); } } public class BaseAttackNotifier : INotifyDamage { - BaseAttackNotifierInfo info; + readonly RadarPings radarPings; + readonly BaseAttackNotifierInfo info; - public int lastAttackTime = -1; + public int lastAttackTime; public CPos lastAttackLocation; - public BaseAttackNotifier(BaseAttackNotifierInfo info) { this.info = info; } + public BaseAttackNotifier(Actor self, BaseAttackNotifierInfo info) + { + radarPings = self.World.WorldActor.TraitOrDefault(); + this.info = info; + lastAttackTime = -info.NotifyInterval * 25; + } public void Damaged(Actor self, AttackInfo e) { @@ -45,8 +54,13 @@ namespace OpenRA.Mods.RA return; if (self.World.FrameNumber - lastAttackTime > info.NotifyInterval * 25) + { Sound.PlayNotification(self.Owner, "Speech", "BaseAttack", self.Owner.Country.Race); + if (radarPings != null) + radarPings.Add(() => self.Owner == self.World.LocalPlayer, self.CenterPosition, info.RadarPingColor, info.RadarPingDuration); + } + lastAttackLocation = self.CenterPosition.ToCPos(); lastAttackTime = self.World.FrameNumber; } diff --git a/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs b/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs index 4f790f9df0..86ddce48a3 100644 --- a/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs +++ b/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs @@ -8,6 +8,7 @@ */ #endregion +using System.Drawing; using OpenRA.Traits; namespace OpenRA.Mods.RA @@ -15,18 +16,26 @@ namespace OpenRA.Mods.RA public class HarvesterAttackNotifierInfo : ITraitInfo { public readonly int NotifyInterval = 30; // seconds + public readonly Color RadarPingColor = Color.Red; + public readonly int RadarPingDuration = 10 * 25; - public object Create(ActorInitializer init) { return new HarvesterAttackNotifier(this); } + public object Create(ActorInitializer init) { return new HarvesterAttackNotifier(init.self, this); } } public class HarvesterAttackNotifier : INotifyDamage { - HarvesterAttackNotifierInfo info; + readonly RadarPings radarPings; + readonly HarvesterAttackNotifierInfo info; - public int lastAttackTime = -1; + public int lastAttackTime; public CPos lastAttackLocation; - public HarvesterAttackNotifier(HarvesterAttackNotifierInfo info) { this.info = info; } + public HarvesterAttackNotifier(Actor self, HarvesterAttackNotifierInfo info) + { + radarPings = self.World.WorldActor.TraitOrDefault(); + this.info = info; + lastAttackTime = -info.NotifyInterval * 25; + } public void Damaged(Actor self, AttackInfo e) { @@ -39,8 +48,13 @@ namespace OpenRA.Mods.RA return; if (self.World.FrameNumber - lastAttackTime > info.NotifyInterval * 25) + { Sound.PlayNotification(self.Owner, "Speech", "HarvesterAttack", self.Owner.Country.Race); + if (radarPings != null) + radarPings.Add(() => self.Owner == self.World.LocalPlayer, self.CenterPosition, info.RadarPingColor, info.RadarPingDuration); + } + lastAttackLocation = self.CenterPosition.ToCPos(); lastAttackTime = self.World.FrameNumber; } From 0a9a959ecfebafac7b2c2a0e9205da2a9fc6499c Mon Sep 17 00:00:00 2001 From: ScottNZ Date: Fri, 21 Feb 2014 22:11:43 +1300 Subject: [PATCH 3/5] Change spacebar key to move to the last visible radar ping location --- OpenRA.Mods.RA/Player/BaseAttackNotifier.cs | 4 +--- OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs | 4 +--- OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs | 13 ++++--------- OpenRA.Mods.RA/World/RadarPings.cs | 7 +++++++ 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs b/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs index 1a67f6ae84..a905455cb7 100644 --- a/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs +++ b/OpenRA.Mods.RA/Player/BaseAttackNotifier.cs @@ -28,8 +28,7 @@ namespace OpenRA.Mods.RA readonly RadarPings radarPings; readonly BaseAttackNotifierInfo info; - public int lastAttackTime; - public CPos lastAttackLocation; + int lastAttackTime; public BaseAttackNotifier(Actor self, BaseAttackNotifierInfo info) { @@ -61,7 +60,6 @@ namespace OpenRA.Mods.RA radarPings.Add(() => self.Owner == self.World.LocalPlayer, self.CenterPosition, info.RadarPingColor, info.RadarPingDuration); } - lastAttackLocation = self.CenterPosition.ToCPos(); lastAttackTime = self.World.FrameNumber; } } diff --git a/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs b/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs index 86ddce48a3..29e773592a 100644 --- a/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs +++ b/OpenRA.Mods.RA/Player/HarvesterAttackNotifier.cs @@ -27,8 +27,7 @@ namespace OpenRA.Mods.RA readonly RadarPings radarPings; readonly HarvesterAttackNotifierInfo info; - public int lastAttackTime; - public CPos lastAttackLocation; + int lastAttackTime; public HarvesterAttackNotifier(Actor self, HarvesterAttackNotifierInfo info) { @@ -55,7 +54,6 @@ namespace OpenRA.Mods.RA radarPings.Add(() => self.Owner == self.World.LocalPlayer, self.CenterPosition, info.RadarPingColor, info.RadarPingDuration); } - lastAttackLocation = self.CenterPosition.ToCPos(); lastAttackTime = self.World.FrameNumber; } } diff --git a/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs b/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs index bdc4837c39..fbd056e4ee 100644 --- a/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs +++ b/OpenRA.Mods.RA/Widgets/WorldCommandWidget.cs @@ -22,12 +22,14 @@ namespace OpenRA.Mods.RA.Widgets { readonly World world; readonly WorldRenderer worldRenderer; + readonly RadarPings radarPings; [ObjectCreator.UseCtor] public WorldCommandWidget(World world, WorldRenderer worldRenderer) { this.world = world; this.worldRenderer = worldRenderer; + radarPings = world.WorldActor.TraitOrDefault(); } public override string GetCursor(int2 pos) { return null; } @@ -241,17 +243,10 @@ namespace OpenRA.Mods.RA.Widgets bool ToLastEvent() { - if (world.LocalPlayer == null) + if (radarPings == null || radarPings.LastPingPosition == null) return true; - var eventNotifier = world.LocalPlayer.PlayerActor.TraitOrDefault(); - if (eventNotifier == null) - return true; - - if (eventNotifier.lastAttackTime < 0) - return true; - - worldRenderer.Viewport.Center(eventNotifier.lastAttackLocation.CenterPosition); + worldRenderer.Viewport.Center(radarPings.LastPingPosition.Value); return true; } diff --git a/OpenRA.Mods.RA/World/RadarPings.cs b/OpenRA.Mods.RA/World/RadarPings.cs index a9677f5f18..1a0cd22dc2 100644 --- a/OpenRA.Mods.RA/World/RadarPings.cs +++ b/OpenRA.Mods.RA/World/RadarPings.cs @@ -30,6 +30,8 @@ namespace OpenRA.Mods.RA public readonly List Pings = new List(); readonly RadarPingsInfo info; + public WPos? LastPingPosition; + public RadarPings(RadarPingsInfo info) { this.info = info; @@ -46,7 +48,12 @@ namespace OpenRA.Mods.RA { var ping = new RadarPing(isVisible, position, color, duration, info.FromRadius, info.ToRadius, info.ShrinkSpeed, info.RotationSpeed); + + if (ping.IsVisible()) + LastPingPosition = ping.Position; + Pings.Add(ping); + return ping; } From 338fb38bd3ab39d7bdd90bedb6b11f9251059d29 Mon Sep 17 00:00:00 2001 From: ScottNZ Date: Sat, 22 Feb 2014 00:00:15 +1300 Subject: [PATCH 4/5] Add beacon/radar ping placements for nukes/ion cannons/chronospheres/iron curtains. --- OpenRA.Mods.RA/SupportPowers/SupportPower.cs | 5 ++++ .../SupportPowers/SupportPowerManager.cs | 27 ++++++++++++++++--- mods/cnc/rules/structures.yaml | 4 +++ mods/d2k/rules/harkonnen.yaml | 2 ++ mods/ra/rules/structures.yaml | 4 +++ 5 files changed, 38 insertions(+), 4 deletions(-) diff --git a/OpenRA.Mods.RA/SupportPowers/SupportPower.cs b/OpenRA.Mods.RA/SupportPowers/SupportPower.cs index da5deaae1d..f55b13c043 100755 --- a/OpenRA.Mods.RA/SupportPowers/SupportPower.cs +++ b/OpenRA.Mods.RA/SupportPowers/SupportPower.cs @@ -30,6 +30,11 @@ namespace OpenRA.Mods.RA public readonly bool DisplayTimer = false; + public readonly bool DisplayBeacon = false; + public readonly int BeaconDuration = 10 * 25; + public readonly string BeaconPalettePrefix = "player"; + public readonly bool DisplayRadarPing = false; + public readonly string OrderName; public abstract object Create(ActorInitializer init); diff --git a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs index 2e3437e499..9a09541944 100755 --- a/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs +++ b/OpenRA.Mods.RA/SupportPowers/SupportPowerManager.cs @@ -10,7 +10,9 @@ using System.Collections.Generic; using System.Linq; +using OpenRA.FileFormats; using OpenRA.Graphics; +using OpenRA.Mods.RA.Effects; using OpenRA.Traits; namespace OpenRA.Mods.RA @@ -23,13 +25,16 @@ namespace OpenRA.Mods.RA public class SupportPowerManager : ITick, IResolveOrder { public readonly Actor self; - public Dictionary Powers = new Dictionary(); + public readonly Dictionary Powers = new Dictionary(); + + public readonly DeveloperMode DevMode; + public readonly Lazy RadarPings; - public readonly DeveloperMode devMode; public SupportPowerManager(ActorInitializer init) { self = init.self; - devMode = init.self.Trait(); + DevMode = init.self.Trait(); + RadarPings = Lazy.New(() => init.world.WorldActor.TraitOrDefault()); init.world.ActorAdded += ActorAdded; init.world.ActorRemoved += ActorRemoved; @@ -148,7 +153,7 @@ namespace OpenRA.Mods.RA if (Active) { var power = Instances.First(); - if (Manager.devMode.FastCharge && RemainingTime > 25) + if (Manager.DevMode.FastCharge && RemainingTime > 25) RemainingTime = 25; if (RemainingTime > 0) --RemainingTime; @@ -187,6 +192,20 @@ namespace OpenRA.Mods.RA RemainingTime = TotalTime; notifiedCharging = notifiedReady = false; + if (power.Info.DisplayBeacon) + power.self.World.Add(new Beacon( + order.Player, + order.TargetLocation.CenterPosition, + power.Info.BeaconDuration, + power.Info.BeaconPalettePrefix)); + + if (power.Info.DisplayRadarPing && Manager.RadarPings != null) + Manager.RadarPings.Value.Add( + () => order.Player.IsAlliedWith(power.self.World.RenderPlayer), + order.TargetLocation.CenterPosition, + order.Player.Color.RGB, + power.Info.BeaconDuration); + if (Info.OneShot) Disabled = true; } diff --git a/mods/cnc/rules/structures.yaml b/mods/cnc/rules/structures.yaml index 0df2bee7b7..56289c78eb 100644 --- a/mods/cnc/rules/structures.yaml +++ b/mods/cnc/rules/structures.yaml @@ -445,6 +445,8 @@ EYE: LaunchSound: ion1.aud SelectTargetSound: select1.aud InsufficientPowerSound: nopower1.aud + DisplayBeacon: True + DisplayRadarPing: True SupportPowerChargeBar: TMPL: @@ -483,6 +485,8 @@ TMPL: LaunchSound: nuklnch1.aud IncomingSound: nuke1.aud MissileWeapon: atomic + DisplayBeacon: True + DisplayRadarPing: True SupportPowerChargeBar: GUN: diff --git a/mods/d2k/rules/harkonnen.yaml b/mods/d2k/rules/harkonnen.yaml index 7b95b5c44d..507055f77d 100644 --- a/mods/d2k/rules/harkonnen.yaml +++ b/mods/d2k/rules/harkonnen.yaml @@ -96,6 +96,8 @@ PALACEH: IncomingSound: MissileWeapon: atomic SpawnOffset: -512,1c171,0 + DisplayBeacon: True + DisplayRadarPing: True CanPowerDown: RequiresPower: SupportPowerChargeBar: diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 5825d961d1..50e94cbd72 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -37,6 +37,8 @@ MSLO: MissileWeapon: atomic SpawnOffset: 0,427,0 DisplayTimer: True + DisplayBeacon: True + DisplayRadarPing: True CanPowerDown: RequiresPower: SupportPowerChargeBar: @@ -224,6 +226,7 @@ IRON: InsufficientPowerSound: nopowr1.aud BeginChargeSound: ironchg1.aud EndChargeSound: ironrdy1.aud + DisplayRadarPing: True SupportPowerChargeBar: PDOX: @@ -264,6 +267,7 @@ PDOX: EndChargeSound: chrordy1.aud Duration: 20 KillCargo: yes + DisplayRadarPing: True SupportPowerChargeBar: -AcceptsSupplies: From b469351f8fd6d28815773c230a15761aba065b6e Mon Sep 17 00:00:00 2001 From: ScottNZ Date: Sun, 23 Feb 2014 13:15:06 +1300 Subject: [PATCH 5/5] Update CHANGELOG for map beacons/radar pings --- CHANGELOG | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 948bd7b04c..3cdcabce5c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ NEW: All Mods: + Added the ability to place map beacons for highlighting areas to teammates. + Structures under attack and friendly superweapon launch targets will now be highlighted on the radar. Fixed unloading passengers moving unnecessarily far from their transport. Fixed the unload cursor sometimes being displayed for transports even when they were unable to unload. An error dialog is now displayed when server connections are lost.