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
{
[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>();

View File

@@ -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;
@@ -33,24 +36,30 @@ namespace OpenRA.Mods.Common.Traits.Render
[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 class VeteranProductionIconOverlay : ITechTreeElement, IProductionIconOverlay
public override object Create(ActorInitializer init) { return new ProductionIconOverlayManager(init, this); }
}
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;
@@ -60,13 +69,13 @@ namespace OpenRA.Mods.Common.Traits.Render
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);
}
}
@@ -88,14 +97,14 @@ namespace OpenRA.Mods.Common.Traits.Render
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)

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 ReplaceSequenceEmbeddedPalette(),
new UnhardcodeBaseBuilderBotModule(),
new UnhardcodeVeteranProductionIconOverlay(),
})
};

View File

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

View File

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

View File

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

View File

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