Init Commit because im an Init Twat
@@ -0,0 +1,82 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.Audio;
|
||||||
|
using Terraria.DataStructures;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.Items
|
||||||
|
{
|
||||||
|
public class BoulderCannon: ModItem
|
||||||
|
{
|
||||||
|
public override void SetDefaults()
|
||||||
|
{
|
||||||
|
Item.damage = 10000;
|
||||||
|
Item.DamageType = DamageClass.Ranged;
|
||||||
|
Item.width = 40;
|
||||||
|
Item.height = 40;
|
||||||
|
Item.useTime = 100;
|
||||||
|
Item.useAnimation = 100;
|
||||||
|
Item.useStyle = ItemUseStyleID.Shoot;
|
||||||
|
Item.knockBack = 6;
|
||||||
|
Item.value = Item.buyPrice(gold: 20);
|
||||||
|
Item.rare = ItemRarityID.Red;
|
||||||
|
Item.UseSound = SoundID.Dig;
|
||||||
|
Item.autoReuse = true;
|
||||||
|
Item.noMelee = true;
|
||||||
|
Item.shoot = ProjectileID.PurificationPowder;
|
||||||
|
Item.shootSpeed = 50f;
|
||||||
|
Item.useAmmo = AmmoID.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On shoot, fire Projectile ID 502 (the rainbow projectile) instead of the default ammo projectile
|
||||||
|
public override bool Shoot(Player player, Terraria.DataStructures.EntitySource_ItemUse_WithAmmo source, Vector2 position, Vector2 velocity, int type, int damage, float knockBack)
|
||||||
|
{
|
||||||
|
// If the player's name contains "Neptune" or "Otter", instakill the player.
|
||||||
|
if (player.name.Contains("Neptune") || player.name.Contains("Otter"))
|
||||||
|
{
|
||||||
|
player.KillMe(Terraria.DataStructures.PlayerDeathReason.ByCustomReason(player.name + " was punished accordingly."), 10000, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block the weapon if there is a boss alive
|
||||||
|
/* for (int i = 0; i < Main.maxNPCs; i++)
|
||||||
|
{
|
||||||
|
NPC npc = Main.npc[i];
|
||||||
|
if (npc.active && npc.boss)
|
||||||
|
{
|
||||||
|
if (Main.myPlayer == player.whoAmI)
|
||||||
|
{
|
||||||
|
Main.NewText("The Boulder Cannon refuses to fire while a boss is alive!", 255, 0, 0);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
Terraria.Projectile.NewProjectile(source, position, velocity, 1013, damage, knockBack, player.whoAmI);
|
||||||
|
|
||||||
|
return false; // return false to prevent tModLoader from shooting the default projectile
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector2? HoldoutOffset() {
|
||||||
|
return new Vector2(2f, -2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ModifyShootStats(Player player, ref Vector2 position, ref Vector2 velocity, ref int type, ref int damage, ref float knockback) {
|
||||||
|
Vector2 muzzleOffset = Vector2.Normalize(velocity) * 25f;
|
||||||
|
|
||||||
|
if (Collision.CanHit(position, 0, 0, position + muzzleOffset, 0, 0)) {
|
||||||
|
position += muzzleOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddRecipes()
|
||||||
|
{
|
||||||
|
Recipe recipe = CreateRecipe();
|
||||||
|
recipe.AddIngredient(ItemID.BouncyBoulder, 100);
|
||||||
|
recipe.AddIngredient(ItemID.LunarBar, 20);
|
||||||
|
recipe.AddTile(TileID.LunarCraftingStation);
|
||||||
|
recipe.Register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,61 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.Audio;
|
||||||
|
using Terraria.DataStructures;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.Items
|
||||||
|
{
|
||||||
|
public class Nyanageddon : ModItem
|
||||||
|
{
|
||||||
|
public override void SetDefaults()
|
||||||
|
{
|
||||||
|
Item.damage = 250;
|
||||||
|
Item.DamageType = DamageClass.Ranged;
|
||||||
|
Item.width = 40;
|
||||||
|
Item.height = 40;
|
||||||
|
Item.useTime = 8;
|
||||||
|
Item.useAnimation = 8;
|
||||||
|
Item.useStyle = ItemUseStyleID.Shoot;
|
||||||
|
Item.knockBack = 6;
|
||||||
|
Item.value = Item.buyPrice(gold: 20);
|
||||||
|
Item.rare = ItemRarityID.Red;
|
||||||
|
Item.UseSound = SoundID.Meowmere;
|
||||||
|
Item.autoReuse = true;
|
||||||
|
Item.noMelee = true;
|
||||||
|
Item.shoot = ProjectileID.PurificationPowder;
|
||||||
|
Item.shootSpeed = 20f;
|
||||||
|
Item.useAmmo = AmmoID.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On shoot, fire Projectile ID 502 (the rainbow projectile) instead of the default ammo projectile
|
||||||
|
public override bool Shoot(Player player, Terraria.DataStructures.EntitySource_ItemUse_WithAmmo source, Vector2 position, Vector2 velocity, int type, int damage, float knockBack)
|
||||||
|
{
|
||||||
|
Terraria.Projectile.NewProjectile(source, position, velocity, 502, damage, knockBack, player.whoAmI);
|
||||||
|
return false; // return false to prevent tModLoader from shooting the default projectile
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector2? HoldoutOffset() {
|
||||||
|
return new Vector2(2f, -2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ModifyShootStats(Player player, ref Vector2 position, ref Vector2 velocity, ref int type, ref int damage, ref float knockback) {
|
||||||
|
Vector2 muzzleOffset = Vector2.Normalize(velocity) * 25f;
|
||||||
|
|
||||||
|
if (Collision.CanHit(position, 0, 0, position + muzzleOffset, 0, 0)) {
|
||||||
|
position += muzzleOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddRecipes()
|
||||||
|
{
|
||||||
|
Recipe recipe = CreateRecipe();
|
||||||
|
recipe.AddIngredient(ItemID.RainbowGun, 1);
|
||||||
|
recipe.AddIngredient(ItemID.LunarBar, 20);
|
||||||
|
recipe.AddIngredient(ItemID.Meowmere, 1);
|
||||||
|
recipe.AddTile(TileID.LunarCraftingStation);
|
||||||
|
recipe.Register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 863 B |
@@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.Audio;
|
||||||
|
using Terraria.DataStructures;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using Terraria.Chat;
|
||||||
|
using Terraria.Localization;
|
||||||
|
using ForgottenWawiTech.Content.NPCs.OriginalLexy;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.Items.SummonItems
|
||||||
|
{
|
||||||
|
public class LexySummon : ModItem
|
||||||
|
{
|
||||||
|
public override void SetDefaults()
|
||||||
|
{
|
||||||
|
Item.width = 40;
|
||||||
|
Item.height = 40;
|
||||||
|
Item.useTime = 10;
|
||||||
|
Item.useAnimation = 10;
|
||||||
|
Item.useStyle = ItemUseStyleID.HoldUp;
|
||||||
|
Item.consumable = false;
|
||||||
|
Item.rare = ItemRarityID.Red;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanUseItem(Player player)
|
||||||
|
{
|
||||||
|
return Main.hardMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool? UseItem(Player player)
|
||||||
|
{
|
||||||
|
string summonText = "Chaos energy fills the air...";
|
||||||
|
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||||
|
{
|
||||||
|
NPC.SpawnOnPlayer(player.whoAmI, ModContent.NPCType<Lexy>());
|
||||||
|
Main.NewText(summonText, 175, 75, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.Audio;
|
||||||
|
using Terraria.DataStructures;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using Terraria.Chat;
|
||||||
|
using Terraria.Localization;
|
||||||
|
using ForgottenWawiTech.Content.NPCs.OriginalLyyka;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.Items.SummonItems
|
||||||
|
{
|
||||||
|
public class LyykaSummon : ModItem
|
||||||
|
{
|
||||||
|
public override void SetDefaults()
|
||||||
|
{
|
||||||
|
Item.width = 40;
|
||||||
|
Item.height = 40;
|
||||||
|
Item.useTime = 10;
|
||||||
|
Item.useAnimation = 10;
|
||||||
|
Item.useStyle = ItemUseStyleID.HoldUp;
|
||||||
|
Item.consumable = false;
|
||||||
|
Item.rare = ItemRarityID.Red;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanUseItem(Player player)
|
||||||
|
{
|
||||||
|
return Main.hardMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool? UseItem(Player player)
|
||||||
|
{
|
||||||
|
string summonText = "A feline presence fills the air...";
|
||||||
|
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||||
|
{
|
||||||
|
NPC.SpawnOnPlayer(player.whoAmI, ModContent.NPCType<Lyyka>());
|
||||||
|
Main.NewText(summonText, 175, 75, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.Audio;
|
||||||
|
using Terraria.DataStructures;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using Terraria.Chat;
|
||||||
|
using Terraria.Localization;
|
||||||
|
using ForgottenWawiTech.Content.NPCs.OriginalNeptune;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.Items.SummonItems
|
||||||
|
{
|
||||||
|
public class NeptuneSummon : ModItem
|
||||||
|
{
|
||||||
|
public override void SetDefaults()
|
||||||
|
{
|
||||||
|
Item.width = 40;
|
||||||
|
Item.height = 40;
|
||||||
|
Item.useTime = 10;
|
||||||
|
Item.useAnimation = 10;
|
||||||
|
Item.useStyle = ItemUseStyleID.HoldUp;
|
||||||
|
Item.consumable = false;
|
||||||
|
Item.rare = ItemRarityID.Red;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanUseItem(Player player)
|
||||||
|
{
|
||||||
|
return Main.hardMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool? UseItem(Player player)
|
||||||
|
{
|
||||||
|
string summonText = "The waters begin to stir...";
|
||||||
|
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||||
|
{
|
||||||
|
NPC.SpawnOnPlayer(player.whoAmI, ModContent.NPCType<Neptune>());
|
||||||
|
Main.NewText(summonText, 175, 75, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,54 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.Audio;
|
||||||
|
using Terraria.DataStructures;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using Terraria.Chat;
|
||||||
|
using Terraria.Localization;
|
||||||
|
using ForgottenWawiTech.Content.NPCs.OriginalNiko;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.Items.SummonItems
|
||||||
|
{
|
||||||
|
public class NikoSummon : ModItem
|
||||||
|
{
|
||||||
|
public override void SetDefaults()
|
||||||
|
{
|
||||||
|
Item.width = 40;
|
||||||
|
Item.height = 40;
|
||||||
|
Item.useTime = 10;
|
||||||
|
Item.useAnimation = 10;
|
||||||
|
Item.useStyle = ItemUseStyleID.HoldUp;
|
||||||
|
Item.consumable = false;
|
||||||
|
Item.rare = ItemRarityID.Red;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only allow the boss to be summoned if the Wall of Flesh is defeated (hardmode)
|
||||||
|
// Will be changed in the future
|
||||||
|
public override bool CanUseItem(Player player)
|
||||||
|
{
|
||||||
|
return Main.hardMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool? UseItem(Player player)
|
||||||
|
{
|
||||||
|
string summonText = "A familiar presence fills the air...";
|
||||||
|
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||||
|
{
|
||||||
|
NPC.SpawnOnPlayer(player.whoAmI, ModContent.NPCType<Niko>());
|
||||||
|
Main.NewText(summonText, 175, 75, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/* public override void AddRecipes()
|
||||||
|
{
|
||||||
|
Recipe recipe = CreateRecipe();
|
||||||
|
recipe.AddIngredient<Nyanageddon>(1);
|
||||||
|
recipe.AddIngredient(ItemID.LunarBar, 20);
|
||||||
|
recipe.AddIngredient(ItemID.Meowmere, 5);
|
||||||
|
recipe.AddTile(TileID.LunarCraftingStation);
|
||||||
|
recipe.Register();
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,66 @@
|
|||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.Audio;
|
||||||
|
using Terraria.DataStructures;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using ForgottenWawiTech.Content.Items;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.Items
|
||||||
|
{
|
||||||
|
public class TrueNyanageddon : ModItem
|
||||||
|
{
|
||||||
|
public override void SetDefaults()
|
||||||
|
{
|
||||||
|
Item.damage = 1200;
|
||||||
|
Item.DamageType = DamageClass.Ranged;
|
||||||
|
Item.width = 40;
|
||||||
|
Item.height = 40;
|
||||||
|
Item.useTime = 7;
|
||||||
|
Item.useAnimation = 7;
|
||||||
|
Item.useStyle = ItemUseStyleID.Shoot;
|
||||||
|
Item.knockBack = 20;
|
||||||
|
Item.value = Item.buyPrice(gold: 60);
|
||||||
|
Item.rare = ItemRarityID.Red;
|
||||||
|
Item.UseSound = SoundID.Meowmere;
|
||||||
|
Item.autoReuse = true;
|
||||||
|
Item.noMelee = true;
|
||||||
|
Item.shoot = ProjectileID.PurificationPowder;
|
||||||
|
Item.shootSpeed = 20f;
|
||||||
|
Item.useAmmo = AmmoID.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On shoot, fire 5 Projectile ID 502 (the rainbow projectile) in an arc instead of the default ammo projectile
|
||||||
|
public override bool Shoot(Player player, Terraria.DataStructures.EntitySource_ItemUse_WithAmmo source, Vector2 position, Vector2 velocity, int type, int damage, float knockBack)
|
||||||
|
{
|
||||||
|
for (int i = -2; i <= 2; i++)
|
||||||
|
{
|
||||||
|
Vector2 newVelocity = velocity.RotatedBy(MathHelper.ToRadians(3 * i));
|
||||||
|
Terraria.Projectile.NewProjectile(source, position, newVelocity, 502, damage, knockBack, player.whoAmI);
|
||||||
|
}
|
||||||
|
return false; // return false to prevent tModLoader from shooting the default projectile
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Vector2? HoldoutOffset() {
|
||||||
|
return new Vector2(2f, -2f);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ModifyShootStats(Player player, ref Vector2 position, ref Vector2 velocity, ref int type, ref int damage, ref float knockback) {
|
||||||
|
Vector2 muzzleOffset = Vector2.Normalize(velocity) * 25f;
|
||||||
|
|
||||||
|
if (Collision.CanHit(position, 0, 0, position + muzzleOffset, 0, 0)) {
|
||||||
|
position += muzzleOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AddRecipes()
|
||||||
|
{
|
||||||
|
Recipe recipe = CreateRecipe();
|
||||||
|
recipe.AddIngredient<Nyanageddon>(1);
|
||||||
|
recipe.AddIngredient(ItemID.LunarBar, 20);
|
||||||
|
recipe.AddIngredient(ItemID.Meowmere, 5);
|
||||||
|
recipe.AddTile(TileID.LunarCraftingStation);
|
||||||
|
recipe.Register();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 863 B |
@@ -0,0 +1,56 @@
|
|||||||
|
using Terraria;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.NPCs.OriginalLexy
|
||||||
|
{
|
||||||
|
[AutoloadBossHead]
|
||||||
|
public class Lexy : ModNPC
|
||||||
|
{
|
||||||
|
public override void SetStaticDefaults()
|
||||||
|
{
|
||||||
|
// DisplayName.SetDefault("Original Lexy");
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
// For now, the boss instantly dies
|
||||||
|
NPC.life = 0;
|
||||||
|
NPC.checkDead();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnKill()
|
||||||
|
{
|
||||||
|
/* // Spawn LexyNPC when killed
|
||||||
|
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||||
|
{
|
||||||
|
NPC.NewNPC(NPC.GetSource_Death(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType<LexyNPC>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NetMessage.SendData(MessageID.SpawnNPC, number: ModContent.NPCType<LexyNPC>(), number2: NPC.whoAmI);
|
||||||
|
} */
|
||||||
|
// Set a world flag or similar to indicate Lexy has been defeated
|
||||||
|
WorldDefeatedBosses.Lexy = 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.OriginalLexy
|
||||||
|
{
|
||||||
|
[AutoloadHead]
|
||||||
|
public class LexyNPC : ModNPC
|
||||||
|
{
|
||||||
|
public override void SetStaticDefaults()
|
||||||
|
{
|
||||||
|
// DisplayName.SetDefault("Lexy");
|
||||||
|
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.Lexy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<string> SetNPCNameList()
|
||||||
|
{
|
||||||
|
return new List<string>() {
|
||||||
|
"Lexy"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "Time to cause some chaos!";
|
||||||
|
case 1:
|
||||||
|
return "Want to see a magic trick?";
|
||||||
|
case 2:
|
||||||
|
return "Everything's more fun with explosions!";
|
||||||
|
default:
|
||||||
|
return "Let's make things interesting...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.MagicMissile;
|
||||||
|
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,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 |
@@ -0,0 +1,136 @@
|
|||||||
|
using Terraria;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Terraria.Chat;
|
||||||
|
using Terraria.Localization;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.NPCs.OriginalNeptune
|
||||||
|
{
|
||||||
|
[AutoloadBossHead]
|
||||||
|
public class Neptune : ModNPC
|
||||||
|
{
|
||||||
|
public override void SetStaticDefaults()
|
||||||
|
{
|
||||||
|
// DisplayName.SetDefault("Original Neptune");
|
||||||
|
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: at 50% HP spawn Raccoon. Neptune becomes invulnerable and does not attack
|
||||||
|
// until Raccoon is defeated, then move to Phase 2.
|
||||||
|
|
||||||
|
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 = phase 1 (initial), 1 = waiting for raccoon, 2 = phase 2
|
||||||
|
int flags = (int)NPC.ai[1]; // bitflags: bit0 = raccoon spawned
|
||||||
|
|
||||||
|
// Phase 0: before Raccoon summoned
|
||||||
|
if (phase == 0)
|
||||||
|
{
|
||||||
|
// If at or below 50% life and raccoon hasn't been spawned, spawn it and enter waiting state
|
||||||
|
if (NPC.life <= NPC.lifeMax / 2 && (flags & 1) == 0)
|
||||||
|
{
|
||||||
|
flags |= 1;
|
||||||
|
NPC.ai[1] = flags;
|
||||||
|
|
||||||
|
// Make Neptune invulnerable and enter waiting phase
|
||||||
|
NPC.dontTakeDamage = true;
|
||||||
|
NPC.ai[0] = 1;
|
||||||
|
NPC.netUpdate = true;
|
||||||
|
|
||||||
|
string announce = "A mischievous raccoon scurries into the battlefield!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple approach movement when not waiting
|
||||||
|
if (NPC.ai[0] == 0)
|
||||||
|
{
|
||||||
|
Vector2 dir = (target.Center - NPC.Center);
|
||||||
|
if (dir.Length() > 8f)
|
||||||
|
{
|
||||||
|
dir.Normalize();
|
||||||
|
NPC.velocity = Vector2.Lerp(NPC.velocity, dir * 3f, 0.02f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Phase 1: waiting for Raccoon to be defeated
|
||||||
|
else if (phase == 1)
|
||||||
|
{
|
||||||
|
bool raccoonAlive = false;
|
||||||
|
int raccoonType = ModContent.NPCType<Raccoon>();
|
||||||
|
for (int i = 0; i < Main.maxNPCs; i++)
|
||||||
|
{
|
||||||
|
NPC check = Main.npc[i];
|
||||||
|
if (check.active && check.type == raccoonType)
|
||||||
|
{
|
||||||
|
raccoonAlive = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stay invulnerable and idle until raccoon is gone
|
||||||
|
if (!raccoonAlive)
|
||||||
|
{
|
||||||
|
NPC.dontTakeDamage = false;
|
||||||
|
NPC.ai[0] = 2; // enter Phase 2
|
||||||
|
NPC.netUpdate = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// idle drift while waiting
|
||||||
|
NPC.velocity *= 0.98f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Phase 2+: normal behaviour (placeholder movement)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Vector2 dir = (target.Center - NPC.Center);
|
||||||
|
if (dir.Length() > 8f)
|
||||||
|
{
|
||||||
|
dir.Normalize();
|
||||||
|
NPC.velocity = Vector2.Lerp(NPC.velocity, dir * 4f, 0.02f);
|
||||||
|
}
|
||||||
|
NPC.spriteDirection = NPC.direction = (target.Center.X < NPC.Center.X) ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnKill()
|
||||||
|
{
|
||||||
|
/* // Spawn NeptuneNPC when killed
|
||||||
|
if (Main.netMode != NetmodeID.MultiplayerClient)
|
||||||
|
{
|
||||||
|
NPC.NewNPC(NPC.GetSource_Death(), (int)NPC.Center.X, (int)NPC.Center.Y, ModContent.NPCType<NeptuneNPC>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NetMessage.SendData(MessageID.SpawnNPC, number: ModContent.NPCType<NeptuneNPC>(), number2: NPC.whoAmI);
|
||||||
|
} */
|
||||||
|
// Set a world flag or similar to indicate Neptune has been defeated
|
||||||
|
WorldDefeatedBosses.Neptune = 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.OriginalNeptune
|
||||||
|
{
|
||||||
|
[AutoloadHead]
|
||||||
|
public class NeptuneNPC : ModNPC
|
||||||
|
{
|
||||||
|
public override void SetStaticDefaults()
|
||||||
|
{
|
||||||
|
// DisplayName.SetDefault("Neptune");
|
||||||
|
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.Neptune;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override List<string> SetNPCNameList()
|
||||||
|
{
|
||||||
|
return new List<string>() {
|
||||||
|
"Neptune"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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 "*Splashing water sounds*";
|
||||||
|
case 1:
|
||||||
|
return "The ocean calls...";
|
||||||
|
case 2:
|
||||||
|
return "Do you like water?";
|
||||||
|
default:
|
||||||
|
return "Waves crash eternally...";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.WaterBolt;
|
||||||
|
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,69 @@
|
|||||||
|
using Terraria;
|
||||||
|
using Terraria.ID;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech.Content.NPCs.OriginalNeptune
|
||||||
|
{
|
||||||
|
[AutoloadBossHead]
|
||||||
|
public class Raccoon : ModNPC
|
||||||
|
{
|
||||||
|
public override void SetStaticDefaults()
|
||||||
|
{
|
||||||
|
// DisplayName.SetDefault("Raccoon");
|
||||||
|
Main.npcFrameCount[NPC.type] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetDefaults()
|
||||||
|
{
|
||||||
|
NPC.width = 40;
|
||||||
|
NPC.height = 40;
|
||||||
|
NPC.damage = 70;
|
||||||
|
NPC.defense = 16;
|
||||||
|
NPC.lifeMax = 18000;
|
||||||
|
NPC.HitSound = SoundID.NPCHit1;
|
||||||
|
NPC.DeathSound = SoundID.NPCDeath1;
|
||||||
|
NPC.knockBackResist = 0f;
|
||||||
|
NPC.boss = true;
|
||||||
|
NPC.aiStyle = -1; // custom behavior later
|
||||||
|
NPC.value = Item.buyPrice(0, 1, 75, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AI()
|
||||||
|
{
|
||||||
|
// Placeholder AI: dash toward player occasionally
|
||||||
|
Player target = Main.player[NPC.target];
|
||||||
|
if (!target.active || target.dead)
|
||||||
|
{
|
||||||
|
NPC.TargetClosest(false);
|
||||||
|
target = Main.player[NPC.target];
|
||||||
|
if (!target.active || target.dead)
|
||||||
|
{
|
||||||
|
NPC.velocity.Y -= 0.1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NPC.ai[0]++;
|
||||||
|
if (NPC.ai[0] < 60)
|
||||||
|
{
|
||||||
|
// approach
|
||||||
|
Vector2 dir = target.Center - NPC.Center;
|
||||||
|
dir.Normalize();
|
||||||
|
NPC.velocity = dir * 3f;
|
||||||
|
}
|
||||||
|
else if (NPC.ai[0] == 60)
|
||||||
|
{
|
||||||
|
// dash
|
||||||
|
Vector2 dash = target.Center - NPC.Center;
|
||||||
|
dash.Normalize();
|
||||||
|
NPC.velocity = dash * 10f;
|
||||||
|
}
|
||||||
|
else if (NPC.ai[0] > 120)
|
||||||
|
{
|
||||||
|
NPC.ai[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NPC.spriteDirection = NPC.direction = (target.Center.X < NPC.Center.X) ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 504 B |
@@ -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>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 504 B |
|
After Width: | Height: | Size: 504 B |
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using System.IO;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.ModLoader.IO;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech
|
||||||
|
{
|
||||||
|
// Please read https://github.com/tModLoader/tModLoader/wiki/Basic-tModLoader-Modding-Guide#mod-skeleton-contents for more information about the various files in a mod.
|
||||||
|
public class ForgottenWawiTech : Mod
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<!-- Import tModLoader mod properties -->
|
||||||
|
<Import Project="..\tModLoader.targets" />
|
||||||
|
|
||||||
|
<!-- General -->
|
||||||
|
<PropertyGroup>
|
||||||
|
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- References -->
|
||||||
|
<ItemGroup>
|
||||||
|
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.5.2.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ForgottenWawiTech", "ForgottenWawiTech.csproj", "{21F9DB8D-48F0-6003-B105-E35E06F69FEB}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{21F9DB8D-48F0-6003-B105-E35E06F69FEB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{21F9DB8D-48F0-6003-B105-E35E06F69FEB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{21F9DB8D-48F0-6003-B105-E35E06F69FEB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{21F9DB8D-48F0-6003-B105-E35E06F69FEB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {BE0328FD-FC45-46F6-9816-4A2C742D5427}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
# This file will automatically update with entries for new content after a build and reload.
|
||||||
|
|
||||||
|
Items: {
|
||||||
|
Nyanageddon: {
|
||||||
|
Tooltip:
|
||||||
|
'''
|
||||||
|
Mob the rainbow, taste the rainbow.
|
||||||
|
Ethically questionable.
|
||||||
|
'''
|
||||||
|
DisplayName: Nyanageddon
|
||||||
|
}
|
||||||
|
|
||||||
|
BoulderCannon: {
|
||||||
|
Tooltip:
|
||||||
|
'''
|
||||||
|
I've been a baaaaad raccoon.
|
||||||
|
Fires boulders at supersonic speeds.
|
||||||
|
Useful for punishing raccoons.
|
||||||
|
'''
|
||||||
|
DisplayName: Pete
|
||||||
|
}
|
||||||
|
|
||||||
|
TrueNyanageddon: {
|
||||||
|
Tooltip: Why are you like this?
|
||||||
|
DisplayName: True Nyanageddon
|
||||||
|
}
|
||||||
|
|
||||||
|
NikoSummon: {
|
||||||
|
Tooltip:
|
||||||
|
'''
|
||||||
|
Summons Niko.
|
||||||
|
Not consumable
|
||||||
|
'You are about to have a bad time.'
|
||||||
|
'''
|
||||||
|
DisplayName: Niko Summon
|
||||||
|
}
|
||||||
|
|
||||||
|
NeptuneSummon: {
|
||||||
|
Tooltip:
|
||||||
|
'''
|
||||||
|
Summons Neptune.
|
||||||
|
Not consumable
|
||||||
|
'The waves are restless...'
|
||||||
|
'''
|
||||||
|
DisplayName: Neptune Summon
|
||||||
|
}
|
||||||
|
|
||||||
|
LyykaSummon: {
|
||||||
|
Tooltip:
|
||||||
|
'''
|
||||||
|
Summons Lyyka.
|
||||||
|
Not consumable
|
||||||
|
'You hear several voices calling out...'
|
||||||
|
'''
|
||||||
|
DisplayName: Lyyka Summon
|
||||||
|
}
|
||||||
|
|
||||||
|
LexySummon: {
|
||||||
|
DisplayName: Lexy Summon
|
||||||
|
Tooltip:
|
||||||
|
'''
|
||||||
|
Summons Lexy.
|
||||||
|
Not consumable
|
||||||
|
'Twist their minds.'
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NPCs: {
|
||||||
|
Lexy.DisplayName: Lexy
|
||||||
|
|
||||||
|
LexyNPC: {
|
||||||
|
DisplayName: Lexy
|
||||||
|
|
||||||
|
TownNPCMood: {
|
||||||
|
Content: I am content.
|
||||||
|
NoHome: I hate not having a home.
|
||||||
|
FarFromHome: I am too far from home.
|
||||||
|
LoveSpace: I love having so much space.
|
||||||
|
DislikeCrowded: I dislike how crowded I am.
|
||||||
|
HateCrowded: I hate how crowded I am.
|
||||||
|
LikeNPC_Princess: I like {NPCName}.
|
||||||
|
Princess_LovesNPC: I like {NPCName}.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Clara.DisplayName: Clara
|
||||||
|
Lyyka.DisplayName: Lyyka
|
||||||
|
|
||||||
|
LyykaNPC: {
|
||||||
|
DisplayName: Lyyka
|
||||||
|
|
||||||
|
TownNPCMood: {
|
||||||
|
Content: I am content.
|
||||||
|
NoHome: I hate not having a home.
|
||||||
|
FarFromHome: I am too far from home.
|
||||||
|
LoveSpace: I love having so much space.
|
||||||
|
DislikeCrowded: I dislike how crowded I am.
|
||||||
|
HateCrowded: I hate how crowded I am.
|
||||||
|
LikeNPC_Princess: I like {NPCName}.
|
||||||
|
Princess_LovesNPC: I like {NPCName}.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Terra.DisplayName: Terra
|
||||||
|
Neptune.DisplayName: Neptune
|
||||||
|
|
||||||
|
NeptuneNPC: {
|
||||||
|
DisplayName: Neptune
|
||||||
|
|
||||||
|
TownNPCMood: {
|
||||||
|
Content: I am content.
|
||||||
|
NoHome: I hate not having a home.
|
||||||
|
FarFromHome: I am too far from home.
|
||||||
|
LoveSpace: I love having so much space.
|
||||||
|
DislikeCrowded: I dislike how crowded I am.
|
||||||
|
HateCrowded: I hate how crowded I am.
|
||||||
|
LikeNPC_Princess: I like {NPCName}.
|
||||||
|
Princess_LovesNPC: I like {NPCName}.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Raccoon.DisplayName: Raccoon
|
||||||
|
Niko.DisplayName: Niko
|
||||||
|
|
||||||
|
NikoNPC: {
|
||||||
|
DisplayName: Niko
|
||||||
|
|
||||||
|
TownNPCMood: {
|
||||||
|
Content: I am content.
|
||||||
|
NoHome: I hate not having a home.
|
||||||
|
FarFromHome: I am too far from home.
|
||||||
|
LoveSpace: I love having so much space.
|
||||||
|
DislikeCrowded: I dislike how crowded I am.
|
||||||
|
HateCrowded: I hate how crowded I am.
|
||||||
|
LikeNPC_Princess: I like {NPCName}.
|
||||||
|
Princess_LovesNPC: I like {NPCName}.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Terraria": {
|
||||||
|
"commandName": "Executable",
|
||||||
|
"executablePath": "$(DotNetName)",
|
||||||
|
"commandLineArgs": "$(tMLPath)",
|
||||||
|
"workingDirectory": "$(tMLSteamPath)"
|
||||||
|
},
|
||||||
|
"TerrariaServer": {
|
||||||
|
"commandName": "Executable",
|
||||||
|
"executablePath": "$(DotNetName)",
|
||||||
|
"commandLineArgs": "$(tMLServerPath)",
|
||||||
|
"workingDirectory": "$(tMLSteamPath)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Terraria;
|
||||||
|
using Terraria.ModLoader;
|
||||||
|
using Terraria.ModLoader.IO;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
|
||||||
|
namespace ForgottenWawiTech
|
||||||
|
{
|
||||||
|
public class WorldDefeatedBosses : ModSystem
|
||||||
|
{
|
||||||
|
public static bool Niko;
|
||||||
|
public static bool Lyyka;
|
||||||
|
public static bool Neptune;
|
||||||
|
public static bool Lexy;
|
||||||
|
public static bool Terra;
|
||||||
|
public static bool Clara;
|
||||||
|
public static bool Raccoon;
|
||||||
|
|
||||||
|
public override void OnWorldUnload()
|
||||||
|
{
|
||||||
|
Niko = Lyyka = Neptune = Lexy = Terra = Clara = Raccoon = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SaveWorldData(TagCompound tag)
|
||||||
|
{
|
||||||
|
var list = new List<string>();
|
||||||
|
if (Niko) list.Add("Niko");
|
||||||
|
if (Lyyka) list.Add("Lyyka");
|
||||||
|
if (Neptune) list.Add("Neptune");
|
||||||
|
if (Lexy) list.Add("Lexy");
|
||||||
|
if (Terra) list.Add("Terra");
|
||||||
|
if (Clara) list.Add("Clara");
|
||||||
|
if (Raccoon) list.Add("Raccoon");
|
||||||
|
|
||||||
|
tag["ForgottenWawiTech_DefeatedBosses"] = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadWorldData(TagCompound tag)
|
||||||
|
{
|
||||||
|
if (tag.TryGet<List<string>>("ForgottenWawiTech_DefeatedBosses", out var list))
|
||||||
|
{
|
||||||
|
Niko = list.Contains("Niko");
|
||||||
|
Lyyka = list.Contains("Lyyka");
|
||||||
|
Neptune = list.Contains("Neptune");
|
||||||
|
Lexy = list.Contains("Lexy");
|
||||||
|
Terra = list.Contains("Terra");
|
||||||
|
Clara = list.Contains("Clara");
|
||||||
|
Raccoon = list.Contains("Raccoon");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Niko = Lyyka = Neptune = Lexy = Terra = Clara = Raccoon = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void NetSend(BinaryWriter writer)
|
||||||
|
{
|
||||||
|
var flags = new BitsByte(
|
||||||
|
Niko,
|
||||||
|
Lyyka,
|
||||||
|
Neptune,
|
||||||
|
Lexy,
|
||||||
|
Terra,
|
||||||
|
Clara,
|
||||||
|
Raccoon
|
||||||
|
);
|
||||||
|
writer.Write((byte)flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void NetReceive(BinaryReader reader)
|
||||||
|
{
|
||||||
|
BitsByte flags = reader.ReadByte();
|
||||||
|
Niko = flags[0];
|
||||||
|
Lyyka = flags[1];
|
||||||
|
Neptune = flags[2];
|
||||||
|
Lexy = flags[3];
|
||||||
|
Terra = flags[4];
|
||||||
|
Clara = flags[5];
|
||||||
|
Raccoon = flags[6];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Immediate network sync helper to broadcast current flags to clients.
|
||||||
|
public static void Sync(Mod mod)
|
||||||
|
{
|
||||||
|
if (mod == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var flags = new BitsByte(
|
||||||
|
Niko,
|
||||||
|
Lyyka,
|
||||||
|
Neptune,
|
||||||
|
Lexy,
|
||||||
|
Terra,
|
||||||
|
Clara,
|
||||||
|
Raccoon
|
||||||
|
);
|
||||||
|
|
||||||
|
ModPacket packet = mod.GetPacket();
|
||||||
|
packet.Write((byte)0); // message type 0 = sync world defeated bosses
|
||||||
|
packet.Write((byte)flags);
|
||||||
|
packet.Send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
displayName = The Forgotten Wawi Tech
|
||||||
|
author = EclypsedMoonfall, Axl_the_Protogen
|
||||||
|
version = 0.1
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Susie's Idea.
|
||||||
|
This mod is solely created for a modpack I am using for myself and friends. You can add it if you want - but I don't know why you would.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Susie's Idea.
|
||||||
|
This mod is solely created for a modpack I am using for myself and friends. You can add it if you want - but I don't know why you would.
|
||||||
|
After Width: | Height: | Size: 3.3 KiB |