Finish set bonuses, add more options to the Avali Trader

This commit is contained in:
2025-11-20 16:22:50 +00:00
parent 9162878883
commit b30fcc9563
44 changed files with 1744 additions and 81 deletions
@@ -0,0 +1,23 @@
using Terraria;
using Terraria.DataStructures;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Projectiles.Protogen;
namespace ForgottenWawiTech.Content.GlobalProjectiles
{
public class ProtogenSentinelGlobalProjectile : GlobalProjectile
{
public bool DisableSentinelSplit { get; set; }
public override bool InstancePerEntity => true;
public override void OnSpawn(Projectile projectile, IEntitySource source)
{
if (projectile.type == ModContent.ProjectileType<ProtogenSentinelFragment>() ||
projectile.type == ModContent.ProjectileType<ProtogenSentinelCoreBeam>())
{
DisableSentinelSplit = true;
}
}
}
}
@@ -5,6 +5,7 @@ using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet; using ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet
{ {
@@ -44,7 +45,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet
} }
player.endurance += 0.10f; player.endurance += 0.10f;
// TODO: Implement hunting drone projectile system player.GetModPlayer<AvaliVanguardPlayer>().EnableHuntingDrones();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -5,6 +5,7 @@ using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet; using ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet
{ {
@@ -45,7 +46,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet
} }
player.endurance += 0.10f; player.endurance += 0.10f;
// TODO: Implement hunting drone projectile system player.GetModPlayer<AvaliVanguardPlayer>().EnableHuntingDrones();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -5,6 +5,7 @@ using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet; using ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet
{ {
@@ -45,7 +46,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet
} }
player.endurance += 0.10f; player.endurance += 0.10f;
// TODO: Implement hunting drone projectile system player.GetModPlayer<AvaliVanguardPlayer>().EnableHuntingDrones();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -5,6 +5,7 @@ using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet; using ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet
{ {
@@ -44,7 +45,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.AvaliVanguardSet
} }
player.endurance += 0.10f; player.endurance += 0.10f;
// TODO: Implement hunting drone projectile system player.GetModPlayer<AvaliVanguardPlayer>().EnableHuntingDrones();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -4,6 +4,7 @@ using Terraria.ModLoader;
using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Items.Armor.ProtogenInitiateSet; using ForgottenWawiTech.Content.Items.Armor.ProtogenInitiateSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet
{ {
@@ -37,7 +38,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet
player.setBonus = "Taking damage releases seeking nanites\nNanites heal you for 50% of damage dealt\n+2 max minions and +18% summon damage"; player.setBonus = "Taking damage releases seeking nanites\nNanites heal you for 50% of damage dealt\n+2 max minions and +18% summon damage";
player.maxMinions += 2; player.maxMinions += 2;
player.GetDamage(DamageClass.Summon) += 0.18f; player.GetDamage(DamageClass.Summon) += 0.18f;
// TODO: Implement nanite swarm healing system player.GetModPlayer<ProtogenOperativePlayer>().EnableNaniteSwarm();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -4,6 +4,7 @@ using Terraria.ModLoader;
using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Items.Armor.ProtogenInitiateSet; using ForgottenWawiTech.Content.Items.Armor.ProtogenInitiateSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet
{ {
@@ -38,7 +39,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet
player.setBonus = "Taking damage releases seeking nanites\nNanites heal you for 50% of damage dealt\n+12% melee damage and speed"; player.setBonus = "Taking damage releases seeking nanites\nNanites heal you for 50% of damage dealt\n+12% melee damage and speed";
player.GetDamage(DamageClass.Melee) += 0.12f; player.GetDamage(DamageClass.Melee) += 0.12f;
player.GetAttackSpeed(DamageClass.Melee) += 0.12f; player.GetAttackSpeed(DamageClass.Melee) += 0.12f;
// TODO: Implement nanite swarm healing system player.GetModPlayer<ProtogenOperativePlayer>().EnableNaniteSwarm();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -4,6 +4,7 @@ using Terraria.ModLoader;
using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Items.Armor.ProtogenInitiateSet; using ForgottenWawiTech.Content.Items.Armor.ProtogenInitiateSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet
{ {
@@ -37,7 +38,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet
player.setBonus = "Taking damage releases seeking nanites\nNanites heal you for 50% of damage dealt\n+18% magic damage and -18% mana cost"; player.setBonus = "Taking damage releases seeking nanites\nNanites heal you for 50% of damage dealt\n+18% magic damage and -18% mana cost";
player.GetDamage(DamageClass.Magic) += 0.18f; player.GetDamage(DamageClass.Magic) += 0.18f;
player.manaCost -= 0.18f; player.manaCost -= 0.18f;
// TODO: Implement nanite swarm healing system player.GetModPlayer<ProtogenOperativePlayer>().EnableNaniteSwarm();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -4,6 +4,7 @@ using Terraria.ModLoader;
using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Items.Armor.ProtogenInitiateSet; using ForgottenWawiTech.Content.Items.Armor.ProtogenInitiateSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet
{ {
@@ -37,7 +38,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet
player.setBonus = "Taking damage releases seeking nanites\nNanites heal you for 50% of damage dealt\n+15% ranged damage and critical strike chance"; player.setBonus = "Taking damage releases seeking nanites\nNanites heal you for 50% of damage dealt\n+15% ranged damage and critical strike chance";
player.GetDamage(DamageClass.Ranged) += 0.15f; player.GetDamage(DamageClass.Ranged) += 0.15f;
player.GetCritChance(DamageClass.Ranged) += 15; player.GetCritChance(DamageClass.Ranged) += 15;
// TODO: Implement nanite swarm healing system player.GetModPlayer<ProtogenOperativePlayer>().EnableNaniteSwarm();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -5,6 +5,7 @@ using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet; using ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet
{ {
@@ -47,7 +48,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet
player.buffImmune[BuffID.Weak] = true; player.buffImmune[BuffID.Weak] = true;
player.buffImmune[BuffID.Silenced] = true; player.buffImmune[BuffID.Silenced] = true;
player.buffImmune[BuffID.Cursed] = true; player.buffImmune[BuffID.Cursed] = true;
// TODO: Implement AI core projectile and splitting projectile system player.GetModPlayer<ProtogenSentinelPlayer>().EnableSentinelCore();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -5,6 +5,7 @@ using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet; using ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet
{ {
@@ -48,7 +49,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet
player.buffImmune[BuffID.Weak] = true; player.buffImmune[BuffID.Weak] = true;
player.buffImmune[BuffID.Silenced] = true; player.buffImmune[BuffID.Silenced] = true;
player.buffImmune[BuffID.Cursed] = true; player.buffImmune[BuffID.Cursed] = true;
// TODO: Implement AI core projectile and splitting projectile system player.GetModPlayer<ProtogenSentinelPlayer>().EnableSentinelCore();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -5,6 +5,7 @@ using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet; using ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet
{ {
@@ -47,7 +48,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet
player.buffImmune[BuffID.Weak] = true; player.buffImmune[BuffID.Weak] = true;
player.buffImmune[BuffID.Silenced] = true; player.buffImmune[BuffID.Silenced] = true;
player.buffImmune[BuffID.Cursed] = true; player.buffImmune[BuffID.Cursed] = true;
// TODO: Implement AI core projectile and splitting projectile system player.GetModPlayer<ProtogenSentinelPlayer>().EnableSentinelCore();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -5,6 +5,7 @@ using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet; using ForgottenWawiTech.Content.Items.Armor.ProtogenOperativeSet;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet
{ {
@@ -47,7 +48,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.ProtogenSentinelSet
player.buffImmune[BuffID.Weak] = true; player.buffImmune[BuffID.Weak] = true;
player.buffImmune[BuffID.Silenced] = true; player.buffImmune[BuffID.Silenced] = true;
player.buffImmune[BuffID.Cursed] = true; player.buffImmune[BuffID.Cursed] = true;
// TODO: Implement AI core projectile and splitting projectile system player.GetModPlayer<ProtogenSentinelPlayer>().EnableSentinelCore();
} }
public override void AddRecipes() public override void AddRecipes()
@@ -4,6 +4,7 @@ using Terraria.ModLoader;
using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Items.Materials;
using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Rarities;
using ForgottenWawiTech.Content.Tiles.CraftingStations; using ForgottenWawiTech.Content.Tiles.CraftingStations;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.SingularitySet namespace ForgottenWawiTech.Content.Items.Armor.SingularitySet
{ {
@@ -40,9 +41,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.SingularitySet
player.GetCritChance(DamageClass.Generic) += 20; player.GetCritChance(DamageClass.Generic) += 20;
player.endurance += 0.15f; player.endurance += 0.15f;
player.waterWalk = true; player.waterWalk = true;
player.GetModPlayer<SingularityPlayer>().EnableSingularityOrb();
// TODO: Implement singularity orb minion projectile
// For now, grant increased stats as placeholder
} }
public override void AddRecipes() public override void AddRecipes()
@@ -2,6 +2,7 @@ using System;
using Terraria; using Terraria;
using Terraria.ID; using Terraria.ID;
using Terraria.ModLoader; using Terraria.ModLoader;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Items.Armor.TranscendentSet namespace ForgottenWawiTech.Content.Items.Armor.TranscendentSet
{ {
@@ -87,7 +88,9 @@ namespace ForgottenWawiTech.Content.Items.Armor.TranscendentSet
player.buffImmune[buffId] = true; player.buffImmune[buffId] = true;
} }
// TODO: Implement Ascendant Swarm minions, sentinel beam volley, and nanite shard projectiles. player.GetModPlayer<TranscendentPlayer>().EnableTranscendentSet();
player.GetModPlayer<ProtogenSentinelPlayer>().EnableSentinelCore();
player.GetModPlayer<SingularityPlayer>().EnableSingularityOrb();
} }
} }
} }
+160 -34
View File
@@ -1,14 +1,69 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using Terraria; using Terraria;
using Terraria.ID; using Terraria.ID;
using Terraria.ModLoader; using Terraria.ModLoader;
using Terraria.GameContent.Personalities; using Terraria.GameContent.Personalities;
using Terraria.Localization; using Terraria.Localization;
using ForgottenWawiTech;
namespace ForgottenWawiTech.Content.NPCs.TownNPCs namespace ForgottenWawiTech.Content.NPCs.TownNPCs
{ {
public class AvalianTrader : ModNPC public class AvalianTrader : ModNPC
{ {
private static readonly Condition HasDefeatedAnyMechBoss = new("Mods.ForgottenWawiTech.Conditions.HasDefeatedAnyMechBoss", () =>
NPC.downedMechBoss1 || NPC.downedMechBoss2 || NPC.downedMechBoss3);
private static readonly Condition HasDefeatedLexy = new("Mods.ForgottenWawiTech.Conditions.HasDefeatedLexy", () =>
Main.hardMode && WorldDefeatedBosses.Lexy);
private static readonly Condition HasDefeatedNiko = new("Mods.ForgottenWawiTech.Conditions.HasDefeatedNiko", () =>
Main.hardMode && WorldDefeatedBosses.Niko);
private static readonly Condition HasDefeatedNeptune = new("Mods.ForgottenWawiTech.Conditions.HasDefeatedNeptune", () =>
Main.hardMode && WorldDefeatedBosses.Neptune);
private static readonly Condition HasDefeatedLyyka = new("Mods.ForgottenWawiTech.Conditions.HasDefeatedLyyka", () =>
Main.hardMode && WorldDefeatedBosses.Lyyka);
private static readonly Condition HasDefeatedCorruptedSwarm = new("Mods.ForgottenWawiTech.Conditions.HasDefeatedCorruptedSwarm", () =>
Main.hardMode && WorldDefeatedBosses.Niko); // TODO: Replace with Corrupted Swarm flag once implemented.
private static readonly Condition HasDefeatedExoMechs = new("Mods.ForgottenWawiTech.Conditions.HasDefeatedExoMechs", CheckExoMechsDowned);
private static readonly Condition HasDefeatedMoonLord = new("Mods.ForgottenWawiTech.Conditions.HasDefeatedMoonLord", () =>
NPC.downedMoonlord);
private static bool CheckExoMechsDowned()
{
if (!ModLoader.TryGetMod("CalamityMod", out Mod calamityMod))
{
return false;
}
var calamityWorldType = calamityMod.Code?.GetType("CalamityMod.World.CalamityWorld");
if (calamityWorldType == null)
{
return false;
}
const BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
var field = calamityWorldType.GetField("downedExoMechs", flags);
if (field?.GetValue(null) is bool fieldValue)
{
return fieldValue;
}
var property = calamityWorldType.GetProperty("downedExoMechs", flags);
if (property?.GetValue(null) is bool propertyValue)
{
return propertyValue;
}
return false;
}
public override void SetStaticDefaults() public override void SetStaticDefaults()
{ {
Main.npcFrameCount[NPC.type] = 25; // The amount of frames the NPC has Main.npcFrameCount[NPC.type] = 25; // The amount of frames the NPC has
@@ -92,48 +147,119 @@ namespace ForgottenWawiTech.Content.NPCs.TownNPCs
public override void AddShops() public override void AddShops()
{ {
Item rainbowBrick = new();
rainbowBrick.SetDefaults(ItemID.RainbowBrick);
rainbowBrick.value = Item.buyPrice(silver: 90);
new NPCShop(Type) new NPCShop(Type)
.Add<Items.Materials.RGBass>(Condition.DownedMoonLord) .Add<Items.Materials.VisorShard>(HasDefeatedLexy)
.Add<Items.Materials.VisorShard>(Condition.Hardmode) .Add<Items.Materials.FallenAngelFeather>(HasDefeatedNiko)
.Add(ItemID.RainbowBrick, Condition.Hardmode) // TODO: Force Rainbow Brick to not have No Value. .Add<Items.Materials.HalfEatenFish>(HasDefeatedNeptune)
.Add<Items.Materials.LyykaBossDrop>(HasDefeatedLyyka)
.Add<Items.Materials.UnstableMatter>(HasDefeatedCorruptedSwarm)
.Add(rainbowBrick, Condition.Hardmode)
.Add<Items.Materials.AvaliFeather>() .Add<Items.Materials.AvaliFeather>()
.Add<Items.Materials.RGBAlloy>(HasDefeatedMoonLord)
.Add<Items.Materials.EnergyCore>(HasDefeatedAnyMechBoss)
.Add<Items.Materials.ContainmentUnit>(HasDefeatedExoMechs)
.Add<Items.Materials.ControlledSingularity>(HasDefeatedExoMechs)
.Add<Items.Materials.MiniSingularity>(HasDefeatedExoMechs)
.Add<Items.Materials.SingularityAlloy>(HasDefeatedExoMechs)
.Add<Items.Materials.RGBass>(HasDefeatedMoonLord)
.Register(); .Register();
} }
public override string GetChat() public override string GetChat()
{ {
switch (Main.rand.Next(15)) List<string> lines = new()
{ {
case 0: "*avalian chirping*",
return "*avalian chirping*"; "Welcome! I've traveled far from Avalon to bring you the finest technology.",
case 1: "My pack may be small, but I've traversed dimensions to get here.",
return "Welcome! I've traveled far from Avalon to bring you the finest technology."; "*chirps excitedly* Oh, you're interested in our wares?",
case 2: "RGBass - it's not just a material, it's a lifestyle.",
return "These feathers? They're not just for show - they're quite valuable!"; "Those rainbow bricks? Ninety silver each. I have transport costs, you know.",
case 3: "The journey here was long, but your world has such fascinating resources!",
return "RGB technology is all the rage back home. Everything needs more colors!"; "Need something? My shop is always open!",
case 4: "Avalian markets never sleep; neither does my inventory.",
return "The visor shards I sell are fragments from our most advanced equipment."; "If you see a hover sled parked outside, please don't touch the controls.",
case 5: "Try not to lick the stock. Some of it bites back.",
return "My pack may be small, but I've traversed dimensions to get here."; "The atmosphere here is thick, but profits make it worth the acclimation.",
case 6: "I keep a thermal blanket under the clothes —these nights get cold even for an Avali.",
return "*chirps excitedly* Oh, you're interested in our wares?"; "Do you have any idea how much customs paperwork interstellar trade requires?",
case 7: "If you hear humming, that's just the containment field. Probably."
return "Avalon sends its regards! And its finest materials."; };
case 8:
return "Don't underestimate the power of a well-crafted alloy."; if (HasDefeatedLexy.IsMet())
case 9: {
return "The journey here was long, but your world has such fascinating resources!"; lines.Add("Defeated Lexy, have you? His visor shards always sell out fast.");
case 10: lines.Add("Lexy's visor tech makes for excellent souvenirs. Stock up while I have them.");
return "*preens feathers* Presentation is important in any trade.";
case 11:
return "RGBass - it's not just a material, it's a lifestyle.";
case 12:
return "I wonder what the other traders back on Avalon would think of this place...";
case 13:
return "My species may be small, but we're excellent engineers!";
default:
return "Need something? My shop is always open!";
} }
else if (Main.hardMode)
{
lines.Add("Still hunting Lexy? Bring me his visor and I'll unlock some premium stock.");
}
if (HasDefeatedNiko.IsMet())
{
lines.Add("Astramora's Fallen Angel Feathers? Delicate, pricey, worth every coin.");
lines.Add("I've reinforced the shipping crates just for Astramora's volatile feathers.");
}
else if (Main.hardMode)
{
lines.Add("I've heard whispers of a rat angel around these parts of the galaxy...");
}
if (HasDefeatedNeptune.IsMet())
{
lines.Add("Neptune leaves quite the mess. Half-eaten fish, anyone?");
lines.Add("Neptune's half-eaten catches sell faster than I'd like—apparently otter bites add flavor.");
}
else if (Main.hardMode)
{
lines.Add("If you're braving the tides, bring Neptune down and I'll import his catches.");
}
if (HasDefeatedLyyka.IsMet())
{
lines.Add("Avalon sends its regards! Lyyka's gear is highly sought after.");
lines.Add("Lyyka's encore was explosive. Her gear? Even more so.");
}
else if (Main.hardMode)
{
lines.Add("Bring down Lyyka and I'll uncrate her signature alloys.");
}
if (HasDefeatedCorruptedSwarm.IsMet())
{
lines.Add("Unstable Matter? Just delicate enough for my clientele.");
lines.Add("Careful with the Unstable Matter; Avalon still has a watchful eye on it.");
}
else if (Main.hardMode)
{
lines.Add("Rumor says there is a swarm of corrupted tech out there. If you defeat it, I might have something worth the risk.");
}
if (HasDefeatedAnyMechBoss.IsMet())
{
lines.Add("Mechanical husks make great recycling. Fancy some RGB alloys?");
}
if (HasDefeatedMoonLord.IsMet())
{
lines.Add("Moon Lord down? Excellent. His trinkets pair nicely with Avalian engineering.");
}
if (HasDefeatedExoMechs.IsMet())
{
lines.Add("The Exo Mechs are no more? Splendid! I've got singularities ready for purchase.");
lines.Add("You walked away from the Exo Mechs? Take these singularities before they destabilize.");
}
else if (ModLoader.TryGetMod("CalamityMod", out _))
{
lines.Add("Calamity's Exo Mechs still stalk your skies. Ground them and my singularity cache opens.");
}
return lines.Count > 0 ? lines[Main.rand.Next(lines.Count)] : "Need something? My shop is always open!";
} }
public override void TownNPCAttackStrength(ref int damage, ref float knockback) public override void TownNPCAttackStrength(ref int damage, ref float knockback)
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Projectiles.Avali;
namespace ForgottenWawiTech.Content.Players
{
public class AvaliVanguardPlayer : ModPlayer
{
private const int DroneCount = 3;
private const float SpawnRadius = 72f;
public bool HuntingDronesActive { get; private set; }
public static int GetDroneBaseDamage(Player player)
{
const int droneBaseDamage = 240;
return (int)player.GetTotalDamage(DamageClass.Summon).ApplyTo(droneBaseDamage);
}
public override void ResetEffects()
{
HuntingDronesActive = false;
}
public void EnableHuntingDrones()
{
HuntingDronesActive = true;
}
public override void PostUpdate()
{
if (!HuntingDronesActive || Player.whoAmI != Main.myPlayer)
{
return;
}
int droneType = ModContent.ProjectileType<AvaliHuntingDrone>();
int owned = Player.ownedProjectileCounts[droneType];
if (owned >= DroneCount)
{
return;
}
var source = Player.GetSource_Misc("AvaliVanguardSet");
for (int i = owned; i < DroneCount; i++)
{
float rotationOffset = MathHelper.TwoPi * i / DroneCount;
Vector2 spawnPos = Player.Center + rotationOffset.ToRotationVector2() * SpawnRadius;
Projectile projectile = Projectile.NewProjectileDirect(
source,
spawnPos,
Vector2.Zero,
droneType,
0,
0f,
Player.whoAmI,
i,
DroneCount);
projectile.originalDamage = GetDroneBaseDamage(Player);
}
}
}
}
@@ -0,0 +1,71 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Projectiles.Protogen;
namespace ForgottenWawiTech.Content.Players
{
public class ProtogenOperativePlayer : ModPlayer
{
private const int NaniteProjectileCount = 3;
private const int NaniteCooldownTicks = 90;
private const int NaniteBaseDamage = 90;
private const float NaniteSpawnRadius = 30f;
private int naniteCooldownTimer;
public bool NaniteSwarmActive { get; private set; }
public override void ResetEffects()
{
NaniteSwarmActive = false;
}
public override void UpdateDead()
{
NaniteSwarmActive = false;
naniteCooldownTimer = 0;
}
public override void PostUpdate()
{
if (naniteCooldownTimer > 0)
{
naniteCooldownTimer--;
}
}
public void EnableNaniteSwarm()
{
NaniteSwarmActive = true;
}
public override void OnHurt(Player.HurtInfo info)
{
if (!NaniteSwarmActive || info.Damage <= 0 || naniteCooldownTimer > 0 || Player.whoAmI != Main.myPlayer)
{
return;
}
naniteCooldownTimer = NaniteCooldownTicks;
var source = Player.GetSource_Misc("ProtogenOperativeNanites");
int damage = (int)Player.GetTotalDamage(DamageClass.Generic).ApplyTo(NaniteBaseDamage);
for (int i = 0; i < NaniteProjectileCount; i++)
{
float angle = MathHelper.TwoPi * i / NaniteProjectileCount;
Vector2 spawnOffset = angle.ToRotationVector2() * NaniteSpawnRadius;
Vector2 spawnVelocity = spawnOffset.SafeNormalize(Vector2.UnitY) * 6f + Player.velocity;
Projectile.NewProjectile(
source,
Player.Center + spawnOffset,
spawnVelocity,
ModContent.ProjectileType<ProtogenOperativeNanite>(),
damage,
2f,
Player.whoAmI);
}
}
}
}
+125
View File
@@ -0,0 +1,125 @@
using System;
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Projectiles.Protogen;
using ForgottenWawiTech.Content.GlobalProjectiles;
namespace ForgottenWawiTech.Content.Players
{
public class ProtogenSentinelPlayer : ModPlayer
{
private const int CoreProjectileCount = 1;
private const int CoreBaseDamage = 320;
private const float CoreSpawnOffset = -68f;
private const float FragmentSplitChance = 0.20f;
public bool SentinelCoreActive { get; private set; }
public bool SentinelProjectileSplitActive { get; private set; }
public override void ResetEffects()
{
SentinelCoreActive = false;
SentinelProjectileSplitActive = false;
}
public void EnableSentinelCore()
{
SentinelCoreActive = true;
SentinelProjectileSplitActive = true;
}
public override void PostUpdate()
{
if (!SentinelCoreActive)
{
return;
}
if (Player.whoAmI != Main.myPlayer)
{
return;
}
int coreType = ModContent.ProjectileType<ProtogenSentinelCore>();
if (Player.ownedProjectileCounts[coreType] >= CoreProjectileCount)
{
return;
}
var source = Player.GetSource_Misc("ProtogenSentinelSet");
Vector2 spawnPos = Player.Center + new Vector2(0f, CoreSpawnOffset);
Projectile.NewProjectile(
source,
spawnPos,
Vector2.Zero,
coreType,
0,
0f,
Player.whoAmI);
}
public static int GetCoreDamage(Player player)
{
return (int)player.GetTotalDamage(DamageClass.Summon).ApplyTo(CoreBaseDamage);
}
public override void OnHitNPCWithProj(Projectile proj, NPC target, NPC.HitInfo hit, int damageDone)
{
if (!SentinelProjectileSplitActive || Player.whoAmI != Main.myPlayer)
{
return;
}
if (!proj.friendly || proj.owner != Player.whoAmI)
{
return;
}
if (proj.GetGlobalProjectile<ProtogenSentinelGlobalProjectile>().DisableSentinelSplit)
{
return;
}
if (proj.type == ModContent.ProjectileType<ProtogenSentinelCoreBeam>() || proj.type == ModContent.ProjectileType<ProtogenSentinelFragment>())
{
return;
}
if (damageDone <= 0)
{
return;
}
if (Main.rand.NextFloat() > FragmentSplitChance)
{
return;
}
SpawnFragments(proj, damageDone);
}
private void SpawnFragments(Projectile sourceProj, int damageDone)
{
int fragmentType = ModContent.ProjectileType<ProtogenSentinelFragment>();
int fragmentCount = 2;
int fragmentDamage = Math.Max(1, damageDone / 2);
var source = Player.GetSource_Misc("ProtogenSentinelSplit");
for (int i = 0; i < fragmentCount; i++)
{
float rotation = MathHelper.ToRadians(Main.rand.NextFloat(-18f, 18f));
Vector2 launch = sourceProj.velocity.SafeNormalize(Vector2.UnitY).RotatedBy(rotation) * 14f;
Projectile fragment = Projectile.NewProjectileDirect(
source,
sourceProj.Center,
launch,
fragmentType,
fragmentDamage,
2f,
Player.whoAmI);
fragment.GetGlobalProjectile<ProtogenSentinelGlobalProjectile>().DisableSentinelSplit = true;
}
}
}
}
+56
View File
@@ -0,0 +1,56 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Projectiles.Singularity;
namespace ForgottenWawiTech.Content.Players
{
public class SingularityPlayer : ModPlayer
{
private const int OrbProjectileLimit = 1;
private const int OrbBaseDamage = 420;
private const float OrbSpawnOffset = -80f;
public bool SingularityOrbActive { get; private set; }
public override void ResetEffects()
{
SingularityOrbActive = false;
}
public void EnableSingularityOrb()
{
SingularityOrbActive = true;
}
public override void PostUpdate()
{
if (!SingularityOrbActive || Player.whoAmI != Main.myPlayer)
{
return;
}
int orbType = ModContent.ProjectileType<SingularityOrb>();
if (Player.ownedProjectileCounts[orbType] >= OrbProjectileLimit)
{
return;
}
var source = Player.GetSource_Misc("SingularitySet");
Vector2 spawnPos = Player.Center + new Vector2(0f, OrbSpawnOffset);
Projectile.NewProjectile(
source,
spawnPos,
Vector2.Zero,
orbType,
0,
0f,
Player.whoAmI);
}
public static int GetOrbDamage(Player player)
{
return (int)player.GetTotalDamage(DamageClass.Generic).ApplyTo(OrbBaseDamage);
}
}
}
+185 -28
View File
@@ -1,5 +1,7 @@
using System;
using Microsoft.Xna.Framework; using Microsoft.Xna.Framework;
using Terraria; using Terraria;
using Terraria.DataStructures;
using Terraria.ID; using Terraria.ID;
using Terraria.ModLoader; using Terraria.ModLoader;
using ForgottenWawiTech.Content.Projectiles.Transcendent; using ForgottenWawiTech.Content.Projectiles.Transcendent;
@@ -8,60 +10,215 @@ namespace ForgottenWawiTech.Content.Players
{ {
public class TranscendentPlayer : ModPlayer public class TranscendentPlayer : ModPlayer
{ {
private const int AccessoryShardInterval = 90;
private const int SetShardInterval = 45;
private const int AccessoryShardBaseDamage = 220;
private const int SetShardBaseDamage = 320;
private const int AscendantDroneCount = 4;
private const int AscendantDroneBaseDamage = 360;
private const int NaniteShardBaseDamage = 260;
public bool SwarmModuleEquipped; public bool SwarmModuleEquipped;
private Item swarmAccessorySourceItem;
private int swarmTimer; private int swarmTimer;
private int naniteShardCooldown;
private bool transcendentSetActive;
public void HandleSwarmAccessory(Item sourceItem) public void HandleSwarmAccessory(Item sourceItem)
{ {
SwarmModuleEquipped = true; SwarmModuleEquipped = true;
swarmAccessorySourceItem = sourceItem;
}
if (Player.whoAmI != Main.myPlayer) public void EnableTranscendentSet()
return;
swarmTimer++;
if (swarmTimer >= 90)
{ {
swarmTimer = 0; transcendentSetActive = true;
int baseDamage = 220;
int damage = (int)Player.GetDamage(DamageClass.Summon).ApplyTo(baseDamage);
float knockBack = 3f;
Vector2 velocity = Main.rand.NextVector2Circular(6f, 6f);
if (velocity.LengthSquared() < 0.01f)
{
velocity = new Vector2(0f, -6f);
} }
Projectile.NewProjectile( public bool HasTranscendentSet => transcendentSetActive;
Player.GetSource_Accessory(sourceItem),
Player.Center,
velocity,
ModContent.ProjectileType<TranscendentBladeShard>(),
damage,
knockBack,
Player.whoAmI);
}
}
public override void ResetEffects() public override void ResetEffects()
{ {
SwarmModuleEquipped = false; SwarmModuleEquipped = false;
transcendentSetActive = false;
swarmAccessorySourceItem = null;
} }
public override void PostUpdate() public override void PostUpdate()
{ {
if (SwarmModuleEquipped) bool swarmActive = SwarmModuleEquipped || transcendentSetActive;
if (swarmActive && Player.whoAmI == Main.myPlayer)
{ {
if (Main.rand.NextBool(6)) int interval = transcendentSetActive ? SetShardInterval : AccessoryShardInterval;
swarmTimer++;
if (swarmTimer >= interval)
{ {
Dust dust = Dust.NewDustDirect(Player.position, Player.width, Player.height, DustID.RainbowTorch, Player.velocity.X * 0.2f, Player.velocity.Y * 0.2f, 150, default, 1.1f); swarmTimer = 0;
dust.noGravity = true; SpawnAscendantShards(transcendentSetActive);
} }
} }
else if (Player.whoAmI == Main.myPlayer && swarmTimer > 0) else if (Player.whoAmI == Main.myPlayer && swarmTimer > 0)
{ {
swarmTimer = 0; swarmTimer = 0;
} }
if (naniteShardCooldown > 0)
{
naniteShardCooldown--;
}
if (transcendentSetActive)
{
MaintainAscendantDrones();
}
if (swarmActive)
{
if (Main.rand.NextBool(transcendentSetActive ? 4 : 6))
{
Dust dust = Dust.NewDustDirect(Player.position, Player.width, Player.height, DustID.RainbowTorch, Player.velocity.X * 0.2f, Player.velocity.Y * 0.2f, 150, default, 1.1f);
dust.noGravity = true;
}
}
}
private void SpawnAscendantShards(bool fromSet)
{
int baseDamage = fromSet ? SetShardBaseDamage : AccessoryShardBaseDamage;
int damage = (int)Player.GetDamage(DamageClass.Summon).ApplyTo(baseDamage);
float knockBack = fromSet ? 4f : 3f;
float speed = fromSet ? 8f : 6f;
int shardCount = fromSet ? 2 : 1;
if (!fromSet && swarmAccessorySourceItem == null)
{
swarmAccessorySourceItem = Player.HeldItem;
}
IEntitySource source = fromSet
? Player.GetSource_Misc("TranscendentAscendantSwarm")
: Player.GetSource_Accessory(swarmAccessorySourceItem ?? Player.HeldItem);
for (int i = 0; i < shardCount; i++)
{
Vector2 velocity = Main.rand.NextVector2Circular(speed, speed);
if (velocity.LengthSquared() < 0.01f)
{
velocity = new Vector2(0f, -speed);
}
Projectile shard = Projectile.NewProjectileDirect(
source,
Player.Center,
velocity,
ModContent.ProjectileType<TranscendentBladeShard>(),
damage,
knockBack,
Player.whoAmI);
shard.originalDamage = damage;
}
}
private void MaintainAscendantDrones()
{
if (Player.whoAmI != Main.myPlayer)
{
return;
}
int droneType = ModContent.ProjectileType<TranscendentAscendantDrone>();
int owned = Player.ownedProjectileCounts[droneType];
if (owned >= AscendantDroneCount)
{
return;
}
var source = Player.GetSource_Misc("TranscendentAscendantDrones");
for (int i = owned; i < AscendantDroneCount; i++)
{
Projectile.NewProjectile(
source,
Player.Center,
Vector2.Zero,
droneType,
0,
0f,
Player.whoAmI,
i,
AscendantDroneCount);
}
}
public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone)
{
TrySpawnNaniteShards(target.Center, damageDone);
}
public override void OnHitNPCWithProj(Projectile proj, NPC target, NPC.HitInfo hit, int damageDone)
{
if (proj.owner != Player.whoAmI || !proj.friendly)
{
return;
}
if (proj.type == ModContent.ProjectileType<TranscendentNaniteShard>() ||
proj.type == ModContent.ProjectileType<TranscendentAscendantBolt>() ||
proj.type == ModContent.ProjectileType<TranscendentBladeShard>())
{
return;
}
TrySpawnNaniteShards(target.Center, damageDone);
}
private void TrySpawnNaniteShards(Vector2 position, int damageDone)
{
if (!transcendentSetActive || Player.whoAmI != Main.myPlayer)
{
return;
}
if (damageDone <= 0 || naniteShardCooldown > 0)
{
return;
}
naniteShardCooldown = 8;
int baseDamage = GetNaniteShardDamage(Player);
int computed = Math.Max(baseDamage, damageDone / 2);
float speed = 13f;
var source = Player.GetSource_Misc("TranscendentNaniteShards");
for (int i = 0; i < 2; i++)
{
Vector2 velocity = Main.rand.NextVector2CircularEdge(1f, 1f) * speed;
if (velocity.LengthSquared() < 0.01f)
{
velocity = new Vector2(0f, -speed);
}
Projectile shard = Projectile.NewProjectileDirect(
source,
position,
velocity,
ModContent.ProjectileType<TranscendentNaniteShard>(),
computed,
2f,
Player.whoAmI);
shard.originalDamage = computed;
}
}
public static int GetAscendantDroneDamage(Player player)
{
return (int)player.GetTotalDamage(DamageClass.Summon).ApplyTo(AscendantDroneBaseDamage);
}
public static int GetNaniteShardDamage(Player player)
{
return (int)player.GetTotalDamage(DamageClass.Generic).ApplyTo(NaniteShardBaseDamage);
} }
} }
} }
@@ -0,0 +1,126 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Projectiles.Avali
{
public class AvaliHuntingDrone : ModProjectile
{
private const float OrbitSpeed = 0.045f;
private const float OrbitRadius = 96f;
private const int ShootCooldown = 28;
private const float TargetRange = 920f;
private const float ShotSpeed = 19.5f;
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionSacrificable[Type] = false;
ProjectileID.Sets.MinionTargettingFeature[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 26;
Projectile.height = 26;
Projectile.friendly = false;
Projectile.minion = true;
Projectile.penetrate = -1;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.DamageType = DamageClass.Summon;
Projectile.netImportant = true;
Projectile.timeLeft = 2;
Projectile.minionSlots = 0f;
Projectile.damage = 0;
}
public override void AI()
{
Player owner = Main.player[Projectile.owner];
AvaliVanguardPlayer modPlayer = owner.GetModPlayer<AvaliVanguardPlayer>();
if (!owner.active || owner.dead || !modPlayer.HuntingDronesActive)
{
Projectile.Kill();
return;
}
Projectile.timeLeft = 2;
float index = Projectile.ai[0];
float total = Projectile.ai[1];
if (total <= 0f)
{
total = 3f;
}
float rotation = (Main.GameUpdateCount * OrbitSpeed) + index * MathHelper.TwoPi / total;
Vector2 offset = rotation.ToRotationVector2() * OrbitRadius;
Projectile.Center = owner.Center + offset;
Projectile.velocity = owner.velocity;
Projectile.rotation = (owner.Center - Projectile.Center).ToRotation() + MathHelper.PiOver2;
Lighting.AddLight(Projectile.Center, 0.35f, 0.6f, 1f);
if (Projectile.owner == Main.myPlayer)
{
Projectile.localAI[0]++;
if (Projectile.localAI[0] >= ShootCooldown)
{
Projectile.localAI[0] = 0f;
NPC target = AcquireTarget(owner, Projectile.Center, TargetRange);
if (target != null)
{
Vector2 velocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.UnitY) * ShotSpeed;
int damage = AvaliVanguardPlayer.GetDroneBaseDamage(owner);
var source = Projectile.GetSource_FromAI();
Projectile.NewProjectile(
source,
Projectile.Center,
velocity,
ModContent.ProjectileType<AvaliHuntingDroneShot>(),
damage,
2f,
owner.whoAmI);
SoundEngine.PlaySound(SoundID.Item12 with { Volume = 0.6f }, Projectile.Center);
Projectile.netUpdate = true;
}
}
}
}
private static NPC AcquireTarget(Player owner, Vector2 center, float range)
{
if (owner.HasMinionAttackTargetNPC)
{
NPC target = Main.npc[owner.MinionAttackTargetNPC];
if (target.CanBeChasedBy())
{
return target;
}
}
NPC closest = null;
float squaredRange = range * range;
for (int i = 0; i < Main.maxNPCs; i++)
{
NPC npc = Main.npc[i];
if (!npc.active || npc.friendly || npc.dontTakeDamage || npc.life <= 0)
{
continue;
}
float distance = Vector2.DistanceSquared(npc.Center, center);
if (distance <= squaredRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0))
{
squaredRange = distance;
closest = npc;
}
}
return closest;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,52 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.ModLoader;
namespace ForgottenWawiTech.Content.Projectiles.Avali
{
public class AvaliHuntingDroneShot : ModProjectile
{
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionShot[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 12;
Projectile.height = 12;
Projectile.friendly = true;
Projectile.timeLeft = 120;
Projectile.penetrate = 1;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.DamageType = DamageClass.Summon;
Projectile.usesLocalNPCImmunity = true;
Projectile.localNPCHitCooldown = 10;
Projectile.extraUpdates = 1;
Projectile.alpha = 40;
}
public override void AI()
{
Projectile.rotation = Projectile.velocity.ToRotation();
Lighting.AddLight(Projectile.Center, 0.4f, 0.7f, 1.2f);
if (Main.rand.NextBool(3))
{
Dust dust = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.Electric, 0f, 0f, 120, default, 1.1f);
dust.noGravity = true;
}
}
public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone)
{
if (Main.myPlayer == Projectile.owner)
{
SoundEngine.PlaySound(SoundID.Item93 with { Volume = 0.4f }, Projectile.Center);
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,115 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace ForgottenWawiTech.Content.Projectiles.Protogen
{
public class ProtogenOperativeNanite : ModProjectile
{
private const float DetectionRange = 640f;
private const float HomingStrength = 0.14f;
private const float DesiredSpeed = 14f;
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionShot[Type] = true;
ProjectileID.Sets.MinionSacrificable[Type] = false;
}
public override void SetDefaults()
{
Projectile.width = 14;
Projectile.height = 14;
Projectile.friendly = true;
Projectile.penetrate = 1;
Projectile.timeLeft = 360;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.DamageType = DamageClass.Generic;
Projectile.usesLocalNPCImmunity = true;
Projectile.localNPCHitCooldown = 20;
Projectile.extraUpdates = 1;
}
public override void AI()
{
Player owner = Main.player[Projectile.owner];
if (!owner.active || owner.dead)
{
Projectile.Kill();
return;
}
Projectile.rotation += 0.2f * Projectile.direction;
Lighting.AddLight(Projectile.Center, 0.25f, 0.55f, 0.75f);
NPC target = AcquireTarget(owner, Projectile.Center, DetectionRange);
if (target != null)
{
Vector2 desiredVelocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.Zero) * DesiredSpeed;
Projectile.velocity = Vector2.Lerp(Projectile.velocity, desiredVelocity, HomingStrength);
}
else
{
Projectile.velocity *= 0.98f;
}
if (Main.rand.NextBool(4))
{
Dust dust = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.Electric, 0f, 0f, 100, default, 1.1f);
dust.noGravity = true;
}
}
public override void OnHitNPC(NPC target, NPC.HitInfo hit, int damageDone)
{
if (Main.myPlayer != Projectile.owner)
{
return;
}
Player owner = Main.player[Projectile.owner];
int healAmount = (int)(damageDone * 0.5f);
if (healAmount <= 0)
{
return;
}
owner.statLife = Utils.Clamp(owner.statLife + healAmount, 0, owner.statLifeMax2);
owner.HealEffect(healAmount);
}
private static NPC AcquireTarget(Player owner, Vector2 center, float range)
{
if (owner.HasMinionAttackTargetNPC)
{
NPC target = Main.npc[owner.MinionAttackTargetNPC];
if (target.CanBeChasedBy())
{
return target;
}
}
NPC closest = null;
float squaredRange = range * range;
for (int i = 0; i < Main.maxNPCs; i++)
{
NPC npc = Main.npc[i];
if (!npc.active || npc.friendly || npc.dontTakeDamage || npc.life <= 0)
{
continue;
}
float distance = Vector2.DistanceSquared(npc.Center, center);
if (distance <= squaredRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0))
{
squaredRange = distance;
closest = npc;
}
}
return closest;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,124 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Players;
using ForgottenWawiTech.Content.GlobalProjectiles;
namespace ForgottenWawiTech.Content.Projectiles.Protogen
{
public class ProtogenSentinelCore : ModProjectile
{
private const float HoverRadius = 70f;
private const float HoverSpeed = 0.035f;
private const int FireCooldown = 32;
private const float TargetRange = 950f;
private const float BeamVelocity = 18f;
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionSacrificable[Type] = false;
ProjectileID.Sets.MinionTargettingFeature[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 36;
Projectile.height = 36;
Projectile.friendly = false;
Projectile.minion = true;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.penetrate = -1;
Projectile.netImportant = true;
Projectile.timeLeft = 2;
Projectile.damage = 0;
Projectile.minionSlots = 0f;
}
public override void AI()
{
Player owner = Main.player[Projectile.owner];
ProtogenSentinelPlayer modPlayer = owner.GetModPlayer<ProtogenSentinelPlayer>();
if (!owner.active || owner.dead || !modPlayer.SentinelCoreActive)
{
Projectile.Kill();
return;
}
Projectile.timeLeft = 2;
float rotation = ((float)Main.GameUpdateCount * HoverSpeed) % MathHelper.TwoPi;
Vector2 desiredOffset = new Vector2(0f, -HoverRadius).RotatedBy(rotation);
Vector2 desiredPosition = owner.Center + desiredOffset;
Projectile.Center = Vector2.Lerp(Projectile.Center, desiredPosition, 0.2f);
Projectile.velocity = owner.velocity;
Lighting.AddLight(Projectile.Center, 0.2f, 0.6f, 0.9f);
if (Projectile.owner == Main.myPlayer)
{
Projectile.localAI[0]++;
if (Projectile.localAI[0] >= FireCooldown)
{
Projectile.localAI[0] = 0f;
NPC target = AcquireTarget(owner, Projectile.Center, TargetRange);
if (target != null)
{
FireBeam(owner, target);
}
}
}
}
private void FireBeam(Player owner, NPC target)
{
Vector2 velocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.UnitY) * BeamVelocity;
int damage = ProtogenSentinelPlayer.GetCoreDamage(owner);
var source = Projectile.GetSource_FromThis();
Projectile beam = Projectile.NewProjectileDirect(
source,
Projectile.Center,
velocity,
ModContent.ProjectileType<ProtogenSentinelCoreBeam>(),
damage,
3f,
owner.whoAmI);
beam.GetGlobalProjectile<ProtogenSentinelGlobalProjectile>().DisableSentinelSplit = true;
SoundEngine.PlaySound(SoundID.Item33 with { Volume = 0.7f, Pitch = 0.15f }, Projectile.Center);
}
private static NPC AcquireTarget(Player owner, Vector2 center, float range)
{
if (owner.HasMinionAttackTargetNPC)
{
NPC target = Main.npc[owner.MinionAttackTargetNPC];
if (target.CanBeChasedBy())
{
return target;
}
}
NPC closest = null;
float squaredRange = range * range;
for (int i = 0; i < Main.maxNPCs; i++)
{
NPC npc = Main.npc[i];
if (!npc.active || npc.friendly || npc.dontTakeDamage || npc.life <= 0)
{
continue;
}
float distance = Vector2.DistanceSquared(npc.Center, center);
if (distance <= squaredRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0))
{
squaredRange = distance;
closest = npc;
}
}
return closest;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,50 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.GlobalProjectiles;
namespace ForgottenWawiTech.Content.Projectiles.Protogen
{
public class ProtogenSentinelCoreBeam : ModProjectile
{
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionShot[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 18;
Projectile.height = 18;
Projectile.friendly = true;
Projectile.timeLeft = 120;
Projectile.penetrate = 2;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.DamageType = DamageClass.Summon;
Projectile.extraUpdates = 1;
Projectile.usesLocalNPCImmunity = true;
Projectile.localNPCHitCooldown = 10;
}
public override void AI()
{
Projectile.rotation = Projectile.velocity.ToRotation();
Lighting.AddLight(Projectile.Center, 0.35f, 0.9f, 1.2f);
if (Main.rand.NextBool(3))
{
Dust dust = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.BlueCrystalShard, 0f, 0f, 150, default, 1.1f);
dust.noGravity = true;
dust.velocity = Projectile.velocity * 0.2f;
}
}
public override void OnSpawn(IEntitySource source)
{
Projectile.GetGlobalProjectile<ProtogenSentinelGlobalProjectile>().DisableSentinelSplit = true;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,87 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.DataStructures;
using Terraria.ID;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.GlobalProjectiles;
namespace ForgottenWawiTech.Content.Projectiles.Protogen
{
public class ProtogenSentinelFragment : ModProjectile
{
private const float HomingRange = 560f;
private const float HomingStrength = 0.18f;
private const float DesiredSpeed = 15f;
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionShot[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 14;
Projectile.height = 14;
Projectile.friendly = true;
Projectile.penetrate = 1;
Projectile.timeLeft = 240;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.DamageType = DamageClass.Generic;
Projectile.extraUpdates = 1;
Projectile.usesLocalNPCImmunity = true;
Projectile.localNPCHitCooldown = 15;
}
public override void AI()
{
Projectile.rotation = Projectile.velocity.ToRotation();
Lighting.AddLight(Projectile.Center, 0.3f, 0.8f, 1.15f);
NPC target = AcquireTarget(Projectile.Center, HomingRange);
if (target != null)
{
Vector2 desiredVelocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.Zero) * DesiredSpeed;
Projectile.velocity = Vector2.Lerp(Projectile.velocity, desiredVelocity, HomingStrength);
}
else
{
Projectile.velocity *= 0.99f;
}
if (Main.rand.NextBool(4))
{
Dust dust = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.Electric, 0f, 0f, 120, default, 1.05f);
dust.noGravity = true;
}
}
public override void OnSpawn(IEntitySource source)
{
Projectile.GetGlobalProjectile<ProtogenSentinelGlobalProjectile>().DisableSentinelSplit = true;
}
private static NPC AcquireTarget(Vector2 center, float range)
{
NPC closest = null;
float squaredRange = range * range;
for (int i = 0; i < Main.maxNPCs; i++)
{
NPC npc = Main.npc[i];
if (!npc.active || npc.friendly || npc.dontTakeDamage || npc.life <= 0)
{
continue;
}
float distance = Vector2.DistanceSquared(npc.Center, center);
if (distance <= squaredRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0))
{
squaredRange = distance;
closest = npc;
}
}
return closest;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,123 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Projectiles.Singularity
{
public class SingularityOrb : ModProjectile
{
private const float OrbitRadius = 90f;
private const float OrbitSpeed = 0.04f;
private const int FireCooldown = 22;
private const float TargetRange = 1000f;
private const float BeamSpeed = 21f;
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionSacrificable[Type] = false;
ProjectileID.Sets.MinionTargettingFeature[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 32;
Projectile.height = 32;
Projectile.friendly = false;
Projectile.minion = true;
Projectile.DamageType = DamageClass.Generic;
Projectile.penetrate = -1;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.netImportant = true;
Projectile.timeLeft = 2;
Projectile.minionSlots = 0f;
}
public override void AI()
{
Player owner = Main.player[Projectile.owner];
SingularityPlayer modPlayer = owner.GetModPlayer<SingularityPlayer>();
if (!owner.active || owner.dead || !modPlayer.SingularityOrbActive)
{
Projectile.Kill();
return;
}
Projectile.timeLeft = 2;
float rotation = ((float)Main.GameUpdateCount * OrbitSpeed) + Projectile.identity * 0.2f;
Vector2 offset = new Vector2(0f, -OrbitRadius).RotatedBy(rotation);
Vector2 desiredPos = owner.Center + offset;
Projectile.Center = Vector2.Lerp(Projectile.Center, desiredPos, 0.28f);
Projectile.velocity = owner.velocity;
Projectile.rotation += 0.03f * Projectile.direction;
Lighting.AddLight(Projectile.Center, 0.55f, 0.2f, 0.65f);
if (Projectile.owner == Main.myPlayer)
{
Projectile.localAI[0]++;
if (Projectile.localAI[0] >= FireCooldown)
{
Projectile.localAI[0] = 0f;
NPC target = AcquireTarget(owner, Projectile.Center, TargetRange);
if (target != null)
{
FireBeam(owner, target);
}
}
}
}
private void FireBeam(Player owner, NPC target)
{
Vector2 velocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.UnitY) * BeamSpeed;
int damage = SingularityPlayer.GetOrbDamage(owner);
var source = Projectile.GetSource_FromThis();
Projectile.NewProjectile(
source,
Projectile.Center,
velocity,
ModContent.ProjectileType<SingularityOrbBeam>(),
damage,
2f,
owner.whoAmI);
SoundEngine.PlaySound(SoundID.Item91 with { Volume = 0.7f, Pitch = 0.35f }, Projectile.Center);
}
private static NPC AcquireTarget(Player owner, Vector2 center, float range)
{
if (owner.HasMinionAttackTargetNPC)
{
NPC forced = Main.npc[owner.MinionAttackTargetNPC];
if (forced.CanBeChasedBy())
{
return forced;
}
}
NPC closest = null;
float sqrRange = range * range;
for (int i = 0; i < Main.maxNPCs; i++)
{
NPC npc = Main.npc[i];
if (!npc.active || npc.friendly || npc.dontTakeDamage || npc.life <= 0)
{
continue;
}
float dist = Vector2.DistanceSquared(npc.Center, center);
if (dist <= sqrRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0))
{
sqrRange = dist;
closest = npc;
}
}
return closest;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,42 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace ForgottenWawiTech.Content.Projectiles.Singularity
{
public class SingularityOrbBeam : ModProjectile
{
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionShot[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 16;
Projectile.height = 16;
Projectile.friendly = true;
Projectile.timeLeft = 120;
Projectile.penetrate = 3;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.DamageType = DamageClass.Generic;
Projectile.extraUpdates = 1;
Projectile.usesLocalNPCImmunity = true;
Projectile.localNPCHitCooldown = 8;
}
public override void AI()
{
Projectile.rotation = Projectile.velocity.ToRotation();
Lighting.AddLight(Projectile.Center, 0.7f, 0.25f, 0.85f);
if (Main.rand.NextBool(3))
{
Dust dust = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.PinkTorch, Projectile.velocity.X * 0.2f, Projectile.velocity.Y * 0.2f, 150, default, 1.2f);
dust.noGravity = true;
}
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,76 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace ForgottenWawiTech.Content.Projectiles.Transcendent
{
public class TranscendentAscendantBolt : ModProjectile
{
private const float HomingRange = 720f;
private const float HomingStrength = 0.2f;
private const float DesiredSpeed = 20f;
/* public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionShot[Type] = true;
} */
public override void SetDefaults()
{
Projectile.width = 18;
Projectile.height = 18;
Projectile.friendly = true;
Projectile.timeLeft = 180;
Projectile.penetrate = 2;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.DamageType = DamageClass.Summon;
Projectile.extraUpdates = 1;
Projectile.usesLocalNPCImmunity = true;
Projectile.localNPCHitCooldown = 10;
}
public override void AI()
{
Projectile.rotation = Projectile.velocity.ToRotation();
Lighting.AddLight(Projectile.Center, 0.6f, 0.55f, 1.2f);
NPC target = AcquireTarget(Projectile.Center, HomingRange);
if (target != null)
{
Vector2 desiredVelocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.Zero) * DesiredSpeed;
Projectile.velocity = Vector2.Lerp(Projectile.velocity, desiredVelocity, HomingStrength);
}
if (Main.rand.NextBool(4))
{
Dust dust = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.Enchanted_Pink, Projectile.velocity.X * 0.2f, Projectile.velocity.Y * 0.2f, 150, default, 1.15f);
dust.noGravity = true;
}
}
private static NPC AcquireTarget(Vector2 center, float range)
{
NPC closest = null;
float sqrRange = range * range;
for (int i = 0; i < Main.maxNPCs; i++)
{
NPC npc = Main.npc[i];
if (!npc.active || npc.friendly || npc.dontTakeDamage || npc.life <= 0)
{
continue;
}
float dist = Vector2.DistanceSquared(npc.Center, center);
if (dist <= sqrRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0))
{
sqrRange = dist;
closest = npc;
}
}
return closest;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,130 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.Audio;
using Terraria.ID;
using Terraria.ModLoader;
using ForgottenWawiTech.Content.Players;
namespace ForgottenWawiTech.Content.Projectiles.Transcendent
{
public class TranscendentAscendantDrone : ModProjectile
{
private const float OrbitRadius = 136f;
private const float OrbitSpeed = 0.055f;
private const int FireCooldown = 18;
private const float TargetRange = 1100f;
private const float BoltSpeed = 19f;
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionSacrificable[Type] = false;
ProjectileID.Sets.MinionTargettingFeature[Type] = true;
//ProjectileID.Sets.Minion[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 28;
Projectile.height = 28;
Projectile.friendly = false;
Projectile.minion = true;
Projectile.penetrate = -1;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.netImportant = true;
Projectile.timeLeft = 2;
Projectile.minionSlots = 0f;
}
public override void AI()
{
Player owner = Main.player[Projectile.owner];
TranscendentPlayer modPlayer = owner.GetModPlayer<TranscendentPlayer>();
if (!owner.active || owner.dead || !modPlayer.HasTranscendentSet)
{
Projectile.Kill();
return;
}
Projectile.timeLeft = 2;
float index = Projectile.ai[0];
float total = Projectile.ai[1];
if (total <= 0f)
{
total = 4f;
}
float rotation = ((float)Main.GameUpdateCount * OrbitSpeed) + index * MathHelper.TwoPi / total;
Vector2 offset = rotation.ToRotationVector2() * OrbitRadius;
Projectile.Center = owner.Center + offset;
Projectile.velocity = owner.velocity;
Projectile.rotation = (owner.Center - Projectile.Center).ToRotation() + MathHelper.PiOver2;
Lighting.AddLight(Projectile.Center, 0.45f, 0.6f, 1.05f);
if (Projectile.owner == Main.myPlayer)
{
Projectile.localAI[0]++;
if (Projectile.localAI[0] >= FireCooldown)
{
Projectile.localAI[0] = 0f;
NPC target = AcquireTarget(owner, Projectile.Center, TargetRange);
if (target != null)
{
FireBolt(owner, target);
}
}
}
}
private void FireBolt(Player owner, NPC target)
{
Vector2 velocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.UnitY) * BoltSpeed;
int damage = TranscendentPlayer.GetAscendantDroneDamage(owner);
var source = Projectile.GetSource_FromThis();
Projectile.NewProjectile(
source,
Projectile.Center,
velocity,
ModContent.ProjectileType<TranscendentAscendantBolt>(),
damage,
4f,
owner.whoAmI);
SoundEngine.PlaySound(SoundID.Item33 with { Volume = 0.6f, Pitch = 0.2f }, Projectile.Center);
Projectile.netUpdate = true;
}
private static NPC AcquireTarget(Player owner, Vector2 center, float range)
{
if (owner.HasMinionAttackTargetNPC)
{
NPC forced = Main.npc[owner.MinionAttackTargetNPC];
if (forced.CanBeChasedBy())
{
return forced;
}
}
NPC closest = null;
float sqrRange = range * range;
for (int i = 0; i < Main.maxNPCs; i++)
{
NPC npc = Main.npc[i];
if (!npc.active || npc.friendly || npc.dontTakeDamage || npc.life <= 0)
{
continue;
}
float dist = Vector2.DistanceSquared(npc.Center, center);
if (dist <= sqrRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0))
{
sqrRange = dist;
closest = npc;
}
}
return closest;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -0,0 +1,81 @@
using Microsoft.Xna.Framework;
using Terraria;
using Terraria.ID;
using Terraria.ModLoader;
namespace ForgottenWawiTech.Content.Projectiles.Transcendent
{
public class TranscendentNaniteShard : ModProjectile
{
private const float HomingRange = 680f;
private const float HomingStrength = 0.22f;
private const float DesiredSpeed = 18f;
public override void SetStaticDefaults()
{
ProjectileID.Sets.MinionShot[Type] = true;
}
public override void SetDefaults()
{
Projectile.width = 14;
Projectile.height = 14;
Projectile.friendly = true;
Projectile.penetrate = 1;
Projectile.timeLeft = 220;
Projectile.tileCollide = false;
Projectile.ignoreWater = true;
Projectile.extraUpdates = 1;
Projectile.DamageType = DamageClass.Generic;
Projectile.usesLocalNPCImmunity = true;
Projectile.localNPCHitCooldown = 12;
Projectile.alpha = 60;
}
public override void AI()
{
Projectile.rotation += 0.35f * Projectile.direction;
Lighting.AddLight(Projectile.Center, 0.45f, 0.8f, 1.15f);
NPC target = AcquireTarget(Projectile.Center, HomingRange);
if (target != null)
{
Vector2 desiredVelocity = (target.Center - Projectile.Center).SafeNormalize(Vector2.Zero) * DesiredSpeed;
Projectile.velocity = Vector2.Lerp(Projectile.velocity, desiredVelocity, HomingStrength);
}
else
{
Projectile.velocity *= 0.98f;
}
if (Main.rand.NextBool(5))
{
Dust dust = Dust.NewDustDirect(Projectile.position, Projectile.width, Projectile.height, DustID.Electric, 0f, 0f, 120, default, 1.05f);
dust.noGravity = true;
}
}
private static NPC AcquireTarget(Vector2 center, float range)
{
NPC closest = null;
float sqrRange = range * range;
for (int i = 0; i < Main.maxNPCs; i++)
{
NPC npc = Main.npc[i];
if (!npc.active || npc.friendly || npc.dontTakeDamage || npc.life <= 0)
{
continue;
}
float dist = Vector2.DistanceSquared(npc.Center, center);
if (dist <= sqrRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0))
{
sqrRange = dist;
closest = npc;
}
}
return closest;
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

@@ -896,6 +896,17 @@ Items: {
} }
} }
Conditions: {
HasDefeatedAnyMechBoss: Defeated a mechanical boss
HasDefeatedExoMechs: Defeated the Exo Mechs
HasDefeatedLexy: Defeated Lexy
HasDefeatedNiko: Defeated Niko
HasDefeatedNeptune: Defeated Neptune
HasDefeatedLyyka: Defeated Lyyka
HasDefeatedCorruptedSwarm: Defeated the Corrupted Swarm
HasDefeatedMoonLord: Defeated the Moon Lord
}
NPCs: { NPCs: {
Lexy.DisplayName: Lexy Lexy.DisplayName: Lexy
@@ -992,6 +1003,17 @@ Projectiles: {
TranscendentNova.DisplayName: Transcendent Nova TranscendentNova.DisplayName: Transcendent Nova
TranscendentRailBolt.DisplayName: Transcendent Rail Bolt TranscendentRailBolt.DisplayName: Transcendent Rail Bolt
AvaliThermalDrone.DisplayName: Avali Thermal Drone AvaliThermalDrone.DisplayName: Avali Thermal Drone
AvaliHuntingDrone.DisplayName: Avali Hunting Drone
AvaliHuntingDroneShot.DisplayName: Avali Hunting Drone Pulse
ProtogenOperativeNanite.DisplayName: Operative Nanite
ProtogenSentinelCore.DisplayName: Sentinel AI Core
ProtogenSentinelCoreBeam.DisplayName: Sentinel Core Beam
ProtogenSentinelFragment.DisplayName: Sentinel Split Fragment
SingularityOrb.DisplayName: Singularity Orb
SingularityOrbBeam.DisplayName: Singularity Orb Beam
TranscendentAscendantDrone.DisplayName: Ascendant Swarm Drone
TranscendentAscendantBolt.DisplayName: Ascendant Swarm Bolt
TranscendentNaniteShard.DisplayName: Nanite Shard
} }
Prefixes: { Prefixes: {