Merge branch 'master' of github.com:joschiwald/TrinityCore into spellscripts

Conflicts:
	src/server/game/Entities/Unit/Unit.cpp
	src/server/game/Spells/Auras/SpellAuraEffects.cpp
	src/server/game/Spells/Spell.cpp
	src/server/game/Spells/SpellEffects.cpp
	src/server/scripts/Spells/spell_paladin.cpp
This commit is contained in:
joschiwald
2012-05-28 04:27:51 +02:00
385 changed files with 3728 additions and 1813 deletions
+7 -80
View File
@@ -23,7 +23,7 @@
#include "World.h"
#include "CreatureAIImpl.h"
int GuardAI::Permissible(const Creature* creature)
int GuardAI::Permissible(Creature const* creature)
{
if (creature->isGuard())
return PERMIT_BASE_SPECIAL;
@@ -31,7 +31,7 @@ int GuardAI::Permissible(const Creature* creature)
return PERMIT_BASE_NO;
}
GuardAI::GuardAI(Creature* creature) : ScriptedAI(creature), i_victimGuid(0), i_state(STATE_NORMAL), i_tracker(TIME_INTERVAL_LOOK)
GuardAI::GuardAI(Creature* creature) : ScriptedAI(creature)
{
}
@@ -40,108 +40,35 @@ bool GuardAI::CanSeeAlways(WorldObject const* obj)
if (!obj->isType(TYPEMASK_UNIT))
return false;
std::list<HostileReference*> t_list = me->getThreatManager().getThreatList();
for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr)
{
if (Unit* unit = Unit::GetUnit(*me, (*itr)->getUnitGuid()))
if (unit == obj)
return true;
}
std::list<HostileReference*> threatList = me->getThreatManager().getThreatList();
for (std::list<HostileReference*>::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
if ((*itr)->getUnitGuid() == obj->GetGUID())
return true;
return false;
}
void GuardAI::MoveInLineOfSight(Unit* unit)
{
// Ignore Z for flying creatures
if (!me->CanFly() && me->GetDistanceZ(unit) > CREATURE_Z_ATTACK_RANGE)
return;
if (!me->getVictim() && me->IsValidAttackTarget(unit) &&
(unit->IsHostileToPlayers() || me->IsHostileTo(unit)) &&
unit->isInAccessiblePlaceFor(me))
{
float attackRadius = me->GetAttackDistance(unit);
if (me->IsWithinDistInMap(unit, attackRadius))
{
//Need add code to let guard support player
AttackStart(unit);
//u->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
}
}
}
void GuardAI::EnterEvadeMode()
{
if (!me->isAlive())
{
sLog->outStaticDebug("Creature stopped attacking because he is dead [guid=%u]", me->GetGUIDLow());
me->GetMotionMaster()->MoveIdle();
i_state = STATE_NORMAL;
i_victimGuid = 0;
me->CombatStop(true);
me->DeleteThreatList();
return;
}
Unit* victim = ObjectAccessor::GetUnit(*me, i_victimGuid);
if (!victim)
{
sLog->outStaticDebug("Creature stopped attacking because victim does not exist [guid=%u]", me->GetGUIDLow());
}
else if (!victim->isAlive())
{
sLog->outStaticDebug("Creature stopped attacking because victim is dead [guid=%u]", me->GetGUIDLow());
}
else if (victim->HasStealthAura())
{
sLog->outStaticDebug("Creature stopped attacking because victim is using stealth [guid=%u]", me->GetGUIDLow());
}
else if (victim->isInFlight())
{
sLog->outStaticDebug("Creature stopped attacking because victim is flying away [guid=%u]", me->GetGUIDLow());
}
else
{
sLog->outStaticDebug("Creature stopped attacking because victim outran him [guid=%u]", me->GetGUIDLow());
}
sLog->outDebug(LOG_FILTER_UNITS, "Guard entry: %u enters evade mode.", me->GetEntry());
me->RemoveAllAuras();
me->DeleteThreatList();
i_victimGuid = 0;
me->CombatStop(true);
i_state = STATE_NORMAL;
// Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
me->GetMotionMaster()->MoveTargetedHome();
}
void GuardAI::UpdateAI(const uint32 /*diff*/)
{
// update i_victimGuid if me->getVictim() !=0 and changed
if (!UpdateVictim())
return;
Unit* const victim = me->getVictim();
if (!victim)
return;
i_victimGuid = victim->GetGUID();
if (me->isAttackReady())
{
if (me->IsWithinMeleeRange(victim))
{
me->AttackerStateUpdate(victim);
me->resetAttackTimer();
}
}
}
void GuardAI::JustDied(Unit* killer)
{
if (Player* player = killer->GetCharmerOrOwnerPlayerOrPlayerItself())
+4 -19
View File
@@ -20,34 +20,19 @@
#define TRINITY_GUARDAI_H
#include "ScriptedCreature.h"
#include "Timer.h"
class Creature;
class GuardAI : public ScriptedAI
{
enum GuardState
{
STATE_NORMAL = 1,
STATE_LOOK_AT_VICTIM = 2
};
public:
explicit GuardAI(Creature* creature);
explicit GuardAI(Creature* c);
void MoveInLineOfSight(Unit*);
void EnterEvadeMode();
void JustDied(Unit*);
static int Permissible(Creature const* creature);
bool CanSeeAlways(WorldObject const* obj);
void UpdateAI(const uint32);
static int Permissible(const Creature*);
private:
uint64 i_victimGuid;
GuardState i_state;
TimeTracker i_tracker;
void EnterEvadeMode();
void JustDied(Unit* killer);
};
#endif
+35 -19
View File
@@ -153,40 +153,56 @@ void PetAI::UpdateAI(const uint32 diff)
if (spellInfo->IsPositive())
{
// non combat spells allowed
// only pet spells have IsNonCombatSpell and not fit this reqs:
// Consume Shadows, Lesser Invisibility, so ignore checks for its
if (spellInfo->CanBeUsedInCombat())
{
// allow only spell without spell cost or with spell cost but not duration limit
int32 duration = spellInfo->GetDuration();
if ((spellInfo->ManaCost || spellInfo->ManaCostPercentage || spellInfo->ManaPerSecond) && duration > 0)
// check spell cooldown
if (me->HasSpellCooldown(spellInfo->Id))
continue;
// allow only spell without cooldown > duration
int32 cooldown = spellInfo->GetRecoveryTime();
if (cooldown >= 0 && duration >= 0 && cooldown > duration)
// Check if we're in combat or commanded to attack
if (!me->isInCombat() && !me->GetCharmInfo()->IsCommandAttack())
continue;
}
Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE, 0);
bool spellUsed = false;
for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
// Some spells can target enemy or friendly (DK Ghoul's Leap)
// Check for enemy first (pet then owner)
Unit* target = me->getAttackerForHelper();
if (!target && owner)
target = owner->getAttackerForHelper();
if (target)
{
Unit* target = ObjectAccessor::GetUnit(*me, *tar);
//only buff targets that are in combat, unless the spell can only be cast while out of combat
if (!target)
continue;
if (spell->CanAutoCast(target))
if (CanAttack(target) && spell->CanAutoCast(target))
{
targetSpellStore.push_back(std::make_pair(target, spell));
spellUsed = true;
break;
}
}
// No enemy, check friendly
if (!spellUsed)
{
for (std::set<uint64>::const_iterator tar = m_AllySet.begin(); tar != m_AllySet.end(); ++tar)
{
Unit* ally = ObjectAccessor::GetUnit(*me, *tar);
//only buff targets that are in combat, unless the spell can only be cast while out of combat
if (!ally)
continue;
if (spell->CanAutoCast(ally))
{
targetSpellStore.push_back(std::make_pair(ally, spell));
spellUsed = true;
break;
}
}
}
// No valid targets at all
if (!spellUsed)
delete spell;
}
@@ -383,7 +383,7 @@ void npc_escortAI::FillPointMovementListForCreature()
if (movePoints.empty())
return;
ScriptPointVector::const_iterator itrEnd = movePoints.end();;
ScriptPointVector::const_iterator itrEnd = movePoints.end();
for (ScriptPointVector::const_iterator itr = movePoints.begin(); itr != itrEnd; ++itr)
{
Escort_Waypoint point(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime);
+3 -3
View File
@@ -804,12 +804,12 @@ void SmartAI::SetFollow(Unit* target, float dist, float angle, uint32 credit, ui
return;
SetRun(mRun);
mFollowGuid = target->GetGUID();
mFollowDist = dist ? dist : PET_FOLLOW_DIST;
mFollowAngle = angle ? angle : me->GetFollowAngle();
mFollowDist = dist >= 0.0f ? dist : PET_FOLLOW_DIST;
mFollowAngle = angle >= 0.0f ? angle : me->GetFollowAngle();
mFollowArrivedTimer = 1000;
mFollowCredit = credit;
mFollowArrivedEntry = end;
me->GetMotionMaster()->MoveFollow(target, dist, angle);
me->GetMotionMaster()->MoveFollow(target, mFollowDist, mFollowAngle);
mFollowCreditType = creditType;
}
@@ -1925,7 +1925,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
}
default:
sLog->outErrorDb("SmartScript::ProcessAction: Unhandled Action type %u", e.GetActionType());
sLog->outErrorDb("SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break;
}
@@ -324,7 +324,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
sLog->outErrorDb("SmartAIMgr: EntryOrGuid %d, event type %u can not be used for Script type %u", e.entryOrGuid, e.GetEventType(), e.GetScriptType());
return false;
}
if (e.action.type >= SMART_ACTION_END)
if (e.action.type <= 0 || e.action.type >= SMART_ACTION_END)
{
sLog->outErrorDb("SmartAIMgr: EntryOrGuid %d using event(%u) has invalid action type (%u), skipped.", e.entryOrGuid, e.event_id, e.GetActionType());
return false;
@@ -334,6 +334,11 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
sLog->outErrorDb("SmartAIMgr: EntryOrGuid %d using event(%u) has invalid phase mask (%u), skipped.", e.entryOrGuid, e.event_id, e.event.event_phase_mask);
return false;
}
if (e.event.event_flags > SMART_EVENT_FLAGS_ALL)
{
sLog->outErrorDb("SmartAIMgr: EntryOrGuid %d using event(%u) has invalid event flags (%u), skipped.", e.entryOrGuid, e.event_id, e.event.event_flags);
return false;
}
if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST)
{
e.event.type = SMART_EVENT_UPDATE_OOC;//force default OOC, can change when calling the script!
@@ -1175,7 +1175,8 @@ enum SmartEventFlags
SMART_EVENT_FLAG_DEBUG_ONLY = 0x080, //Event only occurs in debug build
SMART_EVENT_FLAG_DONT_RESET = 0x100, //Event will not reset in SmartScript::OnReset()
SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0|SMART_EVENT_FLAG_DIFFICULTY_1|SMART_EVENT_FLAG_DIFFICULTY_2|SMART_EVENT_FLAG_DIFFICULTY_3)
SMART_EVENT_FLAG_DIFFICULTY_ALL = (SMART_EVENT_FLAG_DIFFICULTY_0|SMART_EVENT_FLAG_DIFFICULTY_1|SMART_EVENT_FLAG_DIFFICULTY_2|SMART_EVENT_FLAG_DIFFICULTY_3),
SMART_EVENT_FLAGS_ALL = (SMART_EVENT_FLAG_NOT_REPEATABLE|SMART_EVENT_FLAG_DIFFICULTY_ALL|SMART_EVENT_FLAG_RESERVED_5|SMART_EVENT_FLAG_RESERVED_6|SMART_EVENT_FLAG_DEBUG_ONLY|SMART_EVENT_FLAG_DONT_RESET)
};
enum SmartCastFlags
+1 -1
View File
@@ -267,7 +267,7 @@ bool ArenaTeam::LoadMembersFromDB(QueryResult result)
if (Empty() || !captainPresentInTeam)
{
// Arena team is empty or captain is not in team, delete from db
sLog->outErrorDb("ArenaTeam %u does not have any members or its captain is not in team, disbanding it...", TeamId);
sLog->outDebug(LOG_FILTER_BATTLEGROUND, "ArenaTeam %u does not have any members or its captain is not in team, disbanding it...", TeamId);
return false;
}
@@ -550,7 +550,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
if (dist >= maxDist)
{
sLog->outError("BATTLEGROUND: Sending %s back to start location (possible exploit)", plr->GetName());
sLog->outError("BATTLEGROUND: Sending %s back to start location (map: %u) (possible exploit)", plr->GetName(), GetMapId());
plr->TeleportTo(GetMapId(), x, y, z, o);
}
}
@@ -850,9 +850,12 @@ void Battleground::EndBattleground(uint32 winner)
if (team == winner)
{
// update achievement BEFORE personal rating update
ArenaTeamMember* member = winner_arena_team->GetMember(player->GetGUID());
if (member)
player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, 1);
if (ArenaTeamMember* member = winner_arena_team->GetMember(player->GetGUID()))
{
uint32 rating = player->GetArenaPersonalRating(winner_arena_team->GetSlot());
player->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA,
rating ? rating : 1);
}
winner_arena_team->MemberWon(player, loser_matchmaker_rating, winner_matchmaker_change);
}
@@ -290,7 +290,7 @@ int32 BattlegroundAB::_GetNodeNameId(uint8 node)
case BG_AB_NODE_LUMBER_MILL:return LANG_BG_AB_NODE_LUMBER_MILL;
case BG_AB_NODE_GOLD_MINE: return LANG_BG_AB_NODE_GOLD_MINE;
default:
ASSERT(0);
ASSERT(false);
}
return 0;
}
@@ -720,8 +720,13 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
DelCreature(BG_SA_MAXNPC + i);
GraveyardStatus[i] = Source->GetTeamId();
WorldSafeLocsEntry const* sg = NULL;
sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
WorldSafeLocsEntry const* sg = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
if (!sg)
{
sLog->outError("BattlegroundSA::CaptureGraveyard: non-existant GY entry: %u", BG_SA_GYEntries[i]);
return;
}
AddSpiritGuide(i + BG_SA_MAXNPC, sg->x, sg->y, sg->z, BG_SA_GYOrientation[i], (GraveyardStatus[i] == TEAM_ALLIANCE? ALLIANCE : HORDE));
uint32 npc = 0;
uint32 flag = 0;
@@ -781,7 +786,7 @@ void BattlegroundSA::CaptureGraveyard(BG_SA_Graveyards i, Player* Source)
SendWarningToAll(LANG_BG_SA_H_GY_SOUTH);
break;
default:
ASSERT(0);
ASSERT(false);
break;
};
}
+11 -13
View File
@@ -95,9 +95,9 @@ CalendarEventIdList const& CalendarMgr::GetPlayerEvents(uint64 guid)
CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId)
{
CalendarInviteMap::iterator it = _invites.find(inviteId);
if (it != _invites.end())
return &(it->second);
CalendarInviteMap::iterator itr = _invites.find(inviteId);
if (itr != _invites.end())
return &(itr->second);
sLog->outError("CalendarMgr::GetInvite: [" UI64FMTD "] not found!", inviteId);
return NULL;
@@ -105,9 +105,9 @@ CalendarInvite* CalendarMgr::GetInvite(uint64 inviteId)
CalendarEvent* CalendarMgr::GetEvent(uint64 eventId)
{
CalendarEventMap::iterator it = _events.find(eventId);
if (it != _events.end())
return &(it->second);
CalendarEventMap::iterator itr = _events.find(eventId);
if (itr != _events.end())
return &(itr->second);
sLog->outError("CalendarMgr::GetEvent: [" UI64FMTD "] not found!", eventId);
return NULL;
@@ -316,11 +316,6 @@ void CalendarMgr::AddAction(CalendarAction const& action)
if (!calendarEvent)
return;
CalendarInviteIdList const& inviteIds = calendarEvent->GetInviteIdList();
for (CalendarInviteIdList::const_iterator it = inviteIds.begin(); it != inviteIds.end(); ++it)
if (uint64 invitee = RemoveInvite(*it))
SendCalendarEventRemovedAlert(invitee, *calendarEvent);
RemoveEvent(eventId);
break;
}
@@ -464,8 +459,6 @@ bool CalendarMgr::RemoveEvent(uint64 eventId)
return false;
}
_events.erase(itr);
bool val = true;
CalendarInviteIdList const& invites = itr->second.GetInviteIdList();
@@ -474,8 +467,13 @@ bool CalendarMgr::RemoveEvent(uint64 eventId)
CalendarInvite* invite = GetInvite(*itrInvites);
if (!invite || !RemovePlayerEvent(invite->GetInvitee(), eventId))
val = false;
if (uint64 invitee = RemoveInvite(*itrInvites))
SendCalendarEventRemovedAlert(invitee, itr->second);
}
_events.erase(itr);
return val;
}
+1
View File
@@ -535,6 +535,7 @@ void ThreatManager::processThreatEvent(ThreatRefStatusChangeEvent* threatRefStat
setCurrentVictim(NULL);
setDirty(true);
}
iOwner->SendRemoveFromThreatListOpcode(hostilRef);
iThreatContainer.remove(hostilRef);
iThreatOfflineContainer.addReference(hostilRef);
}
+1 -1
View File
@@ -190,7 +190,7 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
}
case CONDITION_OBJECT_ENTRY:
{
if (object->GetTypeId() == ConditionValue1)
if (uint32(object->GetTypeId()) == ConditionValue1)
condMeets = (!ConditionValue2) || (object->GetEntry() == ConditionValue2);
break;
}
+2 -2
View File
@@ -245,7 +245,7 @@ enum AreaFlags
AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
AREA_FLAG_OUTLAND = 0x00000400, // expansion zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
AREA_FLAG_NEED_FLY = 0x00001000, // Unknown
AREA_FLAG_NEED_FLY = 0x00001000, // Respawn alive at the graveyard without corpse
AREA_FLAG_UNUSED1 = 0x00002000, // Unused in 3.3.5a
AREA_FLAG_OUTLAND2 = 0x00004000, // expansion zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
AREA_FLAG_OUTDOOR_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
@@ -260,7 +260,7 @@ enum AreaFlags
AREA_FLAG_WINTERGRASP = 0x01000000, // Wintergrasp and it's subzones
AREA_FLAG_INSIDE = 0x02000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
AREA_FLAG_OUTSIDE = 0x04000000, // used for determinating spell related inside/outside questions in Map::IsOutdoors
AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Same as AREA_FLAG_WINTERGRASP except for The Sunken Ring and Western Bridge.
AREA_FLAG_WINTERGRASP_2 = 0x08000000, // Can Hearth And Resurrect From Area
AREA_FLAG_NO_FLY_ZONE = 0x20000000 // Marks zones where you cannot fly
};
@@ -468,9 +468,9 @@ void Creature::Update(uint32 diff)
switch (m_deathState)
{
case JUST_ALIVED:
// Must not be called, see Creature::setDeathState JUST_ALIVED -> ALIVE promoting.
sLog->outError("Creature (GUID: %u Entry: %u) in wrong state: JUST_ALIVED (4)", GetGUIDLow(), GetEntry());
case JUST_RESPAWNED:
// Must not be called, see Creature::setDeathState JUST_RESPAWNED -> ALIVE promoting.
sLog->outError("Creature (GUID: %u Entry: %u) in wrong state: JUST_RESPAWNED (4)", GetGUIDLow(), GetEntry());
break;
case JUST_DIED:
// Must not be called, see Creature::setDeathState JUST_DIED -> CORPSE promoting.
@@ -1555,7 +1555,7 @@ void Creature::setDeathState(DeathState s)
Unit::setDeathState(CORPSE);
}
else if (s == JUST_ALIVED)
else if (s == JUST_RESPAWNED)
{
//if (isPet())
// setActive(true);
@@ -1611,7 +1611,7 @@ void Creature::Respawn(bool force)
CreatureTemplate const* cinfo = GetCreatureTemplate();
SelectLevel(cinfo);
setDeathState(JUST_ALIVED);
setDeathState(JUST_RESPAWNED);
uint32 displayID = GetNativeDisplayId();
CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID);
@@ -1668,8 +1668,8 @@ bool Creature::IsImmunedToSpell(SpellInfo const* spellInfo)
if (!spellInfo)
return false;
// Spells that don't have effectMechanics.
if (!spellInfo->HasAnyEffectMechanic() && GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1)))
// Creature is immune to main mechanic of the spell
if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1)))
return true;
// This check must be done instead of 'if (GetCreatureTemplate()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1)))' for not break
@@ -1910,6 +1910,7 @@ void GameObject::SetLootState(LootState state, Unit* unit)
{
m_lootState = state;
AI()->OnStateChanged(state, unit);
sScriptMgr->OnGameObjectLootStateChanged(this, state, unit);
if (m_model)
{
// startOpen determines whether we are going to add or remove the LoS on activation
@@ -1929,6 +1930,7 @@ void GameObject::SetLootState(LootState state, Unit* unit)
void GameObject::SetGoState(GOState state)
{
SetByteValue(GAMEOBJECT_BYTES_1, 0, state);
sScriptMgr->OnGameObjectStateChanged(this, state);
if (m_model)
{
if (!IsInWorld())
+22 -11
View File
@@ -10157,7 +10157,8 @@ uint32 Player::GetItemCount(uint32 item, bool inBankAlso, Item* skipItem) const
if (inBankAlso)
{
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i)
// checking every item from 39 to 74 (including bank bags)
for (uint8 i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
if (pItem != skipItem && pItem->GetEntry() == item)
count += pItem->GetCount();
@@ -10197,7 +10198,7 @@ uint32 Player::GetItemCountWithLimitCategory(uint32 limitCategory, Item* skipIte
if (Bag* pBag = GetBagByPos(i))
count += pBag->GetItemCountWithLimitCategory(limitCategory, skipItem);
for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i)
for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
if (pItem != skipItem)
if (ItemTemplate const* pProto = pItem->GetTemplate())
@@ -10223,7 +10224,7 @@ Item* Player::GetItemByGuid(uint64 guid) const
if (pItem->GetGUID() == guid)
return pItem;
for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_ITEM_END; ++i)
for (int i = BANK_SLOT_ITEM_START; i < BANK_SLOT_BAG_END; ++i)
if (Item* pItem = GetItemByPos(INVENTORY_SLOT_BAG_0, i))
if (pItem->GetGUID() == guid)
return pItem;
@@ -12019,7 +12020,7 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
Map const* map = lootedObject->GetMap();
if (uint32 dungeonId = sLFGMgr->GetDungeon(GetGroup()->GetGUID(), true))
if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId))
if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == map->GetDifficulty())
if (uint32(dungeon->map) == map->GetId() && dungeon->difficulty == uint32(map->GetDifficulty()))
lootedObjectInDungeon = true;
if (!lootedObjectInDungeon)
@@ -12180,11 +12181,6 @@ Item* Player::StoreNewItem(ItemPosCountVec const& dest, uint32 item, bool update
pItem->SetItemRandomProperties(randomPropertyId);
pItem = StoreItem(dest, pItem, update);
const ItemTemplate* proto = pItem->GetTemplate();
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger
CastSpell(this, proto->Spells[i].SpellId, true, pItem);
if (allowedLooters.size() > 1 && pItem->GetTemplate()->GetMaxStackSize() == 1 && pItem->IsSoulBound())
{
pItem->SetSoulboundTradeable(allowedLooters);
@@ -12290,6 +12286,14 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool
AddEnchantmentDurations(pItem);
AddItemDurations(pItem);
const ItemTemplate* proto = pItem->GetTemplate();
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger
if (bag == INVENTORY_SLOT_BAG_0 || (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END))
if (!HasAura(proto->Spells[i].SpellId))
CastSpell(this, proto->Spells[i].SpellId, true, pItem);
return pItem;
}
else
@@ -12326,6 +12330,13 @@ Item* Player::_StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool
pItem2->SetState(ITEM_CHANGED, this);
const ItemTemplate* proto = pItem2->GetTemplate();
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
if (proto->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_NO_DELAY_USE && proto->Spells[i].SpellId > 0) // On obtain trigger
if (bag == INVENTORY_SLOT_BAG_0 || (bag >= INVENTORY_SLOT_BAG_START && bag < INVENTORY_SLOT_BAG_END))
if (!HasAura(proto->Spells[i].SpellId))
CastSpell(this, proto->Spells[i].SpellId, true, pItem2);
return pItem2;
}
}
@@ -17658,7 +17669,7 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
}
else
if (IsBagPos(item->GetPos()))
if (Bag* pBag = item->ToBag())
if (item->IsBag())
invalidBagMap[item->GetGUIDLow()] = item;
}
else
@@ -17811,7 +17822,7 @@ Item* Player::_LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, F
GameEventMgr::ActiveEvents const& activeEventsList = sGameEventMgr->GetActiveEventList();
for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
{
if (events[*itr].holiday_id == proto->HolidayId)
if (uint32(events[*itr].holiday_id) == proto->HolidayId)
{
remove = false;
break;
+142 -148
View File
@@ -954,7 +954,7 @@ uint32 Unit::SpellNonMeleeDamageLog(Unit* victim, uint32 spellID, uint32 damage)
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID);
SpellNonMeleeDamage damageInfo(this, victim, spellInfo->Id, spellInfo->SchoolMask);
damage = SpellDamageBonusDone(victim, spellInfo, damage, SPELL_DIRECT_DAMAGE);
damage = victim->SpellDamageBonusTaken(spellInfo, damage, SPELL_DIRECT_DAMAGE);
damage = victim->SpellDamageBonusTaken(this, spellInfo, damage, SPELL_DIRECT_DAMAGE);
CalculateSpellDamageTaken(&damageInfo, damage, spellInfo);
DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
@@ -1151,7 +1151,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, uint32 damage, CalcDamageInfo* dam
damage += CalculateDamage(damageInfo->attackType, false, true);
// Add melee damage bonus
damage = MeleeDamageBonusDone(damageInfo->target, damage, damageInfo->attackType);
damage = MeleeDamageBonusTaken(damage, damageInfo->attackType);
damage = damageInfo->target->MeleeDamageBonusTaken(this, damage, damageInfo->attackType);
// Calculate armor reduction
if (IsDamageReducedByArmor((SpellSchoolMask)(damageInfo->damageSchoolMask)))
@@ -1405,7 +1405,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
if (Unit* caster = (*dmgShieldItr)->GetCaster())
{
damage = caster->SpellDamageBonusDone(this, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
damage = this->SpellDamageBonusTaken(i_spellProto, damage, SPELL_DIRECT_DAMAGE);
damage = this->SpellDamageBonusTaken(caster, i_spellProto, damage, SPELL_DIRECT_DAMAGE);
}
// No Unit::CalcAbsorbResist here - opcode doesn't send that data - this damage is probably not affected by that
@@ -5789,7 +5789,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (AuraEffect* aurEff = victim->GetAuraEffect(64413, 0, GetGUID()))
{
// The shield can grow to a maximum size of 20, 000 damage absorbtion
aurEff->SetAmount(std::max<int32>(aurEff->GetAmount() + basepoints0, 20000));
aurEff->SetAmount(std::min<int32>(aurEff->GetAmount() + basepoints0, 20000));
// Refresh and return to prevent replacing the aura
aurEff->GetBase()->RefreshDuration();
@@ -7285,30 +7285,16 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (procSpell->SpellIconID != 2019)
return false;
AuraEffect* aurEffA = NULL;
AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE);
for (AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
if (Creature* totem = GetMap()->GetCreature(m_SummonSlot[1])) // Fire totem summon slot
{
SpellInfo const* spell = (*i)->GetSpellInfo();
if (spell->SpellFamilyName == uint32(SPELLFAMILY_SHAMAN) && spell->SpellFamilyFlags.HasFlag(0, 0x02000000, 0))
if (SpellInfo const* totemSpell = sSpellMgr->GetSpellInfo(totem->m_spells[0]))
{
if ((*i)->GetCasterGUID() != GetGUID())
continue;
if (spell->Id == 63283)
continue;
aurEffA = (*i);
break;
int32 bp0 = CalculatePctN(totemSpell->Effects[EFFECT_0].CalcValue(), triggerAmount);
int32 bp1 = CalculatePctN(totemSpell->Effects[EFFECT_1].CalcValue(), triggerAmount);
CastCustomSpell(this, 63283, &bp0, &bp1, NULL, true);
return true;
}
}
if (aurEffA)
{
int32 bp0 = 0, bp1 = 0;
bp0 = CalculatePctN(triggerAmount, aurEffA->GetAmount());
if (AuraEffect* aurEffB = aurEffA->GetBase()->GetEffect(EFFECT_1))
bp1 = CalculatePctN(triggerAmount, aurEffB->GetAmount());
CastCustomSpell(this, 63283, &bp0, &bp1, NULL, true, NULL, triggeredByAura);
return true;
}
return false;
}
break;
@@ -7705,17 +7691,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
}
}
}
// Item - Death Knight T10 Melee 4P Bonus
if (dummySpell->Id == 70656)
{
Player* player = ToPlayer();
if (!player)
return false;
for (uint32 i = 0; i < MAX_RUNES; ++i)
if (player->GetRuneCooldown(i) == 0)
return false;
}
break;
}
case SPELLFAMILY_POTION:
@@ -7983,7 +7958,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
*handled = true;
if (victim && victim->HasAura(53601))
{
int32 bp0 = CalculatePctN(int32(damage / 12), dummySpell->Effects[EFFECT_2]. CalcValue());
int32 bp0 = CalculatePctN(int32(damage / 12), dummySpell->Effects[EFFECT_2].CalcValue());
// Item - Paladin T9 Holy 4P Bonus
if (AuraEffect const* aurEff = GetAuraEffect(67191, 0))
AddPctN(bp0, aurEff->GetAmount());
@@ -8643,6 +8618,16 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
trigger_spell_id = 50475;
basepoints0 = CalculatePctN(int32(damage), triggerAmount);
}
// Item - Death Knight T10 Melee 4P Bonus
else if (auraSpellInfo->Id == 70656)
{
if (GetTypeId() != TYPEID_PLAYER || getClass() != CLASS_DEATH_KNIGHT)
return false;
for (uint8 i = 0; i < MAX_RUNES; ++i)
if (ToPlayer()->GetRuneCooldown(i) == 0)
return false;
}
break;
}
case SPELLFAMILY_ROGUE:
@@ -10125,7 +10110,7 @@ Unit* Unit::GetFirstControlled() const
// Sequence: charmed, pet, other guardians
Unit* unit = GetCharm();
if (!unit)
if (uint64 guid = GetUInt64Value(UNIT_FIELD_SUMMON))
if (uint64 guid = GetMinionGUID())
unit = ObjectAccessor::GetUnit(*this, guid);
return unit;
@@ -10326,20 +10311,24 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (GetTypeId() == TYPEID_UNIT && !ToCreature()->isPet())
DoneTotalMod *= ToCreature()->GetSpellDamageMod(ToCreature()->GetCreatureTemplate()->rank);
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
// Some spells don't benefit from pct done mods
if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && !spellProto->IsRankOf(sSpellMgr->GetSpellInfo(12162)))
{
if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
continue;
if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
{
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
AddPctN(DoneTotalMod, (*i)->GetAmount());
else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
AddPctN(DoneTotalMod, (*i)->GetAmount());
else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
AddPctN(DoneTotalMod, (*i)->GetAmount());
if (spellProto->EquippedItemClass == -1 && (*i)->GetSpellInfo()->EquippedItemClass != -1) //prevent apply mods from weapon specific case to non weapon specific spells (Example: thunder clap and two-handed weapon specialization)
continue;
if ((*i)->GetMiscValue() & spellProto->GetSchoolMask())
{
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
AddPctN(DoneTotalMod, (*i)->GetAmount());
else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
AddPctN(DoneTotalMod, (*i)->GetAmount());
else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
AddPctN(DoneTotalMod, (*i)->GetAmount());
}
}
}
@@ -10519,7 +10508,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
break;
}
}
break;
break;
case SPELLFAMILY_PRIEST:
// Mind Flay
if (spellProto->SpellFamilyFlags[0] & 0x800000)
@@ -10552,7 +10541,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (victim->HasAuraState(AURA_STATE_HEALTHLESS_35_PERCENT))
AddPctN(DoneTotalMod, aurEff->GetAmount());
}
break;
break;
case SPELLFAMILY_PALADIN:
// Judgement of Vengeance/Judgement of Corruption
if ((spellProto->SpellFamilyFlags[1] & 0x400000) && spellProto->SpellIconID == 2292)
@@ -10570,7 +10559,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (stacks)
AddPctU(DoneTotalMod, 10 * stacks);
}
break;
break;
case SPELLFAMILY_DRUID:
// Thorns
if (spellProto->SpellFamilyFlags[0] & 0x100)
@@ -10579,7 +10568,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (AuraEffect* aurEff = GetAuraEffectOfRankedSpell(16836, 0))
AddPctN(DoneTotalMod, aurEff->GetAmount());
}
break;
break;
case SPELLFAMILY_WARLOCK:
// Fire and Brimstone
if (spellProto->SpellFamilyFlags[1] & 0x00020040)
@@ -10601,14 +10590,14 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (spellProto->SpellFamilyFlags[1] & 0x00400000 && isPet())
if (uint8 count = victim->GetDoTsByCaster(GetOwnerGUID()))
AddPctN(DoneTotalMod, 15 * count);
break;
break;
case SPELLFAMILY_HUNTER:
// Steady Shot
if (spellProto->SpellFamilyFlags[1] & 0x1)
if (AuraEffect* aurEff = GetAuraEffect(56826, 0)) // Glyph of Steady Shot
if (victim->GetAuraEffect(SPELL_AURA_PERIODIC_DAMAGE, SPELLFAMILY_HUNTER, 0x00004000, 0, 0, GetGUID()))
AddPctN(DoneTotalMod, aurEff->GetAmount());
break;
break;
case SPELLFAMILY_DEATHKNIGHT:
// Improved Icy Touch
if (spellProto->SpellFamilyFlags[0] & 0x2)
@@ -10649,7 +10638,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
}
}
}
break;
break;
}
// Done fixed damage bonus auras
@@ -10670,7 +10659,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (bonus->ap_dot_bonus > 0)
{
WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
float APbonus = (float) victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS);
float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
APbonus += GetTotalAttackPowerValue(attType);
DoneTotal += int32(bonus->ap_dot_bonus * stack * ApCoeffMod * APbonus);
}
@@ -10681,7 +10670,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
if (bonus->ap_bonus > 0)
{
WeaponAttackType attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK;
float APbonus = (float) victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS);
float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS));
APbonus += GetTotalAttackPowerValue(attType);
DoneTotal += int32(bonus->ap_bonus * stack * ApCoeffMod * APbonus);
}
@@ -10711,12 +10700,6 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotalMod = 1.0f;
}
// Some spells don't benefit from pct done mods
// maybe should be implemented like SPELL_ATTR3_NO_DONE_BONUS,
// but then it may break spell power coeffs work on spell 31117
if (spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS)
DoneTotalMod = 1.0f;
float tmpDamage = (int32(pdamage) + DoneTotal) * DoneTotalMod;
// apply spellmod to Done damage (flat and pct)
if (Player* modOwner = GetSpellModOwner())
@@ -10725,7 +10708,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
return uint32(std::max(tmpDamage, 0.0f));
}
uint32 Unit::SpellDamageBonusTaken(SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack)
{
if (!spellProto || damagetype == DIRECT_DAMAGE)
return pdamage;
@@ -10733,11 +10716,11 @@ uint32 Unit::SpellDamageBonusTaken(SpellInfo const* spellProto, uint32 pdamage,
int32 TakenTotal = 0;
float TakenTotalMod = 1.0f;
//from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
//multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085)
// from positive and negative SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN
// multiplicative bonus, for example Dispersion + Shadowform (0.10*0.85=0.085)
TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, spellProto->GetSchoolMask());
//.. taken pct: dummy auras
//.. taken pct: dummy auras
AuraEffectList const& mDummyAuras = GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (AuraEffectList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
{
@@ -10759,7 +10742,7 @@ uint32 Unit::SpellDamageBonusTaken(SpellInfo const* spellProto, uint32 pdamage,
// From caster spells
AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
if ((*i)->GetCasterGUID() == GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
if ((*i)->GetCasterGUID() == caster->GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
AddPctN(TakenTotalMod, (*i)->GetAmount());
// Mod damage from spell mechanic
@@ -10796,7 +10779,7 @@ uint32 Unit::SpellDamageBonusTaken(SpellInfo const* spellProto, uint32 pdamage,
TakenTotal+= int32(TakenAdvertisedBenefit * coeff * factorMod);
}
float tmpDamage = (pdamage + TakenTotal) * TakenTotalMod;
float tmpDamage = (float(pdamage) + TakenTotal) * TakenTotalMod;
return uint32(std::max(tmpDamage, 0.0f));
}
@@ -10837,7 +10820,7 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask)
DoneAdvertisedBenefit += int32(CalculatePctN(GetTotalAttackPowerValue(BASE_ATTACK), (*i)->GetAmount()));
}
return DoneAdvertisedBenefit > 0 ? DoneAdvertisedBenefit : 0;
return DoneAdvertisedBenefit;
}
int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask)
@@ -10849,7 +10832,7 @@ int32 Unit::SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask)
if (((*i)->GetMiscValue() & schoolMask) != 0)
TakenAdvertisedBenefit += (*i)->GetAmount();
return TakenAdvertisedBenefit > 0 ? TakenAdvertisedBenefit : 0;
return TakenAdvertisedBenefit;
}
bool Unit::isSpellCrit(Unit* victim, SpellInfo const* spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType) const
@@ -11116,16 +11099,16 @@ uint32 Unit::SpellCriticalHealingBonus(SpellInfo const* spellProto, uint32 damag
uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack)
{
// For totems get healing bonus from owner (statue isn't totem in fact)
if (GetTypeId() == TYPEID_UNIT && ToCreature()->isTotem())
if (GetTypeId() == TYPEID_UNIT && isTotem())
if (Unit* owner = GetOwner())
return owner->SpellHealingBonusDone(victim, spellProto, healamount, damagetype, stack);
// no bonus for heal potions/bandages
// No bonus healing for potion spells
if (spellProto->SpellFamilyName == SPELLFAMILY_POTION)
return healamount;
float DoneTotalMod = 1.0f;
int32 DoneTotal = 0;
float DoneTotalMod = 1.0f;
int32 DoneTotal = 0;
// Healing done percent
AuraEffectList const& mHealingDonePct = GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_DONE_PERCENT);
@@ -11189,7 +11172,7 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
}
// Done fixed damage bonus auras
int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask());
int32 DoneAdvertisedBenefit = SpellBaseHealingBonusDone(spellProto->GetSchoolMask());
// Check for table values
SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id);
@@ -11202,16 +11185,22 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
coeff = bonus->dot_damage;
if (bonus->ap_dot_bonus > 0)
DoneTotal += int32(bonus->ap_dot_bonus * stack * GetTotalAttackPowerValue(
(spellProto->IsRangedWeaponSpell() && spellProto->DmgClass !=SPELL_DAMAGE_CLASS_MELEE)? RANGED_ATTACK : BASE_ATTACK));
(spellProto->IsRangedWeaponSpell() && spellProto->DmgClass !=SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
}
else
{
coeff = bonus->direct_damage;
if (bonus->ap_bonus > 0)
DoneTotal += int32(bonus->ap_bonus * stack * GetTotalAttackPowerValue(
(spellProto->IsRangedWeaponSpell() && spellProto->DmgClass !=SPELL_DAMAGE_CLASS_MELEE)? RANGED_ATTACK : BASE_ATTACK));
(spellProto->IsRangedWeaponSpell() && spellProto->DmgClass !=SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK));
}
}
else
{
// No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default
if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
return healamount;
}
// Default calculation
if (DoneAdvertisedBenefit)
@@ -11228,23 +11217,21 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
coeff /= 100.0f;
}
// Gift of the Naaru
if (spellProto->SpellFamilyFlags[2] & 0x80000000 && spellProto->SpellIconID == 329)
{
int32 apBonus = int32(std::max(GetTotalAttackPowerValue(BASE_ATTACK), GetTotalAttackPowerValue(RANGED_ATTACK)));
if (apBonus > DoneAdvertisedBenefit)
DoneTotal += int32(apBonus * 0.22f); // 22% of AP per tick
else
DoneTotal += int32(DoneAdvertisedBenefit * 0.377f); // 37.7% of BH per tick
}
else
{
// Earthliving - 0.45% of normal hot coeff
if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000)
// Earthliving - 0.45% of normal hot coeff
if (spellProto->SpellFamilyName == SPELLFAMILY_SHAMAN && spellProto->SpellFamilyFlags[1] & 0x80000)
factorMod *= 0.45f;
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
// Gift of the Naaru
if (spellProto->SpellFamilyFlags[2] & 0x80000000 && spellProto->SpellIconID == 329)
{
int32 apBonus = int32(std::max(GetTotalAttackPowerValue(BASE_ATTACK), GetTotalAttackPowerValue(RANGED_ATTACK)));
if (apBonus > DoneAdvertisedBenefit)
DoneTotal += int32(apBonus * 0.22f); // 22% of AP per tick
else
DoneTotal += int32(DoneAdvertisedBenefit * 0.377f); // 37.7% of BH per tick
}
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -11258,11 +11245,11 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
break;
}
if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH)
DoneTotal = 0;
DoneTotal = 0;
}
// use float as more appropriate for negative values and percent applying
float heal = (int32(healamount) + DoneTotal) * DoneTotalMod;
float heal = float(int32(healamount) + DoneTotal) * DoneTotalMod;
// apply spellmod to Done amount
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
@@ -11270,16 +11257,16 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
return uint32(std::max(heal, 0.0f));
}
uint32 Unit::SpellHealingBonusTaken(SpellInfo const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack)
uint32 Unit::SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack)
{
float TakenTotalMod = 1.0f;
float TakenTotalMod = 1.0f;
// Healing taken percent
float minval = (float)GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
float minval = float(GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
if (minval)
AddPctF(TakenTotalMod, minval);
float maxval = (float)GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT);
float maxval = float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HEALING_PCT));
if (maxval)
AddPctF(TakenTotalMod, maxval);
@@ -11288,7 +11275,7 @@ uint32 Unit::SpellHealingBonusTaken(SpellInfo const *spellProto, uint32 healamou
AddPctN(TakenTotalMod, Tenacity->GetAmount());
// Healing Done
int32 TakenTotal = 0;
int32 TakenTotal = 0;
// Taken fixed damage bonus auras
int32 TakenAdvertisedBenefit = SpellBaseHealingBonusTaken(spellProto->GetSchoolMask());
@@ -11305,11 +11292,11 @@ uint32 Unit::SpellHealingBonusTaken(SpellInfo const *spellProto, uint32 healamou
if (damagetype == DOT)
{
// Healing over time taken percent
float minval_hot = (float)GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT);
float minval_hot = float(GetMaxNegativeAuraModifier(SPELL_AURA_MOD_HOT_PCT));
if (minval_hot)
AddPctF(TakenTotalMod, minval_hot);
float maxval_hot = (float)GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT);
float maxval_hot = float(GetMaxPositiveAuraModifier(SPELL_AURA_MOD_HOT_PCT));
if (maxval_hot)
AddPctF(TakenTotalMod, maxval_hot);
}
@@ -11320,6 +11307,15 @@ uint32 Unit::SpellHealingBonusTaken(SpellInfo const *spellProto, uint32 healamou
float factorMod = 1.0f;
if (bonus)
coeff = (damagetype == DOT) ? bonus->dot_damage : bonus->direct_damage;
else
{
// No bonus healing for SPELL_DAMAGE_CLASS_NONE class spells by default
if (spellProto->DmgClass == SPELL_DAMAGE_CLASS_NONE)
{
healamount = uint32(std::max((float(healamount) * TakenTotalMod), 0.0f));
return healamount;
}
}
// Default calculation
if (TakenAdvertisedBenefit)
@@ -11344,7 +11340,7 @@ uint32 Unit::SpellHealingBonusTaken(SpellInfo const *spellProto, uint32 healamou
AuraEffectList const& mHealingGet= GetAuraEffectsByType(SPELL_AURA_MOD_HEALING_RECEIVED);
for (AuraEffectList::const_iterator i = mHealingGet.begin(); i != mHealingGet.end(); ++i)
if (GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectedOnSpell(spellProto))
if (caster->GetGUID() == (*i)->GetCasterGUID() && (*i)->IsAffectedOnSpell(spellProto))
AddPctN(TakenTotalMod, (*i)->GetAmount());
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -11358,10 +11354,10 @@ uint32 Unit::SpellHealingBonusTaken(SpellInfo const *spellProto, uint32 healamou
break;
}
if (spellProto->Effects[i].Effect == SPELL_EFFECT_HEALTH_LEECH)
TakenTotal = 0;
TakenTotal = 0;
}
float heal = (int32(healamount) + TakenTotal) * TakenTotalMod;
float heal = float(int32(healamount) + TakenTotal) * TakenTotalMod;
return uint32(std::max(heal, 0.0f));
}
@@ -11434,7 +11430,7 @@ bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo)
return false;
uint32 shoolMask = spellInfo->GetSchoolMask();
if (spellInfo->Id != 42292 && spellInfo->Id !=59752)
if (spellInfo->Id != 42292 && spellInfo->Id != 59752)
{
// If m_immuneToSchool type contain this school type, IMMUNE damage.
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
@@ -11475,7 +11471,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo)
}
// Spells that don't have effectMechanics.
if (!spellInfo->HasAnyEffectMechanic() && spellInfo->Mechanic)
if (spellInfo->Mechanic)
{
SpellImmuneList const& mechanicList = m_spellImmune[IMMUNITY_MECHANIC];
for (SpellImmuneList::const_iterator itr = mechanicList.begin(); itr != mechanicList.end(); ++itr)
@@ -11488,16 +11484,17 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo)
{
// State/effect immunities applied by aura expect full spell immunity
// Ignore effects with mechanic, they are supposed to be checked separately
if (spellInfo->Effects[i].Mechanic || !IsImmunedToSpellEffect(spellInfo, i))
if (!IsImmunedToSpellEffect(spellInfo, i))
{
immuneToAllEffects = false;
break;
}
}
if (immuneToAllEffects) //Return immune only if the target is immune to all spell effects.
return true;
if (spellInfo->Id != 42292 && spellInfo->Id !=59752)
if (spellInfo->Id != 42292 && spellInfo->Id != 59752)
{
SpellImmuneList const& schoolList = m_spellImmune[IMMUNITY_SCHOOL];
for (SpellImmuneList::const_iterator itr = schoolList.begin(); itr != schoolList.end(); ++itr)
@@ -11515,8 +11512,9 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo)
bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const
{
if (!spellInfo)
if (!spellInfo || !spellInfo->Effects[index].IsEffect())
return false;
// If m_immuneToEffect type contain this effect type, IMMUNE effect.
uint32 effect = spellInfo->Effects[index].Effect;
SpellImmuneList const& effectList = m_spellImmune[IMMUNITY_EFFECT];
@@ -11552,10 +11550,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
{
if (!victim)
return 0;
if (pdamage == 0)
if (!victim || pdamage == 0)
return 0;
uint32 creatureTypeMask = victim->GetCreatureTypeMask();
@@ -11612,23 +11607,24 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
// Done total percent damage auras
float DoneTotalMod = 1.0f;
// ..done
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
{
if (spellProto)
// Some spells don't benefit from pct done mods
if (spellProto)
if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS) && !spellProto->IsRankOf(sSpellMgr->GetSpellInfo(12162)))
{
if ((*i)->GetMiscValue() & spellProto->GetSchoolMask() && !(spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_NORMAL))
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
{
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
AddPctN(DoneTotalMod, (*i)->GetAmount());
else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
AddPctN(DoneTotalMod, (*i)->GetAmount());
else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
AddPctN(DoneTotalMod, (*i)->GetAmount());
if ((*i)->GetMiscValue() & spellProto->GetSchoolMask() && !(spellProto->GetSchoolMask() & SPELL_SCHOOL_MASK_NORMAL))
{
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
AddPctN(DoneTotalMod, (*i)->GetAmount());
else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
AddPctN(DoneTotalMod, (*i)->GetAmount());
else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
AddPctN(DoneTotalMod, (*i)->GetAmount());
}
}
}
}
AuraEffectList const& mDamageDoneVersus = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_DONE_VERSUS);
for (AuraEffectList::const_iterator i = mDamageDoneVersus.begin(); i != mDamageDoneVersus.end(); ++i)
@@ -11727,7 +11723,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
return uint32(std::max(tmpDamage, 0.0f));
}
uint32 Unit::MeleeDamageBonusTaken(uint32 pdamage, WeaponAttackType attType, SpellInfo const *spellProto)
uint32 Unit::MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto)
{
if (pdamage == 0)
return 0;
@@ -11751,15 +11747,15 @@ uint32 Unit::MeleeDamageBonusTaken(uint32 pdamage, WeaponAttackType attType, Spe
// ..taken
TakenTotalMod *= GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, GetMeleeDamageSchoolMask());
// From caster spells
AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
if ((*i)->GetCasterGUID() == GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
AddPctN(TakenTotalMod, (*i)->GetAmount());
// .. taken pct (special attacks)
if (spellProto)
{
// From caster spells
AuraEffectList const& mOwnerTaken = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_FROM_CASTER);
for (AuraEffectList::const_iterator i = mOwnerTaken.begin(); i != mOwnerTaken.end(); ++i)
if ((*i)->GetCasterGUID() == attacker->GetGUID() && (*i)->IsAffectedOnSpell(spellProto))
AddPctN(TakenTotalMod, (*i)->GetAmount());
// Mod damage from spell mechanic
uint32 mechanicMask = spellProto->GetAllEffectsMechanicMask();
@@ -12160,7 +12156,7 @@ bool Unit::IsValidAttackTarget(Unit const* target) const
}
// function based on function Unit::CanAttack from 13850 client
bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) const
bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, WorldObject const* obj) const
{
ASSERT(target);
@@ -12178,8 +12174,8 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) co
if (IsOnVehicle(target) || m_vehicle->GetBase()->IsOnVehicle(target))
return false;
// can't attack invisible (ignore stealth for aoe spells)
if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !canSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))
// can't attack invisible (ignore stealth for aoe spells) also if the area being looked at is from a spell use the dynamic object created instead of the casting unit.
if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->canSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !canSeeOrDetect(target, bySpell && bySpell->IsAffectingArea())))
return false;
// can't attack dead
@@ -12740,11 +12736,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
void Unit::setDeathState(DeathState s)
{
// death state needs to be updated before RemoveAllAurasOnDeath() calls HandleChannelDeathItem(..) so that
// it can be used to check creation of death items (such as soul shards).
m_deathState = s;
if (s != ALIVE && s != JUST_ALIVED)
if (s != ALIVE && s != JUST_RESPAWNED)
{
CombatStop();
DeleteThreatList();
@@ -12787,8 +12779,10 @@ void Unit::setDeathState(DeathState s)
if (ZoneScript* zoneScript = GetZoneScript() ? GetZoneScript() : (ZoneScript*)GetInstanceScript())
zoneScript->OnUnitDeath(this);
}
else if (s == JUST_ALIVED)
RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // clear skinnable for creature and player (at battleground)
else if (s == JUST_RESPAWNED)
RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // clear skinnable for creature and player (at battleground)
m_deathState = s;
}
/*########################################
@@ -14402,7 +14396,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "ProcDamageAndSpell: doing %u damage from spell id %u (triggered by %s aura of spell %u)", triggeredByAura->GetAmount(), spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId());
SpellNonMeleeDamage damageInfo(this, target, spellInfo->Id, spellInfo->SchoolMask);
uint32 newDamage = SpellDamageBonusDone(target, spellInfo, triggeredByAura->GetAmount(), SPELL_DIRECT_DAMAGE);
newDamage = target->SpellDamageBonusTaken(spellInfo, newDamage, SPELL_DIRECT_DAMAGE);
newDamage = target->SpellDamageBonusTaken(this, spellInfo, newDamage, SPELL_DIRECT_DAMAGE);
CalculateSpellDamageTaken(&damageInfo, newDamage, spellInfo);
DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
SendSpellNonMeleeDamageLog(&damageInfo);
@@ -16943,7 +16937,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
}
if (IsInMap(caster))
caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, true, NULL, NULL, origCasterGUID);
caster->CastCustomSpell(itr->second.spellId, SpellValueMod(SPELLVALUE_BASE_POINT0+i), seatId+1, target, false, NULL, NULL, origCasterGUID);
else // This can happen during Player::_LoadAuras
{
int32 bp0 = seatId;
@@ -16953,7 +16947,7 @@ bool Unit::HandleSpellClick(Unit* clicker, int8 seatId)
else
{
if (IsInMap(caster))
caster->CastSpell(target, spellEntry, true, NULL, NULL, origCasterGUID);
caster->CastSpell(target, spellEntry, false, NULL, NULL, origCasterGUID);
else
Aura::TryRefreshStackOrCreate(spellEntry, MAX_EFFECT_MASK, this, clicker, NULL, NULL, origCasterGUID);
}
+5 -5
View File
@@ -465,7 +465,7 @@ enum DeathState
JUST_DIED = 1,
CORPSE = 2,
DEAD = 3,
JUST_ALIVED = 4,
JUST_RESPAWNED = 4,
};
enum UnitState
@@ -1573,7 +1573,7 @@ class Unit : public WorldObject
bool isTargetableForAttack(bool checkFakeDeath = true) const;
bool IsValidAttackTarget(Unit const* target) const;
bool _IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) const;
bool _IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, WorldObject const* obj = NULL) const;
bool IsValidAssistTarget(Unit const* target) const;
bool _IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) const;
@@ -2038,14 +2038,14 @@ class Unit : public WorldObject
int32 SpellBaseDamageBonusDone(SpellSchoolMask schoolMask);
int32 SpellBaseDamageBonusTaken(SpellSchoolMask schoolMask);
uint32 SpellDamageBonusDone(Unit* victim, SpellInfo const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1);
uint32 SpellDamageBonusTaken(SpellInfo const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1);
uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const *spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1);
int32 SpellBaseHealingBonusDone(SpellSchoolMask schoolMask);
int32 SpellBaseHealingBonusTaken(SpellSchoolMask schoolMask);
uint32 SpellHealingBonusDone(Unit* victim, SpellInfo const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1);
uint32 SpellHealingBonusTaken(SpellInfo const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1);
uint32 SpellHealingBonusTaken(Unit* caster, SpellInfo const *spellProto, uint32 healamount, DamageEffectType damagetype, uint32 stack = 1);
uint32 MeleeDamageBonusDone(Unit *pVictim, uint32 damage, WeaponAttackType attType, SpellInfo const *spellProto = NULL);
uint32 MeleeDamageBonusTaken(uint32 pdamage,WeaponAttackType attType, SpellInfo const *spellProto = NULL);
uint32 MeleeDamageBonusTaken(Unit* attacker, uint32 pdamage,WeaponAttackType attType, SpellInfo const *spellProto = NULL);
bool isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType = BASE_ATTACK);
+29 -49
View File
@@ -6247,74 +6247,54 @@ uint32 ObjectMgr::GenerateLowGuid(HighGuid guidhigh)
switch (guidhigh)
{
case HIGHGUID_ITEM:
if (_hiItemGuid >= 0xFFFFFFFE)
{
sLog->outError("Item guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiItemGuid < 0xFFFFFFFE && "Item guid overflow!");
return _hiItemGuid++;
}
case HIGHGUID_UNIT:
if (_hiCreatureGuid >= 0x00FFFFFE)
{
sLog->outError("Creature guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiCreatureGuid < 0x00FFFFFE && "Creature guid overflow!");
return _hiCreatureGuid++;
}
case HIGHGUID_PET:
if (_hiPetGuid >= 0x00FFFFFE)
{
sLog->outError("Pet guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiPetGuid < 0x00FFFFFE && "Pet guid overflow!");
return _hiPetGuid++;
}
case HIGHGUID_VEHICLE:
if (_hiVehicleGuid >= 0x00FFFFFF)
{
sLog->outError("Vehicle guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiVehicleGuid < 0x00FFFFFF && "Vehicle guid overflow!");
return _hiVehicleGuid++;
}
case HIGHGUID_PLAYER:
if (_hiCharGuid >= 0xFFFFFFFE)
{
sLog->outError("Players guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiCharGuid < 0xFFFFFFFE && "Player guid overflow!");
return _hiCharGuid++;
}
case HIGHGUID_GAMEOBJECT:
if (_hiGoGuid >= 0x00FFFFFE)
{
sLog->outError("Gameobject guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiGoGuid < 0x00FFFFFE && "Gameobject guid overflow!");
return _hiGoGuid++;
}
case HIGHGUID_CORPSE:
if (_hiCorpseGuid >= 0xFFFFFFFE)
{
sLog->outError("Corpse guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiCorpseGuid < 0xFFFFFFFE && "Corpse guid overflow!");
return _hiCorpseGuid++;
}
case HIGHGUID_DYNAMICOBJECT:
if (_hiDoGuid >= 0xFFFFFFFE)
{
sLog->outError("DynamicObject guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiDoGuid < 0xFFFFFFFE && "DynamicObject guid overflow!");
return _hiDoGuid++;
}
case HIGHGUID_MO_TRANSPORT:
if (_hiMoTransGuid >= 0xFFFFFFFE)
{
sLog->outError("MO Transport guid overflow!! Can't continue, shutting down server. ");
World::StopNow(ERROR_EXIT_CODE);
}
{
ASSERT(_hiMoTransGuid < 0xFFFFFFFE && "MO Transport guid overflow!");
return _hiMoTransGuid++;
}
default:
ASSERT(0);
ASSERT(false && "ObjectMgr::GenerateLowGuid - Unknown HIGHGUID type");
return 0;
}
ASSERT(0);
return 0;
}
void ObjectMgr::LoadGameObjectLocales()
@@ -943,7 +943,7 @@ namespace Trinity
if (u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isTotem())
return false;
if (i_funit->_IsValidAttackTarget(u, _spellInfo) && i_obj->IsWithinDistInMap(u, i_range))
if (i_funit->_IsValidAttackTarget(u, _spellInfo,i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : NULL) && i_obj->IsWithinDistInMap(u, i_range))
return true;
return false;
+32 -24
View File
@@ -20,7 +20,7 @@
----- Opcodes Not Used yet -----
SMSG_CALENDAR_CLEAR_PENDING_ACTION SendCalendarClearPendingAction()
SMSG_CALENDAR_RAID_LOCKOUT_UPDATED SendCalendarRaidLockoutUpdated(InstanceSave const* save) <--- Structure unknown, using LOCKOUT_ADDED
SMSG_CALENDAR_RAID_LOCKOUT_UPDATED SendCalendarRaidLockoutUpdated(InstanceSave const* save)
----- Opcodes without Sniffs -----
SMSG_CALENDAR_FILTER_GUILD [ for (... uint32(count) { packguid(???), uint8(???) } ]
@@ -74,7 +74,11 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/)
else
{
sLog->outError("SMSG_CALENDAR_SEND_CALENDAR: No Invite found with id [" UI64FMTD "]", *it);
data << uint64(0) << uint64(0) << uint8(0) << uint8(0);
data << uint64(0);
data << uint64(0);
data << uint8(0);
data << uint8(0);
data << uint8(0);
data.appendPackGUID(0);
}
}
@@ -96,8 +100,12 @@ void WorldSession::HandleCalendarGetCalendar(WorldPacket& /*recvData*/)
else
{
sLog->outError("SMSG_CALENDAR_SEND_CALENDAR: No Event found with id [" UI64FMTD "]", *it);
data << uint64(0) << uint8(0) << uint32(0)
<< uint32(0) << uint32(0) << uint32(0);
data << uint64(0);
data << uint8(0);
data << uint32(0);
data << uint32(0);
data << uint32(0);
data << uint32(0);
data.appendPackGUID(0);
}
}
@@ -835,26 +843,6 @@ void WorldSession::SendCalendarClearPendingAction()
SendPacket(&data);
}
void WorldSession::SendCalendarRaidLockoutUpdated(InstanceSave const* save)
{
if (!save)
return;
uint64 guid = _player->GetGUID();
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_CALENDAR_RAID_LOCKOUT_UPDATED [" UI64FMTD
"] Map: %u, Difficulty %u", guid, save->GetMapId(), save->GetDifficulty());
time_t cur_time = time_t(time(NULL));
WorldPacket data(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, 4 + 4 + 4 + 4 + 8);
data << secsToTimeBitFields(cur_time);
data << uint32(save->GetMapId());
data << uint32(save->GetDifficulty());
data << uint32(save->GetResetTime() - cur_time);
data << uint64(save->GetInstanceId());
SendPacket(&data);
}
void WorldSession::SendCalendarCommandResult(CalendarError err, char const* param /*= NULL*/)
{
uint64 guid = _player->GetGUID();
@@ -898,3 +886,23 @@ void WorldSession::SendCalendarRaidLockout(InstanceSave const* save, bool add)
data << uint64(save->GetInstanceId());
SendPacket(&data);
}
void WorldSession::SendCalendarRaidLockoutUpdated(InstanceSave const* save)
{
if (!save)
return;
uint64 guid = _player->GetGUID();
sLog->outDebug(LOG_FILTER_NETWORKIO, "SMSG_CALENDAR_RAID_LOCKOUT_UPDATED [" UI64FMTD
"] Map: %u, Difficulty %u", guid, save->GetMapId(), save->GetDifficulty());
time_t cur_time = time_t(time(NULL));
WorldPacket data(SMSG_CALENDAR_RAID_LOCKOUT_UPDATED, 4 + 4 + 4 + 4 + 8);
data << secsToTimeBitFields(cur_time);
data << uint32(save->GetMapId());
data << uint32(save->GetDifficulty());
data << uint32(0); // Amount of seconds that has changed to the reset time
data << uint32(save->GetResetTime() - cur_time);
SendPacket(&data);
}
+49
View File
@@ -51,6 +51,7 @@
#include "GameObjectAI.h"
#include "Group.h"
#include "AccountMgr.h"
#include "Spell.h"
void WorldSession::HandleRepopRequestOpcode(WorldPacket & recv_data)
{
@@ -429,6 +430,10 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPacket & /*recv_data*/)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Recvd CMSG_LOGOUT_CANCEL Message");
// Player have already logged out serverside, too late to cancel
if (!GetPlayer())
return;
LogoutRequest(0);
WorldPacket data(SMSG_LOGOUT_CANCEL_ACK, 0);
@@ -1714,3 +1719,47 @@ void WorldSession::HandleInstanceLockResponse(WorldPacket& recvPacket)
_player->SetPendingBind(0, 0);
}
void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket)
{
sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: CMSG_UPDATE_MISSILE_TRAJECTORY");
uint64 guid;
uint32 spellId;
float elevation, speed;
float curX, curY, curZ;
float targetX, targetY, targetZ;
uint8 moveStop;
recvPacket >> guid >> spellId >> elevation >> speed;
recvPacket >> curX >> curY >> curZ;
recvPacket >> targetX >> targetY >> targetZ;
recvPacket >> moveStop;
Unit* caster = ObjectAccessor::GetUnit(*_player, guid);
Spell* spell = caster ? caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) : NULL;
if (!spell || spell->m_spellInfo->Id != spellId || !spell->m_targets.HasDst() || !spell->m_targets.HasSrc())
{
recvPacket.rfinish();
return;
}
Position pos = *spell->m_targets.GetSrcPos();
pos.Relocate(curX, curY, curZ);
spell->m_targets.ModSrc(pos);
pos = *spell->m_targets.GetDstPos();
pos.Relocate(targetX, targetY, targetZ);
spell->m_targets.ModDst(pos);
spell->m_targets.SetElevation(elevation);
spell->m_targets.SetSpeed(speed);
if (moveStop)
{
uint32 opcode;
recvPacket >> opcode;
recvPacket.SetOpcode(opcode);
HandleMovementOpcodes(recvPacket);
}
}
+32 -36
View File
@@ -64,10 +64,9 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->m_InstanceValid = true;
Map* oldMap = GetPlayer()->GetMap();
ASSERT(oldMap);
if (GetPlayer()->IsInWorld())
{
sLog->outCrash("Player (Name %s) is still in world when teleported from map %u to new map %u", GetPlayer()->GetName(), oldMap->GetId(), loc.GetMapId());
sLog->outError("Player (Name %s) is still in world when teleported from map %u to new map %u", GetPlayer()->GetName(), oldMap->GetId(), loc.GetMapId());
oldMap->RemovePlayerFromMap(GetPlayer(), false);
}
@@ -200,8 +199,7 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
sLog->outStaticDebug("Guid " UI64FMTD, guid);
sLog->outStaticDebug("Flags %u, time %u", flags, time/IN_MILLISECONDS);
Unit* mover = _player->m_mover;
Player* plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
Player* plMover = _player->m_mover->ToPlayer();
if (!plMover || !plMover->IsBeingTeleportedNear())
return;
@@ -240,33 +238,33 @@ void WorldSession::HandleMoveTeleportAck(WorldPacket& recv_data)
GetPlayer()->ProcessDelayedOperations();
}
void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data)
void WorldSession::HandleMovementOpcodes(WorldPacket & recvData)
{
uint16 opcode = recv_data.GetOpcode();
uint16 opcode = recvData.GetOpcode();
Unit* mover = _player->m_mover;
ASSERT(mover != NULL); // there must always be a mover
ASSERT(mover != NULL); // there must always be a mover
Player* plMover = mover->GetTypeId() == TYPEID_PLAYER ? (Player*)mover : NULL;
Player* plrMover = mover->ToPlayer();
// ignore, waiting processing in WorldSession::HandleMoveWorldportAckOpcode and WorldSession::HandleMoveTeleportAck
if (plMover && plMover->IsBeingTeleported())
if (plrMover && plrMover->IsBeingTeleported())
{
recv_data.rfinish(); // prevent warnings spam
recvData.rfinish(); // prevent warnings spam
return;
}
/* extract packet */
uint64 guid;
recv_data.readPackGUID(guid);
recvData.readPackGUID(guid);
MovementInfo movementInfo;
movementInfo.guid = guid;
ReadMovementInfo(recv_data, &movementInfo);
ReadMovementInfo(recvData, &movementInfo);
recv_data.rfinish(); // prevent warnings spam
recvData.rfinish(); // prevent warnings spam
// prevent tampered movement data
if (guid != mover->GetGUID())
@@ -274,7 +272,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data)
if (!movementInfo.pos.IsPositionValid())
{
recv_data.rfinish(); // prevent warnings spam
recvData.rfinish(); // prevent warnings spam
return;
}
@@ -285,27 +283,27 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data)
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
if (movementInfo.t_pos.GetPositionX() > 50 || movementInfo.t_pos.GetPositionY() > 50 || movementInfo.t_pos.GetPositionZ() > 50)
{
recv_data.rfinish(); // prevent warnings spam
recvData.rfinish(); // prevent warnings spam
return;
}
if (!Trinity::IsValidMapCoord(movementInfo.pos.GetPositionX() + movementInfo.t_pos.GetPositionX(), movementInfo.pos.GetPositionY() + movementInfo.t_pos.GetPositionY(),
movementInfo.pos.GetPositionZ() + movementInfo.t_pos.GetPositionZ(), movementInfo.pos.GetOrientation() + movementInfo.t_pos.GetOrientation()))
{
recv_data.rfinish(); // prevent warnings spam
recvData.rfinish(); // prevent warnings spam
return;
}
// if we boarded a transport, add us to it
if (plMover && !plMover->GetTransport())
if (plrMover && !plrMover->GetTransport())
{
// elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just dismount if the guid can be found in the transport list
for (MapManager::TransportSet::const_iterator iter = sMapMgr->m_Transports.begin(); iter != sMapMgr->m_Transports.end(); ++iter)
{
if ((*iter)->GetGUID() == movementInfo.t_guid)
{
plMover->m_transport = (*iter);
(*iter)->AddPassenger(plMover);
plrMover->m_transport = (*iter);
(*iter)->AddPassenger(plrMover);
break;
}
}
@@ -318,29 +316,29 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data)
movementInfo.flags &= ~MOVEMENTFLAG_ONTRANSPORT;
}
}
else if (plMover && plMover->GetTransport()) // if we were on a transport, leave
else if (plrMover && plrMover->GetTransport()) // if we were on a transport, leave
{
plMover->m_transport->RemovePassenger(plMover);
plMover->m_transport = NULL;
plrMover->m_transport->RemovePassenger(plrMover);
plrMover->m_transport = NULL;
movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
movementInfo.t_time = 0;
movementInfo.t_seat = -1;
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && plMover && !plMover->isInFlight())
plMover->HandleFall(movementInfo);
if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->isInFlight())
plrMover->HandleFall(movementInfo);
if (plMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plMover->IsInWater())
if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater())
{
// now client not include swimming flag in case jumping under water
plMover->SetInWater(!plMover->IsInWater() || plMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
}
/*----------------------*/
/* process position-change */
WorldPacket data(opcode, recv_data.size());
WorldPacket data(opcode, recvData.size());
movementInfo.time = getMSTime();
movementInfo.guid = mover->GetGUID();
WriteMovementInfo(&data, &movementInfo);
@@ -357,27 +355,25 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data)
mover->UpdatePosition(movementInfo.pos);
if (plMover) // nothing is charmed, or player charmed
if (plrMover) // nothing is charmed, or player charmed
{
plMover->UpdateFallInformationIfNeed(movementInfo, opcode);
plrMover->UpdateFallInformationIfNeed(movementInfo, opcode);
if (movementInfo.pos.GetPositionZ() < -500.0f)
{
if (!(plMover->InBattleground()
&& plMover->GetBattleground()
&& plMover->GetBattleground()->HandlePlayerUnderMap(_player)))
if (!(plrMover->GetBattleground() && plrMover->GetBattleground()->HandlePlayerUnderMap(_player)))
{
// NOTE: this is actually called many times while falling
// even after the player has been teleported away
// TODO: discard movement packets after the player is rooted
if (plMover->isAlive())
if (plrMover->isAlive())
{
plMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
plrMover->EnvironmentalDamage(DAMAGE_FALL_TO_VOID, GetPlayer()->GetMaxHealth());
// player can be alive if GM/etc
// change the death state to CORPSE to prevent the death timer from
// starting in the next player update
if (!plMover->isAlive())
plMover->KillPlayer();
if (!plrMover->isAlive())
plrMover->KillPlayer();
}
}
}
+10 -1
View File
@@ -650,13 +650,22 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket)
uint8 castCount;
float x, y, z; // Position of missile hit
recvPacket.readPackGUID(casterGuid);
recvPacket >> casterGuid;
recvPacket >> spellId;
recvPacket >> castCount;
recvPacket >> x;
recvPacket >> y;
recvPacket >> z;
Unit* caster = ObjectAccessor::GetUnit(*_player, casterGuid);
Spell* spell = caster ? caster->FindCurrentSpellBySpellId(spellId) : NULL;
if (spell && spell->m_targets.HasDst())
{
Position pos = *spell->m_targets.GetDstPos();
pos.Relocate(x, y, z);
spell->m_targets.ModDst(pos);
}
WorldPacket data(SMSG_SET_PROJECTILE_POSITION, 21);
data << uint64(casterGuid);
data << uint8(castCount);
+1 -1
View File
@@ -531,7 +531,7 @@ void WorldSession::HandleBeginTradeOpcode(WorldPacket& /*recvPacket*/)
void WorldSession::SendCancelTrade()
{
if (m_playerRecentlyLogout)
if (PlayerRecentlyLoggedOut() || PlayerLogout())
return;
SendTradeStatus(TRADE_STATUS_TRADE_CANCELED);
+1 -1
View File
@@ -2470,7 +2470,7 @@ bool InstanceMap::AddPlayerToMap(Player* player)
if (uint32 dungeonId = sLFGMgr->GetDungeon(group->GetGUID(), true))
if (LFGDungeonEntry const* dungeon = sLFGDungeonStore.LookupEntry(dungeonId))
if (LFGDungeonEntry const* randomDungeon = sLFGDungeonStore.LookupEntry(*(sLFGMgr->GetSelectedDungeons(player->GetGUID()).begin())))
if (uint32(dungeon->map) == GetId() && dungeon->difficulty == GetDifficulty() && randomDungeon->type == LFG_TYPE_RANDOM)
if (uint32(dungeon->map) == GetId() && dungeon->difficulty == uint32(GetDifficulty()) && randomDungeon->type == uint32(LFG_TYPE_RANDOM))
player->CastSpell(player, LFG_SPELL_LUCK_OF_THE_DRAW, true);
}
+16
View File
@@ -937,6 +937,22 @@ void ScriptMgr::OnGameObjectDamaged(GameObject* go, Player* player)
tmpscript->OnDamaged(go, player);
}
void ScriptMgr::OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* unit)
{
ASSERT(go);
GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
tmpscript->OnLootStateChanged(go, state, unit);
}
void ScriptMgr::OnGameObjectStateChanged(GameObject* go, uint32 state)
{
ASSERT(go);
GET_SCRIPT(GameObjectScript, go->GetScriptId(), tmpscript);
tmpscript->OnGameObjectStateChanged(go, state);
}
void ScriptMgr::OnGameObjectUpdate(GameObject* go, uint32 diff)
{
ASSERT(go);
+8
View File
@@ -473,6 +473,12 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
// Called when the game object is damaged (destructible buildings only).
virtual void OnDamaged(GameObject* /*go*/, Player* /*player*/) { }
// Called when the game object loot state is changed.
virtual void OnLootStateChanged(GameObject* /*go*/, uint32 /*state*/, Unit* /*unit*/) { }
// Called when the game object state is changed.
virtual void OnGameObjectStateChanged(GameObject* /*go*/, uint32 /*state*/) { }
// Called when a GameObjectAI object is needed for the gameobject.
virtual GameObjectAI* GetAI(GameObject* /*go*/) const { return NULL; }
};
@@ -914,6 +920,8 @@ class ScriptMgr
uint32 GetDialogStatus(Player* player, GameObject* go);
void OnGameObjectDestroyed(GameObject* go, Player* player);
void OnGameObjectDamaged(GameObject* go, Player* player);
void OnGameObjectLootStateChanged(GameObject* go, uint32 state, Unit* unit);
void OnGameObjectStateChanged(GameObject* go, uint32 state);
void OnGameObjectUpdate(GameObject* go, uint32 diff);
GameObjectAI* GetGameObjectAI(GameObject* go);
+7 -7
View File
@@ -104,7 +104,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x04B*/ { "CMSG_LOGOUT_REQUEST", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutRequestOpcode },
/*0x04C*/ { "SMSG_LOGOUT_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x04D*/ { "SMSG_LOGOUT_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode },
/*0x04E*/ { "CMSG_LOGOUT_CANCEL", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode },
/*0x04F*/ { "SMSG_LOGOUT_CANCEL_ACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x050*/ { "CMSG_NAME_QUERY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleNameQueryOpcode },
/*0x051*/ { "SMSG_NAME_QUERY_RESPONSE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
@@ -270,8 +270,8 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x0F1*/ { "MSG_MOVE_KNOCK_BACK", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x0F2*/ { "SMSG_MOVE_FEATHER_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x0F3*/ { "SMSG_MOVE_NORMAL_FALL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x0F4*/ { "SMSG_MOVE_SET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x0F5*/ { "SMSG_MOVE_UNSET_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x0F6*/ { "CMSG_MOVE_HOVER_ACK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveHoverAck },
/*0x0F7*/ { "MSG_MOVE_HOVER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x0F8*/ { "CMSG_TRIGGER_CINEMATIC_CHEAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
@@ -310,7 +310,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x119*/ { "CMSG_IGNORE_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleIgnoreTradeOpcode },
/*0x11A*/ { "CMSG_ACCEPT_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleAcceptTradeOpcode },
/*0x11B*/ { "CMSG_UNACCEPT_TRADE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUnacceptTradeOpcode },
/*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode},
/*0x11C*/ { "CMSG_CANCEL_TRADE", STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode },
/*0x11D*/ { "CMSG_SET_TRADE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeItemOpcode },
/*0x11E*/ { "CMSG_CLEAR_TRADE_ITEM", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleClearTradeItemOpcode },
/*0x11F*/ { "CMSG_SET_TRADE_GOLD", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTradeGoldOpcode },
@@ -970,7 +970,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x3AD*/ { "MSG_MOVE_UPDATE_CAN_FLY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x3AE*/ { "MSG_RAID_READY_CHECK_CONFIRM", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x3AF*/ { "CMSG_VOICE_SESSION_ENABLE", STATUS_AUTHED, PROCESS_THREADUNSAFE, &WorldSession::HandleVoiceSessionEnableOpcode },
/*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x3B0*/ { "SMSG_VOICE_SESSION_ENABLE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x3B1*/ { "SMSG_VOICE_PARENTAL_CONTROLS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x3B2*/ { "CMSG_GM_WHISPER", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x3B3*/ { "SMSG_GM_MESSAGECHAT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
@@ -1023,7 +1023,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x3E2*/ { "SMSG_COMSAT_CONNECT_FAIL", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x3E3*/ { "SMSG_VOICE_CHAT_STATUS", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x3E4*/ { "CMSG_REPORT_PVP_AFK", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleReportPvPAFK },
/*0x3E5*/ { "SMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x3E5*/ { "SMSG_REPORT_PVP_AFK_RESULT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x3E6*/ { "CMSG_GUILD_BANKER_ACTIVATE", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankerActivate },
/*0x3E7*/ { "CMSG_GUILD_BANK_QUERY_TAB", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildBankQueryTab },
/*0x3E8*/ { "SMSG_GUILD_BANK_LIST", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
@@ -1148,7 +1148,7 @@ OpcodeHandler opcodeTable[NUM_MSG_TYPES] =
/*0x45F*/ { "CMSG_CALENDAR_EVENT_INVITE_NOTES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x460*/ { "SMSG_CALENDAR_EVENT_INVITE_NOTES", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x461*/ { "SMSG_CALENDAR_EVENT_INVITE_NOTES_ALERT", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
/*0x462*/ { "CMSG_UPDATE_MISSILE_TRAJECTORY", STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateMissileTrajectory },
/*0x463*/ { "SMSG_UPDATE_ACCOUNT_DATA_COMPLETE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x464*/ { "SMSG_TRIGGER_MOVIE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide },
/*0x465*/ { "CMSG_COMPLETE_MOVIE", STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL },
+3 -3
View File
@@ -1248,8 +1248,8 @@ enum Opcodes
SMSG_CALENDAR_CLEAR_PENDING_ACTION = 0x4BB,
SMSG_EQUIPMENT_SET_LIST = 0x4BC, // equipment manager list?
CMSG_EQUIPMENT_SET_SAVE = 0x4BD,
CMSG_UPDATE_PROJECTILE_POSITION = 0x4BE, // uint64 caster, uint32 spellId, uint8 castId, vector3 position
SMSG_SET_PROJECTILE_POSITION = 0x4BF, // uint64 caster, uint8 castId, vector3 position
CMSG_UPDATE_PROJECTILE_POSITION = 0x4BE,
SMSG_SET_PROJECTILE_POSITION = 0x4BF,
SMSG_TALENTS_INFO = 0x4C0,
CMSG_LEARN_PREVIEW_TALENTS = 0x4C1,
CMSG_LEARN_PREVIEW_TALENTS_PET = 0x4C2,
@@ -1354,7 +1354,7 @@ enum SessionStatus
STATUS_AUTHED = 0, // Player authenticated (_player == NULL, m_playerRecentlyLogout = false or will be reset before handler call, m_GUID have garbage)
STATUS_LOGGEDIN, // Player in game (_player != NULL, m_GUID == _player->GetGUID(), inWorld())
STATUS_TRANSFER, // Player transferring to another map (_player != NULL, m_GUID == _player->GetGUID(), !inWorld())
STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, // _player!= NULL or _player == NULL && m_playerRecentlyLogout, m_GUID store last _player guid)
STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, // _player != NULL or _player == NULL && m_playerRecentlyLogout && m_playerLogout, m_GUID store last _player guid)
STATUS_NEVER, // Opcode not accepted from client (deprecated or server side only)
STATUS_UNHANDLED, // Opcode not handled yet
};
+19 -22
View File
@@ -290,7 +290,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
break;
case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT:
if (!_player && !m_playerRecentlyLogout)
if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout
LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT",
"the player has not logged in yet and not recently logout");
else
@@ -323,9 +323,9 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
break;
}
// single from authed time opcodes send in to after logout time
// and before other STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes.
if (packet->GetOpcode() != CMSG_SET_ACTIVE_VOICE_CHANNEL)
// some auth opcodes can be recieved before STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT opcodes
// however when we recieve CMSG_CHAR_ENUM we are surely no longer during the logout process.
if (packet->GetOpcode() == CMSG_CHAR_ENUM)
m_playerRecentlyLogout = false;
sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
@@ -404,7 +404,7 @@ void WorldSession::LogoutPlayer(bool Save)
if (_player)
{
if (uint64 lguid = GetPlayer()->GetLootGUID())
if (uint64 lguid = _player->GetLootGUID())
DoLootRelease(lguid);
///- If the player just died before logging out, make him appear as a ghost
@@ -518,21 +518,21 @@ void WorldSession::LogoutPlayer(bool Save)
if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket)
_player->RemoveFromGroup();
///- Send update to group and reset stored max enchanting level
//! Send update to group and reset stored max enchanting level
if (_player->GetGroup())
{
_player->GetGroup()->SendUpdate();
_player->GetGroup()->ResetMaxEnchantingLevel();
}
///- Broadcast a logout message to the player's friends
//! Broadcast a logout message to the player's friends
sSocialMgr->SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true);
sSocialMgr->RemovePlayerSocial(_player->GetGUIDLow());
// Call script hook before deletion
sScriptMgr->OnPlayerLogout(GetPlayer());
//! Call script hook before deletion
sScriptMgr->OnPlayerLogout(_player);
///- Remove the player from the world
//! Remove the player from the world
// the player may not be in the world when logging out
// e.g if he got disconnected during a transfer to another map
// calls to GetMap in this case may cause crashes
@@ -540,22 +540,19 @@ void WorldSession::LogoutPlayer(bool Save)
sLog->outChar("Account: %d (IP: %s) Logout Character:[%s] (GUID: %u) Level: %d", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName(), _player->GetGUIDLow(), _player->getLevel());
if (Map* _map = _player->FindMap())
_map->RemovePlayerFromMap(_player, true);
SetPlayer(NULL); // deleted in Remove call
///- Send the 'logout complete' packet to the client
SetPlayer(NULL); //! Pointer already deleted during RemovePlayerFromMap
//! Send the 'logout complete' packet to the client
//! Client will respond by sending 3x CMSG_CANCEL_TRADE, which we currently dont handle
WorldPacket data(SMSG_LOGOUT_COMPLETE, 0);
SendPacket(&data);
///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline
//No SQL injection as AccountId is uint32
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ACCOUNT_ONLINE);
stmt->setUInt32(0, GetAccountId());
CharacterDatabase.Execute(stmt);
sLog->outDebug(LOG_FILTER_NETWORKIO, "SESSION: Sent SMSG_LOGOUT_COMPLETE Message");
//! Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ACCOUNT_ONLINE);
stmt->setUInt32(0, GetAccountId());
CharacterDatabase.Execute(stmt);
}
m_playerLogout = false;
+3 -1
View File
@@ -221,6 +221,7 @@ class WorldSession
bool PlayerLoading() const { return m_playerLoading; }
bool PlayerLogout() const { return m_playerLogout; }
bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; }
bool PlayerRecentlyLoggedOut() const { return m_playerRecentlyLogout; }
void SizeError(WorldPacket const& packet, uint32 size) const;
@@ -395,7 +396,7 @@ class WorldSession
public: // opcodes handlers
void Handle_NULL(WorldPacket& recvPacket); // not used
void Handle_EarlyProccess(WorldPacket& recvPacket);// just mark packets processed in WorldSocket::OnRead
void Handle_EarlyProccess(WorldPacket& recvPacket); // just mark packets processed in WorldSocket::OnRead
void Handle_ServerSide(WorldPacket& recvPacket); // sever side only, can't be accepted from client
void Handle_Deprecated(WorldPacket& recvPacket); // never used anymore by client
@@ -785,6 +786,7 @@ class WorldSession
void HandleResetInstancesOpcode(WorldPacket& recv_data);
void HandleHearthAndResurrect(WorldPacket& recv_data);
void HandleInstanceLockResponse(WorldPacket& recvPacket);
void HandleUpdateMissileTrajectory(WorldPacket& recvPacket);
// Looking for Dungeon/Raid
void HandleLfgSetCommentOpcode(WorldPacket& recv_data);
@@ -584,7 +584,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_MAGE && GetSpellInfo()->SpellFamilyFlags[0] & 0x8000 && m_spellInfo->SpellFamilyFlags[2] & 0x8)
{
// +80.53% from +spd bonus
DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8053f;;
DoneActualBenefit += caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()) * 0.8053f;
}
break;
case SPELL_AURA_DUMMY:
@@ -594,7 +594,7 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_SHAMAN && m_spellInfo->SpellFamilyFlags[1] & 0x400)
{
amount = caster->SpellHealingBonusDone(GetBase()->GetUnitOwner(), GetSpellInfo(), amount, SPELL_DIRECT_DAMAGE);
amount = GetBase()->GetUnitOwner()->SpellHealingBonusTaken(GetSpellInfo(), amount, SPELL_DIRECT_DAMAGE);
amount = GetBase()->GetUnitOwner()->SpellHealingBonusTaken(caster, GetSpellInfo(), amount, SPELL_DIRECT_DAMAGE);
}
break;
case SPELL_AURA_PERIODIC_DAMAGE:
@@ -660,19 +660,23 @@ int32 AuraEffect::CalculateAmount(Unit* caster)
}
break;
case SPELL_AURA_PERIODIC_ENERGIZE:
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_GENERIC)
switch (m_spellInfo->Id)
{
// Replenishment (0.25% from max)
// Infinite Replenishment
if (m_spellInfo->SpellIconID == 3184 && m_spellInfo->SpellVisual[0] == 12495)
amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 25 / 10000;
}
// Innervate
else if (m_spellInfo->Id == 29166)
case 57669: // Replenishment (0.2% from max)
amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.002f;
break;
case 61782: // Infinite Replenishment
amount = GetBase()->GetUnitOwner()->GetMaxPower(POWER_MANA) * 0.0025f;
break;
case 29166: // Innervate
ApplyPctF(amount, float(GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA)) / GetTotalTicks());
// Owlkin Frenzy
else if (m_spellInfo->Id == 48391)
break;
case 48391: // Owlkin Frenzy
ApplyPctU(amount, GetBase()->GetUnitOwner()->GetCreatePowers(POWER_MANA));
break;
default:
break;
}
break;
case SPELL_AURA_PERIODIC_HEAL:
if (!caster)
@@ -1240,7 +1244,7 @@ void AuraEffect::SendTickImmune(Unit* target, Unit* caster) const
caster->SendSpellDamageImmune(target, m_spellInfo->Id);
}
void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit* caster)
void AuraEffect::PeriodicTick(AuraApplication * aurApp, Unit* caster) const
{
bool prevented = GetBase()->CallScriptEffectPeriodicHandlers(this, aurApp);
if (prevented)
@@ -5151,66 +5155,63 @@ void AuraEffect::HandleChannelDeathItem(AuraApplication const* aurApp, uint8 mod
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
if (!apply)
if (apply || aurApp->GetRemoveMode() != AURA_REMOVE_BY_DEATH)
return;
Unit* caster = GetCaster();
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
return;
Player* plCaster = caster->ToPlayer();
Unit* target = aurApp->GetTarget();
// Item amount
if (GetAmount() <= 0)
return;
if (GetSpellInfo()->Effects[m_effIndex].ItemType == 0)
return;
// Soul Shard
if (GetSpellInfo()->Effects[m_effIndex].ItemType == 6265)
{
Unit* caster = GetCaster();
if (!caster || caster->GetTypeId() != TYPEID_PLAYER)
// Soul Shard only from units that grant XP or honor
if (!plCaster->isHonorOrXPTarget(target) ||
(target->GetTypeId() == TYPEID_UNIT && !target->ToCreature()->isTappedBy(plCaster)))
return;
Player* plCaster = caster->ToPlayer();
Unit* target = aurApp->GetTarget();
if (target->getDeathState() != JUST_DIED)
return;
// Item amount
if (GetAmount() <= 0)
return;
if (GetSpellInfo()->Effects[m_effIndex].ItemType == 0)
return;
// Soul Shard
if (GetSpellInfo()->Effects[m_effIndex].ItemType == 6265)
// If this is Drain Soul, check for Glyph of Drain Soul
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000))
{
// Soul Shard only from units that grant XP or honor
if (!plCaster->isHonorOrXPTarget(target) ||
(target->GetTypeId() == TYPEID_UNIT && !target->ToCreature()->isTappedBy(plCaster)))
return;
// If this is Drain Soul, check for Glyph of Drain Soul
if (GetSpellInfo()->SpellFamilyName == SPELLFAMILY_WARLOCK && (GetSpellInfo()->SpellFamilyFlags[0] & 0x00004000))
{
// Glyph of Drain Soul - chance to create an additional Soul Shard
if (AuraEffect* aur = caster->GetAuraEffect(58070, 0))
if (roll_chance_i(aur->GetMiscValue()))
caster->CastSpell(caster, 58068, true, 0, aur); // We _could_ simply do ++count here, but Blizz does it this way :)
}
// Glyph of Drain Soul - chance to create an additional Soul Shard
if (AuraEffect* aur = caster->GetAuraEffect(58070, 0))
if (roll_chance_i(aur->GetMiscValue()))
caster->CastSpell(caster, 58068, true, 0, aur); // We _could_ simply do ++count here, but Blizz does it this way :)
}
//Adding items
uint32 noSpaceForCount = 0;
uint32 count = m_amount;
ItemPosCountVec dest;
InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellInfo()->Effects[m_effIndex].ItemType, count, &noSpaceForCount);
if (msg != EQUIP_ERR_OK)
{
count-=noSpaceForCount;
plCaster->SendEquipError(msg, NULL, NULL, GetSpellInfo()->Effects[m_effIndex].ItemType);
if (count == 0)
return;
}
Item* newitem = plCaster->StoreNewItem(dest, GetSpellInfo()->Effects[m_effIndex].ItemType, true);
if (!newitem)
{
plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
return;
}
plCaster->SendNewItem(newitem, count, true, true);
}
//Adding items
uint32 noSpaceForCount = 0;
uint32 count = m_amount;
ItemPosCountVec dest;
InventoryResult msg = plCaster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, GetSpellInfo()->Effects[m_effIndex].ItemType, count, &noSpaceForCount);
if (msg != EQUIP_ERR_OK)
{
count-=noSpaceForCount;
plCaster->SendEquipError(msg, NULL, NULL, GetSpellInfo()->Effects[m_effIndex].ItemType);
if (count == 0)
return;
}
Item* newitem = plCaster->StoreNewItem(dest, GetSpellInfo()->Effects[m_effIndex].ItemType, true);
if (!newitem)
{
plCaster->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
return;
}
plCaster->SendNewItem(newitem, count, true, true);
}
void AuraEffect::HandleBindSight(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -6017,7 +6018,7 @@ void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit*
sLog->outDebug(LOG_FILTER_SPELLS_AURAS,"AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick: Spell %u has non-existent spell %u in EffectTriggered[%d] and is therefor not triggered.", GetId(), triggerSpellId, GetEffIndex());
}
void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster)
void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
{
if (!caster || !target->isAlive())
return;
@@ -6069,7 +6070,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster)
if (GetAuraType() == SPELL_AURA_PERIODIC_DAMAGE)
{
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
damage = target->SpellDamageBonusTaken(GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
// Calculate armor mitigation
if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), GetEffIndex()))
@@ -6159,7 +6160,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster)
caster->DealDamage(target, damage, &cleanDamage, DOT, GetSpellInfo()->GetSchoolMask(), GetSpellInfo(), true);
}
void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster)
void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const
{
if (!caster || !target->isAlive())
return;
@@ -6181,7 +6182,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster)
uint32 damage = std::max(GetAmount(), 0);
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
damage = target->SpellDamageBonusTaken(GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
bool crit = IsPeriodicTickCrit(target, caster);
if (crit)
@@ -6224,7 +6225,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster)
float gainMultiplier = GetSpellInfo()->Effects[GetEffIndex()].CalcValueMultiplier(caster);
uint32 heal = uint32(caster->SpellHealingBonusDone(caster, GetSpellInfo(), uint32(new_damage * gainMultiplier), DOT, GetBase()->GetStackAmount()));
heal = uint32(caster->SpellHealingBonusTaken(GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount()));
heal = uint32(caster->SpellHealingBonusTaken(caster, GetSpellInfo(), heal, DOT, GetBase()->GetStackAmount()));
int32 gain = caster->HealBySpell(caster, GetSpellInfo(), heal);
caster->getHostileRefManager().threatAssist(caster, gain * 0.5f, GetSpellInfo());
@@ -6259,7 +6260,7 @@ void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster)
caster->HealBySpell(target, GetSpellInfo(), damage);
}
void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster)
void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
{
if (!caster || !target->isAlive())
return;
@@ -6328,8 +6329,8 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster)
damage += addition;
}
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
damage = target->SpellHealingBonusTaken(GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
}
bool crit = IsPeriodicTickCrit(target, caster);
@@ -6620,7 +6621,7 @@ void AuraEffect::HandleProcTriggerDamageAuraProc(AuraApplication* aurApp, ProcEv
Unit* triggerTarget = eventInfo.GetProcTarget();
SpellNonMeleeDamage damageInfo(target, triggerTarget, GetId(), GetSpellInfo()->SchoolMask);
uint32 damage = target->SpellDamageBonusDone(triggerTarget, GetSpellInfo(), GetAmount(), SPELL_DIRECT_DAMAGE);
damage = triggerTarget->SpellDamageBonusTaken(GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
damage = triggerTarget->SpellDamageBonusTaken(target, GetSpellInfo(), damage, SPELL_DIRECT_DAMAGE);
target->CalculateSpellDamageTaken(&damageInfo, damage, GetSpellInfo());
target->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
target->SendSpellNonMeleeDamageLog(&damageInfo);
@@ -83,7 +83,7 @@ class AuraEffect
bool HasSpellClassMask() const { return m_spellInfo->Effects[m_effIndex].SpellClassMask; }
void SendTickImmune(Unit* target, Unit* caster) const;
void PeriodicTick(AuraApplication * aurApp, Unit* caster);
void PeriodicTick(AuraApplication * aurApp, Unit* caster) const;
void HandleProc(AuraApplication* aurApp, ProcEventInfo& eventInfo);
@@ -285,10 +285,10 @@ class AuraEffect
void HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const;
void HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) const;
void HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* caster) const;
void HandlePeriodicDamageAurasTick(Unit* target, Unit* caster);
void HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster);
void HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const;
void HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) const;
void HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) const;
void HandlePeriodicHealAurasTick(Unit* target, Unit* caster);
void HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const;
void HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) const;
void HandleObsModPowerAuraTick(Unit* target, Unit* caster) const;
void HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) const;
+2 -2
View File
@@ -1213,7 +1213,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3790, 1))
{
uint32 damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), GetEffect(0)->GetAmount(), DOT);
damage = target->SpellDamageBonusTaken(GetSpellInfo(), damage, DOT);
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT);
int32 basepoints0 = aurEff->GetAmount() * GetEffect(0)->GetTotalTicks() * int32(damage) / 100;
int32 heal = int32(CalculatePctN(basepoints0, 15));
@@ -1228,7 +1228,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 3021, 1))
{
uint32 damage = caster->SpellHealingBonusDone(target, GetSpellInfo(), GetEffect(0)->GetAmount(), HEAL);
damage = target->SpellHealingBonusTaken(GetSpellInfo(), damage, HEAL);
damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, HEAL);
int32 basepoints0 = aurEff->GetAmount() * GetEffect(0)->GetTotalTicks() * int32(damage) / 100;
caster->CastCustomSpell(target, 63544, &basepoints0, NULL, NULL, true, NULL, GetEffect(0));
+18 -13
View File
@@ -2466,9 +2466,10 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx);
}
caster->DealSpellDamage(&damageInfo, true);
m_damage = damageInfo.damage;
caster->DealSpellDamage(&damageInfo, true);
}
// Passive spell hits/misses or active spells only misses (only triggers)
else
@@ -2489,7 +2490,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
}
}
if (missInfo != SPELL_MISS_EVADE && m_caster && !m_caster->IsFriendlyTo(unit) && !m_spellInfo->IsPositive())
if (missInfo != SPELL_MISS_EVADE && m_caster && !m_caster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)))
{
m_caster->CombatStart(unit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO));
@@ -3412,6 +3413,20 @@ void Spell::_handle_immediate_phase()
// process items
for (std::list<ItemTargetInfo>::iterator ihit= m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
DoAllEffectOnTarget(&(*ihit));
if (!m_originalCaster)
return;
// Handle procs on cast
// TODO: finish new proc system:P
if (m_UniqueTargetInfo.empty() && m_targets.HasDst())
{
uint32 procAttacker = m_procAttacker;
if (!procAttacker)
procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS;
// Proc the spells that have DEST target
m_originalCaster->ProcDamageAndSpell(NULL, procAttacker, 0, m_procEx | PROC_EX_NORMAL_HIT, 0, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell);
}
}
void Spell::_handle_finish_phase()
@@ -4947,17 +4962,7 @@ SpellCastResult Spell::CheckCast(bool strict)
{
case SPELL_EFFECT_DUMMY:
{
if (m_spellInfo->Id == 51582) // Rocket Boots Engaged
{
if (m_caster->IsInWater())
return SPELL_FAILED_ONLY_ABOVEWATER;
}
else if (m_spellInfo->Id == 52264) // Deliver Stolen Horse
{
if (!m_caster->FindNearestCreature(28653, 5))
return SPELL_FAILED_OUT_OF_RANGE;
}
else if (m_spellInfo->Id == 31789) // Righteous Defense
if (m_spellInfo->Id == 31789) // Righteous Defense
{
if (m_caster->GetTypeId() != TYPEID_PLAYER)
return SPELL_FAILED_DONT_REPORT;
+15 -22
View File
@@ -446,7 +446,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
{
uint32 pdamage = uint32(std::max(aura->GetAmount(), 0));
pdamage = m_caster->SpellDamageBonusDone(unitTarget, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
pdamage = unitTarget->SpellDamageBonusTaken(aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
pdamage = unitTarget->SpellDamageBonusTaken(m_caster, aura->GetSpellInfo(), pdamage, DOT, aura->GetBase()->GetStackAmount());
uint32 pct_dir = m_caster->CalculateSpellDamage(unitTarget, m_spellInfo, (effIndex + 1));
uint8 baseTotalTicks = uint8(m_caster->CalcSpellDuration(aura->GetSpellInfo()) / aura->GetSpellInfo()->Effects[EFFECT_0].Amplitude);
damage += int32(CalculatePctU(pdamage * baseTotalTicks, pct_dir));
@@ -485,7 +485,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (m_spellInfo->SpellFamilyFlags[1] & 0x2)
{
int32 back_damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
back_damage = unitTarget->SpellDamageBonusTaken(m_spellInfo, (uint32)back_damage, SPELL_DIRECT_DAMAGE);
back_damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, (uint32)back_damage, SPELL_DIRECT_DAMAGE);
// Pain and Suffering reduces damage
if (AuraEffect* aurEff = m_caster->GetDummyAuraEffect(SPELLFAMILY_PRIEST, 2874, 0))
AddPctN(back_damage, -aurEff->GetAmount());
@@ -694,7 +694,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
if (m_originalCaster && damage > 0 && apply_direct_bonus)
{
damage = m_originalCaster->SpellDamageBonusDone(unitTarget, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
damage = unitTarget->SpellDamageBonusTaken(m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
damage = unitTarget->SpellDamageBonusTaken(m_originalCaster, m_spellInfo, (uint32)damage, SPELL_DIRECT_DAMAGE);
}
m_damage += damage;
@@ -1375,7 +1375,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex)
// add spell damage bonus
damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
damage = unitTarget->SpellDamageBonusTaken(m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
int32 power = damage;
@@ -1538,10 +1538,7 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
int32 tickheal = targetAura->GetAmount();
if (Unit* auraCaster = targetAura->GetCaster())
{
tickheal = auraCaster->SpellHealingBonusDone(unitTarget, targetAura->GetSpellInfo(), tickheal, DOT);
tickheal = unitTarget->SpellHealingBonusTaken(targetAura->GetSpellInfo(), tickheal, DOT);
}
//int32 tickheal = targetAura->GetSpellInfo()->EffectBasePoints[idx] + 1;
//It is said that talent bonus should not be included
@@ -1562,12 +1559,12 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
//addhealth += tickheal * tickcount;
//addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth, HEAL, unitTarget);
}
// Glyph of Nourish
// Nourish
else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && m_spellInfo->SpellFamilyFlags[1] & 0x2000000)
{
addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
addhealth = unitTarget->SpellHealingBonusTaken(m_spellInfo, addhealth, HEAL);
// Glyph of Nourish
if (AuraEffect const* aurEff = m_caster->GetAuraEffect(62971, 0))
{
Unit::AuraEffectList const& Periodic = unitTarget->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL);
@@ -1584,7 +1581,7 @@ void Spell::EffectHeal(SpellEffIndex /*effIndex*/)
else
addhealth = caster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
addhealth = unitTarget->SpellHealingBonusTaken(m_spellInfo, addhealth, HEAL);
addhealth = unitTarget->SpellHealingBonusTaken(caster, m_spellInfo, addhealth, HEAL);
// Remove Grievious bite if fully healed
if (unitTarget->HasAura(48920) && (unitTarget->GetHealth() + addhealth >= unitTarget->GetMaxHealth()))
@@ -1611,7 +1608,7 @@ void Spell::EffectHealPct(SpellEffIndex /*effIndex*/)
return;
uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, unitTarget->CountPctFromMaxHealth(damage), HEAL);
heal = unitTarget->SpellHealingBonusTaken(m_spellInfo, heal, HEAL);
heal = unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
m_healing += heal;
}
@@ -1630,7 +1627,7 @@ void Spell::EffectHealMechanical(SpellEffIndex /*effIndex*/)
uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, uint32(damage), HEAL);
m_healing += unitTarget->SpellHealingBonusTaken(m_spellInfo, heal, HEAL);;
m_healing += unitTarget->SpellHealingBonusTaken(m_originalCaster, m_spellInfo, heal, HEAL);
}
void Spell::EffectHealthLeech(SpellEffIndex effIndex)
@@ -1642,7 +1639,7 @@ void Spell::EffectHealthLeech(SpellEffIndex effIndex)
return;
damage = m_caster->SpellDamageBonusDone(unitTarget, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
damage = unitTarget->SpellDamageBonusTaken(m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
damage = unitTarget->SpellDamageBonusTaken(m_caster, m_spellInfo, uint32(damage), SPELL_DIRECT_DAMAGE);
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "HealthLeech :%i", damage);
@@ -1655,7 +1652,7 @@ void Spell::EffectHealthLeech(SpellEffIndex effIndex)
if (m_caster->isAlive())
{
healthGain = m_caster->SpellHealingBonusDone(m_caster, m_spellInfo, healthGain, HEAL);
healthGain = m_caster->SpellHealingBonusTaken(m_spellInfo, healthGain, HEAL);
healthGain = m_caster->SpellHealingBonusTaken(m_caster, m_spellInfo, healthGain, HEAL);
m_caster->HealBySpell(m_caster, m_spellInfo, uint32(healthGain));
}
@@ -3520,8 +3517,8 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
// Add melee damage bonuses (also check for negative)
uint32 damage = m_caster->MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo);
m_damage += unitTarget->MeleeDamageBonusTaken(damage, m_attackType, m_spellInfo);
m_damage += unitTarget->MeleeDamageBonusTaken(m_caster, damage, m_attackType, m_spellInfo);
}
void Spell::EffectThreat(SpellEffIndex /*effIndex*/)
@@ -3546,7 +3543,7 @@ void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
if (!unitTarget || !unitTarget->isAlive())
return;
int32 addhealth;
int32 addhealth = 0;
// damage == 0 - heal for caster max health
if (damage == 0)
@@ -3554,11 +3551,7 @@ void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
else
addhealth = unitTarget->GetMaxHealth() - unitTarget->GetHealth();
if (m_originalCaster)
{
uint32 heal = m_originalCaster->SpellHealingBonusDone(unitTarget, m_spellInfo, addhealth, HEAL);
m_healing += unitTarget->SpellHealingBonusTaken(m_spellInfo, heal, HEAL);
}
m_healing += addhealth;
}
void Spell::EffectInterruptCast(SpellEffIndex effIndex)
+12 -14
View File
@@ -351,7 +351,7 @@ bool SpellEffectInfo::IsEffect() const
bool SpellEffectInfo::IsEffect(SpellEffects effectName) const
{
return Effect == effectName;
return Effect == uint32(effectName);
}
bool SpellEffectInfo::IsAura() const
@@ -1982,22 +1982,20 @@ uint32 SpellInfo::GetMaxTicks() const
if (DotDuration > 30000)
DotDuration = 30000;
uint8 x = 0;
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
for (uint8 x = 0; x < MAX_SPELL_EFFECTS; x++)
{
if (Effects[j].Effect == SPELL_EFFECT_APPLY_AURA && (
Effects[j].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE ||
Effects[j].ApplyAuraName == SPELL_AURA_PERIODIC_HEAL ||
Effects[j].ApplyAuraName == SPELL_AURA_PERIODIC_LEECH))
{
x = j;
break;
}
if (Effects[x].Effect == SPELL_EFFECT_APPLY_AURA)
switch (Effects[x].ApplyAuraName)
{
case SPELL_AURA_PERIODIC_DAMAGE:
case SPELL_AURA_PERIODIC_HEAL:
case SPELL_AURA_PERIODIC_LEECH:
if (Effects[x].Amplitude != 0)
return DotDuration / Effects[x].Amplitude;
break;
}
}
if (Effects[x].Amplitude != 0)
return DotDuration / Effects[x].Amplitude;
return 6;
}