diff options
-rw-r--r-- | src/game/GridNotifiers.cpp | 6 | ||||
-rw-r--r-- | src/game/Object.cpp | 17 | ||||
-rw-r--r-- | src/game/Object.h | 6 | ||||
-rw-r--r-- | src/game/Spell.cpp | 153 | ||||
-rw-r--r-- | src/game/Spell.h | 31 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 6 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 14 | ||||
-rw-r--r-- | src/game/TargetedMovementGenerator.cpp | 2 | ||||
-rw-r--r-- | src/game/Unit.cpp | 6 | ||||
-rw-r--r-- | src/game/Unit.h | 2 | ||||
-rw-r--r-- | src/game/UnitAI.cpp | 2 |
11 files changed, 208 insertions, 37 deletions
diff --git a/src/game/GridNotifiers.cpp b/src/game/GridNotifiers.cpp index 858c807e386..5e40b8d81d9 100644 --- a/src/game/GridNotifiers.cpp +++ b/src/game/GridNotifiers.cpp @@ -150,7 +150,7 @@ MessageDistDeliverer::Visit(PlayerMapType &m) if(!target->InSamePhase(i_phaseMask)) continue; - if(target->GetDistanceSq(i_source) > i_distSq) + if(target->GetExactDistSq(i_source) > i_distSq) continue; // Send packet to all who are sharing the player's vision @@ -175,7 +175,7 @@ MessageDistDeliverer::Visit(CreatureMapType &m) if(!iter->getSource()->InSamePhase(i_phaseMask)) continue; - if(iter->getSource()->GetDistanceSq(i_source) > i_distSq) + if(iter->getSource()->GetExactDistSq(i_source) > i_distSq) continue; // Send packet to all who are sharing the creature's vision @@ -197,7 +197,7 @@ MessageDistDeliverer::Visit(DynamicObjectMapType &m) if(!iter->getSource()->InSamePhase(i_phaseMask)) continue; - if(iter->getSource()->GetDistanceSq(i_source) > i_distSq) + if(iter->getSource()->GetExactDistSq(i_source) > i_distSq) continue; if (IS_PLAYER_GUID(iter->getSource()->GetCasterGUID())) diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 4b79da91651..71d922298dd 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1196,7 +1196,7 @@ float WorldObject::GetDistance(float x, float y, float z) const return ( dist > 0 ? dist : 0); } -float WorldObject::GetDistanceSq(const float &x, const float &y, const float &z) const +float WorldObject::GetExactDistSq(float x, float y, float z) const { float dx = GetPositionX() - x; float dy = GetPositionY() - y; @@ -1204,7 +1204,14 @@ float WorldObject::GetDistanceSq(const float &x, const float &y, const float &z) return dx*dx + dy*dy + dz*dz; } -float WorldObject::GetDistanceSq(const WorldObject *obj) const +float WorldObject::GetDistance2dSq(float x, float y) const +{ + float dx = GetPositionX() - x; + float dy = GetPositionY() - y; + return dx*dx + dy*dy; +} + +float WorldObject::GetExactDistSq(const WorldObject *obj) const { float dx = GetPositionX() - obj->GetPositionX(); float dy = GetPositionY() - obj->GetPositionY(); @@ -1236,8 +1243,7 @@ bool WorldObject::IsWithinDist3d(float x, float y, float z, float dist2compare) float dz = GetPositionZ() - z; float distsq = dx*dx + dy*dy + dz*dz; - float sizefactor = GetObjectSize(); - float maxdist = dist2compare + sizefactor; + float maxdist = dist2compare + GetObjectSize(); return distsq < maxdist * maxdist; } @@ -1248,8 +1254,7 @@ bool WorldObject::IsWithinDist2d(float x, float y, float dist2compare) const float dy = GetPositionY() - y; float distsq = dx*dx + dy*dy; - float sizefactor = GetObjectSize(); - float maxdist = dist2compare + sizefactor; + float maxdist = dist2compare + GetObjectSize(); return distsq < maxdist * maxdist; } diff --git a/src/game/Object.h b/src/game/Object.h index 74527ca5df2..63ee95fd5c6 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -460,8 +460,9 @@ class TRINITY_DLL_SPEC WorldObject : public Object float GetDistance( const WorldObject* obj ) const; float GetDistance(float x, float y, float z) const; - float GetDistanceSq(const float &x, const float &y, const float &z) const; - float GetDistanceSq(const WorldObject *obj) const; + float GetDistance2dSq(float x, float y) const; + float GetExactDistSq(float x, float y, float z) const; + float GetExactDistSq(const WorldObject *obj) const; float GetDistance2d(const WorldObject* obj) const; float GetDistance2d(float x, float y) const; float GetExactDistance2d(const float x, const float y) const; @@ -491,6 +492,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object float GetAngle( const WorldObject* obj ) const; float GetAngle( const float x, const float y ) const; + float GetRelativeAngle(const WorldObject *obj) const { return GetAngle(obj) - GetOrientation(); } void GetSinCos(const float x, const float y, float &vsin, float &vcos); bool HasInArc( const float arcangle, const WorldObject* obj ) const; bool IsInBetween(const WorldObject *obj1, const WorldObject *obj2, float size = 0) const; diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 03d1f0399f6..a18c05e63b2 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -112,7 +112,7 @@ struct PrioritizeHealth typedef std::priority_queue<PrioritizeHealthUnitWraper, std::vector<PrioritizeHealthUnitWraper>, PrioritizeHealth> PrioritizeHealthUnitQueue; -SpellCastTargets::SpellCastTargets() +SpellCastTargets::SpellCastTargets() : m_elevation(0), m_speed(0) { m_unitTarget = NULL; m_itemTarget = NULL; @@ -285,6 +285,16 @@ bool SpellCastTargets::read ( WorldPacket * data, Unit *caster ) *data >> m_destX >> m_destY >> m_destZ; if(!Trinity::IsValidMapCoord(m_destX, m_destY, m_destZ)) return false; + + if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION ) + { + if(data->rpos() + 4 + 4 <= data->size()) + { + *data >> m_elevation >> m_speed; + //*data >> uint16 >> uint8 >> uint32 >> uint32; + //*data >> float >> float >> float >> float... + } + } } if( m_targetMask & TARGET_FLAG_STRING ) @@ -510,7 +520,7 @@ WorldObject* Spell::FindCorpseUsing() return result; } -void Spell::FillTargetMap() +void Spell::SelectSpellTargets() { for(uint32 i = 0; i < 3; ++i) { @@ -529,9 +539,9 @@ void Spell::FillTargetMap() uint32 targetB = m_spellInfo->EffectImplicitTargetB[i]; if(targetA) - SetTargetMap(i, targetA); + SelectEffectTargets(i, targetA); if(targetB) // In very rare case !A && B - SetTargetMap(i, targetB); + SelectEffectTargets(i, targetB); if(effectTargetType != SPELL_REQUIRE_UNIT) { @@ -679,7 +689,7 @@ void Spell::FillTargetMap() case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: // AreaAura if(m_spellInfo->Attributes == 0x9050000 || m_spellInfo->Attributes == 0x10000) - SetTargetMap(i, TARGET_UNIT_PARTY_TARGET); + SelectEffectTargets(i, TARGET_UNIT_PARTY_TARGET); break; case SPELL_EFFECT_SKIN_PLAYER_CORPSE: if(m_targets.getUnitTarget()) @@ -739,12 +749,17 @@ void Spell::FillTargetMap() } } - if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION) + if(m_targets.HasDst()) { - if(m_spellInfo->speed > 0.0f && m_targets.HasDst()) + if(m_targets.HasTraj()) + { + float speed = m_targets.GetSpeedXY(); + if(speed > 0.0f) + m_delayMoment = (uint64)floor(m_targets.GetDist2d() / speed * 1000.0f); + } + else if(m_spellInfo->speed > 0.0f) { float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); - if (dist < 5.0f) dist = 5.0f; m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f); } } @@ -1805,7 +1820,7 @@ WorldObject* Spell::SearchNearbyTarget(float range, SpellTargets TargetType) } } -void Spell::SetTargetMap(uint32 i, uint32 cur) +void Spell::SelectEffectTargets(uint32 i, uint32 cur) { SpellNotifyPushType pushType = PUSH_NONE; Player *modOwner = NULL; @@ -2055,7 +2070,9 @@ void Spell::SetTargetMap(uint32 i, uint32 cur) case TARGET_DEST_DYNOBJ_ALLY: case TARGET_DEST_DYNOBJ_NONE: case TARGET_DEST_DEST: + return; case TARGET_DEST_TRAJ: + SelectTrajTargets(); return; case TARGET_DEST_DEST_FRONT: angle = 0.0f; break; case TARGET_DEST_DEST_BACK: angle = M_PI; break; @@ -2679,7 +2696,11 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect* triggeredByAura // set timer base at cast time ReSetTimer(); - sLog.outDebug("Spell::prepare: spell id %u source %u caster %d target %d triggered %u", m_spellInfo->Id, m_caster->GetEntry(), m_originalCaster ? m_originalCaster->GetEntry() : -1, m_targets.getUnitTarget() ? m_targets.getUnitTarget()->GetEntry() : -1, m_IsTriggeredSpell ? 1 : 0); + sLog.outDebug("Spell::prepare: spell id %u source %u caster %d triggered %u", m_spellInfo->Id, m_caster->GetEntry(), m_originalCaster ? m_originalCaster->GetEntry() : -1, m_IsTriggeredSpell ? 1 : 0); + //if(m_targets.getUnitTarget()) + // sLog.outError("Spell::prepare: unit target %u", m_targets.getUnitTarget()->GetEntry()); + //if(m_targets.HasDst()) + // sLog.outError("Spell::prepare: pos target %f %f %f", m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ); //Containers for channeled spells have to be set //TODO:Apply this to all casted spells if needed @@ -2823,7 +2844,7 @@ void Spell::cast(bool skipCheck) } } - FillTargetMap(); + SelectSpellTargets(); // Spell may be finished after target map check if(m_spellState == SPELL_STATE_FINISHED) @@ -5361,7 +5382,7 @@ bool Spell::CanAutoCast(Unit* target) if(result == SPELL_CAST_OK || result == SPELL_FAILED_UNIT_NOT_INFRONT) { - FillTargetMap(); + SelectSpellTargets(); //check if among target units, our WANTED target is as well (->only self cast spells return false) for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit) if( ihit->targetGUID == targetguid ) @@ -6547,6 +6568,114 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value) } } +void Spell::SelectTrajTargets() +{ + if(!m_targets.HasTraj()) + return; + + float dist2d = m_targets.GetDist2d(); + float dz = m_targets.m_destZ - m_targets.m_srcZ; + + UnitList unitList; + SearchAreaTarget(unitList, dist2d, PUSH_IN_THIN_LINE, SPELL_TARGETS_ANY); + if(unitList.empty()) + return; + + unitList.sort(TargetDistanceOrder(m_caster)); + + float sinE = sin(m_targets.m_elevation); + float dcosE = 2 * cos(m_targets.m_elevation); + float divisor = dist2d * (dist2d - dcosE); + if(abs(divisor) < 0.0001f) divisor = 0.0001f; + float a = (dz - dist2d * sinE) / divisor; + float b = sinE - dcosE * a; + if(a > -0.0001f) a = -0.0001f; + + float bestDist; + UnitList::const_iterator itr = unitList.begin(); + for(; itr != unitList.end(); ++itr) + { + if(m_caster == *itr || m_caster == (*itr)->m_Vehicle || m_caster->m_Vehicle == *itr) + continue; + + const float size = (*itr)->GetObjectSize() * 0.6f; // 1/sqrt(3) + const float objDist2d = m_caster->GetExactDistance2d((*itr)->GetPositionX(), (*itr)->GetPositionY()) * cos(m_caster->GetRelativeAngle(*itr)); + const float dz = (*itr)->GetPositionZ() - m_caster->GetPositionZ(); + + float dist = objDist2d - size; + float height = dist * (a * dist + b); + if(height < dz + size && height > dz - size) + { + bestDist = dist > 0 ? dist : 0; + break; + } + + height = dz - size; + float sqrt1 = b * b + 4 * a * height; + if(sqrt1 > 0) + { + sqrt1 = sqrt(sqrt1); + dist = (sqrt1 - b) / (2 * a); + if(dist < objDist2d + size && dist > objDist2d - size) + { + bestDist = dist; + break; + } + } + + height = dz + size; + float sqrt2 = b * b + 4 * a * height; + if(sqrt2 > 0) + { + sqrt2 = sqrt(sqrt2); + dist = (sqrt2 - b) / (2 * a); + if(dist < objDist2d + size && dist > objDist2d - size) + { + bestDist = dist; + break; + } + + dist = (-sqrt2 - b) / (2 * a); + if(dist < objDist2d + size && dist > objDist2d - size) + { + bestDist = dist; + break; + } + } + + if(sqrt1 > 0) + { + dist = (-sqrt1 - b) / (2 * a); + if(dist < objDist2d + size && dist > objDist2d - size) + { + bestDist = dist; + break; + } + } + } + + if(itr != unitList.end()) + { + 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 distSq = (*itr)->GetExactDistSq(x, y, z); + float sizeSq = (*itr)->GetObjectSize(); + sizeSq *= 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); + } + + m_targets.setDestination(x, y, z); + } +} + void Spell::FillRaidOrPartyTargets( UnitList &TagUnitMap, Unit* target, float radius, bool raid, bool withPets, bool withcaster ) { Player *pTarget = target->GetCharmerOrOwnerPlayerOrPlayerItself(); diff --git a/src/game/Spell.h b/src/game/Spell.h index 9b8430fe121..d100f9e6ee2 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -92,6 +92,7 @@ enum SpellNotifyPushType PUSH_IN_FRONT, PUSH_IN_BACK, PUSH_IN_LINE, + PUSH_IN_THIN_LINE, PUSH_SRC_CENTER, PUSH_DST_CENTER, PUSH_CASTER_CENTER, //this is never used in grid search @@ -137,6 +138,9 @@ class SpellCastTargets m_destY = target.m_destY; m_destZ = target.m_destZ; + m_elevation = target.m_elevation; + m_speed = target.m_speed; + m_strTarget = target.m_strTarget; m_targetMask = target.m_targetMask; @@ -176,11 +180,23 @@ class SpellCastTargets bool IsEmpty() const { return m_GOTargetGUID==0 && m_unitTargetGUID==0 && m_itemTarget==0 && m_CorpseTargetGUID==0; } bool HasSrc() const { return m_targetMask & TARGET_FLAG_SOURCE_LOCATION; } bool HasDst() const { return m_targetMask & TARGET_FLAG_DEST_LOCATION; } + bool HasTraj() const { return m_speed != 0; } + + float GetDist2d() const + { + float dx = m_destX - m_srcX; + float dy = m_destY - m_srcY; + return sqrt(dx*dx + dy*dy); + } + + float GetSpeedXY() const { return m_speed * cos(m_elevation); } + float GetSpeedZ() const { return m_speed * sin(m_elevation); } void Update(Unit* caster); float m_srcX, m_srcY, m_srcZ; float m_destX, m_destY, m_destZ; + float m_elevation, m_speed; int32 m_mapId; std::string m_strTarget; @@ -238,6 +254,7 @@ enum SpellTargets SPELL_TARGETS_ENEMY, SPELL_TARGETS_ENTRY, SPELL_TARGETS_CHAINHEAL, + SPELL_TARGETS_ANY, }; class Spell @@ -403,9 +420,10 @@ class Spell void DoCreateItem(uint32 i, uint32 itemtype); void WriteSpellGoTargets( WorldPacket * data ); void WriteAmmoToPacket( WorldPacket * data ); - void FillTargetMap(); - void SetTargetMap(uint32 i, uint32 cur); + void SelectSpellTargets(); + void SelectEffectTargets(uint32 i, uint32 cur); + void SelectTrajTargets(); void FillRaidOrPartyTargets( UnitList &TagUnitMap, Unit* target, float radius, bool raid, bool withPets, bool withcaster ); void FillRaidOrPartyManaPriorityTargets( UnitList &TagUnitMap, Unit* target, float radius, uint32 count, bool raid, bool withPets, bool withcaster ); void FillRaidOrPartyHealthPriorityTargets( UnitList &TagUnitMap, Unit* target, float radius, uint32 count, bool raid, bool withPets, bool withcaster ); @@ -713,8 +731,9 @@ namespace Trinity if(target->GetEntry()!= i_entry) continue; break; + case SPELL_TARGETS_ANY: default: - continue; + break; } switch(i_push_type) @@ -735,7 +754,11 @@ namespace Trinity i_data->push_back(target); break; case PUSH_IN_LINE: - if(i_source->isInLine(target, i_radius)) + if(i_source->isInLine(target, i_radius, i_source->GetObjectSize())) + i_data->push_back(target); + break; + case PUSH_IN_THIN_LINE: + if(i_source->isInLine(target, i_radius, 0)) i_data->push_back(target); break; } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index 01840cf5842..f8fa301341e 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -3540,14 +3540,12 @@ void SpellMgr::LoadSpellCustomAttr() mSpellCustomAttr[i] |= SPELL_ATTR_CU_CHARGE; break; case SPELL_EFFECT_TRIGGER_SPELL: - if (SpellTargetType[spellInfo->EffectImplicitTargetA[j]]== TARGET_TYPE_DEST_CASTER || - SpellTargetType[spellInfo->EffectImplicitTargetA[j]]== TARGET_TYPE_DEST_TARGET || - SpellTargetType[spellInfo->EffectImplicitTargetA[j]]== TARGET_TYPE_DEST_DEST || + if (IsPositionTarget(spellInfo->EffectImplicitTargetA[j]) || spellInfo->Targets & (TARGET_FLAG_SOURCE_LOCATION|TARGET_FLAG_DEST_LOCATION)) spellInfo->Effect[j] = SPELL_EFFECT_TRIGGER_MISSILE; break; } - + switch(SpellTargetType[spellInfo->EffectImplicitTargetA[j]]) { case TARGET_TYPE_UNIT_TARGET: diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index cb7e00d6e5f..42705f1e7ca 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -294,6 +294,20 @@ inline bool IsCasterSourceTarget(uint32 target) return false; } +inline bool IsPositionTarget(uint32 target) +{ + switch (SpellTargetType[target]) + { + case TARGET_TYPE_DEST_CASTER: + case TARGET_TYPE_DEST_TARGET: + case TARGET_TYPE_DEST_DEST: + return true; + default: + break; + } + return false; +} + inline bool IsSpellWithCasterSourceTargetsOnly(SpellEntry const* spellInfo) { for(int i = 0; i < 3; ++i) diff --git a/src/game/TargetedMovementGenerator.cpp b/src/game/TargetedMovementGenerator.cpp index c1c601921b3..231b5a74e24 100644 --- a/src/game/TargetedMovementGenerator.cpp +++ b/src/game/TargetedMovementGenerator.cpp @@ -93,7 +93,7 @@ TargetedMovementGenerator<T>::_setTargetLocation(T &owner) } } - if(i_target->GetDistanceSq(i_targetX, i_targetY, i_targetZ) < 0.01f) + if(i_target->GetExactDistSq(i_targetX, i_targetY, i_targetZ) < 0.01f) return false; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 1cf62750315..294f1cd9168 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3427,11 +3427,11 @@ bool Unit::isInBackInMap(Unit const* target, float distance, float arc) const return IsWithinDistInMap(target, distance) && !HasInArc( 2 * M_PI - arc, target ); } -bool Unit::isInLine(Unit const* target, float distance) const +bool Unit::isInLine(Unit const* target, float distance, float width) const { if(!HasInArc(M_PI, target) || !IsWithinDistInMap(target, distance)) return false; - float width = GetObjectSize() + target->GetObjectSize() * 0.5f; - float angle = GetAngle(target) - GetOrientation(); + width += target->GetObjectSize() * 0.5f; + float angle = GetRelativeAngle(target); return abs(sin(angle)) * GetExactDistance2d(target->GetPositionX(), target->GetPositionY()) < width; } diff --git a/src/game/Unit.h b/src/game/Unit.h index a2e02a9910f..e976b481e0a 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1558,7 +1558,7 @@ class TRINITY_DLL_SPEC Unit : public WorldObject bool isInFrontInMap(Unit const* target,float distance, float arc = M_PI) const; void SetInFront(Unit const* target); bool isInBackInMap(Unit const* target, float distance, float arc = M_PI) const; - bool isInLine(Unit const* target, float distance) const; + bool isInLine(Unit const* target, float distance, float width) const; // Visibility system UnitVisibility GetVisibility() const { return m_Visibility; } diff --git a/src/game/UnitAI.cpp b/src/game/UnitAI.cpp index 4ba2f94e4db..50936bff001 100644 --- a/src/game/UnitAI.cpp +++ b/src/game/UnitAI.cpp @@ -113,7 +113,7 @@ struct TargetDistanceOrder : public std::binary_function<const Unit *, const Uni // functor for operator ">" bool operator()(const Unit * _Left, const Unit * _Right) const { - return (me->GetDistanceSq(_Left) < me->GetDistanceSq(_Right)); + return (me->GetExactDistSq(_Left) < me->GetExactDistSq(_Right)); } }; |