From 6e1fb0d52511510c973c3bf4d4e8bdad3a2826ce Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Wed, 3 Feb 2021 03:44:09 +0100 Subject: [PATCH] feat(Core/Creature): implement c_t->spell_school_immune_mask (#4358) * feat(Core/Creature): implement spell_school_immune_mask * https://github.com/TrinityCore/TrinityCore/commit/ae878e18ef121b7b1960f40f2b0f99debd2155d8 Co-Authored-By: Wyreth <32145860+Wyreth@users.noreply.github.com> * Import from TC * just capitalize sql keywords * Update rev_1611769264588956600.sql Co-authored-by: Wyreth <32145860+Wyreth@users.noreply.github.com> --- .../rev_1611769264588956600.sql | 37 ++++++++++++++ .../Database/Implementation/WorldDatabase.cpp | 2 +- .../game/Entities/Creature/Creature.cpp | 32 ++++++++++++ src/server/game/Entities/Creature/Creature.h | 2 + src/server/game/Globals/ObjectMgr.cpp | 51 ++++++++++--------- 5 files changed, 98 insertions(+), 26 deletions(-) create mode 100644 data/sql/updates/pending_db_world/rev_1611769264588956600.sql diff --git a/data/sql/updates/pending_db_world/rev_1611769264588956600.sql b/data/sql/updates/pending_db_world/rev_1611769264588956600.sql new file mode 100644 index 000000000..bb7a636e0 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1611769264588956600.sql @@ -0,0 +1,37 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1611769264588956600'); + +ALTER TABLE `creature_template` ADD COLUMN `spell_school_immune_mask` INT(3) UNSIGNED NOT NULL DEFAULT 0 AFTER `mechanic_immune_mask`; + +-- Imported from TrinityCore +-- SPELL_SCHOOL_NORMAL +UPDATE `creature_template` SET `spell_school_immune_mask` = 1 WHERE `entry` = 11284; + +-- SPELL_SCHOOL_FIRE +UPDATE `creature_template` SET `spell_school_immune_mask` = 4 WHERE `entry` IN (89,575,2091,2108,2447,2726,2745,2760,3417,4036,4037,4038,4676,5850,5852,5893,5896,6073,6520,6073,6520,6521,7135,7136,7137,7266,7738,7846,8281,8608,8616,8680,8909,8910,8911,9016,9017,9026,9178,9376,9816,9878,9879,11502,11583,11666,11667,11668,11981,11983,12056,12143,12265,13020,14460,14461,14601,14668,15203,15209,15438,17003,19203,19973,21706,22323,20703,25001,25417,30847); + +-- SPELL_SCHOOL_NATURE +UPDATE `creature_template` SET `spell_school_immune_mask` = 8 WHERE `entry` IN (92,832,2258,2592,2735,2736,2752,2762,2791,4034,4035,4499,4526,5855,5898,5902,6239,8667,9377,9397,11321,11576,11577,11578,11744,11745,11777,11778,11783,11784,12201,12237,14399,14400,14435,14454,14455,14478,14887,14888,14889,14890,15352,16043,17085,17154,17156,17157,17158,17159,17160,18062,18181,21707,23029,11779,22036,26407,28411,28585,28825); + +-- SPELL_SCHOOL_FROST +UPDATE `creature_template` SET `spell_school_immune_mask` = 16 WHERE `entry` IN (510,691,2761,2776,2794,3851,3861,3917,3950,4978,5461,5462,5894,5895,5897,6047,6220,6748,7079,7132,7428,7429,8519,8520,8521,8522,8837,9453,10198,10642,10756,10757,10955,11256,11862,12759,12876,13278,13279,13280,13282,13322,13456,13696,13736,14269,14350,14457,14458,15211,15305,17153,17155,17167,17358,19204,21428,21728,22009,22309,17207,26342,26341,26340,26339,26338,20704,22035,16570,25740,25755,25756,25757,25865,26116,26178,26204,26214,26215,26216,24228,24601,25226,25514,25715,26316,30846); + +-- SPELL_SCHOOL_SHADOW +UPDATE `creature_template` SET `spell_school_immune_mask` = 32 WHERE `entry` IN (703,1043,1364,19206,20705); + +-- SPELL_SCHOOL_ARCANE +UPDATE `creature_template` SET `spell_school_immune_mask` = 64 WHERE `entry` IN (6109,6492,6550,10202,10662,10663,10664,11480,11483,11484,14397,15527,16488,16530,16854,18864,18865,18866,18867,19205,20516,22310,20702,26370,30848); + +-- SPELL_SCHOOL_ARCANE & SPELL_SCHOOL_SHADOW +UPDATE `creature_template` SET `spell_school_immune_mask` = 96 WHERE `entry` = 21032; + +-- SPELL_SCHOOL_ARCANE & SPELL_SCHOOL_SHADOW & SPELL_SCHOOL_FROST & SPELL_SCHOOL_FIRE +UPDATE `creature_template` SET `spell_school_immune_mask` = 116 WHERE `entry` IN (7734,7735); + +-- SPELL_SCHOOL_ARCANE & SPELL_SCHOOL_SHADOW & SPELL_SCHOOL_FROST & SPELL_SCHOOL_FIRE & SPELL_SCHOOL_NATURE +UPDATE `creature_template` SET `spell_school_immune_mask` = 124 WHERE `entry` = 10485; + +-- SPELL_SCHOOL_ARCANE & SPELL_SCHOOL_SHADOW & SPELL_SCHOOL_FROST & SPELL_SCHOOL_FIRE & SPELL_SCHOOL_NATURE & SPELL_SCHOOL_HOLY +UPDATE `creature_template` SET `spell_school_immune_mask` = 126 WHERE `entry` IN (12457,16491); + +-- SPELL_SCHOOL_ARCANE & SPELL_SCHOOL_SHADOW & SPELL_SCHOOL_FROST & SPELL_SCHOOL_FIRE & SPELL_SCHOOL_NATURE & SPELL_SCHOOL_HOLY & SPELL_SCHOOL_NORMAL +UPDATE `creature_template` SET `spell_school_immune_mask` = 127 WHERE `entry` = 8317; diff --git a/src/common/Database/Implementation/WorldDatabase.cpp b/src/common/Database/Implementation/WorldDatabase.cpp index ccca01f37..41899e2f8 100644 --- a/src/common/Database/Implementation/WorldDatabase.cpp +++ b/src/common/Database/Implementation/WorldDatabase.cpp @@ -65,7 +65,7 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_ID_BY_GUID, "SELECT id FROM waypoint_scripts WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH); - PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, scale, `rank`, mindmg, maxdmg, dmgschool, attackpower, DamageModifier, BaseAttackTime, RangeAttackTime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, scale, `rank`, mindmg, maxdmg, dmgschool, attackpower, DamageModifier, BaseAttackTime, RangeAttackTime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_BY_ID, "SELECT guid FROM creature WHERE id = ?", CONNECTION_SYNCH); diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 53c5284aa..4a6cc4539 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -488,6 +488,7 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele UpdateEnvironmentIfNeeded(3); + LoadSpellTemplateImmunity(); return true; } @@ -1804,6 +1805,37 @@ bool Creature::HasMechanicTemplateImmunity(uint32 mask) const return !IS_PLAYER_GUID(GetOwnerGUID()) && (GetCreatureTemplate()->MechanicImmuneMask & mask); } +void Creature::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 + static uint32 const placeholderSpellId = std::numeric_limits::max(); + + // unapply template immunities (in case we're updating entry) + for (uint8 i = SPELL_SCHOOL_NORMAL; i <= SPELL_SCHOOL_ARCANE; ++i) + { + ApplySpellImmune(placeholderSpellId, IMMUNITY_SCHOOL, i, false); + } + + // don't inherit immunities for hunter pets + if (IS_PLAYER_GUID(GetOwnerGUID()) && IsHunterPet()) + { + return; + } + + if (uint8 mask = GetCreatureTemplate()->SpellSchoolImmuneMask) + { + for (uint8 i = SPELL_SCHOOL_NORMAL; i <= SPELL_SCHOOL_ARCANE; ++i) + { + if (mask & (1 << i)) + { + ApplySpellImmune(placeholderSpellId, IMMUNITY_SCHOOL, 1 << i, true); + } + } + } +} + + bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo) { if (!spellInfo) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index eca8cc633..5e9b95bf4 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -141,6 +141,7 @@ struct CreatureTemplate uint32 movementId; bool RegenHealth; uint32 MechanicImmuneMask; + uint8 SpellSchoolImmuneMask; uint32 flags_extra; uint32 ScriptID; WorldPacket queryData; // pussywizard @@ -479,6 +480,7 @@ public: bool isCanInteractWithBattleMaster(Player* player, bool msg) const; bool isCanTrainingAndResetTalentsOf(Player* player) const; bool CanCreatureAttack(Unit const* victim, bool skipDistCheck = false) const; + void LoadSpellTemplateImmunity(); bool IsImmunedToSpell(SpellInfo const* spellInfo) override; [[nodiscard]] bool HasMechanicTemplateImmunity(uint32 mask) const; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 9cdc7b110..f413eacf6 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -459,20 +459,20 @@ void ObjectMgr::LoadCreatureTemplates() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 5 6 7 8 +// 0 1 2 3 4 5 6 7 8 QueryResult result = WorldDatabase.Query("SELECT entry, difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, " - // 9 10 11 12 13 14 15 16 17 18 19 20 21 +// 9 10 11 12 13 14 15 16 17 18 19 20 "modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, faction, npcflag, speed_walk, speed_run, " - // 22 23 24 25 26 27 28 29 30 31 32 33 +// 21 22 23 24 25 26 27 28 29 30 31 32 "scale, `rank`, mindmg, maxdmg, dmgschool, attackpower, DamageModifier, BaseAttackTime, RangeAttackTime, unit_class, unit_flags, unit_flags2, " - // 34 35 36 37 38 39 40 41 42 43 +// 33 34 35 36 37 38 39 40 41 42 "dynamicflags, family, trainer_type, trainer_spell, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, " - // 44 45 46 47 48 49 50 51 52 53 54 +// 43 44 45 46 47 48 49 50 51 52 53 "type_flags, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, " - // 55 56 57 58 59 60 61 62 63 64 65 66 67 +// 54 55 56 57 58 59 60 61 62 63 64 65 66 "spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, " - // 68 69 70 71 72 73 74 75 76 77 78 - "InhabitType, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName " +// 67 68 69 70 71 72 73 74 75 76 77 78 + "InhabitType, HoverHeight, HealthModifier, ManaModifier, ArmorModifier, RacialLeader, movementId, RegenHealth, mechanic_immune_mask, spell_school_immune_mask, flags_extra, ScriptName " "FROM creature_template;"); if (!result) @@ -547,23 +547,24 @@ void ObjectMgr::LoadCreatureTemplates() for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) creatureTemplate.spells[i] = fields[53 + i].GetUInt32(); - creatureTemplate.PetSpellDataId = fields[61].GetUInt32(); - creatureTemplate.VehicleId = fields[62].GetUInt32(); - creatureTemplate.mingold = fields[63].GetUInt32(); - creatureTemplate.maxgold = fields[64].GetUInt32(); - creatureTemplate.AIName = fields[65].GetString(); - creatureTemplate.MovementType = uint32(fields[66].GetUInt8()); - creatureTemplate.InhabitType = uint32(fields[67].GetUInt8()); - creatureTemplate.HoverHeight = fields[68].GetFloat(); - creatureTemplate.ModHealth = fields[69].GetFloat(); - creatureTemplate.ModMana = fields[70].GetFloat(); - creatureTemplate.ModArmor = fields[71].GetFloat(); - creatureTemplate.RacialLeader = fields[72].GetBool(); - creatureTemplate.movementId = fields[73].GetUInt32(); - creatureTemplate.RegenHealth = fields[74].GetBool(); - creatureTemplate.MechanicImmuneMask = fields[75].GetUInt32(); - creatureTemplate.flags_extra = fields[76].GetUInt32(); - creatureTemplate.ScriptID = GetScriptId(fields[77].GetCString()); + creatureTemplate.PetSpellDataId = fields[61].GetUInt32(); + creatureTemplate.VehicleId = fields[62].GetUInt32(); + creatureTemplate.mingold = fields[63].GetUInt32(); + creatureTemplate.maxgold = fields[64].GetUInt32(); + creatureTemplate.AIName = fields[65].GetString(); + creatureTemplate.MovementType = uint32(fields[66].GetUInt8()); + creatureTemplate.InhabitType = uint32(fields[67].GetUInt8()); + creatureTemplate.HoverHeight = fields[68].GetFloat(); + creatureTemplate.ModHealth = fields[69].GetFloat(); + creatureTemplate.ModMana = fields[70].GetFloat(); + creatureTemplate.ModArmor = fields[71].GetFloat(); + creatureTemplate.RacialLeader = fields[72].GetBool(); + creatureTemplate.movementId = fields[73].GetUInt32(); + creatureTemplate.RegenHealth = fields[74].GetBool(); + creatureTemplate.MechanicImmuneMask = fields[75].GetUInt32(); + creatureTemplate.SpellSchoolImmuneMask = fields[76].GetUInt8(); + creatureTemplate.flags_extra = fields[77].GetUInt32(); + creatureTemplate.ScriptID = GetScriptId(fields[78].GetCString()); ++count; } while (result->NextRow());