Decimation_Mod/Content/NPCs/Arachnus/Arachnus.cs
2020-06-05 21:35:06 -04:00

379 lines
13 KiB
C#

using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.IO;
using Decimation.Content.Buffs.Debuffs;
using Decimation.Content.Items.Boss.Arachnus;
using Decimation.Content.Items.Misc.Souls;
using Decimation.Content.Items.Weapons.Arachnus;
using Decimation.Content.Projectiles;
using Decimation.Content.Tiles.ShrineoftheMoltenOne;
namespace Decimation.Content.NPCs.Arachnus
{
[AutoloadBossHead]
class Arachnus : ModNPC
{
private int counter = 0;
private int counterMax = 1320;
private float speed = 2;
public override void SetStaticDefaults()
{
DisplayName.SetDefault("Arachnus");
Main.npcFrameCount[npc.type] = 4;
}
public override void SetDefaults()
{
npc.aiStyle = -1;
npc.lifeMax = 80000;
npc.damage = 100;
npc.defense = 25;
npc.knockBackResist = 0f;
npc.width = 200;
npc.height = 200;
npc.value = 50000;
npc.npcSlots = 1f;
npc.boss = true;
npc.lavaImmune = true;
npc.noGravity = true;
npc.noTileCollide = false; // When not enraged
npc.HitSound = SoundID.NPCHit6;
npc.DeathSound = SoundID.NPCDeath10;
music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/Drums_of_hell");
bossBag = ModContent.ItemType<ArachnusTreasureBag>();
npc.lavaImmune = true;
npc.buffImmune[BuffID.OnFire] = true;
npc.buffImmune[BuffID.Burning] = true;
}
public override void ScaleExpertStats(int numPlayers, float bossLifeScale)
{
npc.lifeMax = (int) (npc.lifeMax * 0.625f * bossLifeScale);
npc.damage = (int) (npc.damage * 0.6f);
npc.defense = (int) (npc.defense + numPlayers * 2);
}
private bool CheckDispawn()
{
bool playersActive = false;
bool playersDead = true;
foreach (Player player in Main.player)
{
if (player.active) playersActive = true;
if (!player.dead) playersDead = false;
}
return playersDead || !playersActive;
}
private void Move()
{
// Rotate to player
Vector2 moveTo = Main.player[npc.target].Center - npc.Center;
float angle = (float) Math.Atan2(moveTo.Y, moveTo.X);
npc.rotation = (float) (angle + Math.PI * 0.5f);
// Move
Vector2 move = moveTo;
float magnitude = (float) Math.Sqrt(move.X * move.X + move.Y * move.Y);
if (magnitude > speed)
{
move *= speed / magnitude;
}
float turnResistance = 50f;
move = (npc.velocity * turnResistance + move) / (turnResistance + 1f);
magnitude = (float) Math.Sqrt(move.X * move.X + move.Y * move.Y);
if (magnitude > speed)
{
move *= speed / magnitude;
}
npc.velocity = npc.ai[1] != 99 ? move : new Vector2(0, 0);
}
private bool CheckForShrine()
{
bool tooFarFromShrine = true;
if (counter % 60 == 0)
{
int validBlockCount = 0;
for (int i = (int) (-50 + npc.Center.X / 16f); i <= (int) (50 + npc.Center.X / 16f); i++)
{
for (int j = (int) (-50 + npc.Center.Y / 16f); j <= (int) (50 + npc.Center.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>() ||
Main.tile[i, j].type == ModContent.TileType<ShrineAltar>())
validBlockCount++;
}
}
}
if (validBlockCount < 15)
tooFarFromShrine = true;
else
tooFarFromShrine = false;
}
else
{
return npc.ai[2] == 1;
}
return tooFarFromShrine;
}
private void CheckEnraged()
{
npc.ai[2] = !Main.player[npc.target].ZoneUnderworldHeight ||
!Collision.CanHit(npc.Center, 0, 0, Main.player[npc.target].Center, 0, 0) || CheckForShrine()
? 1
: 0;
}
public override void AI()
{
if (CheckDispawn())
{
npc.velocity = new Vector2(0, 10f);
npc.noTileCollide = true;
if (npc.timeLeft > 10)
{
npc.timeLeft = 10;
}
}
npc.TargetClosest(true);
CheckEnraged();
// Normal ai
if (npc.ai[0] == 0)
{
float mouthX = (float) (((npc.height) / 2) * Math.Cos(npc.rotation - Math.PI * 0.5f)) + npc.Center.X;
float mouthY = (float) (((npc.height) / 2) * Math.Sin(npc.rotation - Math.PI * 0.5f)) + npc.Center.Y;
//Counter
if (npc.life <= npc.lifeMax / 2) counterMax = 1500;
if (counter >= counterMax && Main.netMode != 1)
{
counter = 0;
npc.netUpdate = true;
}
// Fireballs
if (counter <= 600) npc.ai[1] = 0;
else if (counter > 600 && counter < 800) npc.ai[1] = 98;
// Blast of Heat
else if (counter >= 800 && counter <= 1100)
{
npc.ai[1] = 1;
}
// Increase speed
else if (counter > 1320 && counter <= 1500 ||
(Main.expertMode && counter > 600 && counter < 800 && npc.life <= npc.lifeMax / 4))
{
if (counter == 1321)
{
if (Main.netMode == NetmodeID.SinglePlayer)
Main.PlaySound(SoundID.Roar, (int) npc.position.X, (int) npc.position.Y, 0);
if (Main.netMode == NetmodeID.Server) GetPacket(ArachnusMessageType.RoarSound).Send();
}
npc.ai[1] = 2;
}
else npc.ai[1] = 99;
if (counter % 40 == 0 && npc.ai[1] == 0 && Main.netMode != 1)
{
float speedX = (float) (6 * Math.Cos(npc.rotation - Math.PI * 0.5f)) * 2;
float speedY = (float) (6 * Math.Sin(npc.rotation - Math.PI * 0.5f)) * 2;
Projectile.NewProjectile(new Vector2(mouthX, mouthY), new Vector2(speedX, speedY),
ModContent.ProjectileType<ArachnusFireball>(), 30, 0f);
}
else if (counter % 5 == 0 && npc.ai[1] == 1)
{
if (Main.netMode != 1)
{
float speedX = (float) (7 * Math.Cos(npc.rotation - Math.PI * 0.5f));
float speedY = (float) (7 * Math.Sin(npc.rotation - Math.PI * 0.5f));
Projectile.NewProjectile(new Vector2(mouthX, mouthY), new Vector2(speedX, speedY),
npc.ai[2] == 1
? ModContent.ProjectileType<BlastofShadowFlame>()
: ModContent.ProjectileType<BlastofHeat>(), 30, 0f, 255);
}
Main.PlaySound(SoundID.Item34, npc.position);
if (Main.netMode == 2)
GetPacket(ArachnusMessageType.FlamesSound).Send();
}
else if (npc.ai[1] == 2)
{
speed = 20f;
if (Main.expertMode)
{
speed = (npc.lifeMax - npc.life) / 500;
if (npc.ai[2] == 1)
speed += 20;
}
else if (npc.ai[2] == 1)
speed = 40f;
}
if (npc.ai[1] != 2)
{
speed = 2f;
}
// Enraged
if (npc.ai[2] == 1)
{
npc.noTileCollide = true;
Dust.NewDust(npc.position, npc.width, npc.height, DustID.Shadowflame);
if (npc.ai[1] != 2)
{
speed = 6f;
npc.defense = 300;
}
}
counter++;
}
Move();
}
public override void SendExtraAI(BinaryWriter writer)
{
writer.Write(counter);
writer.Write(counterMax);
writer.Write(speed);
}
public override void ReceiveExtraAI(BinaryReader reader)
{
counter = reader.ReadInt32();
counterMax = reader.ReadInt32();
speed = reader.ReadSingle();
}
private ModPacket GetPacket(ArachnusMessageType type)
{
ModPacket packet = mod.GetPacket();
packet.Write((byte) DecimationModMessageType.Arachnus);
packet.Write(npc.whoAmI);
packet.Write((byte) type);
return packet;
}
public void HandlePacket(BinaryReader reader)
{
ArachnusMessageType type = (ArachnusMessageType) reader.ReadByte();
switch (type)
{
case ArachnusMessageType.RoarSound:
Main.PlaySound(SoundID.Roar, (int) npc.position.X, (int) npc.position.Y, 0);
break;
case ArachnusMessageType.FlamesSound:
Main.PlaySound(SoundID.Item34, npc.position);
break;
}
}
public override void OnHitPlayer(Player target, int damage, bool crit)
{
if (npc.ai[1] == 2 && Main.expertMode)
{
target.AddBuff(ModContent.BuffType<Hyperthermic>(), 900);
}
base.OnHitPlayer(target, damage, crit);
}
public override void FindFrame(int frameHeight)
{
npc.frameCounter += 3f;
if (npc.frameCounter >= 40)
npc.frameCounter = 0;
npc.frame.Y = ((int) npc.frameCounter / 10) * frameHeight;
}
public override void NPCLoot()
{
Item.NewItem(npc.Center, ModContent.ItemType<SoulofSpite>(), Main.rand.Next(15, 31));
if (!Main.expertMode)
{
int rand = Main.rand.Next(3);
if (rand == 0)
Item.NewItem(npc.Center, ModContent.ItemType<ChainStynger>());
else if (rand == 1)
Item.NewItem(npc.Center, ModContent.ItemType<GlaiveWeaver>());
else if (rand == 2)
Item.NewItem(npc.Center, ModContent.ItemType<Infernolizer>());
}
else
{
npc.DropBossBags();
}
}
public override void BossLoot(ref string name, ref int potionType)
{
name = "Arachnus";
// Maybe better
potionType = ItemID.SuperHealingPotion;
DecimationWorld.downedArachnus = true;
}
public override bool? DrawHealthBar(byte hbPosition, ref float scale, ref Vector2 position)
{
scale = 1.5f;
return null;
}
public override bool PreDraw(SpriteBatch spriteBatch, Color drawColor)
{
Vector2 frameSize = new Vector2(298, 318);
Texture2D texture = mod.GetTexture("Content/NPCs/Arachnus/Arachnus");
spriteBatch.Draw
(
texture,
new Vector2
(
npc.position.X - Main.screenPosition.X + frameSize.X * 0.34f,
npc.position.Y - Main.screenPosition.Y + frameSize.Y * 0.31f
),
npc.frame,
drawColor,
npc.rotation,
frameSize * 0.5f,
npc.scale,
SpriteEffects.None,
0f
);
return false;
}
public enum ArachnusMessageType
{
RoarSound,
FlamesSound
}
}
}