返回提交历史
Modified
Common/MyPlayer.cs
+56
-31
Modified
DeathMod.cs
+204
-1
Modified
Projectiles/DeathDomainHarvestSlashProjectile.cs
+11
-5
Modified
Projectiles/DeathDomainHarvestTelegraphProjectile.cs
+1
-1
XFEstudio/DeathMod
改用专用网络包同步领域斩击特效
3efd867
代码差异
4 个文件
+272
-38
@@ -416,23 +416,38 @@ public class MyPlayer : ModPlayer
416
416
continue;
417
417
418
418
float rotation = Main.rand.NextFloat(MathHelper.TwoPi);
419
int projectileIndex = Projectile.NewProjectile(
420
Player.GetSource_Misc("DeathMod:DeathDomainTelegraph"),
421
target.Center,
422
Vector2.Zero,
423
ModContent.ProjectileType<DeathDomainHarvestTelegraphProjectile>(),
424
0,
425
0f,
426
Player.whoAmI,
427
target.whoAmI,
428
remainingFrames,
429
necklace.SlashCount + visualMastery * 0.1f);
430
if (projectileIndex >= 0 && projectileIndex < Main.maxProjectiles)
419
float scale = MathHelper.Clamp(Math.Max(target.width, target.height) / 52f, 0.85f, 2.4f);
420
int projectileIndex = -1;
421
if (Main.netMode == NetmodeID.Server)
422
{
423
DeathMod.BroadcastDeathDomainTelegraph(
424
Player,
425
target,
426
remainingFrames,
427
necklace.SlashCount,
428
visualMastery,
429
rotation,
430
scale);
431
}
432
else
431
433
{
432
Projectile telegraph = Main.projectile[projectileIndex];
433
telegraph.rotation = rotation;
434
telegraph.scale = MathHelper.Clamp(Math.Max(target.width, target.height) / 52f, 0.85f, 2.4f);
435
SynchronizeDeathDomainVisual(projectileIndex);
434
projectileIndex = Projectile.NewProjectile(
435
Player.GetSource_Misc("DeathMod:DeathDomainTelegraph"),
436
target.Center,
437
Vector2.Zero,
438
ModContent.ProjectileType<DeathDomainHarvestTelegraphProjectile>(),
439
0,
440
0f,
441
Player.whoAmI,
442
target.whoAmI,
443
remainingFrames,
444
necklace.SlashCount + visualMastery * 0.1f);
445
if (projectileIndex >= 0 && projectileIndex < Main.maxProjectiles)
446
{
447
Projectile telegraph = Main.projectile[projectileIndex];
448
telegraph.rotation = rotation;
449
telegraph.scale = scale;
450
}
436
451
}
437
452
deathDomainPendingCuts[target.whoAmI] = new PendingDeathDomainCut(rotation, projectileIndex);
438
453
}
@@ -441,6 +456,9 @@ public class MyPlayer : ModPlayer
441
456
private void SpawnDeathDomainHarvestSlash(NPC target, DeathNecklace necklace, float visualMastery, bool requiem, float rotation)
442
457
{
443
458
int slashDamage = CalculateDeathDomainSlashDamage(target, necklace);
459
float scale = MathHelper.Clamp(Math.Max(target.width, target.height) / 52f, 0.85f, 2.4f);
460
float visualState = visualMastery + (requiem ? 2f : 0f);
461
bool serverController = Main.netMode == NetmodeID.Server;
444
462
int projectileIndex = Projectile.NewProjectile(
445
463
Player.GetSource_Misc("DeathMod:DeathDomain"),
446
464
target.Center,
@@ -451,25 +469,28 @@ public class MyPlayer : ModPlayer
451
469
Player.whoAmI,
452
470
target.whoAmI,
453
471
necklace.SlashCount,
454
visualMastery + (requiem ? 2f : 0f));
472
visualState + (serverController ? 10f : 0f));
455
473
if (projectileIndex < 0 || projectileIndex >= Main.maxProjectiles)
456
474
return;
457
475
458
476
Projectile visual = Main.projectile[projectileIndex];
459
477
visual.rotation = rotation;
460
visual.scale = MathHelper.Clamp(Math.Max(target.width, target.height) / 52f, 0.85f, 2.4f);
461
SynchronizeDeathDomainVisual(projectileIndex);
462
}
463
464
private static void SynchronizeDeathDomainVisual(int projectileIndex)
465
{
466
if (Main.netMode != NetmodeID.Server)
467
return;
468
469
// Domain visuals are short lived, so send the complete state in their spawn
470
// tick rather than waiting for the periodic projectile synchronization pass.
471
NetMessage.SendData(MessageID.SyncProjectile, -1, -1, null, projectileIndex);
472
Main.projectile[projectileIndex].netUpdate = false;
478
visual.scale = scale;
479
if (serverController)
480
{
481
// The server projectile is only a staggered damage scheduler. Clients
482
// receive an explicit, local-only visual through the mod packet below.
483
visual.netUpdate = false;
484
visual.netImportant = false;
485
DeathMod.BroadcastDeathDomainHarvestSlash(
486
Player,
487
target,
488
necklace.SlashCount,
489
visualMastery,
490
requiem,
491
rotation,
492
scale);
493
}
473
494
}
474
495
475
496
private void ClearDeathDomainTelegraphs()
@@ -477,8 +498,11 @@ public class MyPlayer : ModPlayer
477
498
if (deathDomainPendingCuts.Count == 0)
478
499
return;
479
500
480
foreach (PendingDeathDomainCut pending in deathDomainPendingCuts.Values)
501
foreach ((int npcIndex, PendingDeathDomainCut pending) in deathDomainPendingCuts)
502
{
481
503
KillDeathDomainTelegraph(pending.ProjectileIndex);
504
DeathMod.BroadcastDeathDomainTelegraphClear(Player, npcIndex);
505
}
482
506
deathDomainPendingCuts.Clear();
483
507
}
484
508
@@ -487,6 +511,7 @@ public class MyPlayer : ModPlayer
487
511
if (!deathDomainPendingCuts.Remove(npcIndex, out PendingDeathDomainCut pending))
488
512
return;
489
513
KillDeathDomainTelegraph(pending.ProjectileIndex);
514
DeathMod.BroadcastDeathDomainTelegraphClear(Player, npcIndex);
490
515
}
491
516
492
517
private void KillDeathDomainTelegraph(int projectileIndex)
@@ -25,7 +25,15 @@ public class DeathMod : Mod
25
25
SyncInventorySlot,
26
26
SyncDeathMark,
27
27
SyncAltarItem,
28
SyncDeathDomainState
28
SyncDeathDomainState,
29
SyncDeathDomainVisual
30
}
31
32
internal enum DeathDomainVisualAction : byte
33
{
34
SpawnTelegraph,
35
SpawnHarvestSlash,
36
ClearTelegraph
29
37
}
30
38
31
39
internal enum OperationResult : byte
@@ -191,6 +199,41 @@ public class DeathMod : Mod
191
199
}
192
200
break;
193
201
}
202
case MessageType.SyncDeathDomainVisual:
203
{
204
DeathDomainVisualAction action = (DeathDomainVisualAction)reader.ReadByte();
205
byte playerIndex = reader.ReadByte();
206
short npcIndex = reader.ReadInt16();
207
Vector2 position = new(reader.ReadSingle(), reader.ReadSingle());
208
float rotation = reader.ReadSingle();
209
float scale = reader.ReadSingle();
210
byte slashCount = reader.ReadByte();
211
float mastery = reader.ReadSingle();
212
short duration = reader.ReadInt16();
213
bool requiem = reader.ReadBoolean();
214
if (Main.netMode == NetmodeID.MultiplayerClient)
215
{
216
if (action == DeathDomainVisualAction.ClearTelegraph)
217
{
218
ClearClientDeathDomainTelegraph(playerIndex, npcIndex);
219
}
220
else
221
{
222
SpawnClientDeathDomainVisual(
223
action,
224
playerIndex,
225
npcIndex,
226
position,
227
rotation,
228
scale,
229
slashCount,
230
mastery,
231
duration,
232
requiem);
233
}
234
}
235
break;
236
}
194
237
default:
195
238
Logger.Warn($"Unknown DeathMod packet: {messageType}");
196
239
break;
@@ -260,6 +303,166 @@ public class DeathMod : Mod
260
303
packet.Send(-1, playerIndex);
261
304
}
262
305
306
internal static void BroadcastDeathDomainTelegraph(
307
Player player,
308
NPC target,
309
int duration,
310
int slashCount,
311
float mastery,
312
float rotation,
313
float scale)
314
{
315
BroadcastDeathDomainVisual(
316
DeathDomainVisualAction.SpawnTelegraph,
317
player.whoAmI,
318
target.whoAmI,
319
target.Center,
320
rotation,
321
scale,
322
slashCount,
323
mastery,
324
duration,
325
requiem: false);
326
}
327
328
internal static void BroadcastDeathDomainHarvestSlash(
329
Player player,
330
NPC target,
331
int slashCount,
332
float mastery,
333
bool requiem,
334
float rotation,
335
float scale)
336
{
337
BroadcastDeathDomainVisual(
338
DeathDomainVisualAction.SpawnHarvestSlash,
339
player.whoAmI,
340
target.whoAmI,
341
target.Center,
342
rotation,
343
scale,
344
slashCount,
345
mastery,
346
duration: 0,
347
requiem);
348
}
349
350
internal static void BroadcastDeathDomainTelegraphClear(Player player, int npcIndex)
351
{
352
BroadcastDeathDomainVisual(
353
DeathDomainVisualAction.ClearTelegraph,
354
player.whoAmI,
355
npcIndex,
356
Vector2.Zero,
357
0f,
358
1f,
359
1,
360
0f,
361
0,
362
requiem: false);
363
}
364
365
private static void BroadcastDeathDomainVisual(
366
DeathDomainVisualAction action,
367
int playerIndex,
368
int npcIndex,
369
Vector2 position,
370
float rotation,
371
float scale,
372
int slashCount,
373
float mastery,
374
int duration,
375
bool requiem)
376
{
377
if (Main.netMode != NetmodeID.Server
378
|| playerIndex < 0
379
|| playerIndex >= Main.maxPlayers
380
|| npcIndex < 0
381
|| npcIndex >= Main.maxNPCs)
382
{
383
return;
384
}
385
386
ModPacket packet = ModContent.GetInstance<DeathMod>().GetPacket();
387
packet.Write((byte)MessageType.SyncDeathDomainVisual);
388
packet.Write((byte)action);
389
packet.Write((byte)playerIndex);
390
packet.Write((short)npcIndex);
391
packet.Write(position.X);
392
packet.Write(position.Y);
393
packet.Write(rotation);
394
packet.Write(scale);
395
packet.Write((byte)Math.Clamp(slashCount, 1, 5));
396
packet.Write(MathHelper.Clamp(mastery, 0f, 1f));
397
packet.Write((short)Math.Clamp(duration, 0, short.MaxValue));
398
packet.Write(requiem);
399
packet.Send();
400
}
401
402
private static void SpawnClientDeathDomainVisual(
403
DeathDomainVisualAction action,
404
int playerIndex,
405
int npcIndex,
406
Vector2 position,
407
float rotation,
408
float scale,
409
int slashCount,
410
float mastery,
411
int duration,
412
bool requiem)
413
{
414
if (playerIndex < 0 || playerIndex >= Main.maxPlayers
415
|| npcIndex < 0 || npcIndex >= Main.maxNPCs
416
|| action is not (DeathDomainVisualAction.SpawnTelegraph or DeathDomainVisualAction.SpawnHarvestSlash))
417
{
418
return;
419
}
420
421
int projectileType = action == DeathDomainVisualAction.SpawnTelegraph
422
? ModContent.ProjectileType<DeathDomainHarvestTelegraphProjectile>()
423
: ModContent.ProjectileType<DeathDomainHarvestSlashProjectile>();
424
float ai1 = action == DeathDomainVisualAction.SpawnTelegraph
425
? Math.Max(1, duration)
426
: Math.Clamp(slashCount, 1, 5);
427
float ai2 = action == DeathDomainVisualAction.SpawnTelegraph
428
? Math.Clamp(slashCount, 1, 5) + MathHelper.Clamp(mastery, 0f, 1f) * 0.1f
429
: MathHelper.Clamp(mastery, 0f, 1f) + (requiem ? 2f : 0f);
430
int projectileIndex = Projectile.NewProjectile(
431
Main.LocalPlayer.GetSource_Misc("DeathMod:NetworkDomainVisual"),
432
position,
433
Vector2.Zero,
434
projectileType,
435
0,
436
0f,
437
Main.myPlayer,
438
npcIndex,
439
ai1,
440
ai2);
441
if (projectileIndex < 0 || projectileIndex >= Main.maxProjectiles)
442
return;
443
444
Projectile visual = Main.projectile[projectileIndex];
445
visual.rotation = rotation;
446
visual.scale = MathHelper.Clamp(scale, 0.5f, 3f);
447
visual.localAI[1] = playerIndex + 1;
448
visual.netUpdate = false;
449
visual.netImportant = false;
450
}
451
452
private static void ClearClientDeathDomainTelegraph(int playerIndex, int npcIndex)
453
{
454
float visualOwnerTag = playerIndex + 1;
455
foreach (Projectile projectile in Main.ActiveProjectiles)
456
{
457
if (projectile.ModProjectile is DeathDomainHarvestTelegraphProjectile
458
&& (int)projectile.ai[0] == npcIndex
459
&& Math.Abs(projectile.localAI[1] - visualOwnerTag) < 0.1f)
460
{
461
projectile.active = false;
462
}
463
}
464
}
465
263
466
internal static void BroadcastDeathMark(NPC npc, bool marked)
264
467
{
265
468
if (Main.netMode != NetmodeID.Server || npc.whoAmI < 0 || npc.whoAmI >= Main.maxNPCs)
@@ -24,8 +24,10 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
24
24
25
25
private int TargetIndex => (int)Projectile.ai[0];
26
26
private int SlashCount => Math.Clamp((int)Projectile.ai[1], 1, MaximumSlashCount);
27
private bool IsRequiem => Projectile.ai[2] >= 2f;
28
private float Mastery => MathHelper.Clamp(IsRequiem ? Projectile.ai[2] - 2f : Projectile.ai[2], 0f, 1f);
27
private bool IsServerController => Projectile.ai[2] >= 10f;
28
private float VisualState => IsServerController ? Projectile.ai[2] - 10f : Projectile.ai[2];
29
private bool IsRequiem => VisualState >= 2f;
30
private float Mastery => MathHelper.Clamp(IsRequiem ? VisualState - 2f : VisualState, 0f, 1f);
29
31
private int TotalLifetime => SlashActiveFrames + (SlashCount - 1) * SlashDelayFrames + EndLingerFrames;
30
32
31
33
public override string Texture => "Terraria/Images/Projectile_0";
@@ -45,7 +47,7 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
45
47
Projectile.ignoreWater = true;
46
48
Projectile.penetrate = -1;
47
49
Projectile.timeLeft = 60;
48
Projectile.netImportant = true;
50
Projectile.netImportant = false;
49
51
}
50
52
51
53
public override void OnSpawn(IEntitySource source)
@@ -74,6 +76,7 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
74
76
75
77
int age = TotalLifetime - Projectile.timeLeft;
76
78
int emittedMask = (int)Projectile.localAI[0];
79
bool createClientEffects = !Main.dedServ && !IsServerController;
77
80
for (int slash = 0; slash < SlashCount; slash++)
78
81
{
79
82
int slashAge = age - slash * SlashDelayFrames;
@@ -82,11 +85,11 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
82
85
{
83
86
emittedMask |= bit;
84
87
ApplyHarvestDamage();
85
if (!Main.dedServ)
88
if (createClientEffects)
86
89
SpawnExecutionBurst(slash);
87
90
}
88
91
89
if (!Main.dedServ && slashAge is >= 0 and < 9)
92
if (createClientEffects && slashAge is >= 0 and < 9)
90
93
SpawnTravellingEdge(slash, slashAge / 8f);
91
94
}
92
95
Projectile.localAI[0] = emittedMask;
@@ -94,6 +97,9 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
94
97
95
98
public override bool PreDraw(ref Color lightColor)
96
99
{
100
if (IsServerController)
101
return false;
102
97
103
int age = TotalLifetime - Projectile.timeLeft;
98
104
for (int slash = 0; slash < SlashCount; slash++)
99
105
{
@@ -39,7 +39,7 @@ public class DeathDomainHarvestTelegraphProjectile : ModProjectile
39
39
Projectile.ignoreWater = true;
40
40
Projectile.penetrate = -1;
41
41
Projectile.timeLeft = 120;
42
Projectile.netImportant = true;
42
Projectile.netImportant = false;
43
43
}
44
44
45
45
public override void OnSpawn(IEntitySource source)