diff --git a/sql/mangos.sql b/sql/mangos.sql index 81acb176b..26d1b3c5f 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_8618_01_mangos_spell_proc_event` bit(1) default NULL + `required_8676_01_mangos_creature_template` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- diff --git a/sql/updates/8676_01_mangos_creature_template.sql b/sql/updates/8676_01_mangos_creature_template.sql new file mode 100644 index 000000000..f0409da15 --- /dev/null +++ b/sql/updates/8676_01_mangos_creature_template.sql @@ -0,0 +1,5 @@ +ALTER TABLE db_version CHANGE COLUMN required_8618_01_mangos_spell_proc_event required_8676_01_mangos_creature_template bit; + +-- set all spirithealer and spiritguides to be visible only for dead people +UPDATE creature_template SET flags_extra = flags_extra | 0x200 +WHERE npcflag & (16384 | 32768); diff --git a/sql/updates/Makefile.am b/sql/updates/Makefile.am index af201b913..5137ff8d4 100644 --- a/sql/updates/Makefile.am +++ b/sql/updates/Makefile.am @@ -135,6 +135,7 @@ pkgdata_DATA = \ 8608_01_mangos_mangos_string.sql \ 8608_02_mangos_battleground_events.sql \ 8618_01_mangos_spell_proc_event.sql \ + 8676_01_mangos_creature_template.sql \ README ## Additional files to include when running 'make dist' @@ -250,4 +251,5 @@ EXTRA_DIST = \ 8608_01_mangos_mangos_string.sql \ 8608_02_mangos_battleground_events.sql \ 8618_01_mangos_spell_proc_event.sql \ + 8676_01_mangos_creature_template.sql \ README diff --git a/src/game/AggressorAI.cpp b/src/game/AggressorAI.cpp index 82e3077d8..faa4e608d 100644 --- a/src/game/AggressorAI.cpp +++ b/src/game/AggressorAI.cpp @@ -46,7 +46,7 @@ AggressorAI::MoveInLineOfSight(Unit *u) if( !m_creature->canFly() && m_creature->GetDistanceZ(u) > CREATURE_Z_ATTACK_RANGE ) return; - if( !m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED) && u->isTargetableForAttack() && + if( !(m_creature->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST) && !m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED) && u->isTargetableForAttack() && ( m_creature->IsHostileTo( u ) /*|| u->getVictim() && m_creature->IsFriendlyTo( u->getVictim() )*/ ) && u->isInAccessablePlaceFor(m_creature) ) { @@ -60,7 +60,7 @@ AggressorAI::MoveInLineOfSight(Unit *u) } else if(sMapStore.LookupEntry(m_creature->GetMapId())->IsDungeon()) { - m_creature->AddThreat(u, 0.0f); + m_creature->AddThreat(u); u->SetInCombatWith(m_creature); } } @@ -155,7 +155,7 @@ AggressorAI::AttackStart(Unit *u) // DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", m_creature->GetName(), u->GetGUIDLow()); i_victimGuid = u->GetGUID(); - m_creature->AddThreat(u, 0.0f); + m_creature->AddThreat(u); m_creature->SetInCombatWith(u); u->SetInCombatWith(m_creature); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index fc2ab843b..b666a0289 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -336,15 +336,6 @@ void Creature::Update(uint32 diff) break; case DEAD: { - if (isSpiritService()) - { - Unit::Update( diff ); - // do not allow the AI to be changed during update - m_AI_locked = true; - i_AI->UpdateAI(diff); - m_AI_locked = false; - break; // they don't should respawn - } if( m_respawnTime <= time(NULL) ) { DEBUG_LOG("Respawning..."); @@ -1563,10 +1554,7 @@ void Creature::setDeathState(DeathState s) RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); AddMonsterMoveFlag(MONSTER_MOVE_WALK); SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag); - if (!isSpiritService()) - Unit::setDeathState(ALIVE); - else - Unit::setDeathState(DEAD); + Unit::setDeathState(ALIVE); clearUnitState(UNIT_STAT_ALL_STATE); i_motionMaster.Clear(); SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); @@ -1761,7 +1749,7 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const // Live player (or with not release body see live creatures or death creatures with corpse disappearing time > 0 if(pl->isAlive() || pl->GetDeathTimer() > 0) { - if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INVISIBLE) + if(GetCreatureInfo()->flags_extra & (CREATURE_FLAG_EXTRA_INVISIBLE | CREATURE_FLAG_EXTRA_GHOST)) return false; return (isAlive() || m_deathTimer > 0 || (m_isDeadByDefault && m_deathState == CORPSE)); } @@ -1778,8 +1766,8 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const } } - // Dead player see Spirit Healer or Spirit Guide - if(isSpiritService()) + // Dead player see ghosts + if (GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST) return true; // and not see any other @@ -2057,7 +2045,7 @@ void Creature::SetInCombatWithZone() if (pPlayer->isAlive()) { pPlayer->SetInCombatWith(this); - AddThreat(pPlayer, 0.0f); + AddThreat(pPlayer); } } } diff --git a/src/game/Creature.h b/src/game/Creature.h index b4f335cc9..d41364ce2 100644 --- a/src/game/Creature.h +++ b/src/game/Creature.h @@ -143,6 +143,7 @@ enum CreatureFlagsExtra CREATURE_FLAG_EXTRA_NO_XP_AT_KILL = 0x00000040, // creature kill not provide XP CREATURE_FLAG_EXTRA_INVISIBLE = 0x00000080, // creature is always invisible for player (mostly trigger creatures) CREATURE_FLAG_EXTRA_NOT_TAUNTABLE = 0x00000100, // creature is immune to taunt auras and effect attack me + CREATURE_FLAG_EXTRA_GHOST = 0x00000200, // creature is only visible for dead players }; // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform @@ -238,13 +239,18 @@ struct CreatureInfo return SKILL_SKINNING; // normal case } + bool IsExotic() const + { + return (type_flags & CREATURE_TYPEFLAGS_EXOTIC); + } + bool isTameable(bool exotic) const { - if(type != CREATURE_TYPE_BEAST || family == 0 || (type_flags & CREATURE_TYPEFLAGS_TAMEABLE)==0) + if(type != CREATURE_TYPE_BEAST || family == 0 || (type_flags & CREATURE_TYPEFLAGS_TAMEABLE) == 0) return false; // if can tame exotic then can tame any temable - return exotic || (type_flags & CREATURE_TYPEFLAGS_EXOTIC)==0; + return exotic || !IsExotic(); } }; diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp index e7fa84a08..3e9c59e28 100644 --- a/src/game/CreatureEventAI.cpp +++ b/src/game/CreatureEventAI.cpp @@ -948,7 +948,7 @@ void CreatureEventAI::AttackStart(Unit *who) if (m_creature->Attack(who, MeleeEnabled)) { - m_creature->AddThreat(who, 0.0f); + m_creature->AddThreat(who); m_creature->SetInCombatWith(who); who->SetInCombatWith(m_creature); @@ -1010,7 +1010,7 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who) } else if (m_creature->GetMap()->IsDungeon()) { - m_creature->AddThreat(who, 0.0f); + m_creature->AddThreat(who); who->SetInCombatWith(m_creature); } } diff --git a/src/game/GuardAI.cpp b/src/game/GuardAI.cpp index aaa9391e6..3d5b529a7 100644 --- a/src/game/GuardAI.cpp +++ b/src/game/GuardAI.cpp @@ -138,7 +138,7 @@ void GuardAI::AttackStart(Unit *u) if(m_creature->Attack(u,true)) { i_victimGuid = u->GetGUID(); - m_creature->AddThreat(u, 0.0f); + m_creature->AddThreat(u); m_creature->SetInCombatWith(u); u->SetInCombatWith(m_creature); diff --git a/src/game/HostilRefManager.cpp b/src/game/HostilRefManager.cpp index 0fa7e379a..c9cd9cd97 100644 --- a/src/game/HostilRefManager.cpp +++ b/src/game/HostilRefManager.cpp @@ -40,7 +40,7 @@ void HostileRefManager::threatAssist(Unit *pVictim, float pThreat, SpellEntry co ref = getFirst(); while(ref != NULL) { - float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell); + float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, false, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell); if(pVictim == getOwner()) ref->addThreat(float (threat) / size); // It is faster to modify the threat durectly if possible else diff --git a/src/game/Item.cpp b/src/game/Item.cpp index eb755b022..644c13dfa 100644 --- a/src/game/Item.cpp +++ b/src/game/Item.cpp @@ -996,6 +996,14 @@ bool Item::IsBindedNotWith( Player const* player ) const } } +void Item::BuildUpdateData(UpdateDataMapType& update_players) +{ + if (Player* pl = GetOwner()) + BuildUpdateDataForPlayer(pl, update_players); + + ClearUpdateMask(false); +} + bool ItemRequiredTarget::IsFitToRequirements( Unit* pUnitTarget ) const { if(pUnitTarget->GetTypeId() != TYPEID_UNIT) diff --git a/src/game/Item.h b/src/game/Item.h index 5f92232bd..a1b444007 100644 --- a/src/game/Item.h +++ b/src/game/Item.h @@ -313,6 +313,7 @@ class MANGOS_DLL_SPEC Item : public Object bool IsPotion() const { return GetProto()->IsPotion(); } bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); } + void BuildUpdateData(UpdateDataMapType& update_players); private: uint8 m_slot; Bag *m_container; diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 4c4926ec3..bf090d523 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -128,7 +128,7 @@ void Object::BuildMovementUpdateBlock(UpdateData * data, uint32 flags ) const buf << uint8( UPDATETYPE_MOVEMENT ); buf.append(GetPackGUID()); - _BuildMovementUpdate(&buf, flags, 0x00000000); + BuildMovementUpdate(&buf, flags, 0x00000000); data->AddUpdateBlock(buf); } @@ -189,12 +189,12 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData *data, Player *target) c buf.append(GetPackGUID()); buf << (uint8)m_objectTypeId; - _BuildMovementUpdate(&buf, flags, flags2); + BuildMovementUpdate(&buf, flags, flags2); UpdateMask updateMask; updateMask.SetCount( m_valuesCount ); _SetCreateBits( &updateMask, target ); - _BuildValuesUpdate(updatetype, &buf, &updateMask, target); + BuildValuesUpdate(updatetype, &buf, &updateMask, target); data->AddUpdateBlock(buf); } @@ -220,7 +220,7 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData *data, Player *target) c updateMask.SetCount( m_valuesCount ); _SetUpdateBits( &updateMask, target ); - _BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target); + BuildValuesUpdate(UPDATETYPE_VALUES, &buf, &updateMask, target); data->AddUpdateBlock(buf); } @@ -240,7 +240,7 @@ void Object::DestroyForPlayer( Player *target, bool anim ) const target->GetSession()->SendPacket( &data ); } -void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2) const +void Object::BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2) const { uint16 unk_flags = ((GetTypeId() == TYPEID_PLAYER) ? ((Player*)this)->m_movementInfo.unk1 : 0); @@ -567,7 +567,7 @@ void Object::_BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 } } -void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const +void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *updateMask, Player *target) const { if(!target) return; @@ -1065,6 +1065,20 @@ bool Object::PrintIndexError(uint32 index, bool set) const return false; } +void Object::BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_players) +{ + UpdateDataMapType::iterator iter = update_players.find(pl); + + if (iter == update_players.end()) + { + std::pair p = update_players.insert( UpdateDataMapType::value_type(pl, UpdateData()) ); + assert(p.second); + iter = p.first; + } + + BuildValuesUpdateBlockForPlayer(&iter->second, iter->first); +} + WorldObject::WorldObject() : m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_currMap(NULL) @@ -1857,3 +1871,33 @@ void WorldObject::UpdateObjectVisibility() GetMap()->UpdateObjectVisibility(this, cell, p); } +struct WorldObjectChangeAccumulator +{ + UpdateDataMapType &i_updateDatas; + WorldObject &i_object; + WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {} + void Visit(PlayerMapType &m) + { + for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) + if(iter->getSource()->HaveAtClient(&i_object)) + i_object.BuildUpdateDataForPlayer(iter->getSource(), i_updateDatas); + } + + template void Visit(GridRefManager &) {} +}; + +void WorldObject::BuildUpdateData( UpdateDataMapType & update_players) +{ + CellPair p = MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + WorldObjectChangeAccumulator notifier(*this, update_players); + TypeContainerVisitor player_notifier(notifier); + CellLock cell_lock(cell, p); + Map* aMap = GetMap(); + //we must build packets for all visible players + cell_lock->Visit(cell_lock, player_notifier, *aMap, *this, aMap->GetVisibilityDistance()); + + ClearUpdateMask(false); +} diff --git a/src/game/Object.h b/src/game/Object.h index f74e96591..20b543eab 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -148,6 +148,7 @@ class MANGOS_DLL_SPEC Object virtual void BuildCreateUpdateBlockForPlayer( UpdateData *data, Player *target ) const; void SendCreateUpdateToPlayer(Player* player); + virtual void BuildUpdateData(UpdateDataMapType& update_players) =0; void BuildValuesUpdateBlockForPlayer( UpdateData *data, Player *target ) const; void BuildOutOfRangeUpdateBlock( UpdateData *data ) const; void BuildMovementUpdateBlock( UpdateData * data, uint32 flags = 0 ) const; @@ -307,8 +308,9 @@ class MANGOS_DLL_SPEC Object virtual void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; virtual void _SetCreateBits(UpdateMask *updateMask, Player *target) const; - void _BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 ) const; - void _BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; + void BuildMovementUpdate(ByteBuffer * data, uint16 flags, uint32 flags2 ) const; + void BuildValuesUpdate(uint8 updatetype, ByteBuffer *data, UpdateMask *updateMask, Player *target ) const; + void BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_players); uint16 m_objectType; @@ -339,8 +341,12 @@ class MANGOS_DLL_SPEC Object Object& operator=(Object const&); // prevent generation assigment operator }; +struct WorldObjectChangeAccumulator; + class MANGOS_DLL_SPEC WorldObject : public Object { + friend struct WorldObjectChangeAccumulator; + public: virtual ~WorldObject ( ) {} @@ -488,11 +494,11 @@ class MANGOS_DLL_SPEC WorldObject : public Object //this function should be removed in nearest time... Map const* GetBaseMap() const; - Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); + void BuildUpdateData(UpdateDataMapType &); + Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); protected: explicit WorldObject(); - std::string m_name; //these functions are used mostly for Relocate() and Corpse/Player specific stuff... //use them ONLY in LoadFromDB()/Create() funcs and nowhere else! @@ -500,6 +506,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object void SetLocationMapId(uint32 _mapId) { m_mapId = _mapId; } void SetLocationInstanceId(uint32 _instanceId) { m_InstanceId = _instanceId; } + std::string m_name; + private: Map * m_currMap; //current object's Map location diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index 1eb61903e..dc377cd12 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -182,49 +182,6 @@ ObjectAccessor::SaveAllPlayers() itr->second->SaveToDB(); } -void -ObjectAccessor::_buildUpdateObject(Object *obj, UpdateDataMapType &update_players) -{ - if(obj->isType(TYPEMASK_ITEM)) - { - Item *item = static_cast(obj); - if (Player* pl = item->GetOwner()) - _buildPacket(pl, obj, update_players); - } - else - _buildChangeObjectForPlayer(static_cast(obj), update_players); -} - -void -ObjectAccessor::_buildPacket(Player *pl, Object *obj, UpdateDataMapType &update_players) -{ - UpdateDataMapType::iterator iter = update_players.find(pl); - - if( iter == update_players.end() ) - { - std::pair p = update_players.insert( UpdateDataValueType(pl, UpdateData()) ); - assert(p.second); - iter = p.first; - } - - obj->BuildValuesUpdateBlockForPlayer(&iter->second, iter->first); -} - -void -ObjectAccessor::_buildChangeObjectForPlayer(WorldObject *obj, UpdateDataMapType &update_players) -{ - CellPair p = MaNGOS::ComputeCellPair(obj->GetPositionX(), obj->GetPositionY()); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - WorldObjectChangeAccumulator notifier(*obj, update_players); - TypeContainerVisitor player_notifier(notifier); - CellLock cell_lock(cell, p); - Map& map = *obj->GetMap(); - //we must build packets for all visible players - cell_lock->Visit(cell_lock, player_notifier, map, *obj, map.GetVisibilityDistance()); -} - Pet* ObjectAccessor::GetPet(uint64 guid) { @@ -386,8 +343,7 @@ ObjectAccessor::Update(uint32 diff) i_objects.erase(i_objects.begin()); if (!obj) continue; - _buildUpdateObject(obj, update_players); - obj->ClearUpdateMask(false); + obj->BuildUpdateData(update_players); } } @@ -400,14 +356,6 @@ ObjectAccessor::Update(uint32 diff) } } -void -ObjectAccessor::WorldObjectChangeAccumulator::Visit(PlayerMapType &m) -{ - for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) - if(iter->getSource()->HaveAtClient(&i_object)) - ObjectAccessor::_buildPacket(iter->getSource(), &i_object, i_updateDatas); -} - /// Define the static member of HashMapHolder template UNORDERED_MAP< uint64, T* > HashMapHolder::m_objectMap; diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index 7f6027dc1..5778732c7 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -89,7 +89,6 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton Player2CorpsesMapType; - typedef UNORDERED_MAP::value_type UpdateDataValueType; template static T* GetObjectInWorld(uint64 guid, T* /*fake*/) { @@ -180,21 +179,10 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton void Visit(GridRefManager &) {} - }; - // TODO: This methods will need lock in MT environment // Theoreticaly multiple threads can enter and search in this method but // in that case linking/delinking other map should be guarded @@ -213,14 +201,11 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton i_mapList; - friend struct WorldObjectChangeAccumulator; Player2CorpsesMapType i_player2corpse; typedef ACE_Thread_Mutex LockType; typedef MaNGOS::GeneralLock Guard; - static void _buildChangeObjectForPlayer(WorldObject *, UpdateDataMapType &); - static void _buildPacket(Player *, Object *, UpdateDataMapType &); std::set i_objects; LockType i_playerGuard; LockType i_updateGuard; diff --git a/src/game/ObjectGridLoader.cpp b/src/game/ObjectGridLoader.cpp index 89f3fcfea..9c60cd2b1 100644 --- a/src/game/ObjectGridLoader.cpp +++ b/src/game/ObjectGridLoader.cpp @@ -102,8 +102,6 @@ template<> void addUnitState(Creature *obj, CellPair const& cell_pair) Cell cell(cell_pair); obj->SetCurrentCell(cell); - if(obj->isSpiritService()) - obj->setDeathState(DEAD); } template diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp index 9dfbc43fa..354ef371a 100644 --- a/src/game/PetAI.cpp +++ b/src/game/PetAI.cpp @@ -172,7 +172,7 @@ void PetAI::UpdateAI(const uint32 diff) return; //if pet misses its target, it will also be the first in threat list - m_creature->getVictim()->AddThreat(m_creature,0.0f); + m_creature->getVictim()->AddThreat(m_creature); if( _needToStop() ) _stopAttack(); diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e99a08f4f..891e541b6 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -2098,15 +2098,14 @@ Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask) return NULL; // player check - if(!CanInteractWithNPCs(!unit->isSpiritService())) + if(!CanInteractWithNPCs(!(unit->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST))) return NULL; // appropriate npc type if(npcflagmask && !unit->HasFlag( UNIT_NPC_FLAGS, npcflagmask )) return NULL; - // alive or spirit healer - if(!unit->isAlive() && (!unit->isSpiritService() || isAlive() )) + if (isAlive() && !unit->isAlive()) return NULL; // not allow interaction under control, but allow with own pets @@ -2357,10 +2356,21 @@ void Player::GiveXP(uint32 xp, Unit* victim) if(level >= sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) return; - // handle SPELL_AURA_MOD_XP_PCT auras - Unit::AuraList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_XP_PCT); - for(Unit::AuraList::const_iterator i = ModXPPctAuras.begin();i != ModXPPctAuras.end(); ++i) - xp = uint32(xp*(1.0f + (*i)->GetModifier()->m_amount / 100.0f)); + if(victim) + { + // handle SPELL_AURA_MOD_KILL_XP_PCT auras + Unit::AuraList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_KILL_XP_PCT); + for(Unit::AuraList::const_iterator i = ModXPPctAuras.begin();i != ModXPPctAuras.end(); ++i) + xp = uint32(xp*(1.0f + (*i)->GetModifier()->m_amount / 100.0f)); + } + else + { + // handle SPELL_AURA_MOD_QUEST_XP_PCT auras + Unit::AuraList const& ModXPPctAuras = GetAurasByType(SPELL_AURA_MOD_QUEST_XP_PCT); + for(Unit::AuraList::const_iterator i = ModXPPctAuras.begin();i != ModXPPctAuras.end(); ++i) + xp = uint32(xp*(1.0f + (*i)->GetModifier()->m_amount / 100.0f)); + } + // XP resting bonus for kill uint32 rested_bonus_xp = victim ? GetXPRestBonus(xp) : 0; @@ -12561,6 +12571,13 @@ bool Player::CanRewardQuest( Quest const *pQuest, uint32 reward, bool msg ) return true; } +void Player::SendPetTameFailure(PetTameFailureReason reason) +{ + WorldPacket data(SMSG_PET_TAME_FAILURE, 1); + data << uint8(reason); + GetSession()->SendPacket(&data); +} + void Player::AddQuest( Quest const *pQuest, Object *questGiver ) { uint16 log_slot = FindQuestSlot( 0 ); diff --git a/src/game/Player.h b/src/game/Player.h index 21e59a85a..ecfc1228a 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1418,6 +1418,8 @@ class MANGOS_DLL_SPEC Player : public Unit bool m_mailsLoaded; bool m_mailsUpdated; + void SendPetTameFailure(PetTameFailureReason reason); + void SetBindPoint(uint64 guid); void SendTalentWipeConfirm(uint64 guid); void RewardRage( uint32 damage, uint32 weaponSpeedHitFactor, bool attacker ); diff --git a/src/game/PoolHandler.cpp b/src/game/PoolHandler.cpp index d1f2305bd..e038add5c 100644 --- a/src/game/PoolHandler.cpp +++ b/src/game/PoolHandler.cpp @@ -185,11 +185,15 @@ void PoolGroup::SpawnObject(uint32 limit, bool cache) if (limit == 1) // This is the only case where explicit chance is used { uint32 roll = RollOne(); - if (cache && m_LastDespawnedNode != roll) - Despawn1Object(m_LastDespawnedNode); - + if (!cache || (cache && m_LastDespawnedNode != roll)) + { + if (cache) + Despawn1Object(m_LastDespawnedNode); + Spawn1Object(roll); + } + else + ReSpawn1Object(roll); m_LastDespawnedNode = 0; - Spawn1Object(roll); } else if (limit < EqualChanced.size() && m_SpawnedPoolAmount < limit) { diff --git a/src/game/ReactorAI.cpp b/src/game/ReactorAI.cpp index bc41faee3..49cbc7e0c 100644 --- a/src/game/ReactorAI.cpp +++ b/src/game/ReactorAI.cpp @@ -49,7 +49,7 @@ ReactorAI::AttackStart(Unit *p) { DEBUG_LOG("Tag unit GUID: %u (TypeId: %u) as a victim", p->GetGUIDLow(), p->GetTypeId()); i_victimGuid = p->GetGUID(); - m_creature->AddThreat(p, 0.0f); + m_creature->AddThreat(p); m_creature->SetInCombatWith(p); p->SetInCombatWith(m_creature); diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 37c38c742..83945c8e2 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -2640,4 +2640,23 @@ enum MailResponseResult MAIL_ERR_ITEM_HAS_EXPIRED = 21, }; +// reasons for why pet tame may fail +// in fact, these are also used elsewhere +enum PetTameFailureReason +{ + PETTAME_INVALIDCREATURE = 0, + PETTAME_TOOMANY = 1, + PETTAME_CREATUREALREADYOWNED = 2, + PETTAME_NOTTAMEABLE = 3, + PETTAME_ANOTHERSUMMONACTIVE = 4, + PETTAME_UNITSCANTTAME = 5, + PETTAME_NOPETAVAILABLE = 6, // not used in taming + PETTAME_INTERNALERROR = 7, + PETTAME_TOOHIGHLEVEL = 8, + PETTAME_DEAD = 9, // not used in taming + PETTAME_NOTDEAD = 10, // not used in taming + PETTAME_CANTCONTROLEXOTIC = 11, // 3.x + PETTAME_UNKNOWNERROR = 12 +}; + #endif diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index b13d5133c..9e56a833b 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1092,7 +1092,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) if (!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI()) ((Creature*)unit)->AI()->AttackedBy(realCaster); - unit->AddThreat(realCaster, 0.0f); + unit->AddThreat(realCaster); unit->SetInCombatWith(realCaster); realCaster->SetInCombatWith(unit); @@ -1116,7 +1116,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) if (unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO)) { realCaster->SetInCombatState(unit->GetCombatTimer() > 0); - unit->getHostileRefManager().threatAssist(realCaster, 0.0f); + unit->getHostileRefManager().threatAssist(realCaster, 0.0f, m_spellInfo); } } } @@ -3770,7 +3770,7 @@ void Spell::HandleThreatSpells(uint32 spellId) if(!threat) return; - m_targets.getUnitTarget()->AddThreat(m_caster, float(threat)); + m_targets.getUnitTarget()->AddThreat(m_caster, float(threat), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo); DEBUG_LOG("Spell %u, rank %u, added an additional %i threat", spellId, spellmgr.GetSpellRank(spellId), threat); } @@ -3860,9 +3860,6 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_NOT_READY; } - if (IsDeathOnlySpell(m_spellInfo) && m_caster->isAlive()) - return SPELL_FAILED_TARGET_NOT_DEAD; - // only allow triggered spells if at an ended battleground if( !m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER) if(BattleGround * bg = ((Player*)m_caster)->GetBattleGround()) @@ -3933,6 +3930,9 @@ SpellCastResult Spell::CheckCast(bool strict) if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot))) return SPELL_FAILED_TARGET_AURASTATE; + if (IsDeathOnlySpell(m_spellInfo) && target->isAlive()) + return SPELL_FAILED_TARGET_NOT_DEAD; + // Target aura req check if need if(m_spellInfo->targetAuraSpell && !target->HasAura(m_spellInfo->targetAuraSpell)) return SPELL_FAILED_CASTER_AURASTATE; @@ -4313,26 +4313,50 @@ SpellCastResult Spell::CheckCast(bool strict) } case SPELL_EFFECT_TAMECREATURE: { - if (m_caster->GetTypeId() != TYPEID_PLAYER) + if (m_caster->GetTypeId() != TYPEID_PLAYER || + !m_targets.getUnitTarget() || + m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; - if (!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) - return SPELL_FAILED_BAD_IMPLICIT_TARGETS; + Player* plrCaster = (Player*)m_caster; + + if(plrCaster->getClass() != CLASS_HUNTER) + { + plrCaster->SendPetTameFailure(PETTAME_UNITSCANTTAME); + return SPELL_FAILED_DONT_REPORT; + } Creature* target = (Creature*)m_targets.getUnitTarget(); - if (target->getLevel() > m_caster->getLevel()) - return SPELL_FAILED_HIGHLEVEL; + if(target->isPet() || target->isCharmed()) + { + plrCaster->SendPetTameFailure(PETTAME_CREATUREALREADYOWNED); + return SPELL_FAILED_DONT_REPORT; + } - // use SMSG_PET_TAME_FAILURE? - if (!target->GetCreatureInfo()->isTameable (((Player*)m_caster)->CanTameExoticPets())) - return SPELL_FAILED_BAD_TARGETS; + if (target->getLevel() > plrCaster->getLevel()) + { + plrCaster->SendPetTameFailure(PETTAME_TOOHIGHLEVEL); + return SPELL_FAILED_DONT_REPORT; + } - if(m_caster->GetPetGUID()) - return SPELL_FAILED_ALREADY_HAVE_SUMMON; + if (target->GetCreatureInfo()->IsExotic() && !plrCaster->CanTameExoticPets()) + { + plrCaster->SendPetTameFailure(PETTAME_CANTCONTROLEXOTIC); + return SPELL_FAILED_DONT_REPORT; + } - if(m_caster->GetCharmGUID()) - return SPELL_FAILED_ALREADY_HAVE_CHARM; + if (!target->GetCreatureInfo()->isTameable(plrCaster->CanTameExoticPets())) + { + plrCaster->SendPetTameFailure(PETTAME_NOTTAMEABLE); + return SPELL_FAILED_DONT_REPORT; + } + + if(plrCaster->GetPetGUID() || plrCaster->GetCharmGUID()) + { + plrCaster->SendPetTameFailure(PETTAME_ANOTHERSUMMONACTIVE); + return SPELL_FAILED_DONT_REPORT; + } break; } diff --git a/src/game/SpellAuraDefines.h b/src/game/SpellAuraDefines.h index 2700d1d2f..3ccdb1ee6 100644 --- a/src/game/SpellAuraDefines.h +++ b/src/game/SpellAuraDefines.h @@ -59,7 +59,7 @@ enum AuraType SPELL_AURA_MOD_DAMAGE_TAKEN = 14, SPELL_AURA_DAMAGE_SHIELD = 15, SPELL_AURA_MOD_STEALTH = 16, - SPELL_AURA_MOD_DETECT = 17, + SPELL_AURA_MOD_STEALTH_DETECT = 17, SPELL_AURA_MOD_INVISIBILITY = 18, SPELL_AURA_MOD_INVISIBILITY_DETECTION = 19, SPELL_AURA_OBS_MOD_HEALTH = 20, //20,21 unofficial @@ -242,12 +242,12 @@ enum AuraType SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE = 197, SPELL_AURA_198 = 198, // old SPELL_AURA_MOD_ALL_WEAPON_SKILLS SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT = 199, - SPELL_AURA_MOD_XP_PCT = 200, + SPELL_AURA_MOD_KILL_XP_PCT = 200, SPELL_AURA_FLY = 201, SPELL_AURA_IGNORE_COMBAT_RESULT = 202, SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE = 203, SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE = 204, - SPELL_AURA_205 = 205, // unused + SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE = 205, SPELL_AURA_MOD_SPEED_MOUNTED = 206, // ? used in strange spells SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED = 207, SPELL_AURA_MOD_SPEED_FLIGHT = 208, @@ -311,11 +311,11 @@ enum AuraType SPELL_AURA_266 = 266, SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL = 267, SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT = 268, - SPELL_AURA_269 = 269, + SPELL_AURA_MOD_IGNORE_DAMAGE_REDUCTION_SCHOOL = 269, SPELL_AURA_MOD_IGNORE_TARGET_RESIST = 270, // Possibly need swap vs 195 aura used only in 1 spell Chaos Bolt Passive SPELL_AURA_MOD_DAMAGE_FROM_CASTER = 271, SPELL_AURA_272 = 272, - SPELL_AURA_273 = 273, + SPELL_AURA_X_RAY = 273, SPELL_AURA_274 = 274, SPELL_AURA_MOD_IGNORE_SHAPESHIFT = 275, SPELL_AURA_276 = 276, // Only "Test Mod Damage % Mechanic" spell, possible mod damage done @@ -329,26 +329,26 @@ enum AuraType SPELL_AURA_284, SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR = 285, SPELL_AURA_ABILITY_PERIODIC_CRIT = 286, - SPELL_AURA_DEFLECT_SPELLS, - SPELL_AURA_288, - SPELL_AURA_289, - SPELL_AURA_MOD_ALL_CRIT_CHANCE, - SPELL_AURA_291, - SPELL_AURA_292, - SPELL_AURA_293, - SPELL_AURA_294, - SPELL_AURA_295, - SPELL_AURA_296, - SPELL_AURA_297, - SPELL_AURA_298, - SPELL_AURA_299, - SPELL_AURA_300, - SPELL_AURA_301, - SPELL_AURA_302, - SPELL_AURA_303, - SPELL_AURA_304, - SPELL_AURA_305, - SPELL_AURA_306, + SPELL_AURA_DEFLECT_SPELLS = 287, + SPELL_AURA_288 = 288, + SPELL_AURA_289 = 289, + SPELL_AURA_MOD_ALL_CRIT_CHANCE = 290, + SPELL_AURA_MOD_QUEST_XP_PCT = 291, + SPELL_AURA_292 = 292, + SPELL_AURA_293 = 293, + SPELL_AURA_294 = 294, + SPELL_AURA_295 = 295, + SPELL_AURA_296 = 296, + SPELL_AURA_297 = 297, + SPELL_AURA_298 = 298, + SPELL_AURA_299 = 299, + SPELL_AURA_300 = 300, + SPELL_AURA_301 = 301, + SPELL_AURA_302 = 302, + SPELL_AURA_303 = 303, + SPELL_AURA_304 = 304, + SPELL_AURA_305 = 305, + SPELL_AURA_306 = 306, TOTAL_AURAS = 307 }; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 43f9e5a5c..8015555f8 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -64,10 +64,10 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleModTaunt, // 11 SPELL_AURA_MOD_TAUNT &Aura::HandleAuraModStun, // 12 SPELL_AURA_MOD_STUN &Aura::HandleModDamageDone, // 13 SPELL_AURA_MOD_DAMAGE_DONE - &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus - &Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DoAttackDamage + &Aura::HandleNoImmediateEffect, // 14 SPELL_AURA_MOD_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellBaseDamageBonusForVictim + &Aura::HandleNoImmediateEffect, // 15 SPELL_AURA_DAMAGE_SHIELD implemented in Unit::DealMeleeDamage &Aura::HandleModStealth, // 16 SPELL_AURA_MOD_STEALTH - &Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT + &Aura::HandleNoImmediateEffect, // 17 SPELL_AURA_MOD_STEALTH_DETECT implemented in Unit::isVisibleForOrDetect &Aura::HandleInvisibility, // 18 SPELL_AURA_MOD_INVISIBILITY &Aura::HandleInvisibilityDetect, // 19 SPELL_AURA_MOD_INVISIBILITY_DETECTION &Aura::HandleAuraModTotalHealthPercentRegen, // 20 SPELL_AURA_OBS_MOD_HEALTH @@ -96,7 +96,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, // 43 SPELL_AURA_PROC_TRIGGER_DAMAGE implemented in Unit::ProcDamageAndSpellFor &Aura::HandleAuraTrackCreatures, // 44 SPELL_AURA_TRACK_CREATURES &Aura::HandleAuraTrackResources, // 45 SPELL_AURA_TRACK_RESOURCES - &Aura::HandleUnused, // 46 SPELL_AURA_46 (used in test spells 54054 and 54058, and spell 48050) (3.0.8a) + &Aura::HandleUnused, // 46 SPELL_AURA_46 (used in test spells 54054 and 54058, and spell 48050) (3.0.8a-3.2.2a) &Aura::HandleAuraModParryPercent, // 47 SPELL_AURA_MOD_PARRY_PERCENT &Aura::HandleNULL, // 48 SPELL_AURA_48 spell Napalm (area damage spell with additional delayed damage effect) &Aura::HandleAuraModDodgePercent, // 49 SPELL_AURA_MOD_DODGE_PERCENT @@ -113,34 +113,34 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModPacifyAndSilence, // 60 SPELL_AURA_MOD_PACIFY_SILENCE &Aura::HandleAuraModScale, // 61 SPELL_AURA_MOD_SCALE &Aura::HandlePeriodicHealthFunnel, // 62 SPELL_AURA_PERIODIC_HEALTH_FUNNEL - &Aura::HandleUnused, // 63 unused (3.0.8a) old SPELL_AURA_PERIODIC_MANA_FUNNEL + &Aura::HandleUnused, // 63 unused (3.0.8a-3.2.2a) old SPELL_AURA_PERIODIC_MANA_FUNNEL &Aura::HandlePeriodicManaLeech, // 64 SPELL_AURA_PERIODIC_MANA_LEECH &Aura::HandleModCastingSpeed, // 65 SPELL_AURA_MOD_CASTING_SPEED_NOT_STACK &Aura::HandleFeignDeath, // 66 SPELL_AURA_FEIGN_DEATH &Aura::HandleAuraModDisarm, // 67 SPELL_AURA_MOD_DISARM &Aura::HandleAuraModStalked, // 68 SPELL_AURA_MOD_STALKED &Aura::HandleSchoolAbsorb, // 69 SPELL_AURA_SCHOOL_ABSORB implemented in Unit::CalcAbsorbResist - &Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell that has only visual effect + &Aura::HandleUnused, // 70 SPELL_AURA_EXTRA_ATTACKS Useless, used by only one spell 41560 that has only visual effect (3.2.2a) &Aura::HandleModSpellCritChanceShool, // 71 SPELL_AURA_MOD_SPELL_CRIT_CHANCE_SCHOOL &Aura::HandleModPowerCostPCT, // 72 SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT &Aura::HandleModPowerCost, // 73 SPELL_AURA_MOD_POWER_COST_SCHOOL &Aura::HandleNoImmediateEffect, // 74 SPELL_AURA_REFLECT_SPELLS_SCHOOL implemented in Unit::SpellHitResult - &Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE + &Aura::HandleNoImmediateEffect, // 75 SPELL_AURA_MOD_LANGUAGE implemented in WorldSession::HandleMessagechatOpcode &Aura::HandleFarSight, // 76 SPELL_AURA_FAR_SIGHT &Aura::HandleModMechanicImmunity, // 77 SPELL_AURA_MECHANIC_IMMUNITY &Aura::HandleAuraMounted, // 78 SPELL_AURA_MOUNTED &Aura::HandleModDamagePercentDone, // 79 SPELL_AURA_MOD_DAMAGE_PERCENT_DONE &Aura::HandleModPercentStat, // 80 SPELL_AURA_MOD_PERCENT_STAT - &Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT + &Aura::HandleNoImmediateEffect, // 81 SPELL_AURA_SPLIT_DAMAGE_PCT implemented in Unit::CalcAbsorbResist &Aura::HandleWaterBreathing, // 82 SPELL_AURA_WATER_BREATHING &Aura::HandleModBaseResistance, // 83 SPELL_AURA_MOD_BASE_RESISTANCE &Aura::HandleModRegen, // 84 SPELL_AURA_MOD_REGEN &Aura::HandleModPowerRegen, // 85 SPELL_AURA_MOD_POWER_REGEN &Aura::HandleChannelDeathItem, // 86 SPELL_AURA_CHANNEL_DEATH_ITEM &Aura::HandleNoImmediateEffect, // 87 SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN implemented in Unit::MeleeDamageBonus and Unit::SpellDamageBonus - &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT + &Aura::HandleNoImmediateEffect, // 88 SPELL_AURA_MOD_HEALTH_REGEN_PERCENT implemented in Player::RegenerateHealth &Aura::HandlePeriodicDamagePCT, // 89 SPELL_AURA_PERIODIC_DAMAGE_PERCENT - &Aura::HandleUnused, // 90 unused (3.0.8a) old SPELL_AURA_MOD_RESIST_CHANCE + &Aura::HandleUnused, // 90 unused (3.0.8a-3.2.2a) old SPELL_AURA_MOD_RESIST_CHANCE &Aura::HandleNoImmediateEffect, // 91 SPELL_AURA_MOD_DETECT_RANGE implemented in Creature::GetAttackDistance &Aura::HandlePreventFleeing, // 92 SPELL_AURA_PREVENTS_FLEEING &Aura::HandleModUnattackable, // 93 SPELL_AURA_MOD_UNATTACKABLE @@ -150,7 +150,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleManaShield, // 97 SPELL_AURA_MANA_SHIELD implemented in Unit::CalcAbsorbResist &Aura::HandleAuraModSkill, // 98 SPELL_AURA_MOD_SKILL_TALENT &Aura::HandleAuraModAttackPower, // 99 SPELL_AURA_MOD_ATTACK_POWER - &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete? all player can see all auras now, but still have spells including GM-spell + &Aura::HandleUnused, //100 SPELL_AURA_AURAS_VISIBLE obsolete 3.x? all player can see all auras now, but still have 2 spells including GM-spell (1852,2855) &Aura::HandleModResistancePercent, //101 SPELL_AURA_MOD_RESISTANCE_PCT &Aura::HandleNoImmediateEffect, //102 SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS implemented in Unit::MeleeDamageBonus &Aura::HandleAuraModTotalThreat, //103 SPELL_AURA_MOD_TOTAL_THREAT @@ -162,14 +162,14 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAddTargetTrigger, //109 SPELL_AURA_ADD_TARGET_TRIGGER &Aura::HandleModPowerRegenPCT, //110 SPELL_AURA_MOD_POWER_REGEN_PERCENT &Aura::HandleNoImmediateEffect, //111 SPELL_AURA_ADD_CASTER_HIT_TRIGGER implemented in Unit::SelectMagnetTarget - &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS + &Aura::HandleNoImmediateEffect, //112 SPELL_AURA_OVERRIDE_CLASS_SCRIPTS implemented in diff functions. &Aura::HandleNoImmediateEffect, //113 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN implemented in Unit::MeleeDamageBonus &Aura::HandleNoImmediateEffect, //114 SPELL_AURA_MOD_RANGED_DAMAGE_TAKEN_PCT implemented in Unit::MeleeDamageBonus &Aura::HandleNoImmediateEffect, //115 SPELL_AURA_MOD_HEALING implemented in Unit::SpellBaseHealingBonusForVictim - &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT + &Aura::HandleNoImmediateEffect, //116 SPELL_AURA_MOD_REGEN_DURING_COMBAT imppemented in Player::RegenerateAll and Player::RegenerateHealth &Aura::HandleNoImmediateEffect, //117 SPELL_AURA_MOD_MECHANIC_RESISTANCE implemented in Unit::MagicSpellHitResult &Aura::HandleNoImmediateEffect, //118 SPELL_AURA_MOD_HEALING_PCT implemented in Unit::SpellHealingBonus - &Aura::HandleUnused, //119 unused (3.0.8a) old SPELL_AURA_SHARE_PET_TRACKING + &Aura::HandleUnused, //119 unused (3.0.8a-3.2.2a) old SPELL_AURA_SHARE_PET_TRACKING &Aura::HandleAuraUntrackable, //120 SPELL_AURA_UNTRACKABLE &Aura::HandleAuraEmpathy, //121 SPELL_AURA_EMPATHY &Aura::HandleModOffhandDamagePercent, //122 SPELL_AURA_MOD_OFFHAND_DAMAGE_PCT @@ -194,27 +194,27 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleRangedAmmoHaste, //141 SPELL_AURA_MOD_RANGED_AMMO_HASTE &Aura::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT &Aura::HandleAuraModResistanceExclusive, //143 SPELL_AURA_MOD_RESISTANCE_EXCLUSIVE - &Aura::HandleAuraSafeFall, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes + &Aura::HandleAuraSafeFall, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes &Aura::HandleAuraModPetTalentsPoints, //145 SPELL_AURA_MOD_PET_TALENT_POINTS - &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE - &Aura::HandleModMechanicImmunityMask, //147 SPELL_AURA_ADD_CREATURE_IMMUNITY implemented in Unit::IsImmunedToSpell and Unit::IsImmunedToSpellEffect (check part) + &Aura::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE implemented in Player::CanTameExoticPets + &Aura::HandleModMechanicImmunityMask, //147 SPELL_AURA_MECHANIC_IMMUNITY_MASK implemented in Unit::IsImmunedToSpell and Unit::IsImmunedToSpellEffect (check part) &Aura::HandleAuraRetainComboPoints, //148 SPELL_AURA_RETAIN_COMBO_POINTS - &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK + &Aura::HandleNoImmediateEffect, //149 SPELL_AURA_REDUCE_PUSHBACK implemented in Spell::Delayed and Spell::DelayedChannel &Aura::HandleShieldBlockValue, //150 SPELL_AURA_MOD_SHIELD_BLOCKVALUE_PCT &Aura::HandleAuraTrackStealthed, //151 SPELL_AURA_TRACK_STEALTHED - &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance - &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT - &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL - &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING - &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN - &Aura::HandleNULL, //157 SPELL_AURA_PET_DAMAGE_MULTI + &Aura::HandleNoImmediateEffect, //152 SPELL_AURA_MOD_DETECTED_RANGE implemented in Creature::GetAttackDistance + &Aura::HandleNoImmediateEffect, //153 SPELL_AURA_SPLIT_DAMAGE_FLAT implemented in Unit::CalcAbsorbResist + &Aura::HandleNoImmediateEffect, //154 SPELL_AURA_MOD_STEALTH_LEVEL implemented in Unit::isVisibleForOrDetect + &Aura::HandleNoImmediateEffect, //155 SPELL_AURA_MOD_WATER_BREATHING implemented in Player::getMaxTimer + &Aura::HandleNoImmediateEffect, //156 SPELL_AURA_MOD_REPUTATION_GAIN implemented in Player::CalculateReputationGain + &Aura::HandleUnused, //157 SPELL_AURA_PET_DAMAGE_MULTI (single test like spell 20782, also single for 214 aura) &Aura::HandleShieldBlockValue, //158 SPELL_AURA_MOD_SHIELD_BLOCKVALUE - &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT only for Honorless Target spell - &Aura::HandleNoImmediateEffect, //160 SPELL_AURA_MOD_AOE_AVOIDANCE implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //161 SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT + &Aura::HandleNoImmediateEffect, //159 SPELL_AURA_NO_PVP_CREDIT implemented in Player::RewardHonor + &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 - &Aura::HandleUnused, //164 unused (3.0.8a), only one test spell + &Aura::HandleNoImmediateEffect, //163 SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE implememnted 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 &Aura::HandleAuraModRangedAttackPowerPercent, //167 SPELL_AURA_MOD_RANGED_ATTACK_POWER_PCT @@ -223,17 +223,17 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNULL, //170 SPELL_AURA_DETECT_AMORE different spells that ignore transformation effects &Aura::HandleAuraModIncreaseSpeed, //171 SPELL_AURA_MOD_SPEED_NOT_STACK &Aura::HandleAuraModIncreaseMountedSpeed, //172 SPELL_AURA_MOD_MOUNTED_SPEED_NOT_STACK - &Aura::HandleUnused, //173 unused (3.0.8a) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell + &Aura::HandleUnused, //173 unused (3.0.8a-3.2.2a) no spells, old SPELL_AURA_ALLOW_CHAMPION_SPELLS only for Proclaim Champion spell &Aura::HandleModSpellDamagePercentFromStat, //174 SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT implemented in Unit::SpellBaseDamageBonus &Aura::HandleModSpellHealingPercentFromStat, //175 SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT implemented in Unit::SpellBaseHealingBonus &Aura::HandleSpiritOfRedemption, //176 SPELL_AURA_SPIRIT_OF_REDEMPTION only for Spirit of Redemption spell, die at aura end - &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM + &Aura::HandleNULL, //177 SPELL_AURA_AOE_CHARM (22 spells) &Aura::HandleNoImmediateEffect, //178 SPELL_AURA_MOD_DEBUFF_RESISTANCE implemented in Unit::MagicSpellHitResult &Aura::HandleNoImmediateEffect, //179 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_CHANCE implemented in Unit::SpellCriticalBonus &Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus - &Aura::HandleUnused, //181 unused (3.0.8a) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS + &Aura::HandleUnused, //181 unused (3.0.8a-3.2.2a) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS &Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT - &Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746 + &Aura::HandleNoImmediateEffect, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746, implemented in ThreatCalcHelper::calcThreat &Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult @@ -244,41 +244,41 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModUseNormalSpeed, //191 SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED &Aura::HandleModMeleeRangedSpeedPct, //192 SPELL_AURA_HASTE_MELEE &Aura::HandleModCombatSpeedPct, //193 SPELL_AURA_MELEE_SLOW (in fact combat (any type attack) speed pct) - &Aura::HandleNULL, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL - &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL implement in Unit::CalculateSpellDamage - &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN + &Aura::HandleNoImmediateEffect, //194 SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL implement in Unit::CalcNotIgnoreAbsorbDamage + &Aura::HandleNoImmediateEffect, //195 SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL implement in Unit::CalcNotIgnoreAbsorbDamage + &Aura::HandleNULL, //196 SPELL_AURA_MOD_COOLDOWN (single spell 24818 in 3.2.2a) &Aura::HandleNoImmediateEffect, //197 SPELL_AURA_MOD_ATTACKER_SPELL_AND_WEAPON_CRIT_CHANCE implemented in Unit::SpellCriticalBonus Unit::GetUnitCriticalChance - &Aura::HandleUnused, //198 unused (3.0.8a) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS + &Aura::HandleUnused, //198 unused (3.0.8a-3.2.2a) old SPELL_AURA_MOD_ALL_WEAPON_SKILLS &Aura::HandleNoImmediateEffect, //199 SPELL_AURA_MOD_INCREASES_SPELL_PCT_TO_HIT implemented in Unit::MagicSpellHitResult - &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_XP_PCT implemented in Player::GiveXP + &Aura::HandleNoImmediateEffect, //200 SPELL_AURA_MOD_KILL_XP_PCT implemented in Player::GiveXP &Aura::HandleAuraAllowFlight, //201 SPELL_AURA_FLY this aura enable flight mode... &Aura::HandleNoImmediateEffect, //202 SPELL_AURA_CANNOT_BE_DODGED implemented in Unit::RollPhysicalOutcomeAgainst - &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage - &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::CalculateSpellDamage - &Aura::HandleNULL, //205 vulnerable to school dmg? + &Aura::HandleNoImmediateEffect, //203 SPELL_AURA_MOD_ATTACKER_MELEE_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::SpellCriticalDamageBonus + &Aura::HandleNoImmediateEffect, //204 SPELL_AURA_MOD_ATTACKER_RANGED_CRIT_DAMAGE implemented in Unit::CalculateMeleeDamage and Unit::SpellCriticalDamageBonus + &Aura::HandleNoImmediateEffect, //205 SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE implemented in Unit::SpellCriticalDamageBonus &Aura::HandleNULL, //206 SPELL_AURA_MOD_SPEED_MOUNTED &Aura::HandleAuraModIncreaseFlightSpeed, //207 SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED &Aura::HandleAuraModIncreaseFlightSpeed, //208 SPELL_AURA_MOD_SPEED_FLIGHT, used only in spell: Flight Form (Passive) &Aura::HandleAuraModIncreaseFlightSpeed, //209 SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS - &Aura::HandleNULL, //210 Commentator's Command + &Aura::HandleNULL, //210 "Increase flight speed by" &Aura::HandleAuraModIncreaseFlightSpeed, //211 SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK &Aura::HandleAuraModRangedAttackPowerOfStatPercent, //212 SPELL_AURA_MOD_RANGED_ATTACK_POWER_OF_STAT_PERCENT &Aura::HandleNoImmediateEffect, //213 SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT implemented in Player::RewardRage - &Aura::HandleNULL, //214 Tamed Pet Passive + &Aura::HandleUnused, //214 Tamed Pet Passive (single test like spell 20782, also single for 157 aura) &Aura::HandleArenaPreparation, //215 SPELL_AURA_ARENA_PREPARATION &Aura::HandleModCastingSpeed, //216 SPELL_AURA_HASTE_SPELLS - &Aura::HandleUnused, //217 unused (3.0.8a) + &Aura::HandleUnused, //217 unused (3.0.8a-3.2.2a) &Aura::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED &Aura::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT &Aura::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT &Aura::HandleNULL, //221 ignored - &Aura::HandleUnused, //222 unused (3.0.8a) only for spell 44586 that not used in real spell cast - &Aura::HandleNULL, //223 Cold Stare - &Aura::HandleUnused, //224 unused (3.0.8a) + &Aura::HandleUnused, //222 unused (3.0.8a-3.2.2a) only for spell 44586 that not used in real spell cast + &Aura::HandleNULL, //223 dummy code (cast damage spell to attacker) and another dymmy (jump to another nearby raid member) + &Aura::HandleUnused, //224 unused (3.0.8a-3.2.2a) &Aura::HandleNoImmediateEffect, //225 SPELL_AURA_PRAYER_OF_MENDING &Aura::HandleAuraPeriodicDummy, //226 SPELL_AURA_PERIODIC_DUMMY &Aura::HandlePeriodicTriggerSpellWithValue, //227 SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE - &Aura::HandleNoImmediateEffect, //228 stealth detection + &Aura::HandleNoImmediateEffect, //228 SPELL_AURA_DETECT_STEALTH &Aura::HandleNoImmediateEffect, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE implemented in Unit::SpellDamageBonus &Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout &Aura::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE @@ -292,11 +292,11 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleAuraModScale, //239 SPELL_AURA_MOD_SCALE_2 only in Noggenfogger Elixir (16595) before 2.3.0 aura 61 &Aura::HandleAuraModExpertise, //240 SPELL_AURA_MOD_EXPERTISE &Aura::HandleForceMoveForward, //241 Forces the player to move forward - &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING + &Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING (only 2 test spels in 3.2.2a) &Aura::HandleNULL, //243 faction reaction override spells - &Aura::HandleComprehendLanguage, //244 Comprehend language + &Aura::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE &Aura::HandleNULL, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS - &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL + &Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL implemented in Unit::CalculateSpellDuration &Aura::HandleNULL, //247 target to become a clone of the caster &Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst &Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE @@ -314,16 +314,16 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandlePhase, //261 SPELL_AURA_PHASE undetectable invisibility? implemented in Unit::isVisibleForOrDetect &Aura::HandleNULL, //262 ignore combat/aura state? &Aura::HandleNULL, //263 SPELL_AURA_ALLOW_ONLY_ABILITY player can use only abilities set in SpellClassMask - &Aura::HandleUnused, //264 unused (3.0.8a) - &Aura::HandleUnused, //265 unused (3.0.8a) - &Aura::HandleUnused, //266 unused (3.0.8a) + &Aura::HandleUnused, //264 unused (3.0.8a-3.2.2a) + &Aura::HandleUnused, //265 unused (3.0.8a-3.2.2a) + &Aura::HandleUnused, //266 unused (3.0.8a-3.2.2a) &Aura::HandleNoImmediateEffect, //267 SPELL_AURA_MOD_IMMUNE_AURA_APPLY_SCHOOL implemented in Unit::IsImmunedToSpellEffect &Aura::HandleAuraModAttackPowerOfStatPercent, //268 SPELL_AURA_MOD_ATTACK_POWER_OF_STAT_PERCENT - &Aura::HandleNULL, //269 ignore DR effects? - &Aura::HandleNULL, //270 SPELL_AURA_MOD_IGNORE_TARGET_RESIST + &Aura::HandleNoImmediateEffect, //269 SPELL_AURA_MOD_IGNORE_DAMAGE_REDUCTION_SCHOOL implemented in Unit::CalcNotIgnoreDamageRedunction + &Aura::HandleUnused, //270 SPELL_AURA_MOD_IGNORE_TARGET_RESIST (unused in 3.2.2a) &Aura::HandleNoImmediateEffect, //271 SPELL_AURA_MOD_DAMAGE_FROM_CASTER implemented in Unit::SpellDamageBonus &Aura::HandleNULL, //272 reduce spell cast time? - &Aura::HandleNULL, //273 x-ray effect + &Aura::HandleNoImmediateEffect, //273 SPELL_AURA_X_RAY (client side implementation) &Aura::HandleNULL, //274 proc free shot? &Aura::HandleNoImmediateEffect, //275 SPELL_AURA_MOD_IGNORE_SHAPESHIFT Use SpellClassMask for spell select &Aura::HandleNULL, //276 mod damage % mechanic? @@ -334,25 +334,25 @@ pAuraHandler AuraHandler[TOTAL_AURAS]= &Aura::HandleNoImmediateEffect, //281 SPELL_AURA_MOD_HONOR_GAIN implemented in Player::RewardHonor &Aura::HandleAuraIncreaseBaseHealthPercent, //282 SPELL_AURA_INCREASE_BASE_HEALTH_PERCENT &Aura::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus - &Aura::HandleUnused, //284 51 spells + &Aura::HandleNULL, //284 51 spells &Aura::HandleAuraModAttackPowerOfArmor, //285 SPELL_AURA_MOD_ATTACK_POWER_OF_ARMOR implemented in Player::UpdateAttackPowerAndDamage &Aura::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in Aura::IsCritFromAbilityAura called from Aura::PeriodicTick &Aura::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult - &Aura::HandleUnused, //288 increase parry/deflect, prevent attack - &Aura::HandleUnused, //289 unused + &Aura::HandleNULL, //288 increase parry/deflect, prevent attack (single spell used 67801) + &Aura::HandleUnused, //289 unused (3.2.2a) &Aura::HandleAuraModAllCritChance, //290 SPELL_AURA_MOD_ALL_CRIT_CHANCE - &Aura::HandleUnused, //291 1 spell (+pct experience bonus) + &Aura::HandleNoImmediateEffect, //291 SPELL_AURA_MOD_QUEST_XP_PCT implemented in Player::GiveXP &Aura::HandleNULL, //292 call stabled pet &Aura::HandleNULL, //293 3 spells &Aura::HandleNULL, //294 2 spells, possible prevent mana regen - &Aura::HandleNULL, //295 unused + &Aura::HandleUnused, //295 unused (3.2.2a) &Aura::HandleNULL, //296 2 spells &Aura::HandleNULL, //297 1 spell (counter spell school?) - &Aura::HandleNULL, //298 unused - &Aura::HandleNULL, //299 unused + &Aura::HandleUnused, //298 unused (3.2.2a) + &Aura::HandleUnused, //299 unused (3.2.2a) &Aura::HandleNULL, //300 3 spells (share damage?) &Aura::HandleNULL, //301 5 spells - &Aura::HandleNULL, //302 unused + &Aura::HandleUnused, //302 unused (3.2.2a) &Aura::HandleNULL, //303 17 spells &Aura::HandleNULL, //304 2 spells (alcohol effect?) &Aura::HandleNULL, //305 2 spells @@ -1575,8 +1575,13 @@ void Aura::TriggerSpell() // case 25041: break; // // Agro Drones // case 25152: break; -// // Consume -// case 25371: break; + // Consume + case 25371: + { + int32 bpDamage = target->GetMaxHealth()*10/100; + caster->CastCustomSpell(target, 25373, &bpDamage, NULL, NULL, true, NULL, this); + return; + } // // Pain Spike // case 25572: break; // // Rotate 360 @@ -2195,7 +2200,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real) case 1515: // Tame beast // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness if( caster && m_target->CanHaveThreatList()) - m_target->AddThreat(caster, 10.0f); + m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); return; case 13139: // net-o-matic // root to self part of (root_target->charge->root_self sequence @@ -4039,7 +4044,7 @@ void Aura::HandleAuraModTotalThreat(bool apply, bool Real) float threatMod = apply ? float(m_modifier.m_amount) : float(-m_modifier.m_amount); - m_target->getHostileRefManager().threatAssist(caster, threatMod); + m_target->getHostileRefManager().threatAssist(caster, threatMod, GetSpellProto()); } void Aura::HandleModTaunt(bool apply, bool Real) @@ -5759,6 +5764,37 @@ void Aura::HandleSpellSpecificBoosts(bool apply) } case SPELLFAMILY_PALADIN: { + if (m_spellProto->Id == 31884) // Avenging Wrath + { + if(!apply) + spellId1 = 57318; // Sanctified Wrath (triggered) + else + { + int32 percent = 0; + Unit::AuraList const& dummyAuras = m_target->GetAurasByType(SPELL_AURA_DUMMY); + for(Unit::AuraList::const_iterator itr = dummyAuras.begin(); itr != dummyAuras.end(); ++itr) + { + if ((*itr)->GetSpellProto()->SpellIconID == 3029) + { + percent = (*itr)->GetModifier()->m_amount; + break; + } + } + + // apply in special way + if(percent) + { + spellId1 = 57318; // Sanctified Wrath (triggered) + // prevent aura deletion, specially in multi-boost case + SetInUse(true); + m_target->CastCustomSpell(m_target, spellId1, &percent, &percent, NULL, true, NULL, this); + SetInUse(false); + } + return; + } + break; + } + // Only process on player casting paladin aura // all aura bonuses applied also in aura area effect way to caster if (GetCasterGUID() != m_target->GetGUID() || !IS_PLAYER_GUID(GetCasterGUID())) @@ -6311,6 +6347,10 @@ void Aura::PeriodicTick() // This method can modify pdamage bool isCrit = IsCritFromAbilityAura(pCaster, pdamage); + // send critical in hit info for threat calculation + if (isCrit) + cleanDamage.hitOutCome = MELEE_HIT_CRIT; + pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist); sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u", @@ -6556,7 +6596,7 @@ void Aura::PeriodicTick() if(gain_amount) { int32 gain = pCaster->ModifyPower(power, gain_amount); - m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); + m_target->AddThreat(pCaster, float(gain) * 0.5f, pInfo.critical, GetSpellSchoolMask(GetSpellProto()), GetSpellProto()); } break; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index db09186e1..902153aa8 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1043,6 +1043,31 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, spell_id, true, NULL); return; } + case 34665: //Administer Antidote + { + if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER ) + return; + // Spell has scriptable target but for sure. + if (unitTarget->GetTypeId() != TYPEID_UNIT) + return; + + uint32 health = unitTarget->GetHealth(); + float x, y, z, o; + + unitTarget->GetPosition(x, y, z); + o = unitTarget->GetOrientation(); + ((Creature*)unitTarget)->ForcedDespawn(); + + if (Creature* summon = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000)) + { + summon->SetHealth(health); + ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992, summon); + + if (summon->AI()) + summon->AI()->AttackStart(m_caster); + } + return; + } case 35745: // Socrethar's Stone { uint32 spell_id; @@ -1122,31 +1147,6 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 42337, true, NULL); return; } - case 34665: //Administer Antidote - { - if (!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER ) - return; - // Spell has scriptable target but for sure. - if (unitTarget->GetTypeId() != TYPEID_UNIT) - return; - - uint32 health = unitTarget->GetHealth(); - float x, y, z, o; - - unitTarget->GetPosition(x, y, z); - o = unitTarget->GetOrientation(); - ((Creature*)unitTarget)->ForcedDespawn(); - - if (Creature* summon = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000)) - { - summon->SetHealth(health); - ((Player*)m_caster)->RewardPlayerAndGroupAtEvent(16992, summon); - - if (summon->AI()) - summon->AI()->AttackStart(m_caster); - } - return; - } case 44997: // Converting Sentry { //Converted Sentry Credit @@ -1159,13 +1159,34 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 45088, true); return; } - case 55004: // Nitro Boosts - if (!m_CastItem) + case 49357: // Brewfest Mount Transformation + if (m_caster->GetTypeId() != TYPEID_PLAYER) return; - if (roll_chance_i(95)) // Nitro Boosts - success - m_caster->CastSpell(m_caster, 54861, true, m_CastItem); - else // Knocked Up - backfire 5% - m_caster->CastSpell(m_caster, 46014, true, m_CastItem); + + if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED)) + return; + + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + // Ram for Alliance, Kodo for Horde + if (((Player *)m_caster)->GetTeam() == ALLIANCE) + { + if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f) + // 100% Ram + m_caster->CastSpell(m_caster, 43900, true); + else + // 60% Ram + m_caster->CastSpell(m_caster, 43899, true); + } + else + { + if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f) + // 100% Kodo + m_caster->CastSpell(m_caster, 49379, true); + else + // 60% Kodo + m_caster->CastSpell(m_caster, 49378, true); + } return; case 50243: // Teach Language { @@ -1233,6 +1254,35 @@ void Spell::EffectDummy(uint32 i) return; m_caster->CastCustomSpell(unitTarget, 52752, &damage, NULL, NULL, true); return; + case 52845: // Brewfest Mount Transformation (Faction Swap) + if (m_caster->GetTypeId() != TYPEID_PLAYER) + return; + + if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED)) + return; + + m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); + + // Ram for Horde, Kodo for Alliance + if (((Player *)m_caster)->GetTeam() == HORDE) + { + if (m_caster->GetSpeedRate(MOVE_RUN) >= 2.0f) + // 100% Ram + m_caster->CastSpell(m_caster, 43900, true); + else + // 60% Ram + m_caster->CastSpell(m_caster, 43899, true); + } + else + { + if (((Player *)m_caster)->GetSpeedRate(MOVE_RUN) >= 2.0f) + // 100% Kodo + m_caster->CastSpell(m_caster, 49379, true); + else + // 60% Kodo + m_caster->CastSpell(m_caster, 49378, true); + } + return; case 53341: // Rune of Cinderglacier case 53343: // Rune of Razorice { @@ -1240,6 +1290,14 @@ void Spell::EffectDummy(uint32 i) m_caster->CastSpell(m_caster, 54586, true); return; } + case 55004: // Nitro Boosts + if (!m_CastItem) + return; + if (roll_chance_i(95)) // Nitro Boosts - success + m_caster->CastSpell(m_caster, 54861, true, m_CastItem); + else // Knocked Up - backfire 5% + m_caster->CastSpell(m_caster, 46014, true, m_CastItem); + return; case 58418: // Portal to Orgrimmar case 58420: // Portal to Stormwind return; // implemented in EffectScript[0] @@ -3840,7 +3898,7 @@ void Spell::EffectAddHonor(uint32 /*i*/) if (m_CastItem) { ((Player*)unitTarget)->RewardHonor(NULL, 1, damage / 10); - sLog.outError("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow()); + sLog.outDebug("SpellEffect::AddHonor (spell_id %u) rewards %d honor points (item %u) for player: %u", m_spellInfo->Id, damage/10, m_CastItem->GetEntry(),((Player*)unitTarget)->GetGUIDLow()); return; } @@ -4097,35 +4155,23 @@ void Spell::EffectEnchantItemTmp(uint32 i) void Spell::EffectTameCreature(uint32 /*i*/) { - if(m_caster->GetPetGUID()) - return; - - if(!unitTarget) - return; - - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - return; + // Caster must be player, checked in Spell::CheckCast + Player* plr = (Player*)m_caster; Creature* creatureTarget = (Creature*)unitTarget; - if(creatureTarget->isPet()) - return; - - if(m_caster->getClass() != CLASS_HUNTER) - return; - // cast finish successfully //SendChannelUpdate(0); finish(); - Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id); + Pet* pet = plr->CreateTamedPetFrom(creatureTarget, m_spellInfo->Id); if(!pet) // in versy specific state like near world end/etc. return; // "kill" original creature creatureTarget->ForcedDespawn(); - uint32 level = (creatureTarget->getLevel() < (m_caster->getLevel() - 5)) ? (m_caster->getLevel() - 5) : creatureTarget->getLevel(); + uint32 level = (creatureTarget->getLevel() < (plr->getLevel() - 5)) ? (plr->getLevel() - 5) : creatureTarget->getLevel(); // prepare visual effect for levelup pet->SetUInt32Value(UNIT_FIELD_LEVEL, level - 1); @@ -4137,13 +4183,10 @@ void Spell::EffectTameCreature(uint32 /*i*/) pet->SetUInt32Value(UNIT_FIELD_LEVEL, level); // caster have pet now - m_caster->SetPet(pet); + plr->SetPet(pet); - if(m_caster->GetTypeId() == TYPEID_PLAYER) - { - pet->SavePetToDB(PET_SAVE_AS_CURRENT); - ((Player*)m_caster)->PetSpellInitialize(); - } + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + plr->PetSpellInitialize(); } void Spell::EffectSummonPet(uint32 i) @@ -4681,7 +4724,7 @@ void Spell::EffectThreat(uint32 /*i*/) if(!unitTarget->CanHaveThreatList()) return; - unitTarget->AddThreat(m_caster, float(damage)); + unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo); } void Spell::EffectHealMaxHealth(uint32 /*i*/) diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 8df296ca2..544a84079 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -438,7 +438,8 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex) // some explicitly required dummy effect sets switch(spellId) { - case 28441: return false; // AB Effect 000 + case 28441: // AB Effect 000 + return false; default: break; } @@ -469,6 +470,7 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex) case 38638: // Nether Exhaustion (green) case 38639: // Nether Exhaustion (blue) case 11196: // Recently Bandaged + case 44689: // Relay Race Accept Hidden Debuff - DND return false; // some spells have unclear target modes for selection, so just make effect positive case 27184: diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 342456f08..f8675224c 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -203,8 +203,7 @@ inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto) inline bool IsDeathOnlySpell(SpellEntry const *spellInfo) { return spellInfo->AttributesEx3 & SPELL_ATTR_EX3_CAST_ON_DEAD - || spellInfo->Id == 2584 - || spellInfo->Id == 22011; + || spellInfo->Id == 2584; } inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo) diff --git a/src/game/StatSystem.cpp b/src/game/StatSystem.cpp index 32dc01b1d..af573e88a 100644 --- a/src/game/StatSystem.cpp +++ b/src/game/StatSystem.cpp @@ -840,8 +840,8 @@ void Creature::UpdateDamagePhysical(WeaponAttackType attType) float weapon_mindamage = GetWeaponDamageRange(BASE_ATTACK, MINDAMAGE); float weapon_maxdamage = GetWeaponDamageRange(BASE_ATTACK, MAXDAMAGE); - float mindamage = ((base_value + weapon_mindamage) * base_pct + total_value) * total_pct * dmg_multiplier; - float maxdamage = ((base_value + weapon_maxdamage) * base_pct + total_value) * total_pct * dmg_multiplier; + float mindamage = ((base_value + weapon_mindamage) * dmg_multiplier * base_pct + total_value) * total_pct; + float maxdamage = ((base_value + weapon_maxdamage) * dmg_multiplier * base_pct + total_value) * total_pct; SetStatFloatValue(UNIT_FIELD_MINDAMAGE, mindamage); SetStatFloatValue(UNIT_FIELD_MAXDAMAGE, maxdamage); diff --git a/src/game/ThreatManager.cpp b/src/game/ThreatManager.cpp index a8802d4d9..11b560482 100644 --- a/src/game/ThreatManager.cpp +++ b/src/game/ThreatManager.cpp @@ -30,12 +30,21 @@ //============================================================== // The pHatingUnit is not used yet -float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) +float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) { + // all flat mods applied early + if(!pThreat) + return 0.0f; + if (pThreatSpell) + { if (Player* modOwner = pHatedUnit->GetSpellModOwner()) modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, pThreat); + if(crit) + pThreat *= pHatedUnit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRITICAL_THREAT,schoolMask); + } + float threat = pHatedUnit->ApplyTotalThreatModifier(pThreat, schoolMask); return threat; } @@ -357,7 +366,7 @@ void ThreatManager::clearReferences() //============================================================ -void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) +void ThreatManager::addThreat(Unit* pVictim, float pThreat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell) { //function deals with adding threat and adding players and pets into ThreatList //mobs, NPCs, guards have ThreatList and HateOfflineList @@ -378,7 +387,7 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask scho assert(getOwner()->GetTypeId()== TYPEID_UNIT); - float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, schoolMask, pThreatSpell); + float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, crit, schoolMask, pThreatSpell); HostileReference* ref = iThreatContainer.addThreat(pVictim, threat); // Ref is not in the online refs, search the offline refs next diff --git a/src/game/ThreatManager.h b/src/game/ThreatManager.h index 55460304c..7c8cf23fb 100644 --- a/src/game/ThreatManager.h +++ b/src/game/ThreatManager.h @@ -39,7 +39,7 @@ struct SpellEntry; class ThreatCalcHelper { public: - static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell); }; //============================================================== @@ -176,7 +176,8 @@ class MANGOS_DLL_SPEC ThreatManager void clearReferences(); - void addThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + void addThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell); + void addThreat(Unit* pVictim, float threat) { addThreat(pVictim,threat,false,SPELL_SCHOOL_MASK_NONE,NULL); } void modifyThreatPercent(Unit *pVictim, int32 pPercent); float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false); diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index b28159b2b..6518b56c6 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -761,9 +761,9 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa if (pVictim->GetTypeId() != TYPEID_PLAYER) { if(spellProto && IsDamageToThreatSpell(spellProto)) - pVictim->AddThreat(this, damage*2, damageSchoolMask, spellProto); + pVictim->AddThreat(this, damage*2, (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto); else - pVictim->AddThreat(this, damage, damageSchoolMask, spellProto); + pVictim->AddThreat(this, damage, (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto); } else // victim is a player { @@ -1060,7 +1060,10 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S damage = SpellCriticalDamageBonus(spellInfo, damage, pVictim); // Resilience - reduce crit damage if (pVictim->GetTypeId()==TYPEID_PLAYER) - damage -= ((Player*)pVictim)->GetMeleeCritDamageReduction(damage); + { + uint32 redunction_affected_damage = CalcNotIgnoreDamageRedunction(damage,damageSchoolMask); + damage -= ((Player*)pVictim)->GetMeleeCritDamageReduction(redunction_affected_damage); + } } } break; @@ -1077,21 +1080,30 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S damage = SpellCriticalDamageBonus(spellInfo, damage, pVictim); // Resilience - reduce crit damage if (pVictim->GetTypeId()==TYPEID_PLAYER) - damage -= ((Player*)pVictim)->GetSpellCritDamageReduction(damage); + { + uint32 redunction_affected_damage = CalcNotIgnoreDamageRedunction(damage,damageSchoolMask); + damage -= ((Player*)pVictim)->GetSpellCritDamageReduction(redunction_affected_damage); + } } } break; } if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER) - damage -= ((Player*)pVictim)->GetSpellDamageReduction(damage); + { + uint32 redunction_affected_damage = CalcNotIgnoreDamageRedunction(damage,damageSchoolMask); + damage -= ((Player*)pVictim)->GetSpellDamageReduction(redunction_affected_damage); + } // damage mitigation - if(damage > 0) + if (damage > 0) { // physical damage => armor - if ( damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL ) - damage = CalcArmorReducedDamage(pVictim, damage); + if (damageSchoolMask & SPELL_SCHOOL_MASK_NORMAL) + { + uint32 armor_affected_damage = CalcNotIgnoreDamageRedunction(damage,damageSchoolMask); + damage = damage - armor_affected_damage + CalcArmorReducedDamage(pVictim, armor_affected_damage); + } // block (only for damage class ranged and -melee, also non-physical damage possible) if (blocked) @@ -1102,21 +1114,9 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S damage-=damageInfo->blocked; } - // absorb/resist: lookup ignore auras on caster for spell - bool ignore = false; - Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL); - for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i) - if ((*i)->isAffectedOnSpell(spellInfo)) - { - ignore = true; - break; - } - - if (!ignore) - { - CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, damage, &damageInfo->absorb, &damageInfo->resist); - damage-= damageInfo->absorb + damageInfo->resist; - } + uint32 absorb_affected_damage = CalcNotIgnoreAbsorbDamage(damage,damageSchoolMask,spellInfo); + CalcAbsorbResist(pVictim, damageSchoolMask, SPELL_DIRECT_DAMAGE, absorb_affected_damage, &damageInfo->absorb, &damageInfo->resist); + damage-= damageInfo->absorb + damageInfo->resist; } else damage = 0; @@ -1125,7 +1125,7 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) { - if (damageInfo==0) + if (!damageInfo) return; Unit *pVictim = damageInfo->target; @@ -1152,8 +1152,8 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss) return; } - // Call default DealDamage - CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL); + // Call default DealDamage (send critical in hit info for threat calculation) + CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT ? MELEE_HIT_CRIT : MELEE_HIT_NORMAL); DealDamage(pVictim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss); } @@ -1205,7 +1205,7 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da } // Physical Immune check - if(damageInfo->target->IsImmunedToDamage(SpellSchoolMask(damageInfo->damageSchoolMask))) + if (damageInfo->target->IsImmunedToDamage(damageInfo->damageSchoolMask)) { damageInfo->HitInfo |= HITINFO_NORMALSWING; damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE; @@ -1219,13 +1219,15 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da // Add melee damage bonus damage = MeleeDamageBonus(damageInfo->target, damage, damageInfo->attackType); // Calculate armor reduction - damageInfo->damage = CalcArmorReducedDamage(damageInfo->target, damage); + + uint32 armor_affected_damage = CalcNotIgnoreDamageRedunction(damage,damageInfo->damageSchoolMask); + damageInfo->damage = damage - armor_affected_damage + CalcArmorReducedDamage(damageInfo->target, armor_affected_damage); damageInfo->cleanDamage += damage - damageInfo->damage; damageInfo->hitOutCome = RollMeleeOutcomeAgainst(damageInfo->target, damageInfo->attackType); // Disable parry or dodge for ranged attack - if(damageInfo->attackType == RANGED_ATTACK) + if (damageInfo->attackType == RANGED_ATTACK) { if (damageInfo->hitOutCome == MELEE_HIT_PARRY) damageInfo->hitOutCome = MELEE_HIT_NORMAL; if (damageInfo->hitOutCome == MELEE_HIT_DODGE) damageInfo->hitOutCome = MELEE_HIT_MISS; @@ -1285,7 +1287,8 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da // Resilience - reduce crit damage if (pVictim->GetTypeId()==TYPEID_PLAYER) { - uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(damageInfo->damage); + uint32 redunction_affected_damage = CalcNotIgnoreDamageRedunction(damageInfo->damage,damageInfo->damageSchoolMask); + uint32 resilienceReduction = ((Player*)pVictim)->GetMeleeCritDamageReduction(redunction_affected_damage); damageInfo->damage -= resilienceReduction; damageInfo->cleanDamage += resilienceReduction; } @@ -1389,18 +1392,21 @@ void Unit::CalculateMeleeDamage(Unit *pVictim, uint32 damage, CalcDamageInfo *da if (GetTypeId() == TYPEID_PLAYER && pVictim->GetTypeId() == TYPEID_PLAYER) { + uint32 redunction_affected_damage = CalcNotIgnoreDamageRedunction(damage,damageInfo->damageSchoolMask); if (attackType != RANGED_ATTACK) - damage-=((Player*)pVictim)->GetMeleeDamageReduction(damage); + damage-=((Player*)pVictim)->GetMeleeDamageReduction(redunction_affected_damage); else - damage-=((Player*)pVictim)->GetRangedDamageReduction(damage); + damage-=((Player*)pVictim)->GetRangedDamageReduction(redunction_affected_damage); } // Calculate absorb resist if(int32(damageInfo->damage) > 0) { damageInfo->procVictim |= PROC_FLAG_TAKEN_ANY_DAMAGE; + // Calculate absorb & resists - CalcAbsorbResist(damageInfo->target, SpellSchoolMask(damageInfo->damageSchoolMask), DIRECT_DAMAGE, damageInfo->damage, &damageInfo->absorb, &damageInfo->resist); + uint32 absorb_affected_damage = CalcNotIgnoreAbsorbDamage(damageInfo->damage,damageInfo->damageSchoolMask); + CalcAbsorbResist(damageInfo->target, damageInfo->damageSchoolMask, DIRECT_DAMAGE, absorb_affected_damage, &damageInfo->absorb, &damageInfo->resist); damageInfo->damage-=damageInfo->absorb + damageInfo->resist; if (damageInfo->absorb) { @@ -1479,7 +1485,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo *damageInfo, bool durabilityLoss) // Call default DealDamage CleanDamage cleanDamage(damageInfo->cleanDamage,damageInfo->attackType,damageInfo->hitOutCome); - DealDamage(pVictim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->damageSchoolMask), NULL, durabilityLoss); + DealDamage(pVictim, damageInfo->damage, &cleanDamage, DIRECT_DAMAGE, damageInfo->damageSchoolMask, NULL, durabilityLoss); // If this is a creature and it attacks from behind it has a probability to daze it's victim if( (damageInfo->hitOutCome==MELEE_HIT_CRIT || damageInfo->hitOutCome==MELEE_HIT_CRUSHING || damageInfo->hitOutCome==MELEE_HIT_NORMAL || damageInfo->hitOutCome==MELEE_HIT_GLANCING) && @@ -1558,6 +1564,36 @@ void Unit::HandleEmoteCommand(uint32 anim_id) SendMessageToSet(&data, true); } +uint32 Unit::CalcNotIgnoreAbsorbDamage( uint32 damage, SpellSchoolMask damageSchoolMask, SpellEntry const* spellInfo /*= NULL*/) +{ + float absorb_affected_rate = 1.0f; + Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_SCHOOL); + for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i) + if ((*i)->GetMiscValue() & damageSchoolMask) + absorb_affected_rate *= (100.0f - (*i)->GetModifier()->m_amount)/100.0f; + + if(spellInfo) + { + Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_ABSORB_FOR_SPELL); + for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i) + if ((*i)->isAffectedOnSpell(spellInfo)) + absorb_affected_rate *= (100.0f - (*i)->GetModifier()->m_amount)/100.0f; + } + + return absorb_affected_rate <= 0.0f ? 0 : (absorb_affected_rate < 1.0f ? uint32(damage * absorb_affected_rate) : damage); +} + +uint32 Unit::CalcNotIgnoreDamageRedunction( uint32 damage, SpellSchoolMask damageSchoolMask) +{ + float absorb_affected_rate = 1.0f; + Unit::AuraList const& ignoreAbsorb = GetAurasByType(SPELL_AURA_MOD_IGNORE_DAMAGE_REDUCTION_SCHOOL); + for(Unit::AuraList::const_iterator i = ignoreAbsorb.begin(); i != ignoreAbsorb.end(); ++i) + if ((*i)->GetMiscValue() & damageSchoolMask) + absorb_affected_rate *= (100.0f - (*i)->GetModifier()->m_amount)/100.0f; + + return absorb_affected_rate <= 0.0f ? 0 : (absorb_affected_rate < 1.0f ? uint32(damage * absorb_affected_rate) : damage); +} + uint32 Unit::CalcArmorReducedDamage(Unit* pVictim, const uint32 damage) { uint32 newdamage = 0; @@ -2157,6 +2193,8 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack // Reduce dodge chance by attacker expertise rating if (GetTypeId() == TYPEID_PLAYER) dodge_chance -= int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType)*100); + else + dodge_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE)*25; // Modify dodge chance by attacker SPELL_AURA_MOD_COMBAT_RESULT_CHANCE dodge_chance+= GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_COMBAT_RESULT_CHANCE, VICTIMSTATE_DODGE); @@ -2183,6 +2221,8 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit *pVictim, WeaponAttack // Reduce parry chance by attacker expertise rating if (GetTypeId() == TYPEID_PLAYER) parry_chance-= int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType)*100); + else + parry_chance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE)*25; if(pVictim->GetTypeId()==TYPEID_PLAYER || !(((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_PARRY) ) { @@ -2527,6 +2567,8 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell) // Reduce dodge chance by attacker expertise rating if (GetTypeId() == TYPEID_PLAYER) dodgeChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f); + else + dodgeChance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE)*25; if (dodgeChance < 0) dodgeChance = 0; @@ -2542,6 +2584,8 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit *pVictim, SpellEntry const *spell) // Reduce parry chance by attacker expertise rating if (GetTypeId() == TYPEID_PLAYER) parryChance-=int32(((Player*)this)->GetExpertiseDodgeOrParryReduction(attType) * 100.0f); + else + parryChance -= GetTotalAuraModifier(SPELL_AURA_MOD_EXPERTISE)*25; if (parryChance < 0) parryChance = 0; @@ -8707,6 +8751,9 @@ uint32 Unit::SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damag critPctDamageMod += GetTotalAuraModifier(SPELL_AURA_MOD_CRIT_DAMAGE_BONUS_MELEE); } } + else + critPctDamageMod += pVictim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_CRIT_DAMAGE,GetSpellSchoolMask(spellProto)); + uint32 creatureTypeMask = pVictim->GetCreatureTypeMask(); critPctDamageMod += GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRIT_PERCENT_VERSUS, creatureTypeMask); @@ -9556,7 +9603,8 @@ bool Unit::isTargetableForAttack(bool inverseAlive /*=false*/) const if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) return false; - if (!(isAlive() != inverseAlive)) + // target is dead or has ghost-flag + if ((!isAlive() || (GetTypeId() == TYPEID_UNIT && ((Creature *)this)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GHOST)) != inverseAlive) return false; return IsInWorld() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; @@ -9845,7 +9893,7 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo //-Stealth Mod(positive like Master of Deception) and Stealth Detection(negative like paranoia) //based on wowwiki every 5 mod we have 1 more level diff in calculation - visibleDistance += (int32(u->GetTotalAuraModifier(SPELL_AURA_MOD_DETECT)) - stealthMod)/5.0f; + visibleDistance += (int32(u->GetTotalAuraModifier(SPELL_AURA_MOD_STEALTH_DETECT)) - stealthMod)/5.0f; visibleDistance = visibleDistance > MAX_PLAYER_STEALTH_DETECT_RANGE ? MAX_PLAYER_STEALTH_DETECT_RANGE : visibleDistance; // recheck new distance @@ -10196,7 +10244,10 @@ bool Unit::CanHaveThreatList() const float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask) { - if(!HasAuraType(SPELL_AURA_MOD_THREAT)) + if (!HasAuraType(SPELL_AURA_MOD_THREAT)) + return threat; + + if (schoolMask == SPELL_SCHOOL_MASK_NONE) return threat; SpellSchools school = GetFirstSchoolInMask(schoolMask); @@ -10206,11 +10257,11 @@ float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask) //====================================================================== -void Unit::AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask, SpellEntry const *threatSpell) +void Unit::AddThreat(Unit* pVictim, float threat /*= 0.0f*/, bool crit /*= false*/, SpellSchoolMask schoolMask /*= SPELL_SCHOOL_MASK_NONE*/, SpellEntry const *threatSpell /*= NULL*/) { // Only mobs can manage threat lists if(CanHaveThreatList()) - m_ThreatManager.addThreat(pVictim, threat, schoolMask, threatSpell); + m_ThreatManager.addThreat(pVictim, threat, crit, schoolMask, threatSpell); } //====================================================================== diff --git a/src/game/Unit.h b/src/game/Unit.h index b1787d6f7..48d53db0b 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -637,7 +637,7 @@ struct CalcDamageInfo { Unit *attacker; // Attacker Unit *target; // Target for damage - uint32 damageSchoolMask; + SpellSchoolMask damageSchoolMask; uint32 damage; uint32 absorb; uint32 resist; @@ -1336,7 +1336,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject // Threat related methods bool CanHaveThreatList() const; - void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL); + void AddThreat(Unit* pVictim, float threat = 0.0f, bool crit = false, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NONE, SpellEntry const *threatSpell = NULL); float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); void DeleteThreatList(); bool SelectHostileTarget(); @@ -1468,6 +1468,9 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void _ApplyAllAuraMods(); int32 CalculateSpellDamage(SpellEntry const* spellProto, uint8 effect_index, int32 basePoints, Unit const* target); + + uint32 CalcNotIgnoreAbsorbDamage( uint32 damage, SpellSchoolMask damageSchoolMask, SpellEntry const* spellInfo = NULL); + uint32 CalcNotIgnoreDamageRedunction( uint32 damage, SpellSchoolMask damageSchoolMask); int32 CalculateSpellDuration(SpellEntry const* spellProto, uint8 effect_index, Unit const* target); float CalculateLevelPenalty(SpellEntry const* spellProto) const; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 1d5d1cedf..d993e1e04 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 "8656" + #define REVISION_NR "8677" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h index ddf639c65..55c964243 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_8596_01_characters_bugreport" - #define REVISION_DB_MANGOS "required_8618_01_mangos_spell_proc_event" + #define REVISION_DB_MANGOS "required_8676_01_mangos_creature_template" #define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters" #endif // __REVISION_SQL_H__