From cb16de1f15ca5fe49c1526a3bc7b4dec132758fe Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Sun, 4 Aug 2024 16:31:25 -0400 Subject: [PATCH] Core/Creatures: Changed the spawn health field in creature table to a percentage Port From (https://github.com/TrinityCore/TrinityCore/commit/def601b4ff82ec8a90af60408a87cac92fdf070d) --- Source/Framework/Constants/CliDBConst.cs | 2 +- .../Database/Databases/WorldDatabase.cs | 4 +- Source/Game/Chat/Commands/NPCCommands.cs | 3 +- Source/Game/Entities/Creature/Creature.cs | 44 ++----------- Source/Game/Entities/Creature/CreatureData.cs | 3 +- Source/Game/Entities/StatSystem.cs | 65 +++++++++++++------ Source/Game/Globals/ObjectManager.cs | 46 +++++++------ .../BlackwingLair/Vaelastrasz.cs | 2 +- Source/Scripts/Spells/Generic.cs | 28 ++++++++ Source/Scripts/World/NpcsSpecial.cs | 2 +- 10 files changed, 112 insertions(+), 87 deletions(-) diff --git a/Source/Framework/Constants/CliDBConst.cs b/Source/Framework/Constants/CliDBConst.cs index 9357550b4..d4f2b18de 100644 --- a/Source/Framework/Constants/CliDBConst.cs +++ b/Source/Framework/Constants/CliDBConst.cs @@ -1979,7 +1979,7 @@ namespace Framework.Constants ContinueRegenWhileFatigued = 0x200, RegenAffectedByHaste = 0x400, SetToMaxOnLevelUp = 0x1000, - SetToMaxLevelOnInitialLogIn = 0x2000, + SetToMaxOnInitialLogIn = 0x2000, AllowCostModsForPlayers = 0x4000 } diff --git a/Source/Framework/Database/Databases/WorldDatabase.cs b/Source/Framework/Database/Databases/WorldDatabase.cs index a3882c1f4..8bec34689 100644 --- a/Source/Framework/Database/Databases/WorldDatabase.cs +++ b/Source/Framework/Database/Databases/WorldDatabase.cs @@ -1,6 +1,6 @@ // Copyright (c) CypherCore All rights reserved. // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. - + namespace Framework.Database { public class WorldDatabase : MySqlBase @@ -50,7 +50,7 @@ namespace Framework.Database PrepareStatement(WorldStatements.SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?"); PrepareStatement(WorldStatements.SEL_GAMEOBJECT_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM gameobject WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_"); PrepareStatement(WorldStatements.SEL_CREATURE_NEAREST, "SELECT guid, id, position_x, position_y, position_z, map, (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) AS order_ FROM creature WHERE map = ? AND (POW(position_x - ?, 2) + POW(position_y - ?, 2) + POW(position_z - ?, 2)) <= ? ORDER BY order_"); - PrepareStatement(WorldStatements.INS_CREATURE, "INSERT INTO creature (guid, id , map, spawnDifficulties, PhaseId, PhaseGroup, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, wander_distance, currentwaypoint, curhealth, curmana, MovementType, npcflag, unit_flags, unit_flags2, unit_flags3) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + PrepareStatement(WorldStatements.INS_CREATURE, "INSERT INTO creature(guid, id, map, spawnDifficulties, PhaseId, PhaseGroup, modelid, equipment_id, position_x, position_y, position_z, orientation, spawntimesecs, wander_distance, currentwaypoint, curHealthPct, MovementType, npcflag, unit_flags, unit_flags2, unit_flags3) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); PrepareStatement(WorldStatements.DEL_GAME_EVENT_CREATURE, "DELETE FROM game_event_creature WHERE guid = ?"); PrepareStatement(WorldStatements.DEL_GAME_EVENT_MODEL_EQUIP, "DELETE FROM game_event_model_equip WHERE guid = ?"); PrepareStatement(WorldStatements.INS_GAMEOBJECT, "INSERT INTO gameobject (guid, id, map, spawnDifficulties, PhaseId, PhaseGroup, position_x, position_y, position_z, orientation, rotation0, rotation1, rotation2, rotation3, spawntimesecs, animprogress, state) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); diff --git a/Source/Game/Chat/Commands/NPCCommands.cs b/Source/Game/Chat/Commands/NPCCommands.cs index dcd6801bc..fff4b61a8 100644 --- a/Source/Game/Chat/Commands/NPCCommands.cs +++ b/Source/Game/Chat/Commands/NPCCommands.cs @@ -990,9 +990,8 @@ namespace Game.Chat return false; } - creature.SetMaxHealth((uint)(100 + 30 * lvl)); - creature.SetHealth((uint)(100 + 30 * lvl)); creature.SetLevel(lvl); + creature.UpdateLevelDependantStats(); creature.SaveToDB(); return true; diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 5099957eb..05b739c19 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -1399,8 +1399,7 @@ namespace Game.Entities // prevent add data integrity problems data.WanderDistance = GetDefaultMovementType() == MovementGeneratorType.Idle ? 0.0f : m_wanderDistance; data.currentwaypoint = 0; - data.curhealth = (uint)GetHealth(); - data.curmana = (uint)GetPower(PowerType.Mana); + data.curHealthPct = (uint)GetHealthPct(); // prevent add data integrity problems data.movementType = (byte)(m_wanderDistance == 0 && GetDefaultMovementType() == MovementGeneratorType.Random ? MovementGeneratorType.Idle : GetDefaultMovementType()); @@ -1440,8 +1439,7 @@ namespace Game.Entities stmt.AddValue(index++, m_respawnDelay); stmt.AddValue(index++, m_wanderDistance); stmt.AddValue(index++, 0); - stmt.AddValue(index++, GetHealth()); - stmt.AddValue(index++, GetPower(PowerType.Mana)); + stmt.AddValue(index++, (uint)GetHealthPct()); stmt.AddValue(index++, (byte)GetDefaultMovementType()); if (npcflag.HasValue) stmt.AddValue(index++, npcflag.Value); @@ -1478,7 +1476,7 @@ namespace Game.Entities UpdateLevelDependantStats(); } - void UpdateLevelDependantStats() + public void UpdateLevelDependantStats() { CreatureTemplate cInfo = GetCreatureTemplate(); CreatureClassifications classification = IsPet() ? CreatureClassifications.Normal : cInfo.Classification; @@ -1502,16 +1500,7 @@ namespace Game.Entities PowerType powerType = CalculateDisplayPowerType(); SetCreateMana(stats.BaseMana); SetStatPctModifier(UnitMods.PowerStart + (int)powerType, UnitModifierPctType.Base, GetCreatureDifficulty().ManaModifier); - SetPowerType(powerType); - - PowerTypeRecord powerTypeEntry = Global.DB2Mgr.GetPowerTypeEntry(powerType); - if (powerTypeEntry != null) - { - if (powerTypeEntry.HasFlag(PowerTypeFlags.UnitsUseDefaultPowerOnInit)) - SetPower(powerType, powerTypeEntry.DefaultPower); - else - SetFullPower(powerType); - } + SetPowerType(powerType, true, true); //Damage float basedamage = GetBaseDamageForLevel(level); @@ -1764,29 +1753,8 @@ namespace Game.Entities public void SetSpawnHealth() { - if (_staticFlags.HasFlag(CreatureStaticFlags5.NoHealthRegen)) - return; - - ulong curhealth; - if (m_creatureData != null && !_regenerateHealth) - { - curhealth = m_creatureData.curhealth; - if (curhealth != 0) - { - curhealth = (uint)(curhealth * GetHealthMod(GetCreatureTemplate().Classification)); - if (curhealth < 1) - curhealth = 1; - } - - SetPower(PowerType.Mana, (int)m_creatureData.curmana); - } - else - { - curhealth = GetMaxHealth(); - SetFullPower(PowerType.Mana); - } - - SetHealth((m_deathState == DeathState.Alive || m_deathState == DeathState.JustRespawned) ? curhealth : 0); + SetHealth(CountPctFromMaxHealth(m_creatureData != null ? (int)m_creatureData.curHealthPct : 100)); + SetInitialPowerValue(GetPowerType()); } public override bool HasQuest(uint questId) diff --git a/Source/Game/Entities/Creature/CreatureData.cs b/Source/Game/Entities/Creature/CreatureData.cs index ab2a2b537..e5b1e83d1 100644 --- a/Source/Game/Entities/Creature/CreatureData.cs +++ b/Source/Game/Entities/Creature/CreatureData.cs @@ -266,8 +266,7 @@ namespace Game.Entities public sbyte equipmentId; public float WanderDistance; public uint currentwaypoint; - public uint curhealth; - public uint curmana; + public uint curHealthPct; public byte movementType; public ulong? npcflag; public uint? unit_flags; // enum UnitFlags mask values diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index 65b503cb9..69b305de8 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -577,12 +577,43 @@ namespace Game.Entities //Powers public PowerType GetPowerType() { return (PowerType)(byte)m_unitData.DisplayPower; } - public void SetPowerType(PowerType powerType, bool sendUpdate = true) + public void SetPowerType(PowerType power, bool sendUpdate = true, bool onInit = false) { - if (GetPowerType() == powerType) + if (!onInit && GetPowerType() == power) return; - SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.DisplayPower), (byte)powerType); + PowerTypeRecord powerTypeEntry = Global.DB2Mgr.GetPowerTypeEntry(power); + if (powerTypeEntry == null) + return; + + if (IsCreature() && !powerTypeEntry.HasFlag(PowerTypeFlags.IsUsedByNPCs)) + return; + + SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.DisplayPower), (byte)power); + + // Update max power + UpdateMaxPower(power); + + // Update current power + if (!onInit) + { + switch (power) + { + case PowerType.Mana: // Keep the same (druid form switching...) + case PowerType.Energy: + break; + case PowerType.Rage: // Reset to zero + SetPower(PowerType.Rage, 0); + break; + case PowerType.Focus: // Make it full + SetFullPower(power); + break; + default: + break; + } + } + else + SetInitialPowerValue(power); if (!sendUpdate) return; @@ -600,24 +631,18 @@ namespace Game.Entities pet.SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE); }*/ - // Update max power - UpdateMaxPower(powerType); + } - // Update current power - switch (powerType) - { - case PowerType.Mana: // Keep the same (druid form switching...) - case PowerType.Energy: - break; - case PowerType.Rage: // Reset to zero - SetPower(PowerType.Rage, 0); - break; - case PowerType.Focus: // Make it full - SetFullPower(powerType); - break; - default: - break; - } + public void SetInitialPowerValue(PowerType power) + { + PowerTypeRecord powerTypeEntry = Global.DB2Mgr.GetPowerTypeEntry(power); + if (powerTypeEntry == null) + return; + + if (powerTypeEntry.HasFlag(PowerTypeFlags.UnitsUseDefaultPowerOnInit)) + SetPower(power, powerTypeEntry.DefaultPower); + else + SetFullPower(power); } public void SetOverrideDisplayPowerId(uint powerDisplayId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.OverrideDisplayPowerID), powerDisplayId); } diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 3a58f9cc1..8709734ae 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -3446,9 +3446,9 @@ namespace Game // 0 1 2 3 4 5 6 7 8 9 10 SQLResult result = DB.World.Query("SELECT creature.guid, id, map, position_x, position_y, position_z, orientation, modelid, equipment_id, spawntimesecs, wander_distance, " + - //11 12 13 14 15 16 17 18 19 20 21 - "currentwaypoint, curhealth, curmana, MovementType, spawnDifficulties, eventEntry, poolSpawnId, creature.npcflag, creature.unit_flags, creature.unit_flags2, creature.unit_flags3, " + - //22 23 24 25 26 27 + //11 12 13 14 15 16 17 18 19 20 + "currentwaypoint, curHealthPct, MovementType, spawnDifficulties, eventEntry, poolSpawnId, creature.npcflag, creature.unit_flags, creature.unit_flags2, creature.unit_flags3, " + + //21 22 23 24 25 26 "creature.phaseUseFlags, creature.phaseid, creature.phasegroup, creature.terrainSwapMap, creature.ScriptName, creature.StringId " + "FROM creature LEFT OUTER JOIN game_event_creature ON creature.guid = game_event_creature.guid LEFT OUTER JOIN pool_members ON pool_members.type = 0 AND creature.guid = pool_members.spawnId"); @@ -3499,28 +3499,27 @@ namespace Game data.spawntimesecs = result.Read(9); data.WanderDistance = result.Read(10); data.currentwaypoint = result.Read(11); - data.curhealth = result.Read(12); - data.curmana = result.Read(13); - data.movementType = result.Read(14); - data.SpawnDifficulties = ParseSpawnDifficulties(result.Read(15), "creature", guid, data.MapId, spawnMasks.LookupByKey(data.MapId)); - short gameEvent = result.Read(16); - data.poolId = result.Read(17); + data.curHealthPct = result.Read(12); + data.movementType = result.Read(13); + data.SpawnDifficulties = ParseSpawnDifficulties(result.Read(14), "creature", guid, data.MapId, spawnMasks.LookupByKey(data.MapId)); + short gameEvent = result.Read(15); + data.poolId = result.Read(16); + if (!result.IsNull(17)) + data.npcflag = result.Read(17); if (!result.IsNull(18)) - data.npcflag = result.Read(18); + data.unit_flags = result.Read(18); if (!result.IsNull(19)) - data.unit_flags = result.Read(19); + data.unit_flags2 = result.Read(19); if (!result.IsNull(20)) - data.unit_flags2 = result.Read(20); - if (!result.IsNull(21)) - data.unit_flags3 = result.Read(21); + data.unit_flags3 = result.Read(20); - data.PhaseUseFlags = (PhaseUseFlagsValues)result.Read(22); - data.PhaseId = result.Read(23); - data.PhaseGroup = result.Read(24); - data.terrainSwapMap = result.Read(25); - data.ScriptId = GetScriptId(result.Read(26)); - data.StringId = result.Read(27); + data.PhaseUseFlags = (PhaseUseFlagsValues)result.Read(21); + data.PhaseId = result.Read(22); + data.PhaseGroup = result.Read(23); + data.terrainSwapMap = result.Read(24); + data.ScriptId = GetScriptId(result.Read(25)); + data.StringId = result.Read(26); data.spawnGroupData = _spawnGroupDataStorage[IsTransportMap(data.MapId) ? 1 : 0u]; // transport spawns default to compatibility group var mapEntry = CliDB.MapStorage.LookupByKey(data.MapId); @@ -3662,6 +3661,13 @@ namespace Game } } + uint healthPct = Math.Clamp(data.curHealthPct, 1, 100); + if (data.curHealthPct != healthPct) + { + Log.outError(LogFilter.Sql, $"Table `creature` has creature (GUID: {guid} Entry: {data.Id}) with invalid `curHealthPct` {data.curHealthPct}, set to {healthPct}."); + data.curHealthPct = healthPct; + } + if (WorldConfig.GetBoolValue(WorldCfg.CalculateCreatureZoneAreaData)) { PhasingHandler.InitDbVisibleMapId(phaseShift, data.terrainSwapMap); diff --git a/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/Vaelastrasz.cs b/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/Vaelastrasz.cs index a2029d87e..eb9606350 100644 --- a/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/Vaelastrasz.cs +++ b/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/Vaelastrasz.cs @@ -56,6 +56,7 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackwingLair.Vaelastrasz { _Reset(); + me.SetSpawnHealth(); me.SetStandState(UnitStandStateType.Dead); Initialize(); } @@ -65,7 +66,6 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackwingLair.Vaelastrasz base.JustEngagedWith(who); DoCast(me, SpellIds.Essenceofthered); - me.SetHealth(me.CountPctFromMaxHealth(30)); // now drop damage requirement to be able to take loot me.ResetPlayerDamageReq(); diff --git a/Source/Scripts/Spells/Generic.cs b/Source/Scripts/Spells/Generic.cs index 6b4e91383..fda59b727 100644 --- a/Source/Scripts/Spells/Generic.cs +++ b/Source/Scripts/Spells/Generic.cs @@ -5102,4 +5102,32 @@ namespace Scripts.Spells.Generic DoEffectCalcDamageAndHealing.Add(new(CalculateHealingBonus, SpellConst.EffectAll, AuraType.Any)); } } + + // 24931 - 100 Health + // 24959 - 500 Health + // 28838 - 1 Health + // 43645 - 1 Health + // 73342 - 1 Health + [Script] // 86562 - 1 Health + class spell_gen_set_health : SpellScript + { + ulong _health; + + public spell_gen_set_health(ulong health) + { + _health = health; + } + + void HandleHit(uint effIndex) + { + if (GetHitUnit().IsAlive() && _health > 0) + GetHitUnit().SetHealth(_health); + } + + public override void Register() + { + OnEffectHitTarget.Add(new EffectHandler(HandleHit, 0, SpellEffectName.ScriptEffect)); + } + } + } \ No newline at end of file diff --git a/Source/Scripts/World/NpcsSpecial.cs b/Source/Scripts/World/NpcsSpecial.cs index 52017a2f2..b32857e68 100644 --- a/Source/Scripts/World/NpcsSpecial.cs +++ b/Source/Scripts/World/NpcsSpecial.cs @@ -868,7 +868,7 @@ namespace Scripts.World.NpcsSpecial me.SetStandState(UnitStandStateType.Kneel); // expect database to have RegenHealth=0 - me.SetHealth(me.CountPctFromMaxHealth(70)); + me.SetSpawnHealth(); } public override void JustEngagedWith(Unit who) { }