aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMeji <alvaro.megias@outlook.com>2024-03-30 20:21:28 +0100
committerGitHub <noreply@github.com>2024-03-30 20:21:28 +0100
commitdef601b4ff82ec8a90af60408a87cac92fdf070d (patch)
tree4e5de744a4712a49b1126b8270ac02d842d56e32 /src
parentd8a82ab909543259be7632bb1e1b256ed6bfa4c2 (diff)
Core/Creatures: Changed the spawn health field in creature table to a percentage (#29801)
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.cpp2
-rw-r--r--src/server/game/DataStores/DBCEnums.h2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp40
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h3
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp64
-rw-r--r--src/server/game/Entities/Unit/Unit.h3
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp48
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp3
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp11
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp29
-rw-r--r--src/server/scripts/World/npcs_special.cpp2
12 files changed, 114 insertions, 95 deletions
diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp
index 2438bc1c1e1..9827b442464 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.cpp
+++ b/src/server/database/Database/Implementation/WorldDatabase.cpp
@@ -66,7 +66,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(WORLD_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_", CONNECTION_SYNCH);
PrepareStatement(WORLD_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_", CONNECTION_SYNCH);
- PrepareStatement(WORLD_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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(WORLD_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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(WORLD_DEL_GAME_EVENT_CREATURE, "DELETE FROM game_event_creature WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_DEL_GAME_EVENT_MODEL_EQUIP, "DELETE FROM game_event_model_equip WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 92c71f389e1..0f6780d56d9 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -1843,7 +1843,7 @@ enum class PowerTypeFlags : int16
ContinueRegenWhileFatigued = 0x0200, // NYI
RegenAffectedByHaste = 0x0400, // NYI
SetToMaxOnLevelUp = 0x1000,
- SetToMaxLevelOnInitialLogIn = 0x2000, // NYI
+ SetToMaxOnInitialLogIn = 0x2000, // NYI
AllowCostModsForPlayers = 0x4000 // NYI
};
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 18343779978..fedad2a592d 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -1492,8 +1492,7 @@ void Creature::SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDiffic
// prevent add data integrity problems
data.wander_distance = GetDefaultMovementType() == IDLE_MOTION_TYPE ? 0.0f : m_wanderDistance;
data.currentwaypoint = 0;
- data.curhealth = GetHealth();
- data.curmana = GetPower(POWER_MANA);
+ data.curHealthPct = uint32(GetHealthPct());
// prevent add data integrity problems
data.movementType = !m_wanderDistance && GetDefaultMovementType() == RANDOM_MOTION_TYPE
? IDLE_MOTION_TYPE : GetDefaultMovementType();
@@ -1546,8 +1545,7 @@ void Creature::SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDiffic
stmt->setUInt32(index++, m_respawnDelay);
stmt->setFloat(index++, m_wanderDistance);
stmt->setUInt32(index++, 0);
- stmt->setUInt32(index++, GetHealth());
- stmt->setUInt32(index++, GetPower(POWER_MANA));
+ stmt->setUInt32(index++, uint32(GetHealthPct()));
stmt->setUInt8(index++, uint8(GetDefaultMovementType()));
if (npcflag.has_value())
stmt->setUInt64(index++, *npcflag);
@@ -1608,15 +1606,7 @@ void Creature::UpdateLevelDependantStats()
Powers powerType = CalculateDisplayPowerType();
SetCreateMana(stats->BaseMana);
SetStatPctModifier(UnitMods(UNIT_MOD_POWER_START + AsUnderlyingType(powerType)), BASE_PCT, GetCreatureDifficulty()->ManaModifier);
- SetPowerType(powerType);
-
- if (PowerTypeEntry const* powerTypeEntry = sDB2Manager.GetPowerTypeEntry(powerType))
- {
- if (powerTypeEntry->GetFlags().HasFlag(PowerTypeFlags::UnitsUseDefaultPowerOnInit))
- SetPower(powerType, powerTypeEntry->DefaultPower);
- else
- SetFullPower(powerType);
- }
+ SetPowerType(powerType, true, true);
// damage
float basedamage = GetBaseDamageForLevel(level);
@@ -1968,28 +1958,8 @@ void Creature::LoadEquipment(int8 id, bool force /*= true*/)
void Creature::SetSpawnHealth()
{
- if (_staticFlags.HasFlag(CREATURE_STATIC_FLAG_5_NO_HEALTH_REGEN))
- return;
-
- uint32 curhealth;
- if (m_creatureData && !_regenerateHealth)
- {
- curhealth = m_creatureData->curhealth;
- if (curhealth)
- {
- curhealth = uint32(curhealth*GetHealthMod(GetCreatureTemplate()->Classification));
- if (curhealth < 1)
- curhealth = 1;
- }
- SetPower(POWER_MANA, m_creatureData->curmana);
- }
- else
- {
- curhealth = GetMaxHealth();
- SetFullPower(POWER_MANA);
- }
-
- SetHealth((m_deathState == ALIVE || m_deathState == JUST_RESPAWNED) ? curhealth : 0);
+ SetHealth(CountPctFromMaxHealth(m_creatureData ? m_creatureData->curHealthPct : 100));
+ SetInitialPowerValue(GetPowerType());
}
bool Creature::hasQuest(uint32 quest_id) const
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 976244a8f85..dea0e4be37b 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -592,8 +592,7 @@ struct CreatureData : public SpawnData
int8 equipmentId = 0;
float wander_distance = 0.0f;
uint32 currentwaypoint = 0;
- uint32 curhealth = 0;
- uint32 curmana = 0;
+ uint32 curHealthPct = 0;
uint8 movementType = 0;
Optional<uint64> npcflag;
Optional<uint32> unit_flags; // enum UnitFlags mask values
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 42919533589..6bb4cd2a8cb 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -5531,12 +5531,43 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType
SendAttackStateUpdate(&dmgInfo);
}
-void Unit::SetPowerType(Powers new_powertype, bool sendUpdate/* = true*/)
+void Unit::SetPowerType(Powers power, bool sendUpdate/* = true*/, bool onInit /*= false*/)
{
- if (GetPowerType() == new_powertype)
+ if (!onInit && GetPowerType() == power)
return;
- SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::DisplayPower), new_powertype);
+ PowerTypeEntry const* powerTypeEntry = sDB2Manager.GetPowerTypeEntry(power);
+ if (!powerTypeEntry)
+ return;
+
+ if (IsCreature() && !powerTypeEntry->GetFlags().HasFlag(PowerTypeFlags::IsUsedByNPCs))
+ return;
+
+ SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::DisplayPower), power);
+
+ // Update max power
+ UpdateMaxPower(power);
+
+ // Update current power
+ if (!onInit)
+ {
+ switch (power)
+ {
+ case POWER_MANA: // Keep the same (druid form switching...)
+ case POWER_ENERGY:
+ break;
+ case POWER_RAGE: // Reset to zero
+ SetPower(POWER_RAGE, 0);
+ break;
+ case POWER_FOCUS: // Make it full
+ SetFullPower(power);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ SetInitialPowerValue(power);
if (!sendUpdate)
return;
@@ -5551,25 +5582,18 @@ void Unit::SetPowerType(Powers new_powertype, bool sendUpdate/* = true*/)
if (pet->isControlled())
pet->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_POWER_TYPE);
}*/
+}
- // Update max power
- UpdateMaxPower(new_powertype);
+void Unit::SetInitialPowerValue(Powers powerType)
+{
+ PowerTypeEntry const* powerTypeEntry = sDB2Manager.GetPowerTypeEntry(powerType);
+ if (!powerTypeEntry)
+ return;
- // Update current power
- switch (new_powertype)
- {
- case POWER_MANA: // Keep the same (druid form switching...)
- case POWER_ENERGY:
- break;
- case POWER_RAGE: // Reset to zero
- SetPower(POWER_RAGE, 0);
- break;
- case POWER_FOCUS: // Make it full
- SetFullPower(new_powertype);
- break;
- default:
- break;
- }
+ if (powerTypeEntry->GetFlags().HasFlag(PowerTypeFlags::UnitsUseDefaultPowerOnInit))
+ SetPower(powerType, powerTypeEntry->DefaultPower);
+ else
+ SetFullPower(powerType);
}
Powers Unit::CalculateDisplayPowerType() const
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index abcf9c295b5..d2a69f57567 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -797,7 +797,8 @@ class TC_GAME_API Unit : public WorldObject
virtual float GetArmorMultiplierForTarget(WorldObject const* /*target*/) const { return 1.0f; }
Powers GetPowerType() const { return Powers(*m_unitData->DisplayPower); }
- void SetPowerType(Powers power, bool sendUpdate = true);
+ void SetPowerType(Powers power, bool sendUpdate = true, bool onInit = false);
+ void SetInitialPowerValue(Powers powerType);
void SetOverrideDisplayPowerId(uint32 powerDisplayId) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::OverrideDisplayPowerID), powerDisplayId); }
Powers CalculateDisplayPowerType() const;
void UpdateDisplayPower();
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 2c1d5c7ae81..7c933cdd774 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -2135,9 +2135,9 @@ void ObjectMgr::LoadCreatures()
// 0 1 2 3 4 5 6 7 8 9 10
QueryResult result = WorldDatabase.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 "
@@ -2182,27 +2182,26 @@ void ObjectMgr::LoadCreatures()
data.equipmentId = fields[8].GetInt8();
data.spawntimesecs = fields[9].GetUInt32();
data.wander_distance = fields[10].GetFloat();
- data.currentwaypoint= fields[11].GetUInt32();
- data.curhealth = fields[12].GetUInt32();
- data.curmana = fields[13].GetUInt32();
- data.movementType = fields[14].GetUInt8();
- data.spawnDifficulties = ParseSpawnDifficulties(fields[15].GetStringView(), "creature", guid, data.mapId, spawnMasks[data.mapId]);
- int16 gameEvent = fields[16].GetInt8();
- data.poolId = fields[17].GetUInt32();
+ data.currentwaypoint = fields[11].GetUInt32();
+ data.curHealthPct = fields[12].GetUInt32();
+ data.movementType = fields[13].GetUInt8();
+ data.spawnDifficulties = ParseSpawnDifficulties(fields[14].GetStringView(), "creature", guid, data.mapId, spawnMasks[data.mapId]);
+ int16 gameEvent = fields[15].GetInt8();
+ data.poolId = fields[16].GetUInt32();
+ if (!fields[17].IsNull())
+ data.npcflag = fields[17].GetUInt64();
if (!fields[18].IsNull())
- data.npcflag = fields[18].GetUInt64();
+ data.unit_flags = fields[18].GetUInt32();
if (!fields[19].IsNull())
- data.unit_flags = fields[19].GetUInt32();
+ data.unit_flags2 = fields[19].GetUInt32();
if (!fields[20].IsNull())
- data.unit_flags2 = fields[20].GetUInt32();
- if (!fields[21].IsNull())
- data.unit_flags3 = fields[21].GetUInt32();
- data.phaseUseFlags = fields[22].GetUInt8();
- data.phaseId = fields[23].GetUInt32();
- data.phaseGroup = fields[24].GetUInt32();
- data.terrainSwapMap = fields[25].GetInt32();
- data.scriptId = GetScriptId(fields[26].GetString());
- data.StringId = fields[27].GetString();
+ data.unit_flags3 = fields[20].GetUInt32();
+ data.phaseUseFlags = fields[21].GetUInt8();
+ data.phaseId = fields[22].GetUInt32();
+ data.phaseGroup = fields[23].GetUInt32();
+ data.terrainSwapMap = fields[24].GetInt32();
+ data.scriptId = GetScriptId(fields[25].GetString());
+ data.StringId = fields[26].GetString();
data.spawnGroupData = IsTransportMap(data.mapId) ? GetLegacySpawnGroup() : GetDefaultSpawnGroup(); // transport spawns default to compatibility group
MapEntry const* mapEntry = sMapStore.LookupEntry(data.mapId);
@@ -2364,6 +2363,13 @@ void ObjectMgr::LoadCreatures()
}
}
+ uint32 healthPct = std::clamp<uint32>(data.curHealthPct, 1, 100);
+ if (data.curHealthPct != healthPct)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `creature` has creature (GUID: {} Entry: {}) with invalid `curHealthPct` {}, set to {}.", guid, data.id, data.curHealthPct, healthPct);
+ data.curHealthPct = healthPct;
+ }
+
if (sWorld->getBoolConfig(CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA))
{
uint32 zoneId = 0;
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index ed6e2014ead..86686a52ac2 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -290,9 +290,8 @@ public:
return false;
}
- creature->SetMaxHealth(100 + 30*lvl);
- creature->SetHealth(100 + 30*lvl);
creature->SetLevel(lvl);
+ creature->UpdateLevelDependantStats();
creature->SaveToDB();
return true;
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp
index ee9e3cb1d07..48844dc0aa9 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp
@@ -84,6 +84,7 @@ struct boss_vaelastrasz : public BossAI
{
_Reset();
+ me->SetSpawnHealth();
me->SetStandState(UNIT_STAND_STATE_DEAD);
Initialize();
}
@@ -93,7 +94,6 @@ struct boss_vaelastrasz : public BossAI
BossAI::JustEngagedWith(who);
DoCast(me, SPELL_ESSENCEOFTHERED);
- me->SetHealth(me->CountPctFromMaxHealth(30));
// now drop damage requirement to be able to take loot
me->ResetPlayerDamageReq();
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
index 3b9e0f2b8de..aa44e6bb7a7 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
@@ -275,19 +275,10 @@ struct boss_valithria_dreamwalker : public ScriptedAI
_done = false;
}
- void InitializeAI() override
- {
- if (CreatureData const* data = me->GetCreatureData())
- if (data->curhealth)
- _spawnHealth = data->curhealth;
-
- ScriptedAI::InitializeAI();
- }
-
void Reset() override
{
_events.Reset();
- me->SetHealth(_spawnHealth);
+ me->SetSpawnHealth();
me->SetReactState(REACT_PASSIVE);
me->LoadCreaturesAddon();
// immune to percent heals
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index ff12c258c5e..8486d30ca9a 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -5317,6 +5317,32 @@ class spell_gen_random_aggro_taunt : public SpellScript
}
};
+// 24931 - 100 Health
+// 24959 - 500 Health
+// 28838 - 1 Health
+// 43645 - 1 Health
+// 73342 - 1 Health
+// 86562 - 1 Health
+class spell_gen_set_health : public SpellScript
+{
+public:
+ spell_gen_set_health(uint64 health) : _health(health) { }
+
+ void HandleHit(SpellEffIndex /*effIndex*/)
+ {
+ if (GetHitUnit()->IsAlive() && _health > 0)
+ GetHitUnit()->SetHealth(_health);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_set_health::HandleHit, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+
+private:
+ uint64 _health;
+};
+
void AddSC_generic_spell_scripts()
{
RegisterSpellScript(spell_gen_absorb0_hitlimit1);
@@ -5493,4 +5519,7 @@ void AddSC_generic_spell_scripts()
RegisterSpellScript(spell_gen_major_healing_cooldown_modifier);
RegisterSpellScript(spell_gen_major_healing_cooldown_modifier_aura);
RegisterSpellScript(spell_gen_random_aggro_taunt);
+ RegisterSpellScriptWithArgs(spell_gen_set_health, "spell_gen_set_health_1", 1);
+ RegisterSpellScriptWithArgs(spell_gen_set_health, "spell_gen_set_health_100", 100);
+ RegisterSpellScriptWithArgs(spell_gen_set_health, "spell_gen_set_health_500", 500);
}
diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp
index a3db8c19c6b..d2294bbd2b7 100644
--- a/src/server/scripts/World/npcs_special.cpp
+++ b/src/server/scripts/World/npcs_special.cpp
@@ -1005,7 +1005,7 @@ public:
me->SetStandState(UNIT_STAND_STATE_KNEEL);
// expect database to have RegenHealth=0
- me->SetHealth(me->CountPctFromMaxHealth(70));
+ me->SetSpawnHealth();
}
void JustEngagedWith(Unit* /*who*/) override { }