diff options
Diffstat (limited to 'src/game/Spell.cpp')
-rw-r--r-- | src/game/Spell.cpp | 215 |
1 files changed, 100 insertions, 115 deletions
diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 848f7e6e02c..3eada04fe42 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -124,7 +124,7 @@ SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0) m_itemTargetGUID = 0; m_itemTargetEntry = 0; - m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0; + m_srcPos.Relocate(0,0,0,0); m_strTarget = ""; m_targetMask = 0; } @@ -145,48 +145,36 @@ void SpellCastTargets::setUnitTarget(Unit *target) void SpellCastTargets::setSrc(float x, float y, float z) { - m_srcX = x; - m_srcY = y; - m_srcZ = z; + m_srcPos.Relocate(x, y, z); m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; } -void SpellCastTargets::setSrc(WorldObject *target) +void SpellCastTargets::setSrc(Position *pos) { - if(!target) - return; - - target->GetPosition(m_srcX, m_srcY, m_srcZ); - m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; + if(pos) + { + m_srcPos.Relocate(pos); + m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; + } } -void SpellCastTargets::setDestination(float x, float y, float z, int32 mapId) +void SpellCastTargets::setDst(float x, float y, float z, uint32 mapId) { - m_destX = x; - m_destY = y; - m_destZ = z; + m_dstPos.Relocate(x, y, z); m_targetMask |= TARGET_FLAG_DEST_LOCATION; - if(mapId >= 0) - m_mapId = mapId; + if(mapId != MAPID_INVALID) + m_dstPos.m_mapId = mapId; } -void SpellCastTargets::setDestination(WorldObject *target) +void SpellCastTargets::setDst(Position *pos) { - if(!target) - return; - - target->GetPosition(m_destX, m_destY, m_destZ); - m_targetMask |= TARGET_FLAG_DEST_LOCATION; + if(pos) + { + m_dstPos.Relocate(pos); + m_targetMask |= TARGET_FLAG_DEST_LOCATION; + } } -/*void SpellCastTargets::setSource(float x, float y, float z) -{ - m_srcX = x; - m_srcY = y; - m_srcZ = z; - m_targetMask |= TARGET_FLAG_SOURCE_LOCATION; -}*/ - void SpellCastTargets::setGOTarget(GameObject *target) { m_GOTarget = target; @@ -269,10 +257,12 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) if(data->rpos() + 4 + 4 + 4 > data->size()) return false; - *data >> m_srcX >> m_srcY >> m_srcZ; - if(!Trinity::IsValidMapCoord(m_srcX, m_srcY, m_srcZ)) + *data >> m_srcPos.m_positionX >> m_srcPos.m_positionY >> m_srcPos.m_positionZ; + if(!m_srcPos.IsPositionValid()) return false; } + else + m_srcPos.Relocate(caster); if( m_targetMask & TARGET_FLAG_DEST_LOCATION ) { @@ -282,8 +272,8 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) if(!data->readPackGUID(m_unitTargetGUID)) return false; - *data >> m_destX >> m_destY >> m_destZ; - if(!Trinity::IsValidMapCoord(m_destX, m_destY, m_destZ)) + *data >> m_dstPos.m_positionX >> m_dstPos.m_positionY >> m_dstPos.m_positionZ; + if(!m_dstPos.IsPositionValid()) return false; if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) @@ -291,11 +281,15 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) if(data->rpos() + 4 + 4 <= data->size()) { *data >> m_elevation >> m_speed; + // TODO: should also read + m_srcPos.m_orientation = caster->GetOrientation(); //*data >> uint16 >> uint8 >> uint32 >> uint32; //*data >> float >> float >> float >> float... } } } + else + m_dstPos.Relocate(caster); if( m_targetMask & TARGET_FLAG_STRING ) { @@ -346,7 +340,7 @@ void SpellCastTargets::write ( WorldPacket * data ) } if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) - *data << m_srcX << m_srcY << m_srcZ; + *data << m_srcPos.m_positionX << m_srcPos.m_positionY << m_srcPos.m_positionZ; if( m_targetMask & TARGET_FLAG_DEST_LOCATION ) { @@ -355,7 +349,7 @@ void SpellCastTargets::write ( WorldPacket * data ) else *data << uint8(0); - *data << m_destX << m_destY << m_destZ; + *data << m_dstPos.m_positionX << m_dstPos.m_positionY << m_dstPos.m_positionZ; } if( m_targetMask & TARGET_FLAG_STRING ) @@ -760,7 +754,7 @@ void Spell::SelectSpellTargets() } else if(m_spellInfo->speed > 0.0f) { - float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); + float dist = m_caster->GetDistance(m_targets.m_dstPos); m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f); } } @@ -1683,20 +1677,16 @@ void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, float max_range, uin void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNotifyPushType type, SpellTargets TargetType, uint32 entry) { - float x, y, z; + Position *pos; switch(type) { case PUSH_DST_CENTER: CheckDst(); - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; + pos = &m_targets.m_dstPos; break; case PUSH_SRC_CENTER: CheckSrc(); - x = m_targets.m_srcX; - y = m_targets.m_srcY; - z = m_targets.m_srcZ; + pos = &m_targets.m_srcPos; break; case PUSH_CHAIN: { @@ -1706,24 +1696,20 @@ void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, SpellNo sLog.outError( "SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id ); return; } - x = target->GetPositionX(); - y = target->GetPositionY(); - z = target->GetPositionZ(); + pos = target; break; } default: - x = m_caster->GetPositionX(); - y = m_caster->GetPositionY(); - z = m_caster->GetPositionZ(); + pos = m_caster; break; } - Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry, x, y, z); + Trinity::SpellNotifierCreatureAndPlayer notifier(m_caster, TagUnitMap, radius, type, TargetType, pos, entry); if((m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_PLAYERS_ONLY) || TargetType == SPELL_TARGETS_ENTRY && !entry) - m_caster->GetMap()->VisitWorld(x, y, radius, notifier); + m_caster->GetMap()->VisitWorld(pos->m_positionX, pos->m_positionY, radius, notifier); else - m_caster->GetMap()->VisitAll(x, y, radius, notifier); + m_caster->GetMap()->VisitAll(pos->m_positionX, pos->m_positionY, radius, notifier); if(m_customAttr & SPELL_ATTR_CU_EXCLUDE_SELF) TagUnitMap.remove(m_caster); @@ -1847,7 +1833,7 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) float dis = rand_norm() * (max_dis - min_dis) + min_dis; float x, y, z; m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis); - m_targets.setDestination(x, y, z); + m_targets.setDst(x, y, z); break; } case TARGET_UNIT_MASTER: @@ -1983,11 +1969,11 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) } else if(cur == TARGET_DST_CASTER) { - m_targets.setDestination(m_caster); + m_targets.setDst(m_caster); break; } - float x, y, z, angle, dist; + float angle, dist; float objSize = m_caster->GetObjectSize(); dist = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); @@ -2011,8 +1997,9 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) default: angle = rand_norm()*2*M_PI; break; } - m_caster->GetGroundPointAroundUnit(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); + Position pos; + m_caster->GetNearPosition(pos, dist, angle); + m_targets.setDst(&pos); // also flag break; } @@ -2027,11 +2014,11 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) if(cur == TARGET_DST_TARGET_ENEMY || cur == TARGET_DEST_TARGET_ANY) { - m_targets.setDestination(target); + m_targets.setDst(target); break; } - float x, y, z, angle, dist; + float angle, dist; float objSize = target->GetObjectSize(); dist = target->GetSpellRadiusForTarget(target, sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); @@ -2053,8 +2040,9 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) default: angle = rand_norm()*2*M_PI; break; } - target->GetGroundPointAroundUnit(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); + Position pos; + target->GetNearPosition(pos, dist, angle); + m_targets.setDst(&pos); break; } @@ -2088,16 +2076,13 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) default: angle = rand_norm()*2*M_PI; break; } - float dist, x, y, z; + float dist; dist = GetSpellRadiusForFriend(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i])); if (cur == TARGET_DEST_DEST_RANDOM) dist *= rand_norm(); - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; - m_caster->GetGroundPoint(x, y, z, dist, angle); - m_targets.setDestination(x, y, z); + // must has dst, no need to set flag + m_caster->MovePosition(m_targets.m_dstPos, dist, angle); break; } @@ -2112,9 +2097,9 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) 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, (int32)st->target_mapId); + m_targets.setDst(st->target_X, st->target_Y, st->target_Z, (int32)st->target_mapId); else if(st->target_mapId == m_caster->GetMapId()) - m_targets.setDestination(st->target_X, st->target_Y, st->target_Z); + m_targets.setDst(st->target_X, st->target_Y, st->target_Z); } else { @@ -2122,12 +2107,12 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) Unit *target = NULL; if(uint64 guid = m_caster->GetUInt64Value(UNIT_FIELD_TARGET)) target = ObjectAccessor::GetUnit(*m_caster, guid); - m_targets.setDestination(target ? target : m_caster); + m_targets.setDst(target ? target : m_caster); } break; case TARGET_DST_HOME: if(m_caster->GetTypeId() == TYPEID_PLAYER) - m_targets.setDestination(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, ((Player*)m_caster)->m_homebindMapId); + m_targets.setDst(((Player*)m_caster)->m_homebindX,((Player*)m_caster)->m_homebindY,((Player*)m_caster)->m_homebindZ, ((Player*)m_caster)->m_homebindMapId); break; case TARGET_DST_NEARBY_ENTRY: { @@ -2135,7 +2120,7 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) if(modOwner) modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); if(WorldObject *target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY)) - m_targets.setDestination(target); + m_targets.setDst(target); break; } } @@ -2162,7 +2147,7 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) if(m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.HasDst()) m_targets = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets; else if(Unit* target = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL)->m_targets.getUnitTarget()) - m_targets.setDestination(target); + m_targets.setDst(target); else sLog.outError( "SPELL: cannot find channel spell destination for spell ID %u", m_spellInfo->Id ); break; @@ -2300,7 +2285,7 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) switch(result->GetTypeId()) { case TYPEID_UNIT: - m_targets.setDestination(result); + m_targets.setDst(result); } } break; @@ -2389,22 +2374,17 @@ void Spell::SelectEffectTargets(uint32 i, uint32 cur) if(cur == TARGET_OBJECT_AREA_SRC) { if(m_targets.HasSrc()) - { - x = m_targets.m_srcX; - y = m_targets.m_srcY; - z = m_targets.m_srcZ; - } + m_targets.m_srcPos.GetPosition(x, y, z); else break; } - else if(m_targets.HasDst()) + else { - x = m_targets.m_destX; - y = m_targets.m_destY; - z = m_targets.m_destZ; + if(m_targets.HasDst()) + m_targets.m_dstPos.GetPosition(x, y, z); + else + break; } - else - break; Trinity::GameObjectInRangeCheck check(x, y, z, radius + 50); std::list<GameObject*> goList; @@ -3127,7 +3107,7 @@ void Spell::_handle_immediate_phase() if(EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_DEST) { if(!m_targets.HasDst()) // FIXME: this will ignore dest set in effect - m_targets.setDestination(m_caster); + m_targets.setDst(m_caster); HandleEffects(m_originalCaster, NULL, NULL, j); m_effectMask |= (1<<j); } @@ -4419,6 +4399,7 @@ SpellCastResult Spell::CheckCast(bool strict) if(m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraStateNot), m_spellInfo, m_caster)) return SPELL_FAILED_CASTER_AURASTATE; + // Note: spell 62473 requres casterAuraSpell = triggering spell if(m_spellInfo->casterAuraSpell && !m_caster->HasAura(m_spellInfo->casterAuraSpell)) return SPELL_FAILED_CASTER_AURASTATE; if(m_spellInfo->excludeCasterAuraSpell && m_caster->HasAura(m_spellInfo->excludeCasterAuraSpell)) @@ -4705,7 +4686,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { - m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); + m_targets.setDst(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ()); if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) AddUnitTarget(creatureScriptTarget, j); @@ -4720,7 +4701,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY || m_spellInfo->EffectImplicitTargetB[j] == TARGET_DST_NEARBY_ENTRY ) { - m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); + m_targets.setDst(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ()); if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_DST_NEARBY_ENTRY && m_spellInfo->EffectImplicitTargetB[j] == 0 && m_spellInfo->Effect[j]!=SPELL_EFFECT_PERSISTENT_AREA_AURA) AddGOTarget(goScriptTarget, j); @@ -5465,11 +5446,11 @@ SpellCastResult Spell::CheckRange(bool strict) return SPELL_FAILED_UNIT_NOT_INFRONT; } - if(m_targets.m_targetMask == TARGET_FLAG_DEST_LOCATION && m_targets.m_destX != 0 && m_targets.m_destY != 0 && m_targets.m_destZ != 0) + if(m_targets.HasDst() && !m_targets.HasTraj()) { - if(!m_caster->IsWithinDist3d(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, max_range)) + if(!m_caster->IsWithinDist3d(&m_targets.m_dstPos, max_range)) return SPELL_FAILED_OUT_OF_RANGE; - if(min_range && m_caster->IsWithinDist3d(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, min_range)) + if(min_range && m_caster->IsWithinDist3d(&m_targets.m_dstPos, min_range)) return SPELL_FAILED_TOO_CLOSE; } @@ -6613,7 +6594,7 @@ void Spell::SelectTrajTargets() if(!dist2d) return; - float dz = m_targets.m_destZ - m_targets.m_srcZ; + float dz = m_targets.m_dstPos.m_positionZ - m_targets.m_srcPos.m_positionZ; UnitList unitList; SearchAreaTarget(unitList, dist2d, PUSH_IN_THIN_LINE, SPELL_TARGETS_ANY); @@ -6627,7 +6608,8 @@ void Spell::SelectTrajTargets() if(a > -0.0001f) a = 0; DEBUG_TRAJ(sLog.outError("Spell::SelectTrajTargets: a %f b %f", a, b);) - float bestDist; + float bestDist = GetSpellMaxRange(m_spellInfo, false); + UnitList::const_iterator itr = unitList.begin(); for(; itr != unitList.end(); ++itr) { @@ -6636,15 +6618,15 @@ void Spell::SelectTrajTargets() const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3) // TODO: all calculation should be based on src instead of m_caster - const float objDist2d = (*itr)->GetExactDist2d(m_targets.m_srcX, m_targets.m_srcY) * cos(m_caster->GetRelativeAngle(*itr)); - const float dz = (*itr)->GetPositionZ() - m_targets.m_srcZ; + const float objDist2d = m_targets.m_srcPos.GetExactDist2d(*itr) * cos(m_targets.m_srcPos.GetRelativeAngle(*itr)); + const float dz = (*itr)->GetPositionZ() - m_targets.m_srcPos.m_positionZ; DEBUG_TRAJ(sLog.outError("Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);) float dist = objDist2d - size; float height = dist * (a * dist + b); DEBUG_TRAJ(sLog.outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);) - if(height < dz + size && height > dz - size) + if(dist < bestDist && height < dz + size && height > dz - size) { bestDist = dist > 0 ? dist : 0; break; @@ -6652,8 +6634,8 @@ void Spell::SelectTrajTargets() #define CHECK_DIST {\ DEBUG_TRAJ(sLog.outError("Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\ - if(dist < objDist2d + size && dist > objDist2d - size)\ - { bestDist = dist; break; }\ + if(dist > bestDist) continue;\ + if(dist < objDist2d + size && dist > objDist2d - size) { bestDist = dist; break; }\ } if(!a) @@ -6697,28 +6679,31 @@ void Spell::SelectTrajTargets() } } - if(itr != unitList.end()) + if(m_targets.m_srcPos.GetExactDist2d(&m_targets.m_dstPos) > bestDist) { - float x = m_targets.m_srcX + cos(m_caster->GetOrientation()) * bestDist; - float y = m_targets.m_srcY + sin(m_caster->GetOrientation()) * bestDist; - float z = m_targets.m_srcZ + bestDist * (a * bestDist + b); + float x = m_targets.m_srcPos.m_positionX + cos(m_caster->GetOrientation()) * bestDist; + float y = m_targets.m_srcPos.m_positionY + sin(m_caster->GetOrientation()) * bestDist; + float z = m_targets.m_srcPos.m_positionZ + bestDist * (a * bestDist + b); - float distSq = (*itr)->GetExactDistSq(x, y, z); - float sizeSq = (*itr)->GetObjectSize(); - sizeSq *= sizeSq; - DEBUG_TRAJ(sLog.outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);) - if(distSq > sizeSq) + if(itr != unitList.end()) { - float factor = 1 - sqrt(sizeSq / distSq); - x += factor * ((*itr)->GetPositionX() - x); - y += factor * ((*itr)->GetPositionY() - y); - z += factor * ((*itr)->GetPositionZ() - z); - - distSq = (*itr)->GetExactDistSq(x, y, z); + float distSq = (*itr)->GetExactDistSq(x, y, z); + float sizeSq = (*itr)->GetObjectSize(); + sizeSq *= sizeSq; DEBUG_TRAJ(sLog.outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);) + if(distSq > sizeSq) + { + float factor = 1 - sqrt(sizeSq / distSq); + x += factor * ((*itr)->GetPositionX() - x); + y += factor * ((*itr)->GetPositionY() - y); + z += factor * ((*itr)->GetPositionZ() - z); + + distSq = (*itr)->GetExactDistSq(x, y, z); + DEBUG_TRAJ(sLog.outError("Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);) + } } - m_targets.setDestination(x, y, z); + m_targets.setDst(x, y, z); } } |