diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/game/CharacterHandler.cpp | 3 | ||||
| -rw-r--r-- | src/game/PetAI.cpp | 36 | ||||
| -rw-r--r-- | src/game/Player.cpp | 132 | ||||
| -rw-r--r-- | src/game/Player.h | 2 | ||||
| -rw-r--r-- | src/game/PlayerDump.cpp | 2 | ||||
| -rw-r--r-- | src/game/Spell.cpp | 11 | ||||
| -rw-r--r-- | src/game/SpellEffects.cpp | 6 | ||||
| -rw-r--r-- | src/game/SpellMgr.cpp | 45 | ||||
| -rw-r--r-- | src/game/SpellMgr.h | 4 | ||||
| -rw-r--r-- | src/game/Unit.cpp | 38 | ||||
| -rw-r--r-- | src/game/Unit.h | 5 |
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); |
