aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/CharacterHandler.cpp3
-rw-r--r--src/game/PetAI.cpp36
-rw-r--r--src/game/Player.cpp132
-rw-r--r--src/game/Player.h2
-rw-r--r--src/game/PlayerDump.cpp2
-rw-r--r--src/game/Spell.cpp11
-rw-r--r--src/game/SpellEffects.cpp6
-rw-r--r--src/game/SpellMgr.cpp45
-rw-r--r--src/game/SpellMgr.h4
-rw-r--r--src/game/Unit.cpp38
-rw-r--r--src/game/Unit.h5
11 files changed, 153 insertions, 131 deletions
diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp
index 2f9c590c0d0..056bcd816e0 100644
--- a/src/game/CharacterHandler.cpp
+++ b/src/game/CharacterHandler.cpp
@@ -854,6 +854,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder)
sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)",
GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow());
+ if(!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED))
+ pCurrChar->SetStandState(UNIT_STAND_STATE_STAND);
+
m_playerLoading = false;
delete holder;
}
diff --git a/src/game/PetAI.cpp b/src/game/PetAI.cpp
index 9515cbba46d..0fcc707b104 100644
--- a/src/game/PetAI.cpp
+++ b/src/game/PetAI.cpp
@@ -122,8 +122,8 @@ void PetAI::UpdateAI(const uint32 diff)
bool inCombat = me->getVictim();
- //Autocast (casted only in combat)
- if (inCombat && m_creature->GetGlobalCooldown() == 0 && !m_creature->hasUnitState(UNIT_STAT_CASTING))
+ // Autocast (casted only in combat or persistent spells in any state)
+ if (m_creature->GetGlobalCooldown() == 0 && !m_creature->hasUnitState(UNIT_STAT_CASTING))
{
typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList;
TargetSpellList targetSpellStore;
@@ -139,12 +139,38 @@ void PetAI::UpdateAI(const uint32 diff)
continue;
// ignore some combinations of combat state and combat/noncombat spells
- if (IsNonCombatSpell(spellInfo))
- continue;
+ if (!inCombat)
+ {
+ // ignore attacking spells, and allow only self/around spells
+ if (!IsPositiveSpell(spellInfo->Id))
+ continue;
+
+ // non combat spells allowed
+ // only pet spells have IsNonCombatSpell and not fit this reqs:
+ // Consume Shadows, Lesser Invisibility, so ignore checks for its
+ if (!IsNonCombatSpell(spellInfo))
+ {
+ // allow only spell without spell cost or with spell cost but not duration limit
+ int32 duration = GetSpellDuration(spellInfo);
+ if ((spellInfo->manaCost || spellInfo->ManaCostPercentage || spellInfo->manaPerSecond) && duration > 0)
+ continue;
+
+ // allow only spell without cooldown > duration
+ int32 cooldown = GetSpellRecoveryTime(spellInfo);
+ if (cooldown >= 0 && duration >= 0 && cooldown > duration)
+ continue;
+ }
+ }
+ else
+ {
+ // just ignore non-combat spells
+ if (IsNonCombatSpell(spellInfo))
+ continue;
+ }
Spell *spell = new Spell(m_creature, spellInfo, false, 0);
- if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim()))
+ if (inCombat && !m_creature->hasUnitState(UNIT_STAT_FOLLOW) && spell->CanAutoCast(m_creature->getVictim()))
{
targetSpellStore.push_back(std::make_pair<Unit*, Spell*>(m_creature->getVictim(), spell));
continue;
diff --git a/src/game/Player.cpp b/src/game/Player.cpp
index 9f28c399c1f..54441fa1a16 100644
--- a/src/game/Player.cpp
+++ b/src/game/Player.cpp
@@ -746,14 +746,14 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
switch(iProto->Spells[0].SpellCategory)
{
case 11: // food
- if(iProto->Stackable > 4)
- count = 4;
+ count = getClass()==CLASS_DEATH_KNIGHT ? 10 : 4;
break;
case 59: // drink
- if(iProto->Stackable > 2)
- count = 2;
+ count = 2;
break;
}
+ if(iProto->Stackable < count)
+ count = iProto->Stackable;
}
StoreNewItemInBestSlots(item_id, count);
@@ -15172,7 +15172,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
delete result;
}
- if(getClass() == CLASS_WARRIOR)
+ if(getClass() == CLASS_WARRIOR && !HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true);
}
@@ -16064,26 +16064,9 @@ void Player::SaveToDB()
// first save/honor gain after midnight will also update the player's honor fields
UpdateHonorFields();
- uint32 is_save_resting = HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0;
- //save, far from tavern/city
- //save, but in tavern/city
sLog.outDebug("The value of player %s at save: ", m_name.c_str());
outDebugValues();
- // save state (after auras removing), if aura remove some flags then it must set it back by self)
- uint32 tmp_bytes = GetUInt32Value(UNIT_FIELD_BYTES_1);
- uint32 tmp_bytes2 = GetUInt32Value(UNIT_FIELD_BYTES_2);
- uint32 tmp_flags = GetUInt32Value(UNIT_FIELD_FLAGS);
- uint32 tmp_pflags = GetUInt32Value(PLAYER_FLAGS);
- uint32 tmp_displayid = GetDisplayId();
-
- // Set player sit state to standing on save, also stealth and shifted form
- SetByteValue(UNIT_FIELD_BYTES_1, 0, UNIT_STAND_STATE_STAND);
- SetByteValue(UNIT_FIELD_BYTES_2, 3, 0); // shapeshift
- RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED);
-
- bool inworld = IsInWorld();
-
CharacterDatabase.BeginTransaction();
CharacterDatabase.PExecute("DELETE FROM characters WHERE guid = '%u'",GetGUIDLow());
@@ -16140,69 +16123,48 @@ void Player::SaveToDB()
ss << "', ";
- ss << m_taxi; // string with TaxiMaskSize numbers
+ ss << m_taxi << ", "; // string with TaxiMaskSize numbers
- ss << ", ";
- ss << (inworld ? 1 : 0);
+ ss << (IsInWorld() ? 1 : 0) << ", ";
- ss << ", ";
- ss << m_cinematic;
+ ss << m_cinematic << ", ";
- ss << ", ";
- ss << m_Played_time[PLAYED_TIME_TOTAL];
- ss << ", ";
- ss << m_Played_time[PLAYED_TIME_LEVEL];
+ ss << m_Played_time[PLAYED_TIME_TOTAL] << ", ";
+ ss << m_Played_time[PLAYED_TIME_LEVEL] << ", ";
- ss << ", ";
- ss << finiteAlways(m_rest_bonus);
- ss << ", ";
- ss << (uint64)time(NULL);
- ss << ", ";
- ss << is_save_resting;
- ss << ", ";
- ss << m_resetTalentsCost;
- ss << ", ";
- ss << (uint64)m_resetTalentsTime;
+ ss << finiteAlways(m_rest_bonus) << ", ";
+ ss << (uint64)time(NULL) << ", ";
+ ss << (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) ? 1 : 0) << ", ";
+ //save, far from tavern/city
+ //save, but in tavern/city
+ ss << m_resetTalentsCost << ", ";
+ ss << (uint64)m_resetTalentsTime << ", ";
- ss << ", ";
- ss << finiteAlways(m_movementInfo.t_x);
- ss << ", ";
- ss << finiteAlways(m_movementInfo.t_y);
- ss << ", ";
- ss << finiteAlways(m_movementInfo.t_z);
- ss << ", ";
- ss << finiteAlways(m_movementInfo.t_o);
- ss << ", ";
+ ss << finiteAlways(m_movementInfo.t_x) << ", ";
+ ss << finiteAlways(m_movementInfo.t_y) << ", ";
+ ss << finiteAlways(m_movementInfo.t_z) << ", ";
+ ss << finiteAlways(m_movementInfo.t_o) << ", ";
if (m_transport)
ss << m_transport->GetGUIDLow();
else
ss << "0";
-
ss << ", ";
- ss << m_ExtraFlags;
- ss << ", ";
- ss << uint32(m_stableSlots); // to prevent save uint8 as char
+ ss << m_ExtraFlags << ", ";
- ss << ", ";
- ss << uint32(m_atLoginFlags);
+ ss << uint32(m_stableSlots) << ", "; // to prevent save uint8 as char
- ss << ", ";
- ss << GetZoneId();
+ ss << uint32(m_atLoginFlags) << ", ";
- ss << ", ";
- ss << (uint64)m_deathExpireTime;
+ ss << GetZoneId() << ", ";
- ss << ", '";
- ss << m_taxi.SaveTaxiDestinationsToString();
+ ss << (uint64)m_deathExpireTime << ", '";
- ss << "', '0', ";
- ss << GetSession()->GetLatency();
- ss << ", ";
- ss << GetBattleGroundId();
- ss << ", ";
- ss << GetBGTeam();
- ss << ", ";
+ ss << m_taxi.SaveTaxiDestinationsToString() << "', ";
+ ss << "'0', "; // arena_pending_points
+ ss << GetSession()->GetLatency() << ", ";
+ ss << GetBattleGroundId() << ", ";
+ ss << GetBGTeam() << ", ";
ss << m_bgEntryPoint.mapid << ", "
<< finiteAlways(m_bgEntryPoint.coord_x) << ", "
<< finiteAlways(m_bgEntryPoint.coord_y) << ", "
@@ -16229,12 +16191,6 @@ void Player::SaveToDB()
CharacterDatabase.CommitTransaction();
- // restore state (before aura apply, if aura remove flag then aura must set it ack by self)
- SetUInt32Value(UNIT_FIELD_BYTES_1, tmp_bytes);
- SetUInt32Value(UNIT_FIELD_BYTES_2, tmp_bytes2);
- SetUInt32Value(UNIT_FIELD_FLAGS, tmp_flags);
- SetUInt32Value(PLAYER_FLAGS, tmp_pflags);
-
// save pet (hunter pet level and experience and all type pets health/mana).
if(Pet* pet = GetPet())
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
@@ -16291,12 +16247,10 @@ void Player::_SaveAuras()
// skip:
// area auras or single cast auras casted by other unit
// passive auras and stances
- if (itr->second->IsPassive()
- || itr->second->IsAuraType(SPELL_AURA_MOD_SHAPESHIFT)
- || itr->second->IsRemovedOnShapeLost())
+ if (itr->second->IsPassive())
continue;
- bool isCaster = itr->second->GetCasterGUID() == GetGUID();
- if (!isCaster)
+
+ if (itr->second->GetCasterGUID() != GetGUID())
if (IsSingleTargetSpell(itr->second->GetSpellProto())
|| itr->second->IsAreaAura())
continue;
@@ -19918,13 +19872,6 @@ void Player::SetClientControl(Unit* target, uint8 allowMove)
void Player::UpdateZoneDependentAuras( uint32 newZone )
{
- // remove new continent flight forms
- if( !IsAllowUseFlyMountsHere() )
- {
- RemoveAurasByType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED);
- RemoveAurasByType(SPELL_AURA_FLY);
- }
-
// Some spells applied at enter into zone (with subzones), aura removed in UpdateAreaDependentAuras that called always at zone->area update
SpellAreaForAreaMapBounds saBounds = spellmgr.GetSpellAreaForAreaMapBounds(newZone);
for(SpellAreaForAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
@@ -20531,14 +20478,11 @@ uint32 Player::CalculateTalentsPoints() const
return uint32(talentPointsForLevel * sWorld.getRate(RATE_TALENT));
}
-bool Player::IsAllowUseFlyMountsHere() const
+bool Player::IsKnowHowFlyIn(uint32 mapid, uint32 zone) const
{
- if (isGameMaster())
- return true;
-
- uint32 zoneId = GetZoneId();
- uint32 v_map = GetVirtualMapForMapAndZone(GetMapId(), zoneId);
- return v_map == 530 || v_map == 571 && HasSpell(54197) && zoneId != 4197;
+ // continent checked in SpellMgr::GetSpellAllowedInLocationError at cast and area update
+ uint32 v_map = GetVirtualMapForMapAndZone(mapid, zone);
+ return v_map != 571 || HasSpell(54197) && zone != 4197; // Cold Weather Flying
}
void Player::learnSpellHighRank(uint32 spellid)
diff --git a/src/game/Player.h b/src/game/Player.h
index fa0153e8b51..692be08c4a7 100644
--- a/src/game/Player.h
+++ b/src/game/Player.h
@@ -2005,7 +2005,7 @@ class TRINITY_DLL_SPEC Player : public Unit
}
void HandleFall(MovementInfo const& movementInfo);
- bool IsAllowUseFlyMountsHere() const;
+ bool IsKnowHowFlyIn(uint32 mapid, uint32 zone) const;
void SetClientControl(Unit* target, uint8 allowMove);
diff --git a/src/game/PlayerDump.cpp b/src/game/PlayerDump.cpp
index 2187614d368..06550269856 100644
--- a/src/game/PlayerDump.cpp
+++ b/src/game/PlayerDump.cpp
@@ -583,7 +583,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
ROLLBACK(DUMP_FILE_BROKEN);
if(!changetoknth(vals, ITEM_FIELD_OWNER+1, newguid))
ROLLBACK(DUMP_FILE_BROKEN);
- if(!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, objmgr.m_ItemTextId))
+ if(!changetokGuid(vals, ITEM_FIELD_ITEM_TEXT_ID+1, itemTexts, objmgr.m_ItemTextId,true))
ROLLBACK(DUMP_FILE_BROKEN);
if(!changenth(line, 3, vals.c_str()))
ROLLBACK(DUMP_FILE_BROKEN);
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp
index 6d635687013..81a30505cc4 100644
--- a/src/game/Spell.cpp
+++ b/src/game/Spell.cpp
@@ -5138,14 +5138,15 @@ SpellCastResult Spell::CheckCast(bool strict)
break;
}
- case SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED:
case SPELL_AURA_FLY:
+ case SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED:
{
- // not allow cast fly spells at old maps by players (all spells is self target)
- if(m_originalCaster && m_originalCaster->GetTypeId()==TYPEID_PLAYER)
+ // not allow cast fly spells if not have req. skills (all spells is self target)
+ // allow always ghost flight spells
+ if (m_originalCaster && m_originalCaster->GetTypeId() == TYPEID_PLAYER && m_originalCaster->isAlive())
{
- if( !((Player*)m_originalCaster)->IsAllowUseFlyMountsHere() )
- return SPELL_FAILED_NOT_HERE;
+ if (!((Player*)m_originalCaster)->IsKnowHowFlyIn(m_originalCaster->GetMapId(),m_originalCaster->GetMapId()))
+ return m_IsTriggeredSpell ? SPELL_FAILED_DONT_REPORT : SPELL_FAILED_NOT_HERE;
}
break;
}
diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp
index 9b414ed9f66..db5cb899f8f 100644
--- a/src/game/SpellEffects.cpp
+++ b/src/game/SpellEffects.cpp
@@ -5359,8 +5359,8 @@ void Spell::EffectScriptEffect(uint32 effIndex)
}
case SPELLFAMILY_PALADIN:
{
- // Judgement
- if (m_spellInfo->SpellFamilyFlags[0] & 0x800000 || m_spellInfo->SpellFamilyFlags[2] & 0x8)
+ // Judgement (seal trigger)
+ if (m_spellInfo->Category == SPELLCATEGORY_JUDGEMENT)
{
if(!unitTarget || !unitTarget->isAlive())
return;
@@ -5370,12 +5370,12 @@ void Spell::EffectScriptEffect(uint32 effIndex)
// Judgement self add switch
switch (m_spellInfo->Id)
{
- case 41467: break; // Judgement
case 53407: spellId1 = 20184; break; // Judgement of Justice
case 20271: // Judgement of Light
case 57774: spellId1 = 20185; break; // Judgement of Light
case 53408: spellId1 = 20186; break; // Judgement of Wisdom
default:
+ sLog.outError("Unsupported Judgement (seal trigger) spell (Id: %u) in Spell::EffectScriptEffect",m_spellInfo->Id);
return;
}
// all seals have aura dummy in 2 effect
diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp
index 2144bd573e7..c5f267e0313 100644
--- a/src/game/SpellMgr.cpp
+++ b/src/game/SpellMgr.cpp
@@ -575,6 +575,10 @@ SpellSpecific GetSpellSpecific(uint32 spellId)
if (spellInfo->SpellFamilyFlags[0] & 0x11010002)
return SPELL_BLESSING;
+
+ if (spellInfo->SpellFamilyFlags[0] & 0x00002190)
+ return SPELL_HAND;
+
// Judgement of Wisdom, Judgement of Light, Judgement of Justice
if (spellInfo->Id == 20184 || spellInfo->Id == 20185 || spellInfo->Id == 20186)
return SPELL_JUDGEMENT;
@@ -634,6 +638,7 @@ bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2)
{
case SPELL_SEAL:
case SPELL_BLESSING:
+ case SPELL_HAND:
case SPELL_AURA:
case SPELL_STING:
case SPELL_CURSE:
@@ -2466,10 +2471,15 @@ void SpellMgr::LoadSpellAreas()
continue;
}
- if(spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_DUMMY && spellInfo->EffectApplyAuraName[0]!=SPELL_AURA_PHASE)
+ switch(spellInfo->EffectApplyAuraName[0])
{
- sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase aura in effect 0", spell,abs(spellArea.auraSpell));
- continue;
+ case SPELL_AURA_DUMMY:
+ case SPELL_AURA_PHASE:
+ case SPELL_AURA_GHOST:
+ break;
+ default:
+ sLog.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase/ghost aura in effect 0", spell,abs(spellArea.auraSpell));
+ continue;
}
if(abs(spellArea.auraSpell)==spellArea.spellId)
@@ -2562,8 +2572,12 @@ void SpellMgr::LoadSpellAreas()
SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player)
{
+ // allow in GM-mode
+ if (player && player->isGameMaster())
+ return SPELL_CAST_OK;
+
// normal case
- if( spellInfo->AreaGroupId > 0)
+ if (spellInfo->AreaGroupId > 0)
{
bool found = false;
AreaGroupEntry const* groupEntry = sAreaGroupStore.LookupEntry(spellInfo->AreaGroupId);
@@ -2582,9 +2596,18 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
return SPELL_FAILED_INCORRECT_AREA;
}
+ // continent limitation (virtual continent)
+ if (spellInfo->AttributesEx4 & SPELL_ATTR_EX4_CAST_ONLY_IN_OUTLAND)
+ {
+ uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id);
+ MapEntry const* mapEntry = sMapStore.LookupEntry(v_map);
+ if(!mapEntry || mapEntry->addon < 1 || !mapEntry->IsContinent())
+ return SPELL_FAILED_INCORRECT_AREA;
+ }
+
// DB base check (if non empty then must fit at least single for allow)
SpellAreaMapBounds saBounds = spellmgr.GetSpellAreaMapBounds(spellInfo->Id);
- if(saBounds.first != saBounds.second)
+ if (saBounds.first != saBounds.second)
{
for(SpellAreaMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
{
@@ -2611,21 +2634,21 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
case 44535: // Spirit Heal (mana)
{
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
- if(!mapEntry)
+ if (!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
return mapEntry->IsBattleGround() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
}
case 44521: // Preparation
{
- if(!player)
+ if (!player)
return SPELL_FAILED_REQUIRES_AREA;
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
- if(!mapEntry)
+ if (!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
- if(!mapEntry->IsBattleGround())
+ if (!mapEntry->IsBattleGround())
return SPELL_FAILED_REQUIRES_AREA;
BattleGround* bg = player->GetBattleGround();
@@ -2637,14 +2660,14 @@ SpellCastResult SpellMgr::GetSpellAllowedInLocationError(SpellEntry const *spell
case 35775: // Green Team (Horde)
{
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
- if(!mapEntry)
+ if (!mapEntry)
return SPELL_FAILED_INCORRECT_AREA;
return mapEntry->IsBattleArena() && player && player->InBattleGround() ? SPELL_CAST_OK : SPELL_FAILED_REQUIRES_AREA;
}
case 32727: // Arena Preparation
{
- if(!player)
+ if (!player)
return SPELL_FAILED_REQUIRES_AREA;
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h
index 42767a7df09..0aae9fc43a4 100644
--- a/src/game/SpellMgr.h
+++ b/src/game/SpellMgr.h
@@ -44,7 +44,8 @@ struct SpellModifier;
enum SpellCategories
{
SPELLCATEGORY_HEALTH_MANA_POTIONS = 4,
- SPELLCATEGORY_DEVOUR_MAGIC = 12
+ SPELLCATEGORY_DEVOUR_MAGIC = 12,
+ SPELLCATEGORY_JUDGEMENT = 1210, // Judgement (seal trigger)
};
enum SpellDisableTypes
@@ -121,6 +122,7 @@ enum SpellSpecific
SPELL_MAGE_ARCANE_BRILLANCE = 24,
SPELL_WARRIOR_ENRAGE = 25,
SPELL_PRIEST_DIVINE_SPIRIT = 26,
+ SPELL_HAND = 27,
};
#define SPELL_LINKED_MAX_SPELLS 200000
diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp
index 4622c4cfe9e..794a3e7bcd0 100644
--- a/src/game/Unit.cpp
+++ b/src/game/Unit.cpp
@@ -868,6 +868,8 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
// only lootable if it has loot or can drop gold
if(cVictim->GetCreatureInfo()->lootid || cVictim->GetCreatureInfo()->maxgold > 0)
cVictim->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ else
+ cVictim->lootForBody = true; // needed for skinning
}
// Call creature just died function
if (cVictim->AI())
@@ -3776,8 +3778,10 @@ bool Unit::AddAura(Aura *Aur, bool handleEffects)
return false;
}
+ SpellEntry const* aurSpellInfo = Aur->GetSpellProto();
+
// ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
- if( !isAlive() && Aur->GetId() != 20584 && Aur->GetId() != 8326 && Aur->GetId() != 2584 &&
+ if( !isAlive() && !IsDeathPersistentSpell(aurSpellInfo) &&
(GetTypeId()!=TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) )
{
delete Aur;
@@ -3793,7 +3797,6 @@ bool Unit::AddAura(Aura *Aur, bool handleEffects)
return false;
}
- SpellEntry const* aurSpellInfo = Aur->GetSpellProto();
uint32 aurId = aurSpellInfo->Id;
// passive and persistent and Incanter's Absorption auras can stack with themselves any number of times
@@ -4174,13 +4177,24 @@ void Unit::RemoveAurasByTypeWithDispel(AuraType auraType, Spell * spell)
}
}
-void Unit::RemoveNotOwnSingleTargetAuras()
+void Unit::RemoveNotOwnSingleTargetAuras(uint32 newPhase)
{
// single target auras from other casters
for (AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end(); )
{
if (iter->second->GetCasterGUID()!=GetGUID() && IsSingleTargetSpell(iter->second->GetSpellProto()))
- RemoveAura(iter);
+ {
+ if(!newPhase)
+ RemoveAura(iter);
+ else
+ {
+ Unit* caster = iter->second->GetCaster();
+ if(!caster || !caster->InSamePhase(newPhase))
+ RemoveAura(iter);
+ else
+ ++iter;
+ }
+ }
else
++iter;
}
@@ -4189,12 +4203,12 @@ void Unit::RemoveNotOwnSingleTargetAuras()
AuraList& scAuras = GetSingleCastAuras();
for (AuraList::iterator iter = scAuras.begin(); iter != scAuras.end();)
{
- Aura * aur=*iter;
+ Aura * aura=*iter;
++iter;
- if (aur->GetTarget()!=this)
+ if (aura->GetTarget() != this && !aura->GetTarget()->InSamePhase(newPhase))
{
uint32 removedAuras = m_removedAurasCount;
- aur->GetTarget()->RemoveAura(aur->GetId(),aur->GetCasterGUID());
+ aura->GetTarget()->RemoveAura(aura->GetId(),aura->GetCasterGUID());
if (removedAuras+1<m_removedAurasCount)
iter=scAuras.begin();
}
@@ -6395,8 +6409,8 @@ bool Unit::HandleDummyAuraProc(Unit *pVictim, uint32 damage, AuraEffect* trigger
triggered_spell_id = 40471;
chance = 15.0f;
}
- // Judgement
- else if( procSpell->SpellFamilyFlags[0] & 0x800000 )
+ // Judgement (any)
+ else if (GetSpellSpecific(procSpell->Id)==SPELL_JUDGEMENT)
{
triggered_spell_id = 40472;
chance = 50.0f;
@@ -14837,6 +14851,12 @@ float Unit::MeleeSpellMissChance(const Unit *pVictim, WeaponAttackType attType,
void Unit::SetPhaseMask(uint32 newPhaseMask, bool update)
{
+ if(newPhaseMask==GetPhaseMask())
+ return;
+
+ if(IsInWorld())
+ RemoveNotOwnSingleTargetAuras(newPhaseMask); // we can lost access to caster or target
+
WorldObject::SetPhaseMask(newPhaseMask,update);
if(!IsInWorld())
diff --git a/src/game/Unit.h b/src/game/Unit.h
index 5a09d0f8c0e..6d200566a2b 100644
--- a/src/game/Unit.h
+++ b/src/game/Unit.h
@@ -1450,7 +1450,10 @@ class TRINITY_DLL_SPEC Unit : public WorldObject
void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId);
void RemoveAurasByType(AuraType auraType, uint64 casterGUID = 0, Aura * except=NULL, bool negative = true, bool positive = true);
void RemoveAurasByTypeWithDispel(AuraType auraType, Spell * spell = NULL);
- void RemoveNotOwnSingleTargetAuras();
+ void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0);
+
+ void RemoveSpellsCausingAura(AuraType auraType);
+ void RemoveRankAurasDueToSpell(uint32 spellId);
bool RemoveNoStackAurasDueToAura(Aura *Aur);
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except = NULL);
void RemoveAurasWithFamily(uint32 family, uint32 familyFlag1, uint32 familyFlag2, uint32 familyFlag3, uint64 casterGUID);