From d48a69d907b418f9aecb7efaefddecfdbf5e6c31 Mon Sep 17 00:00:00 2001 From: CloudeaSoft Date: Fri, 16 Oct 2026 20:35:47 +0800 Subject: [PATCH] fix: correct handheld projectile synchronization Rename the handheld projectile template, synchronize aiming and initialization, constrain projectile spawning to the owner, and handle inverted gravity. Preserve remote client sounds, clean up redundant overrides, and correct weapon rarity assignments. Add regression coverage for aiming and network initialization. Fixes https://github.com/CycloneClub/Everglow/issues/367 --- ...oldProjectile.cs => HandheldProjectile.cs} | 66 +++++-- .../Function/HandheldProjectileTest.cs | 172 ++++++++++++++++++ Sources/Modules/Example/Test/HandholdProj.cs | 2 +- Sources/Modules/Example/Test/HandholdProj2.cs | 3 +- .../Items/Weapons/GildingRevolver.cs | 5 + .../Weapons/KeroseneLanternFlameThrower.cs | 5 + .../Weapons/GildingRevolver_Hold.cs | 57 +++--- .../KeroseneLanternFlameThrower_Hold.cs | 78 ++++---- .../TheTusk/Projectiles/Weapon/ToothBow.cs | 36 ++-- .../Items/Weapons/Legacies/AncientSyringe.cs | 5 +- .../Legacies/AncientSyringe_proj.cs | 38 ++-- .../Items/Weapons/AmberMagicOrb.cs | 1 - .../Items/Weapons/Auburn/RodSpear.cs | 2 +- .../LightSeeker/HandgunOfEnlightment.cs | 2 +- .../Weapons/LightSeeker/LightBeamStaff.cs | 2 +- .../Items/Weapons/YggdrasilAmberLaser.cs | 6 - .../Projectiles/Magic/AmberMagicOrb.cs | 34 +--- .../Projectiles/Magic/LightBeamStaff_proj.cs | 41 ++--- .../Magic/YggdrasilAmberLaser_crystal.cs | 61 +++++-- .../Magic/YggdrasilAmberLaser_proj.cs | 63 ++++--- .../Ranged/PearShapedNeedle_HeldProj.cs | 14 +- 21 files changed, 465 insertions(+), 228 deletions(-) rename Sources/Everglow.Function/Templates/Weapons/{HandholdProjectile.cs => HandheldProjectile.cs} (64%) create mode 100644 Sources/Everglow.UnitTests/Function/HandheldProjectileTest.cs diff --git a/Sources/Everglow.Function/Templates/Weapons/HandholdProjectile.cs b/Sources/Everglow.Function/Templates/Weapons/HandheldProjectile.cs similarity index 64% rename from Sources/Everglow.Function/Templates/Weapons/HandholdProjectile.cs rename to Sources/Everglow.Function/Templates/Weapons/HandheldProjectile.cs index a969a25f91..4ce1f9f684 100644 --- a/Sources/Everglow.Function/Templates/Weapons/HandholdProjectile.cs +++ b/Sources/Everglow.Function/Templates/Weapons/HandheldProjectile.cs @@ -1,11 +1,12 @@ +using Everglow.Commons.Utilities; using Terraria.DataStructures; namespace Everglow.Commons.Templates.Weapons; /// -/// Handhold projectile. +/// Handheld projectile. /// -public abstract class HandholdProjectile : ModProjectile +public abstract class HandheldProjectile : ModProjectile { /// /// The rotation of texture. @@ -35,11 +36,54 @@ public abstract class HandholdProjectile : ModProjectile public float DepartLength = 50; public Vector2 ArmRootPos = Vector2.zeroVector; + /// + /// World-space cursor of the owner. Main.MouseWorld already accounts for local gravity. + /// + protected Vector2 AimPosition + { + get + { + Player player = Main.player[Projectile.owner]; + player.ListenMouseWorld(); + return Projectile.owner == Main.myPlayer ? Main.MouseWorld : player.MouseWorld(); + } + } + + protected Vector2 GravityDrawOffset => DrawOffset * new Vector2(1, Main.player[Projectile.owner].gravDir); + + private bool rotationInitialized; + public override void OnSpawn(IEntitySource source) { - base.OnSpawn(source); + InitializeRotation(); + } + + private void InitializeRotation() + { + rotationInitialized = true; + // Spawn velocity is synchronized by Terraria, unlike the observer's cursor. + Projectile.rotation = Projectile.velocity.SafeNormalize(Vector2.UnitX * Main.player[Projectile.owner].direction).ToRotation() + MathHelper.PiOver4; } + public override bool PreAI() + { + Player player = Main.player[Projectile.owner]; + if (!player.active || player.dead) + { + Projectile.Kill(); + return false; + } + // Received projectiles do not run OnSpawn. + if (!rotationInitialized) + { + InitializeRotation(); + } + player.ListenMouseWorld(); + return true; + } + + public override bool ShouldUpdatePosition() => false; + public override void SetDefaults() { Projectile.width = 32; @@ -69,13 +113,13 @@ public virtual void HeldProjectileAI() { Player player = Main.player[Projectile.owner]; player.heldProj = Projectile.whoAmI; - ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2); + ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2 * player.gravDir); player.SetCompositeArmFront(true, Player.CompositeArmStretchAmount.Full, (Projectile.rotation - MathF.PI * 0.25f) * player.gravDir - MathF.PI * 0.5f); - Vector2 mouseToPlayer = Main.MouseWorld - ArmRootPos; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); + Vector2 mouseToPlayer = AimPosition - ArmRootPos; + mouseToPlayer = mouseToPlayer.SafeNormalize(Vector2.UnitX * player.direction); if (player.controlUseItem) { - float addRot = -MathF.Asin(Vector3.Cross(new Vector3(mouseToPlayer, 0), new Vector3(new Vector2(0, 1).RotatedBy(Projectile.rotation - Math.PI * 0.75), 0)).Z); + float addRot = MathHelper.WrapAngle(mouseToPlayer.ToRotation() + MathHelper.PiOver4 - Projectile.rotation); addRot *= LerpFactorOfRotation; if (Math.Abs(addRot) > MaxRotationSpeed) { @@ -102,7 +146,7 @@ public virtual void HeldProjectileAI() public virtual void RemoveExtraSameProjectiles(Player owner) { - if (owner.ownedProjectileCounts[Projectile.type] > 1) + if (Projectile.owner == Main.myPlayer && owner.ownedProjectileCounts[Projectile.type] > 1) { int count = owner.ownedProjectileCounts[Projectile.type]; for (int a = Main.projectile.Length - 1; a >= 0; a--) @@ -137,12 +181,12 @@ public virtual void DrawBaseTexture(Color lightColor) Player player = Main.player[Projectile.owner]; var texMain = (Texture2D)ModContent.Request(Texture); SpriteEffects se = SpriteEffects.None; - if (player.direction == -1) + if (player.direction * player.gravDir == -1) { se = SpriteEffects.FlipVertically; } - float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction; - Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + DrawOffset, null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); + float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction * player.gravDir; + Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + GravityDrawOffset, null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); } } diff --git a/Sources/Everglow.UnitTests/Function/HandheldProjectileTest.cs b/Sources/Everglow.UnitTests/Function/HandheldProjectileTest.cs new file mode 100644 index 0000000000..9f599fed61 --- /dev/null +++ b/Sources/Everglow.UnitTests/Function/HandheldProjectileTest.cs @@ -0,0 +1,172 @@ +using System.Reflection; +using Everglow.Commons; +using Everglow.Commons.Templates.Weapons; +using Everglow.Yggdrasil.YggdrasilTown.Projectiles.Magic; +using Microsoft.Xna.Framework; +using Terraria; +using Terraria.ModLoader; + +namespace Everglow.UnitTests.Function; + +[TestClass] +[DoNotParallelize] +public class HandheldProjectileTest +{ + private Player[] originalPlayers = null!; + private int originalMyPlayer; + private Vector2 originalScreenPosition; + private int originalMouseX; + private int originalMouseY; + private EverglowPlayer? originalModPlayer; + private Player owner = null!; + private EverglowPlayer modPlayer = null!; + private TestProjectile held = null!; + + private static readonly PropertyInfo InstanceProperty = typeof(ContentInstance).GetProperty("Instance")!; + private static readonly FieldInfo MouseWorldField = typeof(EverglowPlayer).GetField("mouseWorld", BindingFlags.Instance | BindingFlags.NonPublic)!; + + [TestInitialize] + public void Initialize() + { + Program.SavePath = string.Empty; + originalPlayers = Main.player; + originalMyPlayer = Main.myPlayer; + originalScreenPosition = Main.screenPosition; + originalMouseX = Main.mouseX; + originalMouseY = Main.mouseY; + originalModPlayer = ContentInstance.Instance; + + owner = new Player { whoAmI = 1, active = true, controlUseItem = true, itemTimeMax = 30 }; + owner.Center = new Vector2(100, 100); + Main.player = new Player[Main.maxPlayers + 1]; + Main.player[0] = new Player { whoAmI = 0 }; + Main.player[1] = owner; + Main.myPlayer = 0; + Main.screenPosition = Vector2.Zero; + Main.mouseX = 300; + Main.mouseY = 100; + + modPlayer = (EverglowPlayer)new EverglowPlayer().NewInstance(owner); + InstanceProperty.SetValue(null, modPlayer); + typeof(Player).GetField("modPlayers", BindingFlags.Instance | BindingFlags.NonPublic)!.SetValue(owner, new ModPlayer[] { modPlayer }); + held = (TestProjectile)new TestProjectile().NewInstance(new Projectile { owner = 1, active = true }); + held.SetDefaults(); + held.Projectile.rotation = MathHelper.PiOver4; + } + + [TestCleanup] + public void Cleanup() + { + Main.player = originalPlayers; + Main.myPlayer = originalMyPlayer; + Main.screenPosition = originalScreenPosition; + Main.mouseX = originalMouseX; + Main.mouseY = originalMouseY; + InstanceProperty.SetValue(null, originalModPlayer); + } + + [TestMethod] + public void RemoteOwner_AimsAtSynchronizedMouseInsteadOfLocalMouse() + { + MouseWorldField.SetValue(modPlayer, new Vector2(96, 298)); + held.HeldProjectileAI(); + Assert.AreEqual(96f, held.Projectile.Center.X, 0.001f); + Assert.AreEqual(148f, held.Projectile.Center.Y, 0.001f); + } + + [TestMethod] + public void InvertedGravity_MirrorsArmRootOffset() + { + owner.gravDir = -1; + MouseWorldField.SetValue(modPlayer, new Vector2(296, 102)); + held.HeldProjectileAI(); + Assert.AreEqual(new Vector2(96, 102), held.ArmRootPos); + } + + [TestMethod] + public void AimAtArmRoot_DoesNotProduceNonFinitePosition() + { + Main.myPlayer = 1; + Main.mouseX = 96; + Main.mouseY = 98; + MouseWorldField.SetValue(modPlayer, new Vector2(96, 98)); + held.HeldProjectileAI(); + Assert.IsTrue(float.IsFinite(held.Projectile.rotation)); + Assert.IsTrue(float.IsFinite(held.Projectile.Center.X)); + Assert.IsTrue(float.IsFinite(held.Projectile.Center.Y)); + } + + [TestMethod] + public void SpawnDirection_UsesNetworkedVelocityInsteadOfObserverMouse() + { + held.Projectile.velocity = new Vector2(0, -12); + held.OnSpawn(new Terraria.DataStructures.EntitySource_Misc("Test")); + Assert.AreEqual(-MathHelper.PiOver4, held.Projectile.rotation, 0.001f); + } + + [TestMethod] + public void LocalOwner_RequestsMouseSynchronizationBeforeDerivedAI() + { + Main.myPlayer = 1; + Assert.IsTrue(held.PreAI()); + var listenField = typeof(EverglowPlayer).GetField("listenMouseWorld", BindingFlags.Instance | BindingFlags.NonPublic)!; + Assert.IsTrue((bool)listenField.GetValue(modPlayer)!); + } + + [TestMethod] + public void OppositeAim_TurnsToTheOtherSide() + { + MouseWorldField.SetValue(modPlayer, new Vector2(-104, 98)); + held.HeldProjectileAI(); + Assert.AreEqual(46f, held.Projectile.Center.X, 0.001f); + Assert.AreEqual(98f, held.Projectile.Center.Y, 0.001f); + Assert.AreEqual(-1, owner.direction); + } + + [TestMethod] + public void RemoteOwnerGravity_IsIndependentOfObserverGravity() + { + Main.player[0].gravDir = -1; + MouseWorldField.SetValue(modPlayer, new Vector2(96, 298)); + held.HeldProjectileAI(); + Assert.AreEqual(148f, held.Projectile.Center.Y, 0.001f); + } + + [TestMethod] + public void InvertedGravity_MirrorsDrawOffset() + { + owner.gravDir = -1; + held.DrawOffset = new Vector2(-6, -8); + Assert.AreEqual(new Vector2(-6, 8), held.DrawOffsetInWorld); + } + + [TestMethod] + public void CrystalBeforeParentSync_WaitsWithoutDereferencingMissingParent() + { + var crystal = (YggdrasilAmberLaser_crystal)new YggdrasilAmberLaser_crystal().NewInstance(new Projectile { owner = 1, timeLeft = 900 }); + crystal.AI(); + Assert.IsFalse(crystal.EndAI); + } + + [TestMethod] + public void ReceivedProjectile_InitializesDirectionWithoutOnSpawn() + { + held.Projectile.velocity = new Vector2(0, -12); + held.PreAI(); + Assert.AreEqual(-MathHelper.PiOver4, held.Projectile.rotation, 0.001f); + } + + [TestMethod] + public void ReceivedCrystal_InitializesTrackWithoutOnSpawn() + { + var projectile = new Projectile { owner = 1, timeLeft = 900, Center = new Vector2(120, 140) }; + var crystal = (YggdrasilAmberLaser_crystal)new YggdrasilAmberLaser_crystal().NewInstance(projectile); + crystal.AI(); + Assert.AreEqual(new Vector2(120, 140), crystal.CrystalTrack[0]); + } + + private sealed class TestProjectile : HandheldProjectile + { + public Vector2 DrawOffsetInWorld => GravityDrawOffset; + } +} diff --git a/Sources/Modules/Example/Test/HandholdProj.cs b/Sources/Modules/Example/Test/HandholdProj.cs index 48dc26e939..77f2c730c4 100644 --- a/Sources/Modules/Example/Test/HandholdProj.cs +++ b/Sources/Modules/Example/Test/HandholdProj.cs @@ -2,7 +2,7 @@ namespace Everglow.Example.Test; -public class HandholdProj : HandholdProjectile +public class HandholdProj : HandheldProjectile { public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.MiscsProjectiles; } diff --git a/Sources/Modules/Example/Test/HandholdProj2.cs b/Sources/Modules/Example/Test/HandholdProj2.cs index ac6085102f..0a9e09470a 100644 --- a/Sources/Modules/Example/Test/HandholdProj2.cs +++ b/Sources/Modules/Example/Test/HandholdProj2.cs @@ -2,13 +2,12 @@ namespace Everglow.Example.Test; -public class HandholdProj2 : HandholdProjectile +public class HandholdProj2 : HandheldProjectile { public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.MiscsProjectiles; public override void SetDef() { TextureRotation = 1.204f; - base.SetDef(); } } diff --git a/Sources/Modules/Myth/LanternMoon/Items/Weapons/GildingRevolver.cs b/Sources/Modules/Myth/LanternMoon/Items/Weapons/GildingRevolver.cs index aab54dea20..b83a95697c 100644 --- a/Sources/Modules/Myth/LanternMoon/Items/Weapons/GildingRevolver.cs +++ b/Sources/Modules/Myth/LanternMoon/Items/Weapons/GildingRevolver.cs @@ -35,6 +35,11 @@ public override void SetDefaults() public override void HoldItem(Player player) { + if (player.whoAmI != Main.myPlayer) + { + return; + } + player.ListenMouseWorld(); if (player.ownedProjectileCounts[ModContent.ProjectileType()] <= 0) { Projectile.NewProjectile(Item.GetSource_FromAI(), player.Center, Vector2.zeroVector, ModContent.ProjectileType(), 0, 0, player.whoAmI); diff --git a/Sources/Modules/Myth/LanternMoon/Items/Weapons/KeroseneLanternFlameThrower.cs b/Sources/Modules/Myth/LanternMoon/Items/Weapons/KeroseneLanternFlameThrower.cs index 92cb07a5af..2a621ebdb4 100644 --- a/Sources/Modules/Myth/LanternMoon/Items/Weapons/KeroseneLanternFlameThrower.cs +++ b/Sources/Modules/Myth/LanternMoon/Items/Weapons/KeroseneLanternFlameThrower.cs @@ -40,6 +40,11 @@ public override void SetDefaults() public override void HoldItem(Player player) { + if (player.whoAmI != Main.myPlayer) + { + return; + } + player.ListenMouseWorld(); if (UIBar is not null && UIBar.Active) { return; diff --git a/Sources/Modules/Myth/LanternMoon/Projectiles/Weapons/GildingRevolver_Hold.cs b/Sources/Modules/Myth/LanternMoon/Projectiles/Weapons/GildingRevolver_Hold.cs index 8c800b77d4..fac67ad62b 100644 --- a/Sources/Modules/Myth/LanternMoon/Projectiles/Weapons/GildingRevolver_Hold.cs +++ b/Sources/Modules/Myth/LanternMoon/Projectiles/Weapons/GildingRevolver_Hold.cs @@ -1,11 +1,10 @@ using Everglow.Commons.Templates.Weapons; using Everglow.Myth.LanternMoon.Items.Weapons; using Terraria.Audio; -using Terraria.DataStructures; namespace Everglow.Myth.LanternMoon.Projectiles.Weapons; -public class GildingRevolver_Hold : HandholdProjectile +public class GildingRevolver_Hold : HandheldProjectile { public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.RangedProjectiles; @@ -41,17 +40,13 @@ public override void SetDef() ProjectileID.Sets.HeldProjDoesNotUsePlayerGfxOffY[Type] = true; } - public override void OnSpawn(IEntitySource source) - { - } - public override void AI() { if (ReloadCooling <= 0) { if (NormalBulletTimer < 120) { - NormalBulletTimer += 6 * (5f / Main.LocalPlayer.itemTimeMax); + NormalBulletTimer += 6 * (5f / Math.Max(Main.player[Projectile.owner].itemTimeMax, 1)); } if (NormalBulletTimer > 120) @@ -87,7 +82,7 @@ public override void AI() { if (proj is not null && proj.active && proj.type == ModContent.ProjectileType() && proj.owner == Projectile.owner) { - if ((Main.MouseWorld - proj.Center).Length() < 70) + if ((AimPosition - proj.Center).Length() < 70) { MouseInLanternZone = true; break; @@ -102,14 +97,14 @@ public override void HeldProjectileAI() Player player = Main.player[Projectile.owner]; player.heldProj = Projectile.whoAmI; int dir = 1; - if (Main.MouseWorld.X < player.MountedCenter.X) + if (AimPosition.X < player.MountedCenter.X) { dir = -1; } - ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2); - Vector2 mouseToPlayer = Main.MouseWorld - ArmRootPos; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); + ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2 * player.gravDir); + Vector2 mouseToPlayer = AimPosition - ArmRootPos; + mouseToPlayer = mouseToPlayer.SafeNormalize(Vector2.UnitX * player.direction); Projectile.rotation = mouseToPlayer.ToRotation() + MathHelper.PiOver4; Projectile.Center = player.MountedCenter + mouseToPlayer * 12; Item item = player.HeldItem; @@ -158,6 +153,10 @@ public override void HeldProjectileAI() private void Shoot() { + if (Projectile.owner != Main.myPlayer) + { + return; + } Player player = Main.player[Projectile.owner]; var item = player.HeldItem; if (item is not null @@ -166,48 +165,50 @@ private void Shoot() && gildingRevolver.ShootType >= 0) { Vector2 vel = (Projectile.rotation - MathHelper.PiOver4).ToRotationVector2().RotatedByRandom(0.02f) * item.shootSpeed; - Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * -2 + DrawOffset, vel, gildingRevolver.ShootType, item.damage, item.knockBack, Projectile.owner); + Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * -2 + GravityDrawOffset, vel, gildingRevolver.ShootType, item.damage, item.knockBack, Projectile.owner); UsedBulletsCount++; if (NormalBulletsCount == 6 || NormalBulletsCount == 3) { vel = (Projectile.rotation - MathHelper.PiOver4).ToRotationVector2().RotatedByRandom(0.02f) * item.shootSpeed / 4f; - Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * -2 + DrawOffset, vel, ModContent.ProjectileType(), item.damage, item.knockBack, Projectile.owner); + Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * -2 + GravityDrawOffset, vel, ModContent.ProjectileType(), item.damage, item.knockBack, Projectile.owner); } } } private void ShootPhantom() { - SoundEngine.PlaySound(SoundID.Item101); + SoundEngine.PlaySound(SoundID.Item101, Projectile.Center); + if (Projectile.owner != Main.myPlayer) + { + return; + } Player player = Main.player[Projectile.owner]; Item item = player.HeldItem; if (item is null) { return; } - Vector2 vel = (Main.MouseWorld - Projectile.Center).NormalizeSafe().RotatedByRandom(0.03f) * item.shootSpeed * 1.5f; - Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * -2 + DrawOffset, vel, ModContent.ProjectileType(), (int)(item.damage * 0.7f), item.knockBack, Projectile.owner); + Vector2 vel = (AimPosition - Projectile.Center).NormalizeSafe().RotatedByRandom(0.03f) * item.shootSpeed * 1.5f; + Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * -2 + GravityDrawOffset, vel, ModContent.ProjectileType(), (int)(item.damage * 0.7f), item.knockBack, Projectile.owner); } private void Shoot_RightClick() { + if (Projectile.owner != Main.myPlayer) + { + return; + } Player player = Main.player[Projectile.owner]; Item item = player.HeldItem; if (item is null) { return; } - Vector2 vel = (Main.MouseWorld - Projectile.Center).NormalizeSafe() * item.shootSpeed * 1.5f; - Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * -2 + DrawOffset, vel, ModContent.ProjectileType(), item.damage, item.knockBack, Projectile.owner); + Vector2 vel = (AimPosition - Projectile.Center).NormalizeSafe() * item.shootSpeed * 1.5f; + Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * -2 + GravityDrawOffset, vel, ModContent.ProjectileType(), item.damage, item.knockBack, Projectile.owner); UsedBulletsCount++; } - public override bool PreDraw(ref Color lightColor) - { - DrawBaseTexture(lightColor); - return false; - } - public override void DrawBaseTexture(Color lightColor) { Player player = Main.player[Projectile.owner]; @@ -220,12 +221,12 @@ public override void DrawBaseTexture(Color lightColor) { var texMain = ModAsset.GildingRevolver_Hold.Value; SpriteEffects se = SpriteEffects.None; - if (player.direction == -1) + if (player.direction * player.gravDir == -1) { se = SpriteEffects.FlipVertically; } - float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction; - Vector2 drawCenter = Projectile.Center - Main.screenPosition + DrawOffset; + float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction * player.gravDir; + Vector2 drawCenter = Projectile.Center - Main.screenPosition + GravityDrawOffset; Main.spriteBatch.Draw(texMain, drawCenter, null, lightColor, rot, texMain.Size() * 0.5f, 1f, se, 0); } diff --git a/Sources/Modules/Myth/LanternMoon/Projectiles/Weapons/KeroseneLanternFlameThrower_Hold.cs b/Sources/Modules/Myth/LanternMoon/Projectiles/Weapons/KeroseneLanternFlameThrower_Hold.cs index 64aa7a5dfa..8fa0342400 100644 --- a/Sources/Modules/Myth/LanternMoon/Projectiles/Weapons/KeroseneLanternFlameThrower_Hold.cs +++ b/Sources/Modules/Myth/LanternMoon/Projectiles/Weapons/KeroseneLanternFlameThrower_Hold.cs @@ -2,17 +2,21 @@ using Everglow.Commons.Graphics; using Everglow.Commons.Templates.Weapons; using Everglow.Myth.LanternMoon.Items.Weapons; +using ReLogic.Utilities; using Terraria.Audio; -using Terraria.DataStructures; namespace Everglow.Myth.LanternMoon.Projectiles.Weapons; -public class KeroseneLanternFlameThrower_Hold : HandholdProjectile, IWarpProjectile_warpStyle2 +public class KeroseneLanternFlameThrower_Hold : HandheldProjectile, IWarpProjectile_warpStyle2 { public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.RangedProjectiles; public int Timer = 0; + private SlotId beginSoundSlot = SlotId.Invalid; + private SlotId cycleSoundSlot = SlotId.Invalid; + private bool playedEndSound; + public struct SubProj { public Vector2 Pos; @@ -33,17 +37,16 @@ public override void SetDef() DrawOffset = new Vector2(-6, -8); } - public override void OnSpawn(IEntitySource source) - { - SoundEngine.PlaySound(new SoundStyle(ModAsset.Flamethrower_begin_Mod), Projectile.Center); - } - public override void AI() { + if (Timer == 0) + { + beginSoundSlot = SoundEngine.PlaySound(new SoundStyle(ModAsset.Flamethrower_begin_Mod), Projectile.Center); + } Timer++; float shootSpeed = GetShootSpeed(); Vector2 vel = (Projectile.rotation - MathHelper.PiOver4).ToRotationVector2() * shootSpeed; - Vector2 pos = Projectile.Center + vel.NormalizeSafe() * (32 - shootSpeed) + DrawOffset; + Vector2 pos = Projectile.Center + vel.NormalizeSafe() * (32 - shootSpeed) + GravityDrawOffset; var sub = new SubProj { Pos = pos, @@ -77,17 +80,18 @@ public override void HeldProjectileAI() if (player.wet) { Projectile.Kill(); + return; } player.heldProj = Projectile.whoAmI; - ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2); + ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2 * player.gravDir); player.SetCompositeArmFront(true, Player.CompositeArmStretchAmount.Full, (Projectile.rotation - MathF.PI * 0.25f) * player.gravDir - MathF.PI * 0.5f); int dir = 1; - if (Main.MouseWorld.X < player.MountedCenter.X) + if (AimPosition.X < player.MountedCenter.X) { dir = -1; } - Vector2 mouseToPlayer = Main.MouseWorld - ArmRootPos; + Vector2 mouseToPlayer = AimPosition - ArmRootPos; mouseToPlayer = mouseToPlayer.NormalizeSafe(); float powerRate = 1; if (player.HeldItem is not null && player.HeldItem.type == ModContent.ItemType()) @@ -97,9 +101,10 @@ public override void HeldProjectileAI() } if (player.controlUseItem) { + playedEndSound = false; if (Timer % (int)(45 * 2.5f / (powerRate + 2)) == (int)(15 * 2.5f / (powerRate + 2))) { - SoundEngine.PlaySound(new SoundStyle(ModAsset.Flamethrower_cycle_Mod).WithPitchOffset(powerRate), Projectile.Center); + cycleSoundSlot = SoundEngine.PlaySound(new SoundStyle(ModAsset.Flamethrower_cycle_Mod).WithPitchOffset(powerRate), Projectile.Center); } float addRot = -MathF.Asin(Vector3.Cross(new Vector3(mouseToPlayer, 0), new Vector3(new Vector2(0, 1).RotatedBy(Projectile.rotation - Math.PI * 0.75), 0)).Z); addRot *= LerpFactorOfRotation; @@ -111,16 +116,24 @@ public override void HeldProjectileAI() Projectile.Center = ArmRootPos + new Vector2(0, 1).RotatedBy(Projectile.rotation - Math.PI * 0.75) * DepartLength; Projectile.timeLeft = player.itemTimeMax; float shootSpeed = GetShootSpeed(); - if (Math.Abs(addRot) > 0.02f - || Timer % 2 == 1) + if (Projectile.owner == Main.myPlayer && (Math.Abs(addRot) > 0.02f + || Timer % 2 == 1)) { Vector2 vel = (Projectile.rotation - MathHelper.PiOver4).ToRotationVector2() * shootSpeed; - Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * 60 + DrawOffset, vel, ModContent.ProjectileType(), Projectile.damage, Projectile.knockBack, Projectile.owner); + Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), Projectile.Center + vel.NormalizeSafe() * 60 + GravityDrawOffset, vel, ModContent.ProjectileType(), Projectile.damage, Projectile.knockBack, Projectile.owner); } } - else + else if (!playedEndSound) { - SoundEngine.StopTrackedSounds(); + playedEndSound = true; + if (SoundEngine.TryGetActiveSound(beginSoundSlot, out var beginSound)) + { + beginSound.Stop(); + } + if (SoundEngine.TryGetActiveSound(cycleSoundSlot, out var cycleSound)) + { + cycleSound.Stop(); + } SoundEngine.PlaySound(new SoundStyle(ModAsset.Flamethrower_end_Mod).WithPitchOffset(Math.Clamp(powerRate, -1, 0)), Projectile.Center); } player.direction = dir; @@ -138,25 +151,18 @@ public float GetShootSpeed() return 12f; } - public override bool PreDraw(ref Color lightColor) - { - DrawBaseTexture(lightColor); - - return false; - } - public override void DrawBaseTexture(Color lightColor) { Player player = Main.player[Projectile.owner]; var texMain = ModAsset.KeroseneLanternFlameThrower_Hold.Value; SpriteEffects se = SpriteEffects.None; - if (player.direction == -1) + if (player.direction * player.gravDir == -1) { se = SpriteEffects.FlipVertically; } - float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction; - Vector2 drawCenter = Projectile.Center - Main.screenPosition + DrawOffset; + float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction * player.gravDir; + Vector2 drawCenter = Projectile.Center - Main.screenPosition + GravityDrawOffset; var bars0 = new List(); var bars1 = new List(); @@ -235,24 +241,16 @@ public void CreateTrailVertex(List bars0, List bars1, List= 0) + float width = 1f; + if (i >= ShootProjPos.Count - 5) { - width = 1f; - if (i >= ShootProjPos.Count - 5) - { - width = 1 - MathF.Cos((ShootProjPos.Count - i) / 5f * MathHelper.Pi); - width *= 0.5f; - } + width = 1 - MathF.Cos((ShootProjPos.Count - i) / 5f * MathHelper.Pi); + width *= 0.5f; } // timeValue, animate the trail. float timeValue = Timer * 0.05f; - Vector2 drawPos = Projectile.Center; - if (i >= 0) - { - drawPos = ShootProjPos[i].Pos; - } + Vector2 drawPos = ShootProjPos[i].Pos; Color drawColor = GetTrailColor(i, style); drawPos += offset; bars0.Add(drawPos + new Vector2(0, 1).RotatedBy(MathHelper.TwoPi * 2f / 3f) * trailWidth, drawColor, ModifyWarpTexCoordinate(factor, timeValue, 0, width)); diff --git a/Sources/Modules/Myth/TheTusk/Projectiles/Weapon/ToothBow.cs b/Sources/Modules/Myth/TheTusk/Projectiles/Weapon/ToothBow.cs index b47ce3936c..83b29cc9c5 100644 --- a/Sources/Modules/Myth/TheTusk/Projectiles/Weapon/ToothBow.cs +++ b/Sources/Modules/Myth/TheTusk/Projectiles/Weapon/ToothBow.cs @@ -3,7 +3,7 @@ namespace Everglow.Myth.TheTusk.Projectiles.Weapon; -public class ToothBow : HandholdProjectile +public class ToothBow : HandheldProjectile { public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.RangedProjectiles; @@ -16,22 +16,17 @@ public override void SetDef() DepartLength = 20; } - public override void AI() - { - base.AI(); - } - public override void HeldProjectileAI() { Player player = Main.player[Projectile.owner]; player.heldProj = Projectile.whoAmI; int dir = 1; - if (Main.MouseWorld.X < player.MountedCenter.X) + if (AimPosition.X < player.MountedCenter.X) { dir = -1; } - ArmRootPos = player.MountedCenter + new Vector2(-4 * dir, -2); + ArmRootPos = player.MountedCenter + new Vector2(-4 * dir, -2 * player.gravDir); float backValue = (player.itemTimeMax - player.itemTime) / (float)player.itemTimeMax; Player.CompositeArmStretchAmount compositeArmStretchAmount = Player.CompositeArmStretchAmount.Full; if (backValue < 0.5f) @@ -68,8 +63,8 @@ public override void HeldProjectileAI() player.SetCompositeArmFront(true, compositeArmStretchAmount, (Projectile.rotation - MathF.PI * 0.25f) * player.gravDir + MathF.PI * 0.5f); } player.SetCompositeArmBack(true, Player.CompositeArmStretchAmount.Full, (Projectile.rotation - MathF.PI * 0.25f) * player.gravDir - MathF.PI * 0.5f); - Vector2 mouseToPlayer = Main.MouseWorld - ArmRootPos; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); + Vector2 mouseToPlayer = AimPosition - ArmRootPos; + mouseToPlayer = mouseToPlayer.SafeNormalize(Vector2.UnitX * player.direction); if (player.controlUseItem) { float addRot = -MathF.Asin(Vector3.Cross(new Vector3(mouseToPlayer, 0), new Vector3(new Vector2(0, 1).RotatedBy(Projectile.rotation - Math.PI * 0.75), 0)).Z); @@ -86,37 +81,34 @@ public override void HeldProjectileAI() else { SoundEngine.PlaySound(SoundID.Item5, Projectile.Center); - Projectile.NewProjectileDirect(Terraria.Entity.InheritSource(Projectile), Projectile.Center, new Vector2(0, 1).RotatedBy(Projectile.rotation - Math.PI * 0.75) * 30f, ModContent.ProjectileType(), Projectile.damage, Projectile.knockBack, player.whoAmI); + if (Projectile.owner == Main.myPlayer) + { + Projectile.NewProjectileDirect(Terraria.Entity.InheritSource(Projectile), Projectile.Center, new Vector2(0, 1).RotatedBy(Projectile.rotation - Math.PI * 0.75) * 30f, ModContent.ProjectileType(), Projectile.damage, Projectile.knockBack, player.whoAmI); + } Projectile.Kill(); + return; } player.direction = dir; } - public override bool PreDraw(ref Color lightColor) - { - DrawBaseTexture(lightColor); - - return false; - } - public override void DrawBaseTexture(Color lightColor) { Player player = Main.player[Projectile.owner]; var texMain = ModAsset.ToothBow_bow.Value; var texArrow = ModAsset.ToothBow_BloodArrow.Value; SpriteEffects se = SpriteEffects.None; - if (player.direction == -1) + if (player.direction * player.gravDir == -1) { se = SpriteEffects.FlipVertically; } - float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction; + float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction * player.gravDir; float backValue = (player.itemTimeMax - player.itemTime) / (float)player.itemTimeMax * 20; - Vector2 drawCenter = Projectile.Center - Main.screenPosition + DrawOffset; + Vector2 drawCenter = Projectile.Center - Main.screenPosition + GravityDrawOffset; Main.spriteBatch.Draw(texArrow, drawCenter + new Vector2(5 - backValue, 0).RotatedBy(rot), null, lightColor, rot, texArrow.Size() / 2f, 0.75f, se, 0); Main.spriteBatch.Draw(texMain, drawCenter, null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); - if (Main.MouseWorld.X < player.MountedCenter.X) + if (AimPosition.X < player.MountedCenter.X) { player.direction = -1; } diff --git a/Sources/Modules/Yggdrasil/KelpCurtain/Items/Weapons/Legacies/AncientSyringe.cs b/Sources/Modules/Yggdrasil/KelpCurtain/Items/Weapons/Legacies/AncientSyringe.cs index 878ab16538..90e9b0588d 100644 --- a/Sources/Modules/Yggdrasil/KelpCurtain/Items/Weapons/Legacies/AncientSyringe.cs +++ b/Sources/Modules/Yggdrasil/KelpCurtain/Items/Weapons/Legacies/AncientSyringe.cs @@ -32,10 +32,7 @@ public override bool Shoot(Player player, EntitySource_ItemUse_WithAmmo source, { if (Main.myPlayer == player.whoAmI) { - var p0 = Projectile.NewProjectileDirect(player.GetSource_ItemUse(Item), player.Center, Vector2.Zero, type, player.GetWeaponDamage(Item), Item.knockBack, player.whoAmI); - Vector2 mouseToPlayer = Main.MouseWorld - player.MountedCenter; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); - p0.rotation = mouseToPlayer.ToRotation() + MathHelper.PiOver4; + Projectile.NewProjectileDirect(source, player.Center, velocity, type, damage, knockback, player.whoAmI); } } return false; diff --git a/Sources/Modules/Yggdrasil/KelpCurtain/Projectiles/Legacies/AncientSyringe_proj.cs b/Sources/Modules/Yggdrasil/KelpCurtain/Projectiles/Legacies/AncientSyringe_proj.cs index adc32994ce..48879fd369 100644 --- a/Sources/Modules/Yggdrasil/KelpCurtain/Projectiles/Legacies/AncientSyringe_proj.cs +++ b/Sources/Modules/Yggdrasil/KelpCurtain/Projectiles/Legacies/AncientSyringe_proj.cs @@ -6,7 +6,7 @@ namespace Everglow.Yggdrasil.KelpCurtain.Projectiles.Legacies; -public class AncientSyringe_proj : HandholdProjectile +public class AncientSyringe_proj : HandheldProjectile { public override string LocalizationCategory => LocalizationUtils.Categories.MagicProjectiles; @@ -15,11 +15,11 @@ public override void SetDef() DepartLength = 110; Projectile.usesLocalNPCImmunity = true; Projectile.localNPCHitCooldown = 20; - base.SetDef(); } public override void OnSpawn(IEntitySource source) { + base.OnSpawn(source); Player player = Main.player[Projectile.owner]; int timeMax = (int)(player.itemTimeMax / player.meleeSpeed); player.itemTime = timeMax; @@ -27,6 +27,11 @@ public override void OnSpawn(IEntitySource source) public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone) { + target.AddBuff(ModContent.BuffType(), 480); + if (Main.dedServ) + { + return; + } int times = 10; for (int x = 0; x < times; x++) { @@ -60,13 +65,6 @@ public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone) }; Ins.VFXManager.Add(blood); } - target.AddBuff(ModContent.BuffType(), 480); - base.OnHitNPC(target, hit, damageDone); - } - - public override void AI() - { - base.AI(); } public override void HeldProjectileAI() @@ -75,12 +73,13 @@ public override void HeldProjectileAI() if (player.HeldItem.type != ModContent.ItemType()) { Projectile.Kill(); + return; } player.heldProj = Projectile.whoAmI; - ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2); + ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2 * player.gravDir); - Vector2 mouseToPlayer = Main.MouseWorld - ArmRootPos; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); + Vector2 mouseToPlayer = AimPosition - ArmRootPos; + mouseToPlayer = mouseToPlayer.SafeNormalize(Vector2.UnitX * player.direction); int timeMax = (int)(player.itemTimeMax / player.meleeSpeed); if (Projectile.localNPCHitCooldown > timeMax - 1) { @@ -120,6 +119,7 @@ public override void HeldProjectileAI() if (!player.controlUseItem) { Projectile.Kill(); + return; } if (Projectile.Center.X < ArmRootPos.X) { @@ -136,13 +136,13 @@ public override bool PreDraw(ref Color lightColor) Player player = Main.player[Projectile.owner]; var texMain = (Texture2D)ModContent.Request(Texture); SpriteEffects se = SpriteEffects.None; - if (player.direction == -1) + if (player.direction * player.gravDir == -1) { se = SpriteEffects.FlipVertically; } - float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction; - Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + DrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); + float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction * player.gravDir; + Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + GravityDrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); int timeMax = (int)(player.itemTimeMax / player.meleeSpeed); float duration = player.itemTime / (float)timeMax; duration *= 1.5f; @@ -154,11 +154,11 @@ public override bool PreDraw(ref Color lightColor) duration = MathF.Sin(duration * MathHelper.Pi); Texture2D star = Commons.ModAsset.StarSlash_black.Value; Color drawC = new Color(0.7f * lightColor.R / 255f, 2f * lightColor.G / 255f, 0.2f * lightColor.B / 255f, 0); - Main.spriteBatch.Draw(star, Projectile.Center - Main.screenPosition + DrawOffset + new Vector2(24, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, Color.White, MathHelper.PiOver2, star.Size() / 2f, 0.5f * duration, se, 0); - Main.spriteBatch.Draw(star, Projectile.Center - Main.screenPosition + DrawOffset + new Vector2(24, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, Color.White, 0, star.Size() / 2f, 0.5f * duration, se, 0); + Main.spriteBatch.Draw(star, Projectile.Center - Main.screenPosition + GravityDrawOffset + new Vector2(24, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, Color.White, MathHelper.PiOver2, star.Size() / 2f, 0.5f * duration, se, 0); + Main.spriteBatch.Draw(star, Projectile.Center - Main.screenPosition + GravityDrawOffset + new Vector2(24, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, Color.White, 0, star.Size() / 2f, 0.5f * duration, se, 0); star = Commons.ModAsset.StarSlash.Value; - Main.spriteBatch.Draw(star, Projectile.Center - Main.screenPosition + DrawOffset + new Vector2(24, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, drawC, MathHelper.PiOver2, star.Size() / 2f, 0.5f * duration, se, 0); - Main.spriteBatch.Draw(star, Projectile.Center - Main.screenPosition + DrawOffset + new Vector2(24, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, drawC, 0, star.Size() / 2f, 0.5f * duration, se, 0); + Main.spriteBatch.Draw(star, Projectile.Center - Main.screenPosition + GravityDrawOffset + new Vector2(24, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, drawC, MathHelper.PiOver2, star.Size() / 2f, 0.5f * duration, se, 0); + Main.spriteBatch.Draw(star, Projectile.Center - Main.screenPosition + GravityDrawOffset + new Vector2(24, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, drawC, 0, star.Size() / 2f, 0.5f * duration, se, 0); return false; } } diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/AmberMagicOrb.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/AmberMagicOrb.cs index 271831e46c..fde1819caa 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/AmberMagicOrb.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/AmberMagicOrb.cs @@ -18,7 +18,6 @@ public override void SetDefaults() Item.rare = ItemRarityID.Blue; Item.UseSound = SoundID.Item1; Item.value = 4514; - Item.autoReuse = false; Item.DamageType = DamageClass.Magic; Item.mana = 18; Item.noUseGraphic = true; diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/Auburn/RodSpear.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/Auburn/RodSpear.cs index 28e48412f6..1cb9bdef73 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/Auburn/RodSpear.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/Auburn/RodSpear.cs @@ -22,7 +22,7 @@ public override void SetDefaults() Item.crit = 4; Item.knockBack = 4f; - Item.value = ItemRarityID.Green; + Item.rare = ItemRarityID.Green; Item.value = Item.buyPrice(silver: 20); Item.shoot = ModContent.ProjectileType(); diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/LightSeeker/HandgunOfEnlightment.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/LightSeeker/HandgunOfEnlightment.cs index 27db31c6a1..f9bfe3e400 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/LightSeeker/HandgunOfEnlightment.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/LightSeeker/HandgunOfEnlightment.cs @@ -27,7 +27,7 @@ public override void SetDefaults() Item.shootSpeed = 16f; Item.useAmmo = AmmoID.Bullet; - Item.value = ItemRarityID.Green; + Item.rare = ItemRarityID.Green; Item.value = Item.buyPrice(silver: 3); } diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/LightSeeker/LightBeamStaff.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/LightSeeker/LightBeamStaff.cs index 983c639af1..6f405789a4 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/LightSeeker/LightBeamStaff.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/LightSeeker/LightBeamStaff.cs @@ -26,7 +26,7 @@ public override void SetDefaults() Item.noMelee = true; Item.mana = 5; - Item.value = ItemRarityID.Green; + Item.rare = ItemRarityID.Green; Item.value = Item.buyPrice(silver: 8); Item.shoot = ModContent.ProjectileType(); diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/YggdrasilAmberLaser.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/YggdrasilAmberLaser.cs index 11d90c0fb2..7f1f856a25 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/YggdrasilAmberLaser.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Items/Weapons/YggdrasilAmberLaser.cs @@ -1,5 +1,4 @@ using Everglow.Yggdrasil.YggdrasilTown.Projectiles.Magic; -using Terraria.DataStructures; namespace Everglow.Yggdrasil.YggdrasilTown.Items.Weapons; @@ -32,9 +31,4 @@ public override void SetDefaults() Item.shoot = ModContent.ProjectileType(); Item.shootSpeed = 12; } - - public override bool Shoot(Player player, EntitySource_ItemUse_WithAmmo source, Vector2 position, Vector2 velocity, int type, int damage, float knockback) - { - return base.Shoot(player, source, position, velocity, type, damage, knockback); - } } diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/AmberMagicOrb.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/AmberMagicOrb.cs index 14e8ddf1b7..356e03c8c1 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/AmberMagicOrb.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/AmberMagicOrb.cs @@ -1,35 +1,18 @@ using Everglow.Commons.Templates.Weapons; -using Terraria.DataStructures; namespace Everglow.Yggdrasil.YggdrasilTown.Projectiles.Magic; -public class AmberMagicOrb : HandholdProjectile +public class AmberMagicOrb : HandheldProjectile { public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.MagicProjectiles; public override void SetDef() { DepartLength = 60; - Projectile.usesLocalNPCImmunity = true; - Projectile.localNPCHitCooldown = 20; TextureRotation = 5 / 18f * MathHelper.Pi; Projectile.usesLocalNPCImmunity = true; Projectile.localNPCHitCooldown = 5; Projectile.ArmorPenetration = 45; - base.SetDef(); - } - - public override void OnSpawn(IEntitySource source) - { - Player player = Main.player[Projectile.owner]; - Vector2 mouseToPlayer = Main.MouseWorld - player.Center; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); - Projectile.rotation = mouseToPlayer.ToRotation() + MathHelper.PiOver4; - } - - public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone) - { - base.OnHitNPC(target, hit, damageDone); } public override void AI() @@ -45,12 +28,13 @@ public override void HeldProjectileAI() if (player.HeldItem.type != ModContent.ItemType()) { Projectile.Kill(); + return; } player.heldProj = Projectile.whoAmI; - ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2); + ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2 * player.gravDir); - Vector2 mouseToPlayer = Main.MouseWorld - ArmRootPos; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); + Vector2 mouseToPlayer = AimPosition - ArmRootPos; + mouseToPlayer = mouseToPlayer.SafeNormalize(Vector2.UnitX * player.direction); Projectile.rotation = mouseToPlayer.ToRotation() + MathHelper.PiOver4; player.SetCompositeArmFront(true, Player.CompositeArmStretchAmount.Full, (Projectile.rotation - MathF.PI * 0.25f) * player.gravDir - MathF.PI * 0.5f); @@ -91,14 +75,14 @@ public override bool PreDraw(ref Color lightColor) var texMain = (Texture2D)ModContent.Request(Texture); var texGlow = ModAsset.AmberMagicOrb_glow.Value; SpriteEffects se = SpriteEffects.None; - if (player.direction == -1) + if (player.direction * player.gravDir == -1) { se = SpriteEffects.FlipVertically; } - float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction; - Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + DrawOffset, null, lightColor, rot + (float)Main.time * 0.25f, texMain.Size() / 2f, 1f, se, 0); - Main.spriteBatch.Draw(texGlow, Projectile.Center - Main.screenPosition + DrawOffset, null, new Color(1f, 1f, 1f, 0), rot + (float)Main.time * 0.25f, texGlow.Size() / 2f, 1f, se, 0); + float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction * player.gravDir; + Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + GravityDrawOffset, null, lightColor, rot + (float)Main.time * 0.25f, texMain.Size() / 2f, 1f, se, 0); + Main.spriteBatch.Draw(texGlow, Projectile.Center - Main.screenPosition + GravityDrawOffset, null, new Color(1f, 1f, 1f, 0), rot + (float)Main.time * 0.25f, texGlow.Size() / 2f, 1f, se, 0); var bars = new List(); for (int t = 0; t < 3; t++) diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/LightBeamStaff_proj.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/LightBeamStaff_proj.cs index 09455522da..4d8b116fc9 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/LightBeamStaff_proj.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/LightBeamStaff_proj.cs @@ -1,16 +1,16 @@ -using Everglow.Commons.DataStructures; using Everglow.Commons.Templates.Weapons; -using Everglow.Yggdrasil.YggdrasilTown.Items.Weapons; using Everglow.Yggdrasil.YggdrasilTown.Items.Weapons.LightSeeker; using Terraria.Audio; using Terraria.DataStructures; namespace Everglow.Yggdrasil.YggdrasilTown.Projectiles.Magic; -public class LightBeamStaff_proj : HandholdProjectile +public class LightBeamStaff_proj : HandheldProjectile { public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.MagicProjectiles; + private bool playedSpawnSound; + public override void SetDef() { DepartLength = 60; @@ -19,28 +19,25 @@ public override void SetDef() Projectile.localNPCHitCooldown = 5; Projectile.ArmorPenetration = 45; Projectile.friendly = false; - base.SetDef(); } public override void OnSpawn(IEntitySource source) { - SoundEngine.PlaySound(SoundID.Shimmer1.WithPitchOffset(1), Projectile.Center); - Player player = Main.player[Projectile.owner]; - Vector2 mouseToPlayer = Main.MouseWorld - player.Center; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); - Projectile.rotation = mouseToPlayer.ToRotation() + MathHelper.PiOver4; - Projectile.NewProjectile(Projectile.GetSource_FromAI(), Projectile.Center + Projectile.velocity * 2, Projectile.velocity, ModContent.ProjectileType(), Projectile.damage, Projectile.knockBack, Projectile.owner); - } - - public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone) - { - base.OnHitNPC(target, hit, damageDone); + base.OnSpawn(source); + if (Projectile.owner == Main.myPlayer) + { + Projectile.NewProjectile(Projectile.GetSource_FromAI(), Projectile.Center + Projectile.velocity * 2, Projectile.velocity, ModContent.ProjectileType(), Projectile.damage, Projectile.knockBack, Projectile.owner); + } } public override void AI() { + if (!playedSpawnSound) + { + playedSpawnSound = true; + SoundEngine.PlaySound(SoundID.Shimmer1.WithPitchOffset(1), Projectile.Center); + } HeldProjectileAI(); - Player player = Main.player[Projectile.owner]; } public override void HeldProjectileAI() @@ -49,9 +46,10 @@ public override void HeldProjectileAI() if (player.HeldItem.type != ModContent.ItemType()) { Projectile.Kill(); + return; } player.heldProj = Projectile.whoAmI; - ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2); + ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2 * player.gravDir); int timeMax = (int)(player.itemTimeMax / player.meleeSpeed); if (Projectile.localNPCHitCooldown > timeMax - 1) @@ -61,6 +59,7 @@ public override void HeldProjectileAI() if (player.itemTime == 1) { Projectile.Kill(); + return; } player.SetCompositeArmFront(true, Player.CompositeArmStretchAmount.Full, (Projectile.rotation - MathF.PI * 0.25f) * player.gravDir - MathF.PI * 0.5f); DepartLength = 60; @@ -82,12 +81,12 @@ public override bool PreDraw(ref Color lightColor) Player player = Main.player[Projectile.owner]; var texMain = (Texture2D)ModContent.Request(Texture); SpriteEffects se = SpriteEffects.None; - if (player.direction == -1) + if (player.direction * player.gravDir == -1) { se = SpriteEffects.FlipVertically; } lightColor = Lighting.GetColor(Projectile.Center.ToTileCoordinates()); - float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction; + float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction * player.gravDir; var texMain_glow = ModAsset.LightBeamStaff_glow.Value; float duration = player.itemTime / (float)player.itemTimeMax; duration *= 1.5f; @@ -98,9 +97,9 @@ public override bool PreDraw(ref Color lightColor) } duration = MathF.Sin(duration * MathHelper.Pi); - Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + DrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); + Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + GravityDrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); var powerColor = new Color(duration + 0.3f, duration * duration, duration * duration, 0); - Main.spriteBatch.Draw(texMain_glow, Projectile.Center - Main.screenPosition + DrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, powerColor, rot, texMain_glow.Size() / 2f, 1f, se, 0); + Main.spriteBatch.Draw(texMain_glow, Projectile.Center - Main.screenPosition + GravityDrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, powerColor, rot, texMain_glow.Size() / 2f, 1f, se, 0); return false; } } diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/YggdrasilAmberLaser_crystal.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/YggdrasilAmberLaser_crystal.cs index 07159888a0..dc4d4c4199 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/YggdrasilAmberLaser_crystal.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/YggdrasilAmberLaser_crystal.cs @@ -1,3 +1,4 @@ +using System.IO; using Everglow.Commons.DataStructures; using Everglow.Yggdrasil.YggdrasilTown.Buffs; using Everglow.Yggdrasil.YggdrasilTown.Dusts; @@ -19,11 +20,26 @@ public override void SetDefaults() Projectile.width = 10; Projectile.height = 10; Projectile.aiStyle = -1; + Projectile.hide = true; CrystalTrack = new Vector2[50]; } public Projectile LaserOwner; + private int laserOwnerIdentity = -1; + private bool trackInitialized; + + public override void SendExtraAI(BinaryWriter writer) + { + writer.Write(LaserOwner?.identity ?? laserOwnerIdentity); + } + + public override void ReceiveExtraAI(BinaryReader reader) + { + laserOwnerIdentity = reader.ReadInt32(); + LaserOwner = null; + } + public Vector2[] CrystalTrack = new Vector2[50]; public bool EndAI = false; @@ -31,18 +47,23 @@ public override void SetDefaults() public override void OnSpawn(IEntitySource source) { CrystalTrack[0] = Projectile.Center; + trackInitialized = true; Projectile.ai[0] = 0; - Projectile.hide = true; } public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone) { target.AddBuff(ModContent.BuffType(), 6); - base.OnHitNPC(target, hit, damageDone); } public override void AI() { + // Network-created projectiles skip OnSpawn. + if (!trackInitialized) + { + CrystalTrack[0] = Projectile.Center; + trackInitialized = true; + } if (Projectile.timeLeft < 60) { int length = 0; @@ -66,6 +87,26 @@ public override void AI() } } ++Projectile.ai[0]; + if (LaserOwner == null) + { + if (laserOwnerIdentity < 0) + { + return; + } + foreach (var candidate in Main.ActiveProjectiles) + { + if (candidate.owner == Projectile.owner && candidate.identity == laserOwnerIdentity + && candidate.ModProjectile is YggdrasilAmberLaser_proj) + { + LaserOwner = candidate; + break; + } + } + if (LaserOwner == null) + { + return; + } + } if (!LaserOwner.active) { EndAI = true; @@ -134,7 +175,7 @@ public override void AI() return false; } float value = 0; - if (Collision.CheckAABBvLineCollision(targetHitbox.TopLeft(), targetHitbox.Size(), CrystalTrack.ToArray()[i], CrystalTrack.ToArray()[i + 1], 20, ref value)) + if (Collision.CheckAABBvLineCollision(targetHitbox.TopLeft(), targetHitbox.Size(), CrystalTrack[i], CrystalTrack[i + 1], 20, ref value)) { return true; } @@ -142,10 +183,6 @@ public override void AI() return false; } - public override void ModifyHitNPC(NPC target, ref NPC.HitModifiers modifiers) - { - } - public override void DrawBehind(int index, List behindNPCsAndTiles, List behindNPCs, List behindProjectiles, List overPlayers, List overWiresUI) { behindNPCsAndTiles.Add(index); @@ -179,12 +216,12 @@ public override bool PreDraw(ref Color lightColor) } if (CrystalTrack[i + 1] != Vector2.zeroVector) { - Vector2 normal = (CrystalTrack.ToArray()[i + 1] - CrystalTrack.ToArray()[i]).SafeNormalize(Vector2.zeroVector).RotatedBy(MathHelper.PiOver2); - AddVertex(bars, CrystalTrack.ToArray()[i] + normal * width, new Vector3(i * 0.3f, 1, 0)); - AddVertex(bars, CrystalTrack.ToArray()[i] - normal * width, new Vector3(i * 0.3f, 0f, 0)); + Vector2 normal = (CrystalTrack[i + 1] - CrystalTrack[i]).SafeNormalize(Vector2.zeroVector).RotatedBy(MathHelper.PiOver2); + AddVertex(bars, CrystalTrack[i] + normal * width, new Vector3(i * 0.3f, 1, 0)); + AddVertex(bars, CrystalTrack[i] - normal * width, new Vector3(i * 0.3f, 0f, 0)); - AddVertex2(barsReflect, CrystalTrack.ToArray()[i] + normal * width, new Vector3(i * 0.3f, 1, 0)); - AddVertex2(barsReflect, CrystalTrack.ToArray()[i] - normal * width, new Vector3(i * 0.3f, 0f, 0)); + AddVertex2(barsReflect, CrystalTrack[i] + normal * width, new Vector3(i * 0.3f, 1, 0)); + AddVertex2(barsReflect, CrystalTrack[i] - normal * width, new Vector3(i * 0.3f, 0f, 0)); } } diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/YggdrasilAmberLaser_proj.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/YggdrasilAmberLaser_proj.cs index 8088069a58..a5e80fc873 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/YggdrasilAmberLaser_proj.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Magic/YggdrasilAmberLaser_proj.cs @@ -4,14 +4,15 @@ using Everglow.Yggdrasil.YggdrasilTown.Items.Weapons; using Everglow.Yggdrasil.YggdrasilTown.VFXs; using Terraria.Audio; -using Terraria.DataStructures; namespace Everglow.Yggdrasil.YggdrasilTown.Projectiles.Magic; -public class YggdrasilAmberLaser_proj : HandholdProjectile +public class YggdrasilAmberLaser_proj : HandheldProjectile { public override string LocalizationCategory => Everglow.Commons.Utilities.LocalizationUtils.Categories.MagicProjectiles; + private bool playedSpawnSound; + public override void SetDef() { DepartLength = 60; @@ -19,30 +20,31 @@ public override void SetDef() Projectile.usesLocalNPCImmunity = true; Projectile.localNPCHitCooldown = 5; Projectile.ArmorPenetration = 45; - base.SetDef(); } public Vector2 EndPoint = Vector2.Zero; public bool Crystalized = false; - public override void OnSpawn(IEntitySource source) - { - SoundEngine.PlaySound(SoundID.Shimmer1.WithPitchOffset(1), Projectile.Center); - Player player = Main.player[Projectile.owner]; - Vector2 mouseToPlayer = Main.MouseWorld - player.Center; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); - Projectile.rotation = mouseToPlayer.ToRotation() + MathHelper.PiOver4; - EndPoint = Vector2.Zero; - } - - public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone) - { - base.OnHitNPC(target, hit, damageDone); - } - public override void AI() { + if (!playedSpawnSound) + { + playedSpawnSound = true; + SoundEngine.PlaySound(SoundID.Shimmer1.WithPitchOffset(1), Projectile.Center); + } HeldProjectileAI(); + if (!Projectile.active) + { + return; + } + Vector2 direction = (Projectile.rotation - MathHelper.PiOver4).ToRotationVector2(); + int step = -6; + while (step < 200 && !Collision.SolidCollision(Projectile.Center + direction * step * 8, 0, 0)) + { + step++; + } + MaxStep = step; + EndPoint = Projectile.Center + direction * step * 8; Player player = Main.player[Projectile.owner]; int timeMax = (int)(player.itemTimeMax / player.meleeSpeed); float duration = player.itemTime / (float)timeMax; @@ -59,7 +61,7 @@ public override void AI() } if (EndPoint != Vector2.Zero) { - if (!Crystalized) + if (!Crystalized && Projectile.owner == Main.myPlayer) { Crystalized = true; var projectile = Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), EndPoint, Vector2.zeroVector, ModContent.ProjectileType(), Projectile.damage / 2, 0, Projectile.owner); @@ -67,8 +69,13 @@ public override void AI() if (yALc != null) { yALc.LaserOwner = Projectile; + projectile.netUpdate = true; } } + if (Main.dedServ) + { + return; + } for (int g = 0; g < 10; g++) { Vector2 newVelocity = new Vector2(0, Main.rand.NextFloat(0f, 12f)).RotatedByRandom(MathHelper.TwoPi); @@ -105,7 +112,7 @@ public override void AI() return false; } bool k = Collision.CheckAABBvLineCollision(targetHitbox.TopLeft(), new Vector2(targetHitbox.Width, targetHitbox.Height), Projectile.Center, EndPoint); - if (k) + if (k && !Main.dedServ) { for (int g = 0; g < 10; g++) { @@ -133,9 +140,10 @@ public override void HeldProjectileAI() if (player.HeldItem.type != ModContent.ItemType()) { Projectile.Kill(); + return; } player.heldProj = Projectile.whoAmI; - ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2); + ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2 * player.gravDir); int timeMax = (int)(player.itemTimeMax / player.meleeSpeed); if (Projectile.localNPCHitCooldown > timeMax - 1) @@ -145,6 +153,7 @@ public override void HeldProjectileAI() if (player.itemTime == 1) { Projectile.Kill(); + return; } player.SetCompositeArmFront(true, Player.CompositeArmStretchAmount.Full, (Projectile.rotation - MathF.PI * 0.25f) * player.gravDir - MathF.PI * 0.5f); DepartLength = 60; @@ -159,7 +168,7 @@ public override void HeldProjectileAI() { player.direction = 1; } - if (EndPoint != Vector2.zeroVector) + if (!Main.dedServ && EndPoint != Vector2.zeroVector) { int duplicateTimes = 1; for (int i = 0; i < duplicateTimes; i++) @@ -196,12 +205,12 @@ public override bool PreDraw(ref Color lightColor) Player player = Main.player[Projectile.owner]; var texMain = (Texture2D)ModContent.Request(Texture); SpriteEffects se = SpriteEffects.None; - if (player.direction == -1) + if (player.direction * player.gravDir == -1) { se = SpriteEffects.FlipVertically; } - float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction; + float rot = Projectile.rotation - (float)(Math.PI * 0.25) + TextureRotation * player.direction * player.gravDir; var texMain_glow = ModAsset.YggdrasilAmberLaser_glow_proj.Value; float duration = player.itemTime / (float)player.itemTimeMax; duration *= 1.5f; @@ -212,9 +221,9 @@ public override bool PreDraw(ref Color lightColor) } duration = MathF.Sin(duration * MathHelper.Pi); - Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + DrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); + Main.spriteBatch.Draw(texMain, Projectile.Center - Main.screenPosition + GravityDrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, lightColor, rot, texMain.Size() / 2f, 1f, se, 0); var powerColor = new Color(duration, duration * duration, duration * duration, 0); - Main.spriteBatch.Draw(texMain_glow, Projectile.Center - Main.screenPosition + DrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, powerColor, rot, texMain_glow.Size() / 2f, 1f, se, 0); + Main.spriteBatch.Draw(texMain_glow, Projectile.Center - Main.screenPosition + GravityDrawOffset - new Vector2(54, 0).RotatedBy(Projectile.rotation - MathHelper.PiOver4), null, powerColor, rot, texMain_glow.Size() / 2f, 1f, se, 0); SpriteBatchState sBS = Main.spriteBatch.GetState().Value; Main.spriteBatch.End(); @@ -252,8 +261,6 @@ public override bool PreDraw(ref Color lightColor) }; Ins.VFXManager.Add(somg); } - MaxStep = step; - EndPoint = Projectile.Center + MaxStep * mouseToPlayer * 8; } var bars = new List(); step = -6; diff --git a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Ranged/PearShapedNeedle_HeldProj.cs b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Ranged/PearShapedNeedle_HeldProj.cs index 0f5456e067..8dc235cd19 100644 --- a/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Ranged/PearShapedNeedle_HeldProj.cs +++ b/Sources/Modules/Yggdrasil/YggdrasilTown/Projectiles/Ranged/PearShapedNeedle_HeldProj.cs @@ -3,7 +3,7 @@ namespace Everglow.Yggdrasil.YggdrasilTown.Projectiles.Ranged; -public class PearShapedNeedle_HeldProj : HandholdProjectile +public class PearShapedNeedle_HeldProj : HandheldProjectile { public float Timer = 0; @@ -36,12 +36,13 @@ public override void HeldProjectileAI() if (player.HeldItem.type != ModContent.ItemType()) { Projectile.Kill(); + return; } player.heldProj = Projectile.whoAmI; - ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2); + ArmRootPos = player.MountedCenter + new Vector2(-4 * player.direction, -2 * player.gravDir); - Vector2 mouseToPlayer = Main.MouseWorld - ArmRootPos; - mouseToPlayer = Vector2.Normalize(mouseToPlayer); + Vector2 mouseToPlayer = AimPosition - ArmRootPos; + mouseToPlayer = mouseToPlayer.SafeNormalize(Vector2.UnitX * player.direction); Projectile.rotation = mouseToPlayer.ToRotation() + MathHelper.PiOver4; player.SetCompositeArmFront(true, Player.CompositeArmStretchAmount.Full, (Projectile.rotation - MathF.PI * 0.25f) * player.gravDir - MathF.PI * 0.5f); @@ -171,7 +172,6 @@ public float GetReflectValue(float rotation) public override void OnKill(int timeLeft) { ReleaseNeedles(); - base.OnKill(timeLeft); } public bool NeedleReady(int k) @@ -211,6 +211,10 @@ public void ReleaseNeedles() if (NeedleReady(k)) { succeed = true; + if (Projectile.owner != Main.myPlayer) + { + continue; + } Projectile.NewProjectileDirect(Projectile.GetSource_FromAI(), GetNeedleWorldPos(k), GetReleaseVel(k).NormalizeSafe(), ModContent.ProjectileType(), Projectile.damage, Projectile.knockBack, Projectile.owner); if (k > 0) {