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 | 109 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 25 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 14 | ||||
-rw-r--r-- | src/server/game/Handlers/DuelHandler.cpp | 36 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 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, 99 insertions, 111 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 1335976ec8b..9d4523216ed 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -2660,7 +2660,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 @@ -2938,7 +2938,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 1f0cc2b8911..48b17451f6d 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -215,8 +215,6 @@ Player::Player(WorldSession* session): Unit(true) m_auraRaidUpdateMask = 0; m_bPassOnGroupLoot = false; - duel = nullptr; - m_GuildIdInvited = 0; m_ArenaTeamIdInvited = 0; @@ -7104,11 +7102,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; WorldPacket data(SMSG_DUEL_OUTOFBOUNDS, 0); SendDirectMessage(&data); @@ -7118,12 +7116,12 @@ void Player::CheckDuelDistance(time_t currTime) { if (IsWithinDistInMap(obj, 40)) { - duel->outOfBound = 0; + duel->OutOfBoundsTime = 0; WorldPacket data(SMSG_DUEL_INBOUNDS, 0); SendDirectMessage(&data); } - else if (currTime >= (duel->outOfBound+10)) + else if (currTime >= duel->OutOfBoundsTime) DuelComplete(DUEL_FLED); } } @@ -7140,62 +7138,62 @@ 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()); WorldPacket data(SMSG_DUEL_COMPLETE, (1)); - data << (uint8)((type != DUEL_INTERRUPTED) ? 1 : 0); + data << uint8((type != DUEL_INTERRUPTED) ? 1 : 0); SendDirectMessage(&data); - - if (duel->opponent->GetSession()) - duel->opponent->SendDirectMessage(&data); + if (opponent->GetSession()) + opponent->SendDirectMessage(&data); if (type != DUEL_INTERRUPTED) { data.Initialize(SMSG_DUEL_WINNER, (1+20)); // we guess size data << uint8(type == DUEL_WON ? 0 : 1); // 0 = just won; 1 = fled - data << duel->opponent->GetName(); + data << opponent->GetName(); data << GetName(); SendMessageToSet(&data, true); } - 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: UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1); - duel->opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1); + opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 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: @@ -7204,20 +7202,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(GetGuidValue(PLAYER_DUEL_ARBITER)); 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; } @@ -7226,33 +7224,27 @@ 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; } // cleanup combo points - if (GetComboTarget() == duel->opponent) - ClearComboPoints(); - else if (GetComboTargetGUID() == duel->opponent->GetPetGUID()) + if (GetComboTarget() && GetComboTarget()->GetControllingPlayer() == opponent) ClearComboPoints(); - if (duel->opponent->GetComboTarget() == this) - duel->opponent->ClearComboPoints(); - else if (duel->opponent->GetComboTargetGUID() == GetPetGUID()) - duel->opponent->ClearComboPoints(); + if (opponent->GetComboTarget() && opponent->GetComboTarget()->GetControllingPlayer() == this) + opponent->ClearComboPoints(); //cleanups SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty); SetUInt32Value(PLAYER_DUEL_TEAM, 0); - duel->opponent->SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty); - duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 0); + opponent->SetGuidValue(PLAYER_DUEL_ARBITER, ObjectGuid::Empty); + opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 0); - delete duel->opponent->duel; - duel->opponent->duel = nullptr; - delete duel; - duel = nullptr; + opponent->duel.reset(nullptr); + duel.reset(nullptr); } //---------------------------------------------------------// @@ -20354,7 +20346,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); @@ -20408,18 +20400,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); - SetUInt32Value(PLAYER_DUEL_TEAM, 1); - duel->opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 2); + SetUInt32Value(PLAYER_DUEL_TEAM, 1); + duel->Opponent->SetUInt32Value(PLAYER_DUEL_TEAM, 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 @@ -22150,9 +22140,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 c6b8511c7ee..14f252b2cce 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -30,6 +30,7 @@ #include "PetDefines.h" #include "PlayerTaxi.h" #include "QuestDef.h" +#include <memory> #include <queue> struct AccessRequirement; @@ -232,17 +233,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 @@ -1512,7 +1519,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 53b663aaa61..45a9d4b35d3 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -760,7 +760,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; @@ -769,13 +769,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; @@ -895,7 +895,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 @@ -8185,7 +8185,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); @@ -10927,7 +10927,7 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id) // 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); } @@ -12541,7 +12541,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 edbf1d9fdc8..902090750ff 100644 --- a/src/server/game/Handlers/DuelHandler.cpp +++ b/src/server/game/Handlers/DuelHandler.cpp @@ -25,49 +25,49 @@ void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket) { - ObjectGuid guid; - Player* player; - Player* plTarget; - - recvPacket >> guid; - - if (!GetPlayer()->duel) // ignore accept from duel-sender + Player* player = GetPlayer(); + if (!player->duel || player == player->duel->Initiator || player->duel->State != DUEL_STATE_CHALLENGED) return; - player = GetPlayer(); - plTarget = player->duel->opponent; + ObjectGuid guid; + recvPacket >> guid; - if (player == player->duel->initiator || !plTarget || player == plTarget || player->duel->startTime != 0 || plTarget->duel->startTime != 0) + Player* target = player->duel->Opponent; + if (target->GetGuidValue(PLAYER_DUEL_ARBITER) != guid) return; //TC_LOG_DEBUG("network", "WORLD: Received CMSG_DUEL_ACCEPTED"); TC_LOG_DEBUG("network", "Player 1 is: %u (%s)", player->GetGUID().GetCounter(), player->GetName().c_str()); - TC_LOG_DEBUG("network", "Player 2 is: %u (%s)", plTarget->GetGUID().GetCounter(), plTarget->GetName().c_str()); + TC_LOG_DEBUG("network", "Player 2 is: %u (%s)", target->GetGUID().GetCounter(), 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; + + player->duel->State = DUEL_STATE_COUNTDOWN; + target->duel->State = DUEL_STATE_COUNTDOWN; player->SendDuelCountdown(3000); - plTarget->SendDuelCountdown(3000); + target->SendDuelCountdown(3000); } void WorldSession::HandleDuelCancelledOpcode(WorldPacket& recvPacket) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_DUEL_CANCELLED"); + Player* player = GetPlayer(); + ObjectGuid guid; recvPacket >> guid; // 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/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index ea26f14c5a7..e6955b24382 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5342,7 +5342,7 @@ SpellCastResult Spell::CheckCast(bool strict, uint32* param1 /*= nullptr*/, uint { // fix for duels Player* player = unitCaster->ToPlayer(); - if (!player || !player->duel || target != player->duel->opponent) + if (!player || !player->duel || target != player->duel->Opponent) return SPELL_FAILED_NOTHING_TO_DISPEL; } } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 55c9df76914..2b318d165b1 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -4068,21 +4068,9 @@ void Spell::EffectDuel(SpellEffIndex effIndex) target->SendDirectMessage(&data); // 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->SetGuidValue(PLAYER_DUEL_ARBITER, pGameObj->GetGUID()); target->SetGuidValue(PLAYER_DUEL_ARBITER, pGameObj->GetGUID()); diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp index 98414ee89af..5f895243c0f 100644 --- a/src/server/scripts/World/achievement_scripts.cpp +++ b/src/server/scripts/World/achievement_scripts.cpp @@ -237,7 +237,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; } }; |