170 lines
6.6 KiB
C#
170 lines
6.6 KiB
C#
using Decimation.Content.Tiles.ShrineoftheMoltenOne;
|
|
using Decimation.Lib.Util;
|
|
using Microsoft.Xna.Framework;
|
|
using Terraria;
|
|
using Terraria.ID;
|
|
using Terraria.ModLoader;
|
|
|
|
namespace Decimation.Content.NPCs
|
|
{
|
|
// Check line 43861 of NPC.cs
|
|
internal class CoreSpiderWall : ModNPC
|
|
{
|
|
private const int AnimationFps = 10;
|
|
private const int AnimationFrameCount = 4;
|
|
private const float Speed = 2;
|
|
private const int ShootInterval = 120;
|
|
private int _frame;
|
|
|
|
public override void SetStaticDefaults()
|
|
{
|
|
DisplayName.SetDefault("Core Spider");
|
|
Main.npcFrameCount[npc.type] = AnimationFrameCount;
|
|
}
|
|
|
|
public override void SetDefaults()
|
|
{
|
|
npc.width = 52;
|
|
npc.height = 52;
|
|
npc.aiStyle = -1;
|
|
npc.lifeMax = 750;
|
|
npc.knockBackResist = 0.25f;
|
|
npc.lavaImmune = true;
|
|
npc.value = 7000;
|
|
npc.buffImmune[20] = true;
|
|
npc.buffImmune[31] = false;
|
|
npc.buffImmune[BuffID.OnFire] = true;
|
|
npc.buffImmune[BuffID.Burning] = true;
|
|
npc.timeLeft = NPC.activeTime * 2;
|
|
npc.noGravity = true;
|
|
npc.HitSound = SoundID.NPCHit19;
|
|
npc.DeathSound = SoundID.NPCDeath12;
|
|
}
|
|
|
|
public override bool PreAI()
|
|
{
|
|
Lighting.AddLight(npc.Center, LightingUtils.Rgb255ToRgb1(255, 155, 48));
|
|
return true;
|
|
}
|
|
|
|
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 (!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;
|
|
|
|
// Rotation
|
|
if (hasTarget)
|
|
{
|
|
Vector2 distance = target.Center - npc.Center;
|
|
if (distance.Length() > 0)
|
|
{
|
|
float rotation = distance.ToRotation();
|
|
npc.rotation = rotation;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
npc.rotation += Main.rand.NextFloat(-0.05f, 0.05f);
|
|
}
|
|
|
|
Vector2 velocity = new Vector2(1, 0);
|
|
velocity.Normalize();
|
|
velocity *= Speed;
|
|
npc.velocity = velocity.RotatedBy(npc.rotation);
|
|
|
|
if (!hasTarget)
|
|
{
|
|
Vector2 frontTilePosition = npc.Center;
|
|
frontTilePosition += new Vector2(npc.width / 2f + 16, 0).RotatedBy(npc.rotation);
|
|
int frontTileX = (int) frontTilePosition.X / 16;
|
|
int frontTileY = (int) frontTilePosition.Y / 16;
|
|
Tile frontTile = Main.tile[frontTileX, frontTileY];
|
|
Tile frontTileY1 = Main.tile[frontTileX, frontTileY + 1];
|
|
Tile frontTileY2 = Main.tile[frontTileX, frontTileY - 1];
|
|
|
|
if (frontTile == null) frontTile = new Tile();
|
|
if (frontTileY1.nactive() && Main.tileSolid[frontTileY1.type] &&
|
|
!Main.tileSolidTop[frontTileY1.type] &&
|
|
(!frontTileY2.nactive() || !Main.tileSolid[frontTileY2.type] ||
|
|
Main.tileSolidTop[frontTileY2.type]))
|
|
npc.rotation += MathHelper.PiOver2;
|
|
else if (frontTileY2.nactive() && Main.tileSolid[frontTileY2.type] &&
|
|
!Main.tileSolidTop[frontTileY2.type] &&
|
|
(!frontTileY1.nactive() || !Main.tileSolid[frontTileY1.type] ||
|
|
Main.tileSolidTop[frontTileY1.type]))
|
|
npc.rotation -= MathHelper.PiOver2;
|
|
else if (frontTile.nactive() && Main.tileSolid[frontTile.type] && !Main.tileSolidTop[frontTile.type])
|
|
npc.rotation += MathHelper.Pi;
|
|
}
|
|
|
|
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<CoreSpider>());
|
|
|
|
if (Main.expertMode && hasTarget)
|
|
{
|
|
if (_frame >= ShootInterval)
|
|
{
|
|
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);
|
|
|
|
Projectile.NewProjectile(mouthPos, projSpeed, ProjectileID.Fireball, 130, 30);
|
|
}
|
|
|
|
_frame = 0;
|
|
}
|
|
else
|
|
{
|
|
_frame++;
|
|
}
|
|
}
|
|
|
|
if (npc.spriteDirection == -1) npc.spriteDirection = 1;
|
|
}
|
|
|
|
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 bool CheckConditions(int left, int right, int top, int bottom)
|
|
{
|
|
int x = (int) Main.LocalPlayer.position.X / 16;
|
|
int y = (int) Main.LocalPlayer.position.Y / 16;
|
|
|
|
int validBlockCount = 0;
|
|
for (int i = (int) (-50 + x / 16f); i <= (int) (50 + x / 16f); i++)
|
|
for (int j = (int) (-50 + y / 16f); j <= (int) (50 + y / 16f); 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++;
|
|
|
|
return validBlockCount >= 15 && Main.hardMode;
|
|
}
|
|
}
|
|
} |