diff --git a/Content/NPCs/TownNPCs/Skeleton.cs b/Content/NPCs/TownNPCs/Skeleton.cs index af9cf9c..aef8fe1 100644 --- a/Content/NPCs/TownNPCs/Skeleton.cs +++ b/Content/NPCs/TownNPCs/Skeleton.cs @@ -15,7 +15,7 @@ namespace Decimation.Content.NPCs.TownNPCs [AutoloadHead] public class Skeleton : ModNPC { - private readonly List names = new List + private static readonly List Names = new List { "Tommy", "Johnny", @@ -27,34 +27,34 @@ namespace Decimation.Content.NPCs.TownNPCs public override bool Autoload(ref string name) { name = "Skeleton"; - return this.mod.Properties.Autoload; + return mod.Properties.Autoload; } public override void SetStaticDefaults() { - Main.npcFrameCount[this.npc.type] = 26; - NPCID.Sets.ExtraFramesCount[this.npc.type] = NPCID.Sets.ExtraFramesCount[NPCID.Guide]; - NPCID.Sets.AttackFrameCount[this.npc.type] = NPCID.Sets.AttackFrameCount[NPCID.Guide]; - NPCID.Sets.DangerDetectRange[this.npc.type] = 400; - NPCID.Sets.AttackType[this.npc.type] = 0; - NPCID.Sets.AttackTime[this.npc.type] = 60; - NPCID.Sets.AttackAverageChance[this.npc.type] = 30; - NPCID.Sets.HatOffsetY[this.npc.type] = 4; + Main.npcFrameCount[npc.type] = 26; + NPCID.Sets.ExtraFramesCount[npc.type] = NPCID.Sets.ExtraFramesCount[NPCID.Guide]; + NPCID.Sets.AttackFrameCount[npc.type] = NPCID.Sets.AttackFrameCount[NPCID.Guide]; + NPCID.Sets.DangerDetectRange[npc.type] = 400; + NPCID.Sets.AttackType[npc.type] = 0; + NPCID.Sets.AttackTime[npc.type] = 60; + NPCID.Sets.AttackAverageChance[npc.type] = 30; + NPCID.Sets.HatOffsetY[npc.type] = 4; } public override void SetDefaults() { - NPCID.Sets.AttackType[this.npc.type] = 0; - this.npc.CloneDefaults(NPCID.Guide); - this.npc.townNPC = true; - this.npc.friendly = true; - this.npc.aiStyle = 7; - this.npc.damage = 10; - this.npc.defense = 15; - this.npc.lifeMax = 250; - this.npc.HitSound = SoundID.DD2_SkeletonHurt; - this.npc.DeathSound = SoundID.DD2_SkeletonDeath; - this.npc.knockBackResist = 0.5f; + NPCID.Sets.AttackType[npc.type] = 0; + npc.CloneDefaults(NPCID.Guide); + npc.townNPC = true; + npc.friendly = true; + npc.aiStyle = 7; + npc.damage = 10; + npc.defense = 15; + npc.lifeMax = 250; + npc.HitSound = SoundID.DD2_SkeletonHurt; + npc.DeathSound = SoundID.DD2_SkeletonDeath; + npc.knockBackResist = 0.5f; animationType = NPCID.Guide; } @@ -90,7 +90,7 @@ namespace Decimation.Content.NPCs.TownNPCs public override string TownNPCName() { - return names[Main.rand.Next(5)]; + return Names[Main.rand.Next(5)]; } public override string GetChat() diff --git a/Content/NPCs/TownNPCs/Skeleton.png b/Content/NPCs/TownNPCs/Skeleton.png index 720a0b1..2661dc0 100644 Binary files a/Content/NPCs/TownNPCs/Skeleton.png and b/Content/NPCs/TownNPCs/Skeleton.png differ diff --git a/Content/NPCs/TownNPCs/Skeleton_Head.png b/Content/NPCs/TownNPCs/Skeleton_Head.png index e4e61c0..f1349fe 100644 Binary files a/Content/NPCs/TownNPCs/Skeleton_Head.png and b/Content/NPCs/TownNPCs/Skeleton_Head.png differ diff --git a/Content/Projectiles/Bone.png b/Content/Projectiles/Bone.png index 6ff2fcd..bdf75ba 100644 Binary files a/Content/Projectiles/Bone.png and b/Content/Projectiles/Bone.png differ diff --git a/Content/Projectiles/SkeletonBone.cs b/Content/Projectiles/SkeletonBone.cs index 6cc1873..7184571 100644 --- a/Content/Projectiles/SkeletonBone.cs +++ b/Content/Projectiles/SkeletonBone.cs @@ -1,16 +1,64 @@ -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 SkeletonBone : DecimationProjectile + internal class SkeletonBone : 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 NPC TargetNPC => Main.npc[Target]; protected override void Init() { @@ -20,76 +68,108 @@ namespace Decimation.Content.Projectiles projectile.ignoreWater = true; projectile.tileCollide = false; DamageType = DecimationWeapon.DamageType.Ranged; - projectile.penetrate = 2; - projectile.timeLeft = 60; + projectile.penetrate = -1; + projectile.damage = 0; + projectile.timeLeft = 600; + projectile.friendly = false; + projectile.hostile = false; + projectile.damage = 80; 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 (timeLeft < 10) + if (Counter > IdlingCounterMax) { - projectile.ai[1]++; - timeLeft = 600; - projectile.velocity *= 0; + Counter = 0; + State = AiState.Targeting; } + + Counter++; } - else if (projectile.ai[1] == 1) + else if (State == AiState.Targeting) { - if (Main.netMode != 1) - counter++; + projectile.velocity *= 0f; + projectile.rotation += MathHelper.Pi * (1 / 64f) * (1 + Counter / 10); - projectile.localAI[0] += 4; - - if (counter >= 60) + if (Counter > TargetingCounterMax) { - projectile.ai[1]++; - counter = 0; + FindTarget(); + + State = AiState.Attacking; } + + Counter++; } - else if (projectile.ai[1] == 2) + else if (State == AiState.Attacking) { - NPC target = NPC.get - Vector2 velocity = target.position - projectile.position; - - float magnitude = (float)Math.Sqrt(velocity.X * velocity.X + velocity.Y * velocity.Y); - if (magnitude > maxSpeed) + if (Target >= 255) { - float ratio = maxSpeed / magnitude; - velocity.X *= ratio; - velocity.Y *= ratio; + projectile.Kill(); + return; } + Vector2 velocity = TargetNPC.Center - projectile.Center; + velocity.Normalize(); + velocity *= AttackingVelocity; + + projectile.friendly = true; + projectile.penetrate = 1; projectile.velocity = velocity; - projectile.ai[1]++; - }*/ + 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, 125); + Main.dust[dust].noGravity = true; + Lighting.AddLight(projectile.Center, LightingUtils.Rgb255ToRgb1(143, 214, 255)); } - 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, 135, + projectile.scale * 4f); } 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.npc.Length; i++) + { + NPC npc = Main.npc[i]; + if (npc != null && npc.active && !npc.townNPC && npc.damage > 0 && projectile.CanHit(npc)) + { + float distance = projectile.Distance(npc.Center); + if (distance < 400f && 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.png b/Content/Projectiles/SkeletonBone.png index cf78ad5..dedc0df 100644 Binary files a/Content/Projectiles/SkeletonBone.png and b/Content/Projectiles/SkeletonBone.png differ