XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

DeathMod

【Terraria】DeathMod (now aka Soul Harvest)

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/DeathMod

重制领域斩击的单向冲击动画

d9311b7
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

2 个文件 +86 -27
Modified Common/MyPlayer.cs +37 -0
@@ -40,6 +40,9 @@ public class MyPlayer : ModPlayer
40 40 private ulong deathWingTrailUpdateTick = ulong.MaxValue;
41 41 private int deathDomainTimer;
42 42 private int deathDomainVolleyCounter;
43 private int deathDomainScreenShakeFrames;
44 private float deathDomainScreenShakeStrength;
45 private Vector2 deathDomainScreenShakeDirection = Vector2.UnitY;
43 46 private readonly Dictionary<int, PendingDeathDomainCut> deathDomainPendingCuts = [];
44 47
45 48 private readonly record struct PendingDeathDomainCut(float Rotation, int ProjectileIndex);
@@ -59,6 +62,9 @@ public class MyPlayer : ModPlayer
59 62 ActiveDeathNecklace = null;
60 63 deathDomainTimer = 0;
61 64 deathDomainVolleyCounter = 0;
65 deathDomainScreenShakeFrames = 0;
66 deathDomainScreenShakeStrength = 0f;
67 deathDomainScreenShakeDirection = Vector2.UnitY;
62 68 deathDomainPendingCuts.Clear();
63 69 }
64 70
@@ -103,6 +109,37 @@ public class MyPlayer : ModPlayer
103 109 DeathWingsActiveLastTick = DeathWingsActiveThisTick;
104 110 }
105 111
112 public override void ModifyScreenPosition()
113 {
114 if (deathDomainScreenShakeFrames <= 0 || deathDomainScreenShakeStrength <= 0.01f)
115 return;
116
117 float remaining = deathDomainScreenShakeFrames / 6f;
118 float phase = (6 - deathDomainScreenShakeFrames) * 2.45f;
119 Vector2 tangent = deathDomainScreenShakeDirection.RotatedBy(MathHelper.PiOver2);
120 Main.screenPosition += deathDomainScreenShakeDirection * ((float)Math.Sin(phase) * deathDomainScreenShakeStrength * remaining)
121 + tangent * ((float)Math.Sin(phase * 0.63f + 1.1f) * deathDomainScreenShakeStrength * remaining * 0.32f);
122 deathDomainScreenShakeFrames--;
123 if (deathDomainScreenShakeFrames <= 0)
124 deathDomainScreenShakeStrength = 0f;
125 }
126
127 internal void TriggerDeathDomainImpact(Vector2 worldPosition, Vector2 direction, float strength)
128 {
129 if (Main.dedServ || Player.whoAmI != Main.myPlayer)
130 return;
131
132 float distance = Vector2.Distance(Player.Center, worldPosition);
133 float falloff = 1f - MathHelper.Clamp(distance / 1200f, 0f, 1f);
134 strength *= falloff * falloff;
135 if (strength <= deathDomainScreenShakeStrength)
136 return;
137
138 deathDomainScreenShakeStrength = Math.Min(5.2f, strength);
139 deathDomainScreenShakeDirection = direction.SafeNormalize(Vector2.UnitY);
140 deathDomainScreenShakeFrames = 6;
141 }
142
106 143 internal void RecordDeathWingTrail(Vector2 upperTip, Vector2 lowerTip, float mastery)
107 144 {
108 145 if (Main.dedServ || deathWingTrailUpdateTick == Main.GameUpdateCount)
Modified Projectiles/DeathDomainHarvestSlashProjectile.cs +49 -27
@@ -81,7 +81,9 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
81 81 {
82 82 int slashAge = age - slash * SlashDelayFrames;
83 83 int bit = 1 << slash;
84 if ((emittedMask & bit) == 0 && slashAge >= 0)
84 // The visual blade reaches the target centre after two ticks. Apply
85 // damage at that moment instead of before the slash has visibly landed.
86 if ((emittedMask & bit) == 0 && slashAge >= 2)
85 87 {
86 88 emittedMask |= bit;
87 89 ApplyHarvestDamage();
@@ -89,8 +91,8 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
89 91 SpawnExecutionBurst(slash);
90 92 }
91 93
92 if (createClientEffects && slashAge is >= 0 and < 9)
93 SpawnTravellingEdge(slash, slashAge / 8f);
94 if (createClientEffects && slashAge is >= 0 and < 6)
95 SpawnTravellingEdge(slash, slashAge / 5f);
94 96 }
95 97 Projectile.localAI[0] = emittedMask;
96 98 }
@@ -132,9 +134,14 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
132 134
133 135 private void DrawExecutionBlade(float progress, int slash)
134 136 {
135 float reveal = Smooth01(progress / 0.50f);
136 float disappear = 1f - Smooth01((progress - 0.58f) / 0.42f);
137 float strength = Smooth01(progress / 0.08f) * disappear;
137 // A short anticipation is followed by a very fast ease-out traversal. The
138 // blade covers most of its distance in only a few frames, then the wound
139 // hangs briefly and contracts, which reads as a forceful cut instead of a
140 // line being scaled into existence.
141 float reveal = EaseOutCubic((progress - 0.015f) / 0.31f);
142 float disappear = 1f - Smooth01((progress - 0.52f) / 0.42f);
143 float strength = Smooth01((progress - 0.008f) / 0.055f) * disappear;
144 float impactPulse = 1f + (float)Math.Exp(-Math.Pow((progress - 0.27f) / 0.105f, 2f)) * 0.24f;
138 145 float rotation = GetSlashRotation(Projectile.rotation, slash);
139 146 float length = GetSlashLength(Mastery, Projectile.scale, slash);
140 147 float width = (21f + Mastery * 13f + (IsRequiem ? 8f : 0f)) * Projectile.scale;
@@ -143,33 +150,34 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
143 150 // Draw the long blood-line first. The red-black execution blade is layered
144 151 // over it below, allowing the crimson line to extend beyond both tips while
145 152 // the pure-black core remains completely unbroken.
146 float bloodReveal = Smooth01((progress - 0.08f) / 0.34f);
153 Vector2 direction = rotation.ToRotationVector2();
154 float bloodReveal = EaseOutCubic((progress - 0.005f) / 0.27f);
147 155 float bloodFade = 1f - Smooth01((progress - 0.64f) / 0.28f);
148 156 float bloodStrength = bloodReveal * bloodFade;
149 157 float bloodLength = length * (3f + Mastery * 0.47f + (IsRequiem ? 0.3f : 0f));
150 DeathDomainPrimitiveTextureSystem.DrawBladeCentered(
151 center,
158 Vector2 bloodStart = center - direction * bloodLength * 0.5f;
159 DeathDomainPrimitiveTextureSystem.DrawBlade(
160 bloodStart,
152 161 rotation,
153 162 bloodLength,
154 163 (10f + Mastery * 3.5f) * Projectile.scale,
155 164 new Color(95, 0, 24, 0) * (bloodStrength * 0.72f),
156 165 bloodReveal);
157 DeathDomainPrimitiveTextureSystem.DrawBladeCentered(
158 center,
166 DeathDomainPrimitiveTextureSystem.DrawBlade(
167 bloodStart,
159 168 rotation,
160 169 bloodLength,
161 170 (2.4f + Mastery * 0.85f) * Projectile.scale,
162 171 new Color(255, 0, 38, 0) * bloodStrength,
163 172 bloodReveal);
164 173
165 // Three passes over one continuous high-resolution silhouette produce one
166 // integrated blade. The warning line splits at its centre and opens toward
167 // both tips. No perpendicular tip bars are drawn.
168 DrawTaperedBladeLayer(center, rotation, length, width * 1.52f, reveal,
174 // The red-black body follows the same start-to-end path and is drawn after
175 // the blood-line so its pure-black core always wins the overlap.
176 DrawTaperedBladeLayer(center, rotation, length, width * 1.52f * impactPulse, reveal,
169 177 new Color(92, 0, 22, 0) * (strength * 0.54f));
170 DrawTaperedBladeLayer(center, rotation, length, width, reveal,
178 DrawTaperedBladeLayer(center, rotation, length, width * impactPulse, reveal,
171 179 new Color(255, 8, 48, 255) * strength);
172 DrawTaperedBladeLayer(center, rotation, length * 0.985f, width * 0.62f, reveal,
180 DrawTaperedBladeLayer(center, rotation, length * 0.985f, width * 0.62f * impactPulse, reveal,
173 181 Color.Black * Math.Min(1f, strength * 1.32f));
174 182 }
175 183
@@ -178,7 +186,8 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
178 186 if (maximumWidth <= 0.05f || reveal <= 0f)
179 187 return;
180 188
181 DeathDomainPrimitiveTextureSystem.DrawBladeCentered(center, rotation, length, maximumWidth, color, reveal);
189 Vector2 start = center - rotation.ToRotationVector2() * length * 0.5f;
190 DeathDomainPrimitiveTextureSystem.DrawBlade(start, rotation, length, maximumWidth, color, reveal);
182 191 }
183 192
184 193 private void ApplyHarvestDamage()
@@ -227,13 +236,14 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
227 236 Vector2 direction = rotation.ToRotationVector2();
228 237 Vector2 normal = direction.RotatedBy(MathHelper.PiOver2);
229 238 float length = GetSlashLength(Mastery, Projectile.scale, slash);
230 int count = 10 + (int)(Mastery * 8f) + (IsRequiem ? 5 : 0);
239 int count = 16 + (int)(Mastery * 10f) + (IsRequiem ? 7 : 0);
231 240 for (int i = 0; i < count; i++)
232 241 {
233 float side = Main.rand.NextBool() ? -1f : 1f;
234 Vector2 position = Projectile.Center + direction * Main.rand.NextFloat(-length * 0.035f, length * 0.035f);
235 Vector2 velocity = normal * Main.rand.NextFloat(-4.8f, 4.8f)
236 + direction * side * Main.rand.NextFloat(1.2f, 3.6f);
242 Vector2 position = Projectile.Center
243 + direction * Main.rand.NextFloat(-length * 0.06f, length * 0.06f)
244 + normal * Main.rand.NextFloat(-5f, 5f) * Projectile.scale;
245 Vector2 velocity = normal * Main.rand.NextFloat(-3.8f, 3.8f)
246 + direction * Main.rand.NextFloat(3.8f, 9.2f);
237 247 int dustType = i % 3 == 0 ? DustID.Shadowflame : DustID.RedTorch;
238 248 Dust dust = Dust.NewDustPerfect(
239 249 position,
@@ -245,21 +255,26 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
245 255 dust.noGravity = true;
246 256 dust.fadeIn = 0.35f;
247 257 }
258
259 Main.LocalPlayer.GetModPlayer<MyPlayer>().TriggerDeathDomainImpact(
260 Projectile.Center,
261 normal,
262 2.2f + Mastery * 1.8f + (IsRequiem ? 1.2f : 0f));
248 263 }
249 264
250 265 private void SpawnTravellingEdge(int slash, float progress)
251 266 {
252 float reveal = Smooth01(progress);
267 float reveal = EaseOutCubic(progress);
253 268 float rotation = GetSlashRotation(Projectile.rotation, slash);
254 269 Vector2 direction = rotation.ToRotationVector2();
255 270 Vector2 normal = direction.RotatedBy(MathHelper.PiOver2);
256 271 float length = GetSlashLength(Mastery, Projectile.scale, slash);
257 float side = Main.rand.NextBool() ? -1f : 1f;
258 Vector2 position = Projectile.Center + direction * (length * reveal * 0.5f * side);
272 Vector2 start = Projectile.Center - direction * length * 0.5f;
273 Vector2 position = start + direction * (length * reveal);
259 274 Dust dust = Dust.NewDustPerfect(
260 275 position + normal * Main.rand.NextFloat(-4f, 4f) * Projectile.scale,
261 276 Main.rand.NextBool(3) ? DustID.Shadowflame : DustID.RedTorch,
262 normal * Main.rand.NextFloat(-2.4f, 2.4f),
277 direction * Main.rand.NextFloat(2.2f, 4.6f) + normal * Main.rand.NextFloat(-2.4f, 2.4f),
263 278 70,
264 279 new Color(255, 10, 50),
265 280 Main.rand.NextFloat(0.62f, 1.05f));
@@ -290,4 +305,11 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
290 305 value = MathHelper.Clamp(value, 0f, 1f);
291 306 return value * value * (3f - 2f * value);
292 307 }
308
309 private static float EaseOutCubic(float value)
310 {
311 value = MathHelper.Clamp(value, 0f, 1f);
312 float inverse = 1f - value;
313 return 1f - inverse * inverse * inverse;
314 }
293 315 }