using Decimation.Lib.Items; using Decimation.Lib.Util; using Microsoft.Xna.Framework; using Terraria; using Terraria.ID; namespace Decimation.Content.Projectiles.NPC { internal class Bone : DecimationProjectile { private const int IdlingCounterMax = 60; private const int TargetingCounterMax = 90; private const float IdlingVelocity = 5f; private const float AttackingVelocity = 10f; private AiState State { get { { switch ((int) projectile.ai[0]) { case 0: return AiState.Idling; case 1: return AiState.Targeting; default: return AiState.Attacking; } } } set { int state; switch (value) { case AiState.Idling: state = 0; break; case AiState.Targeting: state = 1; break; default: state = 2; break; } projectile.ai[0] = state; } } private int Counter { get => (int) projectile.ai[1]; set => projectile.ai[1] = value; } private int Target { get => (int) projectile.localAI[0]; set => projectile.localAI[0] = value; } private Player TargetPlayer => Main.player[Target]; protected override void Init() { projectile.width = 14; projectile.height = 34; projectile.aiStyle = -1; projectile.ignoreWater = true; projectile.tileCollide = false; DamageType = DecimationWeapon.DamageType.Ranged; projectile.hostile = true; projectile.friendly = false; projectile.penetrate = -1; projectile.hostile = false; projectile.friendly = false; projectile.timeLeft = 600; Damages = Main.expertMode ? 57 : 20; Target = 255; } public override void AI() { if (State == AiState.Idling) { projectile.rotation += MathHelper.Pi * (1 / 64f); projectile.velocity.Normalize(); projectile.velocity *= IdlingVelocity; if (Counter > IdlingCounterMax) { Counter = 0; State = AiState.Targeting; } Counter++; } else if (State == AiState.Targeting) { projectile.velocity *= 0f; projectile.rotation += MathHelper.Pi * (1 / 64f) * (1 + Counter / 10); if (Counter > TargetingCounterMax) { FindTarget(); if (TargetPlayer == null || !TargetPlayer.active || TargetPlayer.dead) { projectile.Kill(); return; } Vector2 velocity = TargetPlayer.Center - projectile.Center; velocity.Normalize(); velocity *= AttackingVelocity; projectile.hostile = true; projectile.velocity = velocity; projectile.penetrate = 1; State = AiState.Attacking; } Counter++; } else if (State == AiState.Attacking) { if (TargetPlayer == null || !TargetPlayer.active || TargetPlayer.dead) { projectile.Kill(); return; } projectile.rotation += MathHelper.Pi * (1 / 64f) * (1 + Counter / 10); } int dust = Dust.NewDust(projectile.position, projectile.width, projectile.height, DustID.Blood); Main.dust[dust].noGravity = true; Lighting.AddLight(projectile.Center, LightingUtils.Rgb255ToRgb1(158, 6, 6)); } public override void Kill(int timeLeft) { DustUtils.NewDustCircle(8, projectile.position, projectile.width, projectile.height, DustID.Blood, projectile.scale * 2f); } public override void OnHitPlayer(Player target, int damage, bool crit) { if (Main.expertMode && Main.rand.Next(100) < 35) target.AddBuff(BuffID.Confused, 600); } private void FindTarget() { if (Target >= 255) { float lastDistance = float.MaxValue; for (int i = 0; i < Main.player.Length; i++) { Player player = Main.player[i]; if (player != null && player.active && !player.dead) { float distance = projectile.Distance(player.Center); if (distance < lastDistance) { lastDistance = distance; Target = i; } } } } } private enum AiState { Idling = 0, Targeting = 1, Attacking = 2 } } }