diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 106 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 24 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 14 | ||||
-rw-r--r-- | src/server/game/Handlers/DuelHandler.cpp | 32 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/SpellEffects.cpp | 18 | ||||
-rw-r--r-- | src/server/scripts/World/achievement_scripts.cpp | 2 |
8 files changed, 96 insertions, 106 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 123a4e416ce..1d8f9073e3c 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2478,7 +2478,7 @@ ReputationRank WorldObject::GetReactionTo(WorldObject const* target) const return REP_FRIENDLY; // duel - always hostile to opponent - if (selfPlayerOwner->duel && selfPlayerOwner->duel->opponent == targetPlayerOwner && selfPlayerOwner->duel->startTime != 0) + if (selfPlayerOwner->duel && selfPlayerOwner->duel->Opponent == targetPlayerOwner && selfPlayerOwner->duel->State == DUEL_STATE_IN_PROGRESS) return REP_HOSTILE; // same group - checks dependant only on our faction - skip FFA_PVP for example @@ -2740,7 +2740,7 @@ bool WorldObject::IsValidAttackTarget(WorldObject const* target, SpellInfo const return false; if (playerAffectingAttacker && playerAffectingTarget) - if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->opponent == playerAffectingTarget && playerAffectingAttacker->duel->startTime != 0) + if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->Opponent == playerAffectingTarget && playerAffectingAttacker->duel->State == DUEL_STATE_IN_PROGRESS) return true; // PvP case - can't attack when attacker or target are in sanctuary diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 34bd02f261a..90795081b39 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -185,8 +185,6 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this) m_groupUpdateMask = 0; m_bPassOnGroupLoot = false; - duel = nullptr; - m_GuildIdInvited = UI64LIT(0); m_ArenaTeamIdInvited = 0; @@ -7369,11 +7367,11 @@ void Player::CheckDuelDistance(time_t currTime) if (!obj) return; - if (duel->outOfBound == 0) + if (!duel->OutOfBoundsTime) { if (!IsWithinDistInMap(obj, 50)) { - duel->outOfBound = currTime; + duel->OutOfBoundsTime = currTime + 10; SendDirectMessage(WorldPackets::Duel::DuelOutOfBounds().Write()); } @@ -7382,11 +7380,11 @@ void Player::CheckDuelDistance(time_t currTime) { if (IsWithinDistInMap(obj, 40)) { - duel->outOfBound = 0; + duel->OutOfBoundsTime = 0; SendDirectMessage(WorldPackets::Duel::DuelInBounds().Write()); } - else if (currTime >= (duel->outOfBound+10)) + else if (currTime >= duel->OutOfBoundsTime) DuelComplete(DUEL_FLED); } } @@ -7403,28 +7401,27 @@ void Player::DuelComplete(DuelCompleteType type) return; // Check if DuelComplete() has been called already up in the stack and in that case don't do anything else here - if (duel->isCompleted || ASSERT_NOTNULL(duel->opponent->duel)->isCompleted) + if (duel->State == DUEL_STATE_COMPLETED) return; - duel->isCompleted = true; - duel->opponent->duel->isCompleted = true; + Player* opponent = duel->Opponent; + duel->State = DUEL_STATE_COMPLETED; + opponent->duel->State = DUEL_STATE_COMPLETED; TC_LOG_DEBUG("entities.unit", "Player::DuelComplete: Player '%s' (%s), Opponent: '%s' (%s)", - GetName().c_str(), GetGUID().ToString().c_str(), duel->opponent->GetName().c_str(), duel->opponent->GetGUID().ToString().c_str()); + GetName().c_str(), GetGUID().ToString().c_str(), opponent->GetName().c_str(), opponent->GetGUID().ToString().c_str()); WorldPackets::Duel::DuelComplete duelCompleted; duelCompleted.Started = type != DUEL_INTERRUPTED; - WorldPacket const* duelCompletedPacket = duelCompleted.Write(); - SendDirectMessage(duelCompletedPacket); - - if (duel->opponent->GetSession()) - duel->opponent->SendDirectMessage(duelCompletedPacket); + SendDirectMessage(duelCompleted.Write()); + if (opponent->GetSession()) + opponent->SendDirectMessage(duelCompleted.GetRawPacket()); if (type != DUEL_INTERRUPTED) { WorldPackets::Duel::DuelWinner duelWinner; - duelWinner.BeatenName = (type == DUEL_WON ? duel->opponent->GetName() : GetName()); - duelWinner.WinnerName = (type == DUEL_WON ? GetName() : duel->opponent->GetName()); + duelWinner.BeatenName = (type == DUEL_WON ? opponent->GetName() : GetName()); + duelWinner.WinnerName = (type == DUEL_WON ? GetName() : opponent->GetName()); duelWinner.BeatenVirtualRealmAddress = GetVirtualRealmAddress(); duelWinner.WinnerVirtualRealmAddress = GetVirtualRealmAddress(); duelWinner.Fled = type != DUEL_WON; @@ -7432,40 +7429,40 @@ void Player::DuelComplete(DuelCompleteType type) SendMessageToSet(duelWinner.Write(), true); } - duel->opponent->DisablePvpRules(); + opponent->DisablePvpRules(); DisablePvpRules(); - sScriptMgr->OnPlayerDuelEnd(duel->opponent, this, type); + sScriptMgr->OnPlayerDuelEnd(opponent, this, type); switch (type) { case DUEL_FLED: // if initiator and opponent are on the same team // or initiator and opponent are not PvP enabled, forcibly stop attacking - if (duel->initiator->GetTeam() == duel->opponent->GetTeam()) + if (GetTeam() == opponent->GetTeam()) { - duel->initiator->AttackStop(); - duel->opponent->AttackStop(); + AttackStop(); + opponent->AttackStop(); } else { - if (!duel->initiator->IsPvP()) - duel->initiator->AttackStop(); - if (!duel->opponent->IsPvP()) - duel->opponent->AttackStop(); + if (!IsPvP()) + AttackStop(); + if (!opponent->IsPvP()) + opponent->AttackStop(); } break; case DUEL_WON: UpdateCriteria(CriteriaType::LoseDuel, 1); - duel->opponent->UpdateCriteria(CriteriaType::WinDuel, 1); + opponent->UpdateCriteria(CriteriaType::WinDuel, 1); // Credit for quest Death's Challenge - if (getClass() == CLASS_DEATH_KNIGHT && duel->opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE) - duel->opponent->CastSpell(duel->opponent, 52994, true); + if (getClass() == CLASS_DEATH_KNIGHT && opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE) + opponent->CastSpell(opponent, 52994, true); // Honor points after duel (the winner) - ImpConfig if (uint32 amount = sWorld->getIntConfig(CONFIG_HONOR_AFTER_DUEL)) - duel->opponent->RewardHonor(nullptr, 1, amount); + opponent->RewardHonor(nullptr, 1, amount); break; default: @@ -7474,20 +7471,20 @@ void Player::DuelComplete(DuelCompleteType type) // Victory emote spell if (type != DUEL_INTERRUPTED) - duel->opponent->CastSpell(duel->opponent, 52852, true); + opponent->CastSpell(opponent, 52852, true); //Remove Duel Flag object GameObject* obj = GetMap()->GetGameObject(m_playerData->DuelArbiter); if (obj) - duel->initiator->RemoveGameObject(obj, true); + duel->Initiator->RemoveGameObject(obj, true); /* remove auras */ - AuraApplicationMap &itsAuras = duel->opponent->GetAppliedAuras(); + AuraApplicationMap &itsAuras = opponent->GetAppliedAuras(); for (AuraApplicationMap::iterator i = itsAuras.begin(); i != itsAuras.end();) { Aura const* aura = i->second->GetBase(); - if (!i->second->IsPositive() && aura->GetCasterGUID() == GetGUID() && aura->GetApplyTime() >= duel->startTime) - duel->opponent->RemoveAura(i); + if (!i->second->IsPositive() && aura->GetCasterGUID() == GetGUID() && aura->GetApplyTime() >= duel->StartTime) + opponent->RemoveAura(i); else ++i; } @@ -7496,7 +7493,7 @@ void Player::DuelComplete(DuelCompleteType type) for (AuraApplicationMap::iterator i = myAuras.begin(); i != myAuras.end();) { Aura const* aura = i->second->GetBase(); - if (!i->second->IsPositive() && aura->GetCasterGUID() == duel->opponent->GetGUID() && aura->GetApplyTime() >= duel->startTime) + if (!i->second->IsPositive() && aura->GetCasterGUID() == opponent->GetGUID() && aura->GetApplyTime() >= duel->StartTime) RemoveAura(i); else ++i; @@ -7504,18 +7501,16 @@ void Player::DuelComplete(DuelCompleteType type) // cleanup combo points ClearComboPoints(); - duel->opponent->ClearComboPoints(); + opponent->ClearComboPoints(); //cleanups SetDuelArbiter(ObjectGuid::Empty); SetDuelTeam(0); - duel->opponent->SetDuelArbiter(ObjectGuid::Empty); - duel->opponent->SetDuelTeam(0); + opponent->SetDuelArbiter(ObjectGuid::Empty); + opponent->SetDuelTeam(0); - delete duel->opponent->duel; - duel->opponent->duel = nullptr; - delete duel; - duel = nullptr; + opponent->duel.reset(nullptr); + duel.reset(nullptr); } //---------------------------------------------------------// @@ -21754,7 +21749,7 @@ void Player::UpdateAfkReport(time_t currTime) void Player::SetContestedPvP(Player* attackedPlayer) { - if (attackedPlayer && (attackedPlayer == this || (duel && duel->opponent == attackedPlayer))) + if (attackedPlayer && (attackedPlayer == this || (duel && duel->Opponent == attackedPlayer))) return; SetContestedPvPTimer(30000); @@ -21808,18 +21803,16 @@ void Player::UpdatePvPFlag(time_t currTime) void Player::UpdateDuelFlag(time_t currTime) { - if (!duel || duel->startTimer == 0 ||currTime < duel->startTimer + 3) - return; - - sScriptMgr->OnPlayerDuelStart(this, duel->opponent); + if (duel && duel->State == DUEL_STATE_COUNTDOWN && duel->StartTime <= currTime) + { + sScriptMgr->OnPlayerDuelStart(this, duel->Opponent); - SetDuelTeam(1); - duel->opponent->SetDuelTeam(2); + SetDuelTeam(1); + duel->Opponent->SetDuelTeam(2); - duel->startTimer = 0; - duel->startTime = currTime; - duel->opponent->duel->startTimer = 0; - duel->opponent->duel->startTime = currTime; + duel->State = DUEL_STATE_IN_PROGRESS; + duel->Opponent->duel->State = DUEL_STATE_IN_PROGRESS; + } } Pet* Player::GetPet() const @@ -23926,9 +23919,12 @@ bool Player::IsAlwaysDetectableFor(WorldObject const* seer) const if (Unit::IsAlwaysDetectableFor(seer)) return true; + if (duel && duel->State != DUEL_STATE_CHALLENGED && duel->Opponent == seer) + return false; + if (Player const* seerPlayer = seer->ToPlayer()) if (IsGroupVisibleFor(seerPlayer)) - return !(seerPlayer->duel && seerPlayer->duel->startTime != 0 && seerPlayer->duel->opponent == this); + return true; return false; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 2f1c19b1fa2..0fed004033e 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -377,17 +377,23 @@ struct PvPInfo time_t EndTimer; ///> Time when player unflags himself for PvP (flag removed after 5 minutes) }; +enum DuelState +{ + DUEL_STATE_CHALLENGED, + DUEL_STATE_COUNTDOWN, + DUEL_STATE_IN_PROGRESS, + DUEL_STATE_COMPLETED +}; struct DuelInfo { - DuelInfo() : initiator(nullptr), opponent(nullptr), startTimer(0), startTime(0), outOfBound(0), isMounted(false), isCompleted(false) { } + DuelInfo(Player* opponent, Player* initiator, bool isMounted) : Opponent(opponent), Initiator(initiator), IsMounted(isMounted) {} - Player* initiator; - Player* opponent; - time_t startTimer; - time_t startTime; - time_t outOfBound; - bool isMounted; - bool isCompleted; + Player* const Opponent; + Player* const Initiator; + bool const IsMounted; + DuelState State = DUEL_STATE_CHALLENGED; + time_t StartTime = 0; + time_t OutOfBoundsTime = 0; }; struct Areas @@ -1892,7 +1898,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void ResetContestedPvP(); /// @todo: maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler - DuelInfo* duel; + std::unique_ptr<DuelInfo> duel; void UpdateDuelFlag(time_t currTime); void CheckDuelDistance(time_t currTime); void DuelComplete(DuelCompleteType type); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 4134cd66b35..0e6c41c1b9f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -767,7 +767,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons return 0; // prevent kill only if killed in duel and killed by opponent or opponent controlled creature - if (victim->ToPlayer()->duel->opponent == attacker->GetControllingPlayer()) + if (victim->ToPlayer()->duel->Opponent == attacker->GetControllingPlayer()) damage = health - 1; duel_hasEnded = true; @@ -776,13 +776,13 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons { Player* victimRider = victim->GetCharmer()->ToPlayer(); - if (victimRider && victimRider->duel && victimRider->duel->isMounted) + if (victimRider && victimRider->duel && victimRider->duel->IsMounted) { if (!attacker) return 0; // prevent kill only if killed in duel and killed by opponent or opponent controlled creature - if (victimRider->duel->opponent == attacker->GetControllingPlayer()) + if (victimRider->duel->Opponent == attacker->GetControllingPlayer()) damage = health - 1; duel_wasMounted = true; @@ -994,7 +994,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons else he->SetHealth(1); - he->duel->opponent->CombatStopWithPets(true); + he->duel->Opponent->CombatStopWithPets(true); he->CombatStopWithPets(true); he->CastSpell(he, 7267, true); // beg @@ -7711,7 +7711,7 @@ void Unit::AttackedTarget(Unit* target, bool canInitialAggro) Player* myPlayerOwner = GetCharmerOrOwnerPlayerOrPlayerItself(); Player* targetPlayerOwner = target->GetCharmerOrOwnerPlayerOrPlayerItself(); - if (myPlayerOwner && targetPlayerOwner && !(myPlayerOwner->duel && myPlayerOwner->duel->opponent == targetPlayerOwner)) + if (myPlayerOwner && targetPlayerOwner && !(myPlayerOwner->duel && myPlayerOwner->duel->Opponent == targetPlayerOwner)) { myPlayerOwner->UpdatePvP(true); myPlayerOwner->SetContestedPvP(targetPlayerOwner); @@ -10473,7 +10473,7 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId) // last damage from non duel opponent or opponent controlled creature if (plrVictim->duel) { - plrVictim->duel->opponent->CombatStopWithPets(true); + plrVictim->duel->Opponent->CombatStopWithPets(true); plrVictim->CombatStopWithPets(true); plrVictim->DuelComplete(DUEL_INTERRUPTED); } @@ -11898,7 +11898,7 @@ void Unit::_ExitVehicle(Position const* exitPosition) Player* player = ToPlayer(); // If the player is on mounted duel and exits the mount, he should immediatly lose the duel - if (player && player->duel && player->duel->isMounted) + if (player && player->duel && player->duel->IsMounted) player->DuelComplete(DUEL_FLED); SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT diff --git a/src/server/game/Handlers/DuelHandler.cpp b/src/server/game/Handlers/DuelHandler.cpp index aa40d210cc6..fae16dc5f64 100644 --- a/src/server/game/Handlers/DuelHandler.cpp +++ b/src/server/game/Handlers/DuelHandler.cpp @@ -50,49 +50,49 @@ void WorldSession::HandleCanDuel(WorldPackets::Duel::CanDuel& packet) void WorldSession::HandleDuelResponseOpcode(WorldPackets::Duel::DuelResponse& duelResponse) { if (duelResponse.Accepted && !duelResponse.Forfeited) - HandleDuelAccepted(); + HandleDuelAccepted(duelResponse.ArbiterGUID); else HandleDuelCancelled(); } -void WorldSession::HandleDuelAccepted() +void WorldSession::HandleDuelAccepted(ObjectGuid arbiterGuid) { - if (!GetPlayer()->duel) // ignore accept from duel-sender - return; - Player* player = GetPlayer(); - Player* plTarget = player->duel->opponent; + if (!player->duel || player == player->duel->Initiator || player->duel->State != DUEL_STATE_CHALLENGED) + return; - if (player == player->duel->initiator || !plTarget || player == plTarget || player->duel->startTime != 0 || plTarget->duel->startTime != 0) + Player* target = player->duel->Opponent; + if (*target->m_playerData->DuelArbiter != arbiterGuid) return; TC_LOG_DEBUG("network", "Player 1 is: %s (%s)", player->GetGUID().ToString().c_str(), player->GetName().c_str()); - TC_LOG_DEBUG("network", "Player 2 is: %s (%s)", plTarget->GetGUID().ToString().c_str(), plTarget->GetName().c_str()); + TC_LOG_DEBUG("network", "Player 2 is: %s (%s)", target->GetGUID().ToString().c_str(), target->GetName().c_str()); time_t now = GameTime::GetGameTime(); - player->duel->startTimer = now; - plTarget->duel->startTimer = now; + player->duel->StartTime = now + 3; + target->duel->StartTime = now + 3; WorldPackets::Duel::DuelCountdown packet(3000); // milliseconds WorldPacket const* worldPacket = packet.Write(); player->GetSession()->SendPacket(worldPacket); - plTarget->GetSession()->SendPacket(worldPacket); + target->GetSession()->SendPacket(worldPacket); player->EnablePvpRules(); - plTarget->EnablePvpRules(); + target->EnablePvpRules(); } void WorldSession::HandleDuelCancelled() { + Player* player = GetPlayer(); + // no duel requested - if (!GetPlayer()->duel) + if (!player->duel || player->duel->State == DUEL_STATE_COMPLETED) return; // player surrendered in a duel using /forfeit - if (GetPlayer()->duel->startTime != 0) + if (GetPlayer()->duel->State == DUEL_STATE_IN_PROGRESS) { GetPlayer()->CombatStopWithPets(true); - if (GetPlayer()->duel->opponent) - GetPlayer()->duel->opponent->CombatStopWithPets(true); + GetPlayer()->duel->Opponent->CombatStopWithPets(true); GetPlayer()->CastSpell(GetPlayer(), 7267, true); // beg GetPlayer()->DuelComplete(DUEL_WON); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 36f2c6a03de..8f987ff0e4b 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -1384,7 +1384,7 @@ class TC_GAME_API WorldSession void HandleCanDuel(WorldPackets::Duel::CanDuel& packet); void HandleDuelResponseOpcode(WorldPackets::Duel::DuelResponse& duelResponse); - void HandleDuelAccepted(); + void HandleDuelAccepted(ObjectGuid arbiterGuid); void HandleDuelCancelled(); void HandleAcceptTradeOpcode(WorldPackets::Trade::AcceptTrade& acceptTrade); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index c43f441dd6c..2560a6d94c2 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3579,21 +3579,9 @@ void Spell::EffectDuel() target->SendDirectMessage(worldPacket); // create duel-info - DuelInfo* duel = new DuelInfo; - duel->initiator = caster; - duel->opponent = target; - duel->startTime = 0; - duel->startTimer = 0; - duel->isMounted = (GetSpellInfo()->Id == 62875); // Mounted Duel - caster->duel = duel; - - DuelInfo* duel2 = new DuelInfo; - duel2->initiator = caster; - duel2->opponent = caster; - duel2->startTime = 0; - duel2->startTimer = 0; - duel2->isMounted = (GetSpellInfo()->Id == 62875); // Mounted Duel - target->duel = duel2; + bool isMounted = (GetSpellInfo()->Id == 62875); + caster->duel = std::make_unique<DuelInfo>(target, caster, isMounted); + target->duel = std::make_unique<DuelInfo>(caster, caster, isMounted); caster->SetDuelArbiter(go->GetGUID()); target->SetDuelArbiter(go->GetGUID()); diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp index e5f32b122ad..62a7621db79 100644 --- a/src/server/scripts/World/achievement_scripts.cpp +++ b/src/server/scripts/World/achievement_scripts.cpp @@ -236,7 +236,7 @@ class achievement_tilted : public AchievementCriteriaScript player->GetAreaId() == AREA_RING_OF_HORDE_VALIANTS || player->GetAreaId() == AREA_RING_OF_CHAMPIONS; - return checkArea && player->duel && player->duel->isMounted; + return checkArea && player->duel && player->duel->IsMounted; } }; |