This is for tModLoader 1.4.4, it adds a new accessory where you double jump and underneath you have a firecloud. The problem is that the double jump is sometimes glitchy, because it's not made in the way it's intended to, which is:

using ExampleMod.Content.Tiles.Furniture;
using Microsoft.Xna.Framework;
using System.Collections.Generic;
using Terraria;
using Terraria.Enums;
using Terraria.ID;
using Terraria.ModLoader;

namespace ExampleMod.Content.Items.Accessories
{
	// Showcases a basic extra jump
	public class ExampleExtraJumpAccessory : ModItem
	{
		public override void SetDefaults() {
			Item.DefaultToAccessory(20, 26);
			Item.SetShopValues(ItemRarityColor.Green2, Item.buyPrice(silver: 50));
		}

		public override void UpdateAccessory(Player player, bool hideVisual) {
			player.GetJumpState<SimpleExtraJump>().Enable();
		}

		public override void AddRecipes() {
			CreateRecipe()
				.AddIngredient<ExampleItem>(20)
				.AddTile<ExampleWorkbench>()
				.Register();
		}
	}

	public class SimpleExtraJump : ExtraJump
	{
		public override Position GetDefaultPosition() => new After(BlizzardInABottle);

		public override IEnumerable<Position> GetModdedConstraints() {
			// By default, modded extra jumps set to be between two vanilla extra jumps (via After and Before) are ordered in load order.
			// This hook allows you to organize where this extra jump is located relative to other modded extra jumps that are also
			// placed between the same two vanilla extra jumps.
			yield return new Before(ModContent.GetInstance<MultipleUseExtraJump>());
		}

		public override float GetDurationMultiplier(Player player) {
			// Use this hook to set the duration of the extra jump
			// The XML summary for this hook mentions the values used by the vanilla extra jumps
			return 2.25f;
		}

		public override void UpdateHorizontalSpeeds(Player player) {
			// Use this hook to modify "player.runAcceleration" and "player.maxRunSpeed"
			// The XML summary for this hook mentions the values used by the vanilla extra jumps
			player.runAcceleration *= 1.75f;
			player.maxRunSpeed *= 2f;
		}

		public override void OnStarted(Player player, ref bool playSound) {
			// Use this hook to trigger effects that should appear at the start of the extra jump
			// This example mimics the logic for spawning the puff of smoke from the Cloud in a Bottle
			int offsetY = player.height;
			if (player.gravDir == -1f)
				offsetY = 0;

			offsetY -= 16;

			for (int i = 0; i < 10; i++) {
				Dust dust = Dust.NewDustDirect(player.position + new Vector2(-34f, offsetY), 102, 32, DustID.Cloud, -player.velocity.X * 0.5f, player.velocity.Y * 0.5f, 100, Color.Gray, 1.5f);
				dust.velocity = dust.velocity * 0.5f - player.velocity * new Vector2(0.1f, 0.3f);
			}

			SpawnCloudPoof(player, player.Top + new Vector2(-16f, offsetY));
			SpawnCloudPoof(player, player.position + new Vector2(-36f, offsetY));
			SpawnCloudPoof(player, player.TopRight + new Vector2(4f, offsetY));
		}

		private static void SpawnCloudPoof(Player player, Vector2 position) {
			Gore gore = Gore.NewGoreDirect(player.GetSource_FromThis(), position, -player.velocity, Main.rand.Next(11, 14));
			gore.velocity.X = gore.velocity.X * 0.1f - player.velocity.X * 0.1f;
			gore.velocity.Y = gore.velocity.Y * 0.1f - player.velocity.Y * 0.05f;
		}

		public override void ShowVisuals(Player player) {
			// Use this hook to trigger effects that should appear throughout the duration of the extra jump
			// This example mimics the logic for spawning the dust from the Blizzard in a Bottle
			int offsetY = player.height - 6;
			if (player.gravDir == -1f)
				offsetY = 6;

			Vector2 spawnPos = new Vector2(player.position.X, player.position.Y + offsetY);

			for (int i = 0; i < 2; i++) {
				SpawnBlizzardDust(player, spawnPos, 0.1f, i == 0 ? -0.07f : -0.13f);
			}

			for (int i = 0; i < 3; i++) {
				SpawnBlizzardDust(player, spawnPos, 0.6f, 0.8f);
			}

			for (int i = 0; i < 3; i++) {
				SpawnBlizzardDust(player, spawnPos, 0.6f, -0.8f);
			}
		}

		private static void SpawnBlizzardDust(Player player, Vector2 spawnPos, float dustVelocityMultiplier, float playerVelocityMultiplier) {
			Dust dust = Dust.NewDustDirect(spawnPos, player.width, 12, DustID.Snow, player.velocity.X * 0.3f, player.velocity.Y * 0.3f, newColor: Color.Gray);
			dust.fadeIn = 1.5f;
			dust.velocity *= dustVelocityMultiplier;
			dust.velocity += player.velocity * playerVelocityMultiplier;
			dust.noGravity = true;
			dust.noLight = true;
		}
	}
}.

That above is the example mod for double jump accessory. Below is the accessory I made, I want you to remake the jumping logic:


using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using Microsoft.Xna.Framework;
using Terraria.Audio;
using System;
using ITD.Utilities;

namespace ITD.Content.Items.Accessories.Movement.Jumps
{
    public class FirestormInABottle : ModItem
    {
        public override void SetDefaults()
        {
            Item.width = 28;
            Item.height = 24;
            Item.value = Item.sellPrice(gold: 2);
            Item.rare = ItemRarityID.Orange;
            Item.accessory = true;
        }

        public override void UpdateAccessory(Player player, bool hideVisual)
        {
            player.GetModPlayer<FirestormPlayer>().hasFireJump = true;
        }
    }

    public class FirestormPlayer : ModPlayer
    {
        public const int FireCloudDuration = 180;
        public const int FireTrailDuration = 60;
        public const int RainDuration = 120;
        public const int FireRainLifetime = 180;
        public const int DamageInterval = 30;

        public bool hasFireJump;
        public bool canDoubleJump;
        public bool waitDoubleJump;
        public int fireCloudTimer;
        public int fireTrailTimer;
        public int rainTimer;
        public int damageTimer;
        public Vector2 jumpPosition;

        public override void ResetEffects() => hasFireJump = false;

        public override void PreUpdate()
        {
            HandleDoubleJump();
            UpdateTimers();
        }

        public override void PostUpdate() => UpdateFireRain();

        private void HandleDoubleJump()
        {
            if ((Player.velocity.Y == 0f || Player.sliding || Player.autoJump && Player.justJumped) && hasFireJump)
            {
                canDoubleJump = true;
                waitDoubleJump = true;
            }
            else if (canDoubleJump && Player.controlJump && !waitDoubleJump)
            {
                PerformDoubleJump();
            }

            waitDoubleJump = Player.controlJump;
        }

        private void PerformDoubleJump()
        {
            if (Player.jump > 0) return;

            Player.velocity.Y = -Player.jumpSpeed * Player.gravDir;
            Player.jump = Player.jumpHeight;
            canDoubleJump = false;

            SoundEngine.PlaySound(new SoundStyle($"ITD/Content/Sounds/FirestormInABottle{Main.rand.Next(1, 3)}"), Player.position);

            fireCloudTimer = FireCloudDuration;
            fireTrailTimer = FireTrailDuration;
            rainTimer = RainDuration;
            damageTimer = DamageInterval;
            jumpPosition = Player.Bottom;
        }

        private void UpdateTimers()
        {
            if (fireCloudTimer > 0) { fireCloudTimer--; FireCloud(); }
            if (fireTrailTimer > 0) { fireTrailTimer--; FireTrail(); }
            if (rainTimer > 0) { rainTimer--; FireRain(); }
            if (damageTimer > 0) damageTimer--;
        }

        private void FireCloud()
        {
            float progress = (float)fireCloudTimer / FireCloudDuration;
            for (int i = 0; i < 10; i++) CreateFireCloudDust(progress);
            DamageEnemy(jumpPosition, damageTimer <= 0);
            if (damageTimer <= 0) damageTimer = DamageInterval;
        }

        private void CreateFireCloudDust(float progress)
        {
            Vector2 speed = Main.rand.NextVector2Circular(5f * progress, 5f * progress);
            speed.Y -= Main.rand.NextFloat(2f * progress, 8f * progress);

            int dustType = Main.rand.Next(3) switch
            {
                0 => DustID.Torch,
                1 => DustID.Smoke,
                _ => DustID.Cloud
            };

            Dust dust = Dust.NewDustPerfect(
                jumpPosition + new Vector2(Main.rand.Next(-50, 51), Main.rand.Next(-20, 21)),
                dustType,
                speed,
                100,
                Color.OrangeRed * progress,
                Main.rand.NextFloat(1f, 2.5f) * progress
            );

            dust.noGravity = true;
            dust.fadeIn = 1f * progress;

            if (dustType == DustID.Cloud)
            {
                dust.color = Color.Lerp(Color.OrangeRed, Color.White, Main.rand.NextFloat(0.5f));
            }
        }

        private void FireTrail()
        {
            for (int i = 0; i < 3; i++) CreateFireTrailDust();
            DamageEnemy(Player.Bottom, false);
        }

        private void CreateFireTrailDust()
        {
            Vector2 speed = new Vector2(Main.rand.NextFloat(-1f, 1f), Main.rand.NextFloat(-1.5f, -0.5f));

            Dust dust = Dust.NewDustPerfect(
                Player.Bottom + new Vector2(Main.rand.Next(-10, 11), 0),
                DustID.Torch,
                speed,
                100,
                Color.OrangeRed,
                Main.rand.NextFloat(0.5f, 1f)
            );

            dust.noGravity = true;
            dust.fadeIn = 0.5f;
            dust.color = Color.Lerp(Color.OrangeRed, Color.Yellow, Main.rand.NextFloat(0.5f));
        }

        private void FireRain()
        {
            float progress = (float)rainTimer / RainDuration;
            for (int i = 0; i < 3; i++) CreateFireRainDust(progress);
        }

        private void CreateFireRainDust(float progress)
        {
            Vector2 rainPosition = jumpPosition + new Vector2(Main.rand.Next(-50, 51), Main.rand.Next(-20, 0));
            Vector2 rainVelocity = new Vector2(Main.windSpeedCurrent * 0.3f, Main.rand.Next(2, 4));

            Dust dust = Dust.NewDustPerfect(
                rainPosition,
                DustID.Torch,
                rainVelocity,
                0,
                Color.OrangeRed * progress,
                Main.rand.NextFloat(0.5f, 1.5f) * progress
            );

            dust.noGravity = false;
            dust.fadeIn = 0.5f;
            dust.color = Color.Lerp(Color.OrangeRed, Color.Yellow, Main.rand.NextFloat(0.5f));

            dust.customData = new FireRainData { InitialPosition = rainPosition, CreationTime = Main.GameUpdateCount };
        }

        private void UpdateFireRain()
        {
            for (int i = 0; i < Main.maxDust; i++)
            {
                Dust dust = Main.dust[i];
                if (dust.active && dust.type == DustID.Torch && dust.customData is FireRainData data)
                {
                    if (Main.GameUpdateCount - data.CreationTime > FireRainLifetime)
                    {
                        dust.active = false;
                        continue;
                    }

                    Vector2 nextPosition = dust.position + dust.velocity;
                    if (IsTileCollision(nextPosition))
                    {
                        dust.scale *= 0.9f;
                        dust.velocity = Vector2.Zero;
                        if (dust.scale < 0.1f) dust.active = false;
                    }

                    if (dust.position.Y > data.InitialPosition.Y + 300) dust.active = false;
                }
            }
        }

        private bool IsTileCollision(Vector2 position)
        {
            Point tileCoords = position.ToTileCoordinates();
            return Helpers.SolidTile(tileCoords.X, tileCoords.Y);
        }

        private void DamageEnemy(Vector2 position, bool dealDamage)
        {
            for (int i = 0; i < Main.maxNPCs; i++)
            {
                NPC npc = Main.npc[i];
                if (npc.active && !npc.friendly && npc.Bottom.Y > position.Y &&
                    Math.Abs(npc.Center.X - position.X) < 100f &&
                    Math.Abs(npc.Center.Y - position.Y) < 100f)
                {
                    npc.AddBuff(BuffID.OnFire, 60);

                    if (dealDamage)
                    {
                        npc.StrikeNPC(new NPC.HitInfo
                        {
                            Damage = Main.rand.Next(21, 30),
                            Knockback = 0,
                            HitDirection = npc.direction,
                            Crit = false,
                            DamageType = DamageClass.Default
                        });
                    }
                }
            }
        }

        private class FireRainData
        {
            public Vector2 InitialPosition;
            public uint CreationTime;
        }
    }
}