Core/Creatures: Split creature_addon and creature_template_addon's byte columns into seperate ones

Port From (https://github.com/TrinityCore/TrinityCore/commit/4119f69b214d6199b7ab508e305b2958eeffb332)
This commit is contained in:
hondacrx
2023-01-23 00:01:10 -05:00
parent 5619f3245a
commit 23e49e96c0
5 changed files with 156 additions and 82 deletions
+7 -2
View File
@@ -252,7 +252,9 @@ namespace Framework.Constants
SitHighChair = 6,
Dead = 7,
Kneel = 8,
Submerged = 9
Submerged = 9,
Max
}
public enum UnitVisFlags
@@ -271,7 +273,9 @@ namespace Framework.Constants
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
}
public enum UnitPVPStateFlags
@@ -543,6 +547,7 @@ namespace Framework.Constants
Unarmed = 0, // non prepared weapon
Melee = 1, // prepared melee weapon
Ranged = 2, // prepared ranged weapon
Max = 3
}
public enum MeleeHitOutcome
+30 -44
View File
@@ -2352,64 +2352,50 @@ namespace Game.Entities
public bool LoadCreaturesAddon()
{
CreatureAddon cainfo = GetCreatureAddon();
if (cainfo == null)
CreatureAddon creatureAddon = GetCreatureAddon();
if (creatureAddon == null)
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
SetStandState((UnitStandStateType)creatureAddon.standState);
ReplaceAllVisFlags((UnitVisFlags)creatureAddon.visFlags);
SetAnimTier((AnimTier)creatureAddon.animTier, false);
SetStandState((UnitStandStateType)(cainfo.bytes1 & 0xFF));
ReplaceAllVisFlags((UnitVisFlags)((cainfo.bytes1 >> 16) & 0xFF));
SetAnimTier((AnimTier)((cainfo.bytes1 >> 24) & 0xFF), false);
//! 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);
}
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
// These fields must only be handled by core internals and must not be modified via scripts/DB dat
ReplaceAllPetFlags(UnitPetFlags.None);
SetShapeshiftForm(ShapeShiftForm.None);
SetSheath((SheathState)(cainfo.bytes2 & 0xFF));
ReplaceAllPvpFlags((UnitPVPStateFlags)((cainfo.bytes2 >> 8) & 0xFF));
ReplaceAllPetFlags(UnitPetFlags.None);
SetShapeshiftForm(ShapeShiftForm.None);
}
if (creatureAddon.emote != 0)
SetEmoteState((Emote)creatureAddon.emote);
if (cainfo.emote != 0)
SetEmoteState((Emote)cainfo.emote);
SetAIAnimKitId(cainfo.aiAnimKit);
SetMovementAnimKitId(cainfo.movementAnimKit);
SetMeleeAnimKitId(cainfo.meleeAnimKit);
SetAIAnimKitId(creatureAddon.aiAnimKit);
SetMovementAnimKitId(creatureAddon.movementAnimKit);
SetMeleeAnimKitId(creatureAddon.meleeAnimKit);
// 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 != null)
if (creatureAddon.auras != null)
{
foreach (var id in cainfo.auras)
foreach (var id in creatureAddon.auras)
{
SpellInfo AdditionalSpellInfo = Global.SpellMgr.GetSpellInfo(id, GetMap().GetDifficultyID());
if (AdditionalSpellInfo == null)
@@ -408,8 +408,11 @@ namespace Game.Entities
{
public uint path_id;
public uint mount;
public uint bytes1;
public uint bytes2;
public byte standState;
public byte animTier;
public byte sheathState;
public byte pvpFlags;
public byte visFlags;
public uint emote;
public ushort aiAnimKit;
public ushort movementAnimKit;
+80 -34
View File
@@ -2097,8 +2097,8 @@ namespace Game
public void LoadCreatureTemplateAddons()
{
var time = Time.GetMSTime();
// 0 1 2 3 4 5 6 7 8 9 10
SQLResult result = DB.World.Query("SELECT entry, path_id, mount, bytes1, bytes2, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_template_addon");
// 0 1 2 3 4 5 6 7 8 9 10 11 12
SQLResult result = DB.World.Query("SELECT entry, path_id, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_template_addon");
if (result.IsEmpty())
{
@@ -2112,20 +2112,23 @@ namespace Game
uint entry = result.Read<uint>(0);
if (GetCreatureTemplate(entry) == null)
{
Log.outError(LogFilter.Sql, "Creature template (Entry: {0}) does not exist but has a record in `creature_template_addon`", entry);
Log.outError(LogFilter.Sql, $"Creature template (Entry: {entry}) does not exist but has a record in `creature_template_addon`");
continue;
}
CreatureAddon creatureAddon = new();
creatureAddon.path_id = result.Read<uint>(1);
creatureAddon.mount = result.Read<uint>(2);
creatureAddon.bytes1 = result.Read<uint>(3);
creatureAddon.bytes2 = result.Read<uint>(4);
creatureAddon.emote = result.Read<uint>(5);
creatureAddon.aiAnimKit = result.Read<ushort>(6);
creatureAddon.movementAnimKit = result.Read<ushort>(7);
creatureAddon.meleeAnimKit = result.Read<ushort>(8);
creatureAddon.visibilityDistanceType = (VisibilityDistanceType)result.Read<byte>(9);
creatureAddon.standState = result.Read<byte>(3);
creatureAddon.animTier = result.Read<byte>(4);
creatureAddon.visFlags = result.Read<byte>(5);
creatureAddon.sheathState = result.Read<byte>(6);
creatureAddon.pvpFlags = result.Read<byte>(7);
creatureAddon.emote = result.Read<uint>(8);
creatureAddon.aiAnimKit = result.Read<ushort>(9);
creatureAddon.movementAnimKit = result.Read<ushort>(10);
creatureAddon.meleeAnimKit = result.Read<ushort>(11);
creatureAddon.visibilityDistanceType = (VisibilityDistanceType)result.Read<byte>(12);
var tokens = new StringArray(result.Read<string>(10), ' ');
for (var c = 0; c < tokens.Length; ++c)
@@ -2137,16 +2140,16 @@ namespace Game
SpellInfo AdditionalSpellInfo = Global.SpellMgr.GetSpellInfo(spellId, Difficulty.None);
if (AdditionalSpellInfo == null)
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has wrong spell {1} defined in `auras` field in `creature_template_addon`.", entry, spellId);
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has wrong spell {spellId} defined in `auras` field in `creature_template_addon`.");
continue;
}
if (AdditionalSpellInfo.HasAura(AuraType.ControlVehicle))
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has SPELL_AURA_CONTROL_VEHICLE aura {1} defined in `auras` field in `creature_template_addon`.", entry, spellId);
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has SPELL_AURA_CONTROL_VEHICLE aura {spellId} defined in `auras` field in `creature_template_addon`.");
if (creatureAddon.auras.Contains(spellId))
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has duplicate aura (spell {1}) in `auras` field in `creature_template_addon`.", entry, spellId);
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has duplicate aura (spell {spellId}) in `auras` field in `creature_template_addon`.");
continue;
}
@@ -2163,32 +2166,52 @@ namespace Game
{
if (CliDB.CreatureDisplayInfoStorage.LookupByKey(creatureAddon.mount) == null)
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid displayInfoId ({1}) for mount defined in `creature_template_addon`", entry, creatureAddon.mount);
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has invalid displayInfoId ({creatureAddon.mount}) for mount defined in `creature_template_addon`");
creatureAddon.mount = 0;
}
}
if (creatureAddon.standState >= (int)UnitStandStateType.Max)
{
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has invalid unit stand state ({creatureAddon.standState}) defined in `creature_addon`. Truncated to 0.");
creatureAddon.standState = 0;
}
if (creatureAddon.animTier >= (int)AnimTier.Max)
{
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has invalid animation tier ({creatureAddon.animTier}) defined in `creature_addon`. Truncated to 0.");
creatureAddon.animTier = 0;
}
if (creatureAddon.sheathState >= (int)SheathState.Max)
{
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has invalid sheath state ({creatureAddon.sheathState}) defined in `creature_addon`. Truncated to 0.");
creatureAddon.sheathState = 0;
}
// PvPFlags don't need any checking for the time being since they cover the entire range of a byte
if (!CliDB.EmotesStorage.ContainsKey(creatureAddon.emote))
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid emote ({1}) defined in `creatureaddon`.", entry, creatureAddon.emote);
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has invalid emote ({creatureAddon.emote}) defined in `creatureaddon`.");
creatureAddon.emote = 0;
}
if (creatureAddon.aiAnimKit != 0 && !CliDB.AnimKitStorage.ContainsKey(creatureAddon.aiAnimKit))
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid aiAnimKit ({1}) defined in `creature_template_addon`.", entry, creatureAddon.aiAnimKit);
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has invalid aiAnimKit ({creatureAddon.aiAnimKit}) defined in `creature_template_addon`.");
creatureAddon.aiAnimKit = 0;
}
if (creatureAddon.movementAnimKit != 0 && !CliDB.AnimKitStorage.ContainsKey(creatureAddon.movementAnimKit))
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid movementAnimKit ({1}) defined in `creature_template_addon`.", entry, creatureAddon.movementAnimKit);
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has invalid movementAnimKit ({creatureAddon.movementAnimKit}) defined in `creature_template_addon`.");
creatureAddon.movementAnimKit = 0;
}
if (creatureAddon.meleeAnimKit != 0 && !CliDB.AnimKitStorage.ContainsKey(creatureAddon.meleeAnimKit))
{
Log.outError(LogFilter.Sql, "Creature (Entry: {0}) has invalid meleeAnimKit ({1}) defined in `creature_template_addon`.", entry, creatureAddon.meleeAnimKit);
Log.outError(LogFilter.Sql, $"Creature (Entry: {entry}) has invalid meleeAnimKit ({creatureAddon.meleeAnimKit}) defined in `creature_template_addon`.");
creatureAddon.meleeAnimKit = 0;
}
@@ -2202,13 +2225,13 @@ namespace Game
count++;
}
while (result.NextRow());
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} creature template addons in {1} ms", count, Time.GetMSTimeDiffToNow(time));
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} creature template addons in {Time.GetMSTimeDiffToNow(time)} ms");
}
public void LoadCreatureAddons()
{
var time = Time.GetMSTime();
// 0 1 2 3 4 5 6 7 8 9 10
SQLResult result = DB.World.Query("SELECT guid, path_id, mount, bytes1, bytes2, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_addon");
// 0 1 2 3 4 5 6 7 8 9 10 11 12
SQLResult result = DB.World.Query("SELECT guid, path_id, mount, StandState, AnimTier, VisFlags, SheathState, PvPFlags, emote, aiAnimKit, movementAnimKit, meleeAnimKit, visibilityDistanceType, auras FROM creature_addon");
if (result.IsEmpty())
{
@@ -2223,7 +2246,7 @@ namespace Game
CreatureData creData = GetCreatureData(guid);
if (creData == null)
{
Log.outError(LogFilter.Sql, "Creature (GUID: {0}) does not exist but has a record in `creatureaddon`", guid);
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) does not exist but has a record in `creatureaddon`");
continue;
}
@@ -2233,12 +2256,15 @@ namespace Game
if (creData.movementType == (byte)MovementGeneratorType.Waypoint && creatureAddon.path_id == 0)
{
creData.movementType = (byte)MovementGeneratorType.Idle;
Log.outError(LogFilter.Sql, "Creature (GUID {0}) has movement type set to WAYPOINTMOTIONTYPE but no path assigned", guid);
Log.outError(LogFilter.Sql, $"Creature (GUID {guid}) has movement type set to WAYPOINTMOTIONTYPE but no path assigned");
}
creatureAddon.mount = result.Read<uint>(2);
creatureAddon.bytes1 = result.Read<uint>(3);
creatureAddon.bytes2 = result.Read<uint>(4);
creatureAddon.standState = result.Read<byte>(3);
creatureAddon.animTier = result.Read<byte>(4);
creatureAddon.visFlags = result.Read<byte>(5);
creatureAddon.sheathState = result.Read<byte>(6);
creatureAddon.pvpFlags = result.Read<byte>(7);
creatureAddon.emote = result.Read<uint>(5);
creatureAddon.aiAnimKit = result.Read<ushort>(6);
creatureAddon.movementAnimKit = result.Read<ushort>(7);
@@ -2255,16 +2281,16 @@ namespace Game
SpellInfo AdditionalSpellInfo = Global.SpellMgr.GetSpellInfo(spellId, Difficulty.None);
if (AdditionalSpellInfo == null)
{
Log.outError(LogFilter.Sql, "Creature (GUID: {0}) has wrong spell {1} defined in `auras` field in `creatureaddon`.", guid, spellId);
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) has wrong spell {spellId} defined in `auras` field in `creatureaddon`.");
continue;
}
if (AdditionalSpellInfo.HasAura(AuraType.ControlVehicle))
Log.outError(LogFilter.Sql, "Creature (GUID: {0}) has SPELL_AURA_CONTROL_VEHICLE aura {1} defined in `auras` field in `creature_addon`.", guid, spellId);
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) has SPELL_AURA_CONTROL_VEHICLE aura {spellId} defined in `auras` field in `creature_addon`.");
if (creatureAddon.auras.Contains(spellId))
{
Log.outError(LogFilter.Sql, "Creature (GUID: {0}) has duplicate aura (spell {1}) in `auras` field in `creature_addon`.", guid, spellId);
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) has duplicate aura (spell {spellId}) in `auras` field in `creature_addon`.");
continue;
}
@@ -2281,33 +2307,53 @@ namespace Game
{
if (!CliDB.CreatureDisplayInfoStorage.ContainsKey(creatureAddon.mount))
{
Log.outError(LogFilter.Sql, "Creature (GUID: {0}) has invalid displayInfoId ({1}) for mount defined in `creatureaddon`", guid, creatureAddon.mount);
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) has invalid displayInfoId ({creatureAddon.mount}) for mount defined in `creatureaddon`");
creatureAddon.mount = 0;
}
}
if (creatureAddon.standState >= (int)UnitStandStateType.Max)
{
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) has invalid unit stand state ({creatureAddon.standState}) defined in `creature_addon`. Truncated to 0.");
creatureAddon.standState = 0;
}
if (creatureAddon.animTier >= (int)AnimTier.Max)
{
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) has invalid animation tier ({creatureAddon.animTier}) defined in `creature_addon`. Truncated to 0.");
creatureAddon.animTier = 0;
}
if (creatureAddon.sheathState >= (int)SheathState.Max)
{
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) has invalid sheath state ({creatureAddon.sheathState}) defined in `creature_addon`. Truncated to 0.");
creatureAddon.sheathState = 0;
}
// PvPFlags don't need any checking for the time being since they cover the entire range of a byte
if (!CliDB.EmotesStorage.ContainsKey(creatureAddon.emote))
{
Log.outError(LogFilter.Sql, "Creature (GUID: {0}) has invalid emote ({1}) defined in `creatureaddon`.", guid, creatureAddon.emote);
Log.outError(LogFilter.Sql, $"Creature (GUID: {guid}) has invalid emote ({creatureAddon.emote}) defined in `creatureaddon`.");
creatureAddon.emote = 0;
}
if (creatureAddon.aiAnimKit != 0 && !CliDB.AnimKitStorage.ContainsKey(creatureAddon.aiAnimKit))
{
Log.outError(LogFilter.Sql, "Creature (Guid: {0}) has invalid aiAnimKit ({1}) defined in `creature_addon`.", guid, creatureAddon.aiAnimKit);
Log.outError(LogFilter.Sql, $"Creature (Guid: {guid}) has invalid aiAnimKit ({creatureAddon.aiAnimKit}) defined in `creature_addon`.");
creatureAddon.aiAnimKit = 0;
}
if (creatureAddon.movementAnimKit != 0 && !CliDB.AnimKitStorage.ContainsKey(creatureAddon.movementAnimKit))
{
Log.outError(LogFilter.Sql, "Creature (Guid: {0}) has invalid movementAnimKit ({1}) defined in `creature_addon`.", guid, creatureAddon.movementAnimKit);
Log.outError(LogFilter.Sql, $"Creature (Guid: {guid}) has invalid movementAnimKit ({creatureAddon.movementAnimKit}) defined in `creature_addon`.");
creatureAddon.movementAnimKit = 0;
}
if (creatureAddon.meleeAnimKit != 0 && !CliDB.AnimKitStorage.ContainsKey(creatureAddon.meleeAnimKit))
{
Log.outError(LogFilter.Sql, "Creature (Guid: {0}) has invalid meleeAnimKit ({1}) defined in `creature_addon`.", guid, creatureAddon.meleeAnimKit);
Log.outError(LogFilter.Sql, $"Creature (Guid: {guid}) has invalid meleeAnimKit ({creatureAddon.meleeAnimKit}) defined in `creature_addon`.");
creatureAddon.meleeAnimKit = 0;
}
@@ -2321,7 +2367,7 @@ namespace Game
count++;
} while (result.NextRow());
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} creature addons in {1} ms", count, Time.GetMSTimeDiffToNow(time));
Log.outInfo(LogFilter.ServerLoading, $"Loaded {count} creature addons in {Time.GetMSTimeDiffToNow(time)} ms");
}
public void LoadCreatureQuestItems()
{
@@ -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`;