using System; using Decimation.Content.Tiles.ShrineoftheMoltenOne; using Microsoft.Xna.Framework; using Terraria; using Terraria.ID; using Terraria.ModLoader; 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] = AnimationFrameCount; } public override void SetDefaults() { npc.width = 72; npc.height = 26; npc.aiStyle = -1; npc.damage = 130; npc.lifeMax = 750; 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() { 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; // 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 * Direction, 0); Vector2 projSpeed = new Vector2(5 * Direction, 0); Projectile.NewProjectile(mouthPos, projSpeed, ProjectileID.Fireball, 130, 30); } _frame = 0; } else { _frame++; } } } public override float SpawnChance(NPCSpawnInfo spawnInfo) { int x = (int) Main.LocalPlayer.position.X / 16; int y = (int) Main.LocalPlayer.position.Y / 16; int validBlockCount = 0; for (int i = -50 + x; i <= 50 + x; i++) for (int j = -50 + y; j <= 50 + y; j++) if (i >= 0 && i <= Main.maxTilesX && j >= 0 && j <= Main.maxTilesY) if (Main.tile[i, j].type == ModContent.TileType() || Main.tile[i, j].type == ModContent.TileType() || Main.tile[i, j].type == ModContent.TileType() || Main.tile[i, j].type == ModContent.TileType() || Main.tile[i, j].type == ModContent.TileType()) validBlockCount++; if (validBlockCount >= 15 && Main.hardMode) return SpawnCondition.Underworld.Chance * 2; return 0; } } }