Skip to content

Commit

Permalink
Made projectile-only swords fully aimable (#198).
Browse files Browse the repository at this point in the history
  • Loading branch information
Mirsario committed Sep 7, 2023
1 parent e8de853 commit 3d115d3
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
- Fixed the `Volcano`, `Blood Butcherer`, and a few other melee weapons using incorrect rotations & locations for their particle effects.
- Fixed the following projectile-only swords not getting the broadsword overhaul: `Night's Edge`, `Excalibur`, `True Excalibur`, `True Night's Edge`, `Terra Blade`, `The Horseman's Blade`.
- Fixed `Blade of Grass` and projectile-only swords being able to create projectiles during a power attack charge.
- Fixed projectile-only swords not being fully aimable.

# 5.0 BETA 13B

Expand Down
73 changes: 73 additions & 0 deletions Common/Hooks/Items/IModifyItemNewProjectile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.DataStructures;
using Terraria.ModLoader;
using Terraria.ModLoader.Core;
using Hook = TerrariaOverhaul.Common.Hooks.Items.IModifyItemNewProjectile;

namespace TerrariaOverhaul.Common.Hooks.Items;

public interface IModifyItemNewProjectile
{
//TODO: Use ref fields when they are available.
public ref struct Args
{
public IEntitySource Source;
public Vector2 Position;
public Vector2 Velocity;
public int Type;
public int Damage;
public float Knockback;
public int Owner;
public float AI0;
public float AI1;
public float AI2;
}

public static readonly GlobalHookList<GlobalItem> Hook = ItemLoader.AddModHook(new GlobalHookList<GlobalItem>(typeof(Hook).GetMethod(nameof(ModifyShootProjectile))));

void ModifyShootProjectile(Player player, Item item, in Args args, ref Args result);

public static void Invoke(Player player, Item item, in Args args, ref Args result)
{
(item.ModItem as Hook)?.ModifyShootProjectile(player, item, in args, ref result);

foreach (Hook g in Hook.Enumerate(item)) {
g.ModifyShootProjectile(player, item, in args, ref result);
}
}
}

public sealed class ItemOnShootProjectileImplementation : ILoadable
{
public void Load(Mod mod)
{
On_Projectile.NewProjectile_IEntitySource_float_float_float_float_int_int_float_int_float_float_float += (orig, entitySource, x, y, speedX, speedY, type, damage, knockback, owner, ai0, ai1, ai2) => {
if (entitySource is EntitySource_ItemUse_WithAmmo parentSource && parentSource.Entity is Player player) {
Hook.Args data;

data.Source = entitySource;
data.Position = new Vector2(x, y);
data.Velocity = new Vector2(speedX, speedY);
data.Type = type;
data.Damage = damage;
data.Knockback = knockback;
data.Owner = owner;
data.AI0 = ai0;
data.AI1 = ai1;
data.AI2 = ai2;

var args = data;

Hook.Invoke(player, parentSource.Item, in args, ref data);

(x, y, speedX, speedY, ai0, ai1, ai2) = (data.Position.X, data.Position.Y, data.Velocity.X, data.Velocity.Y, data.AI0, data.AI1, data.AI2);
}

return orig(entitySource, x, y, speedX, speedY, type, damage, knockback, owner, ai0, ai1, ai2);
};
}

public void Unload() { }
}
15 changes: 13 additions & 2 deletions Common/Melee/ItemMeleeAttackAiming.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;
using TerrariaOverhaul.Common.Damage;
Expand All @@ -11,7 +12,7 @@

namespace TerrariaOverhaul.Common.Melee;

public sealed class ItemMeleeAttackAiming : ItemComponent, ICanMeleeCollideWithNPC
public sealed class ItemMeleeAttackAiming : ItemComponent, ICanMeleeCollideWithNPC, IModifyItemNewProjectile
{
private Vector2 attackDirection;
private float attackAngle;
Expand Down Expand Up @@ -47,7 +48,7 @@ public override void ModifyHitNPC(Item item, Player player, NPC target, ref NPC.
}
}

public bool? CanMeleeCollideWithNPC(Item item, Player player, NPC target, Rectangle itemRectangle)
bool? ICanMeleeCollideWithNPC.CanMeleeCollideWithNPC(Item item, Player player, NPC target, Rectangle itemRectangle)
{
if (!Enabled) {
return null;
Expand All @@ -63,6 +64,16 @@ public override void ModifyHitNPC(Item item, Player player, NPC target, ref NPC.
return CollisionUtils.CheckRectangleVsArcCollision(target.getRect(), player.Center, AttackAngle, MathHelper.Pi * 0.5f, range);
}

void IModifyItemNewProjectile.ModifyShootProjectile(Player player, Item item, in IModifyItemNewProjectile.Args args, ref IModifyItemNewProjectile.Args result)
{
// Makes always horizontally-facing projectiles aimable.
if (args.Source is EntitySource_ItemUse_WithAmmo && args.Velocity.Y == 0f && args.Velocity.X == player.direction) {
if (item.TryGetGlobalItem(out ItemMeleeAttackAiming aiming)) {
result.Velocity = aiming.AttackDirection;
}
}
}

public static float GetAttackRange(Item item, Player player, Rectangle? itemRectangle = null)
{
Rectangle itemHitbox = GetMeleeHitbox(player, item);
Expand Down

0 comments on commit 3d115d3

Please sign in to comment.