Init Commit because im an Init Twat
@@ -0,0 +1,54 @@
|
||||
using Terraria;
|
||||
using Terraria.ID;
|
||||
using Terraria.ModLoader;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace ForgottenWawiTech.Content.NPCs.OriginalLyyka
|
||||
{
|
||||
[AutoloadBossHead]
|
||||
public class Clara : ModNPC
|
||||
{
|
||||
public override void SetStaticDefaults()
|
||||
{
|
||||
// DisplayName.SetDefault("Clara");
|
||||
Main.npcFrameCount[NPC.type] = 1;
|
||||
}
|
||||
|
||||
public override void SetDefaults()
|
||||
{
|
||||
NPC.width = 44;
|
||||
NPC.height = 44;
|
||||
NPC.damage = 65;
|
||||
NPC.defense = 18;
|
||||
NPC.lifeMax = 15000;
|
||||
NPC.HitSound = SoundID.NPCHit1;
|
||||
NPC.DeathSound = SoundID.NPCDeath1;
|
||||
NPC.knockBackResist = 0f;
|
||||
NPC.boss = true;
|
||||
NPC.aiStyle = -1; // placeholder
|
||||
NPC.value = Item.buyPrice(0, 1, 50, 0);
|
||||
}
|
||||
|
||||
public override void AI()
|
||||
{
|
||||
// Placeholder AI: simple orbiting motion around spawn point
|
||||
Vector2 center = NPC.ai[0] != 0 ? new Vector2(NPC.ai[1], NPC.ai[2]) : NPC.Center;
|
||||
if (NPC.ai[0] == 0)
|
||||
{
|
||||
NPC.ai[0] = 1;
|
||||
NPC.ai[1] = NPC.Center.X;
|
||||
NPC.ai[2] = NPC.Center.Y;
|
||||
}
|
||||
|
||||
float orbitRadius = 120f;
|
||||
NPC.ai[3] += 0.02f;
|
||||
float angle = NPC.ai[3];
|
||||
Vector2 targetPos = new Vector2(NPC.ai[1], NPC.ai[2]) + orbitRadius * new Vector2((float)System.Math.Cos(angle), (float)System.Math.Sin(angle));
|
||||
Vector2 move = targetPos - NPC.Center;
|
||||
float speed = 6f;
|
||||
if (move.Length() > speed)
|
||||
move = Vector2.Normalize(move) * speed;
|
||||
NPC.velocity = (NPC.velocity * 20f + move) / 21f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,182 @@
|
||||
using Terraria;
|
||||
using Terraria.ID;
|
||||
using Terraria.ModLoader;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Terraria.Chat;
|
||||
using Terraria.Localization;
|
||||
|
||||
namespace ForgottenWawiTech.Content.NPCs.OriginalLyyka
|
||||
{
|
||||
[AutoloadBossHead]
|
||||
public class Lyyka : ModNPC
|
||||
{
|
||||
public override void SetStaticDefaults()
|
||||
{
|
||||
// DisplayName.SetDefault("Original Lyyka");
|
||||
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 boss AI for Lyyka:
|
||||
// - At 50% HP, spawn Terra. Lyyka becomes invulnerable and waits until Terra is defeated -> Phase 2
|
||||
// - At 30% HP (after Terra phase), spawn Clara. Lyyka becomes invulnerable and waits until Clara is defeated -> Phase 3
|
||||
|
||||
NPC.TargetClosest(false);
|
||||
Player target = Main.player[NPC.target];
|
||||
if (!target.active || target.dead)
|
||||
{
|
||||
NPC.timeLeft = 300;
|
||||
return;
|
||||
}
|
||||
|
||||
int phase = (int)NPC.ai[0]; // 0 = initial, 1 = waiting Terra, 2 = after Terra, 3 = waiting Clara, 4 = final
|
||||
int flags = (int)NPC.ai[1]; // bit0 = Terra spawned, bit1 = Clara spawned
|
||||
|
||||
// Phase 0: before Terra summoned
|
||||
if (phase == 0)
|
||||
{
|
||||
if (NPC.life <= NPC.lifeMax / 2 && (flags & 1) == 0)
|
||||
{
|
||||
flags |= 1;
|
||||
NPC.ai[1] = flags;
|
||||
|
||||
// Make invulnerable and wait for Terra
|
||||
NPC.dontTakeDamage = true;
|
||||
NPC.ai[0] = 1;
|
||||
NPC.netUpdate = true;
|
||||
|
||||
}
|
||||
|
||||
// basic approach movement
|
||||
if (NPC.ai[0] == 0)
|
||||
{
|
||||
Vector2 dir = (target.Center - NPC.Center);
|
||||
if (dir.Length() > 8f)
|
||||
{
|
||||
dir.Normalize();
|
||||
NPC.velocity = Vector2.Lerp(NPC.velocity, dir * 3.5f, 0.02f);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Phase 1: waiting for Terra
|
||||
else if (phase == 1)
|
||||
{
|
||||
bool terraAlive = false;
|
||||
int terraType = ModContent.NPCType<Terra>();
|
||||
for (int i = 0; i < Main.maxNPCs; i++)
|
||||
{
|
||||
NPC check = Main.npc[i];
|
||||
if (check.active && check.type == terraType)
|
||||
{
|
||||
terraAlive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!terraAlive)
|
||||
{
|
||||
NPC.dontTakeDamage = false;
|
||||
NPC.ai[0] = 2; // enter Phase 2
|
||||
NPC.netUpdate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NPC.velocity *= 0.98f; // idle while waiting
|
||||
}
|
||||
}
|
||||
// Phase 2: after Terra defeated, before Clara
|
||||
else if (phase == 2)
|
||||
{
|
||||
// When at or below 30% HP, spawn Clara (if not already spawned)
|
||||
if (NPC.life <= (int)(NPC.lifeMax * 0.3f) && (flags & 2) == 0)
|
||||
{
|
||||
flags |= 2;
|
||||
NPC.ai[1] = flags;
|
||||
|
||||
NPC.dontTakeDamage = true;
|
||||
NPC.ai[0] = 3; // waiting for Clara
|
||||
NPC.netUpdate = true;
|
||||
|
||||
string announceClara = "Clara descends from the sky!";
|
||||
}
|
||||
|
||||
// basic movement in Phase 2
|
||||
Vector2 dir2 = (target.Center - NPC.Center);
|
||||
if (dir2.Length() > 8f)
|
||||
{
|
||||
dir2.Normalize();
|
||||
NPC.velocity = Vector2.Lerp(NPC.velocity, dir2 * 4f, 0.02f);
|
||||
}
|
||||
}
|
||||
// Phase 3: waiting for Clara
|
||||
else if (phase == 3)
|
||||
{
|
||||
bool claraAlive = false;
|
||||
int claraType = ModContent.NPCType<Clara>();
|
||||
for (int i = 0; i < Main.maxNPCs; i++)
|
||||
{
|
||||
NPC check = Main.npc[i];
|
||||
if (check.active && check.type == claraType)
|
||||
{
|
||||
claraAlive = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!claraAlive)
|
||||
{
|
||||
NPC.dontTakeDamage = false;
|
||||
NPC.ai[0] = 4; // final phase
|
||||
NPC.netUpdate = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
NPC.velocity *= 0.98f;
|
||||
}
|
||||
}
|
||||
// Phase 4+: final behaviour
|
||||
else
|
||||
{
|
||||
Vector2 dir3 = (target.Center - NPC.Center);
|
||||
if (dir3.Length() > 8f)
|
||||
{
|
||||
dir3.Normalize();
|
||||
NPC.velocity = Vector2.Lerp(NPC.velocity, dir3 * 4.5f, 0.02f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnKill()
|
||||
{
|
||||
/* // Spawn LyykaNPC when killed
|
||||
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||
{
|
||||
NPC.NewNPC(NPC.GetSource_Death(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType<LyykaNPC>());
|
||||
}
|
||||
else
|
||||
{
|
||||
NetMessage.SendData(MessageID.SpawnNPC, number: ModContent.NPCType<LyykaNPC>(), number2: NPC.whoAmI);
|
||||
} */
|
||||
// Set a world flag or similar to indicate Lyyka has been defeated
|
||||
WorldDefeatedBosses.Lyyka = true;
|
||||
// Immediate sync of world flags
|
||||
WorldDefeatedBosses.Sync(ModContent.GetInstance<ForgottenWawiTech>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,125 @@
|
||||
using System.Collections.Generic;
|
||||
using Terraria;
|
||||
using Terraria.ID;
|
||||
using Terraria.ModLoader;
|
||||
using Terraria.GameContent.Personalities;
|
||||
using Terraria.Localization;
|
||||
|
||||
namespace ForgottenWawiTech.Content.NPCs.OriginalLyyka
|
||||
{
|
||||
[AutoloadHead]
|
||||
public class LyykaNPC : ModNPC
|
||||
{
|
||||
public override void SetStaticDefaults()
|
||||
{
|
||||
// DisplayName.SetDefault("Lyyka");
|
||||
Main.npcFrameCount[NPC.type] = 25;
|
||||
|
||||
NPCID.Sets.ExtraFramesCount[NPC.type] = 9;
|
||||
NPCID.Sets.AttackFrameCount[NPC.type] = 4;
|
||||
NPCID.Sets.DangerDetectRange[NPC.type] = 700;
|
||||
NPCID.Sets.AttackType[NPC.type] = 0;
|
||||
NPCID.Sets.AttackTime[NPC.type] = 90;
|
||||
NPCID.Sets.AttackAverageChance[NPC.type] = 30;
|
||||
NPCID.Sets.HatOffsetY[NPC.type] = 4;
|
||||
|
||||
NPCID.Sets.NPCBestiaryDrawModifiers drawModifiers = new NPCID.Sets.NPCBestiaryDrawModifiers(0)
|
||||
{
|
||||
Velocity = 1f,
|
||||
Direction = 1
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
return WorldDefeatedBosses.Lyyka;
|
||||
}
|
||||
|
||||
public override List<string> SetNPCNameList()
|
||||
{
|
||||
return new List<string>() {
|
||||
"Lyyka"
|
||||
};
|
||||
}
|
||||
|
||||
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)
|
||||
.Add(ItemID.Sunflower);
|
||||
|
||||
npcShop.Register();
|
||||
}
|
||||
|
||||
public override string GetChat()
|
||||
{
|
||||
switch (Main.rand.Next(4))
|
||||
{
|
||||
case 0:
|
||||
return "Meow!";
|
||||
case 1:
|
||||
return "Want some cookies?";
|
||||
case 2:
|
||||
return "Time for a catnap...";
|
||||
default:
|
||||
return "Purr...";
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,50 @@
|
||||
using Terraria;
|
||||
using Terraria.ID;
|
||||
using Terraria.ModLoader;
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace ForgottenWawiTech.Content.NPCs.OriginalLyyka
|
||||
{
|
||||
[AutoloadBossHead]
|
||||
public class Terra : ModNPC
|
||||
{
|
||||
public override void SetStaticDefaults()
|
||||
{
|
||||
// DisplayName.SetDefault("Terra");
|
||||
Main.npcFrameCount[NPC.type] = 1;
|
||||
}
|
||||
|
||||
public override void SetDefaults()
|
||||
{
|
||||
NPC.width = 48;
|
||||
NPC.height = 48;
|
||||
NPC.damage = 80;
|
||||
NPC.defense = 20;
|
||||
NPC.lifeMax = 20000;
|
||||
NPC.HitSound = SoundID.NPCHit1;
|
||||
NPC.DeathSound = SoundID.NPCDeath1;
|
||||
NPC.knockBackResist = 0f;
|
||||
NPC.boss = true;
|
||||
NPC.aiStyle = -1; // custom AI will be added later
|
||||
NPC.value = Item.buyPrice(0, 2, 0, 0);
|
||||
}
|
||||
|
||||
public override void AI()
|
||||
{
|
||||
// Placeholder AI: hover in place and face the player
|
||||
Player target = Main.player[NPC.target];
|
||||
if (!target.active || target.dead)
|
||||
{
|
||||
NPC.TargetClosest(false);
|
||||
target = Main.player[NPC.target];
|
||||
|
||||
}
|
||||
|
||||
Vector2 direction = target.Center - NPC.Center;
|
||||
direction.Normalize();
|
||||
float speed = 2.5f;
|
||||
NPC.velocity = (NPC.velocity * 30f + direction * speed) / 31f;
|
||||
NPC.spriteDirection = NPC.direction = (direction.X < 0f) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 504 B |