Allow WeatherOverlay fade in/out when enabled/disabled

This commit is contained in:
dnqbob
2023-11-01 22:55:36 +08:00
committed by Gustas
parent 02d31a2f2c
commit 264564d006

View File

@@ -19,7 +19,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
[Desc("Adds a particle-based overlay.")] [Desc("Adds a particle-based overlay.")]
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)] [TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class WeatherOverlayInfo : TraitInfo, ILobbyCustomRulesIgnore public class WeatherOverlayInfo : ConditionalTraitInfo, ILobbyCustomRulesIgnore
{ {
[Desc("Average number of particles per 100x100 px square.")] [Desc("Average number of particles per 100x100 px square.")]
public readonly int ParticleDensityFactor = 8; public readonly int ParticleDensityFactor = 8;
@@ -69,10 +69,19 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Works only with line enabled and can be used to fade out the tail of the line like a contrail.")] [Desc("Works only with line enabled and can be used to fade out the tail of the line like a contrail.")]
public readonly byte LineTailAlphaValue = 200; public readonly byte LineTailAlphaValue = 200;
[Desc("Time to fade out once the trait becomes disabled.")]
public readonly int FadeOutTicks = 1000;
[Desc("Time to fade in once the trait becomes enabled.")]
public readonly int FadeInTicks = 1000;
[Desc("Percentage of the initial particle when enabled and the game start.")]
public readonly int InitialParticlePercentage = 100;
public override object Create(ActorInitializer init) { return new WeatherOverlay(init.World, this); } public override object Create(ActorInitializer init) { return new WeatherOverlay(init.World, this); }
} }
public class WeatherOverlay : ITick, IRenderAboveWorld, INotifyViewportZoomExtentsChanged public class WeatherOverlay : ConditionalTrait<WeatherOverlayInfo>, ITick, IRenderAboveWorld, INotifyViewportZoomExtentsChanged
{ {
readonly struct Particle readonly struct Particle
{ {
@@ -133,8 +142,9 @@ namespace OpenRA.Mods.Common.Traits
} }
} }
readonly WeatherOverlayInfo info;
readonly World world; readonly World world;
readonly int fadeInTick;
readonly int fadeOutTick;
float windStrength; float windStrength;
int targetWindStrengthIndex; int targetWindStrengthIndex;
@@ -142,14 +152,19 @@ namespace OpenRA.Mods.Common.Traits
Particle[] particles; Particle[] particles;
Size viewportSize; Size viewportSize;
long lastRender; long lastRender;
bool initialTick = true;
int fadingInTick;
int fadingOutTick;
public WeatherOverlay(World world, WeatherOverlayInfo info) public WeatherOverlay(World world, WeatherOverlayInfo info)
: base(info)
{ {
this.info = info;
this.world = world; this.world = world;
targetWindStrengthIndex = info.ChangingWindLevel ? world.LocalRandom.Next(info.WindLevels.Length) : 0; targetWindStrengthIndex = info.ChangingWindLevel ? world.LocalRandom.Next(info.WindLevels.Length) : 0;
windUpdateCountdown = world.LocalRandom.Next(info.WindTick[0], info.WindTick[1]); windUpdateCountdown = world.LocalRandom.Next(info.WindTick[0], info.WindTick[1]);
windStrength = info.WindLevels[targetWindStrengthIndex]; windStrength = info.WindLevels[targetWindStrengthIndex];
fadeInTick = info.FadeInTicks > 0 ? info.FadeInTicks : 1;
fadeOutTick = info.FadeOutTicks > 0 ? info.FadeOutTicks : 1;
} }
void INotifyViewportZoomExtentsChanged.ViewportZoomExtentsChanged(float minZoom, float maxZoom) void INotifyViewportZoomExtentsChanged.ViewportZoomExtentsChanged(float minZoom, float maxZoom)
@@ -159,30 +174,60 @@ namespace OpenRA.Mods.Common.Traits
viewportSize = new Size(s.X, s.Y); viewportSize = new Size(s.X, s.Y);
// Randomly distribute particles within the initial viewport // Randomly distribute particles within the initial viewport
var particleCount = viewportSize.Width * viewportSize.Height * info.ParticleDensityFactor / 10000; var particleCount = viewportSize.Width * viewportSize.Height * Info.ParticleDensityFactor / 10000;
particles = new Particle[particleCount]; particles = new Particle[particleCount];
var rect = new Rectangle(int2.Zero, viewportSize); var rect = new Rectangle(int2.Zero, viewportSize);
for (var i = 0; i < particles.Length; i++) for (var i = 0; i < particles.Length; i++)
particles[i] = new Particle(info, world.LocalRandom, rect); particles[i] = new Particle(Info, world.LocalRandom, rect);
}
protected override void TraitEnabled(Actor self)
{
if (!initialTick)
fadingInTick = (fadeOutTick - fadingOutTick) * 1000 * fadeInTick / fadeOutTick / 1000;
}
protected override void TraitDisabled(Actor self)
{
if (!initialTick)
fadingOutTick = (fadeInTick - fadingInTick) * 1000 * fadeOutTick / fadeInTick / 1000;
} }
void ITick.Tick(Actor self) void ITick.Tick(Actor self)
{ {
if (!info.ChangingWindLevel || info.WindLevels.Length == 1) if (initialTick)
{
initialTick = false;
var initialPercentage = Exts.Clamp(Info.InitialParticlePercentage, 0, 100);
if (IsTraitDisabled)
fadingOutTick = fadeOutTick * (100 - initialPercentage) / 100;
else
fadingInTick = fadeInTick * initialPercentage / 100;
}
if (IsTraitDisabled)
{
if (fadingOutTick < fadeOutTick)
fadingOutTick++;
}
else if (fadingInTick < fadeInTick)
fadingInTick++;
if (!Info.ChangingWindLevel || Info.WindLevels.Length == 1)
return; return;
if (--windUpdateCountdown <= 0) if (--windUpdateCountdown <= 0)
{ {
windUpdateCountdown = self.World.LocalRandom.Next(info.WindTick[0], info.WindTick[1]); windUpdateCountdown = self.World.LocalRandom.Next(Info.WindTick[0], Info.WindTick[1]);
if (targetWindStrengthIndex > 0 && self.World.LocalRandom.Next(2) == 1) if (targetWindStrengthIndex > 0 && self.World.LocalRandom.Next(2) == 1)
targetWindStrengthIndex--; targetWindStrengthIndex--;
else if (targetWindStrengthIndex < info.WindLevels.Length - 1) else if (targetWindStrengthIndex < Info.WindLevels.Length - 1)
targetWindStrengthIndex++; targetWindStrengthIndex++;
} }
// Fading the wind in little steps towards the TargetWindOffset // Fading the wind in little steps towards the TargetWindOffset
var targetWindLevel = info.WindLevels[targetWindStrengthIndex]; var targetWindLevel = Info.WindLevels[targetWindStrengthIndex];
if (info.InstantWindChanges) if (Info.InstantWindChanges)
windStrength = targetWindLevel; windStrength = targetWindLevel;
else if (Math.Abs(windStrength - targetWindLevel) > 0.01f) else if (Math.Abs(windStrength - targetWindLevel) > 0.01f)
{ {
@@ -205,7 +250,9 @@ namespace OpenRA.Mods.Common.Traits
var tickFraction = Math.Min((runtime - lastRender) * 1f / world.Timestep, 1); var tickFraction = Math.Min((runtime - lastRender) * 1f / world.Timestep, 1);
lastRender = runtime; lastRender = runtime;
for (var i = 0; i < particles.Length; i++) var spawnNum = particles.Length * (IsTraitDisabled ? (fadeOutTick - fadingOutTick) * 1000 / fadeOutTick : fadingInTick * 1000 / fadeInTick) / 1000;
for (var i = 0; i < spawnNum; i++)
{ {
// Simulate wind and gravity effects on the particle // Simulate wind and gravity effects on the particle
var p = particles[i]; var p = particles[i];
@@ -238,7 +285,7 @@ namespace OpenRA.Mods.Common.Traits
// Render the particle // Render the particle
// We must provide a z coordinate to stop the GL near and far Z limits from culling the geometry // We must provide a z coordinate to stop the GL near and far Z limits from culling the geometry
var a = new float3(p.Pos.X, p.Pos.Y, p.Pos.Y); var a = new float3(p.Pos.X, p.Pos.Y, p.Pos.Y);
if (info.UseSquares) if (Info.UseSquares)
{ {
var b = a + new float2(p.Size, p.Size); var b = a + new float2(p.Size, p.Size);
wcr.FillRect(a, b, p.Color); wcr.FillRect(a, b, p.Color);