using System; using Microsoft.Xna.Framework; using Terraria; using Terraria.DataStructures; using Terraria.ID; using Terraria.ModLoader; using ForgottenWawiTech.Content.Projectiles.Transcendent; namespace ForgottenWawiTech.Content.Players { public class TranscendentPlayer : ModPlayer { private const int AccessoryShardInterval = 90; private const int SetShardInterval = 45; private const int AccessoryShardBaseDamage = 220; private const int SetShardBaseDamage = 320; private const int AscendantDroneCount = 4; private const int AscendantDroneBaseDamage = 360; private const int NaniteShardBaseDamage = 260; public bool SwarmModuleEquipped; private Item swarmAccessorySourceItem; private int swarmTimer; private int naniteShardCooldown; private bool transcendentSetActive; public void HandleSwarmAccessory(Item sourceItem) { SwarmModuleEquipped = true; swarmAccessorySourceItem = sourceItem; } public void EnableTranscendentSet() { transcendentSetActive = true; } public bool HasTranscendentSet => transcendentSetActive; public override void ResetEffects() { SwarmModuleEquipped = false; transcendentSetActive = false; swarmAccessorySourceItem = null; } public override void PostUpdate() { bool swarmActive = SwarmModuleEquipped || transcendentSetActive; if (swarmActive && Player.whoAmI == Main.myPlayer) { int interval = transcendentSetActive ? SetShardInterval : AccessoryShardInterval; swarmTimer++; if (swarmTimer >= interval) { swarmTimer = 0; SpawnAscendantShards(transcendentSetActive); } } else if (Player.whoAmI == Main.myPlayer && swarmTimer > 0) { swarmTimer = 0; } if (naniteShardCooldown > 0) { naniteShardCooldown--; } if (transcendentSetActive) { MaintainAscendantDrones(); } if (swarmActive) { if (Main.rand.NextBool(transcendentSetActive ? 4 : 6)) { Dust dust = Dust.NewDustDirect(Player.position, Player.width, Player.height, DustID.RainbowTorch, Player.velocity.X * 0.2f, Player.velocity.Y * 0.2f, 150, default, 1.1f); dust.noGravity = true; } } } private void SpawnAscendantShards(bool fromSet) { int baseDamage = fromSet ? SetShardBaseDamage : AccessoryShardBaseDamage; int damage = (int)Player.GetDamage(DamageClass.Summon).ApplyTo(baseDamage); float knockBack = fromSet ? 4f : 3f; float speed = fromSet ? 8f : 6f; int shardCount = fromSet ? 2 : 1; if (!fromSet && swarmAccessorySourceItem == null) { swarmAccessorySourceItem = Player.HeldItem; } IEntitySource source = fromSet ? Player.GetSource_Misc("TranscendentAscendantSwarm") : Player.GetSource_Accessory(swarmAccessorySourceItem ?? Player.HeldItem); for (int i = 0; i < shardCount; i++) { Vector2 velocity = Main.rand.NextVector2Circular(speed, speed); if (velocity.LengthSquared() < 0.01f) { velocity = new Vector2(0f, -speed); } Projectile shard = Projectile.NewProjectileDirect( source, Player.Center, velocity, ModContent.ProjectileType(), damage, knockBack, Player.whoAmI); shard.originalDamage = damage; } } private void MaintainAscendantDrones() { if (Player.whoAmI != Main.myPlayer) { return; } int droneType = ModContent.ProjectileType(); int owned = Player.ownedProjectileCounts[droneType]; if (owned >= AscendantDroneCount) { return; } var source = Player.GetSource_Misc("TranscendentAscendantDrones"); for (int i = owned; i < AscendantDroneCount; i++) { Projectile.NewProjectile( source, Player.Center, Vector2.Zero, droneType, 0, 0f, Player.whoAmI, i, AscendantDroneCount); } } public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone) { TrySpawnNaniteShards(target.Center, damageDone); } public override void OnHitNPCWithProj(Projectile proj, NPC target, NPC.HitInfo hit, int damageDone) { if (proj.owner != Player.whoAmI || !proj.friendly) { return; } if (proj.type == ModContent.ProjectileType() || proj.type == ModContent.ProjectileType() || proj.type == ModContent.ProjectileType()) { return; } TrySpawnNaniteShards(target.Center, damageDone); } private void TrySpawnNaniteShards(Vector2 position, int damageDone) { if (!transcendentSetActive || Player.whoAmI != Main.myPlayer) { return; } if (damageDone <= 0 || naniteShardCooldown > 0) { return; } naniteShardCooldown = 8; int baseDamage = GetNaniteShardDamage(Player); int computed = Math.Max(baseDamage, damageDone / 2); float speed = 13f; var source = Player.GetSource_Misc("TranscendentNaniteShards"); for (int i = 0; i < 2; i++) { Vector2 velocity = Main.rand.NextVector2CircularEdge(1f, 1f) * speed; if (velocity.LengthSquared() < 0.01f) { velocity = new Vector2(0f, -speed); } Projectile shard = Projectile.NewProjectileDirect( source, position, velocity, ModContent.ProjectileType(), computed, 2f, Player.whoAmI); shard.originalDamage = computed; } } public static int GetAscendantDroneDamage(Player player) { return (int)player.GetTotalDamage(DamageClass.Summon).ApplyTo(AscendantDroneBaseDamage); } public static int GetNaniteShardDamage(Player player) { return (int)player.GetTotalDamage(DamageClass.Generic).ApplyTo(NaniteShardBaseDamage); } } }