diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 04fc0ae65..df4530399 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -426,6 +426,21 @@ void Spell::FillTargetMap() // but need it support in some know cases switch(m_spellInfo->EffectImplicitTargetA[i]) { + case TARGET_SELF: + switch(m_spellInfo->EffectImplicitTargetB[i]) + { + case 0: + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + break; + case TARGET_BEHIND_VICTIM: // use B case that not dependent from from A in fact + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + break; + default: + SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap); + SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap); + break; + } + break; case TARGET_CASTER_COORDINATES: // Note: this hack with search required until GO casting not implemented // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support @@ -2051,8 +2066,15 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) }break; case TARGET_BEHIND_VICTIM: { - Unit *pTarget = m_caster->getVictim(); - if(!pTarget && m_caster->GetTypeId() == TYPEID_PLAYER) + Unit *pTarget = NULL; + + // explicit cast data from client or server-side cast + // some spell at client send caster + if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster) + pTarget = m_targets.getUnitTarget(); + else if(m_caster->getVictim()) + pTarget = m_caster->getVictim(); + else if(m_caster->GetTypeId() == TYPEID_PLAYER) pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); if(pTarget) @@ -2060,9 +2082,13 @@ void Spell::SetTargetMap(uint32 i,uint32 cur,std::list &TagUnitMap) float _target_x, _target_y, _target_z; pTarget->GetClosePoint(_target_x, _target_y, _target_z, m_caster->GetObjectSize(), CONTACT_DISTANCE, M_PI); if(pTarget->IsWithinLOS(_target_x,_target_y,_target_z)) + { + TagUnitMap.push_back(m_caster); m_targets.setDestination(_target_x, _target_y, _target_z); + } } - }break; + break; + } case TARGET_DYNAMIC_OBJECT_COORDINATES: { // if parent spell create dynamic object extract area from it diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 5d3c54473..2ca158838 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2009,39 +2009,41 @@ void Spell::EffectJump(uint32 i) x = m_targets.m_destX; y = m_targets.m_destY; z = m_targets.m_destZ; - o = m_caster->GetOrientation(); + + if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM) + { + // explicit cast data from client or server-side cast + // some spell at client send caster + Unit* pTarget = NULL; + if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=m_caster) + pTarget = m_targets.getUnitTarget(); + else if(unitTarget->getVictim()) + pTarget = m_caster->getVictim(); + else if(m_caster->GetTypeId() == TYPEID_PLAYER) + pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); + + o = pTarget ? pTarget->GetOrientation() : m_caster->GetOrientation(); + } + else + o = m_caster->GetOrientation(); } else if(unitTarget) { - x = unitTarget->GetPositionX(); - y = unitTarget->GetPositionY(); - z = unitTarget->GetPositionZ(); - o = m_spellInfo->EffectImplicitTargetA[i] == TARGET_BEHIND_VICTIM - ? unitTarget->GetOrientation() - : m_caster->GetOrientation(); + unitTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE); + o = m_caster->GetOrientation(); } else if(gameObjTarget) { - x = gameObjTarget->GetPositionX(); - y = gameObjTarget->GetPositionY(); - z = gameObjTarget->GetPositionZ(); + gameObjTarget->GetContactPoint(m_caster,x,y,z,CONTACT_DISTANCE); o = m_caster->GetOrientation(); } - else - return; - - - // Teleport - if(m_caster->GetTypeId() == TYPEID_PLAYER) - ((Player*)m_caster)->TeleportTo(m_caster->GetMapId(), x, y, z, o, - TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); else { - m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, x, y, z, o); - WorldPacket data; - m_caster->BuildTeleportAckMsg(&data, x, y, z, o); - m_caster->SendMessageToSet(&data, false); + sLog.outError( "Spell::EffectJump - unsupported target mode for spell ID %u", m_spellInfo->Id ); + return; } + + m_caster->NearTeleportTo(x,y,z,o,true); } void Spell::EffectTeleportUnits(uint32 i) @@ -2062,45 +2064,38 @@ void Spell::EffectTeleportUnits(uint32 i) } case TARGET_TABLE_X_Y_Z_COORDINATES: { - // TODO: Only players can teleport? - if (unitTarget->GetTypeId() != TYPEID_PLAYER) - return; SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id); if(!st) { sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u", m_spellInfo->Id ); return; } - ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0); + + if(st->target_mapId==unitTarget->GetMapId()) + unitTarget->NearTeleportTo(st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster); + else if(unitTarget->GetTypeId()==TYPEID_PLAYER) + ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0); break; } case TARGET_BEHIND_VICTIM: { - // Get selected target for player (or victim for units) Unit *pTarget = NULL; - if(m_caster->GetTypeId() == TYPEID_PLAYER) - pTarget = ObjectAccessor::GetUnit(*m_caster, ((Player*)m_caster)->GetSelection()); - else - pTarget = m_caster->getVictim(); - // No target present - return - if (!pTarget) - return; + + // explicit cast data from client or server-side cast + // some spell at client send caster + if(m_targets.getUnitTarget() && m_targets.getUnitTarget()!=unitTarget) + pTarget = m_targets.getUnitTarget(); + else if(unitTarget->getVictim()) + pTarget = unitTarget->getVictim(); + else if(unitTarget->GetTypeId() == TYPEID_PLAYER) + pTarget = ObjectAccessor::GetUnit(*unitTarget, ((Player*)unitTarget)->GetSelection()); + // 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 = pTarget->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 - { - m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); - WorldPacket data; - unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); - unitTarget->SendMessageToSet(&data, false); - } + float orientation = pTarget ? pTarget->GetOrientation() : unitTarget->GetOrientation(); + unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster); return; } default: @@ -2118,15 +2113,7 @@ void Spell::EffectTeleportUnits(uint32 i) 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 - { - m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation); - WorldPacket data; - unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation); - unitTarget->SendMessageToSet(&data, false); - } + unitTarget->NearTeleportTo(x,y,z,orientation,unitTarget==m_caster); return; } } @@ -3787,16 +3774,12 @@ void Spell::EffectTeleUnitsFaceCaster(uint32 i) if(unitTarget->isInFlight()) return; - uint32 mapid = m_caster->GetMapId(); float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); float fx,fy,fz; m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis); - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); - else - m_caster->GetMap()->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation()); + unitTarget->NearTeleportTo(fx,fy,fz,-m_caster->GetOrientation(),unitTarget==m_caster); } void Spell::EffectLearnSkill(uint32 i) @@ -5800,7 +5783,6 @@ void Spell::EffectMomentMove(uint32 i) if( m_spellInfo->rangeIndex== 1) //self range { - uint32 mapid = m_caster->GetMapId(); float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); // before caster @@ -5810,7 +5792,7 @@ void Spell::EffectMomentMove(uint32 i) unitTarget->GetPosition(ox,oy,oz); float fx2,fy2,fz2; // getObjectHitPos overwrite last args in any result case - if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5)) + if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(unitTarget->GetMapId(), ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5)) { fx = fx2; fy = fy2; @@ -5818,10 +5800,7 @@ void Spell::EffectMomentMove(uint32 i) unitTarget->UpdateGroundPositionZ(fx,fy,fz); } - if(unitTarget->GetTypeId() == TYPEID_PLAYER) - ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0)); - else - m_caster->GetMap()->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation()); + unitTarget->NearTeleportTo(fx, fy, fz, unitTarget->GetOrientation(),unitTarget==m_caster); } } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 42815fdd5..e933d29ae 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -11373,3 +11373,19 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) if(Pet* pet = GetPet()) pet->SetPhaseMask(newPhaseMask,true); } + +void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool casting /*= false*/ ) +{ + if(GetTypeId() == TYPEID_PLAYER) + ((Player*)this)->TeleportTo(GetMapId(), x, y, z, orientation, TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (casting ? TELE_TO_SPELL : 0)); + else + { + GetMap()->CreatureRelocation((Creature*)this, x, y, z, orientation); + + WorldPacket data; + // Work strange for many spells: triggered active mover set for targeted player to creature + //BuildTeleportAckMsg(&data, x, y, z, orientation); + BuildHeartBeatMsg(&data); + SendMessageToSet(&data, false); + } +} \ No newline at end of file diff --git a/src/game/Unit.h b/src/game/Unit.h index 362ead84b..0c7bc672b 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1066,6 +1066,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SendSpellNonMeleeDamageLog(Unit *target,uint32 SpellID,uint32 Damage, SpellSchoolMask damageSchoolMask,uint32 AbsorbedDamage, uint32 Resist,bool PhysicalDamage, uint32 Blocked, bool CriticalHit = false); void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo); + void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false); + void SendMonsterMove(float NewPosX, float NewPosY, float NewPosZ, uint8 type, uint32 MovementFlags, uint32 Time, Player* player = NULL); void SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 MovementFlags); void SendMonsterMoveWithSpeed(float x, float y, float z, uint32 transitTime = 0, Player* player = NULL); diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 79012bc1f..342ea9b0f 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7449" + #define REVISION_NR "7450" #endif // __REVISION_NR_H__