Unhardcode VeteranProductionIconOverlay.

This commit is contained in:
Mustafa Alperen Seki
2022-01-31 15:13:07 +03:00
committed by Gustas
parent d438508994
commit 54340591e3
9 changed files with 199 additions and 22 deletions

View File

@@ -15,8 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[Desc("Actors possessing this trait should define the GainsExperience trait. When the prerequisites are fulfilled, ", [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 ", "this trait grants a level-up to newly spawned actors.")]
"trait, the production queue icon renders with an overlay defined in that trait.")]
public class ProducibleWithLevelInfo : TraitInfo, Requires<GainsExperienceInfo> public class ProducibleWithLevelInfo : TraitInfo, Requires<GainsExperienceInfo>
{ {
public readonly string[] Prerequisites = Array.Empty<string>(); public readonly string[] Prerequisites = Array.Empty<string>();

View File

@@ -10,17 +10,20 @@
#endregion #endregion
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render namespace OpenRA.Mods.Common.Traits.Render
{ {
[TraitLocation(SystemActors.Player)] [TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor. When attached, enables all actors possessing the ProducibleWithLevel ", [Desc("Attach this to the player actor. Required for WithProductionIconOverlay trait on actors to work.")]
"trait to have their production queue icons render with an overlay defined in this trait. ", public class ProductionIconOverlayManagerInfo : TraitInfo, Requires<TechTreeInfo>, IRulesetLoaded
"The icon change occurs when ProducibleWithLevel.Prerequisites are met.")]
public class VeteranProductionIconOverlayInfo : TraitInfo, Requires<TechTreeInfo>
{ {
[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] [FieldLoader.Require]
[Desc("Image used for the overlay.")] [Desc("Image used for the overlay.")]
public readonly string Image = null; public readonly string Image = null;
@@ -33,24 +36,30 @@ namespace OpenRA.Mods.Common.Traits.Render
[Desc("Palette to render the sprite in. Reference the world actor's PaletteFrom* traits.")] [Desc("Palette to render the sprite in. Reference the world actor's PaletteFrom* traits.")]
public readonly string Palette = "chrome"; 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. // HACK: TechTree doesn't associate Watcher.Key with the registering ITechTreeElement.
// So in a situation where multiple ITechTreeElements register Watchers with the same Key, // 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. // 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. // This makes sure that the keys are unique with respect to the registering ITechTreeElement.
const string Prefix = "ProductionIconOverlay."; readonly string prefix;
readonly Actor self;
readonly Sprite sprite;
readonly VeteranProductionIconOverlayInfo info;
readonly Dictionary<ActorInfo, bool> overlayActive = new Dictionary<ActorInfo, bool>(); readonly Dictionary<ActorInfo, bool> overlayActive = new Dictionary<ActorInfo, bool>();
public VeteranProductionIconOverlay(ActorInitializer init, VeteranProductionIconOverlayInfo info) public ProductionIconOverlayManager(ActorInitializer init, ProductionIconOverlayManagerInfo info)
{ {
self = init.Self; self = init.Self;
@@ -60,13 +69,13 @@ namespace OpenRA.Mods.Common.Traits.Render
this.info = info; this.info = info;
prefix = info.Type + ".";
var ttc = self.Trait<TechTree>(); var ttc = self.Trait<TechTree>();
foreach (var a in self.World.Map.Rules.Actors.Values) foreach (var a in self.World.Map.Rules.Actors.Values)
{ {
var uwc = a.TraitInfoOrDefault<ProducibleWithLevelInfo>(); foreach (var wpio in a.TraitInfos<WithProductionIconOverlayInfo>().Where(wpio => wpio.Types.Contains(info.Type)))
if (uwc != null) ttc.Add(MakeKey(a.Name), wpio.Prerequisites, 0, this);
ttc.Add(MakeKey(a.Name), uwc.Prerequisites, 0, this);
} }
} }
@@ -88,14 +97,14 @@ namespace OpenRA.Mods.Common.Traits.Render
return isActive; 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) public void PrerequisitesAvailable(string key)

View File

@@ -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 { }
}

View File

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

View File

@@ -95,6 +95,7 @@ namespace OpenRA.Mods.Common.UpdateRules
new SplitNukePowerMissileImage(), new SplitNukePowerMissileImage(),
new ReplaceSequenceEmbeddedPalette(), new ReplaceSequenceEmbeddedPalette(),
new UnhardcodeBaseBuilderBotModule(), new UnhardcodeBaseBuilderBotModule(),
new UnhardcodeVeteranProductionIconOverlay(),
}) })
}; };

View File

@@ -131,6 +131,9 @@ MIG:
RequiresSelection: true RequiresSelection: true
GrantConditionOnDamageState@SmokeTrail: GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded
YAK: YAK:
Inherits: ^Plane Inherits: ^Plane
@@ -210,6 +213,9 @@ YAK:
PipCount: 6 PipCount: 6
GrantConditionOnDamageState@SmokeTrail: GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded
TRAN: TRAN:
Inherits: ^Helicopter Inherits: ^Helicopter
@@ -343,6 +349,9 @@ HELI:
RequiresSelection: true RequiresSelection: true
GrantConditionOnDamageState@SmokeTrail: GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded
HIND: HIND:
Inherits: ^Helicopter Inherits: ^Helicopter
@@ -426,6 +435,9 @@ HIND:
PipCount: 6 PipCount: 6
GrantConditionOnDamageState@SmokeTrail: GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded
U2: U2:
Inherits: ^NeutralPlane Inherits: ^NeutralPlane
@@ -544,3 +556,6 @@ MH60:
PipCount: 6 PipCount: 6
GrantConditionOnDamageState@SmokeTrail: GrantConditionOnDamageState@SmokeTrail:
Condition: enable-smoke Condition: enable-smoke
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: aircraft.upgraded

View File

@@ -103,6 +103,9 @@ E1:
IsPlayerPalette: true IsPlayerPalette: true
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: barracks.upgraded Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded
E1R1: E1R1:
Inherits: E1 Inherits: E1
@@ -114,6 +117,9 @@ E1R1:
UpdatesPlayerStatistics: UpdatesPlayerStatistics:
OverrideActor: e1 OverrideActor: e1
-Buildable: -Buildable:
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: techlevel.infonly
E2: E2:
Inherits: ^Soldier Inherits: ^Soldier
@@ -158,6 +164,9 @@ E2:
DamageSource: Killer DamageSource: Killer
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: barracks.upgraded Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded
E3: E3:
Inherits: ^Soldier Inherits: ^Soldier
@@ -202,6 +211,9 @@ E3:
Prerequisites: barracks.upgraded Prerequisites: barracks.upgraded
AutoTarget: AutoTarget:
ScanRadius: 5 ScanRadius: 5
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded
E3R1: E3R1:
Inherits: E3 Inherits: E3
@@ -213,6 +225,9 @@ E3R1:
UpdatesPlayerStatistics: UpdatesPlayerStatistics:
OverrideActor: e3 OverrideActor: e3
-Buildable: -Buildable:
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: techlevel.infonly
E4: E4:
Inherits: ^Soldier Inherits: ^Soldier
@@ -254,6 +269,9 @@ E4:
IsPlayerPalette: true IsPlayerPalette: true
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: barracks.upgraded Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded
E6: E6:
Inherits: ^Soldier Inherits: ^Soldier
@@ -436,6 +454,9 @@ E7:
VoiceSet: TanyaVoice VoiceSet: TanyaVoice
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: barracks.upgraded Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded
MEDI: MEDI:
Inherits: ^Soldier Inherits: ^Soldier
@@ -706,6 +727,9 @@ SHOK:
VoiceSet: ShokVoice VoiceSet: ShokVoice
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: barracks.upgraded Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded
SNIPER: SNIPER:
Inherits: ^Soldier Inherits: ^Soldier
@@ -759,6 +783,9 @@ SNIPER:
-MustBeDestroyed: -MustBeDestroyed:
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: barracks.upgraded Prerequisites: barracks.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: barracks.upgraded
Zombie: Zombie:
Inherits: ^Soldier Inherits: ^Soldier

View File

@@ -172,7 +172,8 @@ Player:
Id: unrestricted Id: unrestricted
GrantConditionOnPrerequisiteManager: GrantConditionOnPrerequisiteManager:
EnemyWatcher: EnemyWatcher:
VeteranProductionIconOverlay: ProductionIconOverlayManager:
Type: Veterancy
Image: iconchevrons Image: iconchevrons
Sequence: veteran Sequence: veteran
ResourceStorageWarning: ResourceStorageWarning:

View File

@@ -47,6 +47,9 @@ V2RL:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
Selectable: Selectable:
DecorationBounds: 1194, 1194 DecorationBounds: 1194, 1194
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
1TNK: 1TNK:
Inherits: ^TrackedVehicle Inherits: ^TrackedVehicle
@@ -89,6 +92,9 @@ V2RL:
WithSpriteTurret: WithSpriteTurret:
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
2TNK: 2TNK:
Inherits: ^TrackedVehicle Inherits: ^TrackedVehicle
@@ -135,6 +141,9 @@ V2RL:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
Selectable: Selectable:
DecorationBounds: 1194, 1194 DecorationBounds: 1194, 1194
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
3TNK: 3TNK:
Inherits: ^TrackedVehicle Inherits: ^TrackedVehicle
@@ -181,6 +190,9 @@ V2RL:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
Selectable: Selectable:
DecorationBounds: 1194, 1194 DecorationBounds: 1194, 1194
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
4TNK: 4TNK:
Inherits: ^TrackedVehicle Inherits: ^TrackedVehicle
@@ -240,6 +252,9 @@ V2RL:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
Selectable: Selectable:
DecorationBounds: 1877, 1621, 0, -170 DecorationBounds: 1877, 1621, 0, -170
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
ARTY: ARTY:
Inherits: ^TrackedVehicle Inherits: ^TrackedVehicle
@@ -285,6 +300,9 @@ ARTY:
LoadedChance: 75 LoadedChance: 75
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
HARV: HARV:
Inherits: ^Vehicle Inherits: ^Vehicle
@@ -432,6 +450,9 @@ JEEP:
LoadingCondition: notmobile LoadingCondition: notmobile
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
APC: APC:
Inherits: ^TrackedVehicle Inherits: ^TrackedVehicle
@@ -475,6 +496,9 @@ APC:
LoadingCondition: notmobile LoadingCondition: notmobile
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
MNLY: MNLY:
Inherits: ^TrackedVehicle Inherits: ^TrackedVehicle
@@ -663,6 +687,9 @@ TTNK:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
Selectable: Selectable:
DecorationBounds: 1280, 1280 DecorationBounds: 1280, 1280
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
FTRK: FTRK:
Inherits: ^Vehicle Inherits: ^Vehicle
@@ -712,6 +739,9 @@ FTRK:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
Selectable: Selectable:
DecorationBounds: 1194, 1194 DecorationBounds: 1194, 1194
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
DTRK: DTRK:
Inherits: ^Vehicle Inherits: ^Vehicle
@@ -797,6 +827,9 @@ CTNK:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
Selectable: Selectable:
DecorationBounds: 1280, 1280 DecorationBounds: 1280, 1280
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded
QTNK: QTNK:
Inherits: ^TrackedVehicle Inherits: ^TrackedVehicle
@@ -896,3 +929,6 @@ STNK:
-MustBeDestroyed: -MustBeDestroyed:
ProducibleWithLevel: ProducibleWithLevel:
Prerequisites: vehicles.upgraded Prerequisites: vehicles.upgraded
WithProductionIconOverlay:
Types: Veterancy
Prerequisites: vehicles.upgraded