Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frost flail #778

Merged
merged 5 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added Assets/Items/Snow/FrostFlail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/Items/Snow/FrostFlailChain.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/Items/Snow/FrostFlailProjectile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/Items/Snow/FrostFlailShard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Assets/Misc/AlphaCrack.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 38 additions & 13 deletions Content/Items/BaseTypes/AbstractHeavyFlail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,23 @@ public override bool CanShoot(Player player)
internal abstract class AbstractHeavyFlailProjectile : ModProjectile
{
public abstract Asset<Texture2D> ChainAsset { get; }
protected static Asset<Texture2D> BallAsset;
protected Asset<Texture2D> BallAsset;

readonly List<Vector2> chainPos = [];
readonly List<Vector2> chainTarget = [];

protected bool slowing;

/// <summary>
/// The maximum length this flail can extend out to if it has room
/// The maximum length this flail can extend out to if it has room.
/// </summary>
public virtual int MaxLength { get; set; } = 200;

/// <summary>
/// The amount of times alternate chain styles should be repeated at the end of the chain.
/// </summary>
public virtual int AlternateStyleRepeats => 3;

public ref float Timer => ref Projectile.ai[0];
public ref float State => ref Projectile.ai[1];
public ref float Length => ref Projectile.ai[2];
Expand All @@ -55,11 +60,6 @@ internal abstract class AbstractHeavyFlailProjectile : ModProjectile
/// </summary>
public virtual void OnImpact(bool wasTile) { }

public override void SetStaticDefaults()
{
BallAsset = ModContent.Request<Texture2D>(Texture);
}

public override void SetDefaults()
{
Projectile.friendly = true;
Expand All @@ -68,6 +68,8 @@ public override void SetDefaults()
Projectile.tileCollide = true;
Projectile.timeLeft = 180;
Projectile.penetrate = -1;

BallAsset = ModContent.Request<Texture2D>(Texture);
}

public override void AI()
Expand Down Expand Up @@ -233,7 +235,7 @@ public override bool OnTileCollide(Vector2 oldVelocity)
{
var hitbox = new Rectangle((int)chainPos[k].X - 4, (int)chainPos[k].Y - 4, 8, 8);

if (hitbox.Intersects(projHitbox))
if (hitbox.Intersects(targetHitbox))
return true;
}
}
Expand All @@ -252,22 +254,45 @@ public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone)

public override bool PreDraw(ref Color lightColor)
{
int extraStyles = (ChainAsset.Height() - 44) / 22;

if (State == 0)
{
int max = (int)(Vector2.Distance(Owner.Center, Projectile.Center) / ChainAsset.Width());

for (int k = 0; k < max; k++)
{
var pos = Vector2.Lerp(Projectile.Center, Owner.Center, k / (float)max);
Main.EntitySpriteDraw(ChainAsset.Value, pos - Main.screenPosition, null, new Color(Lighting.GetSubLight(pos)), Owner.Center.DirectionTo(pos).ToRotation() - 1.57f, ChainAsset.Size() / 2f, 1f, 0, 0);
var pos = Vector2.Lerp(Owner.Center, Projectile.Center, k / (float)max);
Rectangle source = new Rectangle(0, 0, 8, 22);

if (k > 1)
{
source.Y += 22;

if (extraStyles > 0 && (k + 3) >= (max - extraStyles * AlternateStyleRepeats))
source.Y += 22 * (extraStyles - (max - (k + 3)) / AlternateStyleRepeats);
}

Main.EntitySpriteDraw(ChainAsset.Value, pos - Main.screenPosition, source, new Color(Lighting.GetSubLight(pos)), Owner.Center.DirectionTo(pos).ToRotation() - 1.57f, new Vector2(4, 11), 1f, 0, 0);
}
}

for (int k = 0; k < chainPos.Count; k++)
for (int k = 1; k < chainPos.Count; k++)
{
Vector2 prev = k > 0 ? chainPos[k - 1] : Owner.Center;
Vector2 prev = chainPos[k - 1];
Vector2 curr = chainPos[k];
Main.EntitySpriteDraw(ChainAsset.Value, curr - Main.screenPosition, null, new Color(Lighting.GetSubLight(curr)), curr.DirectionTo(prev).ToRotation() - 1.57f, ChainAsset.Size() / 2f, 1f, 0, 0);

Rectangle source = new Rectangle(0, 0, 8, 22);

if (k > 1)
{
source.Y += 22;

if (extraStyles > 0 && (k + 3) >= (chainPos.Count - extraStyles * AlternateStyleRepeats))
source.Y += 22 * (extraStyles - (chainPos.Count - (k + 3)) / AlternateStyleRepeats);
}

Main.EntitySpriteDraw(ChainAsset.Value, curr - Main.screenPosition, source, new Color(Lighting.GetSubLight(curr)), curr.DirectionTo(prev).ToRotation() - 1.57f, new Vector2(4, 11), 1f, 0, 0);
}

Vector2 ballPos = Projectile.oldPosition + Projectile.Size / 2f;
Expand Down
19 changes: 11 additions & 8 deletions Content/Items/Forest/Weapons.HeavyFlail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,17 +48,20 @@ internal class HeavyFlailProjectile : AbstractHeavyFlailProjectile

public override void OnImpact(bool wasTile)
{
Helpers.Helper.PlayPitched("Impacts/StoneStrike", 1, 0, Projectile.Center);
if (wasTile)
{
Helpers.Helper.PlayPitched("Impacts/StoneStrike", 1, 0, Projectile.Center);

if (Owner == Main.LocalPlayer)
CameraSystem.shake += 10;
if (Owner == Main.LocalPlayer)
CameraSystem.shake += 10;

for (int k = 0; k < 32; k++)
{
Dust.NewDust(Projectile.position, Projectile.width, Projectile.height, DustID.Stone);
}
for (int k = 0; k < 32; k++)
{
Dust.NewDust(Projectile.position, Projectile.width, Projectile.height, DustID.Stone);
}

Projectile.NewProjectile(null, Projectile.Center + Vector2.UnitY * 8, Vector2.Zero, ModContent.ProjectileType<HeavyFlailCrack>(), 0, 0);
Projectile.NewProjectile(Projectile.GetSource_FromThis(), Projectile.Center + Vector2.UnitY * 8, Vector2.Zero, ModContent.ProjectileType<HeavyFlailCrack>(), 0, 0);
}
}
}

Expand Down
164 changes: 164 additions & 0 deletions Content/Items/Snow/Weapons.FrostFlail.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
using StarlightRiver.Content.Items.BaseTypes;
using StarlightRiver.Content.Items.Forest;
using StarlightRiver.Content.Tiles.Misc;
using StarlightRiver.Core.Systems.CameraSystem;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Terraria.ID;

namespace StarlightRiver.Content.Items.Snow
{
internal class FrostFlail : AbstractHeavyFlail
{
public override string Texture => AssetDirectory.SnowItem + Name;

public override int ProjType => ModContent.ProjectileType<FrostFlailProjectile>();

public override void SetStaticDefaults()
{
DisplayName.SetDefault("Frost Flail");
Tooltip.SetDefault("Hold to swing a monstrous ball of ice\nCreates icy shards on impact, inflicting frostburn");
}

public override void SetDefaults()
{
base.SetDefaults();
Item.rare = ItemRarityID.Blue;
Item.damage = 14;
}

public override void AddRecipes()
{
Recipe recipe = CreateRecipe();
recipe.AddIngredient(ItemID.IceBlock, 99);
recipe.AddIngredient(ModContent.ItemType<HeavyFlail>(), 1);
recipe.AddTile(TileID.Anvils);
recipe.Register();
}
}

internal class FrostFlailProjectile : AbstractHeavyFlailProjectile
{
public override string Texture => AssetDirectory.SnowItem + Name;

public override Asset<Texture2D> ChainAsset => Assets.Items.Snow.FrostFlailChain;

public override int MaxLength => 160;

public override void AI()
{
base.AI();

for (int k = 0; k < 2; k++)
{
Dust.NewDust(Projectile.Center - Vector2.One * 20, 40, 40, DustID.IceTorch);
}
}

public override void OnImpact(bool wasTile)
{
if (wasTile)
{
Helpers.Helper.PlayPitched("Magic/FrostHit", 1, 0, Projectile.Center);

if (Owner == Main.LocalPlayer)
CameraSystem.shake += 8;

for (int k = 0; k < 30; k++)
{
Dust.NewDust(Projectile.position, Projectile.width, Projectile.height, DustID.Ice);
}

for (int k = 0; k < 10; k++)
{
Dust.NewDust(Projectile.position, Projectile.width, Projectile.height, DustID.SnowSpray, 0, -1);
}

for (int k = 0; k < 3; k++)
{
Projectile.NewProjectile(Projectile.GetSource_FromThis(), Projectile.Center, Vector2.One.RotatedByRandom(6.28f) * 3, ModContent.ProjectileType<FrostFlailShard>(), Projectile.damage / 2, 0, Projectile.owner);
}

Projectile.NewProjectile(Projectile.GetSource_FromThis(), Projectile.Center + Vector2.UnitY * 8, Vector2.Zero, ModContent.ProjectileType<FrostFlailCrack>(), 0, 0);
}
}
}

internal class FrostFlailCrack : ModProjectile, IDrawOverTiles
{
public override string Texture => AssetDirectory.Invisible;

public override void SetDefaults()
{
Projectile.tileCollide = false;
Projectile.penetrate = -1;
Projectile.timeLeft = 200;
}

public override bool PreDraw(ref Color lightColor)
{
return false;
}

public void DrawOverTiles(SpriteBatch spriteBatch)
{
float prog = Projectile.timeLeft > 100 ? 1f : Projectile.timeLeft / 100f;

Color color = Color.Lerp(new Color(150, 240, 255), new Color(50, 80, 150), prog);
color *= prog;
color.A = 0;
var tex = Assets.Misc.AlphaCrack.Value;

spriteBatch.Draw(tex, Projectile.Center - Main.screenPosition, null, color, 0, tex.Size() / 2, Projectile.scale, SpriteEffects.None, 0);
spriteBatch.Draw(tex, Projectile.Center - Main.screenPosition, null, new Color(255, 255, 255, 0) * prog * 0.25f, 0, tex.Size() / 2, Projectile.scale, SpriteEffects.None, 0);
}
}

internal class FrostFlailShard : ModProjectile
{
public override string Texture => AssetDirectory.SnowItem + Name;

public override void SetDefaults()
{
Projectile.width = 18;
Projectile.height = 18;
Projectile.tileCollide = true;
Projectile.timeLeft = 120;
Projectile.friendly = true;
Projectile.aiStyle = -1;
Projectile.penetrate = 15;
}

public override void AI()
{
Projectile.velocity.Y += 0.4f;
Projectile.rotation += Projectile.velocity.X * 0.1f;

Projectile.velocity.X *= 0.99f;

if (Projectile.timeLeft < 30)
Projectile.alpha = (int)((1 - Projectile.timeLeft / 30f) * 255);

if (Main.rand.NextBool(10))
Dust.NewDust(Projectile.position, 18, 18, DustID.IceTorch);
}

public override bool OnTileCollide(Vector2 oldVelocity)
{
if (Projectile.penetrate <= 0)
return true;

Projectile.velocity.Y += oldVelocity.Y * -0.8f;

return false;
}

public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone)
{
target.AddBuff(BuffID.Frostburn, 60);
}
}
}
Loading
Loading