diff --git a/Content/NPCs/NecroCaster.cs b/Content/NPCs/NecroCaster.cs index 61f9f70..ad707ae 100644 --- a/Content/NPCs/NecroCaster.cs +++ b/Content/NPCs/NecroCaster.cs @@ -33,8 +33,8 @@ namespace Decimation.Content.NPCs npc.buffImmune[BuffID.ShadowFlame] = true; npc.value = 10000; npc.damage = 15; - npc.HitSound = SoundID.NPCHit1; - npc.DeathSound = SoundID.NPCDeath1; + npc.HitSound = SoundID.DD2_SkeletonHurt; + npc.DeathSound = SoundID.DD2_SkeletonDeath; animationType = NPCID.Necromancer; } diff --git a/Content/Projectiles/Bone.cs b/Content/Projectiles/Bone.cs index 77d217e..7d1ef25 100644 --- a/Content/Projectiles/Bone.cs +++ b/Content/Projectiles/Bone.cs @@ -1,17 +1,64 @@ -using Microsoft.Xna.Framework; -using System; -using System.IO; -using Decimation.Content.Items.Weapons; -using Decimation.Lib.Items; +using Decimation.Lib.Items; +using Decimation.Lib.Util; +using Microsoft.Xna.Framework; using Terraria; using Terraria.ID; -using Terraria.ModLoader; namespace Decimation.Content.Projectiles { - internal class Bone : DecimationProjectile + internal class Bone : DecimationProjectile { - private float maxSpeed = 5f; + 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() { @@ -23,76 +70,112 @@ namespace Decimation.Content.Projectiles DamageType = DecimationWeapon.DamageType.Ranged; projectile.hostile = true; projectile.friendly = false; - projectile.penetrate = 2; - projectile.timeLeft = 60; - + projectile.penetrate = -1; + projectile.hostile = false; + projectile.friendly = false; + projectile.timeLeft = 600; Damages = Main.expertMode ? 57 : 20; - projectile.localAI[0] = 15; + Target = 255; } - // ai 0: target, ai 1: state, localAI 0: rotation - - private int counter = 0; - public override void AI() { - if (projectile.ai[1] == 0) + if (State == AiState.Idling) { - projectile.localAI[0] = 15; + projectile.rotation += MathHelper.Pi * (1 / 64f); + projectile.velocity.Normalize(); + projectile.velocity *= IdlingVelocity; - if (projectile.timeLeft < 10) + if (Counter > IdlingCounterMax) { - projectile.ai[1]++; - projectile.timeLeft = 600; - projectile.velocity *= 0; - } - } - else if (projectile.ai[1] == 1) - { - if (Main.netMode != 1) - counter++; - - projectile.localAI[0] += 4; - - if (counter >= 60) - { - projectile.ai[1]++; - counter = 0; - } - } - else if (projectile.ai[1] == 2) - { - Player target = Main.player[(int)projectile.ai[0]]; - Vector2 velocity = target.position - projectile.position; - - float magnitude = (float)Math.Sqrt(velocity.X * velocity.X + velocity.Y * velocity.Y); - if (magnitude > maxSpeed) - { - float ratio = maxSpeed / magnitude; - velocity.X *= ratio; - velocity.Y *= ratio; + Counter = 0; + State = AiState.Targeting; } - projectile.velocity = velocity; - projectile.ai[1]++; + 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); } - projectile.rotation += (float)(Math.PI / projectile.localAI[0]); + 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 SendExtraAI(BinaryWriter writer) + public override void Kill(int timeLeft) { - writer.Write(counter); - } - - public override void ReceiveExtraAI(BinaryReader reader) - { - counter = reader.ReadInt32(); + 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 + } } -} +} \ No newline at end of file diff --git a/Content/Projectiles/SkeletonBone.cs b/Content/Projectiles/SkeletonBone.cs index 7184571..7483b3c 100644 --- a/Content/Projectiles/SkeletonBone.cs +++ b/Content/Projectiles/SkeletonBone.cs @@ -103,6 +103,20 @@ namespace Decimation.Content.Projectiles if (Counter > TargetingCounterMax) { FindTarget(); + + if (TargetNPC == null || !TargetNPC.active) + { + projectile.Kill(); + return; + } + + Vector2 velocity = TargetNPC.Center - projectile.Center; + velocity.Normalize(); + velocity *= AttackingVelocity; + + projectile.friendly = true; + projectile.penetrate = 1; + projectile.velocity = velocity; State = AiState.Attacking; } @@ -111,23 +125,16 @@ namespace Decimation.Content.Projectiles } else if (State == AiState.Attacking) { - if (Target >= 255) + if (TargetNPC == null || !TargetNPC.active) { projectile.Kill(); return; } - - Vector2 velocity = TargetNPC.Center - projectile.Center; - velocity.Normalize(); - velocity *= AttackingVelocity; - - projectile.friendly = true; - projectile.penetrate = 1; - projectile.velocity = velocity; + projectile.rotation += MathHelper.Pi * (1 / 64f) * (1 + Counter / 10); } - int dust = Dust.NewDust(projectile.position, projectile.width, projectile.height, 125); + int dust = Dust.NewDust(projectile.position, projectile.width, projectile.height, 135); Main.dust[dust].noGravity = true; Lighting.AddLight(projectile.Center, LightingUtils.Rgb255ToRgb1(143, 214, 255)); }