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

@@ -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);
}
});
}
}