Skip to content

Commit 8db5998

Browse files
committed
Reorganized ScreenShakeSystem, fixed many shakes being global in MP.
1 parent 14ef087 commit 8db5998

File tree

8 files changed

+83
-81
lines changed

8 files changed

+83
-81
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
- Fixed blood spawning in place of cloudy dust when Blood & Gore is disabled in vanilla settings.
4343
- Prevented a seemingly impossible concurrency error in decal code from ever happening. This game has no concurrency, and yet this was reported.
4444
- Fixed a rare `IndexOutOfRangeException` that could occur when dodgerolling while on a grappling hook.
45+
- Fixed many screenshakes being global (positionless) in multiplayer.
4546

4647
### Configuration
4748
- Added `Melee.EnableSwingVelocity` option.

Common/Camera/ItemUseScreenShake.cs

+1-5
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,7 @@ public sealed class ItemUseScreenShake : ItemComponent
1414
if (Enabled) {
1515
var screenShake = ScreenShake;
1616

17-
if (screenShake.Power > 0f && screenShake.Length > 0f) {
18-
screenShake.Position = player.Center;
19-
20-
ScreenShakeSystem.New(screenShake);
21-
}
17+
ScreenShakeSystem.New(screenShake, player.Center);
2218
}
2319

2420
return base.UseItem(item, player);

Common/Camera/ScreenShake.cs

+9-22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
using System;
2-
using Microsoft.Xna.Framework;
3-
using TerrariaOverhaul.Core.Time;
1+
using Microsoft.Xna.Framework;
42
using TerrariaOverhaul.Utilities;
53

64
namespace TerrariaOverhaul.Common.Camera;
@@ -9,32 +7,21 @@ public struct ScreenShake
97
{
108
public const float DefaultRange = 512f;
119

12-
internal float startTime = 0f;
13-
internal float endTime = 0f;
14-
15-
public float Power;
16-
public float Length;
17-
public float Range;
18-
public string? UniqueId;
19-
public Vector2? Position;
10+
public float Power = 0.5f;
2011
public Gradient<float>? PowerGradient;
12+
public float LengthInSeconds = 0.5f;
13+
public float Range = DefaultRange;
14+
public string? UniqueId;
2115

22-
public float TimeLeft => MathF.Max(0f, endTime - TimeSystem.RenderTime);
23-
public float Progress => Length > 0f ? MathHelper.Clamp((TimeSystem.RenderTime - startTime) / Length, 0f, 1f) : 1f;
24-
25-
public ScreenShake(Gradient<float> powerGradient, float lengthInSeconds, Vector2? position = null, float range = DefaultRange, string? uniqueId = null) : this(0f, lengthInSeconds, position, range, uniqueId)
16+
public ScreenShake(Gradient<float> powerGradient, float lengthInSeconds) : this()
2617
{
2718
PowerGradient = powerGradient;
19+
LengthInSeconds = lengthInSeconds;
2820
}
2921

30-
public ScreenShake(float power, float lengthInSeconds, Vector2? position = null, float range = DefaultRange, string? uniqueId = null)
22+
public ScreenShake(float power, float lengthInSeconds) : this()
3123
{
3224
Power = power;
33-
Length = lengthInSeconds;
34-
Position = position;
35-
Range = range;
36-
UniqueId = uniqueId;
37-
38-
PowerGradient = null;
25+
LengthInSeconds = lengthInSeconds;
3926
}
4027
}

Common/Camera/ScreenShakeSystem.cs

+36-30
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,20 @@ namespace TerrariaOverhaul.Common.Camera;
1414
[Autoload(Side = ModSide.Client)]
1515
public sealed class ScreenShakeSystem : ModSystem
1616
{
17+
private struct ScreenShakeInstance
18+
{
19+
public float StartTime;
20+
public float EndTime;
21+
public Vector2? Position;
22+
public ScreenShake Style;
23+
24+
public float TimeLeft => MathF.Max(0f, EndTime - TimeSystem.RenderTime);
25+
public float Progress => Style.LengthInSeconds > 0f ? MathHelper.Clamp((TimeSystem.RenderTime - StartTime) / Style.LengthInSeconds, 0f, 1f) : 1f;
26+
}
27+
1728
public static readonly RangeConfigEntry<float> ScreenShakeStrength = new(ConfigSide.ClientOnly, "Camera", nameof(ScreenShakeStrength), 0f, 1f, () => 1f);
1829

19-
private static readonly List<ScreenShake> screenShakes = new();
30+
private static readonly List<ScreenShakeInstance> screenShakes = new();
2031

2132
private static FastNoiseLite? noise;
2233

@@ -138,21 +149,22 @@ public static float GetPowerAtPoint(Vector2 point)
138149

139150
float power = 0f;
140151

141-
foreach (var shake in EnumerateScreenShakes()) {
142-
float progress = shake.Progress;
152+
foreach (ref var instance in EnumerateScreenShakes()) {
153+
ref readonly var style = ref instance.Style;
154+
float progress = instance.Progress;
143155

144156
float intensity;
145157

146-
if (shake.PowerGradient != null) {
147-
intensity = MathHelper.Clamp(shake.PowerGradient.GetValue(progress), 0f, 1f);
158+
if (style.PowerGradient != null) {
159+
intensity = MathHelper.Clamp(style.PowerGradient.GetValue(progress), 0f, 1f);
148160
} else {
149-
intensity = MathHelper.Clamp(shake.Power, 0f, 1f);
161+
intensity = MathHelper.Clamp(style.Power, 0f, 1f);
150162
intensity *= MathF.Pow(1f - progress, 2f);
151163
}
152164

153-
if (shake.Position.HasValue) {
154-
float distance = Vector2.Distance(shake.Position.Value, point);
155-
float distanceFactor = 1f - Math.Min(1f, distance / shake.Range);
165+
if (instance.Position.HasValue) {
166+
float distance = Vector2.Distance(instance.Position.Value, point);
167+
float distanceFactor = 1f - Math.Min(1f, distance / style.Range);
156168

157169
intensity *= MathF.Pow(distanceFactor, 2f); // Exponential
158170
}
@@ -164,38 +176,32 @@ public static float GetPowerAtPoint(Vector2 point)
164176
return MathHelper.Clamp(power * ScreenShakeStrength.Value, 0f, 1f);
165177
}
166178

167-
public static void New(float power, float time, Vector2? position = null, float range = ScreenShake.DefaultRange, string? uniqueId = null)
168-
=> New(new ScreenShake(power, time, position, range, uniqueId));
169-
170-
public static void New(Gradient<float> powerGradient, float time, Vector2? position = null, float range = ScreenShake.DefaultRange, string? uniqueId = null)
171-
=> New(new ScreenShake(powerGradient, time, position, range, uniqueId));
172-
173-
public static void New(ScreenShake screenShake)
179+
public static void New(ScreenShake style, Vector2? position)
174180
{
175181
if (Main.dedServ) {
176182
return;
177183
}
178184

179-
screenShake.Power = Math.Min(screenShake.Power, 1f);
180-
//screenShake.Length = MathF.Pow(screenShake.Power * 0.6f, 2f);
181-
screenShake.startTime = TimeSystem.RenderTime;
182-
screenShake.endTime = screenShake.startTime + screenShake.Length;
185+
style.Power = MathUtils.Clamp01(style.Power);
183186

184-
if (screenShake.UniqueId == null) {
185-
screenShakes.Add(screenShake);
186-
return;
187-
}
187+
ScreenShakeInstance instance;
188+
189+
instance.Style = style;
190+
instance.Position = position;
191+
instance.StartTime = TimeSystem.RenderTime;
192+
instance.EndTime = instance.StartTime + style.LengthInSeconds;
188193

189-
int index = screenShakes.FindIndex(s => s.UniqueId == screenShake.UniqueId);
194+
string? uniqueId = style.UniqueId;
190195

191-
if (index >= 0) {
192-
screenShakes[index] = screenShake;
193-
} else {
194-
screenShakes.Add(screenShake);
196+
if (uniqueId != null && screenShakes.FindIndex(i => i.Style.UniqueId == uniqueId) is (>= 0 and int index)) {
197+
screenShakes[index] = instance;
198+
return;
195199
}
200+
201+
screenShakes.Add(instance);
196202
}
197203

198-
private static Span<ScreenShake> EnumerateScreenShakes()
204+
private static Span<ScreenShakeInstance> EnumerateScreenShakes()
199205
{
200206
screenShakes.RemoveAll(s => s.TimeLeft <= 0f);
201207

Common/Damage/NPCHitScreenShake.cs

+18-7
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,26 @@ public class NPCHitScreenShake : GlobalNPC
1818

1919
public override void SetDefaults(NPC npc)
2020
{
21-
const float BaseShakeRange = 256f * 5;
21+
const float BaseShakeRange = 256f * 5f;
2222

2323
if (npc.boss || NPCID.Sets.ShouldBeCountedAsBoss[npc.type]) {
24-
OnHitShake = new(0.25f, 0.30f, range: BaseShakeRange, uniqueId: "BossHit");
25-
OnDeathShake = new(1.00f, 1.00f, range: BaseShakeRange * 3f, uniqueId: "BossDeath");
24+
OnHitShake = new(0.25f, 0.30f) {
25+
Range = BaseShakeRange,
26+
UniqueId = "BossHit",
27+
};
28+
OnDeathShake = new(1.00f, 1.00f) {
29+
Range = BaseShakeRange * 3f,
30+
UniqueId = "BossDeath",
31+
};
2632
} else {
27-
OnHitShake = new(0.17f, 0.15f, range: BaseShakeRange, uniqueId: "NpcHit");
28-
OnDeathShake = new(0.30f, 0.30f, range: BaseShakeRange, uniqueId: "NpcDeath");
33+
OnHitShake = new(0.17f, 0.15f) {
34+
Range = BaseShakeRange,
35+
UniqueId = "NpcHit",
36+
};
37+
OnDeathShake = new(0.30f, 0.30f) {
38+
Range = BaseShakeRange,
39+
UniqueId = "NpcDeath",
40+
};
2941
}
3042
}
3143

@@ -40,11 +52,10 @@ private void OnHit(NPC npc, int damage, float knockback, bool crit)
4052
bool isDead = npc.life <= 0;
4153

4254
if ((isDead ? OnDeathShake : OnHitShake) is ScreenShake shake) {
43-
shake.Position = npc.Center;
4455
shake.Power *= MathUtils.Clamp01(damage / 10f);
4556
shake.UniqueId ??= isDead ? "CustomNpcDeath" : "CustomNpcHit";
4657

47-
ScreenShakeSystem.New(shake);
58+
ScreenShakeSystem.New(shake, npc.Center);
4859
}
4960
}
5061
}

Common/Magic/MagicWeapon.cs

+9-7
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,26 @@ public override void SetDefaults(Item item)
5959
item.UseSound = MagicBlastSound;
6060
}
6161

62+
var chargeScreenShakePowerGradient = new Gradient<float>(
63+
(0.0f, 0.0f),
64+
(0.25f, 0.025f),
65+
(1.0f, 0.2f)
66+
);
67+
6268
item.EnableComponent<ItemPowerAttacks>(c => {
6369
c.ChargeLengthMultiplier = 2f;
6470
c.CommonStatMultipliers.ProjectileDamageMultiplier = 1.75f;
6571
c.CommonStatMultipliers.ProjectileKnockbackMultiplier = 1.5f;
6672
c.CommonStatMultipliers.ProjectileSpeedMultiplier = 2f;
6773

6874
c.OnChargeStart += (item, player, chargeLength) => {
69-
if (Main.dedServ) {
75+
if (Main.dedServ || !player.IsLocal()) {
7076
return;
7177
}
7278

7379
ScreenShakeSystem.New(
74-
new Gradient<float>(
75-
(0.0f, 0.0f),
76-
(0.25f, 0.025f),
77-
(1.0f, 0.2f)
78-
),
79-
chargeLength / TimeSystem.LogicFramerate
80+
new ScreenShake(chargeScreenShakePowerGradient, chargeLength * TimeSystem.LogicDeltaTime),
81+
null
8082
);
8183
};
8284
});

Common/Melee/_Overhauls/Broadsword.cs

+5-6
Original file line numberDiff line numberDiff line change
@@ -116,16 +116,15 @@ public override void SetDefaults(Item item)
116116
public override void UseAnimation(Item item, Player player)
117117
{
118118
// Slight screenshake for the swing.
119-
if (!Main.dedServ) {
120-
float intensity = 0.3f;
121-
float time = 0.15f;
119+
if (!Main.dedServ && player.IsLocal()) {
120+
var screenShake = new ScreenShake(0.30f, 0.15f);
122121

123122
if (item.TryGetGlobalItem(out ItemPowerAttacks powerAttacks) && powerAttacks.PowerAttack) {
124-
intensity = 0.75f;
125-
time = 0.25f;
123+
screenShake.Power = 0.75f;
124+
screenShake.LengthInSeconds = 0.25f;
126125
}
127126

128-
ScreenShakeSystem.New(intensity, time);
127+
ScreenShakeSystem.New(screenShake, null);
129128
}
130129
}
131130

Common/ProjectileEffects/ProjectileScreenShake.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ public sealed class ProjectileScreenShake : GlobalProjectile
1515
public override void SetDefaults(Projectile projectile)
1616
{
1717
if (OverhaulProjectileTags.Explosive.Has(projectile.type)) {
18-
ScreenShake = new ScreenShake(0.8f, 1.0f, range: 2048f);
18+
ScreenShake = new ScreenShake(0.8f, 1.0f) {
19+
Range = 2048f,
20+
};
1921
}
2022
}
2123

2224
public override void Kill(Projectile projectile, int timeLeft)
2325
{
2426
if (ScreenShake is ScreenShake shake) {
25-
shake.Position = projectile.Center;
26-
27-
ScreenShakeSystem.New(shake);
27+
ScreenShakeSystem.New(shake, projectile.Center);
2828
}
2929
}
3030
}

0 commit comments

Comments
 (0)