diff --git a/Content/Guardian/GuardianShieldAnchor.cs b/Content/Guardian/GuardianShieldAnchor.cs
index 1fd39772..4732f60d 100644
--- a/Content/Guardian/GuardianShieldAnchor.cs
+++ b/Content/Guardian/GuardianShieldAnchor.cs
@@ -30,7 +30,8 @@ public class GuardianShieldAnchor : OrchidModGuardianAnchor
public float networkedRotation => Projectile.ai[2];
// ...
-
+ public bool IsRotationLocked;
+ private float LockedRotation;
public override void SafeSetDefaults()
{
Projectile.width = 20;
@@ -108,6 +109,7 @@ public override void AI()
}
float addedDistance = 0f;
+
if (Projectile.ai[1] > 0f)
{ // Shield bash
if (isSlamming == 0)
@@ -142,9 +144,12 @@ public override void AI()
if (Projectile.ai[1] <= 0f)
{
+ guardianItem.SlamEnd(owner, Projectile);
Projectile.ai[1] = 0f;
isSlamming = 0;
Projectile.friendly = false;
+ IsRotationLocked = false;
+ Projectile.netUpdate = true;
}
}
@@ -245,13 +250,15 @@ public override void AI()
{
aimedLocation = Main.MouseWorld - owner.Center.Floor();
aimedLocation.Normalize();
+
+ aimedLocation = Vector2.UnitX.RotatedBy(IsRotationLocked ? LockedRotation : OrchidModGuardianShield.GetSnappedAngle(guardianItem, owner,aimedLocation.ToRotation()));
Projectile.velocity = aimedLocation * float.Epsilon;
aimedLocation *= (guardianItem.distance + addedDistance) * -1f;
Projectile.rotation = aimedLocation.ToRotation();
if (guardianItem.shouldFlip)
{
- if (aimedLocation.X < 0)
+ if (aimedLocation.X < 0 || (isSlamming is 1 or 2 && IsRotationLocked && -Vector2.UnitX.RotatedBy(LockedRotation).X < 0))
{
Projectile.spriteDirection = -1;
}
@@ -284,6 +291,12 @@ public override void AI()
if (isSlamming == 1) // Slam() is called here so the projectile has the time to reposition properly before effects such as projectile spawns are called
{
isSlamming = 2;
+ if (guardianItem.lockSlamRotation)
+ {
+ IsRotationLocked = true;
+ LockedRotation = Projectile.rotation + MathHelper.Pi;
+ Projectile.netUpdate = true;
+ }
guardianItem.Slam(owner, Projectile);
guardian.GuardianCounterTime = 0;
}
diff --git a/Content/Guardian/OrchidModGuardianShield.cs b/Content/Guardian/OrchidModGuardianShield.cs
index e0ea28ad..beb40eae 100644
--- a/Content/Guardian/OrchidModGuardianShield.cs
+++ b/Content/Guardian/OrchidModGuardianShield.cs
@@ -1,3 +1,4 @@
+using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using OrchidMod.Common;
@@ -28,6 +29,8 @@ public virtual void SlamHitFirst(Player player, Projectile shield, NPC npc) { }
public virtual void SlamHit(Player player, Projectile shield, NPC npc) { }
/// Called on the first frame of a slam.
public virtual void Slam(Player player, Projectile shield) { }
+ /// Called on the last frame of a slam.
+ public virtual void SlamEnd(Player player, Projectile shield) { }
/// Called when an enemy collides with the shield during a block. Will be called once per frame per enemy colliding with it.
public virtual void Push(Player player, Projectile shield, NPC npc) { }
/// Called once per block when the first enemy or projectile is blocked. This is called after Push or Block, but before Block destroys the projectile.
@@ -49,6 +52,23 @@ public virtual void BlockStart(Player player, Projectile shield) { }
/// Causes the shield's held sprite to flip when facing right.
public bool shouldFlip = false;
public bool slamAutoReuse = true;
+ ///
+ /// If true, the shield will be rotated in discrete steps, instead of a single continuous circle. Defaults to false.
+ ///
+ public bool useDiscreteAim = false;
+ ///
+ /// The amount of steps per half-rotation that the shield will snap to, if useDiscreteAim is true.
+ ///
A value of 0 results in only a single possible angle, directly in front of the player. Otherwise, there will be twice as many snap points as this value.
+ ///
+ public int discreteAimIncrements;
+ ///
+ /// The angle, in pi/2 increments, that the base angle will be rotated by.
+ ///
+ public int discreteAimRotation;
+ ///
+ /// If true, slams performed with the shield will be locked to the rotation they started with, rather than being free to rotate mid-slam.
+ ///
+ public bool lockSlamRotation;
public sealed override void SetDefaults()
{
@@ -61,6 +81,10 @@ public sealed override void SetDefaults()
Item.useStyle = ItemUseStyleID.Thrust;
Item.useTime = 30;
Item.knockBack = 6f;
+ useDiscreteAim = false;
+ discreteAimIncrements = 2;
+ discreteAimRotation = 0;
+ lockSlamRotation = false;
OrchidGlobalItemPerEntity orchidItem = Item.GetGlobalItem();
orchidItem.guardianWeapon = true;
@@ -243,5 +267,17 @@ public override void ModifyTooltips(List tooltips)
OverrideColor = new Color(175, 255, 175)
});
}
+
+ public static float GetSnappedAngle(OrchidModGuardianShield shield, Player player, float originalAngle)
+ {
+ if (!shield.useDiscreteAim) return originalAngle;
+ if (shield.discreteAimIncrements == 0) return -player.direction * MathHelper.PiOver2 * shield.discreteAimRotation + (player.direction == -1 ? MathHelper.Pi : 0f);
+ else
+ {
+ float angleIncrement = MathHelper.Pi / shield.discreteAimIncrements;
+ return (float)Math.Round((Vector2.Normalize(Main.MouseWorld - player.MountedCenter.Floor()).ToRotation() + MathHelper.PiOver2 * shield.discreteAimRotation) / angleIncrement) * angleIncrement - MathHelper.PiOver2 * shield.discreteAimRotation;
+ }
+
+ }
}
}