From 7b0c9f22ecf3a0575207d427b3a21c7adaa3aa89 Mon Sep 17 00:00:00 2001 From: "Wyatt J. Miller" Date: Wed, 27 Aug 2025 22:15:33 -0400 Subject: [PATCH] added consumables and buff healing bonuses --- Data/ISerializer.cs | 5 + Data/JsonSerializer.cs | 14 +++ HealingPlugin.cs | 191 ++++++++++++++++++++++++++++++++---- Mappings/EquipMappings.cs | 31 ++++++ Mappings/HealingMappings.cs | 44 +++++++++ Mappings/IMappings.cs | 5 + Player.cs | 17 ++++ 7 files changed, 289 insertions(+), 18 deletions(-) create mode 100644 Data/ISerializer.cs create mode 100644 Data/JsonSerializer.cs create mode 100644 Mappings/EquipMappings.cs create mode 100644 Mappings/HealingMappings.cs create mode 100644 Mappings/IMappings.cs create mode 100644 Player.cs diff --git a/Data/ISerializer.cs b/Data/ISerializer.cs new file mode 100644 index 0000000..333c583 --- /dev/null +++ b/Data/ISerializer.cs @@ -0,0 +1,5 @@ +public interface ISerializer +{ + string Serialize(T obj); + T Deserialize(string data); +} diff --git a/Data/JsonSerializer.cs b/Data/JsonSerializer.cs new file mode 100644 index 0000000..fdd28bd --- /dev/null +++ b/Data/JsonSerializer.cs @@ -0,0 +1,14 @@ +using Newtonsoft.Json; + +public class JsonSealizer : ISerializer +{ + public string Serialize(T obj) + { + return JsonConvert.SerializeObject(obj, Formatting.Indented); + } + + public T Deserialize(string data) + { + return JsonConvert.DeserializeObject(data); + } +} diff --git a/HealingPlugin.cs b/HealingPlugin.cs index 09361d6..2a9d925 100644 --- a/HealingPlugin.cs +++ b/HealingPlugin.cs @@ -1,6 +1,11 @@ using Terraria; +using Terraria.ID; +using Terraria.Net; +using Terraria.Localization; using TShockAPI; +using TShockAPI.Hooks; using TerrariaApi.Server; +using TerrariaHealingPlugin.Mappings; namespace TerrariaHealingPlugin; @@ -11,51 +16,201 @@ public class HealingPlugin : TerrariaPlugin public override string Name => "HealingPlugin"; public override string Description => "A healing plugin, duh"; public override Version Version => new Version(1, 0, 0); - private DateTime _lastCheck = DateTime.UtcNow; + + private DateTime _lastHealCheck = DateTime.UtcNow; + private DateTime _lastBuffCheck = DateTime.UtcNow; + private List _players = new List(); + + private HealingMappings _healingItemMappings = new HealingMappings(); + private EquipMappings _equipMappings = new EquipMappings(); public HealingPlugin(Main game) : base(game) { } public override void Initialize() { - ServerApi.Hooks.GamePostInitialize.Register(this, OnGamePostInitialize); + TShock.Log.Info($"Initializing {Name} v{Version} by {Author}"); ServerApi.Hooks.ServerJoin.Register(this, OnServerJoin); ServerApi.Hooks.GameUpdate.Register(this, OnUpdate); + ServerApi.Hooks.NetSendData.Register(this, OnSendNetData); + ServerApi.Hooks.NetGetData.Register(this, OnGetNetData); + GetDataHandlers.PlayerSlot.Register(OnPlayerSlot); + // GetDataHandlers.PlayerHP.Register(OnPlayerHPChange); + GetDataHandlers.PlayerBuff.Register(OnPlayerBuff); + PlayerHooks.PlayerPostLogin += OnPlayerPostLogin; } protected override void Dispose(bool disposing) { if (disposing) { - ServerApi.Hooks.GamePostInitialize.Deregister(this, OnGamePostInitialize); ServerApi.Hooks.ServerJoin.Deregister(this, OnServerJoin); - ServerApi.Hooks.GameUpdate.Deregister(this, OnUpdate); + // ServerApi.Hooks.GameUpdate.Deregister(this, OnUpdate); + ServerApi.Hooks.NetSendData.Deregister(this, OnSendNetData); + ServerApi.Hooks.NetGetData.Deregister(this, OnGetNetData); + PlayerHooks.PlayerPostLogin -= OnPlayerPostLogin; } base.Dispose(disposing); } - private void OnUpdate(EventArgs args) + private void OnPlayerPostLogin(PlayerPostLoginEventArgs e) { - if ((DateTime.UtcNow - _lastCheck).TotalSeconds >= 1) - { - _lastCheck = DateTime.UtcNow; + ApplyRegenerationBuff(e.Player); + } - foreach (var player in TShock.Players) - { - if (player != null && player.Active) - { - player.Heal(25); // heal all players 25 HP/second - } - } + private void OnPlayerBuff(object sender, GetDataHandlers.PlayerBuffEventArgs args) + { + // Console.WriteLine($"Player buff arguments: {args}"); + TSPlayer player = args.Player; + int buffType = args.Type; + Console.WriteLine($"Buff type: {buffType}"); + bool isEquippableBuff = _equipMappings.mappings.ContainsKey(buffType); + bool isHealingItemBuff = _healingItemMappings.mappings.ContainsKey(buffType); + Console.WriteLine($"Player: {player.Name}, Buff Type: {buffType}, Is Equippable Buff: {isEquippableBuff}"); + if (isEquippableBuff) + { + var multiplier = _equipMappings.GetHealingMultiplier(buffType); + player.SendSuccessMessage($"Equippable buff detected! Applying x{multiplier} multiplier to healing effects."); + args.Handled = true; } } - private void OnGamePostInitialize(EventArgs args) + private void OnGetNetData(GetDataEventArgs args) { - TShock.Log.Info($"{Name} v{Version} has been initialized."); + // nothing here, yet ;) + } + + private void OnPlayerHPChange(object sender, GetDataHandlers.PlayerHPEventArgs args) + { + TSPlayer player = args.Player; + int previousHP = player.TPlayer.statLife; + int newHP = args.Current; + short healingAmount = (short)(newHP - previousHP); + bool isHealingItem = IsHealingValueValid(healingAmount); + Console.WriteLine($"Player: {player.Name}, Previous HP: {previousHP}, New HP: {newHP}, Healing Amount: {healingAmount}"); + + if (healingAmount > 0 && isHealingItem) + { + args.Handled = true; + } + } + + private void OnPlayerSlot(object sender, GetDataHandlers.PlayerSlotEventArgs args) + { + Console.WriteLine("In OnPlayerSlot method"); + TSPlayer player = args.Player; + short slot = args.Slot; + short newStack = args.Stack; + short itemType = args.Type; + Console.WriteLine($"Player: {player.Name}, Slot: {slot}, New Stack: {newStack}, Item Type: {itemType}"); + var isHealingItem = IsHealingItem(itemType); + var isItemConsumed = IsItemBeingConsumed(player, slot, newStack); + Console.WriteLine($"Is Healing Item: {isHealingItem}, Is Item Being Consumed: {isItemConsumed}"); + + if (isHealingItem && isItemConsumed) + { + var multiplier = _healingItemMappings.GetHealingMultiplier(itemType); + var baseHeal = GetBaseHealAmount(itemType); + var enhancedHeal = (int)(baseHeal * multiplier); + var totalHealing = enhancedHeal + baseHeal; + Console.WriteLine($"Base Heal: {baseHeal}, Multiplier: {multiplier}, Enhanced Heal: {enhancedHeal}"); + + player.Heal(enhancedHeal); + player.SendSuccessMessage($"Enhanced healing! Restored {enhancedHeal} HP (x{multiplier} multiplier)"); + + args.Handled = true; + } + } + + private bool IsHealingItem(int itemType) + { + return _healingItemMappings.mappings.ContainsKey(itemType); + } + + private bool IsHealingValueValid(short healAmount) + { + return _healingItemMappings.mappings.ContainsValue(healAmount); + } + + private int GetBaseHealAmount(int itemType) + { + return _healingItemMappings.mappings.TryGetValue(itemType, out var healAmount) ? healAmount : 0; + } + + private bool IsItemBeingConsumed(TSPlayer player, int slot, short newStack) + { + var item = player.TPlayer.inventory[slot]; + return item.stack > newStack; + } + + private void OnSendNetData(SendDataEventArgs args) + { + // empty, on purpose :D + } + + private void OnUpdate(EventArgs args) + { + if ((DateTime.UtcNow - _lastHealCheck).TotalSeconds >= 1) + { + foreach (var player in TShock.Players) + { + // Console.WriteLine($"Player {player.Name} has the following HP: {player.TPlayer.statLife}"); + // if (player != null && player.Active && player.TPlayer.statLife < player.TPlayer.statLifeMax) + // { + // Console.WriteLine($"Player {player.Name} is not healed all the way, let's increase the regen"); + // player.TPlayer.statLife += 10; + // player.SendData(PacketTypes.EffectHeal, "", player.Index, 10f); + // Console.WriteLine("Increased health via regen"); + // } + // else if (player != null && player.TPlayer.statLife == player.TPlayer.statLifeMax) + // { + // Console.WriteLine($"Player {player.Name} is fully healed."); + // } + } + + _lastHealCheck = DateTime.UtcNow; + } + + if ((DateTime.UtcNow - _lastBuffCheck).TotalSeconds >= 30) + { + foreach (TSPlayer player in TShock.Players) + { + if (player?.Active == true) + { + ApplyRegenerationBuff(player); + } + } + + _lastBuffCheck = DateTime.UtcNow; + } + } + + // private void ApplyRegenerationToAllPlayers() + // { + // foreach (TSPlayer player in TShock.Players) + // { + // if (player?.Active == true && player.ConnectionAlive) + // { + // ApplyRegenerationBuff(player); + // } + // } + // } + + private void ApplyRegenerationBuff(TSPlayer player) + { + if (player?.Active == true && player.ConnectionAlive) + { + player.SetBuff(2, 3600, bypass: true); + Console.WriteLine($"set buff for player {player.Name}"); + } } private void OnServerJoin(JoinEventArgs args) { - TShock.Log.Info($"{args.Who} has joined the server."); + var player = TShock.Players[args.Who]; + if (player != null) + { + _players.Add(new Player(player)); + TShock.Log.Info($"Player {player.Name} joined with IP: {player.IP}"); + } } } diff --git a/Mappings/EquipMappings.cs b/Mappings/EquipMappings.cs new file mode 100644 index 0000000..31e414c --- /dev/null +++ b/Mappings/EquipMappings.cs @@ -0,0 +1,31 @@ +using Terraria.ID; + +namespace TerrariaHealingPlugin.Mappings +{ + public class EquipMappings : IMappings + { + public Dictionary mappings => new() + { + // FIXME: NOT AT ALL COMPLETED + + // choosen designated equipment pieces go here that get a healing boost as an incentive + // ItemID | Healing Amount + { ItemID.FleshKnuckles, 20 }, + { ItemID.PaladinsShield, 20 }, + { ItemID.MedicatedBandage, 20 }, + { ItemID.LifeforcePotion, 80 }, + { ItemID.WormScarf, 10 }, + { ItemID.CelestialShell, 10 }, + { ItemID.CelestialCuffs, 10 }, + }; + + public double GetHealingMultiplier(int itemType) + { + return itemType switch + { + // nothing here, yet ;) + _ => 1, + }; + } + } +} diff --git a/Mappings/HealingMappings.cs b/Mappings/HealingMappings.cs new file mode 100644 index 0000000..d58fca2 --- /dev/null +++ b/Mappings/HealingMappings.cs @@ -0,0 +1,44 @@ +using Terraria.ID; + +namespace TerrariaHealingPlugin.Mappings +{ + public class HealingMappings : IMappings + { + public Dictionary mappings => new() + { + // choosen designated items go here that get a healing boost as an incentive + // ItemID | Healing Amount + { ItemID.Mushroom, 15 }, + { ItemID.Heart, 20}, + { ItemID.BottledWater, 25 }, + { ItemID.LesserHealingPotion, 50 }, + { ItemID.BottledHoney, 80 }, + { ItemID.LesserRestorationPotion, 80 }, + { ItemID.Eggnog, 80 }, + { ItemID.StrangeBrew, 80 }, + { ItemID.RestorationPotion, 90 }, + { ItemID.HealingPotion, 100 }, + { ItemID.Honeyfin, 120 }, + { ItemID.GreaterHealingPotion, 150 }, + { ItemID.SuperHealingPotion, 200 }, + }; + + public double GetHealingMultiplier(int itemType) + { + return itemType switch + { + ItemID.Mushroom => ((0.1 + 1)), + ItemID.Heart => ((0.1 + 1)), + ItemID.BottledWater => ((0.1 + 1)), + ItemID.LesserHealingPotion => ((0.2 + 1)), + ItemID.LesserRestorationPotion => ((0.2 + 1)), + ItemID.BottledHoney => ((0.2 + 1)), + ItemID.HealingPotion => ((0.5 + 1)), + ItemID.Honeyfin => ((0.5 + 1)), + ItemID.GreaterHealingPotion => ((0.5 + 1)), + ItemID.SuperHealingPotion => ((0.5 + 1)), + _ => 1, + }; + } + } +} diff --git a/Mappings/IMappings.cs b/Mappings/IMappings.cs new file mode 100644 index 0000000..92208b3 --- /dev/null +++ b/Mappings/IMappings.cs @@ -0,0 +1,5 @@ +public interface IMappings +{ + public Dictionary mappings { get; } + public double GetHealingMultiplier(int itemType); +} diff --git a/Player.cs b/Player.cs new file mode 100644 index 0000000..ca74ab2 --- /dev/null +++ b/Player.cs @@ -0,0 +1,17 @@ +using Terraria.ID; +using TShockAPI; + +namespace TerrariaHealingPlugin +{ + public class Player + { + public TSPlayer player { get; set; } + public int healAmount { get; set; } = 0; + public int healItem { get; set; } = ItemID.None; + + public Player(TSPlayer player) + { + this.player = player; + } + } +}