Add support for transient text notifications matching speech notifications

This commit is contained in:
Ivaylo Draganov
2022-01-08 18:28:25 +02:00
committed by Paul Chote
parent 9f723be65a
commit 24b9482cc1
50 changed files with 372 additions and 46 deletions

View File

@@ -26,12 +26,13 @@ namespace OpenRA
SystemMessageLabel = "Battlefield Control";
}
public static void AddTransientLine(string text)
public static void AddTransientLine(string text, Player player)
{
if (string.IsNullOrEmpty(text))
return;
AddTextNotification(TextNotificationPool.Transients, SystemMessageLabel, text);
if (player == null || player == player.World.LocalPlayer)
AddTextNotification(TextNotificationPool.Transients, SystemMessageLabel, text);
}
public static void AddFeedbackLine(string text)

View File

@@ -71,6 +71,8 @@ namespace OpenRA.Mods.Cnc.Activities
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech",
infiltrates.Info.Notification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(infiltrates.Info.TextNotification, self.Owner);
if (infiltrates.Info.EnterBehaviour == EnterBehaviour.Dispose)
self.Dispose();
else if (infiltrates.Info.EnterBehaviour == EnterBehaviour.Suicide)

View File

@@ -37,10 +37,16 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Sound the victim will hear when they get robbed.")]
public readonly string InfiltratedNotification = null;
[Desc("Text notification the victim will see when they get robbed.")]
public readonly string InfiltratedTextNotification = null;
[NotificationReference("Speech")]
[Desc("Sound the perpetrator will hear after successful infiltration.")]
public readonly string InfiltrationNotification = null;
[Desc("Text notification the perpetrator will see after successful infiltration.")]
public readonly string InfiltrationTextNotification = null;
[Desc("Whether to show the cash tick indicators rising from the actor.")]
public readonly bool ShowTicks = true;
@@ -74,6 +80,9 @@ namespace OpenRA.Mods.Cnc.Traits
if (info.InfiltrationNotification != null)
Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner);
TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner);
if (info.ShowTicks)
self.World.AddFrameEndTask(w => w.Add(new FloatingText(self.CenterPosition, infiltrator.Owner.Color, FloatingText.FormatCashTick(toGive), 30)));
}

View File

@@ -26,10 +26,16 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Sound the victim will hear when they get sabotaged.")]
public readonly string InfiltratedNotification = null;
[Desc("Text notification the victim will see when they get sabotaged.")]
public readonly string InfiltratedTextNotification = null;
[NotificationReference("Speech")]
[Desc("Sound the perpetrator will hear after successful infiltration.")]
public readonly string InfiltrationNotification = null;
[Desc("Text notification the perpetrator will see after successful infiltration.")]
public readonly string InfiltrationTextNotification = null;
public override object Create(ActorInitializer init) { return new InfiltrateForExploration(this); }
}
@@ -53,6 +59,9 @@ namespace OpenRA.Mods.Cnc.Traits
if (info.InfiltrationNotification != null)
Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner);
TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner);
infiltrator.Owner.Shroud.Explore(self.Owner.Shroud);
var preventReset = self.Owner.PlayerActor.TraitsImplementing<IPreventsShroudReset>()
.Any(p => p.PreventShroudReset(self));

View File

@@ -27,10 +27,16 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Sound the victim will hear when they get sabotaged.")]
public readonly string InfiltratedNotification = null;
[Desc("Text notification the victim will see when they get sabotaged.")]
public readonly string InfiltratedTextNotification = null;
[NotificationReference("Speech")]
[Desc("Sound the perpetrator will hear after successful infiltration.")]
public readonly string InfiltrationNotification = null;
[Desc("Text notification the perpetrator will see after successful infiltration.")]
public readonly string InfiltrationTextNotification = null;
public override object Create(ActorInitializer init) { return new InfiltrateForPowerOutage(init.Self, this); }
}
@@ -56,6 +62,9 @@ namespace OpenRA.Mods.Cnc.Traits
if (info.InfiltrationNotification != null)
Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner);
TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner);
playerPower.TriggerPowerOutage(info.Duration);
}

View File

@@ -28,10 +28,16 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Sound the victim will hear when technology gets stolen.")]
public readonly string InfiltratedNotification = null;
[Desc("Text notification the victim will see when technology gets stolen.")]
public readonly string InfiltratedTextNotification = null;
[NotificationReference("Speech")]
[Desc("Sound the perpetrator will hear after successful infiltration.")]
public readonly string InfiltrationNotification = null;
[Desc("Text notification the perpetrator will see after successful infiltration.")]
public readonly string InfiltrationTextNotification = null;
public override object Create(ActorInitializer init) { return new InfiltrateForSupportPower(this); }
}
@@ -55,6 +61,9 @@ namespace OpenRA.Mods.Cnc.Traits
if (info.InfiltrationNotification != null)
Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner);
TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner);
infiltrator.World.AddFrameEndTask(w => w.CreateActor(info.Proxy, new TypeDictionary
{
new OwnerInit(infiltrator.Owner)

View File

@@ -22,13 +22,19 @@ namespace OpenRA.Mods.Cnc.Traits
public readonly BitSet<TargetableType> Types = default(BitSet<TargetableType>);
[NotificationReference("Speech")]
[Desc("Sound the victim will hear when technology gets stolen.")]
[Desc("Sound the victim will hear when they get sabotaged.")]
public readonly string InfiltratedNotification = null;
[Desc("Text notification the victim will see when they get sabotaged.")]
public readonly string InfiltratedTextNotification = null;
[NotificationReference("Speech")]
[Desc("Sound the perpetrator will hear after successful infiltration.")]
public readonly string InfiltrationNotification = null;
[Desc("Text notification the perpetrator will see after successful infiltration.")]
public readonly string InfiltrationTextNotification = null;
public override object Create(ActorInitializer init) { return new InfiltrateForSupportPowerReset(this); }
}
@@ -52,6 +58,9 @@ namespace OpenRA.Mods.Cnc.Traits
if (info.InfiltrationNotification != null)
Game.Sound.PlayNotification(self.World.Map.Rules, infiltrator.Owner, "Speech", info.InfiltrationNotification, infiltrator.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.InfiltratedTextNotification, self.Owner);
TextNotificationsManager.AddTransientLine(info.InfiltrationTextNotification, infiltrator.Owner);
var manager = self.Owner.PlayerActor.Trait<SupportPowerManager>();
var powers = manager.GetPowersForActor(self).Where(sp => !sp.Disabled);
foreach (var power in powers)

View File

@@ -41,6 +41,9 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Notification to play when a target is infiltrated.")]
public readonly string Notification = null;
[Desc("Text notification to display when a target is infiltrated.")]
public readonly string TextNotification = null;
[Desc("Experience to grant to the infiltrating player.")]
public readonly int PlayerExperience = 0;

View File

@@ -18,17 +18,19 @@ namespace OpenRA.Mods.Common.Activities
class RepairBridge : Enter
{
readonly EnterBehaviour enterBehaviour;
readonly string notification;
readonly string speechNotification;
readonly string textNotification;
Actor enterActor;
BridgeHut enterHut;
LegacyBridgeHut enterLegacyHut;
public RepairBridge(Actor self, in Target target, EnterBehaviour enterBehaviour, string notification, Color targetLineColor)
public RepairBridge(Actor self, in Target target, EnterBehaviour enterBehaviour, string speechNotification, string textNotification, Color targetLineColor)
: base(self, target, targetLineColor)
{
this.enterBehaviour = enterBehaviour;
this.notification = notification;
this.speechNotification = speechNotification;
this.textNotification = textNotification;
}
bool CanEnterHut()
@@ -75,7 +77,8 @@ namespace OpenRA.Mods.Common.Activities
else if (enterHut != null)
enterHut.Repair(self);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", notification, self.Owner.Faction.InternalName);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", speechNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(textNotification, self.Owner);
if (enterBehaviour == EnterBehaviour.Dispose)
self.Dispose();

View File

@@ -262,6 +262,7 @@ namespace OpenRA.Mods.Common.Activities
host.Actor.Owner.PlayerActor.TraitOrDefault<PlayerExperience>()?.GiveExperience(repairsUnits.Info.PlayerExperience);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", repairsUnits.Info.FinishRepairingNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(repairsUnits.Info.FinishRepairingTextNotification, self.Owner);
activeResupplyTypes &= ~ResupplyType.Repair;
return;
@@ -279,6 +280,7 @@ namespace OpenRA.Mods.Common.Activities
{
played = true;
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", repairsUnits.Info.StartRepairingNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(repairsUnits.Info.StartRepairingTextNotification, self.Owner);
}
if (!playerResources.TakeCash(cost, true))

View File

@@ -49,6 +49,7 @@ namespace OpenRA.Mods.Common.Activities
self.World.AddFrameEndTask(w => w.Add(new FloatingText(self.CenterPosition, self.Owner.Color, FloatingText.FormatCashTick(refund), 30)));
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", sellableInfo.Notification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(sellableInfo.TextNotification, self.Owner);
self.Dispose();
return false;

View File

@@ -26,6 +26,7 @@ namespace OpenRA.Mods.Common.Activities
public WAngle Facing = new WAngle(384);
public string[] Sounds = Array.Empty<string>();
public string Notification = null;
public string TextNotification = null;
public int ForceHealthPercentage = 0;
public bool SkipMakeAnims = false;
public string Faction = null;
@@ -95,6 +96,7 @@ namespace OpenRA.Mods.Common.Activities
Game.Sound.PlayToPlayer(SoundType.World, self.Owner, s, self.CenterPosition);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Notification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(TextNotification, self.Owner);
var init = new TypeDictionary
{

View File

@@ -180,6 +180,8 @@ namespace OpenRA.Mods.Common.Orders
if (!AcceptsPlug(topLeft, plugInfo))
{
Game.Sound.PlayNotification(world.Map.Rules, owner, "Speech", notification, owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(placeBuildingInfo.CannotPlaceTextNotification, owner);
yield break;
}
}
@@ -192,6 +194,8 @@ namespace OpenRA.Mods.Common.Orders
yield return order;
Game.Sound.PlayNotification(world.Map.Rules, owner, "Speech", notification, owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(placeBuildingInfo.CannotPlaceTextNotification, owner);
yield break;
}

View File

@@ -34,9 +34,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly string PrimaryCondition = null;
[NotificationReference("Speech")]
[Desc("The speech notification to play when selecting a primary building.")]
[Desc("Speech notification to play when selecting a primary building.")]
public readonly string SelectionNotification = null;
[Desc("Text notification to display when selecting a primary building.")]
public readonly string SelectionTextNotification = null;
[Desc("List of production queues for which the primary flag should be set.",
"If empty, the list given in the `Produces` property of the `" + nameof(Production) + "` trait will be used.")]
public readonly string[] ProductionQueues = Array.Empty<string>();
@@ -113,6 +116,7 @@ namespace OpenRA.Mods.Common.Traits
primaryToken = self.GrantCondition(Info.PrimaryCondition);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.SelectionNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.SelectionTextNotification, self.Owner);
}
else if (primaryToken != Actor.InvalidConditionToken)
primaryToken = self.RevokeCondition(primaryToken);

View File

@@ -21,8 +21,12 @@ namespace OpenRA.Mods.Common.Traits
public class ProductionAirdropInfo : ProductionInfo
{
[NotificationReference("Speech")]
[Desc("Speech notification to play when a unit is delivered.")]
public readonly string ReadyAudio = "Reinforce";
[Desc("Text notification to display when a unit is delivered.")]
public readonly string ReadyTextNotification = null;
[FieldLoader.Require]
[ActorReference(typeof(AircraftInfo))]
[Desc("Cargo aircraft used for delivery. Must have the `" + nameof(Aircraft) + "` trait.")]
@@ -112,6 +116,7 @@ namespace OpenRA.Mods.Common.Traits
self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit, productionType, inits));
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.ReadyTextNotification, self.Owner);
}));
actor.QueueActivity(new FlyOffMap(actor, Target.FromCell(w, endPos)));

View File

@@ -46,9 +46,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly CVec[] Path = Array.Empty<CVec>();
[NotificationReference("Speech")]
[Desc("The speech notification to play when setting a new rallypoint.")]
[Desc("Speech notification to play when setting a new rallypoint.")]
public readonly string Notification = null;
[Desc("Text notification to display when setting a new rallypoint.")]
public readonly string TextNotification = null;
[Desc("Used to group equivalent actors to allow force-setting a rallypoint (e.g. for Primary production).")]
public readonly string ForceSetType = null;
@@ -101,6 +104,7 @@ namespace OpenRA.Mods.Common.Traits
if (order.OrderID == OrderID)
{
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.Notification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.TextNotification, self.Owner);
return new Order(order.OrderID, self, target, queued)
{

View File

@@ -49,6 +49,8 @@ namespace OpenRA.Mods.Common.Traits
[NotificationReference("Speech")]
public readonly string RepairingNotification = null;
public readonly string RepairingTextNotification = null;
public override object Create(ActorInitializer init) { return new RepairableBuilding(init.Self, this); }
}
@@ -111,7 +113,10 @@ namespace OpenRA.Mods.Common.Traits
return;
Repairers.Add(player);
Game.Sound.PlayNotification(self.World.Map.Rules, player, "Speech", Info.RepairingNotification, player.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.RepairingTextNotification, self.Owner);
UpdateCondition(self);
}

View File

@@ -31,12 +31,16 @@ namespace OpenRA.Mods.Common.Traits
[NotificationReference("Speech")]
public readonly string EnabledSpeech = null;
public readonly string EnabledTextNotification = null;
[NotificationReference("Sounds")]
public readonly string DisabledSound = null;
[NotificationReference("Speech")]
public readonly string DisabledSpeech = null;
public readonly string DisabledTextNotification = null;
public override object Create(ActorInitializer init) { return new ToggleConditionOnOrder(this); }
}
@@ -62,6 +66,8 @@ namespace OpenRA.Mods.Common.Traits
if (Info.EnabledSpeech != null)
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.EnabledSpeech, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.EnabledTextNotification, self.Owner);
}
else if (!granted && conditionToken != Actor.InvalidConditionToken)
{
@@ -72,6 +78,8 @@ namespace OpenRA.Mods.Common.Traits
if (Info.DisabledSpeech != null)
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.DisabledSpeech, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.DisabledTextNotification, self.Owner);
}
}

View File

@@ -36,9 +36,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly string Sound = null;
[NotificationReference("Speech")]
[Desc("Notification to play when the crate is collected.")]
[Desc("Speech notification to play when the crate is collected.")]
public readonly string Notification = null;
[Desc("Text notification to display when the crate is collected.")]
public readonly string TextNotification = null;
[Desc("The earliest time (in ticks) that this crate action can occur on.")]
public readonly int TimeDelay = 0;
@@ -92,6 +95,8 @@ namespace OpenRA.Mods.Common.Traits
Game.Sound.PlayNotification(self.World.Map.Rules, collector.Owner, "Speech",
Info.Notification, collector.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.TextNotification, collector.Owner);
if (Info.Image != null && Info.Sequence != null)
collector.World.AddFrameEndTask(w => w.Add(new SpriteEffect(collector, w, Info.Image, Info.Sequence, Info.Palette)));
}

View File

@@ -49,6 +49,8 @@ namespace OpenRA.Mods.Common.Traits
[NotificationReference("Sounds")]
public readonly string LevelUpNotification = null;
public readonly string LevelUpTextNotification = null;
public override object Create(ActorInitializer init) { return new GainsExperience(init, this); }
}
@@ -119,6 +121,8 @@ namespace OpenRA.Mods.Common.Traits
if (!silent)
{
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Sounds", info.LevelUpNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.LevelUpTextNotification, self.Owner);
if (info.LevelUpImage != null && info.LevelUpSequence != null)
self.World.AddFrameEndTask(w => w.Add(new SpriteEffect(self, w, info.LevelUpImage, info.LevelUpSequence, info.LevelUpPalette)));
}

View File

@@ -28,14 +28,20 @@ namespace OpenRA.Mods.Common.Traits
public readonly int RadarPingDuration = 250;
[NotificationReference("Speech")]
[Desc("The audio notification type to play.")]
[Desc("Speech notification type to play.")]
public readonly string Notification = "BaseAttack";
[Desc("Text notification to display.")]
public string TextNotification = null;
[NotificationReference("Speech")]
[Desc("The audio notification to play to allies when under attack.",
[Desc("Speech notification to play to allies when under attack.",
"Won't play a notification to allies if this is null.")]
public readonly string AllyNotification = null;
[Desc("Text notification to display to allies when under attack.")]
public string AllyTextNotification = null;
public override object Create(ActorInitializer init) { return new BaseAttackNotifier(init.Self, this); }
}
@@ -55,6 +61,11 @@ namespace OpenRA.Mods.Common.Traits
void INotifyDamage.Damaged(Actor self, AttackInfo e)
{
var localPlayer = self.World.LocalPlayer;
if (localPlayer == null || localPlayer.Spectating)
return;
if (e.Attacker == null)
return;
@@ -74,12 +85,17 @@ namespace OpenRA.Mods.Common.Traits
if (Game.RunTime > lastAttackTime + info.NotifyInterval)
{
var rules = self.World.Map.Rules;
Game.Sound.PlayNotification(rules, self.Owner, "Speech", info.Notification, self.Owner.Faction.InternalName);
if (info.AllyNotification != null)
foreach (Player p in self.World.Players)
if (p != self.Owner && p.IsAlliedWith(self.Owner) && p != e.Attacker.Owner)
Game.Sound.PlayNotification(rules, p, "Speech", info.AllyNotification, p.Faction.InternalName);
if (self.Owner == localPlayer)
{
Game.Sound.PlayNotification(rules, self.Owner, "Speech", info.Notification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.TextNotification, self.Owner);
}
else if (localPlayer.IsAlliedWith(self.Owner) && localPlayer != e.Attacker.Owner)
{
Game.Sound.PlayNotification(rules, localPlayer, "Speech", info.AllyNotification, localPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.AllyTextNotification, localPlayer);
}
radarPings?.Add(() => self.Owner.IsAlliedWith(self.World.RenderPlayer), self.CenterPosition, info.RadarPingColor, info.RadarPingDuration);

View File

@@ -103,7 +103,10 @@ namespace OpenRA.Mods.Common.Traits
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
{
Game.Sound.PlayNotification(player.World.Map.Rules, player, "Speech", mo.Info.LoseNotification, player.Faction.InternalName);
TextNotificationsManager.AddTransientLine(mo.Info.LoseTextNotification, player);
}
});
}
@@ -116,7 +119,10 @@ namespace OpenRA.Mods.Common.Traits
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
{
Game.Sound.PlayNotification(player.World.Map.Rules, player, "Speech", mo.Info.WinNotification, player.Faction.InternalName);
TextNotificationsManager.AddTransientLine(mo.Info.WinTextNotification, player);
}
});
}
}

View File

@@ -89,8 +89,9 @@ namespace OpenRA.Mods.Common.Traits
if (lastKnownActorIds.Contains(actor.Actor.ActorID))
continue;
// Should we play a sound notification?
var playNotification = !playedNotifications.Contains(actor.Trait.Info.Notification) && ticksBeforeNextNotification <= 0;
// Should we play a notification?
var notificationId = $"{actor.Trait.Info.Notification} {actor.Trait.Info.TextNotification}";
var playNotification = !playedNotifications.Contains(notificationId) && ticksBeforeNextNotification <= 0;
// Notify the actor that he has been discovered
foreach (var trait in actor.Actor.TraitsImplementing<INotifyDiscovered>())
@@ -109,7 +110,7 @@ namespace OpenRA.Mods.Common.Traits
if (!playNotification)
continue;
playedNotifications.Add(actor.Trait.Info.Notification);
playedNotifications.Add(notificationId);
announcedAny = true;
}

View File

@@ -28,9 +28,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly int RadarPingDuration = 250;
[NotificationReference("Speech")]
[Desc("The audio notification type to play.")]
[Desc("Speech notification type to play.")]
public readonly string Notification = "HarvesterAttack";
[Desc("Text notification to display.")]
public string TextNotification = null;
public override object Create(ActorInitializer init) { return new HarvesterAttackNotifier(init.Self, this); }
}
@@ -61,6 +64,8 @@ namespace OpenRA.Mods.Common.Traits
if (Game.RunTime > lastAttackTime + info.NotifyInterval)
{
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.Notification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.TextNotification, self.Owner);
radarPings?.Add(() => self.Owner.IsAlliedWith(self.World.RenderPlayer), self.CenterPosition, info.RadarPingColor, info.RadarPingDuration);
lastAttackTime = Game.RunTime;

View File

@@ -54,12 +54,18 @@ namespace OpenRA.Mods.Common.Traits
[NotificationReference("Speech")]
public readonly string WinNotification = null;
public readonly string WinTextNotification = null;
[NotificationReference("Speech")]
public readonly string LoseNotification = null;
public readonly string LoseTextNotification = null;
[NotificationReference("Speech")]
public readonly string LeaveNotification = null;
public readonly string LeaveTextNotification = null;
public override object Create(ActorInitializer init) { return new MissionObjectives(init.Self.Owner, this); }
}

View File

@@ -26,12 +26,19 @@ namespace OpenRA.Mods.Common.Traits
public readonly int NewOptionsNotificationDelay = 10;
[NotificationReference("Speech")]
[Desc("Notification to play after building placement if new construction options are available.")]
[Desc("Speech notification to play after building placement if new construction options are available.")]
public readonly string NewOptionsNotification = null;
[Desc("Text notification to display after building placement if new construction options are available.")]
public readonly string NewOptionsTextNotification = null;
[NotificationReference("Speech")]
[Desc("Speech notification to play if building placement is not possible.")]
public readonly string CannotPlaceNotification = null;
[Desc("Text notification to display if building placement is not possible.")]
public readonly string CannotPlaceTextNotification = null;
[Desc("Hotkey to toggle between PlaceBuildingVariants when placing a structure.")]
public readonly HotkeyReference ToggleVariantKey = new HotkeyReference();
@@ -223,6 +230,8 @@ namespace OpenRA.Mods.Common.Traits
void PlayNotification(Actor self)
{
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.NewOptionsNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.NewOptionsTextNotification, self.Owner);
triggerNotification = false;
tick = 0;
}

View File

@@ -44,6 +44,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Speech notification to play when the player does not have any funds.")]
public readonly string InsufficientFundsNotification = null;
[Desc("Text notification to display when the player does not have any funds.")]
public readonly string InsufficientFundsTextNotification = null;
[Desc("Delay (in ticks) during which warnings will be muted.")]
public readonly int InsufficientFundsNotificationInterval = 30000;
@@ -179,11 +182,11 @@ namespace OpenRA.Mods.Common.Traits
{
if (Cash + Resources < num)
{
if (notifyLowFunds && !string.IsNullOrEmpty(Info.InsufficientFundsNotification) &&
Game.RunTime > lastNotificationTime + Info.InsufficientFundsNotificationInterval)
if (notifyLowFunds && Game.RunTime > lastNotificationTime + Info.InsufficientFundsNotificationInterval)
{
lastNotificationTime = Game.RunTime;
Game.Sound.PlayNotification(owner.World.Map.Rules, owner, "Speech", Info.InsufficientFundsNotification, owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.InsufficientFundsTextNotification, owner);
}
return false;

View File

@@ -61,18 +61,29 @@ namespace OpenRA.Mods.Common.Traits
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string ReadyAudio = null;
[Desc("Notification displayed when production is complete.")]
public readonly string ReadyTextNotification = null;
[NotificationReference("Speech")]
[Desc("Notification played when you can't train another actor",
"when the build limit exceeded or the exit is jammed.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string BlockedAudio = null;
[Desc("Notification displayed when you can't train another actor",
"when the build limit exceeded or the exit is jammed.")]
public readonly string BlockedTextNotification = null;
[NotificationReference("Speech")]
[Desc("Notification played when you can't queue another actor",
"when the queue length limit is exceeded.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string LimitedAudio = null;
[Desc("Notification displayed when you can't queue another actor",
"when the queue length limit is exceeded.")]
public readonly string LimitedTextNotification = null;
[NotificationReference("Speech")]
[Desc("Notification played when you can't place a building.",
"Overrides PlaceBuilding.CannotPlaceNotification for this queue.",
@@ -84,16 +95,25 @@ namespace OpenRA.Mods.Common.Traits
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string QueuedAudio = null;
[Desc("Notification displayed when user clicks on the build palette icon.")]
public readonly string QueuedTextNotification = null;
[NotificationReference("Speech")]
[Desc("Notification played when player right-clicks on the build palette icon.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string OnHoldAudio = null;
[Desc("Notification displayed when player right-clicks on the build palette icon.")]
public readonly string OnHoldTextNotification = null;
[NotificationReference("Speech")]
[Desc("Notification played when player right-clicks on a build palette icon that is already on hold.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string CancelledAudio = null;
[Desc("Notification displayed when player right-clicks on a build palette icon that is already on hold.")]
public readonly string CancelledTextNotification = null;
public override object Create(ActorInitializer init) { return new ProductionQueue(init, this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
@@ -333,9 +353,10 @@ namespace OpenRA.Mods.Common.Traits
}
}
public bool CanQueue(ActorInfo actor, out string notificationAudio)
public bool CanQueue(ActorInfo actor, out string notificationAudio, out string notificationText)
{
notificationAudio = Info.BlockedAudio;
notificationText = Info.BlockedTextNotification;
var bi = actor.TraitInfoOrDefault<BuildableInfo>();
if (bi == null)
@@ -346,6 +367,7 @@ namespace OpenRA.Mods.Common.Traits
if (Info.QueueLimit > 0 && Queue.Count >= Info.QueueLimit)
{
notificationAudio = Info.LimitedAudio;
notificationText = Info.LimitedTextNotification;
return false;
}
@@ -353,6 +375,7 @@ namespace OpenRA.Mods.Common.Traits
if (Info.ItemLimit > 0 && queueCount >= Info.ItemLimit)
{
notificationAudio = Info.LimitedAudio;
notificationText = Info.LimitedTextNotification;
return false;
}
@@ -366,6 +389,7 @@ namespace OpenRA.Mods.Common.Traits
}
notificationAudio = Info.QueuedAudio;
notificationText = Info.QueuedTextNotification;
return true;
}
@@ -424,13 +448,22 @@ namespace OpenRA.Mods.Common.Traits
var isBuilding = unit.HasTraitInfo<BuildingInfo>();
if (isBuilding && !hasPlayedSound)
{
hasPlayedSound = Game.Sound.PlayNotification(rules, self.Owner, "Speech", Info.ReadyAudio, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.ReadyTextNotification, self.Owner);
}
else if (!isBuilding)
{
if (BuildUnit(unit))
{
Game.Sound.PlayNotification(rules, self.Owner, "Speech", Info.ReadyAudio, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.ReadyTextNotification, self.Owner);
}
else if (!hasPlayedSound && time > 0)
{
hasPlayedSound = Game.Sound.PlayNotification(rules, self.Owner, "Speech", Info.BlockedAudio, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.BlockedTextNotification, self.Owner);
}
}
})), !order.Queued);
}

View File

@@ -24,9 +24,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly int Threshold = 80;
[NotificationReference("Speech")]
[Desc("The speech to play for the warning.")]
[Desc("Speech to play for the warning.")]
public readonly string Notification = "SilosNeeded";
[Desc("Text to display for the warning.")]
public readonly string TextNotification = null;
public override object Create(ActorInitializer init) { return new ResourceStorageWarning(init.Self, this); }
}
@@ -50,7 +53,10 @@ namespace OpenRA.Mods.Common.Traits
var owner = self.Owner;
if (resources.Resources > info.Threshold * resources.ResourceCapacity / 100)
{
Game.Sound.PlayNotification(self.World.Map.Rules, owner, "Speech", info.Notification, owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.TextNotification, owner);
}
lastSiloAdviceTime = Game.RunTime;
}

View File

@@ -140,7 +140,10 @@ namespace OpenRA.Mods.Common.Traits
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
{
Game.Sound.PlayNotification(player.World.Map.Rules, player, "Speech", mo.Info.LoseNotification, player.Faction.InternalName);
TextNotificationsManager.AddTransientLine(mo.Info.LoseTextNotification, player);
}
});
}
@@ -153,7 +156,10 @@ namespace OpenRA.Mods.Common.Traits
Game.RunAfterDelay(info.NotificationDelay, () =>
{
if (Game.IsCurrentWorld(player.World) && player == player.World.LocalPlayer)
{
Game.Sound.PlayNotification(player.World.Map.Rules, player, "Speech", mo.Info.WinNotification, player.Faction.InternalName);
TextNotificationsManager.AddTransientLine(mo.Info.WinTextNotification, player);
}
});
}
}

View File

@@ -25,6 +25,8 @@ namespace OpenRA.Mods.Common.Traits
[NotificationReference("Speech")]
public readonly string SpeechNotification = null;
public readonly string TextNotification = null;
public override object Create(ActorInitializer init) { return new PowerManager(init.Self, this); }
}
@@ -161,6 +163,8 @@ namespace OpenRA.Mods.Common.Traits
if (isLowPower && Game.RunTime > lastPowerAdviceTime + info.AdviceInterval)
{
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.SpeechNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.TextNotification, self.Owner);
lastPowerAdviceTime = Game.RunTime;
}

View File

@@ -29,9 +29,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly string ChuteSound = null;
[NotificationReference("Speech")]
[Desc("Notification to play when dropping the unit.")]
[Desc("Speech notification to play when dropping the unit.")]
public readonly string ReadyAudio = null;
[Desc("Text notification to display when dropping the unit.")]
public readonly string ReadyTextNotification = null;
public override object Create(ActorInitializer init) { return new ProductionParadrop(init, this); }
}
@@ -97,6 +100,7 @@ namespace OpenRA.Mods.Common.Traits
self.World.AddFrameEndTask(ww => DoProduction(self, producee, exit?.Info, productionType, inits));
Game.Sound.Play(SoundType.World, info.ChuteSound, self.CenterPosition);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.ReadyTextNotification, self.Owner);
}));
actor.QueueActivity(new Fly(actor, Target.FromCell(w, endPos)));

View File

@@ -42,6 +42,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Speech notification to play when a bridge is repaired.")]
public readonly string RepairNotification = null;
[Desc("Text notification to display when a bridge is repaired.")]
public readonly string RepairTextNotification = null;
public override object Create(ActorInitializer init) { return new RepairsBridges(this); }
}
@@ -107,7 +110,7 @@ namespace OpenRA.Mods.Common.Traits
else
return;
self.QueueActivity(order.Queued, new RepairBridge(self, order.Target, info.EnterBehaviour, info.RepairNotification, info.TargetLineColor));
self.QueueActivity(order.Queued, new RepairBridge(self, order.Target, info.EnterBehaviour, info.RepairNotification, info.RepairTextNotification, info.TargetLineColor));
self.ShowTargetLines();
}
}

View File

@@ -28,13 +28,19 @@ namespace OpenRA.Mods.Common.Traits
public readonly BitSet<DamageType> RepairDamageTypes = default(BitSet<DamageType>);
[NotificationReference("Speech")]
[Desc("The sound played when starting to repair a unit.")]
[Desc("Speech notification played when starting to repair a unit.")]
public readonly string StartRepairingNotification = null;
[Desc("Text notification displayed when starting to repair a unit.")]
public readonly string StartRepairingTextNotification = null;
[NotificationReference("Speech")]
[Desc("The sound played when repairing a unit is done.")]
[Desc("Speech notification played when repairing a unit is done.")]
public readonly string FinishRepairingNotification = null;
[Desc("Text notification displayed when repairing a unit is done.")]
public readonly string FinishRepairingTextNotification = null;
[Desc("Experience gained by the player owning this actor for repairing an allied unit.")]
public readonly int PlayerExperience = 0;

View File

@@ -27,9 +27,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly string[] SellSounds = Array.Empty<string>();
[NotificationReference("Speech")]
[Desc("The audio notification type to play.")]
[Desc("Speech notification to play.")]
public readonly string Notification = null;
[Desc("Text notification to display.")]
public string TextNotification = null;
[Desc("Whether to show the cash tick indicators rising from the actor.")]
public readonly bool ShowTicks = true;

View File

@@ -16,8 +16,12 @@ namespace OpenRA.Mods.Common.Traits.Sound
class ActorLostNotificationInfo : ConditionalTraitInfo
{
[NotificationReference("Speech")]
[Desc("Speech notification to play.")]
public readonly string Notification = "UnitLost";
[Desc("Text notification to display.")]
public readonly string TextNotification = null;
public readonly bool NotifyAll = false;
public override object Create(ActorInitializer init) { return new ActorLostNotification(this); }
@@ -33,8 +37,15 @@ namespace OpenRA.Mods.Common.Traits.Sound
if (IsTraitDisabled)
return;
var player = Info.NotifyAll ? self.World.LocalPlayer : self.Owner;
var localPlayer = self.World.LocalPlayer;
if (localPlayer == null || localPlayer.Spectating)
return;
var player = Info.NotifyAll ? localPlayer : self.Owner;
Game.Sound.PlayNotification(self.World.Map.Rules, player, "Speech", Info.Notification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.TextNotification, player);
}
}
}

View File

@@ -23,8 +23,12 @@ namespace OpenRA.Mods.Common.Traits.Sound
public readonly bool PingRadar = false;
[NotificationReference("Speech")]
[Desc("Speech notification to play.")]
public readonly string Notification = null;
[Desc("Text notification to display.")]
public readonly string TextNotification = null;
public readonly bool AnnounceNeutrals = false;
public override object Create(ActorInitializer init) { return new AnnounceOnSeen(init.Self, this); }
@@ -56,6 +60,9 @@ namespace OpenRA.Mods.Common.Traits.Sound
if (discoverer != null && !string.IsNullOrEmpty(Info.Notification))
Game.Sound.PlayNotification(self.World.Map.Rules, discoverer, "Speech", Info.Notification, discoverer.Faction.InternalName);
if (discoverer != null)
TextNotificationsManager.AddTransientLine(Info.TextNotification, discoverer);
// Radar notification
if (Info.PingRadar)
radarPings.Value?.Add(() => true, self.CenterPosition, Color.Red, 50);

View File

@@ -17,16 +17,22 @@ namespace OpenRA.Mods.Common.Traits.Sound
public class CaptureNotificationInfo : TraitInfo
{
[NotificationReference("Speech")]
[Desc("The speech notification to play to the new owner.")]
[Desc("Speech notification to play to the new owner.")]
public readonly string Notification = "BuildingCaptured";
[Desc("Text notification to display to the new owner.")]
public readonly string TextNotification = null;
[Desc("Specifies if Notification is played with the voice of the new owners faction.")]
public readonly bool NewOwnerVoice = true;
[NotificationReference("Speech")]
[Desc("The speech notification to play to the old owner.")]
[Desc("Speech notification to play to the old owner.")]
public readonly string LoseNotification = null;
[Desc("Text notification to display to the old owner.")]
public readonly string LoseTextNotification = null;
[Desc("Specifies if LoseNotification is played with the voice of the new owners faction.")]
public readonly bool LoseNewOwnerVoice = false;
@@ -45,9 +51,11 @@ namespace OpenRA.Mods.Common.Traits.Sound
{
var faction = info.NewOwnerVoice ? newOwner.Faction.InternalName : oldOwner.Faction.InternalName;
Game.Sound.PlayNotification(self.World.Map.Rules, newOwner, "Speech", info.Notification, faction);
TextNotificationsManager.AddTransientLine(info.TextNotification, newOwner);
var loseFaction = info.LoseNewOwnerVoice ? newOwner.Faction.InternalName : oldOwner.Faction.InternalName;
Game.Sound.PlayNotification(self.World.Map.Rules, oldOwner, "Speech", info.LoseNotification, loseFaction);
TextNotificationsManager.AddTransientLine(info.LoseTextNotification, oldOwner);
}
}
}

View File

@@ -27,9 +27,12 @@ namespace OpenRA.Mods.Common.Traits
public readonly WVec SquadOffset = new WVec(-1536, 1536, 0);
[NotificationReference("Speech")]
[Desc("Notification to play when entering the drop zone.")]
[Desc("Speech notification to play when entering the drop zone.")]
public readonly string ReinforcementsArrivedSpeechNotification = null;
[Desc("Text notification to display when entering the drop zone.")]
public readonly string ReinforcementsArrivedTextNotification = null;
[Desc("Number of facings that the delivery aircraft may approach from.")]
public readonly int QuantizedFacings = 32;
@@ -134,9 +137,13 @@ namespace OpenRA.Mods.Common.Traits
RemoveBeacon(beacon);
if (!aircraftInRange.Any(kv => kv.Value))
{
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech",
info.ReinforcementsArrivedSpeechNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.ReinforcementsArrivedTextNotification, self.Owner);
}
aircraftInRange[a] = true;
};

View File

@@ -28,15 +28,21 @@ namespace OpenRA.Mods.Common.Traits
public readonly string Type = null;
[NotificationReference("Speech")]
[Desc("Notification played when production is activated.",
[Desc("Speech notification played when production is activated.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string ReadyAudio = null;
[Desc("Text notification displayed when production is activated.")]
public readonly string ReadyTextNotification = null;
[NotificationReference("Speech")]
[Desc("Notification played when the exit is jammed.",
[Desc("Speech notification played when the exit is jammed.",
"The filename of the audio is defined per faction in notifications.yaml.")]
public readonly string BlockedAudio = null;
[Desc("Text notification displayed when the exit is jammed.")]
public readonly string BlockedTextNotification = null;
public override object Create(ActorInitializer init) { return new ProduceActorPower(init, this); }
}
@@ -91,9 +97,15 @@ namespace OpenRA.Mods.Common.Traits
}
if (activated)
{
Game.Sound.PlayNotification(self.World.Map.Rules, manager.Self.Owner, "Speech", info.ReadyAudio, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.ReadyTextNotification, manager.Self.Owner);
}
else
{
Game.Sound.PlayNotification(self.World.Map.Rules, manager.Self.Owner, "Speech", info.BlockedAudio, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.BlockedTextNotification, manager.Self.Owner);
}
}
}
}

View File

@@ -95,6 +95,9 @@ namespace OpenRA.Mods.Common.Traits
Game.Sound.PlayToPlayer(SoundType.UI, manager.Self.Owner, Info.SelectTargetSound);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech",
Info.SelectTargetSpeechNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.SelectTargetTextNotification, manager.Self.Owner);
self.World.OrderGenerator = new SelectSpawnActorPowerTarget(order, manager, this, MouseButton.Left);
}

View File

@@ -53,36 +53,50 @@ namespace OpenRA.Mods.Common.Traits
[NotificationReference("Speech")]
public readonly string DetectedSpeechNotification = null;
public readonly string DetectedTextNotification = null;
public readonly string BeginChargeSound = null;
[NotificationReference("Speech")]
public readonly string BeginChargeSpeechNotification = null;
public readonly string BeginChargeTextNotification = null;
public readonly string EndChargeSound = null;
[NotificationReference("Speech")]
public readonly string EndChargeSpeechNotification = null;
public readonly string EndChargeTextNotification = null;
public readonly string SelectTargetSound = null;
[NotificationReference("Speech")]
public readonly string SelectTargetSpeechNotification = null;
public readonly string SelectTargetTextNotification = null;
public readonly string InsufficientPowerSound = null;
[NotificationReference("Speech")]
public readonly string InsufficientPowerSpeechNotification = null;
public readonly string InsufficientPowerTextNotification = null;
public readonly string LaunchSound = null;
[NotificationReference("Speech")]
public readonly string LaunchSpeechNotification = null;
public readonly string LaunchTextNotification = null;
public readonly string IncomingSound = null;
[NotificationReference("Speech")]
public readonly string IncomingSpeechNotification = null;
public readonly string IncomingTextNotification = null;
[Desc("Defines to which players the timer is shown.")]
public readonly PlayerRelationship DisplayTimerRelationships = PlayerRelationship.None;
@@ -147,11 +161,12 @@ namespace OpenRA.Mods.Common.Traits
{
base.Created(self);
var renderPlayer = self.World.RenderPlayer;
if (renderPlayer != null && renderPlayer != self.Owner)
var player = self.World.LocalPlayer;
if (player != null && player != self.Owner)
{
Game.Sound.Play(SoundType.UI, Info.DetectedSound);
Game.Sound.PlayNotification(self.World.Map.Rules, renderPlayer, "Speech", info.DetectedSpeechNotification, renderPlayer.Faction.InternalName);
Game.Sound.PlayNotification(self.World.Map.Rules, player, "Speech", info.DetectedSpeechNotification, player.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.DetectedTextNotification, player);
}
}
@@ -165,6 +180,8 @@ namespace OpenRA.Mods.Common.Traits
Game.Sound.PlayToPlayer(SoundType.UI, self.Owner, Info.BeginChargeSound);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech",
Info.BeginChargeSpeechNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.BeginChargeTextNotification, self.Owner);
}
public virtual void Charged(Actor self, string key)
@@ -173,6 +190,8 @@ namespace OpenRA.Mods.Common.Traits
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech",
Info.EndChargeSpeechNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.EndChargeTextNotification, self.Owner);
foreach (var notify in self.TraitsImplementing<INotifySupportPower>())
notify.Charged(self);
}
@@ -199,13 +218,19 @@ namespace OpenRA.Mods.Common.Traits
public virtual void PlayLaunchSounds()
{
var renderPlayer = Self.World.RenderPlayer;
var isAllied = Self.Owner.IsAlliedWith(renderPlayer);
var localPlayer = Self.World.LocalPlayer;
if (localPlayer == null || localPlayer.Spectating)
return;
var isAllied = Self.Owner.IsAlliedWith(localPlayer);
Game.Sound.Play(SoundType.UI, isAllied ? Info.LaunchSound : Info.IncomingSound);
var toPlayer = isAllied ? renderPlayer ?? Self.Owner : renderPlayer;
var toPlayer = isAllied ? localPlayer ?? Self.Owner : localPlayer;
var speech = isAllied ? Info.LaunchSpeechNotification : Info.IncomingSpeechNotification;
Game.Sound.PlayNotification(Self.World.Map.Rules, toPlayer, "Speech", speech, toPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(isAllied ? Info.LaunchTextNotification : Info.IncomingTextNotification, toPlayer);
}
public IEnumerable<CPos> CellsMatching(CPos location, char[] footprint, CVec dimensions)

View File

@@ -231,6 +231,8 @@ namespace OpenRA.Mods.Common.Traits
Game.Sound.PlayNotification(power.Self.World.Map.Rules, power.Self.Owner, "Speech",
Info.SelectTargetSpeechNotification, power.Self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.SelectTargetTextNotification, power.Self.Owner);
power.SelectTarget(power.Self, Key, Manager);
}

View File

@@ -39,13 +39,19 @@ namespace OpenRA.Mods.Common.Traits
public readonly string[] NoTransformSounds = Array.Empty<string>();
[NotificationReference("Speech")]
[Desc("Notification to play when transforming.")]
[Desc("Speech notification to play when transforming.")]
public readonly string TransformNotification = null;
[Desc("Text notification to display when transforming.")]
public readonly string TransformTextNotification = null;
[NotificationReference("Speech")]
[Desc("Notification to play when the transformation is blocked.")]
[Desc("Speech notification to play when the transformation is blocked.")]
public readonly string NoTransformNotification = null;
[Desc("Text notification to display when the transformation is blocked.")]
public readonly string NoTransformTextNotification = null;
[CursorReference]
[Desc("Cursor to display when able to (un)deploy the actor.")]
public readonly string DeployCursor = "deploy";
@@ -97,6 +103,7 @@ namespace OpenRA.Mods.Common.Traits
Facing = Info.Facing,
Sounds = Info.TransformSounds,
Notification = Info.TransformNotification,
TextNotification = Info.TransformTextNotification,
Faction = faction
};
}
@@ -136,6 +143,7 @@ namespace OpenRA.Mods.Common.Traits
Game.Sound.PlayToPlayer(SoundType.World, self.Owner, s);
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", Info.NoTransformNotification, self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(Info.NoTransformTextNotification, self.Owner);
return;
}

View File

@@ -20,12 +20,18 @@ namespace OpenRA.Mods.Common.Traits
[NotificationReference("Speech")]
public readonly string Notification = "StartGame";
public readonly string TextNotification = null;
[NotificationReference("Speech")]
public readonly string LoadedNotification = "GameLoaded";
public readonly string LoadedTextNotification = null;
[NotificationReference("Speech")]
public readonly string SavedNotification = "GameSaved";
public readonly string SavedTextNotification = null;
public override object Create(ActorInitializer init) { return new StartGameNotification(this); }
}
@@ -40,19 +46,28 @@ namespace OpenRA.Mods.Common.Traits
void IWorldLoaded.WorldLoaded(World world, WorldRenderer wr)
{
if (!world.IsLoadingGameSave)
{
Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", info.Notification, world.RenderPlayer == null ? null : world.RenderPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.TextNotification, null);
}
}
void INotifyGameLoaded.GameLoaded(World world)
{
if (!world.IsReplay)
{
Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", info.LoadedNotification, world.RenderPlayer == null ? null : world.RenderPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.LoadedTextNotification, null);
}
}
void INotifyGameSaved.GameSaved(World world)
{
if (!world.IsReplay)
{
Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", info.SavedNotification, world.RenderPlayer == null ? null : world.RenderPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(info.SavedTextNotification, null);
}
}
}
}

View File

@@ -121,6 +121,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var faction = world.LocalPlayer?.Faction.InternalName;
Game.Sound.PlayNotification(world.Map.Rules, null, "Speech", moi.LeaveNotification, faction);
TextNotificationsManager.AddTransientLine(moi.LeaveTextNotification, null);
}
}

View File

@@ -305,6 +305,8 @@ namespace OpenRA.Mods.Common.Widgets
// Resume a paused item
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Sounds", ClickSound, null);
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(CurrentQueue.Info.QueuedTextNotification, World.LocalPlayer);
World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false));
return true;
}
@@ -315,10 +317,13 @@ namespace OpenRA.Mods.Common.Widgets
{
// Queue a new item
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Sounds", ClickSound, null);
var canQueue = CurrentQueue.CanQueue(buildable, out var notification);
var canQueue = CurrentQueue.CanQueue(buildable, out var notification, out var textNotification);
if (!CurrentQueue.AllQueued().Any())
{
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", notification, World.LocalPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(textNotification, World.LocalPlayer);
}
if (canQueue)
{
@@ -342,12 +347,16 @@ namespace OpenRA.Mods.Common.Widgets
{
// Instantly cancel items that haven't started, have finished, or if the queue doesn't support pausing
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(CurrentQueue.Info.CancelledTextNotification, World.LocalPlayer);
World.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, icon.Name, handleCount));
}
else
{
// Pause an existing item
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(CurrentQueue.Info.OnHoldTextNotification, World.LocalPlayer);
World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, true));
}
@@ -362,6 +371,8 @@ namespace OpenRA.Mods.Common.Widgets
// Directly cancel, skipping "on-hold"
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Sounds", ClickSound, null);
Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Faction.InternalName);
TextNotificationsManager.AddTransientLine(CurrentQueue.Info.CancelledTextNotification, World.LocalPlayer);
World.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, icon.Name, handleCount));
return true;

View File

@@ -173,6 +173,8 @@ namespace OpenRA.Mods.Common.Widgets
Game.Sound.PlayToPlayer(SoundType.UI, spm.Self.Owner, clicked.Power.Info.InsufficientPowerSound);
Game.Sound.PlayNotification(spm.Self.World.Map.Rules, spm.Self.Owner, "Speech",
clicked.Power.Info.InsufficientPowerSpeechNotification, spm.Self.Owner.Faction.InternalName);
TextNotificationsManager.AddTransientLine(clicked.Power.Info.InsufficientPowerTextNotification, spm.Self.Owner);
}
else
clicked.Power.Target();

View File

@@ -82,6 +82,9 @@ namespace OpenRA.Mods.D2k.Activities
foreach (var player in affectedPlayers)
self.World.AddFrameEndTask(w => w.Add(new MapNotificationEffect(player, "Speech", swallow.Info.WormAttackNotification, 25, true, attackPosition, Color.Red)));
if (affectedPlayers.Contains(self.World.LocalPlayer))
TextNotificationsManager.AddTransientLine(swallow.Info.WormAttackTextNotification, self.World.LocalPlayer);
var barrel = armament.CheckFire(self, facing, target);
if (barrel == null)
return false;

View File

@@ -38,6 +38,8 @@ namespace OpenRA.Mods.D2k.Traits
[NotificationReference("Speech")]
public readonly string WormAttackNotification = "WormAttack";
public readonly string WormAttackTextNotification = "Worm attack.";
public override object Create(ActorInitializer init) { return new AttackSwallow(init.Self, this); }
}