diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Object/Position.cpp | 7 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Position.h | 1 | ||||
-rw-r--r-- | src/server/game/Handlers/SpellHandler.cpp | 3 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 164 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 1 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 9 | ||||
-rw-r--r-- | src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp | 44 | ||||
-rw-r--r-- | src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp | 15 |
8 files changed, 85 insertions, 159 deletions
diff --git a/src/server/game/Entities/Object/Position.cpp b/src/server/game/Entities/Object/Position.cpp index fee50be6e8..65c2ede216 100644 --- a/src/server/game/Entities/Object/Position.cpp +++ b/src/server/game/Entities/Object/Position.cpp @@ -42,9 +42,16 @@ void Position::RelocatePolarOffset(float angle, float dist, float z /*= 0.0f*/) bool Position::HasInLine(Position const* pos, float width) const { + return HasInLine(pos, 0, width); +} + +bool Position::HasInLine(Position const* pos, float objSize, float width) const +{ if (!HasInArc(float(M_PI), pos)) return false; + width += objSize; + float angle = GetRelativeAngle(pos); return std::fabs(std::sin(angle)) * GetExactDist2d(pos->GetPositionX(), pos->GetPositionY()) < width; } diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h index 39751a12a8..baeff5a80d 100644 --- a/src/server/game/Entities/Object/Position.h +++ b/src/server/game/Entities/Object/Position.h @@ -231,6 +231,7 @@ struct Position [[nodiscard]] bool IsWithinBox(const Position& center, float xradius, float yradius, float zradius) const; bool HasInArc(float arcangle, const Position* pos, float targetRadius = 0.0f) const; bool HasInLine(Position const* pos, float width) const; + bool HasInLine(Position const* pos, float objSize, float width) const; [[nodiscard]] std::string ToString() const; // modulos a radian orientation to the range of 0..2PI diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 7d6b5bd2e8..6117637db6 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -855,6 +855,9 @@ void WorldSession::HandleUpdateProjectilePosition(WorldPacket& recvPacket) pos.Relocate(x, y, z); spell->m_targets.ModDst(pos); + // we changed dest, recalculate flight time + spell->RecalculateDelayMomentForDst(); + WorldPacket data(SMSG_SET_PROJECTILE_POSITION, 21); data << casterGuid; data << uint8(castCount); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index e851a039b4..4ae8bfca43 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1744,9 +1744,6 @@ void Spell::SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitT case TARGET_DEST_DYNOBJ_NONE: case TARGET_DEST_DEST: return; - case TARGET_DEST_TRAJ: - SelectImplicitTrajTargets(effIndex, targetType); - return; default: { float angle = targetType.CalcDirectionAngle(); @@ -1885,14 +1882,14 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge if (!dist2d) return; - float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - m_targets.GetSrcPos()->m_positionZ; + Position srcPos = *m_targets.GetSrcPos(); + srcPos.SetOrientation(m_caster->GetOrientation()); + float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - srcPos.m_positionZ; - // xinef: supply correct target type, DEST_DEST and similar are ALWAYS undefined - // xinef: correct target is stored in TRIGGERED SPELL, however as far as i noticed, all checks are ENTRY, ENEMY std::list<WorldObject*> targets; - Acore::WorldObjectSpellTrajTargetCheck check(dist2d, m_targets.GetSrcPos(), m_caster, m_spellInfo, TARGET_CHECK_ENEMY /*targetCheckType*/, m_spellInfo->Effects[effIndex].ImplicitTargetConditions); + Acore::WorldObjectSpellTrajTargetCheck check(dist2d, &srcPos, m_caster, m_spellInfo, targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions); Acore::WorldObjectListSearcher<Acore::WorldObjectSpellTrajTargetCheck> searcher(m_caster, targets, check, GRID_MAP_TYPE_MASK_ALL); - SearchTargets<Acore::WorldObjectListSearcher<Acore::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, m_targets.GetSrcPos(), dist2d); + SearchTargets<Acore::WorldObjectListSearcher<Acore::WorldObjectSpellTrajTargetCheck> > (searcher, GRID_MAP_TYPE_MASK_ALL, m_caster, &srcPos, dist2d); if (targets.empty()) return; @@ -1901,136 +1898,59 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex, SpellImplicitTarge float b = tangent(m_targets.GetElevation()); float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d); if (a > -0.0001f) - a = 0; - - LOG_DEBUG("spells", "Spell::SelectTrajTargets: a {} b {}", a, b); + a = 0.f; - // Xinef: hack for distance, many trajectory spells have RangeEntry 1 (self) - float bestDist = m_spellInfo->GetMaxRange(false) * 2; - if (bestDist < 1.0f) - bestDist = 300.0f; + // We should check if triggered spell has greater range (which is true in many cases, and initial spell has too short max range) + // limit max range to 300 yards, sometimes triggered spells can have 50000yds + float bestDist = m_spellInfo->GetMaxRange(false); + if (SpellInfo const* triggerSpellInfo = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[effIndex].TriggerSpell)) + bestDist = std::min(std::max(bestDist, triggerSpellInfo->GetMaxRange(false)), std::min(dist2d, 300.0f)); - std::list<WorldObject*>::const_iterator itr = targets.begin(); - for (; itr != targets.end(); ++itr) + // GameObjects don't cast traj + Unit* unitCaster = ASSERT_NOTNULL(m_caster->ToUnit()); + for (auto itr = targets.begin(); itr != targets.end(); ++itr) { - if (Unit* unitTarget = (*itr)->ToUnit()) - if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || (unitTarget)->GetVehicle())//(*itr)->IsOnVehicle(m_caster)) - continue; - - 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 = std::fabs(m_targets.GetSrcPos()->GetExactDist2d(*itr) * cos(m_targets.GetSrcPos()->GetRelativeAngle(*itr))); - const float dz = std::fabs((*itr)->GetPositionZ() - m_targets.GetSrcPos()->m_positionZ); - - LOG_DEBUG("spells", "Spell::SelectTrajTargets: check {}, dist between {} {}, height between {} {}.", - (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size); - - float dist = objDist2d - size; - float height = dist * (a * dist + b); - - LOG_DEBUG("spells", "Spell::SelectTrajTargets: dist {}, height {}.", dist, height); - - if (dist < bestDist && height < dz + size && height > dz - size) - { - bestDist = dist > 0 ? dist : 0; - break; - } - -#define CHECK_DIST {\ - LOG_DEBUG("spells", "Spell::SelectTrajTargets: dist {}, height {}.", dist, height);\ - if (dist > bestDist)\ - continue;\ - if (dist < objDist2d + size && dist > objDist2d - size)\ - {\ - bestDist = dist;\ - break;\ - }\ - } - - // RP-GG only, search in straight line, as item have no trajectory - if (m_CastItem) - { - if (dist < bestDist && std::fabs(dz) < 6.0f) // closes target, also check Z difference) - { - bestDist = dist; - break; - } - + if (m_spellInfo->CheckTarget(unitCaster, *itr, true) != SPELL_CAST_OK) continue; - } - if (!a) + if (Unit* unit = (*itr)->ToUnit()) { - // Xinef: everything remade - dist = m_targets.GetSrcPos()->GetExactDist(*itr); - height = m_targets.GetSrcPos()->GetExactDist2d(*itr) * b; + if (unitCaster == *itr || unitCaster->IsOnVehicle(unit) || unit->GetVehicle()) + continue; - if (height < dz + size * (b + 1) && height > dz - size * (b + 1) && dist < bestDist) + if (Creature* creatureTarget = unit->ToCreature()) { - bestDist = dist; - break; + if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_COLLIDE_WITH_MISSILES)) + continue; } - - continue; } - height = dz - size; - float sqrt1 = b * b + 4 * a * height; - if (sqrt1 > 0) - { - sqrt1 = std::sqrt(sqrt1); - dist = (sqrt1 - b) / (2 * a); - CHECK_DIST; - } + float const size = std::max((*itr)->GetCombatReach(), 1.0f); + float const objDist2d = srcPos.GetExactDist2d(*itr); + float const dz = (*itr)->GetPositionZ() - srcPos.m_positionZ; - height = dz + size; - float sqrt2 = b * b + 4 * a * height; - if (sqrt2 > 0) - { - sqrt2 = std::sqrt(sqrt2); - dist = (sqrt2 - b) / (2 * a); - CHECK_DIST; + float const horizontalDistToTraj = std::fabs(objDist2d * std::sin(srcPos.GetRelativeAngle(*itr))); + float const sizeFactor = std::cos((horizontalDistToTraj / size) * (M_PI / 2.0f)); + float const distToHitPoint = std::max(objDist2d * std::cos(srcPos.GetRelativeAngle(*itr)) - size * sizeFactor, 0.0f); + float const height = distToHitPoint * (a * distToHitPoint + b); - dist = (-sqrt2 - b) / (2 * a); - CHECK_DIST; - } + if (fabs(dz - height) > size + b / 2.0f + TRAJECTORY_MISSILE_SIZE) + continue; - if (sqrt1 > 0) + if (distToHitPoint < bestDist) { - dist = (-sqrt1 - b) / (2 * a); - CHECK_DIST; + bestDist = distToHitPoint; + break; } } - if (m_targets.GetSrcPos()->GetExactDist2d(m_targets.GetDstPos()) > bestDist) + if (dist2d > bestDist) { - float x = m_targets.GetSrcPos()->m_positionX + cos(m_caster->GetOrientation()) * bestDist; - float y = m_targets.GetSrcPos()->m_positionY + std::sin(m_caster->GetOrientation()) * bestDist; + float x = m_targets.GetSrcPos()->m_positionX + std::cos(unitCaster->GetOrientation()) * bestDist; + float y = m_targets.GetSrcPos()->m_positionY + std::sin(unitCaster->GetOrientation()) * bestDist; float z = m_targets.GetSrcPos()->m_positionZ + bestDist * (a * bestDist + b); - if (itr != targets.end()) - { - float distSq = (*itr)->GetExactDistSq(x, y, z); - float sizeSq = (*itr)->GetObjectSize(); - sizeSq *= sizeSq; - LOG_DEBUG("spells", "Spell::SelectTrajTargets: Initial {} {} {} {} {}", x, y, z, distSq, sizeSq); - if (distSq > sizeSq) - { - float factor = 1 - std::sqrt(sizeSq / distSq); - x += factor * ((*itr)->GetPositionX() - x); - y += factor * ((*itr)->GetPositionY() - y); - z += factor * ((*itr)->GetPositionZ() - z); - - distSq = (*itr)->GetExactDistSq(x, y, z); - LOG_DEBUG("spells", "Spell::SelectTrajTargets: Initial {} {} {} {} {}", x, y, z, distSq, sizeSq); - } - } - - Position trajDst; - trajDst.Relocate(x, y, z, m_caster->GetOrientation()); - SpellDestination dest(*m_targets.GetDst()); - dest.Relocate(trajDst); - + SpellDestination dest(x, y, z, unitCaster->GetOrientation()); CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); m_targets.ModDst(dest); } @@ -9119,7 +9039,7 @@ namespace Acore } else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE)) { - if (!_caster->HasInLine(target, _caster->GetObjectSize() + target->GetObjectSize())) + if (!_caster->HasInLine(target, target->GetObjectSize(), _caster->GetObjectSize())) return false; } else @@ -9139,9 +9059,13 @@ namespace Acore bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target) { // return all targets on missile trajectory (0 - size of a missile) - if (!_caster->HasInLine(target, target->GetObjectSize())) + if (!_caster->HasInLine(target, target->GetCombatReach(), TRAJECTORY_MISSILE_SIZE)) return false; - return WorldObjectSpellAreaTargetCheck::operator ()(target); + + if (target->GetExactDist2d(_position) > _range) + return false; + + return WorldObjectSpellTargetCheck::operator ()(target); } } //namespace Acore diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index bb8f2cb7bb..3025e803e6 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -39,6 +39,7 @@ class ByteBuffer; class BasicEvent; #define SPELL_CHANNEL_UPDATE_INTERVAL (1 * IN_MILLISECONDS) +#define TRAJECTORY_MISSILE_SIZE 3.0f enum SpellCastFlags { diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 534388fd4f..b9ee0a9b31 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3405,15 +3405,6 @@ void SpellMgr::LoadSpellInfoCustomAttributes() } // Xinef: Cooldown overwrites - // Jotunheim Rapid-Fire Harpoon: Energy Reserve - case 56585: - spellInfo->RecoveryTime = 30000; - spellInfo->_requireCooldownInfo = true; - break; - // Jotunheim Rapid-Fire Harpoon: Rapid-Fire Harpoon - case 56570: - spellInfo->RecoveryTime = 200; - break; // Burst of Speed case 57493: spellInfo->RecoveryTime = 60000; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index c67253561e..cf6318747d 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -143,10 +143,7 @@ public: SecondPhase = false; EventStarted = false; - me->RemoveAllAuras(); - me->SetControlled(false, UNIT_STATE_ROOT); - me->UpdatePosition(343.02f, -507.325f, 104.567f, M_PI, true); - me->StopMovingOnCurrentPos(); + me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE); if (m_pInstance) { @@ -160,29 +157,28 @@ public: Creature* GetGrauf() { return ObjectAccessor::GetCreature(*me, GraufGUID); } - void JustEngagedWith(Unit* /*pWho*/) override + void DoAction(int32 param) override { - if (!EventStarted) + if (param == ACTION_START_EVENT) { - EventStarted = true; - Talk(SAY_AGGRO); - if (m_pInstance) + if (!EventStarted) { - if (IsHeroic()) - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_LODI_DODI); + EventStarted = true; + Talk(SAY_AGGRO); + if (m_pInstance) + { + if (IsHeroic()) + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_LODI_DODI); - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS, IN_PROGRESS); - } + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS, IN_PROGRESS); + } - me->SetControlled(true, UNIT_STATE_ROOT); - me->SetInCombatWithZone(); - events.RescheduleEvent(EVENT_SKADI_START, 2s); + me->SetControlled(true, UNIT_STATE_ROOT); + me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE); + events.RescheduleEvent(EVENT_SKADI_START, 2s); + } } - } - - void DoAction(int32 param) override - { - if (param == ACTION_PHASE2) + else if (param == ACTION_PHASE2) { SecondPhase = true; events.ScheduleEvent(EVENT_SKADI_CRUSH, 8s); @@ -190,7 +186,7 @@ public: events.ScheduleEvent(EVENT_SKADI_WHIRLWIND, 15s); if (me->GetVictim()) - me->GetMotionMaster()->MoveChase(me->GetVictim()); + me->ResumeChasingVictim(); else me->SetInCombatWithZone(); } @@ -415,7 +411,7 @@ public: Map::PlayerList const& pList = me->GetMap()->GetPlayers(); for(Map::PlayerList::const_iterator itr = pList.begin(); itr != pList.end(); ++itr) { - if (itr->GetSource()->GetPositionX() < 320.0f || itr->GetSource()->IsGameMaster() || !itr->GetSource()->IsAlive()) + if (itr->GetSource()->GetPositionY() > -490.0f || itr->GetSource()->IsGameMaster() || !itr->GetSource()->IsAlive()) continue; return; @@ -456,7 +452,7 @@ public: SpawnHelpers(0); SpawnHelpers(0); - events.ScheduleEvent(EVENT_GRAUF_MOVE, 15s); + events.ScheduleEvent(EVENT_GRAUF_MOVE, 5s); events.ScheduleEvent(EVENT_GRAUF_SUMMON_HELPERS, 20s); break; } diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp index 5a36f5e841..47588a7bf8 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp @@ -20,6 +20,12 @@ #include "ScriptedCreature.h" #include "utgarde_pinnacle.h" +ObjectData const creatureData[] = +{ + { NPC_SKADI_THE_RUTHLESS, DATA_SKADI_THE_RUTHLESS }, + { 0, 0 } +}; + class instance_utgarde_pinnacle : public InstanceMapScript { public: @@ -36,7 +42,6 @@ public: ObjectGuid SvalaSorrowgrave; ObjectGuid GortokPalehoof; - ObjectGuid SkadiRuthless; ObjectGuid KingYmiron; ObjectGuid FrenziedWorgen; ObjectGuid RavenousFurbolg; @@ -59,6 +64,7 @@ public: void Initialize() override { SetHeaders(DataHeader); + LoadObjectData(creatureData, nullptr); SkadiHits = 0; SkadiInRange = 0; @@ -88,9 +94,6 @@ public: case NPC_GORTOK_PALEHOOF: GortokPalehoof = pCreature->GetGUID(); break; - case NPC_SKADI_THE_RUTHLESS: - SkadiRuthless = pCreature->GetGUID(); - break; case NPC_KING_YMIRON: KingYmiron = pCreature->GetGUID(); break; @@ -110,6 +113,8 @@ public: Grauf = pCreature->GetGUID(); break; } + + InstanceScript::OnCreatureCreate(pCreature); } void OnGameObjectCreate(GameObject* pGo) override @@ -238,8 +243,6 @@ public: return SvalaSorrowgrave; case DATA_GORTOK_PALEHOOF: return GortokPalehoof; - case DATA_SKADI_THE_RUTHLESS: - return SkadiRuthless; case DATA_KING_YMIRON: return KingYmiron; case DATA_NPC_FRENZIED_WORGEN: |