diff --git a/sql/mangos.sql b/sql/mangos.sql index a06223972..9076fb05d 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -24,7 +24,7 @@ CREATE TABLE `db_version` ( `version` varchar(120) default NULL, `creature_ai_version` varchar(120) default NULL, `cache_id` int(10) default '0', - `required_9045_02_mangos_spell_chain` bit(1) default NULL + `required_9074_01_mangos_command` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -743,7 +743,7 @@ INSERT INTO `command` VALUES ('server restart cancel',3,'Syntax: .server restart cancel\r\n\r\nCancel the restart/shutdown timer if any.'), ('server set loglevel',4,'Syntax: .server set loglevel #level\r\n\r\nSet server log level (0 - errors only, 1 - basic, 2 - detail, 3 - debug).'), ('server set motd',3,'Syntax: .server set motd $MOTD\r\n\r\nSet server Message of the day.'), -('server shutdown',3,'Syntax: .server shutdown #delay [#exist_code]\r\n\r\nShut the server down after #delay seconds. Use #exist_code or 0 as program exist code.'), +('server shutdown',3,'Syntax: .server shutdown #delay [#exit_code]\r\n\r\nShut the server down after #delay seconds. Use #exit_code or 0 as program exit code.'), ('server shutdown cancel',3,'Syntax: .server shutdown cancel\r\n\r\nCancel the restart/shutdown timer if any.'), ('setskill',3,'Syntax: .setskill #skill #level [#max]\r\n\r\nSet a skill of id #skill with a current skill value of #level and a maximum value of #max (or equal current maximum if not provide) for the selected character. If no character is selected, you learn the skill.'), ('showarea',3,'Syntax: .showarea #areaid\r\n\r\nReveal the area of #areaid to the selected character. If no character is selected, reveal this area to you.'), @@ -15271,6 +15271,13 @@ INSERT INTO spell_chain VALUES (10301,10300,7294,5,0), (27150,10301,7294,6,0), (54043,27150,7294,7,0), +/*Righteous Vengeance*/ +(53380,0,53380,1,0), +(53381,53380,53380,2,0), +(53382,53381,53380,3,0), +/*The Art of War*/ +(53486,0,53486,1,0), +(53488,53486,53486,2,0), /*------------------ -- (185) Cooking ------------------*/ @@ -18209,6 +18216,7 @@ INSERT INTO `spell_proc_event` VALUES (45243, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (45244, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (45354, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), +(45355, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), (45481, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), (45482, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), (45483, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), @@ -18367,12 +18375,9 @@ INSERT INTO `spell_proc_event` VALUES (53259, 0x00000000, 9, 0x00000800, 0x00800001, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53260, 0x00000000, 9, 0x00000800, 0x00800001, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53290, 0x00000000, 9, 0x00000800, 0x00000001, 0x00000200, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), -(53380, 0x00000000, 10, 0x00800000, 0x00020000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), -(53381, 0x00000000, 10, 0x00800000, 0x00020000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), -(53382, 0x00000000, 10, 0x00800000, 0x00020000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), +(53380, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53397, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), -(53486, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), -(53488, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), +(53486, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53501, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53502, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), (53503, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0), @@ -18457,7 +18462,7 @@ INSERT INTO `spell_proc_event` VALUES (58386, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0.000000, 0.000000, 0), (58442, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 15), (58444, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 5), -(58597, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0.000000, 100.000000,0), +(58597, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0.000000, 100.000000,6), (58616, 0x00000000, 15, 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58620, 0x00000000, 15, 0x00000000, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (58626, 0x00000000, 15, 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), @@ -18535,7 +18540,10 @@ INSERT INTO `spell_proc_event` VALUES (65661, 0x00000000, 15, 0x00400011, 0x00020004, 0x00000000, 0x00000010, 0x00000001, 0.000000, 100.000000,0), (64127, 0x00000000, 6, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), (67353, 0x00000000, 7, 0x00008000, 0x00100500, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 0), -(67667, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45); +(67667, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), +(67672, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 50), +(67702, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), +(67771, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45); /*!40000 ALTER TABLE `spell_proc_event` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/9064_01_mangos_spell_proc_event.sql b/sql/updates/9064_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..387a6f1d1 --- /dev/null +++ b/sql/updates/9064_01_mangos_spell_proc_event.sql @@ -0,0 +1,8 @@ +ALTER TABLE db_version CHANGE COLUMN required_9045_02_mangos_spell_chain required_9064_01_mangos_spell_proc_event bit; + +DELETE FROM spell_proc_event WHERE entry IN (45355,67672,67702,67771); +INSERT INTO spell_proc_event VALUES +(45355, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), +(67672, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 50), +(67702, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45), +(67771, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0.000000, 0.000000, 45); diff --git a/sql/updates/9068_01_mangos_spell_proc_event.sql b/sql/updates/9068_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..5be35abb0 --- /dev/null +++ b/sql/updates/9068_01_mangos_spell_proc_event.sql @@ -0,0 +1,10 @@ +ALTER TABLE db_version CHANGE COLUMN required_9064_01_mangos_spell_proc_event required_9068_01_mangos_spell_proc_event bit; + +DELETE FROM spell_proc_event WHERE entry IN (53380,53381,53382); +INSERT INTO spell_proc_event VALUES +(53380, 0x00000000, 10, 0x00800000, 0x00028000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0); + + +DELETE FROM spell_proc_event WHERE entry IN (53486,53488); +INSERT INTO spell_proc_event VALUES +(53486, 0x00000000, 0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0.000000, 0.000000, 0); diff --git a/sql/updates/9068_02_mangos_spell_chain.sql b/sql/updates/9068_02_mangos_spell_chain.sql new file mode 100644 index 000000000..39cb7648b --- /dev/null +++ b/sql/updates/9068_02_mangos_spell_chain.sql @@ -0,0 +1,14 @@ +ALTER TABLE db_version CHANGE COLUMN required_9068_01_mangos_spell_proc_event required_9068_02_mangos_spell_chain bit; + +/*Righteous Vengeance*/ +DELETE FROM spell_chain WHERE first_spell = 53380; +INSERT INTO spell_chain VALUES +(53380, 0, 53380, 1, 0), +(53381, 53380, 53380, 2, 0), +(53382, 53381, 53380, 3, 0); + +/*The Art of War*/ +DELETE FROM spell_chain WHERE first_spell = 53486; +INSERT INTO spell_chain VALUES +(53486, 0, 53486, 1, 0), +(53488, 53486, 53486, 2, 0); diff --git a/sql/updates/9070_01_mangos_spell_proc_event.sql b/sql/updates/9070_01_mangos_spell_proc_event.sql new file mode 100644 index 000000000..a825b4642 --- /dev/null +++ b/sql/updates/9070_01_mangos_spell_proc_event.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_9068_02_mangos_spell_chain required_9070_01_mangos_spell_proc_event bit; + +DELETE FROM `spell_proc_event` WHERE `entry` IN (58597); +INSERT INTO `spell_proc_event` VALUES +(58597, 0x00000000, 10, 0x40000000, 0x00000000, 0x00000000, 0x00008000, 0x00000000, 0.000000, 100.000000,6); diff --git a/sql/updates/9074_01_mangos_command.sql b/sql/updates/9074_01_mangos_command.sql new file mode 100644 index 000000000..a3c8477bb --- /dev/null +++ b/sql/updates/9074_01_mangos_command.sql @@ -0,0 +1,6 @@ +ALTER TABLE db_version CHANGE COLUMN required_9070_01_mangos_spell_proc_event required_9074_01_mangos_command bit; + +DELETE FROM command where name IN ('server shutdown'); + +INSERT INTO `command` VALUES +('server shutdown',3,'Syntax: .server shutdown #delay [#exit_code]\r\n\r\nShut the server down after #delay seconds. Use #exit_code or 0 as program exit code.'); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index f07dec653..c6782d2ea 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -219,6 +219,11 @@ pkgdata_DATA = \ 9034_01_mangos_spell_proc_event.sql \ 9045_01_mangos_spell_proc_event.sql \ 9045_02_mangos_spell_chain.sql \ + 9064_01_mangos_spell_proc_event.sql \ + 9068_01_mangos_spell_proc_event.sql \ + 9068_02_mangos_spell_chain.sql \ + 9070_01_mangos_spell_proc_event.sql \ + 9074_01_mangos_command.sql \ README ## Additional files to include when running 'make dist' @@ -418,4 +423,9 @@ EXTRA_DIST = \ 9034_01_mangos_spell_proc_event.sql \ 9045_01_mangos_spell_proc_event.sql \ 9045_02_mangos_spell_chain.sql \ + 9064_01_mangos_spell_proc_event.sql \ + 9068_01_mangos_spell_proc_event.sql \ + 9068_02_mangos_spell_chain.sql \ + 9070_01_mangos_spell_proc_event.sql \ + 9074_01_mangos_command.sql \ README diff --git a/src/game/CreatureAI.cpp b/src/game/CreatureAI.cpp index 784ea7d35..8f48ad15d 100644 --- a/src/game/CreatureAI.cpp +++ b/src/game/CreatureAI.cpp @@ -18,6 +18,7 @@ #include "CreatureAI.h" #include "Creature.h" +#include "DBCStores.h" CreatureAI::~CreatureAI() { @@ -28,3 +29,90 @@ void CreatureAI::AttackedBy( Unit* attacker ) if(!m_creature->getVictim()) AttackStart(attacker); } + +CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, bool isTriggered) +{ + // If not triggered, we check + if (!isTriggered) + { + // State does not allow + if (m_creature->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING | UNIT_STAT_DIED)) + return CAST_FAIL_STATE; + + if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + return CAST_FAIL_STATE; + + if (pSpell->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) + return CAST_FAIL_STATE; + + // Check for power (also done by Spell::CheckCast()) + if (m_creature->GetPower((Powers)pSpell->powerType) < pSpell->manaCost) + return CAST_FAIL_POWER; + } + + if (const SpellRangeEntry *pSpellRange = sSpellRangeStore.LookupEntry(pSpell->rangeIndex)) + { + if (pTarget != m_creature) + { + // pTarget is out of range of this spell (also done by Spell::CheckCast()) + float fDistance = m_creature->GetCombatDistance(pTarget); + + if (fDistance > (m_creature->IsHostileTo(pTarget) ? pSpellRange->maxRange : pSpellRange->maxRangeFriendly)) + return CAST_FAIL_TOO_FAR; + + float fMinRange = m_creature->IsHostileTo(pTarget) ? pSpellRange->minRange : pSpellRange->minRangeFriendly; + + if (fMinRange && fDistance < fMinRange) + return CAST_FAIL_TOO_CLOSE; + } + + return CAST_OK; + } + else + return CAST_FAIL_OTHER; +} + +CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, uint64 uiOriginalCasterGUID) +{ + Unit* pCaster = m_creature; + + if (uiCastFlags & CAST_FORCE_TARGET_SELF) + pCaster = pTarget; + + // Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered + if (!pCaster->IsNonMeleeSpellCasted(false) || (uiCastFlags & (CAST_TRIGGERED | CAST_INTURRUPT_PREVIOUS))) + { + if (const SpellEntry* pSpell = sSpellStore.LookupEntry(uiSpell)) + { + // If cast flag CAST_AURA_NOT_PRESENT is active, check if target already has aura on them + if (uiCastFlags & CAST_AURA_NOT_PRESENT) + { + if (pTarget->HasAura(uiSpell)) + return CAST_FAIL_TARGET_AURA; + } + + // Check if cannot cast spell + if (!(uiCastFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST))) + { + CanCastResult castResult = CanCastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED); + + if (castResult != CAST_OK) + return castResult; + } + + // Interrupt any previous spell + if (uiCastFlags & CAST_INTURRUPT_PREVIOUS && pCaster->IsNonMeleeSpellCasted(false)) + pCaster->InterruptNonMeleeSpells(false); + + pCaster->CastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED, NULL, NULL, uiOriginalCasterGUID); + return CAST_OK; + } + else + { + sLog.outErrorDb("DoCastSpellIfCan by creature entry %u attempt to cast spell %u but spell does not exist.", m_creature->GetEntry(), uiSpell); + return CAST_FAIL_OTHER; + } + } + else + return CAST_FAIL_IS_CASTING; +} diff --git a/src/game/CreatureAI.h b/src/game/CreatureAI.h index 4038b675e..f049b5964 100644 --- a/src/game/CreatureAI.h +++ b/src/game/CreatureAI.h @@ -34,6 +34,18 @@ struct SpellEntry; #define TIME_INTERVAL_LOOK 5000 #define VISIBILITY_RANGE 10000 +enum CanCastResult +{ + CAST_OK = 0, + CAST_FAIL_IS_CASTING = 1, + CAST_FAIL_OTHER = 2, + CAST_FAIL_TOO_FAR = 3, + CAST_FAIL_TOO_CLOSE = 4, + CAST_FAIL_POWER = 5, + CAST_FAIL_STATE = 6, + CAST_FAIL_TARGET_AURA = 7 +}; + enum CastFlags { CAST_INTURRUPT_PREVIOUS = 0x01, //Interrupt any spell casting @@ -68,6 +80,10 @@ class MANGOS_DLL_SPEC CreatureAI // Called at any heal cast/item used (call non implemented) virtual void HealBy(Unit * /*healer*/, uint32 /*amount_healed*/) {} + // Helper functions for cast spell + CanCastResult DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags = 0, uint64 uiOriginalCasterGUID = 0); + virtual CanCastResult CanCastSpell(Unit* pTarget, const SpellEntry *pSpell, bool isTriggered); + // Called at any Damage to any victim (before damage apply) virtual void DamageDeal(Unit * /*done_to*/, uint32 & /*damage*/) {} diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 0e5cc17fa..f70bca36b 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1752,6 +1752,13 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const case 856: // The Noxious Glade (Eastern Plaguelands) case 2456: // Death's Breach (Eastern Plaguelands) if(z > 350.0f) areaflag = 1950; break; + // Winterfin Caverns + case 1652: // Coldarra + case 1653: // The Westrift + case 1661: // Winterfin Village + if (x > 3823.0f && x < 4141.5f && y > 6247.0f && y < 64890.0f && z < 42.5f) + areaflag = 1723; + break; // Dalaran case 2492: // Forlorn Woods (Crystalsong Forest) case 2371: // Valley of Echoes (Icecrown Glacier) diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index 5448e8f2e..cf83bb1d9 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -463,3 +463,12 @@ bool MotionMaster::GetDestination(float &x, float &y, float &z) return top()->GetDestination(x,y,z); } + +void MotionMaster::UpdateFinalDistanceToTarget(float fDistance) +{ + if (!empty()) + { + if (top()->GetMovementGeneratorType() == TARGETED_MOTION_TYPE) + top()->UpdateFinalDistance(fDistance); + } +} diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h index d304d9db5..1950bdd86 100644 --- a/src/game/MotionMaster.h +++ b/src/game/MotionMaster.h @@ -121,6 +121,9 @@ class MANGOS_DLL_SPEC MotionMaster : private std::stack void propagateSpeedChange(); + // will only work in MMgens where we have a target (TARGETED_MOTION_TYPE) + void UpdateFinalDistanceToTarget(float fDistance); + bool GetDestination(float &x, float &y, float &z); private: void Mutate(MovementGenerator *m); // use Move* functions instead diff --git a/src/game/MovementGenerator.h b/src/game/MovementGenerator.h index 2653ea636..a7d455e8f 100644 --- a/src/game/MovementGenerator.h +++ b/src/game/MovementGenerator.h @@ -44,6 +44,8 @@ class MANGOS_DLL_SPEC MovementGenerator virtual void unitSpeedChanged() { } + virtual void UpdateFinalDistance(float fDistance) { } + virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } }; diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 063a00d8c..5139ce329 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -40,7 +40,7 @@ char const* petTypeSuffix[MAX_PET_TYPE] = Pet::Pet(PetType type) : Creature(), m_removed(false), m_petType(type), m_happinessTimer(7500), m_duration(0), m_resetTalentsCost(0), m_bonusdamage(0), m_resetTalentsTime(0), m_usedTalentCount(0), m_auraUpdateMask(0), m_loading(false), -m_declinedname(NULL) +m_declinedname(NULL), m_petModeFlags(PET_MODE_DEFAULT) { m_isPet = true; m_name = "Pet"; @@ -1948,3 +1948,20 @@ void Pet::SynchronizeLevelWithOwner() break; } } + +void Pet::ApplyModeFlags(PetModeFlags mode, bool apply) +{ + if (apply) + m_petModeFlags = PetModeFlags(m_petModeFlags | mode); + else + m_petModeFlags = PetModeFlags(m_petModeFlags & ~mode); + + Unit* owner = GetOwner(); + if(!owner || owner->GetTypeId()!=TYPEID_PLAYER) + return; + + WorldPacket data(SMSG_PET_MODE, 12); + data << uint64(GetGUID()); + data << uint32(m_petModeFlags); + ((Player*)owner)->GetSession()->SendPacket(&data); +} diff --git a/src/game/Pet.h b/src/game/Pet.h index 600a1d535..4c6d3f70e 100644 --- a/src/game/Pet.h +++ b/src/game/Pet.h @@ -46,6 +46,17 @@ enum PetSaveMode PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100 }; +// There might be a lot more +enum PetModeFlags +{ + PET_MODE_UNKNOWN_0 = 0x0000001, + PET_MODE_UNKNOWN_2 = 0x0000100, + PET_MODE_DISABLE_ACTIONS = 0x8000000, + + // autoset in client at summon + PET_MODE_DEFAULT = PET_MODE_UNKNOWN_0 | PET_MODE_UNKNOWN_2, +}; + enum HappinessState { UNHAPPY = 1, @@ -182,6 +193,9 @@ class Pet : public Creature bool CanTakeMoreActiveSpells(uint32 SpellIconID); void ToggleAutocast(uint32 spellid, bool apply); + void ApplyModeFlags(PetModeFlags mode, bool apply); + PetModeFlags GetModeFlags() const { return m_petModeFlags; } + bool HasSpell(uint32 spell) const; void LearnPetPassives(); @@ -242,6 +256,8 @@ class Pet : public Creature DeclinedName *m_declinedname; private: + PetModeFlags m_petModeFlags; + void SaveToDB(uint32, uint8) // overwrited of Creature::SaveToDB - don't must be called { assert(false); diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 354ef371a..3b305dfc7 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -44,9 +44,16 @@ PetAI::PetAI(Creature *c) : CreatureAI(c), i_tracker(TIME_INTERVAL_LOOK), inComb void PetAI::MoveInLineOfSight(Unit *u) { - if( !m_creature->getVictim() && m_creature->GetCharmInfo() && - m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE) && - u->isTargetableForAttack() && m_creature->IsHostileTo( u ) && + if (m_creature->getVictim()) + return; + + if (m_creature->isPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) + return; + + if (!m_creature->GetCharmInfo() || !m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE)) + return; + + if (u->isTargetableForAttack() && m_creature->IsHostileTo( u ) && u->isInAccessablePlaceFor(m_creature)) { float attackRadius = m_creature->GetAttackDistance(u); @@ -139,7 +146,7 @@ void PetAI::UpdateAI(const uint32 diff) else m_updateAlliesTimer -= diff; - if (inCombat && !m_creature->getVictim()) + if (inCombat && (!m_creature->getVictim() || m_creature->isPet() && ((Pet*)m_creature)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS)) _stopAttack(); // i_pet.getVictim() can't be used for check in case stop fighting, i_pet.getVictim() clear at Unit death etc. diff --git a/src/game/PetHandler.cpp b/src/game/PetHandler.cpp index 8dc158f3d..a732d69d2 100644 --- a/src/game/PetHandler.cpp +++ b/src/game/PetHandler.cpp @@ -44,23 +44,33 @@ void WorldSession::HandlePetAction( WorldPacket & recv_data ) // used also for charmed creature Unit* pet= ObjectAccessor::GetUnit(*_player, guid1); sLog.outDetail("HandlePetAction.Pet %u flag is %u, spellid is %u, target %u.", uint32(GUID_LOPART(guid1)), uint32(flag), spellid, uint32(GUID_LOPART(guid2)) ); - if(!pet) + if (!pet) { sLog.outError( "Pet %u not exist.", uint32(GUID_LOPART(guid1)) ); return; } - if(pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) + if (pet != GetPlayer()->GetPet() && pet != GetPlayer()->GetCharm()) { sLog.outError("HandlePetAction.Pet %u isn't pet of player %s.", uint32(GUID_LOPART(guid1)), GetPlayer()->GetName() ); return; } - if(!pet->isAlive()) + if (!pet->isAlive()) return; - if(pet->GetTypeId() == TYPEID_PLAYER && !(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) - return; + if (pet->GetTypeId() == TYPEID_PLAYER) + { + // controller player can only do melee attack + if (!(flag == ACT_COMMAND && spellid == COMMAND_ATTACK)) + return; + } + else if (((Creature*)pet)->isPet()) + { + // pet can have action bar disabled + if(((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) + return; + } CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) @@ -316,6 +326,10 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data ) return; } + // pet can have action bar disabled + if(pet->isPet() && ((Pet*)pet)->GetModeFlags() & PET_MODE_DISABLE_ACTIONS) + return; + CharmInfo *charmInfo = pet->GetCharmInfo(); if(!charmInfo) { diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 16c6c310a..e79fde53e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17095,6 +17095,18 @@ void Player::PetSpellInitialize() GetSession()->SendPacket(&data); } +void Player::SendPetGUIDs() +{ + if(!GetPetGUID()) + return; + + // Later this function might get modified for multiple guids + WorldPacket data(SMSG_PET_GUIDS, 12); + data << uint32(1); // count + data << uint64(GetPetGUID()); + GetSession()->SendPacket(&data); +} + void Player::PossessSpellInitialize() { Unit* charm = GetCharm(); diff --git a/src/game/Player.h b/src/game/Player.h index ac398375d..4b1173595 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1565,6 +1565,7 @@ class MANGOS_DLL_SPEC Player : public Unit } void PetSpellInitialize(); + void SendPetGUIDs(); void CharmSpellInitialize(); void PossessSpellInitialize(); void RemovePetActionBar(); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 60f3e82cd..71e1d8f53 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -358,7 +358,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = { #define SPELL_ATTR_EX4_UNK5 0x00000020 // 5 #define SPELL_ATTR_EX4_NOT_STEALABLE 0x00000040 // 6 although such auras might be dispellable, they cannot be stolen #define SPELL_ATTR_EX4_UNK7 0x00000080 // 7 -#define SPELL_ATTR_EX4_UNK8 0x00000100 // 8 +#define SPELL_ATTR_EX4_STACK_DOT_MODIFIER 0x00000100 // 8 no effect on non DoTs? #define SPELL_ATTR_EX4_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST 0x00000400 // 10 Rogue Shiv have this flag #define SPELL_ATTR_EX4_UNK11 0x00000800 // 11 @@ -445,7 +445,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = { #define SPELL_ATTR_EX6_UNK26 0x04000000 // 26 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK27 0x08000000 // 27 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK28 0x10000000 // 28 not set in 3.0.3 -#define SPELL_ATTR_EX6_UNK29 0x20000000 // 29 not set in 3.0.3 +#define SPELL_ATTR_EX6_NO_DMG_PERCENT_MODS 0x20000000 // 29 do not apply damage percent mods (usually in cases where it has already been applied) #define SPELL_ATTR_EX6_UNK30 0x40000000 // 30 not set in 3.0.3 #define SPELL_ATTR_EX6_UNK31 0x80000000 // 31 not set in 3.0.3 diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index b4c2a665e..8cac57a5c 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -692,24 +692,29 @@ void Spell::prepareDataForTriggerSystem() else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000010000000000)) m_canTrigger = true; break; - case SPELLFAMILY_WARLOCK: // For Hellfire Effect / Rain of Fire / Seed of Corruption triggers need do it + case SPELLFAMILY_WARLOCK: + // For Hellfire Effect / Rain of Fire / Seed of Corruption triggers need do it if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000060)) m_canTrigger = true; break; - case SPELLFAMILY_PRIEST: // For Penance,Mind Sear,Mind Flay heal/damage triggers need do it + case SPELLFAMILY_PRIEST: + // For Penance,Mind Sear,Mind Flay heal/damage triggers need do it if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001800000800000) || (m_spellInfo->SpellFamilyFlags2 & 0x00000040)) m_canTrigger = true; break; - case SPELLFAMILY_ROGUE: // For poisons need do it + case SPELLFAMILY_ROGUE: + // For poisons need do it if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x000000101001E000)) m_canTrigger = true; break; - case SPELLFAMILY_HUNTER: // Hunter Rapid Killing/Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect/Explosive Shot + case SPELLFAMILY_HUNTER: + // Hunter Rapid Killing/Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect/Explosive Shot if ((m_spellInfo->SpellFamilyFlags & UI64LIT(0x0100200000000214)) || m_spellInfo->SpellFamilyFlags2 & 0x200) m_canTrigger = true; break; - case SPELLFAMILY_PALADIN: // For Judgements (all) / Holy Shock triggers need do it + case SPELLFAMILY_PALADIN: + // For Judgements (all) / Holy Shock triggers need do it if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0001000900B80400)) m_canTrigger = true; break; @@ -1279,7 +1284,7 @@ struct TargetDistanceOrder : public std::binary_functionEffectRadiusIndex[effIndex]) @@ -1304,11 +1309,35 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) // custom target amount cases switch(m_spellInfo->SpellFamilyName) { + case SPELLFAMILY_GENERIC: + { + switch(m_spellInfo->Id) + { + case 33711: // Murmur's Touch + case 38794: // Murmur's Touch (h) + unMaxTargets = 1; + break; + case 28796: // Poison Bolt Volley + case 29213: // Curse of the Plaguebringer + case 31298: // Sleep + unMaxTargets = 3; + break; + case 30843: // Enfeeble + unMaxTargets = 5; + break; + case 54098: // Poison Bolt Volley (h) + case 54835: // Curse of the Plaguebringer (h) + unMaxTargets = 10; + break; + } + break; + } case SPELLFAMILY_DRUID: - // Starfall - if (m_spellInfo->SpellFamilyFlags2 & 0x00000100) + { + if (m_spellInfo->SpellFamilyFlags2 & 0x00000100)// Starfall unMaxTargets = 2; break; + } default: break; } @@ -1333,7 +1362,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) m_caster->GetClosePoint(dest_x, dest_y, dest_z, 0.0f, radius, angle); m_targets.setDestination(dest_x, dest_y, dest_z); - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; } case TARGET_RANDOM_NEARBY_DEST: @@ -1349,10 +1378,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) if (radius > 0.0f) { // caster included here? - FillAreaTargets(TagUnitMap, dest_x, dest_y, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(targetUnitMap, dest_x, dest_y, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); } else - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; } @@ -1365,7 +1394,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) case TARGET_AREAEFFECT_CUSTOM: case TARGET_AREAEFFECT_CUSTOM_2: case TARGET_SUMMON: - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA: { @@ -1378,11 +1407,11 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - std::list tempUnitMap; + std::list tempTargetUnitMap; { MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range); - MaNGOS::UnitListSearcher searcher(m_caster, tempUnitMap, u_check); + MaNGOS::UnitListSearcher searcher(m_caster, tempTargetUnitMap, u_check); TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); @@ -1392,34 +1421,34 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *m_caster, max_range); } - if(tempUnitMap.empty()) + if(tempTargetUnitMap.empty()) break; - tempUnitMap.sort(TargetDistanceOrder(m_caster)); + tempTargetUnitMap.sort(TargetDistanceOrder(m_caster)); //Now to get us a random target that's in the initial range of the spell uint32 t = 0; - std::list::iterator itr = tempUnitMap.begin(); - while(itr!= tempUnitMap.end() && (*itr)->IsWithinDist(m_caster,radius)) + std::list::iterator itr = tempTargetUnitMap.begin(); + while(itr!= tempTargetUnitMap.end() && (*itr)->IsWithinDist(m_caster, radius)) ++t, ++itr; if(!t) break; - itr = tempUnitMap.begin(); + itr = tempTargetUnitMap.begin(); std::advance(itr, rand()%t); Unit *pUnitTarget = *itr; - TagUnitMap.push_back(pUnitTarget); + targetUnitMap.push_back(pUnitTarget); - tempUnitMap.erase(itr); + tempTargetUnitMap.erase(itr); - tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); + tempTargetUnitMap.sort(TargetDistanceOrder(pUnitTarget)); t = unMaxTargets - 1; Unit *prev = pUnitTarget; - std::list::iterator next = tempUnitMap.begin(); + std::list::iterator next = tempTargetUnitMap.begin(); - while(t && next != tempUnitMap.end() ) + while(t && next != tempTargetUnitMap.end() ) { if(!prev->IsWithinDist(*next,CHAIN_SPELL_JUMP_RADIUS)) break; @@ -1431,10 +1460,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) } prev = *next; - TagUnitMap.push_back(prev); - tempUnitMap.erase(next); - tempUnitMap.sort(TargetDistanceOrder(prev)); - next = tempUnitMap.begin(); + targetUnitMap.push_back(prev); + tempTargetUnitMap.erase(next); + tempTargetUnitMap.sort(TargetDistanceOrder(prev)); + next = tempTargetUnitMap.begin(); --t; } @@ -1449,10 +1478,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - std::list tempUnitMap; + std::list tempTargetUnitMap; { MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range); - MaNGOS::UnitListSearcher searcher(m_caster, tempUnitMap, u_check); + MaNGOS::UnitListSearcher searcher(m_caster, tempTargetUnitMap, u_check); TypeContainerVisitor, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor, GridTypeMapContainer > grid_unit_searcher(searcher); @@ -1462,34 +1491,34 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *m_caster, max_range); } - if(tempUnitMap.empty()) + if(tempTargetUnitMap.empty()) break; - tempUnitMap.sort(TargetDistanceOrder(m_caster)); + tempTargetUnitMap.sort(TargetDistanceOrder(m_caster)); //Now to get us a random target that's in the initial range of the spell uint32 t = 0; - std::list::iterator itr = tempUnitMap.begin(); - while(itr!= tempUnitMap.end() && (*itr)->IsWithinDist(m_caster,radius)) + std::list::iterator itr = tempTargetUnitMap.begin(); + while(itr!= tempTargetUnitMap.end() && (*itr)->IsWithinDist(m_caster, radius)) ++t, ++itr; if(!t) break; - itr = tempUnitMap.begin(); + itr = tempTargetUnitMap.begin(); std::advance(itr, rand()%t); Unit *pUnitTarget = *itr; - TagUnitMap.push_back(pUnitTarget); + targetUnitMap.push_back(pUnitTarget); - tempUnitMap.erase(itr); + tempTargetUnitMap.erase(itr); - tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); + tempTargetUnitMap.sort(TargetDistanceOrder(pUnitTarget)); t = unMaxTargets - 1; Unit *prev = pUnitTarget; - std::list::iterator next = tempUnitMap.begin(); + std::list::iterator next = tempTargetUnitMap.begin(); - while(t && next != tempUnitMap.end() ) + while(t && next != tempTargetUnitMap.end()) { if(!prev->IsWithinDist(*next,CHAIN_SPELL_JUMP_RADIUS)) break; @@ -1500,10 +1529,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) continue; } prev = *next; - TagUnitMap.push_back(prev); - tempUnitMap.erase(next); - tempUnitMap.sort(TargetDistanceOrder(prev)); - next = tempUnitMap.begin(); + targetUnitMap.push_back(prev); + tempTargetUnitMap.erase(next); + tempTargetUnitMap.sort(TargetDistanceOrder(prev)); + next = tempTargetUnitMap.begin(); --t; } break; @@ -1512,7 +1541,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) { Pet* tmpUnit = m_caster->GetPet(); if (!tmpUnit) break; - TagUnitMap.push_back(tmpUnit); + targetUnitMap.push_back(tmpUnit); break; } case TARGET_CHAIN_DAMAGE: @@ -1522,7 +1551,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), m_spellInfo)) { m_targets.setUnitTarget(pUnitTarget); - TagUnitMap.push_back(pUnitTarget); + targetUnitMap.push_back(pUnitTarget); } } else @@ -1546,10 +1575,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - std::list tempUnitMap; + std::list tempTargetUnitMap; { MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, originalCaster, max_range, false); - MaNGOS::UnitListSearcher searcher(m_caster, tempUnitMap, u_check); + MaNGOS::UnitListSearcher searcher(m_caster, tempTargetUnitMap, u_check); TypeContainerVisitor, WorldTypeMapContainer> world_unit_searcher(searcher); TypeContainerVisitor, GridTypeMapContainer> grid_unit_searcher(searcher); CellLock cell_lock(cell, p); @@ -1557,20 +1586,20 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) cell_lock->Visit(cell_lock, world_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range); cell_lock->Visit(cell_lock, grid_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range); } - if (tempUnitMap.empty()) + if (tempTargetUnitMap.empty()) break; - tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); + tempTargetUnitMap.sort(TargetDistanceOrder(pUnitTarget)); - if (*tempUnitMap.begin() == pUnitTarget) - tempUnitMap.erase (tempUnitMap.begin()); + if (*tempTargetUnitMap.begin() == pUnitTarget) + tempTargetUnitMap.erase(tempTargetUnitMap.begin()); - TagUnitMap.push_back(pUnitTarget); + targetUnitMap.push_back(pUnitTarget); uint32 t = unMaxTargets - 1; Unit *prev = pUnitTarget; - std::list::iterator next = tempUnitMap.begin(); + std::list::iterator next = tempTargetUnitMap.begin(); - while (t && next != tempUnitMap.end()) + while (t && next != tempTargetUnitMap.end()) { if (!prev->IsWithinDist (*next,CHAIN_SPELL_JUMP_RADIUS)) break; @@ -1580,17 +1609,17 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) continue; } prev = *next; - TagUnitMap.push_back(prev); - tempUnitMap.erase(next); - tempUnitMap.sort (TargetDistanceOrder(prev)); - next = tempUnitMap.begin(); + targetUnitMap.push_back(prev); + tempTargetUnitMap.erase(next); + tempTargetUnitMap.sort(TargetDistanceOrder(prev)); + next = tempTargetUnitMap.begin(); --t; } } break; } case TARGET_ALL_ENEMY_IN_AREA: - FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(targetUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); break; case TARGET_AREAEFFECT_INSTANT: { @@ -1599,10 +1628,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) if (IsPositiveEffect(m_spellInfo->Id, effIndex)) targetB = SPELL_TARGETS_FRIENDLY; - FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius, PUSH_DEST_CENTER, targetB); + FillAreaTargets(targetUnitMap, m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_DEST_CENTER, targetB); // exclude caster - TagUnitMap.remove(m_caster); + targetUnitMap.remove(m_caster); break; } case TARGET_ALL_ENEMY_IN_AREA_INSTANT: @@ -1613,13 +1642,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) case SPELL_EFFECT_PERSISTENT_AREA_AURA: break; case SPELL_EFFECT_SUMMON: - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; default: - FillAreaTargets(TagUnitMap,m_targets.m_destX, m_targets.m_destY,radius,PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE); - - // exclude caster (this can be important if this not original caster) - TagUnitMap.remove(m_caster); + FillAreaTargets(targetUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); break; } break; @@ -1629,34 +1655,34 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) if(Unit* currentTarget = m_targets.getUnitTarget()) { m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ()); - TagUnitMap.push_back(currentTarget); + targetUnitMap.push_back(currentTarget); } break; } case TARGET_ALL_PARTY_AROUND_CASTER: case TARGET_ALL_PARTY_AROUND_CASTER_2: case TARGET_ALL_PARTY: - FillRaidOrPartyTargets(TagUnitMap, m_caster, m_caster, radius, false, true, true); + FillRaidOrPartyTargets(targetUnitMap, m_caster, m_caster, radius, false, true, true); break; case TARGET_ALL_RAID_AROUND_CASTER: { if(m_spellInfo->Id == 57669) // Replenishment (special target selection) - FillRaidOrPartyManaPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 10, true, false, true); + FillRaidOrPartyManaPriorityTargets(targetUnitMap, m_caster, m_caster, radius, 10, true, false, true); else if (m_spellInfo->Id==52759) // Ancestral Awakening (special target selection) - FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 1, true, false, true); + FillRaidOrPartyHealthPriorityTargets(targetUnitMap, m_caster, m_caster, radius, 1, true, false, true); else - FillRaidOrPartyTargets(TagUnitMap, m_caster, m_caster, radius, true, true, true); + FillRaidOrPartyTargets(targetUnitMap, m_caster, m_caster, radius, true, true, true); break; } case TARGET_SINGLE_FRIEND: case TARGET_SINGLE_FRIEND_2: if(m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); break; case TARGET_NONCOMBAT_PET: if(Unit* target = m_targets.getUnitTarget()) if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET) - TagUnitMap.push_back(target); + targetUnitMap.push_back(target); break; case TARGET_CASTER_COORDINATES: { @@ -1671,21 +1697,21 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) break; } case TARGET_ALL_HOSTILE_UNITS_AROUND_CASTER: - FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_SELF_CENTER, SPELL_TARGETS_HOSTILE); + FillAreaTargets(targetUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_SELF_CENTER, SPELL_TARGETS_HOSTILE); break; case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER: switch (m_spellInfo->Id) { case 64844: // Divine Hymn // target amount stored in parent spell dummy effect but hard to access - FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 3, true, false, false); + FillRaidOrPartyHealthPriorityTargets(targetUnitMap, m_caster, m_caster, radius, 3, true, false, false); break; case 64904: // Hymn of Hope // target amount stored in parent spell dummy effect but hard to access - FillRaidOrPartyManaPriorityTargets(TagUnitMap, m_caster, m_caster, radius, 3, true, false, false); + FillRaidOrPartyManaPriorityTargets(targetUnitMap, m_caster, m_caster, radius, 3, true, false, false); break; default: - FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); + FillAreaTargets(targetUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); break; } break; @@ -1696,7 +1722,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) // checked in Spell::CheckCast if (m_caster->GetTypeId()==TYPEID_PLAYER) if (Unit* target = m_caster->GetMap()->GetPet(((Player*)m_caster)->GetSelection())) - TagUnitMap.push_back(target); + targetUnitMap.push_back(target); } // Wild Growth else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellIconID == 2864) @@ -1706,10 +1732,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) target = m_caster; uint32 count = CalculateDamage(2,m_caster); // stored in dummy effect, affected by mods - FillRaidOrPartyHealthPriorityTargets(TagUnitMap, m_caster, target, radius, count, true, false, true); + FillRaidOrPartyHealthPriorityTargets(targetUnitMap, m_caster, target, radius, count, true, false, true); } else - FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_FRIENDLY); + FillAreaTargets(targetUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_FRIENDLY); break; // TARGET_SINGLE_PARTY means that the spells can only be casted on a party member and not on the caster (some seals, fire shield from imp, etc..) case TARGET_SINGLE_PARTY: @@ -1729,7 +1755,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) { if( target == owner ) { - TagUnitMap.push_back(target); + targetUnitMap.push_back(target); break; } pGroup = ((Player*)owner)->GetGroup(); @@ -1739,7 +1765,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) { if( targetOwner == m_caster && target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet()) { - TagUnitMap.push_back(target); + targetUnitMap.push_back(target); break; } pGroup = ((Player*)m_caster)->GetGroup(); @@ -1755,13 +1781,13 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) target->GetOwnerGUID() == targetOwner->GetGUID() && pGroup->IsMember(((Player*)targetOwner)->GetGUID())) { - TagUnitMap.push_back(target); + targetUnitMap.push_back(target); } } // 1Our target can be a player who is on our group else if (target->GetTypeId() == TYPEID_PLAYER && pGroup->IsMember(((Player*)target)->GetGUID())) { - TagUnitMap.push_back(target); + targetUnitMap.push_back(target); } } } @@ -1774,17 +1800,17 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) case TARGET_IN_FRONT_OF_CASTER: { bool inFront = m_spellInfo->SpellVisual[0] != 3879; - FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(),radius,inFront ? PUSH_IN_FRONT : PUSH_IN_BACK,SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(targetUnitMap, m_caster->GetPositionX(), m_caster->GetPositionY(), radius, inFront ? PUSH_IN_FRONT : PUSH_IN_BACK, SPELL_TARGETS_AOE_DAMAGE); break; } case TARGET_LARGE_FRONTAL_CONE: - FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_90, SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(targetUnitMap, m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_90, SPELL_TARGETS_AOE_DAMAGE); break; case TARGET_NARROW_FRONTAL_CONE: - FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_15, SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(targetUnitMap, m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_15, SPELL_TARGETS_AOE_DAMAGE); break; case TARGET_IN_FRONT_OF_CASTER_30: - FillAreaTargets(TagUnitMap,m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_30, SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(targetUnitMap, m_caster->GetPositionX(), m_caster->GetPositionY(), radius, PUSH_IN_FRONT_30, SPELL_TARGETS_AOE_DAMAGE); break; case TARGET_DUELVSPLAYER: { @@ -1793,14 +1819,14 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) { if(m_caster->IsFriendlyTo(target)) { - TagUnitMap.push_back(target); + targetUnitMap.push_back(target); } else { if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), m_spellInfo)) { m_targets.setUnitTarget(pUnitTarget); - TagUnitMap.push_back(pUnitTarget); + targetUnitMap.push_back(pUnitTarget); } } } @@ -1814,23 +1840,23 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) break; case TARGET_MASTER: if(Unit* owner = m_caster->GetCharmerOrOwner()) - TagUnitMap.push_back(owner); + targetUnitMap.push_back(owner); break; case TARGET_ALL_ENEMY_IN_AREA_CHANNELED: // targets the ground, not the units in the area if (m_spellInfo->Effect[effIndex]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) - FillAreaTargets(TagUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(targetUnitMap, m_targets.m_destX, m_targets.m_destY, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE); break; case TARGET_MINION: if(m_spellInfo->Effect[effIndex] != SPELL_EFFECT_DUEL) - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; case TARGET_SINGLE_ENEMY: { if(Unit* pUnitTarget = m_caster->SelectMagnetTarget(m_targets.getUnitTarget(), m_spellInfo)) { m_targets.setUnitTarget(pUnitTarget); - TagUnitMap.push_back(pUnitTarget); + targetUnitMap.push_back(pUnitTarget); } break; } @@ -1841,7 +1867,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) if(owner) { - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); if(owner->GetTypeId() == TYPEID_PLAYER) pTarget = (Player*)owner; } @@ -1877,39 +1903,39 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) if(Target && Target->GetSubGroup()==subgroup && !m_caster->IsHostileTo(Target)) { if( pTarget->IsWithinDistInMap(Target, radius) ) - TagUnitMap.push_back(Target); + targetUnitMap.push_back(Target); if(Pet* pet = Target->GetPet()) if( pTarget->IsWithinDistInMap(pet, radius) ) - TagUnitMap.push_back(pet); + targetUnitMap.push_back(pet); } } } else if (owner) { if(m_caster->IsWithinDistInMap(owner, radius)) - TagUnitMap.push_back(owner); + targetUnitMap.push_back(owner); } else if(pTarget) { - TagUnitMap.push_back(pTarget); + targetUnitMap.push_back(pTarget); if(Pet* pet = pTarget->GetPet()) if( m_caster->IsWithinDistInMap(pet, radius) ) - TagUnitMap.push_back(pet); + targetUnitMap.push_back(pet); } break; } case TARGET_SCRIPT: { if(m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); if(m_targets.getItemTarget()) AddItemTarget(m_targets.getItemTarget(), effIndex); break; } case TARGET_SELF_FISHING: - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; case TARGET_CHAIN_HEAL: { @@ -1918,33 +1944,33 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) break; if (EffectChainTarget <= 1) - TagUnitMap.push_back(pUnitTarget); + targetUnitMap.push_back(pUnitTarget); else { unMaxTargets = EffectChainTarget; float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS; - UnitList tempUnitMap; + UnitList tempTargetUnitMap; - FillAreaTargets(tempUnitMap, m_caster->GetPositionX(), m_caster->GetPositionY(), max_range, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); + FillAreaTargets(tempTargetUnitMap, m_caster->GetPositionX(), m_caster->GetPositionY(), max_range, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY); - if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(), m_caster) == tempUnitMap.end() ) - tempUnitMap.push_front(m_caster); + if (m_caster != pUnitTarget && std::find(tempTargetUnitMap.begin(), tempTargetUnitMap.end(), m_caster) == tempTargetUnitMap.end()) + tempTargetUnitMap.push_front(m_caster); - tempUnitMap.sort(TargetDistanceOrder(pUnitTarget)); + tempTargetUnitMap.sort(TargetDistanceOrder(pUnitTarget)); - if(tempUnitMap.empty()) + if (tempTargetUnitMap.empty()) break; - if(*tempUnitMap.begin() == pUnitTarget) - tempUnitMap.erase(tempUnitMap.begin()); + if (*tempTargetUnitMap.begin() == pUnitTarget) + tempTargetUnitMap.erase(tempTargetUnitMap.begin()); - TagUnitMap.push_back(pUnitTarget); + targetUnitMap.push_back(pUnitTarget); uint32 t = unMaxTargets - 1; Unit *prev = pUnitTarget; - std::list::iterator next = tempUnitMap.begin(); + std::list::iterator next = tempTargetUnitMap.begin(); - while(t && next != tempUnitMap.end() ) + while(t && next != tempTargetUnitMap.end()) { if(!prev->IsWithinDist(*next, CHAIN_SPELL_JUMP_RADIUS)) break; @@ -1957,15 +1983,15 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) if((*next)->GetHealth() == (*next)->GetMaxHealth()) { - next = tempUnitMap.erase(next); + next = tempTargetUnitMap.erase(next); continue; } prev = *next; - TagUnitMap.push_back(prev); - tempUnitMap.erase(next); - tempUnitMap.sort(TargetDistanceOrder(prev)); - next = tempUnitMap.begin(); + targetUnitMap.push_back(prev); + tempTargetUnitMap.erase(next); + tempTargetUnitMap.sort(TargetDistanceOrder(prev)); + next = tempTargetUnitMap.begin(); --t; } @@ -1977,10 +2003,10 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) Unit* currentTarget = m_targets.getUnitTarget(); if(currentTarget) { - TagUnitMap.push_back(currentTarget); + targetUnitMap.push_back(currentTarget); m_targets.setDestination(currentTarget->GetPositionX(), currentTarget->GetPositionY(), currentTarget->GetPositionZ()); if(m_spellInfo->EffectImplicitTargetB[effIndex]==TARGET_ALL_ENEMY_IN_AREA_INSTANT) - FillAreaTargets(TagUnitMap, currentTarget->GetPositionX(), currentTarget->GetPositionY(), radius, PUSH_TARGET_CENTER, SPELL_TARGETS_AOE_DAMAGE); + FillAreaTargets(targetUnitMap, currentTarget->GetPositionX(), currentTarget->GetPositionY(), radius, PUSH_TARGET_CENTER, SPELL_TARGETS_AOE_DAMAGE); } break; } @@ -2001,12 +2027,12 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) targetPlayer->getClass() == Target->getClass() && !m_caster->IsHostileTo(Target) ) { - TagUnitMap.push_back(Target); + targetUnitMap.push_back(Target); } } } else if(m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); break; } case TARGET_TABLE_X_Y_Z_COORDINATES: @@ -2059,7 +2085,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) pTarget->GetClosePoint(_target_x, _target_y, _target_z, pTarget->GetObjectSize(), dist, angle); if(pTarget->IsWithinLOS(_target_x, _target_y, _target_z)) { - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); m_targets.setDestination(_target_x, _target_y, _target_z); } } @@ -2089,7 +2115,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) m_targets.setDestination(x,y,m_caster->GetPositionZ()); } - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; case TARGET_POINT_AT_NORTH: @@ -2139,7 +2165,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) m_targets.setDestination(_target_x, _target_y, _target_z); } - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; } case TARGET_EFFECT_SELECT: @@ -2162,12 +2188,12 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) { case TYPEID_UNIT: case TYPEID_PLAYER: - TagUnitMap.push_back((Unit*)result); + targetUnitMap.push_back((Unit*)result); break; case TYPEID_CORPSE: m_targets.setCorpseTarget((Corpse*)result); if (Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID())) - TagUnitMap.push_back(owner); + targetUnitMap.push_back(owner); break; } } @@ -2183,7 +2209,7 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) } default: if (m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); break; } break; @@ -2202,22 +2228,22 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) case SPELL_EFFECT_REPUTATION: case SPELL_EFFECT_SEND_TAXI: if (m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); // Triggered spells have additional spell targets - cast them even if no explicit unit target is given (required for spell 50516 for example) else if (m_spellInfo->Effect[effIndex] == SPELL_EFFECT_TRIGGER_SPELL) - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; case SPELL_EFFECT_SUMMON_PLAYER: if (m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetSelection()) { Player* target = sObjectMgr.GetPlayer(((Player*)m_caster)->GetSelection()); if(target) - TagUnitMap.push_back(target); + targetUnitMap.push_back(target); } break; case SPELL_EFFECT_RESURRECT_NEW: if (m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); if (m_targets.getCorpseTargetGUID()) { Corpse *corpse = m_caster->GetMap()->GetCorpse(m_targets.getCorpseTargetGUID()); @@ -2225,12 +2251,12 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) { Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID()); if(owner) - TagUnitMap.push_back(owner); + targetUnitMap.push_back(owner); } } break; case SPELL_EFFECT_SUMMON: - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; case SPELL_EFFECT_SUMMON_CHANGE_ITEM: case SPELL_EFFECT_TRANS_DOOR: @@ -2240,11 +2266,11 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) case SPELL_EFFECT_FEED_PET: case SPELL_EFFECT_DESTROY_ALL_TOTEMS: case SPELL_EFFECT_SKILL: - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; case SPELL_EFFECT_LEARN_PET_SPELL: if (Pet* pet = m_caster->GetPet()) - TagUnitMap.push_back(pet); + targetUnitMap.push_back(pet); break; case SPELL_EFFECT_ENCHANT_ITEM: case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY: @@ -2260,27 +2286,27 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) { case SPELL_AURA_ADD_FLAT_MODIFIER: // some spell mods auras have 0 target modes instead expected TARGET_SELF(1) (and present for other ranks for same spell for example) case SPELL_AURA_ADD_PCT_MODIFIER: - TagUnitMap.push_back(m_caster); + targetUnitMap.push_back(m_caster); break; default: // apply to target in other case if (m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); break; } break; case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: // AreaAura if(m_spellInfo->Attributes == 0x9050000 || m_spellInfo->Attributes == 0x10000) - SetTargetMap(effIndex,TARGET_AREAEFFECT_PARTY, TagUnitMap); + SetTargetMap(effIndex, TARGET_AREAEFFECT_PARTY, targetUnitMap); break; case SPELL_EFFECT_SKIN_PLAYER_CORPSE: if (m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); else if (m_targets.getCorpseTargetGUID()) { if (Corpse *corpse = m_caster->GetMap()->GetCorpse(m_targets.getCorpseTargetGUID())) if (Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID())) - TagUnitMap.push_back(owner); + targetUnitMap.push_back(owner); } break; @@ -2294,40 +2320,40 @@ void Spell::SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap) break; } - if (unMaxTargets && TagUnitMap.size() > unMaxTargets) + if (unMaxTargets && targetUnitMap.size() > unMaxTargets) { // make sure one unit is always removed per iteration uint32 removed_utarget = 0; - for (UnitList::iterator itr = TagUnitMap.begin(), next; itr != TagUnitMap.end(); itr = next) + for (UnitList::iterator itr = targetUnitMap.begin(), next; itr != targetUnitMap.end(); itr = next) { next = itr; ++next; if (!*itr) continue; if ((*itr) == m_targets.getUnitTarget()) { - TagUnitMap.erase(itr); + targetUnitMap.erase(itr); removed_utarget = 1; // break; } } // remove random units from the map - while (TagUnitMap.size() > unMaxTargets - removed_utarget) + while (targetUnitMap.size() > unMaxTargets - removed_utarget) { - uint32 poz = urand(0, TagUnitMap.size()-1); - for (UnitList::iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end(); ++itr, --poz) + uint32 poz = urand(0, targetUnitMap.size()-1); + for (UnitList::iterator itr = targetUnitMap.begin(); itr != targetUnitMap.end(); ++itr, --poz) { if (!*itr) continue; if (!poz) { - TagUnitMap.erase(itr); + targetUnitMap.erase(itr); break; } } } // the player's target will always be added to the map if (removed_utarget && m_targets.getUnitTarget()) - TagUnitMap.push_back(m_targets.getUnitTarget()); + targetUnitMap.push_back(m_targets.getUnitTarget()); } } @@ -4167,12 +4193,12 @@ SpellCastResult Spell::CheckCast(bool strict) return castResult; } - //ImpliciteTargetA-B = 38, If fact there is 0 Spell with ImpliciteTargetB=38 + // Database based targets from spell_target_script if (m_UniqueTargetInfo.empty()) // skip second CheckCast apply (for delayed spells for example) { for(uint8 j = 0; j < 3; ++j) { - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || (m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT && m_spellInfo->EffectImplicitTargetA[j] != TARGET_SELF) || m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES || @@ -4180,7 +4206,8 @@ SpellCastResult Spell::CheckCast(bool strict) { SpellScriptTargetBounds bounds = sSpellMgr.GetSpellScriptTargetBounds(m_spellInfo->Id); - if(bounds.first==bounds.second) + + if (bounds.first==bounds.second) sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id); SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex); @@ -4203,8 +4230,8 @@ SpellCastResult Spell::CheckCast(bool strict) Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range); - MaNGOS::GameObjectLastSearcher checker(m_caster, p_GameObject,go_check); + MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster, i_spellST->second.targetEntry, range); + MaNGOS::GameObjectLastSearcher checker(m_caster, p_GameObject, go_check); TypeContainerVisitor, GridTypeMapContainer > object_checker(checker); CellLock cell_lock(cell, p); @@ -4239,7 +4266,7 @@ SpellCastResult Spell::CheckCast(bool strict) CellPair p(MaNGOS::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); // Really don't know what is that??? + cell.SetNoCreate(); MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range); MaNGOS::CreatureLastSearcher searcher(m_caster, p_Creature, u_check); @@ -4249,7 +4276,7 @@ SpellCastResult Spell::CheckCast(bool strict) CellLock cell_lock(cell, p); cell_lock->Visit(cell_lock, grid_creature_searcher, *m_caster->GetMap(), *m_caster, range); - if(p_Creature ) + if (p_Creature) { creatureScriptTarget = p_Creature; goScriptTarget = NULL; @@ -4260,35 +4287,43 @@ SpellCastResult Spell::CheckCast(bool strict) } } - if(creatureScriptTarget) + if (creatureScriptTarget) { // store coordinates for TARGET_SCRIPT_COORDINATES if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES) { m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->Effect[j] != SPELL_EFFECT_PERSISTENT_AREA_AURA) AddUnitTarget(creatureScriptTarget, j); } // store explicit target for TARGET_SCRIPT else - AddUnitTarget(creatureScriptTarget, j); + { + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT) + AddUnitTarget(creatureScriptTarget, j); + } } - else if(goScriptTarget) + else if (goScriptTarget) { // store coordinates for TARGET_SCRIPT_COORDINATES if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES || - m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES ) + m_spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT_COORDINATES) { m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); - if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT_COORDINATES && m_spellInfo->Effect[j] != SPELL_EFFECT_PERSISTENT_AREA_AURA) AddGOTarget(goScriptTarget, j); } - // store explicit target for TARGET_SCRIPT + // store explicit target for TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT else - AddGOTarget(goScriptTarget, j); + { + if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT || + m_spellInfo->EffectImplicitTargetB[j] == TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT) + AddGOTarget(goScriptTarget, j); + } } //Missing DB Entry or targets for this spellEffect. else @@ -4299,7 +4334,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_spellInfo->EffectImplicitTargetA[j] != TARGET_FOCUS_OR_SCRIPTED_GAMEOBJECT) { // not report target not existence for triggered spells - if(m_triggeredByAuraSpell || m_IsTriggeredSpell) + if (m_triggeredByAuraSpell || m_IsTriggeredSpell) return SPELL_FAILED_DONT_REPORT; else return SPELL_FAILED_BAD_TARGETS; @@ -6108,13 +6143,13 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk return SPELL_CAST_OK; } -void Spell::FillAreaTargets( UnitList& TagUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets ) +void Spell::FillAreaTargets(UnitList &targetUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets) { CellPair p(MaNGOS::ComputeCellPair(x, y)); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, pushType, spellTargets); + MaNGOS::SpellNotifierCreatureAndPlayer notifier(*this, targetUnitMap, radius, pushType, spellTargets); TypeContainerVisitor world_notifier(notifier); TypeContainerVisitor grid_notifier(notifier); CellLock cell_lock(cell, p); @@ -6122,7 +6157,7 @@ void Spell::FillAreaTargets( UnitList& TagUnitMap, float x, float y, float radiu cell_lock->Visit(cell_lock, grid_notifier, *m_caster->GetMap(), *m_caster, radius); } -void Spell::FillRaidOrPartyTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, bool raid, bool withPets, bool withcaster ) +void Spell::FillRaidOrPartyTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, bool raid, bool withPets, bool withcaster) { Player *pMember = member->GetCharmerOrOwnerPlayerOrPlayerItself(); Group *pGroup = pMember ? pMember->GetGroup() : NULL; @@ -6141,13 +6176,13 @@ void Spell::FillRaidOrPartyTargets( UnitList &TagUnitMap, Unit* member, Unit* ce { if ((Target==center || center->IsWithinDistInMap(Target, radius)) && (withcaster || Target != m_caster)) - TagUnitMap.push_back(Target); + targetUnitMap.push_back(Target); if (withPets) if (Pet* pet = Target->GetPet()) if ((pet==center || center->IsWithinDistInMap(pet, radius)) && (withcaster || pet != m_caster)) - TagUnitMap.push_back(pet); + targetUnitMap.push_back(pet); } } } @@ -6156,46 +6191,46 @@ void Spell::FillRaidOrPartyTargets( UnitList &TagUnitMap, Unit* member, Unit* ce Unit* ownerOrSelf = pMember ? pMember : member->GetCharmerOrOwnerOrSelf(); if ((ownerOrSelf==center || center->IsWithinDistInMap(ownerOrSelf, radius)) && (withcaster || ownerOrSelf != m_caster)) - TagUnitMap.push_back(ownerOrSelf); + targetUnitMap.push_back(ownerOrSelf); if (withPets) if (Pet* pet = ownerOrSelf->GetPet()) if ((pet==center || center->IsWithinDistInMap(pet, radius)) && (withcaster || pet != m_caster)) - TagUnitMap.push_back(pet); + targetUnitMap.push_back(pet); } } -void Spell::FillRaidOrPartyManaPriorityTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withCaster ) +void Spell::FillRaidOrPartyManaPriorityTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withCaster) { - FillRaidOrPartyTargets(TagUnitMap, member, center, radius, raid, withPets, withCaster); + FillRaidOrPartyTargets(targetUnitMap, member, center, radius, raid, withPets, withCaster); PrioritizeManaUnitQueue manaUsers; - for(UnitList::const_iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end() && manaUsers.size() < count; ++itr) + for(UnitList::const_iterator itr = targetUnitMap.begin(); itr != targetUnitMap.end() && manaUsers.size() < count; ++itr) if ((*itr)->getPowerType() == POWER_MANA && !(*itr)->isDead()) manaUsers.push(PrioritizeManaUnitWraper(*itr)); - TagUnitMap.clear(); + targetUnitMap.clear(); while(!manaUsers.empty()) { - TagUnitMap.push_back(manaUsers.top().getUnit()); + targetUnitMap.push_back(manaUsers.top().getUnit()); manaUsers.pop(); } } -void Spell::FillRaidOrPartyHealthPriorityTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withCaster ) +void Spell::FillRaidOrPartyHealthPriorityTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withCaster) { - FillRaidOrPartyTargets(TagUnitMap, member, center, radius, raid, withPets, withCaster); + FillRaidOrPartyTargets(targetUnitMap, member, center, radius, raid, withPets, withCaster); PrioritizeHealthUnitQueue healthQueue; - for(UnitList::const_iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end() && healthQueue.size() < count; ++itr) + for(UnitList::const_iterator itr = targetUnitMap.begin(); itr != targetUnitMap.end() && healthQueue.size() < count; ++itr) if (!(*itr)->isDead()) healthQueue.push(PrioritizeHealthUnitWraper(*itr)); - TagUnitMap.clear(); + targetUnitMap.clear(); while(!healthQueue.empty()) { - TagUnitMap.push_back(healthQueue.top().getUnit()); + targetUnitMap.push_back(healthQueue.top().getUnit()); healthQueue.pop(); } } diff --git a/src/game/Spell.h b/src/game/Spell.h index 206b0f073..018f06e47 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -372,12 +372,12 @@ class Spell typedef std::list UnitList; void FillTargetMap(); - void SetTargetMap(uint32 effIndex,uint32 targetMode,UnitList& TagUnitMap); + void SetTargetMap(uint32 effIndex, uint32 targetMode, UnitList &targetUnitMap); - void FillAreaTargets( UnitList& TagUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets ); - void FillRaidOrPartyTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, bool raid, bool withPets, bool withcaster ); - void FillRaidOrPartyManaPriorityTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withcaster ); - void FillRaidOrPartyHealthPriorityTargets( UnitList &TagUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withcaster ); + void FillAreaTargets(UnitList &targetUnitMap, float x, float y, float radius, SpellNotifyPushType pushType, SpellTargets spellTargets); + void FillRaidOrPartyTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, bool raid, bool withPets, bool withcaster); + void FillRaidOrPartyManaPriorityTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withcaster); + void FillRaidOrPartyHealthPriorityTargets(UnitList &targetUnitMap, Unit* member, Unit* center, float radius, uint32 count, bool raid, bool withPets, bool withcaster); template WorldObject* FindCorpseUsing(); diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 0f5bb6437..a784d2f00 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -205,7 +205,7 @@ enum AuraType SPELL_AURA_MOD_AOE_AVOIDANCE = 160, SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT = 161, SPELL_AURA_POWER_BURN_MANA = 162, - SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE = 163, + SPELL_AURA_MOD_CRIT_DAMAGE_BONUS = 163, SPELL_AURA_164 = 164, SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS = 165, SPELL_AURA_MOD_ATTACK_POWER_PCT = 166, diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index da4754842..0a60275e0 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -213,7 +213,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT implemented in Player::RegenerateAll and Player::RegenerateHealth &Aura::HandleAuraPowerBurn, //162 SPELL_AURA_POWER_BURN_MANA - &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE implememnted in Unit::CalculateMeleeDamage and Unit::SpellCriticalDamageBonus + &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS implemented in Unit::CalculateMeleeDamage and Unit::SpellCriticalDamageBonus &Aura::HandleUnused, //164 unused (3.0.8a-3.2.2a), only one test spell 10654 &Aura::HandleNoImmediateEffect, //165 SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS implemented in Unit::MeleeDamageBonus &Aura::HandleAuraModAttackPowerPercent, //166 SPELL_AURA_MOD_ATTACK_POWER_PCT @@ -2241,6 +2241,12 @@ void Aura::HandleAuraDummy(bool apply, bool Real) if (Unit* caster = GetCaster()) m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); return; + case 7057: // Haunting Spirits + // expected to tick with 30 sec period (tick part see in Aura::PeriodicTick) + m_isPeriodic = true; + m_modifier.periodictime = 30*IN_MILISECONDS; + m_periodicTimer = m_modifier.periodictime; + return; case 13139: // net-o-matic // root to self part of (root_target->charge->root_self sequence if (Unit* caster = GetCaster()) @@ -2389,6 +2395,14 @@ void Aura::HandleAuraDummy(bool apply, bool Real) switch(GetId()) { + case 28169: // Mutating Injection + { + // Mutagen Explosion + m_target->CastSpell(m_target, 28206, true, NULL, this); + // Poison Cloud + m_target->CastSpell(m_target, 28240, true, NULL, this); + return; + } case 36730: // Flame Strike { m_target->CastSpell(m_target, 36731, true, NULL, this); @@ -2813,7 +2827,7 @@ void Aura::HandleAuraMounted(bool apply, bool Real) if (minfo) display_id = minfo->modelid; - m_target->Mount(display_id); + m_target->Mount(display_id, m_spellProto->Id); } else { @@ -7014,6 +7028,7 @@ void Aura::PeriodicTick() break; } // Here tick dummy auras + case SPELL_AURA_DUMMY: // some spells have dummy aura case SPELL_AURA_PERIODIC_DUMMY: { PeriodicDummyTick(); @@ -7099,6 +7114,10 @@ void Aura::PeriodicDummyTick() // 7053 Forsaken Skill: Shadow return; } + case 7057: // Haunting Spirits + if (roll_chance_i(33)) + m_target->CastSpell(m_target,m_modifier.m_amount,true,NULL,this); + return; // // Panda // case 19230: break; // // Gossip NPC Periodic - Talk @@ -7253,6 +7272,21 @@ void Aura::PeriodicDummyTick() // case 50493: break; // // Love Rocket Barrage // case 50530: break; + case 50789: // Summon iron dwarf (left or right) + case 59860: + m_target->CastSpell(m_target, roll_chance_i(50) ? 50790 : 50791, true, NULL, this); + return; + case 50792: // Summon iron trogg (left or right) + case 59859: + m_target->CastSpell(m_target, roll_chance_i(50) ? 50793 : 50794, true, NULL, this); + return; + case 50801: // Summon malformed ooze (left or right) + case 59858: + m_target->CastSpell(m_target, roll_chance_i(50) ? 50802 : 50803, true, NULL, this); + return; + case 50824: // Summon earthen dwarf + m_target->CastSpell(m_target, roll_chance_i(50) ? 50825 : 50826, true, NULL, this); + return; // Exist more after, need add later default: break; diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index f47f74a05..4a28ebf47 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -749,44 +749,6 @@ void Spell::EffectDummy(uint32 i) ((Creature*)unitTarget)->setDeathState(JUST_ALIVED); return; } - case 12162: // Deep wounds - case 12850: // (now good common check for this spells) - case 12868: - { - if (!unitTarget) - return; - - float damage; - // DW should benefit of attack power, damage percent mods etc. - // TODO: check if using offhand damage is correct and if it should be divided by 2 - if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK)) - damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2; - else - damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2; - - switch (m_spellInfo->Id) - { - case 12162: damage *= 0.16f; break; // Rank 1 - case 12850: damage *= 0.32f; break; // Rank 2 - case 12868: damage *= 0.48f; break; // Rank 3 - default: - sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id); - return; - }; - - // get remaining damage of old Deep Wound aura - Aura* deepWound = unitTarget->GetAura(12721, 0); - if (deepWound) - { - int32 remainingTicks = deepWound->GetAuraDuration() / deepWound->GetModifier()->periodictime; - damage += remainingTicks * deepWound->GetModifier()->m_amount; - } - - // 1 tick/sec * 6 sec = 6 ticks - int32 deepWoundsDotBasePoints0 = int32(damage / 6); - m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL); - return; - } case 13120: // net-o-matic { if (!unitTarget) @@ -6477,7 +6439,11 @@ void Spell::EffectPlayerPull(uint32 i) if(!unitTarget) return; - unitTarget->KnockBackFrom(m_caster,float(damage ? damage : unitTarget->GetDistance2d(m_caster)),float(m_spellInfo->EffectMiscValue[i])/10); + float dist = unitTarget->GetDistance2d(m_caster); + if (damage && dist > damage) + dist = damage; + + unitTarget->KnockBackFrom(m_caster,-dist,float(m_spellInfo->EffectMiscValue[i])/10); } void Spell::EffectDispelMechanic(uint32 i) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index b361a2825..ea6f7b9b7 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -1568,6 +1568,11 @@ bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) cons (spellId_2 == 33891 && spellId_1 == 34123)) return false; + // Lifebloom and Wild Growth + if (spellInfo_1->SpellIconID == 2101 && spellInfo_2->SpellIconID == 2864 || + spellInfo_2->SpellIconID == 2101 && spellInfo_1->SpellIconID == 2864 ) + return false; + // Innervate and Glyph of Innervate and some other spells if (spellInfo_1->SpellIconID == 62 && spellInfo_2->SpellIconID == 62) return false; diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp index 53d037848..57bff7243 100644 --- a/src/game/TargetedMovementGenerator.cpp +++ b/src/game/TargetedMovementGenerator.cpp @@ -102,6 +102,19 @@ void TargetedMovementGenerator::Initialize(Creature &owner) _setTargetLocation(owner); } +template<> +void TargetedMovementGenerator::UpdateFinalDistance(float fDistance) +{ + // nothing to do for Player +} + +template<> +void TargetedMovementGenerator::UpdateFinalDistance(float fDistance) +{ + i_offset = fDistance; + i_recalculateTravel = true; +} + template<> void TargetedMovementGenerator::Initialize(Player &owner) { diff --git a/src/game/TargetedMovementGenerator.h b/src/game/TargetedMovementGenerator.h index 478c54fe3..09499c251 100644 --- a/src/game/TargetedMovementGenerator.h +++ b/src/game/TargetedMovementGenerator.h @@ -61,6 +61,8 @@ class MANGOS_DLL_SPEC TargetedMovementGenerator } void unitSpeedChanged() { i_recalculateTravel=true; } + void UpdateFinalDistance(float fDistance); + private: void _setTargetLocation(T &); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index c2baad92e..f60f1f3e9 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -216,17 +216,17 @@ void Unit::Update( uint32 p_time ) // Check UNIT_STAT_MELEE_ATTACKING or UNIT_STAT_CHASE (without UNIT_STAT_FOLLOW in this case) so pets can reach far away // targets without stopping half way there and running off. // These flags are reset after target dies or another command is given. - if( m_HostileRefManager.isEmpty() ) + if (m_HostileRefManager.isEmpty()) { // m_CombatTimer set at aura start and it will be freeze until aura removing - if ( m_CombatTimer <= p_time ) - ClearInCombat(); + if (m_CombatTimer <= p_time) + CombatStop(); else m_CombatTimer -= p_time; } } - if(uint32 base_att = getAttackTimer(BASE_ATTACK)) + if (uint32 base_att = getAttackTimer(BASE_ATTACK)) { setAttackTimer(BASE_ATTACK, (p_time >= base_att ? 0 : base_att - p_time) ); } @@ -1292,10 +1292,9 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da if(damageInfo->attackType == RANGED_ATTACK) mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE); else - { mod += damageInfo->target->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE); - mod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE); - } + + mod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, SPELL_SCHOOL_MASK_NORMAL); uint32 crTypeMask = damageInfo->target->GetCreatureTypeMask(); @@ -3608,16 +3607,26 @@ bool Unit::AddAura(Aura *Aur) { for(AuraMap::iterator i2 = m_Auras.lower_bound(spair); i2 != m_Auras.upper_bound(spair); ++i2) { - if(i2->second->GetCasterGUID()==Aur->GetCasterGUID()) + Aura* aur2 = i2->second; + if(aur2->GetCasterGUID()==Aur->GetCasterGUID()) { // Aura can stack on self -> Stack it; if(aurSpellInfo->StackAmount) { // can be created with >1 stack by some spell mods - i2->second->modStackAmount(Aur->GetStackAmount()); + aur2->modStackAmount(Aur->GetStackAmount()); delete Aur; return false; } + // Carry over removed Aura's remaining damage if Aura still has ticks remaining + else if (aur2->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_STACK_DOT_MODIFIER && aurName == SPELL_AURA_PERIODIC_DAMAGE && aur2->GetAuraDuration() > 0) + { + int32 remainingTicks = 1 + (aur2->GetAuraDuration() / aur2->GetModifier()->periodictime); + int32 remainingDamage = aur2->GetModifier()->m_amount * remainingTicks; + + int32 maxTicks = Aur->GetAuraMaxDuration() / Aur->GetModifier()->periodictime; + Aur->GetModifier()->m_amount += int32(remainingDamage / maxTicks); + } // can be only single (this check done at _each_ aura add RemoveAura(i2,AURA_REMOVE_BY_STACK); break; @@ -5833,6 +5842,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu // Wrath crit if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000001)) { + if (HasAura(48517)) + return false; if (!roll_chance_i(60)) return false; triggered_spell_id = 48518; @@ -5842,6 +5853,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAu // Starfire crit if (procSpell->SpellFamilyFlags & UI64LIT(0x0000000000000004)) { + if (HasAura(48518)) + return false; triggered_spell_id = 48517; target = this; break; @@ -7007,6 +7020,34 @@ bool Unit::HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggeredB } break; case SPELLFAMILY_WARRIOR: + // Deep Wounds (replace triggered spells to directly apply DoT), dot spell have finilyflags + if (auraSpellInfo->SpellFamilyFlags == UI64LIT(0x0) && auraSpellInfo->SpellIconID == 243) + { + float weaponDamage; + // DW should benefit of attack power, damage percent mods etc. + // TODO: check if using offhand damage is correct and if it should be divided by 2 + if (haveOffhandWeapon() && getAttackTimer(BASE_ATTACK) > getAttackTimer(OFF_ATTACK)) + weaponDamage = (GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2; + else + weaponDamage = (GetFloatValue(UNIT_FIELD_MINDAMAGE) + GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2; + + switch (auraSpellInfo->Id) + { + case 12834: basepoints[0] = int32(weaponDamage * 16 / 100); break; + case 12849: basepoints[0] = int32(weaponDamage * 32 / 100); break; + case 12867: basepoints[0] = int32(weaponDamage * 48 / 100); break; + // Impossible case + default: + sLog.outError("Unit::HandleProcTriggerSpell: DW unknown spell rank %u",auraSpellInfo->Id); + return false; + } + + // 1 tick/sec * 6 sec = 6 ticks + basepoints[0] /= 6; + + trigger_spell_id = 12721; + break; + } if (auraSpellInfo->Id == 50421) // Scent of Blood trigger_spell_id = 50422; break; @@ -8346,6 +8387,9 @@ void Unit::SetPet(Pet* pet) { SetPetGUID(pet ? pet->GetGUID() : 0); + if(pet && GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->SendPetGUIDs(); + // FIXME: hack, speed must be set only at follow if(pet && GetTypeId()==TYPEID_PLAYER) for(int i = 0; i < MAX_MOVE_TYPE; ++i) @@ -8520,16 +8564,19 @@ uint32 Unit::SpellDamageBonus(Unit *pVictim, SpellEntry const *spellProto, uint3 if( GetTypeId() == TYPEID_UNIT && !((Creature*)this)->isPet() ) DoneTotalMod *= ((Creature*)this)->GetSpellDamageMod(((Creature*)this)->GetCreatureInfo()->rank); - AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); - for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) + if (!(spellProto->AttributesEx6 & SPELL_ATTR_EX6_NO_DMG_PERCENT_MODS)) { - if (((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) && - (*i)->GetSpellProto()->EquippedItemClass == -1 && - // -1 == any item class (not wand then) - (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0) - // 0 == any inventory type (not wand then) + AuraList const& mModDamagePercentDone = GetAurasByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE); + for(AuraList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i) { - DoneTotalMod *= ((*i)->GetModifier()->m_amount + 100.0f) / 100.0f; + if( ((*i)->GetModifier()->m_miscvalue & GetSpellSchoolMask(spellProto)) && + (*i)->GetSpellProto()->EquippedItemClass == -1 && + // -1 == any item class (not wand then) + (*i)->GetSpellProto()->EquippedItemInventoryTypeMask == 0 ) + // 0 == any inventory type (not wand then) + { + DoneTotalMod *= ((*i)->GetModifier()->m_amount+100.0f)/100.0f; + } } } @@ -9034,17 +9081,6 @@ bool Unit::isSpellCrit(Unit *pVictim, SpellEntry const *spellProto, SpellSchoolM break; } case SPELL_DAMAGE_CLASS_MELEE: - { - // Judgement of Command proc always crits on stunned target - if(spellProto->SpellFamilyName == SPELLFAMILY_PALADIN) - { - if(spellProto->SpellFamilyFlags & 0x0000000000800000LL && spellProto->SpellIconID == 561) - { - if(pVictim->hasUnitState(UNIT_STAT_STUNNED)) - return true; - } - } - } case SPELL_DAMAGE_CLASS_RANGED: { if (pVictim) @@ -9095,14 +9131,13 @@ uint32 Unit::SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damag if(GetWeaponAttackType(spellProto) == RANGED_ATTACK) critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE); else - { critPctDamageMod += pVictim->GetTotalAuraModifier(SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE); - critPctDamageMod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE); - } } else critPctDamageMod += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE,GetSpellSchoolMask(spellProto)); + critPctDamageMod += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS, GetSpellSchoolMask(spellProto)); + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); critPctDamageMod += GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask); @@ -9839,9 +9874,9 @@ float Unit::GetPPMProcChance(uint32 WeaponSpeed, float PPM) const return WeaponSpeed * PPM / 600.0f; // result is chance in percents (probability = Speed_in_sec * (PPM / 60)) } -void Unit::Mount(uint32 mount) +void Unit::Mount(uint32 mount, uint32 spellId) { - if(!mount) + if (!mount) return; RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_MOUNTING); @@ -9850,9 +9885,27 @@ void Unit::Mount(uint32 mount) SetFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); - // unsummon pet - if(GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->UnsummonPetTemporaryIfAny(); + if (GetTypeId() == TYPEID_PLAYER) + { + // Called by Taxi system / GM command + if (!spellId) + ((Player*)this)->UnsummonPetTemporaryIfAny(); + // Called by mount aura + else if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId)) + { + // Flying case (Unsummon any pet) + if (IsSpellHaveAura(spellInfo, SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)) + ((Player*)this)->UnsummonPetTemporaryIfAny(); + // Normal case (Unsummon only permanent pet) + else if (Pet* pet = GetPet()) + { + if (pet->IsPermanentPetFor((Player*)this)) + ((Player*)this)->UnsummonPetTemporaryIfAny(); + else + pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS,true); + } + } + } } void Unit::Unmount() @@ -9869,7 +9922,12 @@ void Unit::Unmount() // this prevents adding a pet to a not created map which would otherwise cause a crash // (it could probably happen when logging in after a previous crash) if(GetTypeId() == TYPEID_PLAYER) - ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny(); + { + if(Pet* pet = GetPet()) + pet->ApplyModeFlags(PET_MODE_DISABLE_ACTIONS,false); + else + ((Player*)this)->ResummonPetTemporaryUnSummonedIfAny(); + } } void Unit::SetInCombatWith(Unit* enemy) diff --git a/src/game/Unit.h b/src/game/Unit.h index 81b84dc33..304070422 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1026,7 +1026,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject bool IsMounted() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_MOUNT ); } uint32 GetMountID() const { return GetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID); } - void Mount(uint32 mount); + void Mount(uint32 mount, uint32 spellId = 0); void Unmount(); uint16 GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? getLevelForTarget(target) : getLevel()) * 5; } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 343a65f99..911db56a7 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "9055" + #define REVISION_NR "9086" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index c649603f6..1d1a0c56c 100644 --- a/src/shared/revision_sql.h +++ b/src/shared/revision_sql.h @@ -1,6 +1,6 @@ #ifndef __REVISION_SQL_H__ #define __REVISION_SQL_H__ #define REVISION_DB_CHARACTERS "required_8874_01_characters_character_skills" - #define REVISION_DB_MANGOS "required_9045_02_mangos_spell_chain" + #define REVISION_DB_MANGOS "required_9074_01_mangos_command" #define REVISION_DB_REALMD "required_9010_01_realmd_realmlist" #endif // __REVISION_SQL_H__