diff options
-rw-r--r-- | src/game/Player.cpp | 2 | ||||
-rw-r--r-- | src/game/Spell.cpp | 56 | ||||
-rw-r--r-- | src/game/Spell.h | 22 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 59 | ||||
-rw-r--r-- | src/game/Unit.cpp | 31 | ||||
-rw-r--r-- | src/game/Unit.h | 3 |
6 files changed, 105 insertions, 68 deletions
diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 3eb5563831f..c6e7b65249e 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -16603,7 +16603,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, uint32 mount_i ModifyMoney(-(int32)totalcost); // prevent stealth flight - RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + RemoveInterruptableAura(AURA_INTERRUPT_FLAG_STEALTH); WorldPacket data(SMSG_ACTIVATETAXIREPLY, 4); data << uint32(ERR_TAXIOK); diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 074eff34950..a200ef88467 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -94,7 +94,7 @@ void SpellCastTargets::setUnitTarget(Unit *target) m_targetMask |= TARGET_FLAG_UNIT; } -void SpellCastTargets::setDestination(float x, float y, float z, bool send) +void SpellCastTargets::setDestination(float x, float y, float z, bool send, uint32 mapId) { m_destX = x; m_destY = y; @@ -102,6 +102,8 @@ void SpellCastTargets::setDestination(float x, float y, float z, bool send) m_hasDest = true; if(send) m_targetMask |= TARGET_FLAG_DEST_LOCATION; + if(mapId) + m_mapId = mapId; } void SpellCastTargets::setDestination(Unit *target, bool send) @@ -1006,12 +1008,14 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask) //if(!IsPositiveSpell(m_spellInfo->Id)) { - unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + //do not remove feign death + unit->RemoveInterruptableAura(AURA_INTERRUPT_FLAG_STEALTH + AURA_INTERRUPT_FLAG_DAMAGE); } } else { // for delayed spells ignore negative spells (after duel end) for friendly targets + // TODO: this cause soul transfer bugged if(m_spellInfo->speed > 0.0f && !IsPositiveSpell(m_spellInfo->Id)) { m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE); @@ -1249,13 +1253,24 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, Unit* pUnitTarget, f void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const uint32 &type, SpellTargets TargetType, uint32 entry) { - if(type == PUSH_DEST_CENTER && !m_targets.HasDest()) + float x, y; + if(type == PUSH_DEST_CENTER) { - sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id ); - return; + if(!m_targets.HasDest()) + { + sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id ); + return; + } + x = m_targets.m_destX; + y = m_targets.m_destY; + } + else + { + x = m_caster->GetPositionX(); + y = m_caster->GetPositionY(); } - CellPair p(Trinity::ComputeCellPair(m_targets.m_destX, m_targets.m_destY)); + CellPair p(Trinity::ComputeCellPair(x, y)); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); @@ -1435,12 +1450,21 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) case TARGET_TABLE_X_Y_Z_COORDINATES: if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id)) { - if (st->target_mapId == m_caster->GetMapId()) + //TODO: fix this check + if(m_spellInfo->Effect[0] == SPELL_EFFECT_TELEPORT_UNITS + || m_spellInfo->Effect[1] == SPELL_EFFECT_TELEPORT_UNITS + || m_spellInfo->Effect[2] == SPELL_EFFECT_TELEPORT_UNITS) + m_targets.setDestination(st->target_X, st->target_Y, st->target_Z, true, st->target_mapId); + else if(st->target_mapId == m_caster->GetMapId()) m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); } else sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id ); break; + case TARGET_INNKEEPER_COORDINATES: + if(m_caster->GetTypeId() == TYPEID_PLAYER) + m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, true, ((Player*)m_caster)->m_homebindMapId); + break; // area targets case TARGET_ALL_ENEMY_IN_AREA_INSTANT: @@ -1480,7 +1504,6 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) }break; case TARGET_IN_FRONT_OF_CASTER: case TARGET_UNIT_CONE_ENEMY_UNKNOWN: - { switch(spellmgr.GetSpellExtraAttr(m_spellInfo->Id, SPELL_EXTRA_ATTR_CONE_TYPE)) { default: @@ -1493,12 +1516,10 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) case 2: SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_AOE_DAMAGE); break; - } - }break; + }break; case TARGET_UNIT_CONE_ALLY: - { SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_FRIENDLY); - }break; + break; // nearby target case TARGET_UNIT_NEARBY_ALLY: @@ -1999,7 +2020,7 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) // destination around destination case TARGET_DEST_DEST_RANDOM: { - if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)) + if(!m_targets.HasDest()) { sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id); break; @@ -2013,7 +2034,11 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap) m_targets.setDestination(px, py, pz); }break; case TARGET_SELF2: - m_targets.m_hasDest = true; + if(!m_targets.HasDest()) + { + sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id); + break; + } break; default: break; @@ -2123,8 +2148,7 @@ void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura) // skip triggered spell (item equip spell casting and other not explicit character casts/item uses) if ( !m_IsTriggeredSpell && isSpellBreakStealth(m_spellInfo) ) { - m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - m_caster->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + m_caster->RemoveInterruptableAura(AURA_INTERRUPT_FLAG_STEALTH); } if(m_IsTriggeredSpell) diff --git a/src/game/Spell.h b/src/game/Spell.h index c6a18504784..f6fa5103578 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -111,6 +111,7 @@ class SpellCastTargets //m_srcY = target.m_srcY; //m_srcZ = target.m_srcZ; + m_mapId = 0; m_destX = target.m_destX; m_destY = target.m_destY; m_destZ = target.m_destZ; @@ -126,7 +127,7 @@ class SpellCastTargets uint64 getUnitTargetGUID() const { return m_unitTargetGUID; } Unit *getUnitTarget() const { return m_unitTarget; } void setUnitTarget(Unit *target); - void setDestination(float x, float y, float z, bool send = true); + void setDestination(float x, float y, float z, bool send = true, uint32 mapId = 0); void setDestination(Unit *target, bool send = true); uint64 getGOTargetGUID() const { return m_GOTargetGUID; } @@ -154,6 +155,7 @@ class SpellCastTargets void Update(Unit* caster); float m_srcX, m_srcY, m_srcZ; + uint32 m_mapId; float m_destX, m_destY, m_destZ; bool m_hasDest; std::string m_strTarget; @@ -548,21 +550,21 @@ namespace Trinity const uint32& i_push_type; float i_radius; SpellTargets i_TargetType; - Unit* i_originalCaster; + Unit* i_caster; uint32 i_entry; SpellNotifierCreatureAndPlayer(Spell &spell, std::list<Unit*> &data, float radius, const uint32 &type, SpellTargets TargetType = SPELL_TARGETS_AOE_DAMAGE, uint32 entry = 0) : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType), i_entry(entry) { - i_originalCaster = spell.GetCaster(); + i_caster = spell.GetCaster(); } template<class T> inline void Visit(GridRefManager<T> &m) { assert(i_data); - if(!i_originalCaster) + if(!i_caster) return; for(typename GridRefManager<T>::iterator itr = m.begin(); itr != m.end(); ++itr) @@ -573,7 +575,7 @@ namespace Trinity switch (i_TargetType) { case SPELL_TARGETS_FRIENDLY: - if (!itr->getSource()->isTargetableForAttack() || !i_originalCaster->IsFriendlyTo( itr->getSource() )) + if (!itr->getSource()->isTargetableForAttack() || !i_caster->IsFriendlyTo( itr->getSource() )) continue; break; case SPELL_TARGETS_AOE_DAMAGE: @@ -583,7 +585,7 @@ namespace Trinity if(!itr->getSource()->isTargetableForAttack()) continue; - Unit* check = i_originalCaster->GetCharmerOrOwnerOrSelf(); + Unit* check = i_caster->GetCharmerOrOwnerOrSelf(); if( check->GetTypeId()==TYPEID_PLAYER ) { @@ -607,19 +609,19 @@ namespace Trinity switch(i_push_type) { case PUSH_IN_FRONT: - if(i_spell.GetCaster()->isInFront((Unit*)(itr->getSource()), i_radius, M_PI/3 )) + if(i_caster->isInFront((Unit*)(itr->getSource()), i_radius, M_PI/3 )) i_data->push_back(itr->getSource()); break; case PUSH_IN_BACK: - if(i_spell.GetCaster()->isInBack((Unit*)(itr->getSource()), i_radius, M_PI/3 )) + if(i_caster->isInBack((Unit*)(itr->getSource()), i_radius, M_PI/3 )) i_data->push_back(itr->getSource()); break; case PUSH_IN_LINE: - if(i_spell.GetCaster()->isInLine((Unit*)(itr->getSource()), i_radius )) + if(i_caster->isInLine((Unit*)(itr->getSource()), i_radius )) i_data->push_back(itr->getSource()); break; case PUSH_SELF_CENTER: - if(i_spell.GetCaster()->IsWithinDistInMap((Unit*)(itr->getSource()), i_radius)) + if(i_caster->IsWithinDistInMap((Unit*)(itr->getSource()), i_radius)) i_data->push_back(itr->getSource()); break; case PUSH_DEST_CENTER: diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 6a335d73a06..555fe1bb055 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -1971,43 +1971,28 @@ void Spell::EffectTeleportUnits(uint32 i) if(!unitTarget || unitTarget->isInFlight()) return; - switch (m_spellInfo->EffectImplicitTargetB[i]) + // If not exist data for dest location - return + if(!m_targets.HasDest()) { - case TARGET_INNKEEPER_COORDINATES: - { - // Only players can teleport to innkeeper - if (unitTarget->GetTypeId() != TYPEID_PLAYER) - return; - - ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0); - return; - } - default: - { - // If not exist data for dest location - return - if(!m_targets.HasDest()) - { - sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id ); - return; - } - // Init dest coordinates - uint32 mapid = m_caster->GetMapId(); - float x = m_targets.m_destX; - float y = m_targets.m_destY; - float z = m_targets.m_destZ; - float orientation = unitTarget->GetOrientation(); - // Teleport - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); - else - { - MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); - WorldPacket data; - unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); - unitTarget->SendMessageToSet(&data, false); - } - return; - } + sLog.outError( "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id ); + return; + } + // Init dest coordinates + uint32 mapid = m_targets.m_mapId; + float x = m_targets.m_destX; + float y = m_targets.m_destY; + float z = m_targets.m_destZ; + float orientation = unitTarget->GetOrientation(); + sLog.outDebug("Spell::EffectTeleportUnits - teleport unit to %u %f %f %f\n", mapid, x, y, z); + // Teleport + if(unitTarget->GetTypeId() == TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); + else + { + MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); + WorldPacket data; + unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); + unitTarget->SendMessageToSet(&data, false); } // post effects for TARGET_TABLE_X_Y_Z_COORDINATES @@ -3489,7 +3474,7 @@ void Spell::EffectPickPocket(uint32 /*i*/) else { // Reveal action + get attack - m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + m_caster->RemoveInterruptableAura(AURA_INTERRUPT_FLAG_STEALTH); if (((Creature*)unitTarget)->AI()) ((Creature*)unitTarget)->AI()->AttackStart(m_caster); } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index a095083d4ae..b594f3c0767 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -454,6 +454,26 @@ void Unit::RemoveSpellsCausingAura(AuraType auraType) } } +void Unit::RemoveInterruptableAura(uint32 flag) +{ + AuraList::iterator iter, next; + for (iter = m_interruptableAuras.begin(); iter != m_interruptableAuras.end(); iter = next) + { + next = iter; + ++next; + + //sLog.outDetail("auraflag:%u flag:%u = %u",(*iter)->GetSpellProto()->AuraInterruptFlags,flag,(*iter)->GetSpellProto()->AuraInterruptFlags & flag); + if(*iter && ((*iter)->GetSpellProto()->AuraInterruptFlags & flag) == flag) + { + RemoveAurasDueToSpell((*iter)->GetId()); + if (!m_interruptableAuras.empty()) + next = m_interruptableAuras.begin(); + else + return; + } + } +} + bool Unit::HasAuraType(AuraType auraType) const { return (!m_modAuras[auraType].empty()); @@ -474,14 +494,13 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa } // remove affects from victim (including from 0 damage and DoTs) - if(pVictim != this) - pVictim->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + //if(pVictim != this) + // pVictim->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); // remove affects from attacker at any non-DoT damage (including 0 damage) if( damagetype != DOT) { - RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); + RemoveInterruptableAura(AURA_INTERRUPT_FLAG_STEALTH); if(pVictim->GetTypeId() == TYPEID_PLAYER && !pVictim->IsStandState() && !pVictim->hasUnitState(UNIT_STAT_STUNNED)) pVictim->SetStandState(PLAYER_STATE_NONE); @@ -3738,6 +3757,8 @@ bool Unit::AddAura(Aura *Aur) if (Aur->GetModifier()->m_auraname < TOTAL_AURAS) { m_modAuras[Aur->GetModifier()->m_auraname].push_back(Aur); + if(Aur->GetSpellProto()->AuraInterruptFlags) + m_interruptableAuras.push_back(Aur); } Aur->ApplyModifier(true,true); @@ -4110,6 +4131,8 @@ void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) if ((*i).second->GetModifier()->m_auraname < TOTAL_AURAS) { m_modAuras[(*i).second->GetModifier()->m_auraname].remove((*i).second); + if((*i).second->GetSpellProto()->AuraInterruptFlags) + m_interruptableAuras.remove((*i).second); } // remove from list before mods removing (prevent cyclic calls, mods added before including to aura list - use reverse order) diff --git a/src/game/Unit.h b/src/game/Unit.h index 81a2b5f8eb8..040e8300a03 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -71,6 +71,7 @@ enum SpellAuraInterruptFlags AURA_INTERRUPT_FLAG_UNK11 = 0x00000800, // 11 AURA_INTERRUPT_FLAG_UNK12 = 0x00001000, // 12 removed by attack? AURA_INTERRUPT_FLAG_UNK13 = 0x00002000, // 13 + AURA_INTERRUPT_FLAG_STEALTH = 0x00003C00, AURA_INTERRUPT_FLAG_UNK14 = 0x00004000, // 14 AURA_INTERRUPT_FLAG_UNK15 = 0x00008000, // 15 removed by casting a spell? AURA_INTERRUPT_FLAG_UNK16 = 0x00010000, // 16 @@ -1003,6 +1004,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject void RemoveNotOwnSingleTargetAuras(); void RemoveSpellsCausingAura(AuraType auraType); + void RemoveInterruptableAura(uint32 flag); void RemoveRankAurasDueToSpell(uint32 spellId); bool RemoveNoStackAurasDueToAura(Aura *Aur); void RemoveAurasWithInterruptFlags(uint32 flags); @@ -1300,6 +1302,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject uint32 m_removedAuras; AuraList m_modAuras[TOTAL_AURAS]; + AuraList m_interruptableAuras; float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END]; float m_weaponDamage[MAX_ATTACK][2]; bool m_canModifyStats; |