Skip to content

Commit

Permalink
Unhardcode VeteranProductionIconOverlay.
Browse files Browse the repository at this point in the history
  • Loading branch information
MustaphaTR authored and PunkPun committed Aug 16, 2022
1 parent d438508 commit 5434059
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 22 deletions.
3 changes: 1 addition & 2 deletions OpenRA.Mods.Common/Traits/ProducibleWithLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
namespace OpenRA.Mods.Common.Traits
{
[Desc("Actors possessing this trait should define the GainsExperience trait. When the prerequisites are fulfilled, ",
"this trait grants a level-up to newly spawned actors. If additionally the actor's owning player defines the ProductionIconOverlay ",
"trait, the production queue icon renders with an overlay defined in that trait.")]
"this trait grants a level-up to newly spawned actors.")]
public class ProducibleWithLevelInfo : TraitInfo, Requires<GainsExperienceInfo>
{
public readonly string[] Prerequisites = Array.Empty<string>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,20 @@
#endregion

using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
using OpenRA.Traits;

namespace OpenRA.Mods.Common.Traits.Render
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor. When attached, enables all actors possessing the ProducibleWithLevel ",
"trait to have their production queue icons render with an overlay defined in this trait. ",
"The icon change occurs when ProducibleWithLevel.Prerequisites are met.")]
public class VeteranProductionIconOverlayInfo : TraitInfo, Requires<TechTreeInfo>
[Desc("Attach this to the player actor. Required for WithProductionIconOverlay trait on actors to work.")]
public class ProductionIconOverlayManagerInfo : TraitInfo, Requires<TechTreeInfo>, IRulesetLoaded
{
[FieldLoader.Require]
[Desc("Type of the overlay. Prerequisites from WithProductionIconOverlay traits with matching types determine when this overlay will be enabled.")]
public readonly string Type = null;

[FieldLoader.Require]
[Desc("Image used for the overlay.")]
public readonly string Image = null;
Expand All @@ -33,24 +36,30 @@ public class VeteranProductionIconOverlayInfo : TraitInfo, Requires<TechTreeInfo
[Desc("Palette to render the sprite in. Reference the world actor's PaletteFrom* traits.")]
public readonly string Palette = "chrome";

public override object Create(ActorInitializer init) { return new VeteranProductionIconOverlay(init, this); }
public virtual void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
if (rules.Actors[SystemActors.Player].TraitInfos<ProductionIconOverlayManagerInfo>().Where(piom => piom != this && piom.Type == Type).Any())
throw new YamlException($"Multiple 'ProductionIconOverlayManager's with type '{Type}' exist.");
}

public override object Create(ActorInitializer init) { return new ProductionIconOverlayManager(init, this); }
}

public class VeteranProductionIconOverlay : ITechTreeElement, IProductionIconOverlay
public class ProductionIconOverlayManager : ITechTreeElement, IProductionIconOverlay
{
readonly Actor self;
readonly Sprite sprite;
readonly ProductionIconOverlayManagerInfo info;

// HACK: TechTree doesn't associate Watcher.Key with the registering ITechTreeElement.
// So in a situation where multiple ITechTreeElements register Watchers with the same Key,
// and one removes its Watcher, all other ITechTreeElements' Watchers get removed too.
// This makes sure that the keys are unique with respect to the registering ITechTreeElement.
const string Prefix = "ProductionIconOverlay.";

readonly Actor self;
readonly Sprite sprite;
readonly VeteranProductionIconOverlayInfo info;
readonly string prefix;

readonly Dictionary<ActorInfo, bool> overlayActive = new Dictionary<ActorInfo, bool>();

public VeteranProductionIconOverlay(ActorInitializer init, VeteranProductionIconOverlayInfo info)
public ProductionIconOverlayManager(ActorInitializer init, ProductionIconOverlayManagerInfo info)
{
self = init.Self;

Expand All @@ -60,13 +69,13 @@ public VeteranProductionIconOverlay(ActorInitializer init, VeteranProductionIcon

this.info = info;

prefix = info.Type + ".";
var ttc = self.Trait<TechTree>();

foreach (var a in self.World.Map.Rules.Actors.Values)
{
var uwc = a.TraitInfoOrDefault<ProducibleWithLevelInfo>();
if (uwc != null)
ttc.Add(MakeKey(a.Name), uwc.Prerequisites, 0, this);
foreach (var wpio in a.TraitInfos<WithProductionIconOverlayInfo>().Where(wpio => wpio.Types.Contains(info.Type)))
ttc.Add(MakeKey(a.Name), wpio.Prerequisites, 0, this);
}
}

Expand All @@ -88,14 +97,14 @@ bool IProductionIconOverlay.IsOverlayActive(ActorInfo ai)
return isActive;
}

static string MakeKey(string name)
string MakeKey(string name)
{
return Prefix + name;
return prefix + name;
}

static string GetName(string key)
string GetName(string key)
{
return key.Substring(Prefix.Length);
return key.Substring(prefix.Length);
}

public void PrerequisitesAvailable(string key)
Expand Down
40 changes: 40 additions & 0 deletions OpenRA.Mods.Common/Traits/Render/WithProductionIconOverlay.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 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, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion

using System;
using System.Linq;
using OpenRA.Traits;

namespace OpenRA.Mods.Common.Traits.Render
{
[Desc("Displays overlays from `ProductionIconOverlayManager` with matching types when defined prerequisites are granted.")]
public class WithProductionIconOverlayInfo : TraitInfo<WithProductionIconOverlay>, IRulesetLoaded
{
[FieldLoader.Require]
public readonly string[] Types = Array.Empty<string>();

public readonly string[] Prerequisites = Array.Empty<string>();

public virtual void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
foreach (var type in Types)
{
if (!rules.Actors[SystemActors.Player].TraitInfos<ProductionIconOverlayManagerInfo>().Where(piom => piom.Type == type).Any())
throw new YamlException($"A 'ProductionIconOverlayManager' with type '{type}' doesn't exist.");

if (ai.TraitInfos<WithProductionIconOverlayInfo>().Where(wpio => wpio != this && wpio.Types.Contains(type)).Any())
throw new YamlException($"Multiple 'WithProductionIconOverlay's with type '{type}' exist on the actor.");
}
}
}

public class WithProductionIconOverlay { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#region Copyright & License Information
/*
* Copyright 2007-2022 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, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion

using System.Collections.Generic;
using System.Linq;

namespace OpenRA.Mods.Common.UpdateRules.Rules
{
public class UnhardcodeVeteranProductionIconOverlay : UpdateRule
{
public override string Name => "VeteranProductionIconOverlay is changed to ProductionIconOverlayManager giving it more customisation.";

public override string Description => "ProductionIconOverlayManager now works with the new WithProductionIconOverlay trait, instead of ProducibleWithLevel.";

readonly List<string> locations = new List<string>();

public override IEnumerable<string> AfterUpdate(ModData modData)
{
if (locations.Any())
yield return "Icon overlay logic has been split from ProducibleWithLevel to WithProductionIconOverlay trait.\n" +
"If you have been using VeteranProductionIconOverlay trait, add WithProductionIconOverlay to following actors:\n" +
UpdateUtils.FormatMessageList(locations);

locations.Clear();
}

public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
{
foreach (var veteranProductionIconOverlay in actorNode.ChildrenMatching("VeteranProductionIconOverlay"))
{
veteranProductionIconOverlay.RenameKey("ProductionIconOverlayManager");
veteranProductionIconOverlay.AddNode(new MiniYamlNode("Type", "Veterancy"));
}

foreach (var producibleWithLevel in actorNode.ChildrenMatching("ProducibleWithLevel"))
locations.Add($"{actorNode.Key}: {producibleWithLevel.Key} ({actorNode.Location.Filename})");

yield break;
}
}
}
1 change: 1 addition & 0 deletions OpenRA.Mods.Common/UpdateRules/UpdatePath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public class UpdatePath
new SplitNukePowerMissileImage(),
new ReplaceSequenceEmbeddedPalette(),
new UnhardcodeBaseBuilderBotModule(),
new UnhardcodeVeteranProductionIconOverlay(),
})
};

Expand Down
15 changes: 15 additions & 0 deletions mods/ra/rules/aircraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ MIG:
RequiresSelection: true
GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded

YAK:
Inherits: ^Plane
Expand Down Expand Up @@ -210,6 +213,9 @@ YAK:
PipCount: 6
GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded

TRAN:
Inherits: ^Helicopter
Expand Down Expand Up @@ -343,6 +349,9 @@ HELI:
RequiresSelection: true
GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded

HIND:
Inherits: ^Helicopter
Expand Down Expand Up @@ -426,6 +435,9 @@ HIND:
PipCount: 6
GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded

U2:
Inherits: ^NeutralPlane
Expand Down Expand Up @@ -544,3 +556,6 @@ MH60:
PipCount: 6
GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded
27 changes: 27 additions & 0 deletions mods/ra/rules/infantry.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ E1:
IsPlayerPalette: true
ProducibleWithLevel:
Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded

E1R1:
Inherits: E1
Expand All @@ -114,6 +117,9 @@ E1R1:
UpdatesPlayerStatistics:
OverrideActor: e1
-Buildable:
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: techlevel.infonly

E2:
Inherits: ^Soldier
Expand Down Expand Up @@ -158,6 +164,9 @@ E2:
DamageSource: Killer
ProducibleWithLevel:
Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded

E3:
Inherits: ^Soldier
Expand Down Expand Up @@ -202,6 +211,9 @@ E3:
Prerequisites: barracks.upgraded
AutoTarget:
ScanRadius: 5
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded

E3R1:
Inherits: E3
Expand All @@ -213,6 +225,9 @@ E3R1:
UpdatesPlayerStatistics:
OverrideActor: e3
-Buildable:
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: techlevel.infonly

E4:
Inherits: ^Soldier
Expand Down Expand Up @@ -254,6 +269,9 @@ E4:
IsPlayerPalette: true
ProducibleWithLevel:
Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded

E6:
Inherits: ^Soldier
Expand Down Expand Up @@ -436,6 +454,9 @@ E7:
VoiceSet: TanyaVoice
ProducibleWithLevel:
Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded

MEDI:
Inherits: ^Soldier
Expand Down Expand Up @@ -706,6 +727,9 @@ SHOK:
VoiceSet: ShokVoice
ProducibleWithLevel:
Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded

SNIPER:
Inherits: ^Soldier
Expand Down Expand Up @@ -759,6 +783,9 @@ SNIPER:
-MustBeDestroyed:
ProducibleWithLevel:
Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded

Zombie:
Inherits: ^Soldier
Expand Down
3 changes: 2 additions & 1 deletion mods/ra/rules/player.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,8 @@ Player:
Id: unrestricted
GrantConditionOnPrerequisiteManager:
EnemyWatcher:
VeteranProductionIconOverlay:
ProductionIconOverlayManager:
Type: Veterancy
Image: iconchevrons
Sequence: veteran
ResourceStorageWarning:
Expand Down
Loading

0 comments on commit 5434059

Please sign in to comment.