Decimation_Mod/Content/NPCs/CoreSpider.cs
2020-07-06 14:11:49 -04:00

212 lines
9.4 KiB
C#

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<CoreSpiderWall>());
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<ShrineBrick>() ||
Main.tile[i, j].type == ModContent.TileType<LockedShrineDoor>() ||
Main.tile[i, j].type == ModContent.TileType<ShrineDoorClosed>() ||
Main.tile[i, j].type == ModContent.TileType<ShrineDoorOpened>() ||
Main.tile[i, j].type == ModContent.TileType<RedHotSpike>())
validBlockCount++;
if (validBlockCount >= 15 && Main.hardMode)
return SpawnCondition.Underworld.Chance * 2;
return 0;
}
}
}