diff --git a/Source/Framework/Database/Databases/WorldDatabase.cs b/Source/Framework/Database/Databases/WorldDatabase.cs index 46e16861a..4216c22cb 100644 --- a/Source/Framework/Database/Databases/WorldDatabase.cs +++ b/Source/Framework/Database/Databases/WorldDatabase.cs @@ -75,7 +75,7 @@ namespace Framework.Database PrepareStatement(WorldStatements.SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?"); PrepareStatement(WorldStatements.DEL_CREATURE, "DELETE FROM creature WHERE guid = ?"); PrepareStatement(WorldStatements.SEL_COMMANDS, "SELECT name, permission, help FROM command"); - PrepareStatement(WorldStatements.SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ? OR 1 = ?"); + PrepareStatement(WorldStatements.SEL_CREATURE_TEMPLATE, "SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, name, femaleName, subname, TitleAlt, IconName, gossip_menu_id, minlevel, maxlevel, HealthScalingExpansion, RequiredExpansion, VignetteID, faction, npcflag, speed_walk, speed_run, scale, `rank`, dmgschool, BaseAttackTime, RangeAttackTime, BaseVariance, RangeVariance, unit_class, unit_flags, unit_flags2, unit_flags3, dynamicflags, family, trainer_class, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, HealthModifierExtra, ManaModifier, ManaModifierExtra, ArmorModifier, DamageModifier, ExperienceModifier, RacialLeader, movementId, WidgetSetID, WidgetSetUnitConditionID, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ? OR 1 = ?"); PrepareStatement(WorldStatements.SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?"); 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_"); diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 0b6a69f91..8becba0b0 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -420,6 +420,7 @@ namespace Game.Entities UpdateMovementFlags(); LoadCreaturesAddon(); LoadMechanicTemplateImmunity(); + LoadSpellTemplateImmunity(); return true; } @@ -1892,6 +1893,27 @@ namespace Game.Entities } } + void LoadSpellTemplateImmunity() + { + // uint32 max used for "spell id", the immunity system will not perform SpellInfo checks against invalid spells + // used so we know which immunities were loaded from template + uint placeholderSpellId = uint.MaxValue; + + // unapply template immunities (in case we're updating entry) + for (var i = SpellSchoolMask.Normal; i <= SpellSchoolMask.Arcane; ++i) + ApplySpellImmune(placeholderSpellId, SpellImmunity.School, i, false); + + // don't inherit immunities for hunter pets + if (GetOwnerGUID().IsPlayer() && IsHunterPet()) + return; + + byte mask = GetCreatureTemplate().SpellSchoolImmuneMask; + if (mask != 0) + for (var i = (int)SpellSchoolMask.Normal; i <= (int)SpellSchoolMask.Arcane; ++i) + if ((mask & (1 << i)) != 0) + ApplySpellImmune(placeholderSpellId, SpellImmunity.School, 1u << i, true); + } + public override bool IsImmunedToSpell(SpellInfo spellInfo, Unit caster) { if (spellInfo == null) diff --git a/Source/Game/Entities/Creature/CreatureData.cs b/Source/Game/Entities/Creature/CreatureData.cs index 7cf74045b..e85cf11e0 100644 --- a/Source/Game/Entities/Creature/CreatureData.cs +++ b/Source/Game/Entities/Creature/CreatureData.cs @@ -89,6 +89,7 @@ namespace Game.Entities public int WidgetSetUnitConditionID; public bool RegenHealth; public uint MechanicImmuneMask; + public byte SpellSchoolImmuneMask; public CreatureFlagsExtra FlagsExtra; public uint ScriptID; diff --git a/Source/Game/Globals/ObjectManager.cs b/Source/Game/Globals/ObjectManager.cs index 0a2b17237..45f34897e 100644 --- a/Source/Game/Globals/ObjectManager.cs +++ b/Source/Game/Globals/ObjectManager.cs @@ -1870,8 +1870,9 @@ namespace Game creature.WidgetSetUnitConditionID = fields.Read(72); creature.RegenHealth = fields.Read(73); creature.MechanicImmuneMask = fields.Read(74); - creature.FlagsExtra = (CreatureFlagsExtra)fields.Read(75); - creature.ScriptID = GetScriptId(fields.Read(76)); + creature.SpellSchoolImmuneMask = fields.Read(75); + creature.FlagsExtra = (CreatureFlagsExtra)fields.Read(76); + creature.ScriptID = GetScriptId(fields.Read(77)); _creatureTemplateStorage[entry] = creature; } diff --git a/sql/updates/world/master/2021_03_14_02_world_2017_12_16_03_world.sql b/sql/updates/world/master/2021_03_14_02_world_2017_12_16_03_world.sql new file mode 100644 index 000000000..0037fd354 --- /dev/null +++ b/sql/updates/world/master/2021_03_14_02_world_2017_12_16_03_world.sql @@ -0,0 +1,2 @@ +-- +ALTER TABLE `creature_template` ADD COLUMN `spell_school_immune_mask` int(3) unsigned NOT NULL DEFAULT '0' AFTER `mechanic_immune_mask`;