diff --git a/Content/NPCs/CoreSpider.cs b/Content/NPCs/CoreSpider.cs index 537470f..9911fa4 100644 --- a/Content/NPCs/CoreSpider.cs +++ b/Content/NPCs/CoreSpider.cs @@ -10,46 +10,170 @@ namespace Decimation.Content.NPCs // Check line 43861 of NPC.cs internal class CoreSpider : ModNPC { + private const int AnimationFps = 10; + private const int AnimationFrameCount = 8; private readonly int shootFrame = 120; private int _frame; + private int Direction + { + get => (int) npc.ai[0]; + set => npc.ai[0] = value; + } + public override void SetStaticDefaults() { DisplayName.SetDefault("Core Spider"); - Main.npcFrameCount[npc.type] = 8; + Main.npcFrameCount[npc.type] = AnimationFrameCount; } public override void SetDefaults() { - npc.CloneDefaults(NPCID.BlackRecluse); - npc.width = 84; - npc.height = 24; + npc.width = 72; + npc.height = 26; + npc.aiStyle = -1; + npc.damage = 130; npc.lifeMax = 750; - animationType = NPCID.BlackRecluse; - + npc.knockBackResist = 0.25f; npc.lavaImmune = true; + npc.buffImmune[20] = true; + npc.buffImmune[31] = false; npc.buffImmune[BuffID.OnFire] = true; npc.buffImmune[BuffID.Burning] = true; + npc.timeLeft = NPC.activeTime * 2; + } + + public override void FindFrame(int frameHeight) + { + if (++npc.frameCounter >= 60f / AnimationFps) + { + npc.frameCounter = 0; + + npc.frame.Y += frameHeight; + if (npc.frame.Y / frameHeight >= AnimationFrameCount) npc.frame.Y = 0; + } } public override void AI() { - int x = (int) npc.Center.X / 16; - int y = (int) npc.Center.Y / 16; - bool onWall = false; - for (int i = x - 1; i <= x + 1; i++) - for (int j = y - 1; j <= y + 1; j++) - if (Main.tile[i, j].wall > 0) - onWall = true; + if (npc.target >= 255) npc.TargetClosest(); + Player target = Main.player[npc.target]; + if (npc.Distance(target.position) > 480) npc.target = 255; + if (Math.Abs(target.position.Y - npc.position.Y) > 80) npc.target = 255; + if (!Collision.CanHitLine(npc.position, npc.width, npc.height, target.position, target.width, target.height)) npc.target = 255; + bool hasTarget = npc.target < 255 && target.active && !target.dead; - if (Main.expertMode) + // Walking + if (hasTarget) Direction = target.position.X - npc.position.X > 0 ? 1 : -1; + npc.velocity.X = 2 * Direction; + + Vector2 position = npc.position; + position.X += npc.velocity.X; + int frontTileX = (int) (position.X + npc.width / 2f + (npc.width / 2f + 1f) * Direction) / 16; + int frontTileY = (int) (position.Y + npc.height - 1) / 16; + Tile frontTile = Main.tile[frontTileX, frontTileY]; + Tile frontTileY1 = Main.tile[frontTileX, frontTileY - 1]; + Tile frontTileY2 = Main.tile[frontTileX, frontTileY - 2]; + Tile frontTileY3 = Main.tile[frontTileX, frontTileY - 3]; + Tile frontTileY4 = Main.tile[frontTileX, frontTileY - 4]; + Tile topTileY3 = Main.tile[frontTileX - Direction, frontTileY - 3]; + Tile bottomTile = Main.tile[frontTileX - Direction, frontTileY + 1]; + Tile frontTileX1 = Main.tile[frontTileX + Direction, frontTileY]; + Tile frontTileX1Y1 = Main.tile[frontTileX + Direction, frontTileY - 1]; + + if (frontTile == null) frontTile = new Tile(); + if (frontTileY1 == null) frontTileY1 = new Tile(); + if (frontTileY2 == null) frontTileY2 = new Tile(); + if (frontTileY3 == null) frontTileY3 = new Tile(); + if (frontTileY4 == null) frontTileY4 = new Tile(); + if (topTileY3 == null) topTileY3 = new Tile(); + if (bottomTile == null) bottomTile = new Tile(); + if (frontTileX1 == null) frontTileX1 = new Tile(); + if (frontTileX1Y1 == null) frontTileX1Y1 = new Tile(); + + if (frontTileX * 16 < position.X + npc.width && frontTileX * 16 + 16 > position.X && + (frontTile.nactive() && !frontTile.topSlope() && !frontTileY1.topSlope() && + Main.tileSolid[frontTile.type] && !Main.tileSolidTop[frontTile.type] || + frontTileY1.halfBrick() && frontTileY1.nactive()) && + (!frontTileY1.nactive() || !Main.tileSolid[frontTileY1.type] || Main.tileSolidTop[frontTileY1.type] || + frontTileY1.halfBrick() && (!frontTileY4.nactive() || !Main.tileSolid[frontTileY4.type] || + Main.tileSolidTop[frontTileY4.type])) && + (!frontTileY2.nactive() || !Main.tileSolid[frontTileY2.type] || Main.tileSolidTop[frontTileY2.type]) && + (!frontTileY3.nactive() || !Main.tileSolid[frontTileY3.type] || Main.tileSolidTop[frontTileY3.type]) && + (!topTileY3.nactive() || !Main.tileSolid[topTileY3.type])) + { + float newYPosition = frontTileY * 16; + if (frontTile.halfBrick()) newYPosition += 8f; + if (frontTileY1.halfBrick()) newYPosition -= 8f; + if (newYPosition < position.Y + npc.height) + { + float yDifference = position.Y + npc.height - newYPosition; + if (yDifference < 24.1f) + { + npc.gfxOffY += npc.position.Y + npc.height - newYPosition; + npc.position.Y = newYPosition - npc.height; + + if (yDifference < 9f) npc.stepSpeed = 1f; + else npc.stepSpeed = 2f; + } + } + } + + if ((frontTile.nactive() && !frontTile.topSlope() && Main.tileSolid[frontTile.type] && + !Main.tileSolidTop[frontTile.type] && + (frontTileY1.nactive() && !frontTileY1.topSlope() && Main.tileSolid[frontTileY1.type] && + !Main.tileSolidTop[frontTileY1.type] || frontTileY1.nactive() && frontTileY1.halfBrick()) || + frontTileX1.nactive() && !frontTileX1.topSlope() && Main.tileSolid[frontTileX1.type] && + !Main.tileSolidTop[frontTileX1.type] && + (frontTileX1Y1.nactive() && !frontTileX1Y1.topSlope() && Main.tileSolid[frontTileX1Y1.type] && + !Main.tileSolidTop[frontTileX1Y1.type] || + frontTileX1Y1.nactive() && frontTileX1Y1.halfBrick()) + ) && bottomTile.nactive() && (Main.tileSolid[bottomTile.type] || Main.tileSolidTop[bottomTile.type] || + bottomTile.halfBrick())) + { + if (!hasTarget && + frontTileY2.nactive() && !frontTileY2.topSlope() && Main.tileSolid[frontTileY2.type] && + !Main.tileSolidTop[frontTileY2.type] && + frontTileY3.nactive() && !frontTileY3.topSlope() && Main.tileSolid[frontTileY3.type] && + !Main.tileSolidTop[frontTileY3.type] && + frontTileY4.nactive() && !frontTileY4.topSlope() && Main.tileSolid[frontTileY4.type] && + !Main.tileSolidTop[frontTileY4.type] && !frontTileY4.halfBrick() + ) + { + // Turn around + Direction *= -1; + } + else + { + // Jump + npc.velocity.Y -= 1; + } + } + + if (npc.velocity.X < 0f) npc.spriteDirection = -1; + else if (npc.velocity.X > 0f) npc.spriteDirection = 1; + + int currentTileX = (int) npc.Center.X / 16; + int currentTileY = (int) npc.Center.Y / 16; + bool onWall = false; + for (int x = currentTileX - 1; x <= currentTileX + 1; x++) + { + for (int y = currentTileY - 1; y <= currentTileY + 1; y++) + { + if (Main.tile[x, y].wall > 0) onWall = true; + } + } + + if (onWall) npc.Transform(ModContent.NPCType()); + + if (Main.expertMode && hasTarget) { if (_frame >= shootFrame) { if (Main.rand.Next(4) == 0) { - Vector2 mouthPos = npc.Center + new Vector2(npc.width / 2f, 0).RotatedBy(npc.rotation); - Vector2 projSpeed = new Vector2(5, 0).RotatedBy(npc.rotation); + Vector2 mouthPos = npc.Center + new Vector2(npc.width / 2f * Direction, 0); + Vector2 projSpeed = new Vector2(5 * Direction, 0); Projectile.NewProjectile(mouthPos, projSpeed, ProjectileID.Fireball, 130, 30); } @@ -61,11 +185,6 @@ namespace Decimation.Content.NPCs _frame++; } } - - if (onWall) - npc.Transform(ModContent.NPCType()); - else - base.AI(); } public override float SpawnChance(NPCSpawnInfo spawnInfo) diff --git a/Content/NPCs/CoreSpider.png b/Content/NPCs/CoreSpider.png index 67436cb..47aeb6c 100644 Binary files a/Content/NPCs/CoreSpider.png and b/Content/NPCs/CoreSpider.png differ