返回提交历史
Modified
Common/MyPlayer.cs
+82
-15
Modified
Projectiles/DeathDomainHarvestSlashProjectile.cs
+10
-44
XFEstudio/DeathMod
修复专服领域斩击伤害结算
0da39c4
代码差异
2 个文件
+92
-59
@@ -46,8 +46,10 @@ public class MyPlayer : ModPlayer
46
46
private float deathDomainScreenShakeStrength;
47
47
private Vector2 deathDomainScreenShakeDirection = Vector2.UnitY;
48
48
private readonly Dictionary<int, PendingDeathDomainCut> deathDomainPendingCuts = [];
49
private readonly List<PendingDeathDomainStrike> pendingDeathDomainStrikes = [];
49
50
50
51
private readonly record struct PendingDeathDomainCut(float Rotation, int ProjectileIndex);
52
private readonly record struct PendingDeathDomainStrike(int NpcIndex, int RemainingFrames, int Damage);
51
53
52
54
public override void Initialize()
53
55
{
@@ -69,6 +71,7 @@ public class MyPlayer : ModPlayer
69
71
deathDomainScreenShakeStrength = 0f;
70
72
deathDomainScreenShakeDirection = Vector2.UnitY;
71
73
deathDomainPendingCuts.Clear();
74
pendingDeathDomainStrikes.Clear();
72
75
}
73
76
74
77
public override void ResetEffects()
@@ -98,6 +101,7 @@ public class MyPlayer : ModPlayer
98
101
if (deathDomainSlashSoundCooldown > 0)
99
102
deathDomainSlashSoundCooldown--;
100
103
104
UpdatePendingDeathDomainStrikes();
101
105
UpdateDeathDomain();
102
106
103
107
if (Player.dead)
@@ -517,7 +521,29 @@ public class MyPlayer : ModPlayer
517
521
int slashDamage = CalculateDeathDomainSlashDamage(target, necklace);
518
522
float scale = MathHelper.Clamp(Math.Max(target.width, target.height) / 52f, 0.85f, 2.4f);
519
523
float visualState = visualMastery + (requiem ? 2f : 0f);
520
bool serverController = Main.netMode == NetmodeID.Server;
524
525
if (Main.netMode == NetmodeID.Server)
526
{
527
for (int slash = 0; slash < necklace.SlashCount; slash++)
528
{
529
pendingDeathDomainStrikes.Add(new PendingDeathDomainStrike(
530
target.whoAmI,
531
DeathDomainHarvestSlashProjectile.SlashImpactFrame
532
+ slash * DeathDomainHarvestSlashProjectile.SlashDelayFrames,
533
slashDamage));
534
}
535
536
DeathMod.BroadcastDeathDomainHarvestSlash(
537
Player,
538
target,
539
necklace.SlashCount,
540
visualMastery,
541
requiem,
542
rotation,
543
scale);
544
return;
545
}
546
521
547
int projectileIndex = Projectile.NewProjectile(
522
548
Player.GetSource_Misc("DeathMod:DeathDomain"),
523
549
target.Center,
@@ -528,27 +554,68 @@ public class MyPlayer : ModPlayer
528
554
Player.whoAmI,
529
555
target.whoAmI,
530
556
necklace.SlashCount,
531
visualState + (serverController ? 10f : 0f));
557
visualState);
532
558
if (projectileIndex < 0 || projectileIndex >= Main.maxProjectiles)
533
559
return;
534
560
535
561
Projectile visual = Main.projectile[projectileIndex];
536
562
visual.rotation = rotation;
537
563
visual.scale = scale;
538
if (serverController)
564
}
565
566
private void UpdatePendingDeathDomainStrikes()
567
{
568
if (Main.netMode == NetmodeID.MultiplayerClient || pendingDeathDomainStrikes.Count == 0)
569
return;
570
571
for (int index = pendingDeathDomainStrikes.Count - 1; index >= 0; index--)
539
572
{
540
// The server projectile is only a staggered damage scheduler. Clients
541
// receive an explicit, local-only visual through the mod packet below.
542
visual.netUpdate = false;
543
visual.netImportant = false;
544
DeathMod.BroadcastDeathDomainHarvestSlash(
545
Player,
546
target,
547
necklace.SlashCount,
548
visualMastery,
549
requiem,
550
rotation,
551
scale);
573
PendingDeathDomainStrike pending = pendingDeathDomainStrikes[index];
574
int remainingFrames = pending.RemainingFrames - 1;
575
if (remainingFrames > 0)
576
{
577
pendingDeathDomainStrikes[index] = pending with { RemainingFrames = remainingFrames };
578
continue;
579
}
580
581
pendingDeathDomainStrikes.RemoveAt(index);
582
ApplyDeathDomainStrike(pending.NpcIndex, pending.Damage);
583
}
584
}
585
586
internal void ApplyDeathDomainStrike(int npcIndex, int damage)
587
{
588
if (npcIndex < 0 || npcIndex >= Main.maxNPCs)
589
return;
590
591
NPC target = Main.npc[npcIndex];
592
if (!target.active || target.friendly || target.immortal || target.dontTakeDamage || target.life <= 0)
593
return;
594
595
bool bossOrBossPart = target.boss
596
|| NPCID.Sets.ShouldBeCountedAsBoss[target.type]
597
|| target.realLife >= 0 && target.realLife < Main.maxNPCs && Main.npc[target.realLife].boss;
598
target.GetGlobalNPC<MyGlobalNPC>().ApplyDeathDomainHitStop(target, bossOrBossPart ? 1 : 3);
599
600
if (Main.netMode == NetmodeID.MultiplayerClient || damage <= 0)
601
return;
602
603
target.GetGlobalNPC<MyGlobalNPC>().RegisterSickleHit(target, Player.whoAmI);
604
target.lastInteraction = Player.whoAmI;
605
NPC.HitInfo harvestHit = new()
606
{
607
Damage = damage,
608
SourceDamage = damage,
609
HitDirection = 0,
610
Knockback = 0f,
611
DamageType = DamageClass.Generic,
612
Crit = false
613
};
614
target.StrikeNPC(harvestHit, fromNet: false, noPlayerInteraction: false);
615
if (Main.netMode == NetmodeID.Server)
616
{
617
NetMessage.SendStrikeNPC(target, in harvestHit);
618
target.netUpdate = true;
552
619
}
553
620
}
554
621
@@ -18,7 +18,8 @@ namespace DeathMod.Projectiles;
18
18
public class DeathDomainHarvestSlashProjectile : ModProjectile
19
19
{
20
20
private const int SlashActiveFrames = 60;
21
private const int SlashDelayFrames = 5;
21
internal const int SlashDelayFrames = 5;
22
internal const int SlashImpactFrame = 5;
22
23
private const int EndLingerFrames = 7;
23
24
private const int MaximumSlashCount = 5;
24
25
@@ -83,10 +84,15 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
83
84
int bit = 1 << slash;
84
85
// The visible blade reaches the target centre after five ticks. Apply
85
86
// damage at that moment instead of before the slash has visibly landed.
86
if ((emittedMask & bit) == 0 && slashAge >= 5)
87
if ((emittedMask & bit) == 0 && slashAge >= SlashImpactFrame)
87
88
{
88
89
emittedMask |= bit;
89
ApplyHarvestDamage();
90
if (Projectile.owner >= 0 && Projectile.owner < Main.maxPlayers)
91
{
92
Main.player[Projectile.owner]
93
.GetModPlayer<MyPlayer>()
94
.ApplyDeathDomainStrike(TargetIndex, Projectile.damage);
95
}
90
96
if (createClientEffects)
91
97
SpawnExecutionBurst(slash);
92
98
}
@@ -126,7 +132,7 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
126
132
float impactPulse = 1f + (float)Math.Exp(-Math.Pow((progress - 0.083f) / 0.034f, 2f)) * 0.24f;
127
133
float rotation = GetSlashRotation(Projectile.rotation, slash);
128
134
float length = GetSlashLength(Mastery, Projectile.scale, slash);
129
float width = (21f + Mastery * 13f + (IsRequiem ? 8f : 0f)) * Projectile.scale;
135
float width = (21f + Mastery * 13f + (IsRequiem ? 8f : 0f)) * Projectile.scale * 0.78f;
130
136
Vector2 center = Projectile.Center - Main.screenPosition;
131
137
132
138
Vector2 direction = rotation.ToRotationVector2();
@@ -225,46 +231,6 @@ public class DeathDomainHarvestSlashProjectile : ModProjectile
225
231
}
226
232
}
227
233
228
private void ApplyHarvestDamage()
229
{
230
if (Projectile.owner < 0
231
|| Projectile.owner >= Main.maxPlayers
232
|| TargetIndex < 0
233
|| TargetIndex >= Main.maxNPCs)
234
{
235
return;
236
}
237
238
NPC target = Main.npc[TargetIndex];
239
if (!target.active || target.friendly || target.immortal || target.dontTakeDamage || target.life <= 0)
240
return;
241
242
bool bossOrBossPart = target.boss
243
|| NPCID.Sets.ShouldBeCountedAsBoss[target.type]
244
|| target.realLife >= 0 && target.realLife < Main.maxNPCs && Main.npc[target.realLife].boss;
245
target.GetGlobalNPC<MyGlobalNPC>().ApplyDeathDomainHitStop(target, bossOrBossPart ? 1 : 3);
246
247
// Explicit client visuals repeat the timing of the hidden server scheduler.
248
// They only apply the local hit-stop above; damage remains authoritative.
249
if (Main.netMode == NetmodeID.MultiplayerClient || Projectile.damage <= 0)
250
return;
251
252
target.GetGlobalNPC<MyGlobalNPC>().RegisterSickleHit(target, Projectile.owner);
253
target.lastInteraction = Projectile.owner;
254
NPC.HitInfo harvestHit = new()
255
{
256
Damage = Projectile.damage,
257
SourceDamage = Projectile.damage,
258
HitDirection = 0,
259
Knockback = 0f,
260
DamageType = DamageClass.Generic,
261
Crit = false
262
};
263
target.StrikeNPC(harvestHit, fromNet: false, noPlayerInteraction: false);
264
if (Main.netMode == NetmodeID.Server)
265
NetMessage.SendStrikeNPC(target, in harvestHit);
266
}
267
268
234
private void SpawnExecutionBurst(int slash)
269
235
{
270
236
float rotation = GetSlashRotation(Projectile.rotation, slash);