Init Commit because im an Init Twat
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
using Terraria;
|
||||
using Terraria.ID;
|
||||
using Terraria.ModLoader;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Terraria.Chat;
|
||||
using Terraria.Localization;
|
||||
|
||||
namespace ForgottenWawiTech.Content.NPCs.OriginalNiko
|
||||
{
|
||||
[AutoloadBossHead]
|
||||
public class Niko : ModNPC
|
||||
{
|
||||
public override void SetStaticDefaults()
|
||||
{
|
||||
// DisplayName.SetDefault("Original Niko");
|
||||
Main.npcFrameCount[NPC.type] = 1;
|
||||
}
|
||||
|
||||
public override void SetDefaults()
|
||||
{
|
||||
NPC.width = 40;
|
||||
NPC.height = 40;
|
||||
NPC.damage = 1786;
|
||||
NPC.defense = 290;
|
||||
NPC.lifeMax = 1000000;
|
||||
NPC.HitSound = SoundID.NPCHit1;
|
||||
NPC.DeathSound = SoundID.NPCDeath1;
|
||||
NPC.knockBackResist = 0f;
|
||||
NPC.boss = true;
|
||||
NPC.aiStyle = -1;
|
||||
NPC.value = Item.buyPrice(0, 1, 0, 0);
|
||||
}
|
||||
|
||||
public override void AI()
|
||||
{
|
||||
// Phased behaviour for Niko:
|
||||
// Phase 0: initial/dummy AI until 50% HP
|
||||
// Phase 1: invulnerable for ~1 minute (dialogue opportunity)
|
||||
// Phase 2: dummy AI until 30% HP
|
||||
// Phase 3: spawn other bosses (Lyyka, Neptune, Lexy) if they are undefeated, then move to Phase 4
|
||||
|
||||
NPC.TargetClosest(false);
|
||||
Player target = Main.player[NPC.target];
|
||||
if (!target.active || target.dead)
|
||||
{
|
||||
NPC.timeLeft = 300;
|
||||
return;
|
||||
}
|
||||
|
||||
int phase = (int)NPC.ai[0];
|
||||
int flags = (int)NPC.ai[1]; // bit0=Lyyka spawned, bit1=Neptune spawned, bit2=Lexy spawned
|
||||
int timer = (int)NPC.ai[2];
|
||||
|
||||
// Simple dummy movement helper
|
||||
void DoDummyMovement(float speed)
|
||||
{
|
||||
Vector2 dir = target.Center - NPC.Center;
|
||||
if (dir.Length() > 8f)
|
||||
{
|
||||
dir.Normalize();
|
||||
NPC.velocity = Vector2.Lerp(NPC.velocity, dir * speed, 0.02f);
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 0: initial until 50% HP
|
||||
if (phase == 0)
|
||||
{
|
||||
DoDummyMovement(3f);
|
||||
if (NPC.life <= NPC.lifeMax / 2)
|
||||
{
|
||||
// Enter invulnerable phase
|
||||
NPC.ai[0] = 1;
|
||||
NPC.ai[2] = 0; // reset timer
|
||||
NPC.dontTakeDamage = true;
|
||||
NPC.netUpdate = true;
|
||||
|
||||
string announce = "Niko envelopes themself in a strange silence...";
|
||||
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||
Main.NewText(announce, 200, 100, 255);
|
||||
else
|
||||
ChatHelper.BroadcastChatMessage(NetworkText.FromLiteral(announce), new Color(200, 100, 255));
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 1: invulnerable waiting (~1 minute) for dialogue
|
||||
else if (phase == 1)
|
||||
{
|
||||
NPC.ai[2]++;
|
||||
// Idle drift
|
||||
NPC.velocity *= 0.98f;
|
||||
|
||||
// Periodic short dialogue during invulnerable phase
|
||||
int t = (int)NPC.ai[2];
|
||||
if (t == 120)
|
||||
{
|
||||
string line = "...silence stretches, an uneasy calm.";
|
||||
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||
Main.NewText(line, 200, 120, 255);
|
||||
else
|
||||
ChatHelper.BroadcastChatMessage(NetworkText.FromLiteral(line), new Color(200, 120, 255));
|
||||
}
|
||||
else if (t == 900)
|
||||
{
|
||||
string line = "Niko: You think you've seen everything?";
|
||||
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||
Main.NewText(line, 220, 160, 255);
|
||||
else
|
||||
ChatHelper.BroadcastChatMessage(NetworkText.FromLiteral(line), new Color(220, 160, 255));
|
||||
}
|
||||
else if (t == 2100)
|
||||
{
|
||||
string line = "Niko: There's more yet to come...";
|
||||
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||
Main.NewText(line, 200, 140, 255);
|
||||
else
|
||||
ChatHelper.BroadcastChatMessage(NetworkText.FromLiteral(line), new Color(200, 140, 255));
|
||||
}
|
||||
|
||||
// After approx 60 seconds (3600 ticks), end invulnerability
|
||||
if (NPC.ai[2] >= 3600)
|
||||
{
|
||||
NPC.dontTakeDamage = false;
|
||||
NPC.ai[0] = 2;
|
||||
NPC.netUpdate = true;
|
||||
|
||||
string announce = "Niko's barrier fades... the battle resumes.";
|
||||
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||
Main.NewText(announce, 255, 150, 100);
|
||||
else
|
||||
ChatHelper.BroadcastChatMessage(NetworkText.FromLiteral(announce), new Color(255, 150, 100));
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 2: dummy AI after invul until 30% HP
|
||||
else if (phase == 2)
|
||||
{
|
||||
DoDummyMovement(4f);
|
||||
if (NPC.life <= (int)(NPC.lifeMax * 0.3f))
|
||||
{
|
||||
NPC.ai[0] = 3; // go to spawn phase
|
||||
NPC.netUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 3: spawn other bosses if undefeated
|
||||
else if (phase == 3)
|
||||
{
|
||||
// Spawn Lyyka if undefeated and not already spawned
|
||||
if (!WorldDefeatedBosses.Lyyka && (flags & 1) == 0)
|
||||
{
|
||||
flags |= 1;
|
||||
string announceL = "Lyyka is called to the fray!";
|
||||
}
|
||||
|
||||
// Spawn Neptune if undefeated and not already spawned
|
||||
if (!WorldDefeatedBosses.Neptune && (flags & 2) == 0)
|
||||
{
|
||||
flags |= 2;
|
||||
string announceN = "The waves answer Niko's call: Neptune arrives!";
|
||||
}
|
||||
|
||||
// Spawn Lexy if undefeated and not already spawned
|
||||
if (!WorldDefeatedBosses.Lexy && (flags & 4) == 0)
|
||||
{
|
||||
flags |= 4;
|
||||
string announceX = "Lexy emerges to twist the battlefield!";
|
||||
}
|
||||
|
||||
// Save flags and move to final phase
|
||||
NPC.ai[1] = flags;
|
||||
NPC.ai[0] = 4;
|
||||
NPC.netUpdate = true;
|
||||
}
|
||||
|
||||
// Phase 4+: final behaviour (dummy)
|
||||
else
|
||||
{
|
||||
DoDummyMovement(5f);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnKill()
|
||||
{
|
||||
// Spawn NikoNPC when killed
|
||||
/* if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||
{
|
||||
NPC.NewNPC(NPC.GetSource_Death(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType<NikoNPC>());
|
||||
}
|
||||
else
|
||||
{
|
||||
NetMessage.SendData(MessageID.SpawnNPC, number: ModContent.NPCType<NikoNPC>(), number2: NPC.whoAmI);
|
||||
} */
|
||||
// Set a world flag or similar to indicate Niko has been defeated
|
||||
WorldDefeatedBosses.Niko = true;
|
||||
// Immediate sync of world flags
|
||||
WorldDefeatedBosses.Sync(ModContent.GetInstance<ForgottenWawiTech>());
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,139 @@
|
||||
using System.Collections.Generic;
|
||||
using Terraria;
|
||||
using Terraria.ID;
|
||||
using Terraria.ModLoader;
|
||||
using Terraria.GameContent.Personalities;
|
||||
using Terraria.Localization;
|
||||
|
||||
namespace ForgottenWawiTech.Content.NPCs.OriginalNiko
|
||||
{
|
||||
[AutoloadHead]
|
||||
public class NikoNPC : ModNPC
|
||||
{
|
||||
public override void SetStaticDefaults()
|
||||
{
|
||||
// DisplayName.SetDefault("Niko");
|
||||
Main.npcFrameCount[NPC.type] = 25; // The amount of frames the NPC has
|
||||
|
||||
NPCID.Sets.ExtraFramesCount[NPC.type] = 9; // Generally for Town NPCs, this should be 9
|
||||
NPCID.Sets.AttackFrameCount[NPC.type] = 4;
|
||||
NPCID.Sets.DangerDetectRange[NPC.type] = 700; // The amount of pixels away from the center of the npc that it tries to attack enemies
|
||||
NPCID.Sets.AttackType[NPC.type] = 0;
|
||||
NPCID.Sets.AttackTime[NPC.type] = 90; // The amount of time it takes for the NPC's attack animation to be over
|
||||
NPCID.Sets.AttackAverageChance[NPC.type] = 30;
|
||||
NPCID.Sets.HatOffsetY[NPC.type] = 4; // For when a party is active, the party hat spawns at a Y offset
|
||||
|
||||
// Influences how the NPC looks in the Bestiary
|
||||
NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers = new NPCID.Sets.NPCBestiaryDrawModifiers(0)
|
||||
{
|
||||
Velocity = 1f, // Draws the NPC in the bestiary as if its walking +1 tiles in the x direction
|
||||
Direction = 1 // -1 is left and 1 is right. NPCs are drawn facing the left by default
|
||||
};
|
||||
|
||||
NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, drawModifiers);
|
||||
}
|
||||
|
||||
public override void SetDefaults()
|
||||
{
|
||||
NPC.townNPC = true;
|
||||
NPC.friendly = true;
|
||||
NPC.width = 18;
|
||||
NPC.height = 40;
|
||||
NPC.aiStyle = 7;
|
||||
NPC.damage = 10;
|
||||
NPC.defense = 15;
|
||||
NPC.lifeMax = 250;
|
||||
NPC.HitSound = SoundID.NPCHit1;
|
||||
NPC.DeathSound = SoundID.NPCDeath1;
|
||||
NPC.knockBackResist = 0.5f;
|
||||
|
||||
AnimationType = NPCID.Guide;
|
||||
}
|
||||
|
||||
public override bool CanTownNPCSpawn(int numTownNPCs)
|
||||
{
|
||||
// NikoNPC can only spawn after Original Niko is defeated
|
||||
// Due to Terraria logic, we need to return true here if Niko has been defeated so that the NPC can respawn.
|
||||
return WorldDefeatedBosses.Niko;
|
||||
|
||||
}
|
||||
|
||||
public override List<string> SetNPCNameList()
|
||||
{
|
||||
return new List<string>() {
|
||||
"Niko"
|
||||
};
|
||||
}
|
||||
|
||||
public override void SetChatButtons(ref string button, ref string button2)
|
||||
{
|
||||
button = Language.GetTextValue("LegacyInterface.28"); // "Shop"
|
||||
}
|
||||
|
||||
public override void OnChatButtonClicked(bool firstButton, ref string shop)
|
||||
{
|
||||
if (firstButton)
|
||||
{
|
||||
shop = "Shop";
|
||||
}
|
||||
}
|
||||
|
||||
public override void AddShops()
|
||||
{
|
||||
var npcShop = new NPCShop(Type)
|
||||
.Add(ItemID.LightningBug) // Example item, replace with your own items
|
||||
.Add(ItemID.Sunflower); // Example item, replace with your own items
|
||||
|
||||
npcShop.Register();
|
||||
}
|
||||
|
||||
public override string GetChat()
|
||||
{
|
||||
switch (Main.rand.Next(8))
|
||||
{
|
||||
case 0:
|
||||
return "Just because you defeated me doesn't mean I'm gone forever.";
|
||||
case 1:
|
||||
return "I'm taking the internet down for an hour, hope you don't mind.";
|
||||
case 2:
|
||||
return "FUCK!";
|
||||
case 3:
|
||||
return "Be quick, I'm about to bugger off to Nando's.";
|
||||
case 4:
|
||||
return "I'm not dead yet!";
|
||||
case 5:
|
||||
return "You can't get rid of me that easily!";
|
||||
case 6:
|
||||
return "I'll be back!";
|
||||
case 7:
|
||||
return "This isn't the end!";
|
||||
default:
|
||||
return "I have no idea what to say.";
|
||||
}
|
||||
}
|
||||
|
||||
public override void TownNPCAttackStrength(ref int damage, ref float knockback)
|
||||
{
|
||||
damage = 20;
|
||||
knockback = 4f;
|
||||
}
|
||||
|
||||
public override void TownNPCAttackCooldown(ref int cooldown, ref int randExtraCooldown)
|
||||
{
|
||||
cooldown = 30;
|
||||
randExtraCooldown = 30;
|
||||
}
|
||||
|
||||
public override void TownNPCAttackProj(ref int projType, ref int attackDelay)
|
||||
{
|
||||
projType = ProjectileID.SwordBeam;
|
||||
attackDelay = 1;
|
||||
}
|
||||
|
||||
public override void TownNPCAttackProjSpeed(ref float multiplier, ref float gravityCorrection, ref float randomOffset)
|
||||
{
|
||||
multiplier = 12f;
|
||||
randomOffset = 2f;
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 504 B |
Binary file not shown.
|
After Width: | Height: | Size: 504 B |
Binary file not shown.
|
After Width: | Height: | Size: 504 B |
Reference in New Issue
Block a user