diff --git a/Content/Buffs/Debuffs/ThermalMarkDebuff.cs b/Content/Buffs/Debuffs/ThermalMarkDebuff.cs new file mode 100644 index 0000000..5baeb46 --- /dev/null +++ b/Content/Buffs/Debuffs/ThermalMarkDebuff.cs @@ -0,0 +1,25 @@ +using Terraria; +using Terraria.ID; +using Terraria.ModLoader; +using ForgottenWawiTech.Content.GlobalNPCs; + +namespace ForgottenWawiTech.Content.Buffs.Debuffs +{ + public class ThermalMarkDebuff : ModBuff + { + public override void SetStaticDefaults() + { + Main.debuff[Type] = true; + Main.pvpBuff[Type] = true; + Main.buffNoSave[Type] = true; + BuffID.Sets.LongerExpertDebuff[Type] = true; + BuffID.Sets.NurseCannotRemoveDebuff[Type] = true; + } + + public override void Update(NPC npc, ref int buffIndex) + { + npc.GetGlobalNPC().ThermalMarked = true; + Lighting.AddLight(npc.Center, 0.9f, 0.45f, 0.2f); + } + } +} diff --git a/Content/Buffs/Debuffs/ThermalMarkDebuff.png b/Content/Buffs/Debuffs/ThermalMarkDebuff.png new file mode 100644 index 0000000..725a740 Binary files /dev/null and b/Content/Buffs/Debuffs/ThermalMarkDebuff.png differ diff --git a/Content/GlobalNPCs/ThermalMarkGlobalNPC.cs b/Content/GlobalNPCs/ThermalMarkGlobalNPC.cs new file mode 100644 index 0000000..92cf7e7 --- /dev/null +++ b/Content/GlobalNPCs/ThermalMarkGlobalNPC.cs @@ -0,0 +1,26 @@ +using Terraria; +using Terraria.ModLoader; +using ForgottenWawiTech.Content.Buffs.Debuffs; + +namespace ForgottenWawiTech.Content.GlobalNPCs +{ + public class ThermalMarkGlobalNPC : GlobalNPC + { + public bool ThermalMarked { get; set; } + + public override bool InstancePerEntity => true; + + public override void ResetEffects(NPC npc) + { + ThermalMarked = false; + } + + public override void ModifyIncomingHit(NPC npc, ref NPC.HitModifiers modifiers) + { + if (npc.HasBuff(ModContent.BuffType())) + { + modifiers.FinalDamage *= 1.12f; + } + } + } +} diff --git a/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherCowl.cs b/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherCowl.cs index 53adc3b..95f0f5a 100644 --- a/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherCowl.cs +++ b/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherCowl.cs @@ -4,6 +4,9 @@ using Terraria.ModLoader; using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Items.Armor.AvaliScoutSet; +using ForgottenWawiTech.Content.Players; + +// Pre-hardmode namespace ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet { @@ -36,7 +39,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet player.setBonus = "Summons thermal vision drones that mark enemies\nMarked enemies take 12% more damage\n+2 max minions and +20% summon damage"; player.maxMinions += 2; player.GetDamage(DamageClass.Summon) += 0.20f; - // TODO: Implement thermal vision drone marking system + player.GetModPlayer().EnableThermalDrones(); } public override void AddRecipes() diff --git a/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherHelmet.cs b/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherHelmet.cs index 6d6d8a3..3686874 100644 --- a/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherHelmet.cs +++ b/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherHelmet.cs @@ -4,6 +4,7 @@ using Terraria.ModLoader; using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Items.Armor.AvaliScoutSet; +using ForgottenWawiTech.Content.Players; namespace ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet { @@ -37,7 +38,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet player.setBonus = "Summons thermal vision drones that mark enemies\nMarked enemies take 12% more damage\n+15% melee damage and speed"; player.GetDamage(DamageClass.Melee) += 0.15f; player.GetAttackSpeed(DamageClass.Melee) += 0.15f; - // TODO: Implement thermal vision drone marking system + player.GetModPlayer().EnableThermalDrones(); } public override void AddRecipes() diff --git a/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherHood.cs b/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherHood.cs index b5ab86c..0b0aa84 100644 --- a/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherHood.cs +++ b/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherHood.cs @@ -4,6 +4,7 @@ using Terraria.ModLoader; using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Items.Armor.AvaliScoutSet; +using ForgottenWawiTech.Content.Players; namespace ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet { @@ -37,7 +38,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet player.setBonus = "Summons thermal vision drones that mark enemies\nMarked enemies take 12% more damage\n+20% magic damage and -15% mana cost"; player.GetDamage(DamageClass.Magic) += 0.20f; player.manaCost -= 0.15f; - // TODO: Implement thermal vision drone marking system + player.GetModPlayer().EnableThermalDrones(); } public override void AddRecipes() diff --git a/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherMask.cs b/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherMask.cs index 12010f3..ce77d4a 100644 --- a/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherMask.cs +++ b/Content/Items/Armor/AvaliSkirmisherSet/AvaliSkirmisherMask.cs @@ -4,6 +4,7 @@ using Terraria.ModLoader; using ForgottenWawiTech.Content.Items.Materials; using ForgottenWawiTech.Content.Rarities; using ForgottenWawiTech.Content.Items.Armor.AvaliScoutSet; +using ForgottenWawiTech.Content.Players; namespace ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet { @@ -36,7 +37,7 @@ namespace ForgottenWawiTech.Content.Items.Armor.AvaliSkirmisherSet player.setBonus = "Summons thermal vision drones that mark enemies\nMarked enemies take 12% more damage\n+18% ranged damage and critical strike chance"; player.GetDamage(DamageClass.Ranged) += 0.18f; player.GetCritChance(DamageClass.Ranged) += 18; - // TODO: Implement thermal vision drone marking system + player.GetModPlayer().EnableThermalDrones(); } public override void AddRecipes() diff --git a/Content/Players/AvaliSkirmisherPlayer.cs b/Content/Players/AvaliSkirmisherPlayer.cs new file mode 100644 index 0000000..328c2ac --- /dev/null +++ b/Content/Players/AvaliSkirmisherPlayer.cs @@ -0,0 +1,63 @@ +using Microsoft.Xna.Framework; +using Terraria; +using Terraria.ID; +using Terraria.ModLoader; +using ForgottenWawiTech.Content.Projectiles.Avali; + +namespace ForgottenWawiTech.Content.Players +{ + public class AvaliSkirmisherPlayer : ModPlayer + { + private const int DroneCount = 2; + private const float SpawnRadius = 60f; + + public bool ThermalDronesActive { get; private set; } + + public override void ResetEffects() + { + ThermalDronesActive = false; + } + + public void EnableThermalDrones() + { + ThermalDronesActive = true; + } + + public override void PostUpdate() + { + if (!ThermalDronesActive) + { + return; + } + + if (Player.whoAmI != Main.myPlayer) + { + return; + } + + int droneType = ModContent.ProjectileType(); + int owned = Player.ownedProjectileCounts[droneType]; + if (owned >= DroneCount) + { + return; + } + + var source = Player.GetSource_Misc("AvaliSkirmisherSet"); + for (int i = owned; i < DroneCount; i++) + { + float rotationOffset = MathHelper.TwoPi * i / DroneCount; + Vector2 spawnPos = Player.Center + rotationOffset.ToRotationVector2() * SpawnRadius; + Projectile.NewProjectile( + source, + spawnPos, + Vector2.Zero, + droneType, + 0, + 0f, + Player.whoAmI, + i, + DroneCount); + } + } + } +} diff --git a/Content/Projectiles/Avali/AvaliThermalDrone.cs b/Content/Projectiles/Avali/AvaliThermalDrone.cs new file mode 100644 index 0000000..b930af2 --- /dev/null +++ b/Content/Projectiles/Avali/AvaliThermalDrone.cs @@ -0,0 +1,107 @@ +using Microsoft.Xna.Framework; +using Terraria; +using Terraria.ID; +using Terraria.ModLoader; +using ForgottenWawiTech.Content.Buffs.Debuffs; +using ForgottenWawiTech.Content.Players; + +namespace ForgottenWawiTech.Content.Projectiles.Avali +{ + public class AvaliThermalDrone : ModProjectile + { + private const float OrbitSpeed = 0.06f; + private const float OrbitRadius = 72f; + private const int MarkCooldown = 45; + private const float MarkRange = 700f; + + public override void SetStaticDefaults() + { + ProjectileID.Sets.MinionSacrificable[Type] = false; + ProjectileID.Sets.MinionShot[Type] = true; + } + + public override void SetDefaults() + { + Projectile.width = 26; + Projectile.height = 26; + Projectile.friendly = true; + Projectile.DamageType = DamageClass.Summon; + Projectile.penetrate = -1; + Projectile.tileCollide = false; + Projectile.ignoreWater = true; + Projectile.timeLeft = 2; + Projectile.netImportant = true; + Projectile.minion = true; + Projectile.minionSlots = 0f; + } + + public override void AI() + { + Player owner = Main.player[Projectile.owner]; + AvaliSkirmisherPlayer modPlayer = owner.GetModPlayer(); + if (!owner.active || owner.dead || !modPlayer.ThermalDronesActive) + { + Projectile.Kill(); + return; + } + + Projectile.timeLeft = 2; + + float index = Projectile.ai[0]; + float total = Projectile.ai[1]; + if (total <= 0f) + { + total = 2f; + } + + float rotation = (Main.GameUpdateCount * OrbitSpeed) + index * MathHelper.TwoPi / total; + Vector2 offset = rotation.ToRotationVector2() * OrbitRadius; + Projectile.Center = owner.Center + offset; + Projectile.velocity = owner.velocity; + + Lighting.AddLight(Projectile.Center, 0.55f, 0.2f, 0.15f); + + if (Projectile.localAI[0]++ >= MarkCooldown) + { + Projectile.localAI[0] = 0f; + if (Projectile.owner == Main.myPlayer) + { + NPC target = FindTarget(Projectile.Center, MarkRange); + if (target != null) + { + target.AddBuff(ModContent.BuffType(), 300); + Vector2 burstDirection = (target.Center - Projectile.Center).SafeNormalize(Vector2.UnitY); + for (int i = 0; i < 6; i++) + { + Dust dust = Dust.NewDustDirect(Projectile.Center, 0, 0, DustID.Torch, burstDirection.X * 4f, burstDirection.Y * 4f, 120, default, 1.1f); + dust.noGravity = true; + } + } + } + } + } + + private static NPC FindTarget(Vector2 center, float range) + { + NPC selected = 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(center, npc.Center); + if (dist < sqrRange && Collision.CanHitLine(center, 0, 0, npc.Center, 0, 0)) + { + sqrRange = dist; + selected = npc; + } + } + + return selected; + } + } +} diff --git a/Content/Projectiles/Avali/AvaliThermalDrone.png b/Content/Projectiles/Avali/AvaliThermalDrone.png new file mode 100644 index 0000000..9e0cf81 Binary files /dev/null and b/Content/Projectiles/Avali/AvaliThermalDrone.png differ diff --git a/Localization/en-US_Mods.ForgottenWawiTech.hjson b/Localization/en-US_Mods.ForgottenWawiTech.hjson index 37e4b78..9cad27d 100644 --- a/Localization/en-US_Mods.ForgottenWawiTech.hjson +++ b/Localization/en-US_Mods.ForgottenWawiTech.hjson @@ -991,6 +991,7 @@ Projectiles: { TranscendentBladeShard.DisplayName: Transcendent Blade Shard TranscendentNova.DisplayName: Transcendent Nova TranscendentRailBolt.DisplayName: Transcendent Rail Bolt + AvaliThermalDrone.DisplayName: Avali Thermal Drone } Prefixes: { @@ -1003,4 +1004,9 @@ Buffs: { DisplayName: Nullified Description: Your wings feel heavy and unresponsive, alongside a general sense of numbness. } + + ThermalMarkDebuff: { + DisplayName: Thermal Mark + Description: You are tagged by Avali thermal drones, making you vulnerable. + } }