aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/3.3.5/2023_01_09_00_world.sql34
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp70
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h7
-rw-r--r--src/server/game/Entities/Unit/UnitDefines.h14
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp74
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);