using Microsoft.Xna.Framework; using Terraria; using Terraria.Audio; using Terraria.DataStructures; using Terraria.ID; using Terraria.ModLoader; namespace ForgottenWawiTech.Content.Projectiles.FragmentedPrism { public class FragmentedPrismController : ModProjectile { public const int ShardCount = 5; public const float ChargeTimePerShard = 48f; private const float ChargeDecayRate = 3f; private const int ShardSpawnDelay = 4; public static float MaxChargeTime => ChargeTimePerShard * ShardCount; private ref float SpawnTimer => ref Projectile.ai[0]; private ref float ChargeTimer => ref Projectile.ai[1]; private ref float LastFiringCount => ref Projectile.localAI[0]; public override string Texture => "Terraria/Images/Projectile_0"; public override void SetDefaults() { Projectile.width = 10; Projectile.height = 10; Projectile.friendly = false; Projectile.hostile = false; Projectile.penetrate = -1; Projectile.tileCollide = false; Projectile.ignoreWater = true; Projectile.hide = true; Projectile.DamageType = DamageClass.Magic; } public override void AI() { Player player = Main.player[Projectile.owner]; int itemType = ModContent.ItemType(); if (!player.active || player.dead || player.HeldItem.type != itemType) { Projectile.Kill(); return; } player.heldProj = Projectile.whoAmI; if (player.channel || ChargeTimer > 0f) { player.itemAnimation = player.itemTime = 2; player.SetDummyItemTime(2); } Projectile.Center = player.Center; Projectile.timeLeft = 2; if (Main.myPlayer == player.whoAmI) { SpawnTimer++; if (SpawnTimer >= ShardSpawnDelay) { SpawnTimer = 0f; TrySpawnShard(player); } } float maxCharge = MaxChargeTime; if (player.channel) { ChargeTimer = MathHelper.Clamp(ChargeTimer + 1f, 0f, maxCharge); } else { ChargeTimer = MathHelper.Clamp(ChargeTimer - ChargeDecayRate, 0f, maxCharge); } int currentFiringCount = (int)MathHelper.Clamp(ChargeTimer / ChargeTimePerShard, 0f, ShardCount); if (currentFiringCount > LastFiringCount) { SoundEngine.PlaySound(SoundID.Item117 with { Volume = 0.45f, Pitch = 0.3f }, player.Center); Projectile.netUpdate = true; } else if (currentFiringCount < LastFiringCount) { Projectile.netUpdate = true; } LastFiringCount = currentFiringCount; } public override void OnKill(int timeLeft) { if (Main.player[Projectile.owner] is not Player player) { return; } for (int i = 0; i < Main.maxProjectiles; i++) { Projectile other = Main.projectile[i]; if (other.active && other.owner == Projectile.owner && other.type == ModContent.ProjectileType()) { other.Kill(); } } } private void TrySpawnShard(Player player) { int shardType = ModContent.ProjectileType(); bool[] occupied = new bool[ShardCount]; for (int i = 0; i < Main.maxProjectiles; i++) { Projectile shard = Main.projectile[i]; if (shard.active && shard.owner == player.whoAmI && shard.type == shardType) { int slot = (int)shard.ai[0]; if (slot >= 0 && slot < ShardCount) { occupied[slot] = true; } } } IEntitySource source = player.GetSource_ItemUse_WithPotentialAmmo(player.HeldItem, AmmoID.None); bool spawnedAny = false; for (int index = 0; index < ShardCount; index++) { if (occupied[index]) { continue; } int proj = Projectile.NewProjectile(source, player.Center, Vector2.Zero, shardType, Projectile.damage, Projectile.knockBack, player.whoAmI, index); if (Main.projectile.IndexInRange(proj)) { Main.projectile[proj].originalDamage = Projectile.damage; Main.projectile[proj].ai[1] = MathHelper.TwoPi * (index / (float)ShardCount); } spawnedAny = true; } if (spawnedAny) { SoundEngine.PlaySound(SoundID.Item4 with { Volume = 0.35f, Pitch = -0.3f }, player.Center); } } } }