using System; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Terraria; using Terraria.Audio; using Terraria.ModLoader; namespace Decimation.Lib.NPCs { public abstract class Worm : ModNPC { public int bodyType; public bool directional = false; public bool flies = false; /* ai[0] = follower * ai[1] = following * ai[2] = distanceFromTail * ai[3] = head */ public bool head; public int headType; public int maxLength; public int minLength; public float speed; public bool tail; public int tailType; public float turnSpeed; public LegacySoundStyle undergroundSound; public override void AI() { if (npc.localAI[1] == 0f) { npc.localAI[1] = 1f; Init(); } if (npc.ai[3] > 0f) npc.realLife = (int) npc.ai[3]; if (!head && npc.timeLeft < 300) npc.timeLeft = 300; if (npc.target < 0 || npc.target == 255 || Main.player[npc.target].dead) npc.TargetClosest(); if (Main.player[npc.target].dead && npc.timeLeft > 300) npc.timeLeft = 300; if (Main.netMode != 1) { if (!tail && npc.ai[0] == 0f) { if (head) { npc.ai[3] = npc.whoAmI; npc.realLife = npc.whoAmI; npc.ai[2] = Main.rand.Next(minLength, maxLength + 1); npc.ai[0] = NPC.NewNPC((int) (npc.position.X + npc.width / 2f), (int) (npc.position.Y + npc.height), bodyType, npc.whoAmI); } else if (npc.ai[2] > 0f) { npc.ai[0] = NPC.NewNPC((int) (npc.position.X + npc.width / 2f), (int) (npc.position.Y + npc.height), npc.type, npc.whoAmI); } else { npc.ai[0] = NPC.NewNPC((int) (npc.position.X + npc.width / 2f), (int) (npc.position.Y + npc.height), tailType, npc.whoAmI); } Main.npc[(int) npc.ai[0]].ai[3] = npc.ai[3]; Main.npc[(int) npc.ai[0]].realLife = npc.realLife; Main.npc[(int) npc.ai[0]].ai[1] = npc.whoAmI; Main.npc[(int) npc.ai[0]].ai[2] = npc.ai[2] - 1f; npc.netUpdate = true; } if (!head && (!Main.npc[(int) npc.ai[1]].active || Main.npc[(int) npc.ai[1]].type != headType && Main.npc[(int) npc.ai[1]].type != bodyType)) { npc.life = 0; npc.HitEffect(); npc.active = false; } if (!tail && (!Main.npc[(int) npc.ai[0]].active || Main.npc[(int) npc.ai[0]].type != bodyType && Main.npc[(int) npc.ai[0]].type != tailType)) { npc.life = 0; npc.HitEffect(); npc.active = false; } if (!npc.active && Main.netMode == 2) NetMessage.SendData(28, -1, -1, null, npc.whoAmI, -1f); } int num180 = (int) (npc.position.X / 16f) - 1; int num181 = (int) ((npc.position.X + npc.width) / 16f) + 2; int num182 = (int) (npc.position.Y / 16f) - 1; int num183 = (int) ((npc.position.Y + npc.height) / 16f) + 2; if (num180 < 0) num180 = 0; if (num181 > Main.maxTilesX) num181 = Main.maxTilesX; if (num182 < 0) num182 = 0; if (num183 > Main.maxTilesY) num183 = Main.maxTilesY; bool flag18 = flies; if (!flag18) for (int num184 = num180; num184 < num181; num184++) for (int num185 = num182; num185 < num183; num185++) if (Main.tile[num184, num185] != null && (Main.tile[num184, num185].nactive() && (Main.tileSolid[Main.tile[num184, num185].type] || Main.tileSolidTop[Main.tile[num184, num185].type] && Main.tile[num184, num185].frameY == 0) || Main.tile[num184, num185].liquid > 64)) { Vector2 vector17; vector17.X = num184 * 16; vector17.Y = num185 * 16; if (npc.position.X + npc.width > vector17.X && npc.position.X < vector17.X + 16f && npc.position.Y + npc.height > vector17.Y && npc.position.Y < vector17.Y + 16f) { flag18 = true; if (Main.rand.NextBool(100) && npc.behindTiles && Main.tile[num184, num185].nactive()) WorldGen.KillTile(num184, num185, true, true); if (Main.netMode != 1 && Main.tile[num184, num185].type == 2) { ushort arg_BFCA_0 = Main.tile[num184, num185 - 1].type; } } } if (!flag18 && head) { Rectangle rectangle = new Rectangle((int) npc.position.X, (int) npc.position.Y, npc.width, npc.height); int num186 = 1000; bool flag19 = true; for (int num187 = 0; num187 < 255; num187++) if (Main.player[num187].active) { Rectangle rectangle2 = new Rectangle((int) Main.player[num187].position.X - num186, (int) Main.player[num187].position.Y - num186, num186 * 2, num186 * 2); if (rectangle.Intersects(rectangle2)) { flag19 = false; break; } } if (flag19) flag18 = true; } if (directional) { if (npc.velocity.X < 0f) npc.spriteDirection = 1; else if (npc.velocity.X > 0f) npc.spriteDirection = -1; } float num188 = speed; float num189 = turnSpeed; Vector2 vector18 = new Vector2(npc.position.X + npc.width * 0.5f, npc.position.Y + npc.height * 0.5f); float num191 = Main.player[npc.target].position.X + Main.player[npc.target].width / 2; float num192 = Main.player[npc.target].position.Y + Main.player[npc.target].height / 2; num191 = (int) (num191 / 16f) * 16; num192 = (int) (num192 / 16f) * 16; vector18.X = (int) (vector18.X / 16f) * 16; vector18.Y = (int) (vector18.Y / 16f) * 16; num191 -= vector18.X; num192 -= vector18.Y; float num193 = (float) Math.Sqrt(num191 * num191 + num192 * num192); if (npc.ai[1] > 0f && npc.ai[1] < Main.npc.Length) { try { vector18 = new Vector2(npc.position.X + npc.width * 0.5f, npc.position.Y + npc.height * 0.5f); num191 = Main.npc[(int) npc.ai[1]].position.X + Main.npc[(int) npc.ai[1]].width / 2 - vector18.X; num192 = Main.npc[(int) npc.ai[1]].position.Y + Main.npc[(int) npc.ai[1]].height / 2 - vector18.Y; } catch { } npc.rotation = (float) Math.Atan2(num192, num191) + 1.57f; num193 = (float) Math.Sqrt(num191 * num191 + num192 * num192); int num194 = npc.width; num193 = (num193 - num194) / num193; num191 *= num193; num192 *= num193; npc.velocity = Vector2.Zero; npc.position.X = npc.position.X + num191; npc.position.Y = npc.position.Y + num192; if (directional) { if (num191 < 0f) npc.spriteDirection = 1; if (num191 > 0f) npc.spriteDirection = -1; } } else { if (!flag18) { npc.TargetClosest(); npc.velocity.Y = npc.velocity.Y + 0.11f; if (npc.velocity.Y > num188) npc.velocity.Y = num188; if (Math.Abs(npc.velocity.X) + Math.Abs(npc.velocity.Y) < num188 * 0.4) { if (npc.velocity.X < 0f) npc.velocity.X = npc.velocity.X - num189 * 1.1f; else npc.velocity.X = npc.velocity.X + num189 * 1.1f; } else if (npc.velocity.Y == num188) { if (npc.velocity.X < num191) npc.velocity.X = npc.velocity.X + num189; else if (npc.velocity.X > num191) npc.velocity.X = npc.velocity.X - num189; } else if (npc.velocity.Y > 4f) { if (npc.velocity.X < 0f) npc.velocity.X = npc.velocity.X + num189 * 0.9f; else npc.velocity.X = npc.velocity.X - num189 * 0.9f; } } else { if (!flies && npc.behindTiles && npc.soundDelay == 0) { npc.soundDelay = 120; Main.PlaySound(undergroundSound, npc.position); } num193 = (float) Math.Sqrt(num191 * num191 + num192 * num192); float num196 = Math.Abs(num191); float num197 = Math.Abs(num192); float num198 = num188 / num193; num191 *= num198; num192 *= num198; if (ShouldRun()) { if (Main.netMode != 1 && npc.position.Y / 16f > (Main.rockLayer + Main.maxTilesY) / 2.0) { npc.active = false; int num200 = (int) npc.ai[0]; while (num200 > 0 && num200 < 200 && Main.npc[num200].active && Main.npc[num200].aiStyle == npc.aiStyle) { int num201 = (int) Main.npc[num200].ai[0]; Main.npc[num200].active = false; npc.life = 0; if (Main.netMode == 2) NetMessage.SendData(23, -1, -1, null, num200); num200 = num201; } if (Main.netMode == 2) NetMessage.SendData(23, -1, -1, null, npc.whoAmI); } num191 = 0f; num192 = num188; } bool flag21 = false; if (npc.type == 87) { if ((npc.velocity.X > 0f && num191 < 0f || npc.velocity.X < 0f && num191 > 0f || npc.velocity.Y > 0f && num192 < 0f || npc.velocity.Y < 0f && num192 > 0f) && Math.Abs(npc.velocity.X) + Math.Abs(npc.velocity.Y) > num189 / 2f && num193 < 300f) { flag21 = true; if (Math.Abs(npc.velocity.X) + Math.Abs(npc.velocity.Y) < num188) npc.velocity *= 1.1f; } if (npc.position.Y > Main.player[npc.target].position.Y || Main.player[npc.target].position.Y / 16f > Main.worldSurface || Main.player[npc.target].dead) { flag21 = true; if (Math.Abs(npc.velocity.X) < num188 / 2f) { if (npc.velocity.X == 0f) npc.velocity.X = npc.velocity.X - npc.direction; npc.velocity.X = npc.velocity.X * 1.1f; } else { if (npc.velocity.Y > -num188) npc.velocity.Y = npc.velocity.Y - num189; } } } if (!flag21) { if (npc.velocity.X > 0f && num191 > 0f || npc.velocity.X < 0f && num191 < 0f || npc.velocity.Y > 0f && num192 > 0f || npc.velocity.Y < 0f && num192 < 0f) { if (npc.velocity.X < num191) { npc.velocity.X = npc.velocity.X + num189; } else { if (npc.velocity.X > num191) npc.velocity.X = npc.velocity.X - num189; } if (npc.velocity.Y < num192) { npc.velocity.Y = npc.velocity.Y + num189; } else { if (npc.velocity.Y > num192) npc.velocity.Y = npc.velocity.Y - num189; } if (Math.Abs(num192) < num188 * 0.2 && (npc.velocity.X > 0f && num191 < 0f || npc.velocity.X < 0f && num191 > 0f)) { if (npc.velocity.Y > 0f) npc.velocity.Y = npc.velocity.Y + num189 * 2f; else npc.velocity.Y = npc.velocity.Y - num189 * 2f; } if (Math.Abs(num191) < num188 * 0.2 && (npc.velocity.Y > 0f && num192 < 0f || npc.velocity.Y < 0f && num192 > 0f)) { if (npc.velocity.X > 0f) npc.velocity.X = npc.velocity.X + num189 * 2f; else npc.velocity.X = npc.velocity.X - num189 * 2f; } } else { if (num196 > num197) { if (npc.velocity.X < num191) npc.velocity.X = npc.velocity.X + num189 * 1.1f; else if (npc.velocity.X > num191) npc.velocity.X = npc.velocity.X - num189 * 1.1f; if (Math.Abs(npc.velocity.X) + Math.Abs(npc.velocity.Y) < num188 * 0.5) { if (npc.velocity.Y > 0f) npc.velocity.Y = npc.velocity.Y + num189; else npc.velocity.Y = npc.velocity.Y - num189; } } else { if (npc.velocity.Y < num192) npc.velocity.Y = npc.velocity.Y + num189 * 1.1f; else if (npc.velocity.Y > num192) npc.velocity.Y = npc.velocity.Y - num189 * 1.1f; if (Math.Abs(npc.velocity.X) + Math.Abs(npc.velocity.Y) < num188 * 0.5) { if (npc.velocity.X > 0f) npc.velocity.X = npc.velocity.X + num189; else npc.velocity.X = npc.velocity.X - num189; } } } } } npc.rotation = (float) Math.Atan2(npc.velocity.Y, npc.velocity.X) + 1.57f; if (head) { if (flag18) { if (npc.localAI[0] != 1f) npc.netUpdate = true; npc.localAI[0] = 1f; } else { if (npc.localAI[0] != 0f) npc.netUpdate = true; npc.localAI[0] = 0f; } if ((npc.velocity.X > 0f && npc.oldVelocity.X < 0f || npc.velocity.X < 0f && npc.oldVelocity.X > 0f || npc.velocity.Y > 0f && npc.oldVelocity.Y < 0f || npc.velocity.Y < 0f && npc.oldVelocity.Y > 0f) && !npc.justHit) { npc.netUpdate = true; return; } } } CustomBehavior(); } public virtual void Init() { } public virtual bool ShouldRun() { return false; } public virtual void CustomBehavior() { } public override bool? DrawHealthBar(byte hbPosition, ref float scale, ref Vector2 position) { return head ? (bool?) null : false; } protected void Draw(String texturePath, SpriteBatch spriteBatch, Color drawColor) { Vector2 frameSize = new Vector2(npc.width, npc.height); Texture2D texture = mod.GetTexture(texturePath); spriteBatch.Draw ( texture, new Vector2( npc.position.X - Main.screenPosition.X + frameSize.X / 2, npc.position.Y - Main.screenPosition.Y + frameSize.Y / 2 ), npc.frame, drawColor, npc.rotation, frameSize * 0.5f, npc.scale, SpriteEffects.None, 0f ); } } }