Updated Skeleton Town NPC.
@ -15,7 +15,7 @@ namespace Decimation.Content.NPCs.TownNPCs
|
||||
[AutoloadHead]
|
||||
public class Skeleton : ModNPC
|
||||
{
|
||||
private readonly List<string> names = new List<string>
|
||||
private static readonly List<string> Names = new List<string>
|
||||
{
|
||||
"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()
|
||||
|
||||
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 321 B After Width: | Height: | Size: 420 B |
|
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 325 B |
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 292 B |