326 lines
11 KiB
C#
326 lines
11 KiB
C#
using System.IO;
|
|
using System.Linq;
|
|
using Decimation.Content.Buffs.Debuffs;
|
|
using Decimation.Content.Items.Boss.DuneWyrm;
|
|
using Decimation.Content.NPCs.DuneWyrm.AncientTombCrawler;
|
|
using Decimation.Content.Projectiles;
|
|
using Decimation.Lib.NPCs;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using Terraria;
|
|
using Terraria.ID;
|
|
using Terraria.ModLoader;
|
|
|
|
namespace Decimation.Content.NPCs.DuneWyrm
|
|
{
|
|
[AutoloadBossHead]
|
|
internal class DuneWyrmHead : DuneWyrm
|
|
{
|
|
private int _previousTile = -1;
|
|
private bool _spawnedAncientTombCrawler;
|
|
|
|
public override void SetDefaults()
|
|
{
|
|
npc.lifeMax = 11000;
|
|
npc.damage = 65;
|
|
npc.defense = 15;
|
|
npc.width = 116;
|
|
npc.height = 116;
|
|
Main.npcFrameCount[npc.type] = 1;
|
|
npc.value = Item.buyPrice(gold: 12);
|
|
npc.npcSlots = 1f;
|
|
npc.aiStyle = -1;
|
|
music = mod.GetSoundSlot(SoundType.Music, "Sounds/Music/The_Deserts_Call");
|
|
|
|
DuneWyrmBody.bodyPartsCount = 0;
|
|
}
|
|
|
|
public override void Init()
|
|
{
|
|
base.Init();
|
|
head = true;
|
|
}
|
|
|
|
public override void OnHitNPC(NPC target, int damage, float knockback, bool crit)
|
|
{
|
|
if (Main.rand.NextBool(5) || !Main.expertMode && Main.rand.NextBool(2))
|
|
target.AddBuff(ModContent.BuffType<Hyperthermic>(), Main.expertMode ? 600 : 300);
|
|
}
|
|
|
|
public override void OnHitPlayer(Player target, int damage, bool crit)
|
|
{
|
|
if (Main.rand.NextBool(5) || !Main.expertMode && Main.rand.NextBool(2))
|
|
target.AddBuff(ModContent.BuffType<Hyperthermic>(), Main.expertMode ? 600 : 300);
|
|
}
|
|
|
|
public override void BossLoot(ref string name, ref int potionType)
|
|
{
|
|
name = "The Dune Wyrm";
|
|
DecimationWorld.downedDuneWyrm = true;
|
|
|
|
potionType = ItemID.HealingPotion;
|
|
base.BossLoot(ref name, ref potionType);
|
|
}
|
|
|
|
public override void SendExtraAI(BinaryWriter writer)
|
|
{
|
|
writer.Write(_previousTile);
|
|
writer.Write(_spawnedAncientTombCrawler);
|
|
}
|
|
|
|
public override void ReceiveExtraAI(BinaryReader reader)
|
|
{
|
|
_previousTile = reader.ReadInt32();
|
|
_spawnedAncientTombCrawler = reader.ReadBoolean();
|
|
}
|
|
|
|
public override void CustomBehavior()
|
|
{
|
|
if (npc.life < npc.lifeMax / 2f) ComputeSpeed();
|
|
if (Main.expertMode) SummonSandnado();
|
|
if (Main.tile[(int) npc.Center.X / 16, (int) npc.Center.Y / 16].type != 0 && _previousTile == 0)
|
|
ShootAmmonite();
|
|
|
|
if (npc.life <= npc.lifeMax * 0.15f &&
|
|
!_spawnedAncientTombCrawler && !NPC.AnyNPCs(ModContent.NPCType<AncientTombCrawlerHead>()))
|
|
{
|
|
if (Main.netMode != 1)
|
|
NPC.SpawnOnPlayer(npc.target, ModContent.NPCType<AncientTombCrawlerHead>());
|
|
_spawnedAncientTombCrawler = true;
|
|
}
|
|
|
|
_previousTile = Main.tile[(int) npc.Center.X / 16, (int) npc.Center.Y / 16].type;
|
|
}
|
|
|
|
public override bool ShouldRun()
|
|
{
|
|
bool playersActive = Main.player.Any(p => p.active);
|
|
bool playersDead = Main.player.Any(p => p.dead);
|
|
|
|
return !Main.player[npc.target].ZoneDesert || !playersActive || playersDead;
|
|
}
|
|
|
|
private void ComputeSpeed()
|
|
{
|
|
const float ratio = 0.4545454f;
|
|
float deltaLife = npc.lifeMax / 2f - npc.life;
|
|
float addedSpeed = deltaLife * ratio / 1000f;
|
|
speed = BaseSpeed + addedSpeed;
|
|
}
|
|
|
|
private void SummonSandnado()
|
|
{
|
|
int tile = Main.tile[(int) npc.Center.X / 16, (int) npc.Center.Y / 16].type;
|
|
|
|
if (tile == 0 &&
|
|
_previousTile != 0 && Main.netMode != 1)
|
|
Projectile.NewProjectile(npc.Center, new Vector2(0, 0), ProjectileID.SandnadoHostile, 15, 10f);
|
|
}
|
|
|
|
private void ShootAmmonite()
|
|
{
|
|
Main.PlaySound(SoundID.Item14, npc.Center);
|
|
|
|
// Smoke
|
|
for (int i = 0; i < 50; i++)
|
|
{
|
|
int dustIndex = Dust.NewDust(new Vector2(npc.position.X, npc.position.Y), npc.width,
|
|
npc.height, 31, 0f, 0f, 100, default, 2f);
|
|
Main.dust[dustIndex].velocity *= 1.4f;
|
|
}
|
|
|
|
float x = npc.position.X + npc.width / 2f - 24f;
|
|
float y = npc.position.Y + npc.height / 2f - 24f;
|
|
|
|
for (int g = 0; g < 2; g++)
|
|
{
|
|
int goreIndex =
|
|
Gore.NewGore(
|
|
new Vector2(x, y), default, Main.rand.Next(61, 64));
|
|
Main.gore[goreIndex].scale = 1.5f;
|
|
Main.gore[goreIndex].velocity.X += 1.5f;
|
|
Main.gore[goreIndex].velocity.Y += 1.5f;
|
|
goreIndex = Gore.NewGore(
|
|
new Vector2(x, y), default, Main.rand.Next(61, 64));
|
|
Main.gore[goreIndex].scale = 1.5f;
|
|
Main.gore[goreIndex].velocity.X -= 1.5f;
|
|
Main.gore[goreIndex].velocity.Y += 1.5f;
|
|
goreIndex = Gore.NewGore(
|
|
new Vector2(x, y), default, Main.rand.Next(61, 64));
|
|
Main.gore[goreIndex].scale = 1.5f;
|
|
Main.gore[goreIndex].velocity.X += 1.5f;
|
|
Main.gore[goreIndex].velocity.Y -= 1.5f;
|
|
goreIndex = Gore.NewGore(
|
|
new Vector2(x, y), default, Main.rand.Next(61, 64));
|
|
Main.gore[goreIndex].scale = 1.5f;
|
|
Main.gore[goreIndex].velocity.X -= 1.5f;
|
|
Main.gore[goreIndex].velocity.Y -= 1.5f;
|
|
}
|
|
|
|
// Ammonite
|
|
int ammoniteNbr = Main.rand.Next(5, 9);
|
|
|
|
if (Main.netMode != 1)
|
|
for (int i = 0; i < ammoniteNbr; i++)
|
|
Projectile.NewProjectile(npc.Center,
|
|
new Vector2(Main.rand.Next(-8, 9), Main.rand.Next(8, 15)),
|
|
ModContent.ProjectileType<Ammonite>(), 15, 5f);
|
|
}
|
|
|
|
public override bool? DrawHealthBar(byte hbPosition, ref float scale, ref Vector2 position)
|
|
{
|
|
scale = 1.9f; //this make the NPC Health Bar bigger
|
|
return null;
|
|
}
|
|
|
|
public override bool PreDraw(SpriteBatch spriteBatch, Color drawColor)
|
|
{
|
|
Draw("Content/NPCs/DuneWyrm/DuneWyrmHead", spriteBatch, drawColor);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal class DuneWyrmBody : DuneWyrm
|
|
{
|
|
public static int bodyPartsCount;
|
|
private int _bodyIndex;
|
|
|
|
public override void SetDefaults()
|
|
{
|
|
npc.width = 66;
|
|
npc.height = 66;
|
|
npc.damage = 45;
|
|
npc.defense = 5;
|
|
npc.lifeMax = 1;
|
|
npc.dontCountMe = true;
|
|
|
|
_bodyIndex = bodyPartsCount++;
|
|
}
|
|
|
|
public override bool PreDraw(SpriteBatch spriteBatch, Color drawColor)
|
|
{
|
|
Vector2 frameSize = new Vector2(npc.width, npc.height);
|
|
Texture2D texture = mod.GetTexture("Content/NPCs/DuneWyrm/DuneWyrmBody");
|
|
Rectangle sourceRectangle = npc.frame;
|
|
|
|
if (_bodyIndex % 4 == 0)
|
|
{
|
|
texture = mod.GetTexture("Content/NPCs/DuneWyrm/DuneWyrmBody2");
|
|
sourceRectangle.Width = 88;
|
|
sourceRectangle.Height = 66;
|
|
frameSize.X += 11;
|
|
frameSize.Y -= 10;
|
|
}
|
|
|
|
Vector2 position = new Vector2(
|
|
npc.position.X - Main.screenPosition.X + frameSize.X / 2f,
|
|
npc.position.Y - Main.screenPosition.Y + frameSize.Y / 2f
|
|
);
|
|
|
|
spriteBatch.Draw
|
|
(
|
|
texture,
|
|
position,
|
|
sourceRectangle,
|
|
drawColor,
|
|
npc.rotation,
|
|
frameSize * 0.5f,
|
|
npc.scale,
|
|
SpriteEffects.None,
|
|
0f
|
|
);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
internal class DuneWyrmTail : DuneWyrm
|
|
{
|
|
public override void SetDefaults()
|
|
{
|
|
npc.width = 54;
|
|
npc.height = 54;
|
|
npc.damage = 45;
|
|
npc.defense = 14;
|
|
npc.lifeMax = 1;
|
|
npc.dontCountMe = true;
|
|
}
|
|
|
|
public override void Init()
|
|
{
|
|
base.Init();
|
|
tail = true;
|
|
}
|
|
|
|
public override bool PreDraw(SpriteBatch spriteBatch, Color drawColor)
|
|
{
|
|
Draw("Content/NPCs/DuneWyrm/DuneWyrmTail", spriteBatch, drawColor);
|
|
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public abstract class DuneWyrm : Worm
|
|
{
|
|
protected const float BaseSpeed = 10f;
|
|
|
|
public override void SetStaticDefaults()
|
|
{
|
|
DisplayName.SetDefault("Dune Wyrm");
|
|
}
|
|
|
|
public override void Init()
|
|
{
|
|
minLength = 16;
|
|
maxLength = 16;
|
|
tailType = ModContent.NPCType<DuneWyrmTail>();
|
|
bodyType = ModContent.NPCType<DuneWyrmBody>();
|
|
headType = ModContent.NPCType<DuneWyrmHead>();
|
|
speed = BaseSpeed;
|
|
turnSpeed = 0.045f;
|
|
npc.scale = 1.5f;
|
|
npc.lavaImmune = true;
|
|
npc.noGravity = true;
|
|
npc.noTileCollide = true;
|
|
npc.behindTiles = true;
|
|
npc.knockBackResist = 0f;
|
|
npc.netAlways = true;
|
|
npc.DeathSound = SoundID.NPCDeath18;
|
|
npc.HitSound = SoundID.NPCHit1;
|
|
npc.boss = true;
|
|
bossBag = ModContent.ItemType<DuneWyrmTreasureBag>();
|
|
undergroundSound = mod.GetLegacySoundSlot(SoundType.Custom, "Sounds/Custom/Earthquake");
|
|
}
|
|
|
|
protected override void SendSoundPacket()
|
|
{
|
|
GetPacket(DuneWyrmMessageType.UndergroundSound).Send();
|
|
}
|
|
|
|
private ModPacket GetPacket(DuneWyrmMessageType type)
|
|
{
|
|
ModPacket packet = mod.GetPacket();
|
|
packet.Write((byte) DecimationModMessageType.DuneWyrm);
|
|
packet.Write(npc.whoAmI);
|
|
packet.Write((byte) type);
|
|
return packet;
|
|
}
|
|
|
|
public void HandlePacket(BinaryReader reader)
|
|
{
|
|
DuneWyrmMessageType type = (DuneWyrmMessageType) reader.ReadByte();
|
|
switch (type)
|
|
{
|
|
case DuneWyrmMessageType.UndergroundSound:
|
|
Main.PlaySound(undergroundSound, npc.Center);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public enum DuneWyrmMessageType
|
|
{
|
|
UndergroundSound
|
|
}
|
|
} |