diff --git a/OpenRA.Mods.Common/Traits/Cloak.cs b/OpenRA.Mods.Common/Traits/Cloak.cs index 48164dc04f..05f71412c7 100644 --- a/OpenRA.Mods.Common/Traits/Cloak.cs +++ b/OpenRA.Mods.Common/Traits/Cloak.cs @@ -39,6 +39,8 @@ namespace OpenRA.Mods.Common.Traits // Type tag for DetectionTypes public class DetectionType { } + public enum CloakStyle { None, Alpha, Color, Palette } + [Desc("This unit can cloak and uncloak in specific situations.")] public class CloakInfo : PausableConditionalTraitInfo { @@ -57,10 +59,6 @@ namespace OpenRA.Mods.Common.Traits public readonly string CloakSound = null; public readonly string UncloakSound = null; - [PaletteReference(nameof(IsPlayerPalette))] - public readonly string Palette = "cloak"; - public readonly bool IsPlayerPalette = false; - public readonly BitSet DetectionTypes = new("Cloak"); [GrantedConditionReference] @@ -70,6 +68,22 @@ namespace OpenRA.Mods.Common.Traits [Desc("The type of cloak. Same type of cloaks won't trigger cloaking and uncloaking sound and effect.")] public readonly string CloakType = null; + [Desc("Render effect to use when cloaked.")] + public readonly CloakStyle CloakStyle = CloakStyle.Alpha; + + [Desc("The alpha level to use when cloaked when using Alpha CloakStyle.")] + public readonly float CloakedAlpha = 0.55f; + + [Desc("The color to use when cloaked when using Color CloakStyle.")] + public readonly Color CloakedColor = Color.FromArgb(140, 0, 0, 0); + + [PaletteReference(nameof(IsPlayerPalette))] + [Desc("The palette to use when cloaked when using Palette CloakStyle.")] + public readonly string CloakedPalette = null; + + [Desc("Indicates that CloakedPalette is a player palette when using Palette CloakStyle.")] + public readonly bool IsPlayerPalette = false; + [Desc("Which image to use for the effect played when cloaking or uncloaking.")] public readonly string EffectImage = null; @@ -95,8 +109,11 @@ namespace OpenRA.Mods.Common.Traits } public class Cloak : PausableConditionalTrait, IRenderModifier, INotifyDamage, INotifyUnloadCargo, INotifyLoadCargo, INotifyDemolition, INotifyInfiltration, - INotifyAttack, ITick, IVisibilityModifier, IRadarColorModifier, INotifyCreated, INotifyDockClient, INotifySupportPower + INotifyAttack, ITick, IVisibilityModifier, IRadarColorModifier, INotifyDockClient, INotifySupportPower { + readonly float3 cloakedColor; + readonly float cloakedColorAlpha; + [Sync] int remainingTime; @@ -112,6 +129,8 @@ namespace OpenRA.Mods.Common.Traits : base(info) { remainingTime = info.InitialDelay; + cloakedColor = new float3(info.CloakedColor.R, info.CloakedColor.G, info.CloakedColor.B) / 255f; + cloakedColorAlpha = info.CloakedColor.A / 255f; } protected override void Created(Actor self) @@ -162,15 +181,28 @@ namespace OpenRA.Mods.Common.Traits if (Cloaked && IsVisible(self, self.World.RenderPlayer)) { - var palette = wr.Palette(Info.IsPlayerPalette ? Info.Palette + self.Owner.InternalName : Info.Palette); + switch (Info.CloakStyle) + { + case CloakStyle.Alpha: + return r.Select(a => !a.IsDecoration && a is IModifyableRenderable mr ? mr.WithAlpha(Info.CloakedAlpha) : a); - if (palette == null) - return r; - else - return r.Select(a => !a.IsDecoration && a is IPalettedRenderable pr ? pr.WithPalette(palette) : a); + case CloakStyle.Color: + return r.Select(a => !a.IsDecoration && a is IModifyableRenderable mr ? + mr.WithTint(cloakedColor, mr.TintModifiers | TintModifiers.ReplaceColor).WithAlpha(cloakedColorAlpha) : + a); + + case CloakStyle.Palette: + { + var palette = wr.Palette(Info.IsPlayerPalette ? Info.CloakedPalette + self.Owner.InternalName : Info.CloakedPalette); + return r.Select(a => !a.IsDecoration && a is IPalettedRenderable pr ? pr.WithPalette(palette) : a); + } + + default: + return r; + } } - else - return SpriteRenderable.None; + + return SpriteRenderable.None; } IEnumerable IRenderModifier.ModifyScreenBounds(Actor self, WorldRenderer wr, IEnumerable bounds) diff --git a/OpenRA.Mods.Common/UpdateRules/Rules/20231010/ReplaceCloakPalette.cs b/OpenRA.Mods.Common/UpdateRules/Rules/20231010/ReplaceCloakPalette.cs new file mode 100644 index 0000000000..788d8f7254 --- /dev/null +++ b/OpenRA.Mods.Common/UpdateRules/Rules/20231010/ReplaceCloakPalette.cs @@ -0,0 +1,49 @@ +#region Copyright & License Information +/* + * Copyright (c) The OpenRA Developers and Contributors + * 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; + +namespace OpenRA.Mods.Common.UpdateRules.Rules +{ + public class ReplaceCloakPalette : UpdateRule + { + public override string Name => "Change default Cloak style from Palette to Alpha."; + + public override string Description => + "Cloak has gained several new rendering modes\n" + + "and its default behaviour has changed from using a palette to native alpha."; + + readonly List locations = new(); + + public override IEnumerable AfterUpdate(ModData modData) + { + if (locations.Count > 0) + yield return "Cloak no longer defaults to replacing the actor's palette.\n" + + "If you wish to keep the previous behavior you wish to change the\n" + + "Cloak definitions on the following actor definitions:\n" + + UpdateUtils.FormatMessageList(locations); + + locations.Clear(); + } + + public override IEnumerable UpdateActorNode(ModData modData, MiniYamlNodeBuilder actorNode) + { + foreach (var cloak in actorNode.ChildrenMatching("Cloak")) + { + cloak.RemoveNodes("Palette"); + cloak.RemoveNodes("IsPlayerPalette"); + locations.Add($"{actorNode.Key} ({actorNode.Location.Filename})"); + } + + yield break; + } + } +} diff --git a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs index f667d8a5a7..6917590ecb 100644 --- a/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs +++ b/OpenRA.Mods.Common/UpdateRules/UpdatePath.cs @@ -85,6 +85,7 @@ namespace OpenRA.Mods.Common.UpdateRules new ExtractResourceStorageFromHarvester(), new ReplacePaletteModifiers(), new RemoveConyardChronoReturnAnimation(), + new ReplaceCloakPalette(), // Execute these rules last to avoid premature yaml merge crashes. new AbstractDocking(), diff --git a/mods/cnc/rules/aircraft.yaml b/mods/cnc/rules/aircraft.yaml index 82d60dc103..bf71828681 100644 --- a/mods/cnc/rules/aircraft.yaml +++ b/mods/cnc/rules/aircraft.yaml @@ -208,6 +208,8 @@ C17: Cloak: InitialDelay: 0 CloakDelay: 0 + CloakStyle: Palette + CloakedPalette: cloak DetectionTypes: C17 RequiresCondition: global-C17-stealth Contrail@1: diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index 0eda31a3bb..2ac5b7ffcf 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -199,6 +199,8 @@ CloakDelay: 90 CloakSound: trans1.aud UncloakSound: trans1.aud + CloakStyle: Palette + CloakedPalette: cloak PauseOnCondition: cloak-force-disabled RequiresCondition: cloak-crate-collected ExternalCondition@CLOAK: diff --git a/mods/cnc/rules/vehicles.yaml b/mods/cnc/rules/vehicles.yaml index e68f58ed3c..04ae7dfe3f 100644 --- a/mods/cnc/rules/vehicles.yaml +++ b/mods/cnc/rules/vehicles.yaml @@ -708,6 +708,8 @@ STNK: CloakDelay: 85 CloakSound: trans1.aud UncloakSound: trans1.aud + CloakStyle: Palette + CloakedPalette: cloak UncloakOn: Attack, Unload, Dock, Damage, Heal PauseOnCondition: cloak-force-disabled GrantConditionOnDamageState@UNCLOAK: diff --git a/mods/d2k/rules/campaign-palettes.yaml b/mods/d2k/rules/campaign-palettes.yaml index 9467b234e9..e5d9b88ffa 100644 --- a/mods/d2k/rules/campaign-palettes.yaml +++ b/mods/d2k/rules/campaign-palettes.yaml @@ -1,6 +1,5 @@ ^Palettes: -PlayerColorPalette: - -PaletteFromPlayerPaletteWithAlpha@cloak: IndexedPlayerPalette: BasePalette: d2k BaseName: player @@ -15,7 +14,3 @@ Mercenaries: 239, 238, 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224 Neutral: 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240 Creeps: 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240 - PaletteFromPlayerPaletteWithAlpha@Cloak: - BaseName: cloak - BasePalette: player - Alpha: 0.55 diff --git a/mods/d2k/rules/infantry.yaml b/mods/d2k/rules/infantry.yaml index d777588aaf..3f5c7634ad 100644 --- a/mods/d2k/rules/infantry.yaml +++ b/mods/d2k/rules/infantry.yaml @@ -186,7 +186,6 @@ fremen: InitialDelay: 85 CloakDelay: 85 UncloakOn: Attack, Unload, Infiltrate, Demolish, Dock, Damage, Heal - IsPlayerPalette: true PauseOnCondition: cloak-force-disabled GrantConditionOnDamageState@UNCLOAK: Condition: cloak-force-disabled @@ -328,7 +327,6 @@ saboteur: CloakDelay: 25 CloakSound: STEALTH1.WAV UncloakOn: Attack, Unload, Infiltrate, Demolish, Damage, Heal - IsPlayerPalette: true PauseOnCondition: cloak-force-disabled GrantConditionOnDamageState@UNCLOAK: Condition: cloak-force-disabled diff --git a/mods/d2k/rules/palettes.yaml b/mods/d2k/rules/palettes.yaml index b66768b299..9081ad8815 100644 --- a/mods/d2k/rules/palettes.yaml +++ b/mods/d2k/rules/palettes.yaml @@ -44,7 +44,3 @@ RemapIndex: 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240 MenuPostProcessEffect: FlashPostProcessEffect: - PaletteFromPlayerPaletteWithAlpha@cloak: - BaseName: cloak - BasePalette: player - Alpha: 0.55 diff --git a/mods/d2k/rules/vehicles.yaml b/mods/d2k/rules/vehicles.yaml index faa4251a9a..83e5c405db 100644 --- a/mods/d2k/rules/vehicles.yaml +++ b/mods/d2k/rules/vehicles.yaml @@ -498,7 +498,6 @@ stealth_raider: InitialDelay: 45 CloakDelay: 90 UncloakOn: Attack, Unload, Infiltrate, Demolish, Dock, Damage, Heal - IsPlayerPalette: true PauseOnCondition: cloak-force-disabled GrantConditionOnDamageState@UNCLOAK: Condition: cloak-force-disabled diff --git a/mods/ra/maps/fort-lonestar/rules.yaml b/mods/ra/maps/fort-lonestar/rules.yaml index d624c8e134..2a0f021431 100644 --- a/mods/ra/maps/fort-lonestar/rules.yaml +++ b/mods/ra/maps/fort-lonestar/rules.yaml @@ -316,7 +316,6 @@ SNIPER: CloakSound: UncloakSound: UncloakOn: Attack, Unload, Infiltrate, Demolish, Move - IsPlayerPalette: true PauseOnCondition: cloak-force-disabled GrantConditionOnDamageState@UNCLOAK: Condition: cloak-force-disabled diff --git a/mods/ra/rules/campaign-palettes.yaml b/mods/ra/rules/campaign-palettes.yaml index 24d63baa3e..4877b0d355 100644 --- a/mods/ra/rules/campaign-palettes.yaml +++ b/mods/ra/rules/campaign-palettes.yaml @@ -1,7 +1,6 @@ ^Palettes: -PlayerColorPalette: -PlayerColorPalette@NOSHADOW: - -PaletteFromPlayerPaletteWithAlpha@cloak: IndexedPlayerPalette: BasePalette: player BaseName: player @@ -40,7 +39,3 @@ Creeps: 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143 GoodGuy: 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175 BadGuy: 229, 230, 231, 232, 233, 234, 235, 8, 236, 237, 238, 239, 221, 222, 223, 223 - PaletteFromPlayerPaletteWithAlpha@Cloak: - BaseName: cloak - BasePalette: player - Alpha: 0.55 diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index ed53b9536b..6236a13865 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -559,10 +559,10 @@ DetectionTypes: Underwater InitialDelay: 0 CloakDelay: 50 + CloakStyle: Color CloakSound: subshow1.aud UncloakSound: subshow1.aud CloakedCondition: underwater - Palette: submerged PauseOnCondition: cloak-force-disabled GrantConditionOnDamageState@UNCLOAK: Condition: cloak-force-disabled @@ -1230,7 +1230,7 @@ Cloak: CloakSound: UncloakSound: - Palette: + CloakStyle: None DetectionTypes: Mine InitialDelay: 0 Tooltip: diff --git a/mods/ra/rules/infantry.yaml b/mods/ra/rules/infantry.yaml index a42310f05b..c2a0f9b79d 100644 --- a/mods/ra/rules/infantry.yaml +++ b/mods/ra/rules/infantry.yaml @@ -664,7 +664,6 @@ THF: CloakDelay: 120 UncloakOn: Attack, Unload, Infiltrate, Demolish, Move DetectionTypes: Cloak - IsPlayerPalette: true PauseOnCondition: cloak-force-disabled GrantConditionOnDamageState@UNCLOAK: Condition: cloak-force-disabled diff --git a/mods/ra/rules/palettes.yaml b/mods/ra/rules/palettes.yaml index 9bf7a8fe84..66b4786cd3 100644 --- a/mods/ra/rules/palettes.yaml +++ b/mods/ra/rules/palettes.yaml @@ -56,12 +56,6 @@ G: 0 B: 0 A: 140 - PaletteFromRGBA@submerged: - Name: submerged - R: 0 - G: 0 - B: 0 - A: 140 PaletteFromRGBA@moveflash: Name: moveflash R: 255 @@ -80,10 +74,6 @@ BaseName: player-noshadow BasePalette: player-noshadow RemapIndex: 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95 - PaletteFromPlayerPaletteWithAlpha@cloak: - BaseName: cloak - BasePalette: player - Alpha: 0.55 MenuPostProcessEffect: RotationPaletteEffect@defaultwater: Palettes: terrain diff --git a/mods/ra/rules/structures.yaml b/mods/ra/rules/structures.yaml index 1677355519..cab716e8ab 100644 --- a/mods/ra/rules/structures.yaml +++ b/mods/ra/rules/structures.yaml @@ -795,7 +795,6 @@ HBOX: Cloak: InitialDelay: 125 CloakDelay: 60 - IsPlayerPalette: true PauseOnCondition: cloak-force-disabled GrantConditionOnDamageState@UNCLOAK: Condition: cloak-force-disabled diff --git a/mods/ra/rules/vehicles.yaml b/mods/ra/rules/vehicles.yaml index 1593bc7b45..800b3ee334 100644 --- a/mods/ra/rules/vehicles.yaml +++ b/mods/ra/rules/vehicles.yaml @@ -919,7 +919,6 @@ STNK: CloakDelay: 175 CloakSound: appear1.aud UncloakSound: appear1.aud - IsPlayerPalette: true PauseOnCondition: cloak-force-disabled UncloakOn: Attack, Load, Unload, Heal, Dock GrantConditionOnDamageState@UNCLOAK: diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index d7e75992c0..3181840970 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -129,7 +129,6 @@ RequiresCondition: cloakgenerator || crate-cloak InitialDelay: 0 CloakDelay: 90 - IsPlayerPalette: true CloakSound: cloak5.aud UncloakSound: cloak5.aud UncloakOn: Attack, Unload, Infiltrate, Demolish, Damage, Heal, SupportPower diff --git a/mods/ts/rules/nod-vehicles.yaml b/mods/ts/rules/nod-vehicles.yaml index b47c2beb3e..f9fb10ee7e 100644 --- a/mods/ts/rules/nod-vehicles.yaml +++ b/mods/ts/rules/nod-vehicles.yaml @@ -526,7 +526,6 @@ STNK: CloakDelay: 90 CloakSound: cloak5.aud UncloakSound: cloak5.aud - IsPlayerPalette: true UncloakOn: Attack, Unload, Infiltrate, Demolish, Damage, Heal PauseOnCondition: cloak-force-disabled || empdisable CloakType: nod-stealth diff --git a/mods/ts/rules/palettes.yaml b/mods/ts/rules/palettes.yaml index 5c644a8753..4afcbbd51c 100644 --- a/mods/ts/rules/palettes.yaml +++ b/mods/ts/rules/palettes.yaml @@ -152,10 +152,6 @@ BaseName: player-nobright BasePalette: player-nobright RemapIndex: 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 - PaletteFromPlayerPaletteWithAlpha@cloak: - BaseName: cloak - BasePalette: player - Alpha: 0.55 PaletteFromPaletteWithAlpha@terrainalpha: BasePalette: terraindecoration Name: terrainalpha