From 1672c2794c863c00757e3d2d2e6fe9319f21ada9 Mon Sep 17 00:00:00 2001 From: jokerlfm Date: Tue, 27 Jun 2023 14:11:16 +0800 Subject: [PATCH] premerge 202306271411 --- src/game/CMakeLists.txt | 2 + src/game/Group/Group.h | 5 + src/game/Nier/NierActions/NierAction_Base.cpp | 737 +++------ src/game/Nier/NierActions/NierAction_Base.h | 38 +- .../Nier/NierActions/NierAction_Druid.cpp | 4 +- .../Nier/NierActions/NierAction_Hunter.cpp | 4 +- src/game/Nier/NierActions/NierAction_Mage.cpp | 4 +- .../Nier/NierActions/NierAction_Paladin.cpp | 1393 ++++++++++++++++- .../Nier/NierActions/NierAction_Paladin.h | 44 +- .../Nier/NierActions/NierAction_Rogue.cpp | 340 +++- src/game/Nier/NierActions/NierAction_Rogue.h | 9 +- .../Nier/NierActions/NierAction_Warrior.cpp | 42 +- .../Nier/NierActions/NierAction_Warrior.h | 2 +- src/game/Nier/NierConfig.h | 12 + src/game/Nier/NierEntity.cpp | 37 +- src/game/Nier/NierManager.cpp | 301 ++-- src/game/Nier/NierManager.h | 4 +- .../NierStrategies/GroupStrategy_Base.cpp | 364 +++++ .../Nier/NierStrategies/GroupStrategy_Base.h | 40 + .../Nier/NierStrategies/NierStrategy_Base.cpp | 843 ++-------- .../Nier/NierStrategies/NierStrategy_Base.h | 55 +- src/game/ObjectMgr.cpp | 2 +- src/game/Objects/Player.cpp | 17 +- src/game/Objects/Player.h | 6 +- 24 files changed, 2772 insertions(+), 1533 deletions(-) create mode 100644 src/game/Nier/NierStrategies/GroupStrategy_Base.cpp create mode 100644 src/game/Nier/NierStrategies/GroupStrategy_Base.h diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index 4fe52ec79b3..64fb85e398f 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -424,6 +424,8 @@ set (game_SRCS Nier/NierManager.cpp Nier/NierStrategies/NierStrategy_Base.h Nier/NierStrategies/NierStrategy_Base.cpp + Nier/NierStrategies/GroupStrategy_Base.h + Nier/NierStrategies/GroupStrategy_Base.cpp Nier/NierActions/NierAction_Base.h Nier/NierActions/NierAction_Base.cpp Nier/NierActions/NierAction_Druid.h diff --git a/src/game/Group/Group.h b/src/game/Group/Group.h index 449ef99b034..0a574bc083e 100644 --- a/src/game/Group/Group.h +++ b/src/game/Group/Group.h @@ -35,6 +35,9 @@ #include #include + // lfm nier +#include "Nier/NierStrategies/GroupStrategy_Base.h" + class WorldSession; class Map; class BattleGround; @@ -210,6 +213,8 @@ class Group // lfm nier uint32 GetTargetIconByGuid(ObjectGuid ogTarget); ObjectGuid GetGuidByTargetIcon(uint32 icon); + std::unordered_map nierGroupStrategyMap; + uint32 activeStrategyIndex; // lfm group target arrangement std::unordered_map groupTargetArrangementMap; diff --git a/src/game/Nier/NierActions/NierAction_Base.cpp b/src/game/Nier/NierActions/NierAction_Base.cpp index 8f1ca7681dd..31de29a4e66 100644 --- a/src/game/Nier/NierActions/NierAction_Base.cpp +++ b/src/game/Nier/NierActions/NierAction_Base.cpp @@ -18,12 +18,10 @@ NierMovement::NierMovement(Player* pmMe) ogChaseTarget = ObjectGuid(); ogFollowTarget = ObjectGuid(); positionTarget = me->GetPosition(); - distanceMax = 0.0f; - distanceMin = 0.0f; - holding = false; - forceBack = false; + maxDistance = 0.0f; + minDistance = 0.0f; moveCheckDelay = 0; - backwardCheckDelay = 0; + updateCheckDelay = 0; activeMovementType = NierMovementType::NierMovementType_None; } @@ -35,11 +33,10 @@ void NierMovement::ResetMovement() ogChaseTarget = ObjectGuid(); ogFollowTarget = ObjectGuid(); positionTarget = me->GetPosition(); - distanceMax = 0.0f; - distanceMin = 0.0f; - holding = false; - forceBack = false; + minDistance = 0.0f; + maxDistance = 0.0f; moveCheckDelay = 0; + updateCheckDelay = 0; me->m_movementInfo.moveFlags = 0; activeMovementType = NierMovementType::NierMovementType_None; } @@ -61,12 +58,12 @@ void NierMovement::Run() void NierMovement::Update_Direct(uint32 pmDiff) { - if (moveCheckDelay > 0) + if (updateCheckDelay > 0) { - moveCheckDelay -= pmDiff; + updateCheckDelay -= pmDiff; return; } - moveCheckDelay = DEFAULT_MOVEMENT_UPDATE_DELAY; + updateCheckDelay = DEFAULT_MOVEMENT_UPDATE_DELAY; if (!me) { return; @@ -79,6 +76,10 @@ void NierMovement::Update_Direct(uint32 pmDiff) { return; } + if (!me->CanFreeMove()) + { + return; + } if (me->HasUnitState(UnitState::UNIT_STAT_CAN_NOT_MOVE) || me->HasUnitState(UnitState::UNIT_STAT_NOT_MOVE)) { return; @@ -118,7 +119,7 @@ void NierMovement::Update_Direct(uint32 pmDiff) { me->StopMoving(); me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); + me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING | MoveOptions::MOVE_RUN_MODE); } } } @@ -128,73 +129,63 @@ void NierMovement::Update_Direct(uint32 pmDiff) { if (Unit* chaseTarget = ObjectAccessor::GetUnit(*me, ogTankTarget)) { - if (holding) + float targetDistance = me->GetDistance3dToCenter(chaseTarget->GetPosition()); + if (targetDistance > VISIBILITY_DISTANCE_LARGE) { - if (me->IsMoving()) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - if (!me->HasInArc(chaseTarget, M_PI / 2)) - { - me->SetFacingToObject(chaseTarget); - } + ResetMovement(); + break; } - else + float attackDistance = chaseTarget->GetCombatReach(); + float chaseDistance = attackDistance / 2.0f; + float meleeMinDistance = std::min(NIER_MIN_DISTANCE, attackDistance); + if (targetDistance < attackDistance && targetDistance > meleeMinDistance) { - float targetDistance = me->GetDistance3dToCenter(chaseTarget->GetPosition()); - if (targetDistance > VISIBILITY_DISTANCE_LARGE) + if (me->IsWithinLOSInMap(chaseTarget)) { - ResetMovement(); - break; - } - float chaseDistance = distanceMax; - if (chaseDistance > MELEE_RANGE) - { - chaseDistance = chaseDistance - MELEE_RANGE; - } - if (targetDistance < chaseTarget->GetCombatReach() + me->GetCombatReach() + distanceMax) - { - if (me->IsWithinLOSInMap(chaseTarget)) + if (me->IsMoving()) { - if (me->IsMoving()) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - if (!me->HasInArc(chaseTarget, M_PI / 2)) - { - me->SetFacingToObject(chaseTarget); - } - break; + me->StopMoving(); + me->GetMotionMaster()->Clear(); } - else + if (!me->IsFacingTarget(chaseTarget)) { - chaseDistance = chaseDistance / 2.0f; + me->SetFacingToObject(chaseTarget); } + //if (!me->HasInArc(chaseTarget, M_PI / 2)) + //{ + // me->SetFacingToObject(chaseTarget); + //} + break; } - if (me->IsMoving()) + else if (me->IsMoving()) { - bool ptValid = true; - if (chaseTarget->GetDistance3dToCenter(positionTarget) > chaseTarget->GetCombatReach() + distanceMax) - { - ptValid = false; - } - else if (!chaseTarget->IsWithinLOS(positionTarget.x, positionTarget.y, positionTarget.z)) - { - ptValid = false; - } - if (ptValid) + if (moveCheckDelay > 0) { + moveCheckDelay -= pmDiff; break; } + moveCheckDelay = DEFAULT_MOVEMENT_CHECK_DELAY; } - //Position predict = sNierManager->PredictPosition(chaseTarget); - chaseTarget->GetNearPoint(chaseTarget, positionTarget.x, positionTarget.y, positionTarget.z, 0.0f, chaseDistance, chaseTarget->GetAngle(me)); - Run(); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); + else + { + chaseDistance = std::max(targetDistance / 2.0f, NIER_MIN_DISTANCE); + } + } + Position nextPosition; + chaseTarget->GetNearPoint(nullptr, nextPosition.x, nextPosition.y, nextPosition.z, 0.0f, chaseDistance, chaseTarget->GetAngle(me)); + float dx = nextPosition.x - positionTarget.x; + float dy = nextPosition.y - positionTarget.y; + float dz = nextPosition.z - positionTarget.z; + float dist = sqrt((dx * dx) + (dy * dy) + (dz * dz)); + if (dist > NIER_MIN_DISTANCE) + { + //Run(); + //me->StopMoving(); + //me->GetMotionMaster()->Clear(); + positionTarget.x = nextPosition.x; + positionTarget.y = nextPosition.y; + positionTarget.z = nextPosition.z; + me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING | MoveOptions::MOVE_RUN_MODE); } } else @@ -207,214 +198,68 @@ void NierMovement::Update_Direct(uint32 pmDiff) { if (Unit* chaseTarget = ObjectAccessor::GetUnit(*me, ogChaseTarget)) { - if (holding) + float targetDistance = me->GetDistance3dToCenter(chaseTarget->GetPosition()); + if (targetDistance > VISIBILITY_DISTANCE_LARGE) { - if (me->IsMoving()) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - if (!me->HasInArc(chaseTarget, M_PI / 2)) - { - me->SetFacingToObject(chaseTarget); - } + ResetMovement(); + break; } - else + float attackDistance = maxDistance; + // melee attack + if (attackDistance < INTERACTION_DISTANCE) + { + attackDistance = chaseTarget->GetCombatReach(); + } + float chaseDistance = attackDistance / 2.0f; + float attackMinDistance = std::max(NIER_MIN_DISTANCE, minDistance); + if (targetDistance < attackDistance && targetDistance > attackMinDistance) { - float targetDistance = me->GetDistance3dToCenter(chaseTarget->GetPosition()); - if (backwardCheckDelay < 0) + if (me->IsWithinLOSInMap(chaseTarget)) { - if (targetDistance < me->GetCombatDistance(chaseTarget) / 4.0f) + if (me->IsMoving()) { - float moveDist = me->GetCombatDistance(chaseTarget) / 2.0f; - chaseTarget->GetNearPoint(chaseTarget, positionTarget.x, positionTarget.y, positionTarget.z, 0.0f, moveDist, chaseTarget->GetAngle(me)); - Run(); me->StopMoving(); me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); - break; - } - - backwardCheckDelay = 20; - } - else - { - backwardCheckDelay -= 1; - } - if (targetDistance > VISIBILITY_DISTANCE_LARGE) - { - ResetMovement(); - break; - } - float chaseDistance = distanceMax; - if (targetDistance < (chaseTarget->GetCombatReach() + me->GetCombatReach()) / 2.0f + distanceMax) - { - bool minValid = true; - if (distanceMin > 0.0f) - { - if (targetDistance < chaseTarget->GetCombatReach() + distanceMin) - { - minValid = false; - chaseDistance = distanceMin + (distanceMax - distanceMin) / 2.0f; - } } - if (minValid) + if (!me->IsFacingTarget(chaseTarget)) { - if (me->IsWithinLOSInMap(chaseTarget)) - { - if (!me->HasInArc(chaseTarget, M_PI / 2)) - { - me->SetFacingToObject(chaseTarget); - break; - } - if (forceBack) - { - if (!chaseTarget->HasInArc(me, M_PI * 7 / 4)) - { - if (me->IsMoving()) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - break; - } - } - else - { - if (me->IsMoving()) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - break; - } - } - else - { - chaseDistance = chaseDistance / 2.0f; - } + me->SetFacingToObject(chaseTarget); } + //if (!me->HasInArc(chaseTarget, M_PI / 2)) + //{ + // me->SetFacingToObject(chaseTarget); + //} + break; } - if (me->IsMoving()) + else if (me->IsMoving()) { - bool ptValid = true; - float ptDistance = chaseTarget->GetDistance3dToCenter(positionTarget); - if (ptDistance > (chaseTarget->GetCombatReach() + me->GetCombatReach()) / 2.0f + distanceMax) - { - ptValid = false; - } - else if (!chaseTarget->IsWithinLOS(positionTarget.x, positionTarget.y, positionTarget.z)) - { - ptValid = false; - } - else if (distanceMin > 0.0f) - { - if (ptDistance < chaseTarget->GetCombatReach() + distanceMin) - { - ptValid = false; - } - } - if (ptValid) + if (moveCheckDelay > 0) { + moveCheckDelay -= pmDiff; break; } - } - if (forceBack) - { - chaseTarget->GetNearPoint(chaseTarget, positionTarget.x, positionTarget.y, positionTarget.z, 0.0f, DEFAULT_OBJECT_SCALE, chaseTarget->GetOrientation() + M_PI); + moveCheckDelay = DEFAULT_MOVEMENT_CHECK_DELAY; } else { - positionTarget = chaseTarget->GetPosition(); - } - Run(); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); - } - } - else - { - ResetMovement(); - } - break; - } - case NierMovementType::NierMovementType_Follow: - { - if (Unit* chaseTarget = ObjectAccessor::GetUnit(*me, ogFollowTarget)) - { - if (holding) - { - if (me->IsMoving()) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - if (!me->HasInArc(chaseTarget, M_PI / 2)) - { - me->SetFacingToObject(chaseTarget); + chaseDistance = std::max(targetDistance / 2.0f, NIER_MIN_DISTANCE); } } - else + Position nextPosition; + chaseTarget->GetNearPoint(nullptr, nextPosition.x, nextPosition.y, nextPosition.z, 0.0f, chaseDistance, chaseTarget->GetAngle(me)); + float dx = nextPosition.x - positionTarget.x; + float dy = nextPosition.y - positionTarget.y; + float dz = nextPosition.z - positionTarget.z; + float dist = sqrt((dx * dx) + (dy * dy) + (dz * dz)); + if (dist > NIER_MIN_DISTANCE) { - float targetDistance = me->GetDistance3dToCenter(chaseTarget->GetPosition()); - if (targetDistance > VISIBILITY_DISTANCE_LARGE) - { - ResetMovement(); - break; - } - float chaseDistance = distanceMax; - if (targetDistance < distanceMax) - { - if (me->IsWithinLOSInMap(chaseTarget)) - { - if (me->IsMoving()) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - if (!me->HasInArc(chaseTarget, M_PI / 2)) - { - me->SetFacingToObject(chaseTarget); - } - break; - } - else - { - chaseDistance = chaseDistance / 2.0f; - } - } - if (me->IsMoving()) - { - bool ptValid = true; - float ptDistance = chaseTarget->GetDistance3dToCenter(positionTarget); - if (ptDistance > distanceMax) - { - ptValid = false; - } - else if (!chaseTarget->IsWithinLOS(positionTarget.x, positionTarget.y, positionTarget.z)) - { - ptValid = false; - } - else if (distanceMin > 0.0f) - { - if (ptDistance < chaseTarget->GetCombatReach() + distanceMin) - { - ptValid = false; - } - } - if (ptValid) - { - break; - } - } - //Position predict = sNierManager->PredictPosition(chaseTarget); - //chaseTarget->GetNearPoint(chaseTarget, positionTarget.x, positionTarget.y, positionTarget.z, 0.0f, chaseDistance, chaseTarget->GetAngle(me), 0.0f, &predict); - positionTarget = chaseTarget->GetPosition(); - Run(); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); + //Run(); + //me->StopMoving(); + //me->GetMotionMaster()->Clear(); + positionTarget.x = nextPosition.x; + positionTarget.y = nextPosition.y; + positionTarget.z = nextPosition.z; + me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING | MoveOptions::MOVE_RUN_MODE); } } else @@ -423,247 +268,66 @@ void NierMovement::Update_Direct(uint32 pmDiff) } break; } - default: - { - break; - } - } -} - -void NierMovement::Update_Chase(uint32 pmDiff) -{ - if (moveCheckDelay > 0) - { - moveCheckDelay -= pmDiff; - return; - } - if (!me) - { - return; - } - if (!me->IsAlive()) - { - return; - } - if (me->HasAuraType(SPELL_AURA_MOD_PACIFY)) - { - return; - } - if (me->HasUnitState(UnitState::UNIT_STAT_CAN_NOT_MOVE) || me->HasUnitState(UnitState::UNIT_STAT_NOT_MOVE)) - { - return; - } - //if (me->HasUnitState(UnitState::UNIT_STATE_ROAMING_MOVE)) - //{ - // return; - //} - if (me->IsNonMeleeSpellCasted(false, false, true)) - { - return; - } - if (me->IsBeingTeleported()) - { - return; - } - switch (activeMovementType) - { - case NierMovementType::NierMovementType_None: - { - break; - } - case NierMovementType::NierMovementType_Point: - { - float distance = me->GetDistance(positionTarget); - if (distance > VISIBILITY_DISTANCE_LARGE) - { - ResetMovement(); - } - else - { - if (distance < CONTACT_DISTANCE) - { - activeMovementType = NierMovementType::NierMovementType_None; - } - else - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != MovementGeneratorType::POINT_MOTION_TYPE) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); - } - moveCheckDelay = DEFAULT_MOVEMENT_UPDATE_DELAY; - } - } - break; - } - case NierMovementType::NierMovementType_Tank: + case NierMovementType::NierMovementType_Follow: { - if (Unit* chaseTarget = ObjectAccessor::GetUnit(*me, ogTankTarget)) + if (Unit* chaseTarget = ObjectAccessor::GetUnit(*me, ogFollowTarget)) { - if (holding) + float targetDistance = me->GetDistance3dToCenter(chaseTarget->GetPosition()); + if (targetDistance > VISIBILITY_DISTANCE_LARGE) { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != MovementGeneratorType::IDLE_MOTION_TYPE) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - if (!me->HasInArc(chaseTarget, M_PI / 2)) - { - me->SetFacingToObject(chaseTarget); - } + ResetMovement(); + break; } - else + float chaseDistance = maxDistance; + if (targetDistance < chaseDistance) { - float chaseDistance = distanceMax; - if (chaseDistance > MELEE_RANGE) - { - chaseDistance = chaseDistance - MELEE_RANGE; - } - float targetDistance = me->GetDistance3dToCenter(chaseTarget->GetPosition()); - if (me->IsWithinLOSInMap(chaseTarget) && targetDistance < chaseTarget->GetCombatReach() + chaseDistance) + if (me->IsWithinLOSInMap(chaseTarget)) { - if (!me->HasInArc(chaseTarget, M_PI / 2)) + if (me->IsMoving()) { - me->SetFacingToObject(chaseTarget); + me->StopMoving(); + me->GetMotionMaster()->Clear(); } - return; - } - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == MovementGeneratorType::CHASE_MOTION_TYPE) - { - if (const ChaseMovementGenerator* mg = static_cast const*>(me->GetMotionMaster()->top())) - { - if (Unit* mgTarget = mg->GetTarget()) - { - if (mgTarget->GetObjectGuid() == chaseTarget->GetObjectGuid()) - { - break; - } - } - } - } - Run(); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(chaseTarget, chaseDistance); - } - //moveCheckDelay = 100; - } - else - { - ResetMovement(); - } - break; - } - case NierMovementType::NierMovementType_Chase: - { - if (Unit* chaseTarget = ObjectAccessor::GetUnit(*me, ogChaseTarget)) - { - if (holding) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != MovementGeneratorType::IDLE_MOTION_TYPE) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - if (!me->HasInArc(chaseTarget, M_PI / 2)) - { - me->SetFacingToObject(chaseTarget); - } - } - else - { - float chaseDistance = distanceMax; - float targetDistance = me->GetDistance3dToCenter(chaseTarget->GetPosition()); - if (me->IsWithinLOSInMap(chaseTarget) && targetDistance < chaseTarget->GetCombatReach() + me->GetCombatReach() + chaseDistance) - { - if (!me->HasInArc(chaseTarget, M_PI / 2)) + if (!me->IsFacingTarget(chaseTarget)) { me->SetFacingToObject(chaseTarget); } - return; - } - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == MovementGeneratorType::CHASE_MOTION_TYPE) - { - if (const ChaseMovementGenerator* mg = static_cast const*>(me->GetMotionMaster()->top())) - { - if (Unit* mgTarget = mg->GetTarget()) - { - if (mgTarget->GetObjectGuid() == chaseTarget->GetObjectGuid()) - { - return; - } - } - } + //if (!me->HasInArc(chaseTarget, M_PI / 2)) + //{ + // me->SetFacingToObject(chaseTarget); + //} + break; } - float chaseAngle = 0.0f; - if (forceBack) + else if (me->IsMoving()) { - if (chaseTarget->GetTargetGuid() != me->GetObjectGuid()) + if (moveCheckDelay > 0) { - chaseAngle = frand(M_PI - M_PI / 8, M_PI + M_PI / 8); + moveCheckDelay -= pmDiff; + break; } + moveCheckDelay = DEFAULT_MOVEMENT_CHECK_DELAY; } - Run(); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(chaseTarget, chaseDistance, chaseAngle); - } - moveCheckDelay = DEFAULT_MOVEMENT_UPDATE_DELAY; - } - else - { - ResetMovement(); - } - break; - } - case NierMovementType::NierMovementType_Follow: - { - if (Unit* followTarget = ObjectAccessor::GetUnit(*me, ogFollowTarget)) - { - if (holding) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != MovementGeneratorType::IDLE_MOTION_TYPE) - { - me->StopMoving(); - me->GetMotionMaster()->Clear(); - } - if (!me->HasInArc(followTarget, M_PI / 2)) + else { - me->SetFacingToObject(followTarget); + chaseDistance = targetDistance / 2.0f; } } - else + Position nextPosition; + chaseTarget->GetNearPoint(nullptr, nextPosition.x, nextPosition.y, nextPosition.z, 0.0f, chaseDistance, chaseTarget->GetAngle(me)); + float dx = nextPosition.x - positionTarget.x; + float dy = nextPosition.y - positionTarget.y; + float dz = nextPosition.z - positionTarget.z; + float dist = sqrt((dx * dx) + (dy * dy) + (dz * dz)); + if (dist > NIER_MIN_DISTANCE) { - float followDistance = distanceMax; - float targetDistance = me->GetDistance3dToCenter(followTarget->GetPosition()); - if (me->IsWithinLOSInMap(followTarget) && targetDistance < followTarget->GetCombatReach() + me->GetCombatReach() + followDistance) - { - if (!me->HasInArc(followTarget, M_PI / 2)) - { - me->SetFacingToObject(followTarget); - } - return; - } - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == MovementGeneratorType::CHASE_MOTION_TYPE) - { - if (const ChaseMovementGenerator* mg = static_cast const*>(me->GetMotionMaster()->top())) - { - if (Unit* mgTarget = mg->GetTarget()) - { - if (mgTarget->GetObjectGuid() == followTarget->GetObjectGuid()) - { - return; - } - } - } - } - Run(); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(followTarget, followDistance); + //Run(); + //me->StopMoving(); + //me->GetMotionMaster()->Clear(); + positionTarget.x = nextPosition.x; + positionTarget.y = nextPosition.y; + positionTarget.z = nextPosition.z; + me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING | MoveOptions::MOVE_RUN_MODE); } - moveCheckDelay = DEFAULT_MOVEMENT_UPDATE_DELAY; } else { @@ -678,11 +342,8 @@ void NierMovement::Update_Chase(uint32 pmDiff) } } -bool NierMovement::Tank(Unit* pmTankTarget, float pmDistanceMax, float pmDistanceMin, bool pmHolding) +bool NierMovement::Tank(Unit* pmTankTarget) { - distanceMax = pmDistanceMax; - distanceMin = pmDistanceMin; - holding = pmHolding; if (me && pmTankTarget) { float distance = me->GetDistance(pmTankTarget); @@ -703,16 +364,14 @@ bool NierMovement::Tank(Unit* pmTankTarget, float pmDistanceMax, float pmDistanc return false; } -bool NierMovement::Chase(Unit* pmChaseTarget, float pmDistanceMax, float pmDistanceMin, bool pmHolding, bool pmForceBack) +bool NierMovement::Chase(Unit* pmChaseTarget, float pmDistanceMax, float pmDistanceMin) { if (me && pmChaseTarget) { if (me->IsWithinDist(pmChaseTarget, VISIBILITY_DISTANCE_NORMAL)) { - distanceMax = pmDistanceMax; - distanceMin = pmDistanceMin; - holding = pmHolding; - forceBack = pmForceBack; + maxDistance = pmDistanceMax; + minDistance = pmDistanceMin; activeMovementType = NierMovementType::NierMovementType_Chase; if (ogChaseTarget != pmChaseTarget->GetObjectGuid()) { @@ -728,15 +387,13 @@ bool NierMovement::Chase(Unit* pmChaseTarget, float pmDistanceMax, float pmDista return false; } -bool NierMovement::Follow(Unit* pmFollowTarget, float pmDistanceMax, float pmDistanceMin, bool pmHolding) +bool NierMovement::Follow(Unit* pmFollowTarget, float pmDistance) { if (me && pmFollowTarget) { - if (me->IsWithinDist(pmFollowTarget, VISIBILITY_DISTANCE_NORMAL)) + if (me->IsWithinDistInMap(pmFollowTarget, VISIBILITY_DISTANCE_NORMAL)) { - distanceMax = pmDistanceMax; - distanceMin = pmDistanceMin; - holding = pmHolding; + maxDistance = pmDistance; activeMovementType = NierMovementType::NierMovementType_Follow; if (ogFollowTarget != pmFollowTarget->GetObjectGuid()) { @@ -772,7 +429,7 @@ void NierMovement::Point(Position pmPosTarget, uint32 pmLimit) Run(); me->StopMoving(); me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); + me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING | MoveOptions::MOVE_RUN_MODE); moveCheckDelay = DEFAULT_MOVEMENT_UPDATE_DELAY; } } @@ -853,7 +510,7 @@ bool NierMovement::Direction(Unit* pmCommander, uint32 pmDirection, uint32 pmLim Run(); me->StopMoving(); me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); + me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING | MoveOptions::MOVE_RUN_MODE); result = true; } @@ -874,7 +531,7 @@ bool NierMovement::Direction(float pmAngle, uint32 pmLimit, float pmDistance) } me->StopMoving(); me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING); + me->GetMotionMaster()->MovePoint(0, positionTarget.x, positionTarget.y, positionTarget.z, MoveOptions::MOVE_PATHFINDING | MoveOptions::MOVE_RUN_MODE); result = true; return result; @@ -916,22 +573,27 @@ void NierAction_Base::Update(uint32 pmDiff) //nm->Update_Chase(pmDiff); } -bool NierAction_Base::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, float pmDistanceMin, bool pmHolding, bool pmInstantOnly, bool pmChasing) +bool NierAction_Base::Attack(Unit* pmTarget) +{ + return false; +} + +bool NierAction_Base::Interrupt(Unit* pmTarget) { return false; } -bool NierAction_Base::AOE(Unit* pmTarget, bool pmRushing, float pmDistanceMax, float pmDistanceMin, bool pmHolding, bool pmInstantOnly, bool pmChasing) +bool NierAction_Base::DPS(Unit* pmTarget, bool pmRushing, bool pmChasing, float pmDistanceMax, float pmDistanceMin) { return false; } -bool NierAction_Base::Tank(Unit* pmTarget, bool pmAOE, float pmDistanceMax, float pmDistanceMin, bool pmHolding) +bool NierAction_Base::Tank(Unit* pmTarget, bool aoe) { return false; } -bool NierAction_Base::Follow(Unit* pmFollowTarget, float pmDistanceMax, float pmDistanceMin, bool pmHolding) +bool NierAction_Base::Follow(Unit* pmFollowTarget, float pmDistance) { if (!me) { @@ -949,7 +611,7 @@ bool NierAction_Base::Follow(Unit* pmFollowTarget, float pmDistanceMax, float pm { return false; } - if (!nm->Follow(pmFollowTarget, pmDistanceMax, pmDistanceMin, pmHolding)) + if (!nm->Follow(pmFollowTarget, pmDistance)) { if (me->GetTargetGuid() == pmFollowTarget->GetObjectGuid()) { @@ -1007,7 +669,7 @@ uint32 NierAction_Base::Caution() me->InterruptNonMeleeSpells(false); me->StopMoving(); me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, pos.x, pos.y, pos.z, MoveOptions::MOVE_PATHFINDING); + me->GetMotionMaster()->MovePoint(0, pos.x, pos.y, pos.z, MoveOptions::MOVE_PATHFINDING | MoveOptions::MOVE_RUN_MODE); return 2000; } } @@ -1142,6 +804,16 @@ void NierAction_Base::TrainSpells(uint32 pmTrainerEntry) { hadNew = true; SpellEntry const* proto = sSpellMgr.GetSpellEntry(eachSpell->spell); + for (size_t i = 0; i < MAX_SPELL_REAGENTS; i++) + { + if (proto->Reagent[i] > 0) + { + if (!me->HasItemCount(proto->Reagent[i], proto->ReagentCount[i])) + { + me->StoreNewItemInBestSlots(proto->Reagent[i], proto->ReagentCount[i] * 10); + } + } + } me->InterruptSpellsWithChannelFlags(AURA_INTERRUPT_INTERACTING_CANCELS); me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_INTERACTING_CANCELS); me->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED); @@ -1241,6 +913,10 @@ void NierAction_Base::EquipRandomItem(uint32 pmEquipSlot, uint32 pmClass, uint32 return; } + if (pmInventoryTypeSet.size() > 0) + { + inventoryType = *pmInventoryTypeSet.begin(); + } int maxReqLevel = me->GetLevel(); int minReqLevel = maxReqLevel - 5; while (minReqLevel > 0 && maxReqLevel > 1) @@ -1248,13 +924,13 @@ void NierAction_Base::EquipRandomItem(uint32 pmEquipSlot, uint32 pmClass, uint32 if (sNierManager->equipsMap.find(inventoryType) != sNierManager->equipsMap.end()) { int activeLevel = urand(minReqLevel, maxReqLevel); - if (sNierManager->equipsMap[inventoryType].find(activeLevel) != sNierManager->equipsMap[inventoryType].end()) + if (sNierManager->equipsMap[inventoryType][pmSubclass].find(activeLevel) != sNierManager->equipsMap[inventoryType][pmSubclass].end()) { - int itemsSize = sNierManager->equipsMap[inventoryType][activeLevel].size(); + int itemsSize = sNierManager->equipsMap[inventoryType][pmSubclass][activeLevel].size(); if (itemsSize > 0) { int itemIndex = urand(0, itemsSize - 1); - uint32 itemEntry = sNierManager->equipsMap[inventoryType][activeLevel][itemIndex]; + uint32 itemEntry = sNierManager->equipsMap[inventoryType][pmSubclass][activeLevel][itemIndex]; if (const ItemPrototype* pProto = sObjectMgr.GetItemPrototype(itemEntry)) { bool hasStat = false; @@ -1282,19 +958,52 @@ void NierAction_Base::EquipRandomItem(uint32 pmEquipSlot, uint32 pmClass, uint32 } if (hasStat) { - if (Item* pItem = Item::CreateItem(itemEntry, 1)) + uint16 eDest; + uint8 msg = me->CanEquipNewItem(NULL_SLOT, eDest, itemEntry, false); + if (msg == EQUIP_ERR_OK) { - uint16 dest = 0; - if (me->CanEquipItem(pmEquipSlot, dest, pItem, false) == InventoryResult::EQUIP_ERR_OK) + if (Item* pItem = Item::CreateItem(itemEntry, 1, me->GetObjectGuid())) + { + if (uint32 randomPropertyId = Item::GenerateItemRandomPropertyId(itemEntry)) + { + pItem->SetItemRandomProperties(randomPropertyId); + pItem->SetState(ItemUpdateState::ITEM_NEW, me); + } + me->SendNewItem(pItem, 1, true, true); + ItemPosCountVec sDest; + uint8 storeResult = me->CanStoreItem(NULL_BAG, NULL_SLOT, sDest, pItem, false); + if (storeResult == EQUIP_ERR_OK) + { + me->StoreItem(sDest, pItem, true); + } + } + for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) { - me->EquipItem(dest, pItem, true); - std::ostringstream msgStream; - msgStream << me->GetName() << " Equiped " << pItem->GetProto()->Name1; - sWorld.SendServerMessage(ServerMessageType::SERVER_MSG_CUSTOM, msgStream.str().c_str()); - sLog.Out(LogType::LOG_BASIC, LogLevel::LOG_LVL_BASIC, msgStream.str().c_str()); - return; + if (Item* targetItem = me->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + { + if (targetItem->GetEntry() == itemEntry) + { + uint16 dest = 0; + InventoryResult ir = me->CanEquipItem(NULL_SLOT, dest, targetItem, false); + if (ir == EQUIP_ERR_OK) + { + me->RemoveItem(INVENTORY_SLOT_BAG_0, i, true); + me->EquipItem(dest, targetItem, true); + break; + } + } + } } } + + //if (me->StoreNewItemInBestSlots(itemEntry, 1)) + //{ + // std::ostringstream msgStream; + // msgStream << me->GetName() << " Equiped " << itemEntry; + // sWorld.SendServerMessage(ServerMessageType::SERVER_MSG_CUSTOM, msgStream.str().c_str()); + // sLog.Out(LogType::LOG_BASIC, LogLevel::LOG_LVL_BASIC, msgStream.str().c_str()); + // return; + //} } } } @@ -1449,6 +1158,14 @@ bool NierAction_Base::CastSpell(Unit* pmTarget, uint32 pmSpellId, bool pmCheckAu } } } + if (Spell* checkSpell = new Spell(me, pS, false)) + { + SpellCastResult scr = checkSpell->CheckCast(true); + if (scr != SpellCastResult::SPELL_CAST_OK) + { + return false; + } + } if (!me->HasInArc(pmTarget, M_PI / 2)) { me->SetFacingToObject(pmTarget); @@ -1524,7 +1241,7 @@ bool NierAction_Base::Eat() } else if (myLevel >= 55) { - foodEntry = 27855; + foodEntry = 21023; } else if (myLevel >= 45) { @@ -1823,7 +1540,7 @@ bool NierAction_Base::RandomTeleport() float nearX = 0.0f; float nearY = 0.0f; float nearZ = 0.0f; - float nearDistance = frand(100.0f, 300.0f); + float nearDistance = frand(100.0f, 300.0f); float nearAngle = frand(0.0f, M_PI * 2); targetPlayer->GetNearPoint(targetPlayer, nearX, nearY, nearZ, 0.0f, nearDistance, nearAngle); if (!me->IsAlive()) diff --git a/src/game/Nier/NierActions/NierAction_Base.h b/src/game/Nier/NierActions/NierAction_Base.h index ff7d03ca3b6..e82de274efe 100644 --- a/src/game/Nier/NierActions/NierAction_Base.h +++ b/src/game/Nier/NierActions/NierAction_Base.h @@ -9,6 +9,10 @@ #define DEFAULT_MOVEMENT_UPDATE_DELAY 100 #endif +#ifndef DEFAULT_MOVEMENT_CHECK_DELAY +#define DEFAULT_MOVEMENT_CHECK_DELAY 500 +#endif + #include "Nier/NierConfig.h" #include "Nier/NierManager.h" #include "MotionMaster.h" @@ -43,12 +47,11 @@ class NierMovement NierMovement(Player* pmMe); void ResetMovement(); void Update_Direct(uint32 pmDiff); - void Update_Chase(uint32 pmDiff); void Run(); - bool Tank(Unit* pmTankTarget, float pmDistanceMax, float pmDistanceMin, bool pmHolding); - bool Chase(Unit* pmChaseTarget, float pmDistanceMax, float pmDistanceMin, bool pmHolding, bool pmForceBack); - bool Follow(Unit* pmFollowTarget, float pmDistanceMax, float pmDistanceMin, bool pmHolding); + bool Tank(Unit* pmTankTarget); + bool Chase(Unit* pmChaseTarget, float pmDistanceMax, float pmDistanceMin); + bool Follow(Unit* pmFollowTarget, float pmDistance); void Point(Position pmPosTarget, uint32 pmLimit = DEFAULT_ACTION_LIMIT_DELAY); bool Direction(Unit* pmCommander, uint32 pmDirection, uint32 pmLimit = DEFAULT_ACTION_LIMIT_DELAY, float pmDistance = INTERACTION_DISTANCE); bool Direction(float pmAngle, uint32 pmLimit = DEFAULT_ACTION_LIMIT_DELAY, float pmDistance = NIER_NORMAL_DISTANCE); @@ -60,13 +63,11 @@ class NierMovement ObjectGuid ogChaseTarget; ObjectGuid ogFollowTarget; Position positionTarget; - uint32 activeMovementType; - float distanceMax; - float distanceMin; - bool holding; - bool forceBack; + uint32 activeMovementType; + float maxDistance; + float minDistance; + int updateCheckDelay; int moveCheckDelay; - int backwardCheckDelay; }; class NierAction_Base @@ -76,18 +77,19 @@ class NierAction_Base virtual void Reset(); virtual void Prepare(); virtual void Update(uint32 pmDiff); - virtual bool DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, float pmDistanceMin, bool pmHolding, bool pmInstantOnly, bool pmChasing); - virtual bool AOE(Unit* pmTarget, bool pmRushing, float pmDistanceMax, float pmDistanceMin, bool pmHolding, bool pmInstantOnly, bool pmChasing); - virtual bool Tank(Unit* pmTarget, bool pmAOE, float pmDistanceMax, float pmDistanceMin, bool pmHolding); + virtual bool Attack(Unit* pmTarget); + virtual bool Interrupt(Unit* pmTarget); + virtual bool DPS(Unit* pmTarget, bool pmRushing, bool pmChasing, float pmDistanceMax = DEFAULT_COMBAT_REACH, float pmDistanceMin = CONTACT_DISTANCE); + virtual bool Tank(Unit* pmTarget, bool aoe); virtual bool Heal(Unit* pmTarget, bool pmInstantOnly); - virtual bool Follow(Unit* pmFollowTarget, float pmDistanceMax, float pmDistanceMin, bool pmHolding); + virtual bool Follow(Unit* pmFollowTarget, float pmDistance); virtual bool ReadyTank(Unit* pmTarget); virtual bool GroupHeal(Unit* pmTarget, bool pmInstantOnly); virtual bool SimpleHeal(Unit* pmTarget, bool pmInstantOnly); virtual bool Cure(Unit* pmTarget); - virtual bool Buff(Unit* pmTarget); + virtual bool Buff(Unit* pmTarget); virtual uint32 Caution(); - virtual bool Mark(Unit* pmTarget,int pmRTI); + virtual bool Mark(Unit* pmTarget, int pmRTI); virtual bool Assist(int pmRTI); virtual bool Revive(Player* pmTarget); virtual bool Petting(bool pmSummon = true, bool pmReset = false); @@ -103,7 +105,7 @@ class NierAction_Base void PetStop(); bool UseItem(Item* pmItem, Unit* pmTarget); bool UseItem(Item* pmItem, Item* pmTarget); - bool CastSpell(Unit* pmTarget, uint32 pmSpellId, bool pmCheckAura = false, bool pmOnlyMyAura = false, bool pmClearShapeShift = false, uint32 pmMaxAuraStack = 1); + bool CastSpell(Unit* pmTarget, uint32 pmSpellId, bool pmCheckAura = false, bool pmOnlyMyAura = false, bool pmClearShapeShift = false, uint32 pmMaxAuraStack = 1); void CancelAura(uint32 pmSpellID); bool Eat(); bool Drink(); @@ -120,6 +122,6 @@ class NierAction_Base Player* me; NierMovement* nm; - uint32 specialty; + uint32 specialty; }; #endif diff --git a/src/game/Nier/NierActions/NierAction_Druid.cpp b/src/game/Nier/NierActions/NierAction_Druid.cpp index 66b01cac915..ab1379be5e3 100644 --- a/src/game/Nier/NierActions/NierAction_Druid.cpp +++ b/src/game/Nier/NierActions/NierAction_Druid.cpp @@ -591,7 +591,7 @@ bool NierAction_Druid::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, } if (pmChasing) { - if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin, pmHolding, false)) + if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin)) { if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) { @@ -759,7 +759,7 @@ bool NierAction_Druid::AOE(Unit* pmTarget, bool pmRushing, float pmDistanceMax, } if (pmChasing) { - if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin, pmHolding, false)) + if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin)) { if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) { diff --git a/src/game/Nier/NierActions/NierAction_Hunter.cpp b/src/game/Nier/NierActions/NierAction_Hunter.cpp index fa8eb4cf310..6c9c56a0002 100644 --- a/src/game/Nier/NierActions/NierAction_Hunter.cpp +++ b/src/game/Nier/NierActions/NierAction_Hunter.cpp @@ -600,7 +600,7 @@ bool NierAction_Hunter::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, } if (pmChasing) { - if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin, pmHolding, false)) + if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin)) { if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) { @@ -779,7 +779,7 @@ bool NierAction_Hunter::AOE(Unit* pmTarget, bool pmRushing, float pmDistanceMax, } if (pmChasing) { - if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin, pmHolding, false)) + if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin)) { if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) { diff --git a/src/game/Nier/NierActions/NierAction_Mage.cpp b/src/game/Nier/NierActions/NierAction_Mage.cpp index 963f8edacec..7689400209d 100644 --- a/src/game/Nier/NierActions/NierAction_Mage.cpp +++ b/src/game/Nier/NierActions/NierAction_Mage.cpp @@ -622,7 +622,7 @@ bool NierAction_Mage::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, f } if (pmChasing) { - if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin, pmHolding, false)) + if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin)) { if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) { @@ -862,7 +862,7 @@ bool NierAction_Mage::AOE(Unit* pmTarget, bool pmRushing, float pmDistanceMax, f } if (pmChasing) { - if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin, pmHolding, false)) + if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin)) { if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) { diff --git a/src/game/Nier/NierActions/NierAction_Paladin.cpp b/src/game/Nier/NierActions/NierAction_Paladin.cpp index 5e62e299e06..7071f44f736 100644 --- a/src/game/Nier/NierActions/NierAction_Paladin.cpp +++ b/src/game/Nier/NierActions/NierAction_Paladin.cpp @@ -2,11 +2,1392 @@ NierAction_Paladin::NierAction_Paladin(Player* pmMe) :NierAction_Base(pmMe) { - blessingType = PaladinBlessingType::PaladinBlessingType_Might; - auraType = PaladinAuraType::PaladinAuraType_Retribution; - sealType = PaladinSealType::PaladinSealType_Righteousness; + spell_ConcentrationAura = 0; + spell_FrostResistanceAura = 0; + spell_RetributionAura = 0; + spell_ShadowResistanceAura = 0; + spell_FireResistanceAura = 0; + spell_DevotionAura = 0; + spell_BlessingOfWisdom = 0; + spell_BlessingOfSalvation = 0; + spell_BlessingOfMight = 0; + spell_SealOfJustice = 0; + spell_SealOfRighteousness = 0; + spell_SealOfTheCrusader = 0; + spell_Judgement = 0; + spell_HammerOfJustice = 0; + spell_Exorcism = 0; + spell_LayOnHands = 0; + spell_DivineIntervention = 0; + spell_Consecration = 0; + spell_Blessing_Of_Sanctuary = 0; + spell_HolyShield = 0; + spell_RighteousFury = 0; + spell_Redemption = 0; - judgementDelay = 0; - hammerOfJusticeDelay = 0; - sealDelay = 0; + blessingType = PaladinBlessingType::PaladinBlessingType_Might; + auraType = PaladinAuraType::PaladinAuraType_Devotion; + sealType = PaladinSealType::PaladinSealType_Righteousness; + + judgementDelay = 0; + hammerOfJusticeDelay = 0; + sealDelay = 0; + exorcismDelay = 0; + layOnHandsDelay = 0; + interventionDelay = 0; + consecrationDelay = 0; + holyShieldDelay = 0; +} + +void NierAction_Paladin::InitializeCharacter(uint32 pmTargetLevel, uint32 pmSpecialtyTabIndex) +{ + if (!me) + { + return; + } + specialty = pmSpecialtyTabIndex; + me->ClearInCombat(); + uint32 myLevel = me->GetLevel(); + if (myLevel != pmTargetLevel) + { + me->GiveLevel(pmTargetLevel); + me->LearnDefaultSpells(); + me->LearnQuestRewardedSpells(); + + ResetTalent(); + RemoveEquipments(); + myLevel = me->GetLevel(); + } + + spell_DevotionAura = 465; + spell_SealOfRighteousness = 21084; + + if (myLevel >= 4) + { + spell_BlessingOfMight = 19740; + spell_Judgement = 20271; + } + if (myLevel >= 6) + { + spell_SealOfTheCrusader = 21082; + } + if (myLevel >= 8) + { + spell_HammerOfJustice = 853; + } + if (myLevel >= 10) + { + spell_DevotionAura = 10290; + spell_SealOfRighteousness = 20287; + spell_LayOnHands = 633; + } + if (myLevel >= 12) + { + spell_BlessingOfMight = 19834; + spell_SealOfTheCrusader = 20162; + spell_Redemption = 7328; + } + if (myLevel >= 14) + { + spell_BlessingOfWisdom = 19742; + } + if (myLevel >= 16) + { + spell_RetributionAura = 7294; + spell_RighteousFury = 25780; + } + if (myLevel >= 18) + { + spell_SealOfRighteousness = 20288; + } + if (myLevel >= 20) + { + spell_DevotionAura = 643; + spell_Exorcism = 879; + spell_Consecration = 26573; + } + if (myLevel >= 22) + { + spell_ConcentrationAura = 19746; + spell_BlessingOfMight = 19835; + spell_SealOfJustice = 20164; + spell_SealOfTheCrusader = 20305; + } + if (myLevel >= 24) + { + spell_BlessingOfWisdom = 19850; + spell_HammerOfJustice = 5588; + } + if (myLevel >= 26) + { + spell_RetributionAura = 10298; + spell_BlessingOfSalvation = 1038; + spell_SealOfRighteousness = 20289; + } + if (myLevel >= 28) + { + spell_ShadowResistanceAura = 19876; + spell_Exorcism = 5614; + } + if (myLevel >= 30) + { + spell_DevotionAura = 10291; + spell_LayOnHands = 2800; + spell_DivineIntervention = 19752; + spell_Consecration = 20116; + } + if (myLevel >= 32) + { + spell_FrostResistanceAura = 19888; + spell_BlessingOfMight = 19836; + spell_SealOfTheCrusader = 20306; + } + if (myLevel >= 34) + { + spell_BlessingOfWisdom = 19852; + spell_SealOfRighteousness = 20290; + } + if (myLevel >= 36) + { + spell_RetributionAura = 10299; + spell_FireResistanceAura = 19891; + spell_Exorcism = 5615; + } + if (myLevel >= 37) + { + + } + if (myLevel >= 38) + { + + } + if (myLevel >= 40) + { + spell_ShadowResistanceAura = 19895; + spell_DevotionAura = 1032; + spell_HammerOfJustice = 5589; + spell_Consecration = 20922; + } + if (myLevel >= 41) + { + spell_Blessing_Of_Sanctuary = 20911; + spell_Blessing_Of_Sanctuary = 20912; + } + if (myLevel >= 42) + { + spell_BlessingOfMight = 19837; + spell_SealOfRighteousness = 20291; + spell_SealOfTheCrusader = 20307; + } + if (myLevel >= 44) + { + spell_FrostResistanceAura = 19897; + spell_BlessingOfWisdom = 19853; + spell_Exorcism = 10312; + } + if (myLevel >= 46) + { + spell_RetributionAura = 10300; + } + if (myLevel >= 48) + { + spell_FireResistanceAura = 19899; + } + if (myLevel >= 50) + { + spell_DevotionAura = 10292; + spell_SealOfRighteousness = 20292; + spell_LayOnHands = 10310; + spell_Consecration = 20923; + spell_Blessing_Of_Sanctuary = 20913; + } + if (myLevel >= 51) + { + spell_DevotionAura = 10292; + spell_SealOfRighteousness = 20292; + spell_LayOnHands = 10310; + spell_Consecration = 20923; + spell_Blessing_Of_Sanctuary = 20913; + spell_HolyShield = 20925; + spell_HolyShield = 20927; + } + if (myLevel >= 52) + { + spell_ShadowResistanceAura = 19896; + spell_BlessingOfMight = 19838; + spell_SealOfTheCrusader = 20308; + spell_Exorcism = 10313; + } + if (myLevel >= 54) + { + spell_BlessingOfWisdom = 19854; + spell_HammerOfJustice = 10308; + } + if (myLevel >= 56) + { + spell_FrostResistanceAura = 19898; + spell_RetributionAura = 10301; + } + if (myLevel >= 58) + { + spell_SealOfRighteousness = 20293; + } + if (myLevel >= 60) + { + spell_FireResistanceAura = 19900; + spell_DevotionAura = 10293; + spell_Exorcism = 10314; + spell_Consecration = 20924; + spell_Blessing_Of_Sanctuary = 20914; + spell_HolyShield = 20928; + } + + me->UpdateSkillsToMaxSkillsForLevel(); + std::ostringstream msgStream; + msgStream << me->GetName() << " initialized"; + sWorld.SendServerMessage(ServerMessageType::SERVER_MSG_CUSTOM, msgStream.str().c_str()); +} + +void NierAction_Paladin::ResetTalent() +{ + if (!me) + { + return; + } + me->ResetTalents(true); + + // talent tab : 381 - retribution, 382 - holy, 383 - protection + // DPS + //LearnTalent(1450); + //LearnTalent(1407); + //LearnTalent(1631); + //LearnTalent(1464); + //LearnTalent(1411); + //LearnTalent(1634); + //LearnTalent(1405); + //LearnTalent(1401); + //LearnTalent(1410); + //LearnTalent(1402); + //LearnTalent(1463); + //LearnTalent(1449); + //LearnTalent(1446); + + //LearnTalent(1481); + //LearnTalent(1409); + + // Tank + LearnTalent(1449); + LearnTalent(1463); + LearnTalent(1435); + + LearnTalent(1422); + LearnTalent(1421); + LearnTalent(1501); + LearnTalent(1629); + LearnTalent(1424, 2); + LearnTalent(1431); + LearnTalent(1424); + LearnTalent(1423); + LearnTalent(1630); + LearnTalent(1430); + + LearnTalent(1443); + + LearnTalent(1425); + LearnTalent(1429); + + // paladin trainer Lord Grayson Shadowbreaker + TrainSpells(928); +} + +bool NierAction_Paladin::InitializeEquipments(bool pmReset) +{ + if (!me) + { + return true; + } + if (pmReset) + { + for (uint8 slot = INVENTORY_SLOT_ITEM_START; slot < INVENTORY_SLOT_ITEM_END; ++slot) + { + if (Item* inventoryItem = me->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + { + me->DestroyItem(INVENTORY_SLOT_BAG_0, slot, true); + } + } + for (uint32 checkEquipSlot = EquipmentSlots::EQUIPMENT_SLOT_HEAD; checkEquipSlot < EquipmentSlots::EQUIPMENT_SLOT_TABARD; checkEquipSlot++) + { + if (Item* currentEquip = me->GetItemByPos(INVENTORY_SLOT_BAG_0, checkEquipSlot)) + { + me->DestroyItem(INVENTORY_SLOT_BAG_0, checkEquipSlot, true); + } + } + } + uint32 myLevel = me->GetLevel(); + uint32 minQuality = ItemQualities::ITEM_QUALITY_UNCOMMON; + if (myLevel < 20) + { + minQuality = ItemQualities::ITEM_QUALITY_POOR; + } + for (uint32 checkEquipSlot = EquipmentSlots::EQUIPMENT_SLOT_HEAD; checkEquipSlot < EquipmentSlots::EQUIPMENT_SLOT_TABARD; checkEquipSlot++) + { + if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_HEAD) + { + if (myLevel < 30) + { + continue; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_SHOULDERS) + { + if (myLevel < 30) + { + continue; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_NECK) + { + if (myLevel < 30) + { + continue; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_FINGER1 || checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_FINGER2) + { + if (myLevel < 30) + { + continue; + } + } + std::unordered_set inventoryTypeSet; + uint32 modType = ItemModType::ITEM_MOD_AGILITY; + uint32 equipItemClass = 0; + uint32 equipItemSubClass = 0; + if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_HEAD) + { + equipItemClass = 4; + equipItemSubClass = 3; + if (myLevel >= 40) + { + equipItemSubClass = 4; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_SHOULDERS) + { + equipItemClass = 4; + equipItemSubClass = 3; + if (myLevel >= 40) + { + equipItemSubClass = 4; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_WRISTS) + { + equipItemClass = 4; + equipItemSubClass = 3; + if (myLevel >= 40) + { + equipItemSubClass = 4; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_WAIST) + { + equipItemClass = 4; + equipItemSubClass = 3; + if (myLevel >= 40) + { + equipItemSubClass = 4; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_FEET) + { + equipItemClass = 4; + equipItemSubClass = 3; + if (myLevel >= 40) + { + equipItemSubClass = 4; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_HANDS) + { + equipItemClass = 4; + equipItemSubClass = 3; + if (myLevel >= 40) + { + equipItemSubClass = 4; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_CHEST) + { + equipItemClass = 4; + equipItemSubClass = 3; + if (myLevel >= 40) + { + equipItemSubClass = 4; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_LEGS) + { + equipItemClass = 4; + equipItemSubClass = 3; + if (myLevel >= 40) + { + equipItemSubClass = 4; + } + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_BACK) + { + equipItemClass = 4; + equipItemSubClass = 1; + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_NECK) + { + equipItemClass = 4; + equipItemSubClass = 0; + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_FINGER1) + { + equipItemClass = 4; + equipItemSubClass = 0; + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_FINGER2) + { + equipItemClass = 4; + equipItemSubClass = 0; + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_MAINHAND) + { + equipItemClass = 2; + equipItemSubClass = 4; + inventoryTypeSet.insert(InventoryType::INVTYPE_WEAPON); + inventoryTypeSet.insert(InventoryType::INVTYPE_WEAPONMAINHAND); + } + else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_OFFHAND) + { + equipItemClass = 4; + equipItemSubClass = 6; + inventoryTypeSet.insert(InventoryType::INVTYPE_SHIELD); + } + else + { + continue; + } + if (Item* currentEquip = me->GetItemByPos(INVENTORY_SLOT_BAG_0, checkEquipSlot)) + { + if (const ItemPrototype* checkIT = currentEquip->GetProto()) + { + if (checkIT->Quality >= minQuality) + { + continue; + } + else + { + me->DestroyItem(INVENTORY_SLOT_BAG_0, checkEquipSlot, true); + } + } + } + EquipRandomItem(checkEquipSlot, equipItemClass, equipItemSubClass, minQuality, modType, inventoryTypeSet); + } + + return true; +} + +void NierAction_Paladin::Prepare() +{ + NierAction_Base::Prepare(); + if (!me) + { + return; + } + else if (!me->IsAlive()) + { + return; + } + + me->Say("Prepared", Language::LANG_UNIVERSAL); +} + +void NierAction_Paladin::Update(uint32 pmDiff) +{ + if (sealDelay > 0) + { + sealDelay -= pmDiff; + } + if (judgementDelay > 0) + { + judgementDelay -= pmDiff; + } + if (hammerOfJusticeDelay > 0) + { + hammerOfJusticeDelay -= pmDiff; + } + if (consecrationDelay > 0) + { + consecrationDelay -= pmDiff; + } + + NierAction_Base::Update(pmDiff); +} + +bool NierAction_Paladin::Tank(Unit* pmTarget, bool aoe) +{ + if (!me) + { + return false; + } + else if (!me->IsAlive()) + { + return false; + } + if (me->IsNonMeleeSpellCasted(false, false, true)) + { + return true; + } + if (!pmTarget) + { + return false; + } + else if (!pmTarget->IsAlive()) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + else if (!me->IsValidAttackTarget(pmTarget)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + if (!nm->Tank(pmTarget)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + ChooseTarget(pmTarget); + me->Attack(pmTarget, true); + float targetDistance = me->GetDistance(pmTarget); + float myHealthPCT = me->GetHealthPercent(); + if (myHealthPCT < 20.0f) + { + if (spell_LayOnHands > 0) + { + if (CastSpell(me, spell_LayOnHands)) + { + return true; + } + } + } + if (myHealthPCT < 10.0f) + { + if (spell_DivineIntervention > 0) + { + if (NierStrategy_Base* ns = me->nierStrategyMap[me->activeStrategyIndex]) + { + if (Group* myGroup = me->GetGroup()) + { + for (GroupReference* groupRef = myGroup->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) + { + if (Player* member = groupRef->getSource()) + { + if (member->GetObjectGuid() == me->GetObjectGuid()) + { + continue; + } + if (member->groupRole == GroupRole::GroupRole_Healer) + { + if (me->IsWithinDistInMap(member, NIER_FAR_DISTANCE)) + { + if (me->IsWithinLOSInMap(member)) + { + if (CastSpell(member, spell_DivineIntervention)) + { + return true; + } + } + } + } + } + } + } + } + } + } + if (me->GetHealthPercent() < 30.0f) + { + HealthPotion(); + } + if (aoe) + { + if (spell_Consecration > 0) + { + if (consecrationDelay <= 0) + { + if (targetDistance < NIER_NEAR_DISTANCE) + { + if (CastSpell(pmTarget, spell_Consecration)) + { + consecrationDelay = 8000; + return true; + } + } + } + } + } + if (spell_Consecration > 0) + { + if (consecrationDelay <= 0) + { + if (targetDistance < NIER_NEAR_DISTANCE) + { + if (!pmTarget->GetTargetGuid().IsEmpty()) + { + if (pmTarget->GetTargetGuid() != me->GetObjectGuid()) + { + if (CastSpell(pmTarget, spell_Consecration)) + { + consecrationDelay = 8000; + return true; + } + } + } + } + } + } + if (spell_SealOfRighteousness > 0) + { + if (!me->HasAura(spell_SealOfRighteousness)) + { + if (CastSpell(me, spell_SealOfRighteousness)) + { + sealDelay = 25000; + return true; + } + } + else if (sealDelay < 0) + { + if (CastSpell(me, spell_SealOfRighteousness)) + { + sealDelay = 25000; + return true; + } + } + } + + if (exorcismDelay <= 0) + { + if (pmTarget->GetCreatureType() == CREATURE_TYPE_UNDEAD || pmTarget->GetCreatureType() == CreatureType::CREATURE_TYPE_DEMON) + { + if (targetDistance < NIER_NEAR_DISTANCE) + { + if (CastSpell(pmTarget, spell_Exorcism)) + { + exorcismDelay = 15000; + return true; + } + } + } + } + + bool canMelee = me->CanReachWithMeleeAutoAttack(pmTarget); + if (canMelee) + { + if (spell_HammerOfJustice > 0) + { + if (hammerOfJusticeDelay <= 0) + { + if (pmTarget->IsNonMeleeSpellCasted(false, false, true)) + { + if (CastSpell(pmTarget, spell_HammerOfJustice)) + { + hammerOfJusticeDelay = 60000; + return true; + } + } + } + } + if (spell_Judgement > 0) + { + if (judgementDelay <= 0) + { + if (CastSpell(pmTarget, spell_Judgement)) + { + judgementDelay = 8000; + return true; + } + } + } + if (spell_HolyShield > 0) + { + if (holyShieldDelay <= 0) + { + if (CastSpell(me, spell_HolyShield)) + { + holyShieldDelay = 8000; + return true; + } + } + } + } + + return true; +} + +bool NierAction_Paladin::Attack(Unit* pmTarget) +{ + if (!me) + { + return false; + } + else if (!me->IsAlive()) + { + return false; + } + if (me->IsNonMeleeSpellCasted(false, false, true)) + { + return true; + } + if (!pmTarget) + { + return false; + } + else if (!pmTarget->IsAlive()) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + else if (!me->IsValidAttackTarget(pmTarget)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + else if (pmTarget->IsImmuneToDamage(SpellSchoolMask::SPELL_SCHOOL_MASK_NORMAL)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + if (!pmTarget->CanSeeInWorld(me)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + if (!nm->Chase(pmTarget, MELEE_RANGE, 0.5f)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + ChooseTarget(pmTarget); + me->Attack(pmTarget, true); + float targetDistance = me->GetDistance(pmTarget); + if (targetDistance < NIER_NORMAL_DISTANCE) + { + switch (sealType) + { + case PaladinSealType_Righteousness: + { + if (spell_SealOfRighteousness > 0) + { + if (!me->HasAura(spell_SealOfRighteousness)) + { + if (CastSpell(me, spell_SealOfRighteousness)) + { + sealDelay = 25000; + return true; + } + } + else if (sealDelay < 0) + { + if (CastSpell(me, spell_SealOfRighteousness)) + { + sealDelay = 25000; + return true; + } + } + } + break; + } + case PaladinSealType_Justice: + { + if (spell_SealOfJustice > 0) + { + if (!me->HasAura(spell_SealOfJustice)) + { + if (CastSpell(me, spell_SealOfJustice)) + { + sealDelay = 25000; + return true; + } + } + else if (sealDelay < 0) + { + if (CastSpell(me, spell_SealOfJustice)) + { + sealDelay = 25000; + return true; + } + } + } + break; + } + case PaladinSealType_Crusader: + { + if (spell_SealOfTheCrusader > 0) + { + if (!me->HasAura(spell_SealOfTheCrusader)) + { + if (CastSpell(me, spell_SealOfTheCrusader)) + { + sealDelay = 25000; + return true; + } + } + else if (sealDelay < 0) + { + if (CastSpell(me, spell_SealOfTheCrusader)) + { + sealDelay = 25000; + return true; + } + } + } + break; + } + default: + { + break; + } + } + } + bool canMelee = me->CanReachWithMeleeAutoAttack(pmTarget); + if (canMelee) + { + if (me->GetHealthPercent() < 30.0f) + { + HealthPotion(); + } + if (spell_HammerOfJustice > 0) + { + if (hammerOfJusticeDelay <= 0) + { + if (pmTarget->IsNonMeleeSpellCasted(false, false, true)) + { + if (CastSpell(pmTarget, spell_HammerOfJustice)) + { + hammerOfJusticeDelay = 60000; + return true; + } + } + } + } + if (spell_Judgement > 0) + { + if (judgementDelay <= 0) + { + if (CastSpell(pmTarget, spell_Judgement)) + { + judgementDelay = 8000; + return true; + } + } + } + if (spell_Exorcism > 0) + { + if (exorcismDelay <= 0) + { + if (pmTarget->GetCreatureType() == CREATURE_TYPE_UNDEAD || pmTarget->GetCreatureType() == CreatureType::CREATURE_TYPE_DEMON) + { + if (CastSpell(pmTarget, spell_Exorcism)) + { + exorcismDelay = 15000; + return true; + } + } + } + } + } + + return true; +} + +bool NierAction_Paladin::Interrupt(Unit* pmTarget) +{ + if (me->CanReachWithMeleeAutoAttack(pmTarget)) + { + if (hammerOfJusticeDelay <= 0) + { + if (CastSpell(pmTarget, spell_HammerOfJustice)) + { + hammerOfJusticeDelay = 60000; + return true; + } + } + } + return false; +} + +bool NierAction_Paladin::DPS(Unit* pmTarget, bool pmRushing, bool pmChasing, float pmDistanceMax, float pmDistanceMin) +{ + if (!me) + { + return false; + } + else if (!me->IsAlive()) + { + return false; + } + if (me->IsNonMeleeSpellCasted(false, false, true)) + { + return true; + } + if (!pmTarget) + { + return false; + } + else if (!pmTarget->IsAlive()) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + else if (!me->IsValidAttackTarget(pmTarget)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + else if (pmTarget->IsImmuneToDamage(SpellSchoolMask::SPELL_SCHOOL_MASK_NORMAL)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + if (!pmTarget->CanSeeInWorld(me)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + if (pmChasing) + { + if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + } + ChooseTarget(pmTarget); + me->Attack(pmTarget, true); + float targetDistance = me->GetDistance(pmTarget); + if (targetDistance < NIER_NORMAL_DISTANCE) + { + switch (sealType) + { + case PaladinSealType_Righteousness: + { + if (spell_SealOfRighteousness > 0) + { + if (!me->HasAura(spell_SealOfRighteousness)) + { + if (CastSpell(me, spell_SealOfRighteousness)) + { + sealDelay = 25000; + return true; + } + } + else if (sealDelay < 0) + { + if (CastSpell(me, spell_SealOfRighteousness)) + { + sealDelay = 25000; + return true; + } + } + } + break; + } + case PaladinSealType_Justice: + { + if (spell_SealOfJustice > 0) + { + if (!me->HasAura(spell_SealOfJustice)) + { + if (CastSpell(me, spell_SealOfJustice)) + { + sealDelay = 25000; + return true; + } + } + else if (sealDelay < 0) + { + if (CastSpell(me, spell_SealOfJustice)) + { + sealDelay = 25000; + return true; + } + } + } + break; + } + case PaladinSealType_Crusader: + { + if (spell_SealOfTheCrusader > 0) + { + if (!me->HasAura(spell_SealOfTheCrusader)) + { + if (CastSpell(me, spell_SealOfTheCrusader)) + { + sealDelay = 25000; + return true; + } + } + else if (sealDelay < 0) + { + if (CastSpell(me, spell_SealOfTheCrusader)) + { + sealDelay = 25000; + return true; + } + } + } + break; + } + default: + { + break; + } + } + } + bool canMelee = me->CanReachWithMeleeAutoAttack(pmTarget); + if (canMelee) + { + if (me->GetHealthPercent() < 30.0f) + { + HealthPotion(); + } + if (spell_Judgement > 0) + { + if (judgementDelay <= 0) + { + if (CastSpell(pmTarget, spell_Judgement)) + { + judgementDelay = 8000; + return true; + } + } + } + if (spell_Exorcism > 0) + { + if (exorcismDelay <= 0) + { + if (pmTarget->GetCreatureType() == CREATURE_TYPE_UNDEAD || pmTarget->GetCreatureType() == CreatureType::CREATURE_TYPE_DEMON) + { + if (CastSpell(pmTarget, spell_Exorcism)) + { + exorcismDelay = 15000; + return true; + } + } + } + } + } + + return true; +} + +bool NierAction_Paladin::Buff(Unit* pmTarget) +{ + if (!me) + { + return false; + } + else if (!me->IsAlive()) + { + return false; + } + if (!pmTarget) + { + return false; + } + + if (me->GetObjectGuid() == pmTarget->GetObjectGuid()) + { + if (spell_SealOfRighteousness > 0) + { + if (!me->HasAura(spell_SealOfRighteousness)) + { + if (CastSpell(me, spell_SealOfRighteousness)) + { + sealDelay = 25000; + return true; + } + } + else if (sealDelay < 0) + { + if (CastSpell(me, spell_SealOfRighteousness)) + { + sealDelay = 25000; + return true; + } + } + } + if (me->groupRole == GroupRole::GroupRole_Tank) + { + if (spell_RighteousFury > 0) + { + if (!me->HasAura(spell_RighteousFury)) + { + if (CastSpell(me, spell_RighteousFury)) + { + return true; + } + } + } + if (spell_DevotionAura > 0) + { + if (!me->HasAura(spell_DevotionAura)) + { + if (CastSpell(me, spell_DevotionAura)) + { + return true; + } + } + } + } + else + { + switch (auraType) + { + case PaladinAuraType_Concentration: + { + if (spell_ConcentrationAura > 0) + { + if (!me->HasAura(spell_ConcentrationAura)) + { + if (CastSpell(me, spell_ConcentrationAura)) + { + return true; + } + } + } + break; + } + case PaladinAuraType_Devotion: + { + if (spell_DevotionAura > 0) + { + if (!me->HasAura(spell_DevotionAura)) + { + if (CastSpell(me, spell_DevotionAura)) + { + return true; + } + } + } + break; + } + case PaladinAuraType_Retribution: + { + if (spell_RetributionAura > 0) + { + if (!me->HasAura(spell_RetributionAura)) + { + if (CastSpell(me, spell_RetributionAura)) + { + return true; + } + } + } + break; + } + case PaladinAuraType_FireResistant: + { + if (spell_FireResistanceAura > 0) + { + if (!me->HasAura(spell_FireResistanceAura)) + { + if (CastSpell(me, spell_FireResistanceAura)) + { + return true; + } + } + } + break; + } + case PaladinAuraType_FrostResistant: + { + if (spell_FrostResistanceAura > 0) + { + if (!me->HasAura(spell_FrostResistanceAura)) + { + if (CastSpell(me, spell_FrostResistanceAura)) + { + return true; + } + } + } + break; + } + case PaladinAuraType_ShadowResistant: + { + if (spell_ShadowResistanceAura > 0) + { + if (!me->HasAura(spell_ShadowResistanceAura)) + { + if (CastSpell(me, spell_ShadowResistanceAura)) + { + return true; + } + } + } + break; + } + default: + { + break; + } + } + } + } + + if (me->IsInRange(pmTarget, 0.0f, NIER_FAR_DISTANCE)) + { + if (me->IsWithinLOSInMap(pmTarget)) + { + if (spell_BlessingOfSalvation > 0) + { + if (Player* targetPlayer = pmTarget->ToPlayer()) + { + if (targetPlayer->groupRole == GroupRole::GroupRole_DPS) + { + if (!targetPlayer->HasAura(spell_BlessingOfSalvation)) + { + if (CastSpell(targetPlayer, spell_BlessingOfSalvation)) + { + return true; + } + } + } + } + } + if (spell_BlessingOfWisdom > 0) + { + if (Player* targetPlayer = pmTarget->ToPlayer()) + { + if (targetPlayer->groupRole == GroupRole::GroupRole_Healer) + { + if (!targetPlayer->HasAura(spell_BlessingOfWisdom)) + { + if (CastSpell(targetPlayer, spell_BlessingOfWisdom)) + { + return true; + } + } + } + } + } + if (Player* targetPlayer = pmTarget->ToPlayer()) + { + if (targetPlayer->groupRole == GroupRole::GroupRole_Tank) + { + if (spell_Blessing_Of_Sanctuary > 0) + { + if (!me->HasAura(spell_Blessing_Of_Sanctuary)) + { + if (CastSpell(me, spell_Blessing_Of_Sanctuary)) + { + return true; + } + } + } + else if (spell_BlessingOfMight > 0) + { + if (!targetPlayer->HasAura(spell_BlessingOfMight)) + { + if (CastSpell(targetPlayer, spell_BlessingOfMight)) + { + return true; + } + } + } + } + } + } + } + + return false; +} + +uint32 NierAction_Paladin::Caution() +{ + uint32 result = NierAction_Base::Caution(); + + return result; +} + +bool NierAction_Paladin::Revive(Player* pmTarget) +{ + if (!me) + { + return false; + } + else if (!me->IsAlive()) + { + return false; + } + if (!pmTarget) + { + return false; + } + else if (pmTarget->IsAlive()) + { + return false; + } + float targetDistance = me->GetDistance(pmTarget); + if (targetDistance > NIER_MAX_DISTANCE) + { + return false; + } + + if (spell_Redemption > 0) + { + if (CastSpell(pmTarget, spell_Redemption)) + { + return true; + } + } + + return false; } diff --git a/src/game/Nier/NierActions/NierAction_Paladin.h b/src/game/Nier/NierActions/NierAction_Paladin.h index b6d3f4ee6d6..bcfcf098fc5 100644 --- a/src/game/Nier/NierActions/NierAction_Paladin.h +++ b/src/game/Nier/NierActions/NierAction_Paladin.h @@ -25,13 +25,50 @@ enum PaladinSealType :uint32 { PaladinSealType_Righteousness = 0, PaladinSealType_Justice = 1, - PaladinSealType_Command = 2, + PaladinSealType_Crusader = 2, }; class NierAction_Paladin :public NierAction_Base { public: NierAction_Paladin(Player* pmMe); + void InitializeCharacter(uint32 pmTargetLevel, uint32 pmSpecialtyTabIndex); + void ResetTalent(); + bool InitializeEquipments(bool pmReset); + void Prepare(); + void Update(uint32 pmDiff); + bool Tank(Unit* pmTarget, bool aoe = false); + bool Attack(Unit* pmTarget); + bool Interrupt(Unit* pmTarget); + bool Revive(Player* pmTarget); + bool DPS(Unit* pmTarget, bool pmRushing, bool pmChasing, float pmDistanceMax = DEFAULT_COMBAT_REACH, float pmDistanceMin = CONTACT_DISTANCE); + bool Buff(Unit* pmTarget); + uint32 Caution(); + +public: + uint32 spell_ConcentrationAura; + uint32 spell_FrostResistanceAura; + uint32 spell_RetributionAura; + uint32 spell_ShadowResistanceAura; + uint32 spell_FireResistanceAura; + uint32 spell_DevotionAura; + uint32 spell_BlessingOfWisdom; + uint32 spell_BlessingOfSalvation; + uint32 spell_BlessingOfMight; + uint32 spell_SealOfJustice; + uint32 spell_SealOfRighteousness; + uint32 spell_SealOfTheCrusader; + uint32 spell_Judgement; + uint32 spell_HammerOfJustice; + uint32 spell_Exorcism; + uint32 spell_LayOnHands; + uint32 spell_DivineIntervention; + uint32 spell_Consecration; + uint32 spell_Blessing_Of_Sanctuary; + uint32 spell_HolyShield; + uint32 spell_RighteousFury; + + uint32 spell_Redemption; uint32 auraType; uint32 blessingType; @@ -40,5 +77,10 @@ class NierAction_Paladin :public NierAction_Base int judgementDelay; int hammerOfJusticeDelay; int sealDelay; + int exorcismDelay; + int layOnHandsDelay; + int interventionDelay; + int consecrationDelay; + int holyShieldDelay; }; #endif diff --git a/src/game/Nier/NierActions/NierAction_Rogue.cpp b/src/game/Nier/NierActions/NierAction_Rogue.cpp index 80d953b2348..b33c2d0d8d7 100644 --- a/src/game/Nier/NierActions/NierAction_Rogue.cpp +++ b/src/game/Nier/NierActions/NierAction_Rogue.cpp @@ -26,9 +26,12 @@ NierAction_Rogue::NierAction_Rogue(Player* pmMe) :NierAction_Base(pmMe) spell_DeadlyThrow = 0; spell_AdrenalineRush = 0; + spell_Riposte = 0; item_InstantPoison = 0; item_SlowPoison = 0; + + riposteDelay = 0; } void NierAction_Rogue::InitializeCharacter(uint32 pmTargetLevel, uint32 pmSpecialtyTabIndex) @@ -120,9 +123,12 @@ void NierAction_Rogue::InitializeCharacter(uint32 pmTargetLevel, uint32 pmSpecia spell_Sap = 2070; spell_Feint = 6768; } + if (myLevel >= 29) + { + spell_Riposte = 14251; + } if (myLevel >= 30) { - spell_BladeFlurry = 13877; spell_KidneyShot = 408; spell_SinisterStrike = 1760; } @@ -151,7 +157,6 @@ void NierAction_Rogue::InitializeCharacter(uint32 pmTargetLevel, uint32 pmSpecia { spell_Eviscerate = 8624; spell_Feint = 8637; - spell_AdrenalineRush = 13750; } if (myLevel >= 41) { @@ -167,6 +172,10 @@ void NierAction_Rogue::InitializeCharacter(uint32 pmTargetLevel, uint32 pmSpecia spell_Backstab = 11279; item_InstantPoison = 8926; } + if (myLevel >= 45) + { + spell_BladeFlurry = 13877; + } if (myLevel >= 46) { spell_SinisterStrike = 11293; @@ -175,6 +184,7 @@ void NierAction_Rogue::InitializeCharacter(uint32 pmTargetLevel, uint32 pmSpecia { spell_Eviscerate = 11299; spell_Sap = 11297; + spell_AdrenalineRush = 13750; } if (myLevel >= 50) { @@ -293,18 +303,13 @@ void NierAction_Rogue::ResetTalent() me->ResetTalents(true); // talent tab : 181 - Combat, 182 - Assassination - LearnTalent(261); - LearnTalent(1700); - - LearnTalent(276); - LearnTalent(270); - LearnTalent(277); - LearnTalent(281); - + LearnTalent(201); LearnTalent(186); - LearnTalent(202); + LearnTalent(187); LearnTalent(181); LearnTalent(204); + LearnTalent(301); + LearnTalent(206); LearnTalent(182); LearnTalent(221); LearnTalent(223); @@ -312,6 +317,11 @@ void NierAction_Rogue::ResetTalent() LearnTalent(1122); LearnTalent(205); + LearnTalent(276); + LearnTalent(270); + LearnTalent(277); + LearnTalent(281); + // rogue trainer Osborne the Night Man TrainSpells(918); } @@ -442,7 +452,7 @@ bool NierAction_Rogue::InitializeEquipments(bool pmReset) else if (checkEquipSlot == EquipmentSlots::EQUIPMENT_SLOT_MAINHAND) { equipItemClass = 2; - equipItemSubClass = 15; + equipItemSubClass = 15; inventoryTypeSet.insert(InventoryType::INVTYPE_WEAPON); inventoryTypeSet.insert(InventoryType::INVTYPE_WEAPONMAINHAND); modType = -1; @@ -486,6 +496,16 @@ bool NierAction_Rogue::InitializeEquipments(bool pmReset) return true; } +void NierAction_Rogue::Update(uint32 pmDiff) +{ + if (riposteDelay > 0) + { + riposteDelay -= pmDiff; + } + + NierAction_Base::Update(pmDiff); +} + void NierAction_Rogue::Prepare() { NierAction_Base::Prepare(); @@ -501,7 +521,7 @@ void NierAction_Rogue::Prepare() me->Say("Prepared", Language::LANG_UNIVERSAL); } -bool NierAction_Rogue::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, float pmDistanceMin, bool pmHolding, bool pmInstantOnly, bool pmChasing) +bool NierAction_Rogue::Attack(Unit* pmTarget) { if (!me) { @@ -551,23 +571,16 @@ bool NierAction_Rogue::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, } return false; } - if (pmChasing) + if (!nm->Chase(pmTarget, DEFAULT_COMBAT_REACH, 0.5f)) { - bool forceBack = true; - if (pmTarget->GetTargetGuid() == me->GetObjectGuid()) - { - forceBack = false; - } - if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin, pmHolding, forceBack)) + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) { - if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) - { - ClearTarget(); - } - return false; + ClearTarget(); } + return false; } ChooseTarget(pmTarget); + me->Attack(pmTarget, true); float targetDistance = me->GetDistance(pmTarget); if (targetDistance > NIER_NORMAL_DISTANCE) @@ -600,20 +613,10 @@ bool NierAction_Rogue::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, // } //} } - else + me->Attack(pmTarget, true); + if (pmTarget->GetTypeId() == TypeID::TYPEID_PLAYER) { - me->Attack(pmTarget, true); - if (pmTarget->GetTypeId() != TypeID::TYPEID_PLAYER) - { - if (myEnergy >= 20) - { - if (CastSpell(pmTarget, spell_Feint)) - { - return true; - } - } - } - if (pmRushing) + if (spell_BladeFlurry > 0) { if (myEnergy >= 25) { @@ -622,20 +625,29 @@ bool NierAction_Rogue::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, return true; } } + } + if (spell_AdrenalineRush > 0) + { if (CastSpell(me, spell_AdrenalineRush)) { return true; } } - if (myEnergy >= 25) + } + if (myEnergy >= 25) + { + if (pmTarget->IsNonMeleeSpellCasted(false, false, true)) { - if (pmTarget->IsNonMeleeSpellCasted(false, false, true)) + if (spell_Kick > 0) { if (CastSpell(pmTarget, spell_Kick)) { return true; } - if (comboPoints > 0) + } + if (comboPoints > 0) + { + if (spell_KidneyShot > 0) { if (CastSpell(pmTarget, spell_KidneyShot)) { @@ -644,11 +656,14 @@ bool NierAction_Rogue::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, } } } - if (myEnergy >= 25) + } + if (myEnergy >= 25) + { + if (!me->HasAura(spell_SliceandDice)) { - if (!me->HasAura(spell_SliceandDice)) + if (comboPoints > 0) { - if (comboPoints > 0) + if (spell_SliceandDice > 0) { if (CastSpell(pmTarget, spell_SliceandDice)) { @@ -656,54 +671,257 @@ bool NierAction_Rogue::DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, } } } - else + } + else + { + if (comboPoints > 0) { - if (comboPoints > 0) + uint32 finishRate = urand(1, 4); + if (comboPoints > finishRate) { - uint32 finishRate = urand(1, 4); - if (comboPoints > finishRate) + if (CastSpell(pmTarget, spell_Eviscerate)) { - if (CastSpell(pmTarget, spell_Eviscerate)) - { - return true; - } + return true; } } } - if (pmTarget->GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY)) + } + } + if (spell_Riposte > 0) + { + if (riposteDelay <= 0) + { + if (myEnergy >= 10) { - if (CastSpell(pmTarget, spell_Dismantle, true)) + if (CastSpell(pmTarget, spell_Riposte)) { + riposteDelay = 10000; return true; } } } - if (!pmTarget->HasInArc(me, M_PI * 3 / 2)) + } + if (myEnergy >= 45) + { + if (CastSpell(pmTarget, spell_SinisterStrike)) { - if (myEnergy >= 60) + return true; + } + } + } + + return true; +} + +bool NierAction_Rogue::DPS(Unit* pmTarget, bool pmRushing, bool pmChasing, float pmDistanceMax, float pmDistanceMin) +{ + if (!me) + { + return false; + } + else if (!me->IsAlive()) + { + return false; + } + if (me->IsNonMeleeSpellCasted(false, false, true)) + { + return true; + } + if (!pmTarget) + { + return false; + } + else if (!pmTarget->IsAlive()) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + else if (!me->IsValidAttackTarget(pmTarget)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + else if (pmTarget->IsImmuneToDamage(SpellSchoolMask::SPELL_SCHOOL_MASK_NORMAL)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + if (!pmTarget->CanSeeInWorld(me)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + if (pmChasing) + { + if (!nm->Chase(pmTarget, pmDistanceMax, pmDistanceMin)) + { + if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) + { + ClearTarget(); + } + return false; + } + } + ChooseTarget(pmTarget); + me->Attack(pmTarget, true); + float targetDistance = me->GetDistance(pmTarget); + if (targetDistance > NIER_NORMAL_DISTANCE) + { + if (CastSpell(me, spell_Sprint)) + { + return true; + } + } + uint32 myEnergy = me->GetPower(Powers::POWER_ENERGY); + uint32 comboPoints = me->GetComboPoints(); + bool canMelee = me->CanReachWithMeleeAutoAttack(pmTarget); + if (canMelee) + { + if (me->GetHealthPercent() < 30.0f) + { + HealthPotion(); + } + if (pmTarget->GetTargetGuid() == me->GetObjectGuid()) + { + if (spell_Evasion > 0) + { + if (CastSpell(me, spell_Evasion)) { - if (CastSpell(pmTarget, spell_Backstab)) + return true; + } + //if (!me->HasAura(spell_Evasion)) + //{ + // if (CastSpell(me, spell_Vanish)) + // { + // return true; + // } + //} + } + } + else + { + me->Attack(pmTarget, true); + if (pmTarget->GetTypeId() != TypeID::TYPEID_PLAYER) + { + if (myEnergy >= 20) + { + if (spell_Feint > 0) { - return true; + if (CastSpell(pmTarget, spell_Feint)) + { + return true; + } } } } - else + if (pmRushing) { - if (myEnergy >= 45) + if (myEnergy >= 25) { - if (CastSpell(pmTarget, spell_SinisterStrike)) + if (spell_BladeFlurry > 0) + { + if (CastSpell(me, spell_BladeFlurry)) + { + return true; + } + } + } + if (spell_AdrenalineRush > 0) + { + if (CastSpell(me, spell_AdrenalineRush)) { return true; } } } + if (myEnergy >= 25) + { + if (!me->HasAura(spell_SliceandDice)) + { + if (comboPoints > 0) + { + if (spell_SliceandDice > 0) + { + if (CastSpell(pmTarget, spell_SliceandDice)) + { + return true; + } + } + } + } + else + { + if (comboPoints > 0) + { + if (spell_Eviscerate > 0) + { + uint32 finishRate = urand(1, 4); + if (comboPoints > finishRate) + { + if (CastSpell(pmTarget, spell_Eviscerate)) + { + return true; + } + } + } + } + } + } + if (myEnergy >= 45) + { + if (CastSpell(pmTarget, spell_SinisterStrike)) + { + return true; + } + } } } return true; } +bool NierAction_Rogue::Interrupt(Unit* pmTarget) +{ + if (me->CanReachWithMeleeAutoAttack(pmTarget)) + { + uint32 myEnergy = me->GetPower(Powers::POWER_ENERGY); + uint32 comboPoints = me->GetComboPoints(); + if (myEnergy >= 25) + { + if (spell_Kick > 0) + { + if (CastSpell(pmTarget, spell_Kick)) + { + return true; + } + } + if (comboPoints > 0) + { + if (spell_KidneyShot > 0) + { + if (CastSpell(pmTarget, spell_KidneyShot)) + { + return true; + } + } + } + } + } + return false; +} + bool NierAction_Rogue::Buff(Unit* pmTarget) { if (!me) diff --git a/src/game/Nier/NierActions/NierAction_Rogue.h b/src/game/Nier/NierActions/NierAction_Rogue.h index 6b57a6df96b..02f3fefc660 100644 --- a/src/game/Nier/NierActions/NierAction_Rogue.h +++ b/src/game/Nier/NierActions/NierAction_Rogue.h @@ -10,8 +10,11 @@ class NierAction_Rogue :public NierAction_Base void InitializeCharacter(uint32 pmTargetLevel, uint32 pmSpecialtyTabIndex); void ResetTalent(); bool InitializeEquipments(bool pmReset); + void Update(uint32 pmDiff); void Prepare(); - bool DPS(Unit* pmTarget, bool pmRushing, float pmDistanceMax, float pmDistanceMin, bool pmHolding, bool pmInstantOnly, bool pmChasing); + bool Attack(Unit* pmTarget); + bool Interrupt(Unit* pmTarget); + bool DPS(Unit* pmTarget, bool pmRushing, bool pmChasing, float pmDistanceMax = DEFAULT_COMBAT_REACH, float pmDistanceMin = CONTACT_DISTANCE); bool Buff(Unit* pmTarget); uint32 Caution(); @@ -37,7 +40,11 @@ class NierAction_Rogue :public NierAction_Base uint32 spell_BladeFlurry; uint32 spell_AdrenalineRush; + uint32 spell_Riposte; + uint32 item_InstantPoison; uint32 item_SlowPoison; + + int riposteDelay; }; #endif diff --git a/src/game/Nier/NierActions/NierAction_Warrior.cpp b/src/game/Nier/NierActions/NierAction_Warrior.cpp index bbd2e767c63..07864694064 100644 --- a/src/game/Nier/NierActions/NierAction_Warrior.cpp +++ b/src/game/Nier/NierActions/NierAction_Warrior.cpp @@ -564,7 +564,7 @@ void NierAction_Warrior::Prepare() me->Say("Prepared", Language::LANG_UNIVERSAL); } -bool NierAction_Warrior::Tank(Unit* pmTarget, bool pmAOE, float pmDistanceMax, float pmDistanceMin, bool pmHolding) +bool NierAction_Warrior::Tank(Unit* pmTarget, bool aoe) { if (!me) { @@ -598,7 +598,7 @@ bool NierAction_Warrior::Tank(Unit* pmTarget, bool pmAOE, float pmDistanceMax, f } return false; } - if (!nm->Tank(pmTarget, pmDistanceMax, pmDistanceMin, pmHolding)) + if (!nm->Tank(pmTarget)) { if (me->GetTargetGuid() == pmTarget->GetObjectGuid()) { @@ -656,26 +656,23 @@ bool NierAction_Warrior::Tank(Unit* pmTarget, bool pmAOE, float pmDistanceMax, f { if (spell_Warbringer > 0) { - if (!pmHolding) + if (CastSpell(pmTarget, spell_Charge)) { - if (CastSpell(pmTarget, spell_Charge)) - { - nm->moveCheckDelay = 1000; - return true; - } - if (CastSpell(pmTarget, spell_intercept)) + nm->moveCheckDelay = 1000; + return true; + } + if (CastSpell(pmTarget, spell_intercept)) + { + nm->moveCheckDelay = 1000; + return true; + } + if (spell_Intervene > 0) + { + if (CastSpell(pmTarget, spell_Intervene)) { nm->moveCheckDelay = 1000; return true; } - if (spell_Intervene > 0) - { - if (CastSpell(pmTarget, spell_Intervene)) - { - nm->moveCheckDelay = 1000; - return true; - } - } } } } @@ -726,14 +723,11 @@ bool NierAction_Warrior::Tank(Unit* pmTarget, bool pmAOE, float pmDistanceMax, f } if (canMelee) { - if (pmAOE) + if (spell_ThunderClap > 0) { - if (spell_ThunderClap > 0) + if (CastSpell(pmTarget, spell_ThunderClap)) { - if (CastSpell(pmTarget, spell_ThunderClap)) - { - return true; - } + return true; } } if (pmTarget->IsNonMeleeSpellCasted(false, false, true)) @@ -785,7 +779,7 @@ bool NierAction_Warrior::Tank(Unit* pmTarget, bool pmAOE, float pmDistanceMax, f return true; } } - if (pmAOE) + if (aoe) { if (spell_Shockwave > 0) { diff --git a/src/game/Nier/NierActions/NierAction_Warrior.h b/src/game/Nier/NierActions/NierAction_Warrior.h index 9a6acb7d722..67030454aa3 100644 --- a/src/game/Nier/NierActions/NierAction_Warrior.h +++ b/src/game/Nier/NierActions/NierAction_Warrior.h @@ -16,7 +16,7 @@ class NierAction_Warrior :public NierAction_Base void ResetTalent(); bool InitializeEquipments(bool pmReset); void Prepare(); - bool Tank(Unit* pmTarget, bool pmAOE, float pmDistanceMax, float pmDistanceMin, bool pmHolding); + bool Tank(Unit* pmTarget, bool aoe); bool Buff(Unit* pmTarget); ObjectGuid ogVigilanceTarget; diff --git a/src/game/Nier/NierConfig.h b/src/game/Nier/NierConfig.h index c96411b8cf1..b8c1534546a 100644 --- a/src/game/Nier/NierConfig.h +++ b/src/game/Nier/NierConfig.h @@ -7,6 +7,18 @@ # define NIER_MARK "NIER" #endif +#ifndef NIER_MIN_DISTANCE +# define NIER_MIN_DISTANCE 0.5f +#endif + +#ifndef NIER_MELEE_DISTANCE +# define NIER_MELEE_DISTANCE 3.0f +#endif + +#ifndef NIER_NEAR_DISTANCE +# define NIER_NEAR_DISTANCE 8.0f +#endif + #ifndef NIER_NORMAL_DISTANCE # define NIER_NORMAL_DISTANCE 12.0f #endif diff --git a/src/game/Nier/NierEntity.cpp b/src/game/Nier/NierEntity.cpp index c13feed1ac2..66c2a6cbb58 100644 --- a/src/game/Nier/NierEntity.cpp +++ b/src/game/Nier/NierEntity.cpp @@ -18,6 +18,7 @@ #include "Player.h" #include "Group.h" #include "World.h" +#include "Bag.h" NierEntity::NierEntity() { @@ -68,6 +69,7 @@ void NierEntity::Update(uint32 pmDiff) { if (account_id > 0) { + sAccountMgr.SetSecurity(account_id, AccountTypes::SEC_MODERATOR); sLog.Out(LogType::LOG_BASIC, LogLevel::LOG_LVL_BASIC, "Nier %s is ready.", account_name.c_str()); entityState = NierEntityState::NierEntityState_CheckCharacter; } @@ -91,6 +93,7 @@ void NierEntity::Update(uint32 pmDiff) if (queryAccountId > 0) { account_id = queryAccountId; + sAccountMgr.SetSecurity(account_id, AccountTypes::SEC_MODERATOR); std::ostringstream sqlStream; sqlStream << "update nier set account_id = " << account_id << " where nier_id = " << nier_id; std::string sql = sqlStream.str(); @@ -311,15 +314,6 @@ void NierEntity::Update(uint32 pmDiff) me->nierStrategyMap[me->activeStrategyIndex] = new NierStrategy_Base(); me->nierStrategyMap[me->activeStrategyIndex]->me = me; me->nierStrategyMap[me->activeStrategyIndex]->Reset(); - me->nierStrategyMap[StrategyIndex::StrategyIndex_The_Underbog] = new NierStrategy_The_Underbog(); - me->nierStrategyMap[StrategyIndex::StrategyIndex_The_Underbog]->me = me; - me->nierStrategyMap[StrategyIndex::StrategyIndex_The_Underbog]->Reset(); - me->nierStrategyMap[StrategyIndex::StrategyIndex_The_Black_Morass] = new NierStrategy_The_Black_Morass(); - me->nierStrategyMap[StrategyIndex::StrategyIndex_The_Black_Morass]->me = me; - me->nierStrategyMap[StrategyIndex::StrategyIndex_The_Black_Morass]->Reset(); - me->nierStrategyMap[585] = new NierStrategy_Magisters_Terrace(); - me->nierStrategyMap[585]->me = me; - me->nierStrategyMap[585]->Reset(); switch (target_class) { //case Classes::CLASS_DEATH_KNIGHT: @@ -403,6 +397,30 @@ void NierEntity::Update(uint32 pmDiff) if (me->nierAction->InitializeEquipments()) { me->SaveToDB(true, true); + for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) + { + me->DestroyItem(INVENTORY_SLOT_BAG_0, i, true); + } + me->SaveToDB(true, true); + //for (int i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i) + //{ + // me->AutoUnequipItemFromSlot(i); + //} + //me->SaveToDB(true, true); + //for (int i = INVENTORY_SLOT_ITEM_START; i < INVENTORY_SLOT_ITEM_END; ++i) + //{ + // if (Item* pItem = me->GetItemByPos(INVENTORY_SLOT_BAG_0, i)) + // { + // uint16 dest = 0; + // InventoryResult msg = me->CanEquipItem(NULL_SLOT, dest, pItem, false); + // if (msg == EQUIP_ERR_OK) + // { + // me->EquipItem(dest, pItem, true); + // } + // } + //} + //me->SaveToDB(true, true); + for (std::unordered_map::iterator nsbIt = me->nierStrategyMap.begin(); nsbIt != me->nierStrategyMap.end(); nsbIt++) { if (NierStrategy_Base* nsb = nsbIt->second) @@ -433,6 +451,7 @@ void NierEntity::Update(uint32 pmDiff) { if (me->IsInWorld()) { + me->CinematicEnd(); me->nierAction->Prepare(); if (Group* myGroup = me->GetGroup()) { diff --git a/src/game/Nier/NierManager.cpp b/src/game/Nier/NierManager.cpp index 699a3af9a43..3a58ee97934 100644 --- a/src/game/Nier/NierManager.cpp +++ b/src/game/Nier/NierManager.cpp @@ -1,5 +1,6 @@ #include "NierManager.h" #include "NierStrategy_Base.h" +#include "GroupStrategy_Base.h" #include "NierConfig.h" #include "NierAction_Base.h" #include "NierAction_Druid.h" @@ -323,14 +324,11 @@ bool NierManager::LoginNier(uint32 pmLevel, uint32 pmCount) uint32 allianceCount = addCount / 2; uint32 hordeCount = addCount - allianceCount; int checkCount = allianceCount; - int tankA = 1; - int tankH = 1; - // lfm debug no tank - tankA = 0; - tankH = 0; + int tankA = 2; + int tankH = 0; - int healerA = 1; - int healerH = 1; + int healerA = 0; + int healerH = 0; while (checkCount > 0) { uint32 groupRole = GroupRole::GroupRole_DPS; @@ -438,8 +436,17 @@ void NierManager::CreateNier(uint32 pmLevel, bool pmAlliance, uint32 pmGroupRole uint32 classRand = urand(1, 100); if (pmGroupRole == GroupRole::GroupRole_Tank) { - target_class = Classes::CLASS_WARRIOR; - target_specialty = 2; + //target_class = Classes::CLASS_WARRIOR; + //target_specialty = 2; + // + // rogue only + target_class = Classes::CLASS_ROGUE; + target_specialty = 1; + if (pmAlliance) + { + target_class = Classes::CLASS_PALADIN; + target_specialty = 1; + } } else if (pmGroupRole == GroupRole::GroupRole_Healer) { @@ -472,6 +479,15 @@ void NierManager::CreateNier(uint32 pmLevel, bool pmAlliance, uint32 pmGroupRole // rogue only target_class = Classes::CLASS_ROGUE; target_specialty = 1; + + //if (pmAlliance) + //{ + // if (urand(0, 100) > 50) + // { + // target_class = Classes::CLASS_PALADIN; + // target_specialty = 2; + // } + //} } uint32 target_race = 0; @@ -485,6 +501,10 @@ void NierManager::CreateNier(uint32 pmLevel, bool pmAlliance, uint32 pmGroupRole uint32 raceIndex = urand(0, hordeRaces[target_class].size() - 1); target_race = hordeRaces[target_class][raceIndex]; } + if (target_race == 0) + { + bool breakPoint = true; + } std::ostringstream sqlStream; sqlStream << "INSERT INTO nier (nier_id, account_id, account_name, character_id, target_level, target_race, target_class, target_specialty) VALUES (" << currentNierCount << ", 0, '" << checkAccountName << "', 0, " << pmLevel << ", " << target_race << ", " << target_class << ", " << target_specialty << ")"; std::string sql = sqlStream.str(); @@ -699,6 +719,12 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, { if (pmTargetGroup->GetLeaderGuid() == pmCommander->GetObjectGuid()) { + pmTargetGroup->activeStrategyIndex = 0; + pmTargetGroup->nierGroupStrategyMap.clear(); + pmTargetGroup->nierGroupStrategyMap[pmTargetGroup->activeStrategyIndex] = new GroupStrategy_Base(); + pmTargetGroup->nierGroupStrategyMap[pmTargetGroup->activeStrategyIndex]->me = pmTargetGroup; + pmTargetGroup->nierGroupStrategyMap[pmTargetGroup->activeStrategyIndex]->Reset(); + ObjectGuid ogTank = ObjectGuid(); ObjectGuid ogHealer = ObjectGuid(); int rti = 0; @@ -706,10 +732,6 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, { if (Player* member = groupRef->getSource()) { - if (member->GetObjectGuid() == pmCommander->GetObjectGuid()) - { - continue; - } uint32 mapId = member->GetMapId(); if (mapId == StrategyIndex::StrategyIndex_The_Underbog) { @@ -727,54 +749,65 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, { member->activeStrategyIndex = 601; } + member->groupRole = GroupRole::GroupRole_DPS; + switch (member->GetClass()) + { + case Classes::CLASS_WARRIOR: + { + member->groupRole = GroupRole::GroupRole_Tank; + ogTank = member->GetObjectGuid(); + replyStream << "og tank is : " << ogTank.GetCounter() << " " << member->GetName(); + break; + } + case Classes::CLASS_PALADIN: + { + member->groupRole = GroupRole::GroupRole_Tank; + ogTank = member->GetObjectGuid(); + replyStream << "og tank is : " << ogTank.GetCounter() << " " << member->GetName(); + break; + } + case Classes::CLASS_HUNTER: + { + break; + } + case Classes::CLASS_MAGE: + { + break; + } + case Classes::CLASS_DRUID: + { + break; + } + case Classes::CLASS_ROGUE: + { + break; + } + case Classes::CLASS_PRIEST: + { + member->groupRole = GroupRole::GroupRole_Healer; + ogHealer = member->GetObjectGuid(); + replyStream << "og healer is : " << ogHealer.GetCounter() << " " << member->GetName(); + break; + } + default: + { + break; + } + } if (NierStrategy_Base* ns = member->nierStrategyMap[member->activeStrategyIndex]) { ns->Reset(); - member->groupRole = GroupRole::GroupRole_DPS; - switch (member->GetClass()) - { - case Classes::CLASS_WARRIOR: - { - member->groupRole = GroupRole::GroupRole_Tank; - ogTank = member->GetObjectGuid(); - break; - } - case Classes::CLASS_HUNTER: - { - break; - } - case Classes::CLASS_MAGE: - { - ns->rti = rti; - rti++; - break; - } - case Classes::CLASS_DRUID: - { - ns->rti = rti; - rti++; - break; - } - case Classes::CLASS_ROGUE: - { - ns->forceBack = true; - break; - } - case Classes::CLASS_PRIEST: - { - member->groupRole = GroupRole::GroupRole_Healer; - ogHealer = member->GetObjectGuid(); - break; - } - default: - { - break; - } - } + ns->rti = rti; + rti++; + } + if (member->nierAction) + { + member->nierAction->Prepare(); } - member->nierAction->Prepare(); } } + + // roles and report for (GroupReference* groupRef = pmTargetGroup->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) { if (Player* member = groupRef->getSource()) @@ -786,7 +819,9 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, if (NierStrategy_Base* ns = member->nierStrategyMap[member->activeStrategyIndex]) { ns->ogTank = ogTank; + replyStream << "og tank for member " << member->GetName() << " is : " << ns->ogTank.GetCounter(); ns->ogHealer = ogHealer; + replyStream << "og healer for member " << member->GetName() << " is : " << ns->ogHealer.GetCounter(); ns->Report(); } } @@ -900,13 +935,13 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, float distance = pmTargetPlayer->GetDistance(distanceTarget); std::ostringstream replyStream0; replyStream0 << "base : " << distance; - pmTargetPlayer->Say(replyStream0.str(), Language::LANG_UNIVERSAL); + pmTargetPlayer->Say(replyStream0.str().c_str(), Language::LANG_UNIVERSAL); } else { std::ostringstream replyStream; replyStream << "No target"; - pmTargetPlayer->Say(replyStream.str(), Language::LANG_UNIVERSAL); + pmTargetPlayer->Say(replyStream.str().c_str(), Language::LANG_UNIVERSAL); } } else if (pmTargetGroup) @@ -970,7 +1005,7 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, { replyStream << "No color"; } - pmTargetPlayer->Say(replyStream.str(), Language::LANG_UNIVERSAL); + pmTargetPlayer->Say(replyStream.str().c_str(), Language::LANG_UNIVERSAL); } else if (pmTargetGroup) { @@ -1068,15 +1103,15 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, std::string checkStr = commandVector.at(1); distance = atof(checkStr.c_str()); } - pmTargetPlayer->nierAction->nm->Chase(distanceTarget, distance, 0.0f, false, false); + pmTargetPlayer->nierAction->nm->Chase(distanceTarget, distance, 0.0f); replyStream << "chasing : " << distanceTarget->GetName(); - pmTargetPlayer->Say(replyStream.str(), Language::LANG_UNIVERSAL); + pmTargetPlayer->Say(replyStream.str().c_str(), Language::LANG_UNIVERSAL); } else { replyStream << "No target"; } - pmTargetPlayer->Say(replyStream.str(), Language::LANG_UNIVERSAL); + pmTargetPlayer->Say(replyStream.str().c_str(), Language::LANG_UNIVERSAL); } else if (pmTargetGroup) { @@ -1192,17 +1227,6 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, sWorld.SendServerMessage(ServerMessageType::SERVER_MSG_CUSTOM, "You are not in a group", pmCommander); } } - else if (commandName == "debug") - { - if (commandVector.size() > 1) - { - std::string debugType = commandVector.at(1); - if (debugType == "jingzhe1") - { - //pmCommander->StoreNewItemInBestSlots(6948, 1); - } - } - } else if (commandName == "nier") { if (commandVector.size() > 1) @@ -1378,7 +1402,7 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, } if (pmTargetPlayer->groupRole == GroupRole::GroupRole_Tank) { - if (ns->DoTank(target)) + if (ns->DoTank(target, false)) { if (Group* tankGroup = pmTargetPlayer->GetGroup()) { @@ -1680,12 +1704,6 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, WhisperTo(pmCommander, replyStream.str(), Language::LANG_UNIVERSAL, pmTargetPlayer); } } - else if (ns->Revive()) - { - std::ostringstream replyStream; - replyStream << "Try to do reviving"; - WhisperTo(pmCommander, replyStream.str(), Language::LANG_UNIVERSAL, pmTargetPlayer); - } } } else if (pmTargetGroup) @@ -1714,7 +1732,7 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, { std::string cmdDistanceStr = commandVector.at(1); float cmdDistance = atof(cmdDistanceStr.c_str()); - if (cmdDistance >= CONTACT_DISTANCE && cmdDistance <= NIER_MAX_DISTANCE) + if (cmdDistance >= 0.0f && cmdDistance <= NIER_MAX_DISTANCE) { ns->followDistance = cmdDistance; replyStream << "Follow distance - " << ns->followDistance; @@ -1749,6 +1767,53 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, } } } + else if (commandName == "debug") + { + if (pmTargetPlayer) + { + if (NierStrategy_Base* ns = pmTargetPlayer->nierStrategyMap[pmTargetPlayer->activeStrategyIndex]) + { + std::ostringstream replyStream; + if (commandVector.size() > 1) + { + std::string debugContents = commandVector.at(1); + if (debugContents == "follow") + { + if (pmTargetPlayer->nierAction->nm->ogFollowTarget.IsEmpty()) + { + replyStream << "follow target og is empty"; + } + else + { + if (Player* ft = ObjectAccessor::FindPlayer(pmTargetPlayer->nierAction->nm->ogFollowTarget)) + { + replyStream << "follow target is " << ft->GetName(); + } + else + { + replyStream << "follow target not found : " << pmTargetPlayer->nierAction->nm->ogFollowTarget.GetCounter(); + } + } + } + } + WhisperTo(pmCommander, replyStream.str(), Language::LANG_UNIVERSAL, pmTargetPlayer); + } + } + else if (pmTargetGroup) + { + for (GroupReference* groupRef = pmTargetGroup->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) + { + Player* member = groupRef->getSource(); + if (member) + { + if (member->GetObjectGuid() != pmCommander->GetObjectGuid()) + { + HandleChatCommand(pmCommander, pmContent, member); + } + } + } + } + } else if (commandName == "chase") { if (pmTargetPlayer) @@ -2247,41 +2312,41 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, if (NierStrategy_Base* ns = pmTargetPlayer->nierStrategyMap[pmTargetPlayer->activeStrategyIndex]) { std::ostringstream replyStream; - if (commandVector.size() > 1) - { - std::string roleCMD = commandVector.at(1); - bool onoff = false; - if (commandVector.size() > 2) - { - std::string switchCMD = commandVector.at(2); - if (switchCMD == "on") - { - onoff = true; - } - if (roleCMD == "tank") - { - if (pmTargetPlayer->groupRole == GroupRole::GroupRole_Tank) - { - ns->aoe = onoff; - } - } - else if (roleCMD == "dps") - { - if (pmTargetPlayer->groupRole == GroupRole::GroupRole_DPS) - { - ns->aoe = onoff; - } - } - } - } - if (ns->aoe) - { - replyStream << "AOE is on"; - } - else - { - replyStream << "AOE is off"; - } + //if (commandVector.size() > 1) + //{ + // std::string roleCMD = commandVector.at(1); + // bool onoff = false; + // if (commandVector.size() > 2) + // { + // std::string switchCMD = commandVector.at(2); + // if (switchCMD == "on") + // { + // onoff = true; + // } + // if (roleCMD == "tank") + // { + // if (pmTargetPlayer->groupRole == GroupRole::GroupRole_Tank) + // { + // ns->aoe = onoff; + // } + // } + // else if (roleCMD == "dps") + // { + // if (pmTargetPlayer->groupRole == GroupRole::GroupRole_DPS) + // { + // ns->aoe = onoff; + // } + // } + // } + //} + //if (ns->aoe) + //{ + // replyStream << "AOE is on"; + //} + //else + //{ + // replyStream << "AOE is off"; + //} WhisperTo(pmCommander, replyStream.str(), Language::LANG_UNIVERSAL, pmTargetPlayer); } } @@ -2396,7 +2461,7 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, { std::ostringstream replyStream; replyStream << "Portal to " << city; - pmTargetPlayer->Say(replyStream.str(), Language::LANG_UNIVERSAL); + pmTargetPlayer->Say(replyStream.str().c_str(), Language::LANG_UNIVERSAL); nam->CastSpell(pmTargetPlayer, portalSpell); } } @@ -2543,7 +2608,7 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, { std::ostringstream replyStream; replyStream << "Innervate - " << pmTargetPlayer->GetName(); - pmTargetPlayer->Yell(replyStream.str(), Language::LANG_UNIVERSAL); + pmTargetPlayer->Yell(replyStream.str().c_str(), Language::LANG_UNIVERSAL); } } else if (roleName == "healer") @@ -2568,7 +2633,7 @@ void NierManager::HandleChatCommand(Player* pmCommander, std::string pmContent, { std::ostringstream replyStream; replyStream << "Innervate - " << member->GetName(); - pmTargetPlayer->Yell(replyStream.str(), Language::LANG_UNIVERSAL); + pmTargetPlayer->Yell(replyStream.str().c_str(), Language::LANG_UNIVERSAL); break; } } diff --git a/src/game/Nier/NierManager.h b/src/game/Nier/NierManager.h index 0ab8ea839fd..d4d8b21a74c 100644 --- a/src/game/Nier/NierManager.h +++ b/src/game/Nier/NierManager.h @@ -76,8 +76,8 @@ class NierManager std::unordered_map> characterTalentTabNameMap; std::unordered_set instanceEncounterEntrySet; - // inventorytype - required level - item index, item entry - std::unordered_map>> equipsMap; + // inventorytype - sub class - required level - item index, item entry + std::unordered_map>>> equipsMap; private: void CreateNier(uint32 pmLevel, bool pmAlliance, uint32 pmGroupRole); diff --git a/src/game/Nier/NierStrategies/GroupStrategy_Base.cpp b/src/game/Nier/NierStrategies/GroupStrategy_Base.cpp new file mode 100644 index 00000000000..097698e285d --- /dev/null +++ b/src/game/Nier/NierStrategies/GroupStrategy_Base.cpp @@ -0,0 +1,364 @@ +#include "GroupStrategy_Base.h" +#include "NierConfig.h" +#include "NierManager.h" +#include "NierAction_Base.h" +#include "NierAction_Paladin.h" + +#include "Player.h" +#include "Group.h" +#include "Pet.h" +#include "GridNotifiers.h" +#include "Spell.h" + +GroupStrategy_Base::GroupStrategy_Base() +{ + me = nullptr; + interruptDelay = 0; +} + +void GroupStrategy_Base::Reset() +{ + interruptDelay = 0; +} + +void GroupStrategy_Base::Update(uint32 pmDiff) +{ + if (!me) + { + return; + } + + if (interruptDelay > 0) + { + interruptDelay -= pmDiff; + } + bool groupInCombat = false; + Unit* tank = nullptr; + Unit* lowMember = nullptr; + for (GroupReference* groupRef = me->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) + { + if (Player* member = groupRef->getSource()) + { + if (member->IsAlive()) + { + if (member->groupRole == GroupRole::GroupRole_Tank) + { + tank = member; + } + else + { + if (member->GetHealthPercent() < 50.0f) + { + lowMember = member; + } + } + } + if (member->IsInCombat()) + { + groupInCombat = true; + } + } + } + if (groupInCombat) + { + bool tankAOE = false; + uint32 tankEnemyCount = 0; + if (tank) + { + std::list targets; + MaNGOS::AnyUnitInObjectRangeCheck u_check(tank, NIER_NEAR_DISTANCE); + MaNGOS::UnitListSearcher searcher(targets, u_check); + // Don't need to use visibility modifier, units won't be able to cast outside of draw distance + Cell::VisitAllObjects(tank, searcher, NIER_NEAR_DISTANCE); + for (std::list::iterator uIT = targets.begin(); uIT != targets.end(); uIT++) + { + if (Unit* eachUnit = *uIT) + { + if (eachUnit->IsHostileTo(tank)) + { + if (eachUnit->IsInCombat()) + { + tankEnemyCount += 1; + } + } + } + } + } + if (tankEnemyCount > 1) + { + tankAOE = true; + } + std::unordered_set interruptedSet; + for (GroupReference* groupRef = me->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) + { + if (Player* member = groupRef->getSource()) + { + if (member->isNier) + { + if (member->IsAlive()) + { + if (member->HasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING)) + { + continue; + } + if (NierStrategy_Base* ns = member->nierStrategyMap[member->activeStrategyIndex]) + { + if (ns->basicStrategyType == BasicStrategyType::BasicStrategyType_Freeze) + { + continue; + } + if (member->groupRole == GroupRole::GroupRole_Tank) + { + Unit* ogTankTarget = ObjectAccessor::GetUnit(*member, me->GetGuidByTargetIcon(7)); + if (ogTankTarget) + { + if (!ogTankTarget->GetTargetGuid().IsEmpty()) + { + if (ogTankTarget->GetTargetGuid() != member->GetObjectGuid()) + { + if (ns->DoTank(ogTankTarget, tankAOE)) + { + continue; + } + } + } + } + Unit* myTarget = member->GetSelectedUnit(); + if (myTarget) + { + if (!myTarget->GetTargetGuid().IsEmpty()) + { + if (myTarget->GetTargetGuid() != member->GetObjectGuid()) + { + if (ns->DoTank(myTarget, tankAOE)) + { + me->SetTargetIcon(7, myTarget->GetObjectGuid()); + continue; + } + } + } + } + if (Unit* nearestOTUnit = GetNeareastOTUnit(member)) + { + if (ns->DoTank(nearestOTUnit, tankAOE)) + { + me->SetTargetIcon(7, nearestOTUnit->GetObjectGuid()); + continue; + } + } + if (ns->DoTank(ogTankTarget, tankAOE)) + { + continue; + } + if (myTarget) + { + if (!sNierManager->IsPolymorphed(myTarget)) + { + if (ns->DoTank(myTarget, tankAOE)) + { + me->SetTargetIcon(7, myTarget->GetObjectGuid()); + continue; + } + } + } + if (Unit* nearestAttacker = GetNeareastAttacker(member)) + { + if (ns->DoTank(nearestAttacker, tankAOE)) + { + me->SetTargetIcon(7, nearestAttacker->GetObjectGuid()); + continue; + } + } + } + else if (member->groupRole == GroupRole::GroupRole_DPS) + { + if (ns->ogVip.IsEmpty()) + { + if (ObjectGuid ogTankTarget = me->GetGuidByTargetIcon(7)) + { + if (Unit* tankTarget = ObjectAccessor::GetUnit(*member, ogTankTarget)) + { + if (interruptDelay <= 0) + { + if (tankTarget->IsNonMeleeSpellCasted(false, false, true)) + { + if (interruptedSet.find(tankTarget->GetObjectGuid()) == interruptedSet.end()) + { + if (member->nierAction->Interrupt(tankTarget)) + { + interruptedSet.insert(tankTarget->GetObjectGuid()); + interruptDelay = 500; + continue; + } + } + } + } + if (ns->DoDPS(tankTarget, false, true)) + { + continue; + } + } + } + + if (Player* leader = ObjectAccessor::FindPlayer(me->GetLeaderGuid())) + { + if (Unit* leaderTarget = leader->GetSelectedUnit()) + { + if (leaderTarget->IsInCombat()) + { + if (!sNierManager->IsPolymorphed(leaderTarget)) + { + if (interruptDelay <= 0) + { + if (leaderTarget->IsNonMeleeSpellCasted(false, false, true)) + { + if (interruptedSet.find(leaderTarget->GetObjectGuid()) == interruptedSet.end()) + { + if (member->nierAction->Interrupt(leaderTarget)) + { + interruptedSet.insert(leaderTarget->GetObjectGuid()); + interruptDelay = 500; + continue; + } + } + } + } + if (ns->DoDPS(leaderTarget, false, true)) + { + continue; + } + } + } + } + } + } + } + else if (member->groupRole == GroupRole::GroupRole_Healer) + { + if (member->GetHealthPercent() < 50.0f) + { + if (ns->DoHeal(member, false)) + { + continue; + } + } + if (tank) + { + if (tank->GetHealthPercent() < 80.0f) + { + if (ns->DoHeal(tank, false)) + { + continue; + } + } + } + if (lowMember) + { + if (ns->DoHeal(lowMember, false)) + { + continue; + } + } + } + } + } + } + } + } + } +} + +Unit* GroupStrategy_Base::GetNeareastOTUnit(Unit* pmTank) +{ + if (!me) + { + return nullptr; + } + + Unit* nearestOTUnit = nullptr; + float nearestDistance = VISIBILITY_DISTANCE_NORMAL; + for (GroupReference* groupRef = me->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) + { + if (Player* member = groupRef->getSource()) + { + if (member->IsAlive()) + { + if (member->GetObjectGuid() != pmTank->GetObjectGuid()) + { + float memberDistance = pmTank->GetDistance(member); + if (memberDistance < NIER_FAR_DISTANCE) + { + std::set memberAttackers = member->GetAttackers(); + for (std::set::iterator ait = memberAttackers.begin(); ait != memberAttackers.end(); ++ait) + { + if (Unit* eachAttacker = *ait) + { + if (pmTank->IsValidAttackTarget(eachAttacker)) + { + if (!eachAttacker->GetTargetGuid().IsEmpty()) + { + if (eachAttacker->GetTargetGuid() != pmTank->GetObjectGuid()) + { + float eachDistance = pmTank->GetDistance(eachAttacker); + if (eachDistance < NIER_FAR_DISTANCE) + { + if (eachDistance < nearestDistance) + { + if (me->GetTargetIconByGuid(eachAttacker->GetObjectGuid()) == -1) + { + nearestDistance = eachDistance; + nearestOTUnit = eachAttacker; + } + } + } + } + } + } + } + } + } + } + } + } + } + + return nearestOTUnit; +} + +Unit* GroupStrategy_Base::GetNeareastAttacker(Unit* pmTank) +{ + if (!me) + { + return nullptr; + } + + Unit* nearestAttacker = nullptr; + float nearestDistance = VISIBILITY_DISTANCE_NORMAL; + std::set myAttackers = pmTank->GetAttackers(); + for (std::set::iterator ait = myAttackers.begin(); ait != myAttackers.end(); ++ait) + { + if (Unit* eachAttacker = *ait) + { + if (pmTank->IsValidAttackTarget(eachAttacker)) + { + if (!sNierManager->IsPolymorphed(eachAttacker)) + { + float eachDistance = pmTank->GetDistance(eachAttacker); + if (eachDistance < nearestDistance) + { + if (me->GetTargetIconByGuid(eachAttacker->GetObjectGuid()) == -1) + { + if (!eachAttacker->IsImmuneToDamage(SpellSchoolMask::SPELL_SCHOOL_MASK_NORMAL)) + { + nearestDistance = eachDistance; + nearestAttacker = eachAttacker; + } + } + } + } + } + } + } + + return nearestAttacker; +} \ No newline at end of file diff --git a/src/game/Nier/NierStrategies/GroupStrategy_Base.h b/src/game/Nier/NierStrategies/GroupStrategy_Base.h new file mode 100644 index 00000000000..39e45e0ab3d --- /dev/null +++ b/src/game/Nier/NierStrategies/GroupStrategy_Base.h @@ -0,0 +1,40 @@ +#ifndef GROUP_STRATEGY_H +#define GROUP_STRATEGY_H + +#ifndef ENTRY_HUNGARFEN +#define ENTRY_HUNGARFEN 17770 +#endif + +#ifndef ENTRY_HUNGARFEN_1 +#define ENTRY_HUNGARFEN_1 20169 +#endif + +#ifndef ENTRY_UNDERBOG_MUSHROOM +#define ENTRY_UNDERBOG_MUSHROOM 17990 +#endif + +#ifndef ENTRY_UNDERBOG_MUSHROOM_1 +#define ENTRY_UNDERBOG_MUSHROOM_1 20189 +#endif + +#include "Nier/NierConfig.h" + +class NierAction_Base; + +class GroupStrategy_Base +{ +public: + GroupStrategy_Base(); + virtual void Reset(); + + virtual void Update(uint32 pmDiff); + + Unit* GetNeareastOTUnit(Unit* pmTank); + Unit* GetNeareastAttacker(Unit* pmTank); + +public: + Group* me; + + int interruptDelay; +}; +#endif diff --git a/src/game/Nier/NierStrategies/NierStrategy_Base.cpp b/src/game/Nier/NierStrategies/NierStrategy_Base.cpp index d57587109df..94d24ca79f1 100644 --- a/src/game/Nier/NierStrategies/NierStrategy_Base.cpp +++ b/src/game/Nier/NierStrategies/NierStrategy_Base.cpp @@ -2,6 +2,7 @@ #include "NierConfig.h" #include "NierManager.h" #include "NierAction_Base.h" +#include "NierAction_Paladin.h" #include "Player.h" #include "Group.h" @@ -31,11 +32,9 @@ NierStrategy_Base::NierStrategy_Base() basicStrategyType = BasicStrategyType::BasicStrategyType_Normal; cure = true; - aoe = true; petting = false; rushing = false; - forceBack = false; instantOnly = false; actionLimit = 0; @@ -45,9 +44,9 @@ NierStrategy_Base::NierStrategy_Base() vipEntry = 0; actionType = ActionType::ActionType_None; - dpsDistance = MELEE_RANGE; + dpsDistance = DEFAULT_COMBAT_REACH; dpsDistanceMin = 0.0f; - followDistance = INTERACTION_DISTANCE; + followDistance = NIER_MIN_DISTANCE; cautionSpellMap.clear(); } @@ -63,6 +62,17 @@ void NierStrategy_Base::Report() std::ostringstream reportStream; reportStream << "Strategy : " << me->activeStrategyIndex << " - Role : " << me->groupRole << " - Specialty : " << sNierManager->characterTalentTabNameMap[me->GetClass()][me->nierAction->specialty] << " RTI : " << rti; sNierManager->WhisperTo(leaderPlayer, reportStream.str(), Language::LANG_UNIVERSAL, me); + + // paladin report + std::ostringstream classStream; + if (me->GetClass() == Classes::CLASS_PALADIN) + { + if (NierAction_Paladin* na = (NierAction_Paladin*)me->nierAction) + { + classStream << "Seal type : " << na->sealType << " - Blessing type : " << na->blessingType << " - Aura type : " << na->auraType; + sNierManager->WhisperTo(leaderPlayer, classStream.str(), Language::LANG_UNIVERSAL, me); + } + } } } } @@ -84,12 +94,10 @@ void NierStrategy_Base::Reset() basicStrategyType = BasicStrategyType::BasicStrategyType_Normal; cure = true; - aoe = true; petting = false; rushing = false; rti = -1; - forceBack = false; instantOnly = false; actionLimit = 0; @@ -100,9 +108,9 @@ void NierStrategy_Base::Reset() vipEntry = 0; cautionSpellMap.clear(); - dpsDistance = me->GetMeleeReach(); + dpsDistance = DEFAULT_COMBAT_REACH; dpsDistanceMin = 0.0f; - followDistance = INTERACTION_DISTANCE; + followDistance = NIER_MIN_DISTANCE; switch (me->GetClass()) { @@ -113,7 +121,6 @@ void NierStrategy_Base::Reset() } case Classes::CLASS_HUNTER: { - aoe = true; dpsDistance = NIER_MAX_DISTANCE; dpsDistanceMin = 0; break; @@ -124,19 +131,19 @@ void NierStrategy_Base::Reset() } case Classes::CLASS_PALADIN: { + me->groupRole = GroupRole::GroupRole_Tank; break; } case Classes::CLASS_WARLOCK: { - aoe = true; dpsDistance = NIER_FAR_DISTANCE; break; } case Classes::CLASS_PRIEST: { - aoe = true; me->groupRole = GroupRole::GroupRole_Healer; dpsDistance = NIER_FAR_DISTANCE; + followDistance = NIER_NORMAL_DISTANCE; break; } case Classes::CLASS_ROGUE: @@ -145,14 +152,12 @@ void NierStrategy_Base::Reset() } case Classes::CLASS_MAGE: { - aoe = true; dpsDistance = NIER_FAR_DISTANCE; dpsDistanceMin = 0; break; } case Classes::CLASS_DRUID: { - aoe = true; dpsDistance = NIER_FAR_DISTANCE; break; } @@ -224,6 +229,10 @@ void NierStrategy_Base::Update(uint32 pmDiff) } if (me->IsAlive()) { + if (me->HasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING)) + { + return; + } if (me->IsNonMeleeSpellCasted(true)) { bool interrupt = false; @@ -329,6 +338,17 @@ void NierStrategy_Base::Update(uint32 pmDiff) } return; } + case ActionType::ActionType_Attack: + { + if (Unit* actionTarget = ObjectAccessor::GetUnit(*me, ogActionTarget)) + { + if (me->nierAction->Attack(actionTarget)) + { + return; + } + } + break; + } default: break; } @@ -457,10 +477,6 @@ void NierStrategy_Base::Update(uint32 pmDiff) } case GroupRole::GroupRole_Tank: { - if (TryTank()) - { - return; - } break; } default: @@ -510,8 +526,8 @@ void NierStrategy_Base::Update(uint32 pmDiff) { return; } + Follow(); } - Follow(); } else { @@ -531,7 +547,7 @@ void NierStrategy_Base::Update(uint32 pmDiff) { return; } - if (TryDPS(false, false, true)) + if (TryAttack()) { return; } @@ -576,14 +592,14 @@ void NierStrategy_Base::Update(uint32 pmDiff) { if (eachUnit->GetTypeId() == TypeID::TYPEID_PLAYER) { - if (Engage(eachUnit)) + if (me->nierAction->Attack(eachUnit)) { me->SetPvP(true); me->UpdatePvP(true); me->pvpInfo.inPvPCombat = true; actionLimit = 30 * IN_MILLISECONDS; ogActionTarget = eachUnit->GetObjectGuid(); - actionType = ActionType::ActionType_Engage; + actionType = ActionType::ActionType_Attack; return; } } @@ -680,7 +696,7 @@ bool NierStrategy_Base::Engage(Unit* pmTarget) { case GroupRole::GroupRole_Tank: { - if (me->nierAction->Tank(pmTarget, aoe, dpsDistance, dpsDistanceMin, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold)) + if (me->nierAction->Tank(pmTarget, false)) { if (Group* myGroup = me->GetGroup()) { @@ -706,7 +722,7 @@ bool NierStrategy_Base::Engage(Unit* pmTarget) return false; } -bool NierStrategy_Base::TryTank() +bool NierStrategy_Base::TryAttack() { if (!me) { @@ -717,147 +733,49 @@ bool NierStrategy_Base::TryTank() return false; } - if (Group* myGroup = me->GetGroup()) + if (Unit* myTarget = me->GetSelectedUnit()) { - Unit* ogTankTarget = ObjectAccessor::GetUnit(*me, myGroup->GetGuidByTargetIcon(7)); - if (ogTankTarget) - { - if (!ogTankTarget->GetTargetGuid().IsEmpty()) - { - if (ogTankTarget->GetTargetGuid() != me->GetObjectGuid()) - { - if (DoTank(ogTankTarget)) - { - return true; - } - } - } - } - Unit* myTarget = me->GetSelectedUnit(); - if (myTarget) + if (!sNierManager->IsPolymorphed(myTarget)) { - if (!myTarget->GetTargetGuid().IsEmpty()) + if (me->nierAction->Attack(myTarget)) { - if (myTarget->GetTargetGuid() != me->GetObjectGuid()) - { - if (DoTank(myTarget)) - { - myGroup->SetTargetIcon(7, myTarget->GetObjectGuid()); - return true; - } - } - } - } - Unit* nearestOTUnit = nullptr; - float nearestDistance = VISIBILITY_DISTANCE_NORMAL; - for (GroupReference* groupRef = myGroup->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) - { - if (Player* member = groupRef->getSource()) - { - if (member->IsAlive()) - { - if (member->GetObjectGuid() != me->GetObjectGuid()) - { - float memberDistance = me->GetDistance(member); - if (memberDistance < VISIBILITY_DISTANCE_NORMAL) - { - std::set memberAttackers = member->GetAttackers(); - for (std::set::iterator ait = memberAttackers.begin(); ait != memberAttackers.end(); ++ait) - { - if (Unit* eachAttacker = *ait) - { - if (me->IsValidAttackTarget(eachAttacker)) - { - if (!eachAttacker->GetTargetGuid().IsEmpty()) - { - if (eachAttacker->GetTargetGuid() != me->GetObjectGuid()) - { - float eachDistance = me->GetDistance(eachAttacker); - if (eachDistance < NIER_NORMAL_DISTANCE) - { - if (eachDistance < nearestDistance) - { - if (myGroup->GetTargetIconByGuid(eachAttacker->GetObjectGuid()) == -1) - { - nearestDistance = eachDistance; - nearestOTUnit = eachAttacker; - } - } - } - } - } - } - } - } - } - } - } - } - } - if (nearestOTUnit) - { - if (DoTank(nearestOTUnit)) - { - myGroup->SetTargetIcon(7, nearestOTUnit->GetObjectGuid()); return true; } } - if (DoTank(ogTankTarget)) - { - return true; - } - if (myTarget) - { - if (!sNierManager->IsPolymorphed(myTarget)) - { - if (DoTank(myTarget)) - { - myGroup->SetTargetIcon(7, myTarget->GetObjectGuid()); - return true; - } - } - } - Unit* nearestAttacker = nullptr; - nearestDistance = VISIBILITY_DISTANCE_NORMAL; - std::set myAttackers = me->GetAttackers(); - for (std::set::iterator ait = myAttackers.begin(); ait != myAttackers.end(); ++ait) + } + Unit* nearestAttacker = nullptr; + float nearestDistance = VISIBILITY_DISTANCE_NORMAL; + std::set myAttackers = me->GetAttackers(); + for (std::set::iterator ait = myAttackers.begin(); ait != myAttackers.end(); ++ait) + { + if (Unit* eachAttacker = *ait) { - if (Unit* eachAttacker = *ait) + if (me->IsValidAttackTarget(eachAttacker)) { - if (me->IsValidAttackTarget(eachAttacker)) + if (!sNierManager->IsPolymorphed(eachAttacker)) { - if (!sNierManager->IsPolymorphed(eachAttacker)) + float eachDistance = me->GetDistance(eachAttacker); + if (eachDistance < nearestDistance) { - float eachDistance = me->GetDistance(eachAttacker); - if (eachDistance < nearestDistance) - { - if (myGroup->GetTargetIconByGuid(eachAttacker->GetObjectGuid()) == -1) - { - if (!eachAttacker->IsImmuneToDamage(SpellSchoolMask::SPELL_SCHOOL_MASK_NORMAL)) - { - nearestDistance = eachDistance; - nearestAttacker = eachAttacker; - } - } - } + nearestDistance = eachDistance; + nearestAttacker = eachAttacker; } } } } - if (nearestAttacker) + } + if (nearestAttacker) + { + if (me->nierAction->Attack(nearestAttacker)) { - if (DoTank(nearestAttacker)) - { - myGroup->SetTargetIcon(7, nearestAttacker->GetObjectGuid()); - return true; - } + return true; } } return false; } -bool NierStrategy_Base::DoTank(Unit* pmTarget) +bool NierStrategy_Base::DoTank(Unit* pmTarget, bool aoe) { if (!me) { @@ -867,8 +785,17 @@ bool NierStrategy_Base::DoTank(Unit* pmTarget) { return false; } + if (!pmTarget) + { + return false; + } + else if (!pmTarget->IsAlive()) + { + return false; + } + - if (me->nierAction->Tank(pmTarget, aoe, dpsDistance, dpsDistanceMin, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold)) + if (me->nierAction->Tank(pmTarget, aoe)) { return true; } @@ -917,78 +844,6 @@ bool NierStrategy_Base::TryDPS(bool pmDelay, bool pmForceInstantOnly, bool pmCha } } - if (Group* myGroup = me->GetGroup()) - { - if (ObjectGuid ogTankTarget = myGroup->GetGuidByTargetIcon(7)) - { - if (Unit* tankTarget = ObjectAccessor::GetUnit(*me, ogTankTarget)) - { - if (DoDPS(tankTarget, pmForceInstantOnly, pmChasing)) - { - return true; - } - } - } - - if (Player* leader = ObjectAccessor::FindPlayer(myGroup->GetLeaderGuid())) - { - if (Unit* leaderTarget = leader->GetSelectedUnit()) - { - if (leaderTarget->IsInCombat()) - { - if (!sNierManager->IsPolymorphed(leaderTarget)) - { - if (DoDPS(leaderTarget, pmForceInstantOnly, pmChasing)) - { - return true; - } - } - } - } - } - } - else - { - if (Unit* myTarget = me->GetSelectedUnit()) - { - if (!sNierManager->IsPolymorphed(myTarget)) - { - if (DoDPS(myTarget, pmForceInstantOnly, pmChasing)) - { - return true; - } - } - } - Unit* nearestAttacker = nullptr; - float nearestDistance = VISIBILITY_DISTANCE_NORMAL; - std::set myAttackers = me->GetAttackers(); - for (std::set::iterator ait = myAttackers.begin(); ait != myAttackers.end(); ++ait) - { - if (Unit* eachAttacker = *ait) - { - if (me->IsValidAttackTarget(eachAttacker)) - { - if (!sNierManager->IsPolymorphed(eachAttacker)) - { - float eachDistance = me->GetDistance(eachAttacker); - if (eachDistance < nearestDistance) - { - nearestDistance = eachDistance; - nearestAttacker = eachAttacker; - } - } - } - } - } - if (nearestAttacker) - { - if (DoDPS(nearestAttacker, pmForceInstantOnly, pmChasing)) - { - return true; - } - } - } - return false; } @@ -1006,6 +861,10 @@ bool NierStrategy_Base::DoDPS(Unit* pmTarget, bool pmForceInstantOnly, bool pmCh { return false; } + else if (!pmTarget->IsAlive()) + { + return false; + } bool instant = pmForceInstantOnly; if (!instant) @@ -1013,37 +872,37 @@ bool NierStrategy_Base::DoDPS(Unit* pmTarget, bool pmForceInstantOnly, bool pmCh instant = instantOnly; } - if (aoe) - { - int attackerInRangeCount = 0; - std::list creatureList; - pmTarget->GetCreatureListWithEntryInGrid(creatureList, 0, INTERACTION_DISTANCE); - if (!creatureList.empty()) - { - for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) - { - if (Creature* hostileCreature = *itr) - { - if (!hostileCreature->IsPet()) - { - if (me->IsValidAttackTarget(hostileCreature)) - { - attackerInRangeCount++; - } - } - } - } - } - if (attackerInRangeCount > 3) - { - if (me->nierAction->AOE(pmTarget, rushing, dpsDistance, dpsDistanceMin, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold, instant, pmChasing)) - { - return true; - } - } - } - - if (me->nierAction->DPS(pmTarget, rushing, dpsDistance, dpsDistanceMin, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold, instant, pmChasing)) + //if (aoe) + //{ + // int attackerInRangeCount = 0; + // std::list creatureList; + // pmTarget->GetCreatureListWithEntryInGrid(creatureList, 0, INTERACTION_DISTANCE); + // if (!creatureList.empty()) + // { + // for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) + // { + // if (Creature* hostileCreature = *itr) + // { + // if (!hostileCreature->IsPet()) + // { + // if (me->IsValidAttackTarget(hostileCreature)) + // { + // attackerInRangeCount++; + // } + // } + // } + // } + // } + // if (attackerInRangeCount > 3) + // { + // if (me->nierAction->AOE(pmTarget, rushing, dpsDistance, dpsDistanceMin, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold, instant, pmChasing)) + // { + // return true; + // } + // } + //} + + if (me->nierAction->DPS(pmTarget, rushing, pmChasing, dpsDistance, dpsDistanceMin)) { return true; } @@ -1110,68 +969,7 @@ bool NierStrategy_Base::TryHeal(bool pmForceInstantOnly) if (Group* myGroup = me->GetGroup()) { - if (me->GetHealthPercent() < 50.0f) - { - if (DoHeal(me, pmForceInstantOnly)) - { - return true; - } - } - Player* tank = nullptr; - Player* lowMember = nullptr; - uint32 lowMemberCount = 0; - for (GroupReference* groupRef = myGroup->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) - { - if (Player* member = groupRef->getSource()) - { - if (me->IsWithinDist(member, NIER_MAX_DISTANCE)) - { - if (member->GetHealthPercent() < 60.0f) - { - lowMember = member; - lowMemberCount++; - } - if (member->groupRole == GroupRole::GroupRole_Tank) - { - tank = member; - } - } - } - } - if (tank) - { - if (tank->GetHealthPercent() < 50.0f) - { - if (DoHeal(tank, pmForceInstantOnly)) - { - return true; - } - } - } - if (lowMemberCount > 1) - { - if (me->nierAction->GroupHeal(lowMember, pmForceInstantOnly)) - { - return true; - } - } - if (tank) - { - if (DoHeal(tank, pmForceInstantOnly)) - { - return true; - } - } - for (GroupReference* groupRef = myGroup->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) - { - if (Player* member = groupRef->getSource()) - { - if (me->nierAction->SimpleHeal(member, pmForceInstantOnly)) - { - return true; - } - } - } + // group actions } else { @@ -1208,7 +1006,7 @@ bool NierStrategy_Base::DoHeal(Unit* pmTarget, bool pmForceInstantOnly) return false; } -bool NierStrategy_Base::Revive() +bool NierStrategy_Base::Revive(Unit* pmTarget) { if (!me) { @@ -1218,44 +1016,17 @@ bool NierStrategy_Base::Revive() { return false; } - - if (Group* myGroup = me->GetGroup()) + if (me->IsNonMeleeSpellCasted(false, false, true)) { - for (GroupReference* groupRef = myGroup->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next()) - { - if (Player* member = groupRef->getSource()) - { - if (!member->IsAlive()) - { - if (me->nierAction->Revive(member)) - { - actionLimit = DEFAULT_ACTION_LIMIT_DELAY; - ogActionTarget = member->GetObjectGuid(); - actionType = ActionType::ActionType_Revive; - return true; - } - } - } - } - } - - return false; -} - -bool NierStrategy_Base::Revive(Unit* pmTarget) -{ - if (!me) - { - return false; - } - else if (!me->IsAlive()) - { - return false; + return true; } if (Player* targetPlayer = (Player*)pmTarget) { if (me->nierAction->Revive(targetPlayer)) { + actionLimit = DEFAULT_ACTION_LIMIT_DELAY; + ogActionTarget = pmTarget->GetObjectGuid(); + actionType = ActionType::ActionType_Revive; return true; } } @@ -1411,20 +1182,10 @@ bool NierStrategy_Base::Follow() } if (Group* myGroup = me->GetGroup()) { - if (me->groupRole != GroupRole::GroupRole_Tank) + ObjectGuid ogLeader = myGroup->GetLeaderGuid(); + if (Player* leader = ObjectAccessor::FindPlayer(ogLeader)) { - if (Player* tank = ObjectAccessor::FindPlayer(ogTank)) - { - if (me->nierAction->Follow(tank, followDistance, 0.0f, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold)) - { - ogActionTarget = tank->GetObjectGuid(); - return true; - } - } - } - if (Player* leader = ObjectAccessor::FindPlayer(myGroup->GetLeaderGuid())) - { - if (me->nierAction->Follow(leader, followDistance, 0.0f, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold)) + if (me->nierAction->Follow(leader, followDistance)) { ogActionTarget = leader->GetObjectGuid(); return true; @@ -1464,14 +1225,14 @@ bool NierStrategy_Base::Wander() { if (eachUnit->GetTypeId() == TypeID::TYPEID_PLAYER) { - if (Engage(eachUnit)) + if (me->nierAction->Attack(eachUnit)) { me->SetPvP(true); me->UpdatePvP(true); me->pvpInfo.inPvPCombat = true; actionLimit = 30 * IN_MILLISECONDS; ogActionTarget = eachUnit->GetObjectGuid(); - actionType = ActionType::ActionType_Engage; + actionType = ActionType::ActionType_Attack; return true; } } @@ -1537,371 +1298,3 @@ void NierStrategy_Base::SetGroupRole(std::string pmRoleName) me->groupRole = GroupRole::GroupRole_Healer; } } - -NierStrategy_The_Underbog::NierStrategy_The_Underbog() :NierStrategy_Base() -{ - hungarfen = false; -} - -NierStrategy_The_Black_Morass::NierStrategy_The_Black_Morass() : NierStrategy_Base() -{ - -} - -bool NierStrategy_The_Black_Morass::DoDPS(Unit* pmTarget, bool pmForceInstantOnly, bool pmChasing) -{ - if (!me) - { - return false; - } - else if (!me->IsAlive()) - { - return false; - } - if (aoe) - { - int attackerInRangeCount = 0; - std::list creatureList; - pmTarget->GetCreatureListWithEntryInGrid(creatureList, 0, INTERACTION_DISTANCE); - if (!creatureList.empty()) - { - for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) - { - if (Creature* hostileCreature = *itr) - { - if (!hostileCreature->IsPet()) - { - if (me->IsValidAttackTarget(hostileCreature)) - { - attackerInRangeCount++; - } - } - } - } - } - if (attackerInRangeCount > 2) - { - if (me->nierAction->AOE(pmTarget, rushing, dpsDistance, dpsDistanceMin, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold, instantOnly, pmChasing)) - { - return true; - } - } - } - - if (pmTarget->GetEntry() == 20745 || pmTarget->GetEntry() == 17880) - { - if (pmTarget->HasAura(38592)) - { - return false; - } - } - if (me->nierAction->DPS(pmTarget, rushing, dpsDistance, dpsDistanceMin, basicStrategyType == BasicStrategyType::BasicStrategyType_Hold, instantOnly, pmChasing)) - { - return true; - } - - return false; -} - -NierStrategy_Magisters_Terrace::NierStrategy_Magisters_Terrace() : NierStrategy_Base() -{ - kael = false; -} - -void NierStrategy_Magisters_Terrace::Update(uint32 pmDiff) -{ - if (!me) - { - kael = false; - } - else if (!me->IsAlive()) - { - kael = false; - } - else if (!me->IsInCombat()) - { - kael = false; - } - else if (kael) - { - me->nierAction->Update(pmDiff); - if (actionLimit > 0) - { - actionLimit -= pmDiff; - if (actionLimit < 0) - { - actionLimit = 0; - } - return; - } - if (Creature* phoenix = me->FindNearestCreature(24674, NIER_NORMAL_DISTANCE - MELEE_RANGE)) - { - me->nierAction->nm->ResetMovement(); - me->InterruptNonMeleeSpells(true); - Position pos; - me->GetNearPoint(phoenix, pos.x, pos.y, pos.z, 0.0f, NIER_NORMAL_DISTANCE, phoenix->GetAngle(me)); - me->GetMotionMaster()->MovePoint(0, pos.x, pos.y, pos.z, MoveOptions::MOVE_PATHFINDING); - actionType = ActionType::ActionType_Move; - actionLimit = 2000; - return; - } - if (Creature* flame = me->FindNearestCreature(24666, NIER_NORMAL_DISTANCE - MELEE_RANGE)) - { - me->nierAction->nm->ResetMovement(); - me->InterruptNonMeleeSpells(true); - Position pos; - me->GetNearPoint(flame, pos.x, pos.y, pos.z, 0.0f, NIER_NORMAL_DISTANCE, flame->GetAngle(me)); - me->GetMotionMaster()->MovePoint(0, pos.x, pos.y, pos.z, MoveOptions::MOVE_PATHFINDING); - actionType = ActionType::ActionType_Move; - actionLimit = 2000; - return; - } - } - if (basicStrategyType == BasicStrategyType::BasicStrategyType_Glue) - { - switch (me->groupRole) - { - case GroupRole::GroupRole_DPS: - { - TryDPS(false, true, false); - break; - } - case GroupRole::GroupRole_Healer: - { - TryHeal(true); - Cure(); - break; - } - case GroupRole::GroupRole_Tank: - { - break; - } - default: - { - break; - } - } - if (Group* myGroup = me->GetGroup()) - { - if (Player* leader = ObjectAccessor::FindPlayer(myGroup->GetLeaderGuid())) - { - if (leader->IsAlive()) - { - if (me->GetDistance(leader) > CONTACT_DISTANCE) - { - me->nierAction->nm->ResetMovement(); - me->InterruptNonMeleeSpells(true); - me->GetMotionMaster()->MovePoint(0, leader->GetPositionX(), leader->GetPositionY(), leader->GetPositionZ(), MoveOptions::MOVE_PATHFINDING); - } - return; - } - else - { - basicStrategyType = BasicStrategyType::BasicStrategyType_Normal; - } - } - else - { - basicStrategyType = BasicStrategyType::BasicStrategyType_Normal; - } - } - } - NierStrategy_Base::Update(pmDiff); -} - -bool NierStrategy_Magisters_Terrace::TryTank() -{ - if (!me) - { - return false; - } - else if (!me->IsAlive()) - { - return false; - } - if (kael) - { - if (Creature* egg = me->FindNearestCreature(24675, VISIBILITY_DISTANCE_NORMAL)) - { - if (DoTank(egg)) - { - return true; - } - } - Creature* boss = me->FindNearestCreature(24664, VISIBILITY_DISTANCE_NORMAL); - if (!boss) - { - boss = me->FindNearestCreature(24857, VISIBILITY_DISTANCE_NORMAL); - } - if (DoTank(boss)) - { - return true; - } - } - - return NierStrategy_Base::TryTank(); -} - -bool NierStrategy_Magisters_Terrace::DoTank(Unit* pmTarget) -{ - if (!me) - { - return false; - } - else if (!me->IsAlive()) - { - return false; - } - if (pmTarget->GetEntry() == 24664 || pmTarget->GetEntry() == 24857) - { - kael = true; - } - return NierStrategy_Base::DoTank(pmTarget); -} - -bool NierStrategy_Magisters_Terrace::TryDPS(bool pmDelay, bool pmForceInstantOnly, bool pmChasing) -{ - if (pmDelay) - { - if (combatDuration < dpsDelay) - { - return false; - } - } - - if (!me) - { - return false; - } - else if (!me->IsAlive()) - { - return false; - } - if (kael) - { - if (Creature* phoenix = me->FindNearestCreature(24674, VISIBILITY_DISTANCE_NORMAL)) - { - if (DoDPS(phoenix, false, pmChasing)) - { - rushing = true; - return true; - } - } - if (Creature* egg = me->FindNearestCreature(24675, VISIBILITY_DISTANCE_NORMAL)) - { - if (DoDPS(egg, false, pmChasing)) - { - rushing = true; - return true; - } - } - Creature* boss = me->FindNearestCreature(24664, VISIBILITY_DISTANCE_NORMAL); - if (!boss) - { - boss = me->FindNearestCreature(24857, VISIBILITY_DISTANCE_NORMAL); - } - if (DoDPS(boss, false, pmChasing)) - { - rushing = true; - return true; - } - } - if (Group* myGroup = me->GetGroup()) - { - if (ObjectGuid ogTankTarget = myGroup->GetGuidByTargetIcon(7)) - { - if (Unit* tankTarget = ObjectAccessor::GetUnit(*me, ogTankTarget)) - { - if (DoDPS(tankTarget, pmForceInstantOnly, pmChasing)) - { - if (tankTarget->GetEntry() == 24664 || tankTarget->GetEntry() == 24857) - { - kael = true; - } - return true; - } - } - } - - if (Player* leader = ObjectAccessor::FindPlayer(myGroup->GetLeaderGuid())) - { - if (Unit* leaderTarget = leader->GetSelectedUnit()) - { - if (leaderTarget->IsInCombat()) - { - if (!sNierManager->IsPolymorphed(leaderTarget)) - { - if (DoDPS(leaderTarget, pmForceInstantOnly, pmChasing)) - { - if (leaderTarget->GetEntry() == 24664 || leaderTarget->GetEntry() == 24857) - { - kael = true; - } - return true; - } - } - } - } - } - } - - return false; -} - -bool NierStrategy_Magisters_Terrace::DoDPS(Unit* pmTarget, bool pmForceInstantOnly, bool pmChasing) -{ - if (!me) - { - return false; - } - else if (!me->IsAlive()) - { - return false; - } - if (!pmTarget) - { - return false; - } - else if (!pmTarget->IsAlive()) - { - return false; - } - if (pmTarget->GetEntry() == 24664 || pmTarget->GetEntry() == 24857) - { - kael = true; - } - - return NierStrategy_Base::DoDPS(pmTarget, pmForceInstantOnly, pmChasing); -} - -bool NierStrategy_Magisters_Terrace::DoHeal(Unit* pmTarget, bool pmForceInstantOnly) -{ - if (!me) - { - return false; - } - else if (!me->IsAlive()) - { - return false; - } - if (!pmTarget) - { - return false; - } - else if (!pmTarget->IsAlive()) - { - return false; - } - if (Player* targetPlayer = pmTarget->ToPlayer()) - { - if (Unit* targetTarget = targetPlayer->GetSelectedUnit()) - { - if (targetTarget->GetEntry() == 24664 || targetTarget->GetEntry() == 24857) - { - kael = true; - } - } - } - - return NierStrategy_Base::DoHeal(pmTarget, pmForceInstantOnly); -} \ No newline at end of file diff --git a/src/game/Nier/NierStrategies/NierStrategy_Base.h b/src/game/Nier/NierStrategies/NierStrategy_Base.h index ad62bb567ea..32fcbf661e3 100644 --- a/src/game/Nier/NierStrategies/NierStrategy_Base.h +++ b/src/game/Nier/NierStrategies/NierStrategy_Base.h @@ -32,7 +32,7 @@ enum StrategyIndex :uint32 { StrategyIndex_Base = 0, StrategyIndex_The_Underbog = 546, - StrategyIndex_The_Black_Morass = 269, + StrategyIndex_The_Black_Morass = 269, }; enum BasicStrategyType :uint32 @@ -50,6 +50,7 @@ enum ActionType :uint32 ActionType_Revive = 2, ActionType_Move = 3, ActionType_ReadyTank = 4, + ActionType_Attack = 5, }; class NierStrategy_Base @@ -61,8 +62,8 @@ class NierStrategy_Base virtual void Reset(); virtual void Update(uint32 pmDiff); virtual bool Engage(Unit* pmTarget); - virtual bool TryTank(); - virtual bool DoTank(Unit* pmTarget); + virtual bool TryAttack(); + virtual bool DoTank(Unit* pmTarget, bool aoe); virtual bool TryDPS(bool pmDelay, bool pmForceInstantOnly, bool pmChasing); virtual bool DoDPS(Unit* pmTarget, bool pmForceInstantOnly, bool pmChasing); virtual bool Follow(); @@ -72,7 +73,6 @@ class NierStrategy_Base virtual bool Buff(); virtual bool Assist(); virtual uint32 Caution(); - virtual bool Revive(); virtual bool Revive(Unit* pmTarget); virtual bool Rest(bool pmForce = false); virtual bool Petting(); @@ -91,11 +91,11 @@ class NierStrategy_Base float followDistance; int randomTeleportDelay; - int assembleDelay; - int reviveDelay; + int assembleDelay; + int reviveDelay; int corpseRunDelay; int dpsDelay; - int wanderDelay; + int wanderDelay; int rti; int restLimit; @@ -106,10 +106,8 @@ class NierStrategy_Base uint32 basicStrategyType; bool cure; - bool aoe; bool rushing; bool petting; - bool forceBack; bool instantOnly; uint32 actionType; @@ -117,44 +115,11 @@ class NierStrategy_Base ObjectGuid ogActionTarget; ObjectGuid ogTank; ObjectGuid ogHealer; - uint32 vipEntry; - ObjectGuid ogVip; - int vipCheckDelay; + uint32 vipEntry; + ObjectGuid ogVip; + int vipCheckDelay; std::unordered_map> cautionSpellMap; std::unordered_set cautionPosSet; }; - - -class NierStrategy_The_Underbog :public NierStrategy_Base -{ -public: - NierStrategy_The_Underbog(); - -public: - bool hungarfen; -}; - -class NierStrategy_The_Black_Morass :public NierStrategy_Base -{ -public: - NierStrategy_The_Black_Morass(); - - bool DoDPS(Unit* pmTarget, bool pmForceInstantOnly, bool pmChasing); -}; - -class NierStrategy_Magisters_Terrace :public NierStrategy_Base -{ -public: - NierStrategy_Magisters_Terrace(); - - void Update(uint32 pmDiff); - bool TryTank(); - bool DoTank(Unit* pmTarget); - bool TryDPS(bool pmDelay, bool pmForceInstantOnly, bool pmChasing); - bool DoDPS(Unit* pmTarget, bool pmForceInstantOnly, bool pmChasing); - bool DoHeal(Unit* pmTarget, bool pmForceInstantOnly); - - bool kael; -}; #endif diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 2f767b705c2..6caa1e8c08e 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -3809,7 +3809,7 @@ void ObjectMgr::LoadItemPrototypes() { requiredLevel = item.ItemLevel; } - sNierManager->equipsMap[item.InventoryType][requiredLevel][sNierManager->equipsMap[item.InventoryType][requiredLevel].size()] = item.ItemId; + sNierManager->equipsMap[item.InventoryType][item.SubClass][requiredLevel][sNierManager->equipsMap[item.InventoryType][item.SubClass][requiredLevel].size()] = item.ItemId; } // lfm ming vendor equips diff --git a/src/game/Objects/Player.cpp b/src/game/Objects/Player.cpp index 9b5d52684d4..bffac6b7386 100644 --- a/src/game/Objects/Player.cpp +++ b/src/game/Objects/Player.cpp @@ -1760,7 +1760,7 @@ void Player::Update(uint32 update_diff, uint32 p_time) } // lfm auto fish - if (fishingDelay>0) + if (fishingDelay > 0) { fishingDelay -= p_time; if (fishingDelay <= 0) @@ -1770,7 +1770,20 @@ void Player::Update(uint32 update_diff, uint32 p_time) } } - // lfm nier + if (Group* myGroup = GetGroup()) + { + // leader will update group + if (myGroup->IsLeader(GetObjectGuid())) + { + if (myGroup->nierGroupStrategyMap.size() > 0) + { + if (myGroup->nierGroupStrategyMap[activeStrategyIndex]) + { + myGroup->nierGroupStrategyMap[activeStrategyIndex]->Update(p_time); + } + } + } + } if (m_session->isNier) { if (nierStrategyMap.size() > 0) diff --git a/src/game/Objects/Player.h b/src/game/Objects/Player.h index 57f86aa9387..a3f4025b49d 100644 --- a/src/game/Objects/Player.h +++ b/src/game/Objects/Player.h @@ -2006,9 +2006,9 @@ class Player final: public Unit uint16 GetHomeBindAreaId() const { return m_homebindAreaId; } // lfm nier - float GetHomeBindX() const { return m_homebindX; } - float GetHomeBindY() const { return m_homebindY; } - float GetHomeBindZ() const { return m_homebindZ; } + float GetHomeBindX() const { return m_homebind.x; } + float GetHomeBindY() const { return m_homebind.y; } + float GetHomeBindZ() const { return m_homebind.z; } void SendSummonRequest(ObjectGuid summonerGuid, uint32 mapId, uint32 zoneId, float x, float y, float z); void SetSummonPoint(uint32 mapid, float x, float y, float z)