diff options
-rw-r--r-- | sql/updates/world/3.3.5/2023_01_09_00_world.sql | 34 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 70 | ||||
-rw-r--r-- | src/server/game/Entities/Creature/CreatureData.h | 7 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/UnitDefines.h | 14 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 74 |
5 files changed, 137 insertions, 62 deletions
diff --git a/sql/updates/world/3.3.5/2023_01_09_00_world.sql b/sql/updates/world/3.3.5/2023_01_09_00_world.sql new file mode 100644 index 00000000000..c58503cbc0c --- /dev/null +++ b/sql/updates/world/3.3.5/2023_01_09_00_world.sql @@ -0,0 +1,34 @@ +ALTER TABLE `creature_template_addon` + ADD COLUMN `StandState` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `MountCreatureID`, + ADD COLUMN `AnimTier` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `StandState`, + ADD COLUMN `VisFlags` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `AnimTier`, + ADD COLUMN `SheathState` TINYINT UNSIGNED DEFAULT 1 NOT NULL AFTER `VisFlags`, + ADD COLUMN `PvPFlags` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `SheathState`; + +UPDATE `creature_template_addon` SET `StandState`=`bytes1` & 0xFF; +UPDATE `creature_template_addon` SET `AnimTier`=(`bytes1` >> 24) & 0xFF; +UPDATE `creature_template_addon` SET `VisFlags`=(`bytes1` >> 16) & 0xFF; +UPDATE `creature_template_addon` SET `SheathState`=`bytes2` & 0xFF; +UPDATE `creature_template_addon` SET `PvPFlags`=(`bytes2` >> 8) & 0xFF; + +ALTER TABLE `creature_addon` + ADD COLUMN `StandState` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `MountCreatureID`, + ADD COLUMN `AnimTier` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `StandState`, + ADD COLUMN `VisFlags` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `AnimTier`, + ADD COLUMN `SheathState` TINYINT UNSIGNED DEFAULT 1 NOT NULL AFTER `VisFlags`, + ADD COLUMN `PvPFlags` TINYINT UNSIGNED DEFAULT 0 NOT NULL AFTER `SheathState`; + +UPDATE `creature_addon` SET `StandState`=`bytes1` & 0xFF; +UPDATE `creature_addon` SET `AnimTier`=(`bytes1` >> 24) & 0xFF; +UPDATE `creature_addon` SET `VisFlags`=(`bytes1` >> 16) & 0xFF; +UPDATE `creature_addon` SET `SheathState`=`bytes2` & 0xFF; +UPDATE `creature_addon` SET `PvPFlags`=(`bytes2` >> 8) & 0xFF; + +-- Conversion done, drop old columns +ALTER TABLE `creature_template_addon` + DROP COLUMN `bytes1`, + DROP COLUMN `bytes2`; + +ALTER TABLE `creature_addon` + DROP COLUMN `bytes1`, + DROP COLUMN `bytes2`; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index d7f2bec6d57..0b0d343830b 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2510,60 +2510,48 @@ CreatureAddon const* Creature::GetCreatureAddon() const //creature_addon table bool Creature::LoadCreaturesAddon() { - CreatureAddon const* cainfo = GetCreatureAddon(); - if (!cainfo) + CreatureAddon const* creatureAddon = GetCreatureAddon(); + if (!creatureAddon) return false; - if (cainfo->mount != 0) - Mount(cainfo->mount); + if (creatureAddon->mount != 0) + Mount(creatureAddon->mount); - if (cainfo->bytes1 != 0) - { - // 0 StandState - // 1 FreeTalentPoints Pet only, so always 0 for default creature - // 2 StandFlags - // 3 StandMiscFlags + // UNIT_FIELD_BYTES_1 values + SetStandState(UnitStandStateType(creatureAddon->standState)); + SetAnimTier(AnimTier(creatureAddon->animTier)); + ReplaceAllVisFlags(UnitVisFlags(creatureAddon->visFlags)); - SetStandState(UnitStandStateType(cainfo->bytes1 & 0xFF)); - ReplaceAllVisFlags(UnitVisFlags((cainfo->bytes1 >> 16) & 0xFF)); - SetAnimTier(AnimTier((cainfo->bytes1 >> 24) & 0xFF)); + //! Suspected correlation between UNIT_FIELD_BYTES_1, offset 3, value 0x2: + //! If no inhabittype_fly (if no MovementFlag_DisableGravity or MovementFlag_CanFly flag found in sniffs) + //! Check using InhabitType as movement flags are assigned dynamically + //! basing on whether the creature is in air or not + //! Set MovementFlag_Hover. Otherwise do nothing. + if (CanHover()) + AddUnitMovementFlag(MOVEMENTFLAG_HOVER); - //! Suspected correlation between UNIT_FIELD_BYTES_1, offset 3, value 0x2: - //! If no inhabittype_fly (if no MovementFlag_DisableGravity or MovementFlag_CanFly flag found in sniffs) - //! Check using InhabitType as movement flags are assigned dynamically - //! basing on whether the creature is in air or not - //! Set MovementFlag_Hover. Otherwise do nothing. - if (CanHover()) - AddUnitMovementFlag(MOVEMENTFLAG_HOVER); - } + // UNIT_FIELD_BYTES_2 values + SetSheath(SheathState(creatureAddon->sheathState)); + ReplaceAllPvpFlags(UnitPVPStateFlags(creatureAddon->pvpFlags)); - if (cainfo->bytes2 != 0) - { - // 0 SheathState - // 1 PvpFlags - // 2 PetFlags Pet only, so always 0 for default creature - // 3 ShapeshiftForm Must be determined/set by shapeshift spell/aura - - SetSheath(SheathState(cainfo->bytes2 & 0xFF)); - ReplaceAllPvpFlags(UnitPVPStateFlags((cainfo->bytes2 >> 8) & 0xFF)); - ReplaceAllPetFlags(UNIT_PET_FLAG_NONE); - SetShapeshiftForm(FORM_NONE); - } + // These fields must only be handled by core internals and must not be modified via scripts/DB data + ReplaceAllPetFlags(UNIT_PET_FLAG_NONE); + SetShapeshiftForm(FORM_NONE); - if (cainfo->emote != 0) - SetEmoteState(Emote(cainfo->emote)); + if (creatureAddon->emote != 0) + SetEmoteState(Emote(creatureAddon->emote)); // Check if visibility distance different - if (cainfo->visibilityDistanceType != VisibilityDistanceType::Normal) - SetVisibilityDistanceOverride(cainfo->visibilityDistanceType); + if (creatureAddon->visibilityDistanceType != VisibilityDistanceType::Normal) + SetVisibilityDistanceOverride(creatureAddon->visibilityDistanceType); // Load Path - if (cainfo->path_id != 0) - _waypointPathId = cainfo->path_id; + if (creatureAddon->path_id != 0) + _waypointPathId = creatureAddon->path_id; - if (!cainfo->auras.empty()) + if (!creatureAddon->auras.empty()) { - for (std::vector<uint32>::const_iterator itr = cainfo->auras.begin(); itr != cainfo->auras.end(); ++itr) + for (std::vector<uint32>::const_iterator itr = creatureAddon->auras.begin(); itr != creatureAddon->auras.end(); ++itr) { SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(*itr); if (!AdditionalSpellInfo) diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index 96c6e2a7cb5..325bc22ab26 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -479,8 +479,11 @@ struct CreatureAddon { uint32 path_id; uint32 mount; - uint32 bytes1; - uint32 bytes2; + uint8 standState; + uint8 animTier; + uint8 sheathState; + uint8 pvpFlags; + uint8 visFlags; uint32 emote; std::vector<uint32> auras; VisibilityDistanceType visibilityDistanceType; diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h index b95c0d4c1ac..af72559baa8 100644 --- a/src/server/game/Entities/Unit/UnitDefines.h +++ b/src/server/game/Entities/Unit/UnitDefines.h @@ -40,7 +40,9 @@ enum UnitStandStateType : uint8 UNIT_STAND_STATE_SIT_HIGH_CHAIR = 6, UNIT_STAND_STATE_DEAD = 7, UNIT_STAND_STATE_KNEEL = 8, - UNIT_STAND_STATE_SUBMERGED = 9 + UNIT_STAND_STATE_SUBMERGED = 9, + + MAX_UNIT_STAND_STATE }; // byte flag value (UNIT_FIELD_BYTES_1, 2) @@ -85,7 +87,9 @@ enum class AnimTier : uint8 Swim = 1, // falls back to ground tier animations, not handled by the client, should never appear in sniffs, will prevent tier change animations from playing correctly if used Hover = 2, // plays flying tier animations or falls back to ground tier animations, automatically enables hover clientside when entering visibility with this value Fly = 3, // plays flying tier animations - Submerged = 4 + Submerged = 4, + + Max }; // low byte (0 from 0..3) of UNIT_FIELD_BYTES_2 @@ -93,10 +97,10 @@ enum SheathState : uint8 { SHEATH_STATE_UNARMED = 0, // non prepared weapon SHEATH_STATE_MELEE = 1, // prepared melee weapon - SHEATH_STATE_RANGED = 2 // prepared ranged weapon -}; + SHEATH_STATE_RANGED = 2, // prepared ranged weapon -#define MAX_SHEATH_STATE 3 + MAX_SHEATH_STATE +}; // byte (1 from 0..3) of UNIT_FIELD_BYTES_2 enum UnitPVPStateFlags : uint8 diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 46d9cf9d9bd..eddedb75126 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -711,8 +711,8 @@ void ObjectMgr::LoadCreatureTemplateAddons() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 5 6 7 - QueryResult result = WorldDatabase.Query("SELECT entry, path_id, mount, bytes1, bytes2, emote, visibilityDistanceType, auras FROM creature_template_addon"); + // 0 1 2 3 4 5 6 7 8 9 10 + QueryResult result = WorldDatabase.Query("SELECT entry, path_id, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, visibilityDistanceType, auras FROM creature_template_addon"); if (!result) { @@ -737,12 +737,15 @@ void ObjectMgr::LoadCreatureTemplateAddons() creatureAddon.path_id = fields[1].GetUInt32(); creatureAddon.mount = fields[2].GetUInt32(); - creatureAddon.bytes1 = fields[3].GetUInt32(); - creatureAddon.bytes2 = fields[4].GetUInt32(); - creatureAddon.emote = fields[5].GetUInt32(); - creatureAddon.visibilityDistanceType = VisibilityDistanceType(fields[6].GetUInt8()); + creatureAddon.standState = fields[3].GetUInt8(); + creatureAddon.animTier = fields[4].GetUInt8(); + creatureAddon.visFlags = fields[5].GetUInt8(); + creatureAddon.sheathState = fields[6].GetUInt8(); + creatureAddon.pvpFlags = fields[7].GetUInt8(); + creatureAddon.emote = fields[8].GetUInt32(); + creatureAddon.visibilityDistanceType = VisibilityDistanceType(fields[9].GetUInt8()); - for (std::string_view aura : Trinity::Tokenize(fields[7].GetStringView(), ' ', false)) + for (std::string_view aura : Trinity::Tokenize(fields[10].GetStringView(), ' ', false)) { SpellInfo const* spellInfo = nullptr; @@ -782,6 +785,26 @@ void ObjectMgr::LoadCreatureTemplateAddons() } } + if (creatureAddon.standState >= MAX_UNIT_STAND_STATE) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid unit stand state (%u) defined in `creature_addon`. Truncated to 0.", entry, creatureAddon.standState); + creatureAddon.standState = 0; + } + + if (AnimTier(creatureAddon.animTier) >= AnimTier::Max) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid animation tier (%u) defined in `creature_addon`. Truncated to 0.", entry, creatureAddon.animTier); + creatureAddon.animTier = 0; + } + + if (creatureAddon.sheathState >= MAX_SHEATH_STATE) + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid sheath state (%u) defined in `creature_addon`. Truncated to 0.", entry, creatureAddon.sheathState); + creatureAddon.sheathState = 0; + } + + // PvPFlags don't need any checking for the time being since they cover the entire range of a byte + if (!sEmotesStore.LookupEntry(creatureAddon.emote)) { TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid emote (%u) defined in `creature_template_addon`.", entry, creatureAddon.emote); @@ -1259,8 +1282,8 @@ void ObjectMgr::LoadCreatureAddons() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 5 6 7 - QueryResult result = WorldDatabase.Query("SELECT guid, path_id, mount, bytes1, bytes2, emote, visibilityDistanceType, auras FROM creature_addon"); + // 0 1 2 3 4 5 6 7 8 9 10 + QueryResult result = WorldDatabase.Query("SELECT guid, path_id, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, visibilityDistanceType, auras FROM creature_addon"); if (!result) { @@ -1292,12 +1315,15 @@ void ObjectMgr::LoadCreatureAddons() } creatureAddon.mount = fields[2].GetUInt32(); - creatureAddon.bytes1 = fields[3].GetUInt32(); - creatureAddon.bytes2 = fields[4].GetUInt32(); - creatureAddon.emote = fields[5].GetUInt32(); - creatureAddon.visibilityDistanceType = VisibilityDistanceType(fields[6].GetUInt8()); + creatureAddon.standState = fields[3].GetUInt8(); + creatureAddon.animTier = fields[4].GetUInt8(); + creatureAddon.visFlags = fields[5].GetUInt8(); + creatureAddon.sheathState = fields[6].GetUInt8(); + creatureAddon.pvpFlags = fields[7].GetUInt8(); + creatureAddon.emote = fields[8].GetUInt32(); + creatureAddon.visibilityDistanceType = VisibilityDistanceType(fields[9].GetUInt8()); - for (std::string_view aura : Trinity::Tokenize(fields[7].GetStringView(), ' ', false)) + for (std::string_view aura : Trinity::Tokenize(fields[10].GetStringView(), ' ', false)) { SpellInfo const* spellInfo = nullptr; if (Optional<uint32> spellId = Trinity::StringTo<uint32>(aura)) @@ -1336,6 +1362,26 @@ void ObjectMgr::LoadCreatureAddons() } } + if (creatureAddon.standState >= MAX_UNIT_STAND_STATE) + { + TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has invalid unit stand state (%u) defined in `creature_addon`. Truncated to 0.", guid, creatureAddon.standState); + creatureAddon.standState = 0; + } + + if (AnimTier(creatureAddon.animTier) >= AnimTier::Max) + { + TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has invalid animation tier (%u) defined in `creature_addon`. Truncated to 0.", guid, creatureAddon.animTier); + creatureAddon.animTier = 0; + } + + if (creatureAddon.sheathState >= MAX_SHEATH_STATE) + { + TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has invalid sheath state (%u) defined in `creature_addon`. Truncated to 0.", guid, creatureAddon.sheathState); + creatureAddon.sheathState = 0; + } + + // PvPFlags don't need any checking for the time being since they cover the entire range of a byte + if (!sEmotesStore.LookupEntry(creatureAddon.emote)) { TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has invalid emote (%u) defined in `creature_addon`.", guid, creatureAddon.emote); |