From 093f3c659d25549a6e76dc0bb7dfaff4fe934185 Mon Sep 17 00:00:00 2001 From: moJItoz Date: Sun, 19 Aug 2018 20:43:56 +0300 Subject: [PATCH] Core/Garrisons Fixes (#71) --- src/server/game/Garrison/Garrison.cpp | 71 +++++++++---------- src/server/game/Garrison/GarrisonConstants.h | 21 +++--- src/server/game/Garrison/GarrisonMgr.cpp | 8 +-- .../game/Garrison/WodGarrison/WodGarrison.cpp | 14 ++-- .../game/Garrison/WodGarrison/WodGarrison.h | 2 +- .../game/Server/Packets/GarrisonPackets.cpp | 4 +- .../game/Server/Packets/GarrisonPackets.h | 32 ++++----- 7 files changed, 77 insertions(+), 75 deletions(-) diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp index f9e866a8108d4..9064d25d5372d 100644 --- a/src/server/game/Garrison/Garrison.cpp +++ b/src/server/game/Garrison/Garrison.cpp @@ -32,9 +32,9 @@ #include "ScriptMgr.h" #include "VehicleDefines.h" -Garrison::Garrison(Player* owner) : _owner(owner), _siteLevel(nullptr), _followerActivationsRemainingToday(1) +Garrison::Garrison(Player* owner) : _garrisonType(), _owner(owner), _siteLevel(nullptr), _followerActivationsRemainingToday(1) { - _timers[GUPDATE_MISSIONS_DISTRIBUTION].SetInterval(MINUTE*IN_MILLISECONDS); + _timers[GUPDATE_MISSIONS_DISTRIBUTION].SetInterval(MINUTE * IN_MILLISECONDS); } bool Garrison::Create(uint32 garrSiteId) @@ -56,12 +56,12 @@ bool Garrison::Create(uint32 garrSiteId) void Garrison::Update(uint32 const diff) { // Update the different timers - for (uint8 i = 0; i < GUPDATE_COUNT; ++i) + for (auto& _timer : _timers) { - if (_timers[i].GetCurrent() >= 0) - _timers[i].Update(diff); + if (_timer.GetCurrent() >= 0) + _timer.Update(diff); else - _timers[i].SetCurrent(0); + _timer.SetCurrent(0); } if (_timers[GUPDATE_MISSIONS_DISTRIBUTION].Passed()) @@ -314,7 +314,7 @@ void Garrison::SaveToDB(SQLTransaction& trans) void Garrison::DeleteFromDB(SQLTransaction& trans) { - Garrison::DeleteFromDB(trans, _owner->GetGUID().GetCounter(), GetType()); + DeleteFromDB(trans, _owner->GetGUID().GetCounter(), GetType()); } void Garrison::DeleteFromDB(SQLTransaction& trans, ObjectGuid::LowType guid, GarrisonType garrType) @@ -391,7 +391,7 @@ void Garrison::AI_Destroy() void Garrison::AddFollower(uint32 garrFollowerId) { WorldPackets::Garrison::GarrisonAddFollowerResult addFollowerResult; - addFollowerResult.GarrTypeID = (int32)_garrisonType; + addFollowerResult.GarrTypeID = _garrisonType; GarrFollowerEntry const* followerEntry = sGarrFollowerStore.LookupEntry(garrFollowerId); if (_followerIds.count(garrFollowerId) || !followerEntry) { @@ -409,12 +409,7 @@ void Garrison::AddFollower(uint32 garrFollowerId) follower.PacketInfo.FollowerLevel = followerEntry->FollowerLevel; follower.PacketInfo.ItemLevelWeapon = followerEntry->ItemLevelWeapon; follower.PacketInfo.ItemLevelArmor = followerEntry->ItemLevelArmor; - follower.PacketInfo.Xp = 0; - follower.PacketInfo.CurrentBuildingID = 0; - follower.PacketInfo.CurrentMissionID = 0; follower.PacketInfo.AbilityID = sGarrisonMgr.RollFollowerAbilities(garrFollowerId, followerEntry, follower.PacketInfo.Quality, GetFaction(), true); - follower.PacketInfo.FollowerStatus = 0; - addFollowerResult.Follower = follower.PacketInfo; _owner->SendDirectMessage(addFollowerResult.Write()); @@ -483,11 +478,7 @@ void Garrison::AddMission(uint32 garrMissionId) mission.PacketInfo.MissionRecID = garrMissionId; mission.PacketInfo.OfferTime = time(nullptr); mission.PacketInfo.OfferDuration = missionEntry->OfferTime; - mission.PacketInfo.StartTime = time_t(2254525440); - mission.PacketInfo.TravelDuration = missionEntry->TravelTime; - mission.PacketInfo.MissionDuration = missionEntry->Duration; - mission.PacketInfo.MissionState = 0; - mission.PacketInfo.SuccessChance = 0; + mission.PacketInfo.MissionState = GarrisonMission::State::Offered; mission.PacketInfo.Unknown2 = 1; // TODO : Generate rewards for mission @@ -504,7 +495,7 @@ void Garrison::AddMission(uint32 garrMissionId) WorldPackets::Garrison::GarrisonAddMissionResult garrisonAddMissionResult; garrisonAddMissionResult.GarrType = GetType(); garrisonAddMissionResult.Result = GarrisonMission::Result::Success; - garrisonAddMissionResult.State = GarrisonMission::State::Available; + garrisonAddMissionResult.State = GarrisonMission::State::Offered; garrisonAddMissionResult.Mission = mission.PacketInfo; garrisonAddMissionResult.Rewards = mission.Rewards; garrisonAddMissionResult.BonusRewards = mission.BonusRewards; @@ -541,7 +532,7 @@ void Garrison::DeleteMission(uint64 dbId) std::vector Garrison::GetMissionFollowers(uint32 garrMissionId) { - std::vector missionFollowers; + std::vector missionFollowers; for (auto followerItr : _followers) if (followerItr.second.PacketInfo.CurrentMissionID == garrMissionId) missionFollowers.push_back(&followerItr.second); @@ -564,7 +555,7 @@ std::pair, std::vector> Garrison::G uint32 const maxFollowerlevel = GetMaxFollowerLevel(); uint32 const activeFolowerCount = GetActiveFollowersCount(); - uint32 const averageFollowerILevel = GetAverageFollowerILevel(); + //uint32 const averageFollowerILevel = GetAverageFollowerILevel(); for (uint32 i = 0; i < sGarrMissionStore.GetNumRows(); ++i) { @@ -589,8 +580,8 @@ std::pair, std::vector> Garrison::G if (missionEntry->RequiredFollowersCount > activeFolowerCount) continue; - if (missionEntry->RequiredItemLevel > averageFollowerILevel) - continue; + //if (missionEntry->RequiredItemLevel > averageFollowerILevel) + // continue; uint32 requiredClass = sGarrisonMgr.GetClassByMissionType(missionEntry->MissionType); if (requiredClass != CLASS_NONE && requiredClass != _owner->getClass()) @@ -601,7 +592,7 @@ std::pair, std::vector> Garrison::G continue; double weight = 100.0; - if (missionEntry->Flags & GarrisonMission::Flags::Rare) + if (missionEntry->Flags & GarrisonMission::Flags::isRare) weight = 25.0; availableMissions.push_back(missionEntry); @@ -614,12 +605,10 @@ std::pair, std::vector> Garrison::G void Garrison::GenerateMissions() { uint32 maxMissionCount = ceil(GetActiveFollowersCount() * GARRISON_MISSION_DISTRIB_FOLLOWER_COEFF); - if (GetMissions().size() >= maxMissionCount) return; uint32 missionToAddCount = urand(0, maxMissionCount - GetMissions().size()); - if (!missionToAddCount) return; @@ -653,31 +642,40 @@ void Garrison::StartMission(uint32 garrMissionId, std::vector F if (!missionEntry) return SendStartMissionResult(false); - Garrison::Mission* mission = GetMissionByID(missionEntry->ID); + Mission* mission = GetMissionByID(missionEntry->ID); if (!mission) return SendStartMissionResult(false); + if (missionEntry->CurrencyCost && !_owner->HasCurrency(missionEntry->CurrencyID, missionEntry->CurrencyCost)) + return SendStartMissionResult(false); // GARRISON_ERROR_NOT_ENOUGH_CURRENCY + + mission->PacketInfo.TravelDuration = missionEntry->TravelTime; + mission->PacketInfo.MissionDuration = missionEntry->Duration; mission->PacketInfo.StartTime = time(nullptr); mission->PacketInfo.MissionState = GarrisonMission::State::InProgress; mission->PacketInfo.SuccessChance = sGarrisonMgr.GetMissionSuccessChance(this, mission->PacketInfo.MissionRecID); for (uint64 followerDbID : Followers) { - Garrison::Follower* follower = GetFollower(followerDbID); - + Follower* follower = GetFollower(followerDbID); if (!follower) return SendStartMissionResult(false); if (follower->PacketInfo.CurrentMissionID != 0 || follower->PacketInfo.CurrentBuildingID != 0) return SendStartMissionResult(false); + if (follower->PacketInfo.FollowerStatus == FOLLOWER_STATUS_INACTIVE) + return SendStartMissionResult(false); + follower->PacketInfo.CurrentMissionID = missionEntry->ID; } + _owner->ModifyCurrency(missionEntry->CurrencyID, -static_cast(missionEntry->CurrencyCost)); + SendStartMissionResult(true, mission, &Followers); } -void Garrison::SendStartMissionResult(bool success, Garrison::Mission* mission /*= nullptr*/, std::vector* Followers /*= nullptr*/) +void Garrison::SendStartMissionResult(bool success, Mission* mission /*= nullptr*/, std::vector* Followers /*= nullptr*/) { WorldPackets::Garrison::GarrisonStartMissionResult garrisonStartMissionResult; @@ -701,7 +699,7 @@ void Garrison::CompleteMission(uint32 garrMissionId) if (!missionEntry) return; - Garrison::Mission* mission = GetMissionByID(missionEntry->ID); + Mission* mission = GetMissionByID(missionEntry->ID); if (!mission) return; @@ -710,12 +708,11 @@ void Garrison::CompleteMission(uint32 garrMissionId) if (canComplete) { - std::vector followers = GetMissionFollowers(missionEntry->ID); - if (followers.empty()) + if (GetMissionFollowers(missionEntry->ID).empty()) return; success = roll_chance_i(mission->PacketInfo.SuccessChance); - mission->PacketInfo.MissionState = success ? GarrisonMission::State::CompleteSuccess : GarrisonMission::State::CompleteFailed; + mission->PacketInfo.MissionState = success ? GarrisonMission::State::Completed : GarrisonMission::State::Reward2Claimed; } WorldPackets::Garrison::GarrisonCompleteMissionResult garrisonCompleteMissionResult; @@ -731,7 +728,7 @@ void Garrison::CalculateMissonBonusRoll(uint32 garrMissionId) if (!missionEntry) return; - Garrison::Mission* mission = GetMissionByID(missionEntry->ID); + Mission* mission = GetMissionByID(missionEntry->ID); if (!mission) return; @@ -767,8 +764,8 @@ void Garrison::RewardMission(Mission* mission, bool withOvermaxReward) if (reward.FollowerXP) { - std::vector followers = GetMissionFollowers(mission->PacketInfo.MissionRecID); - for (Garrison::Follower* follower : followers) + std::vector followers = GetMissionFollowers(mission->PacketInfo.MissionRecID); + for (Follower* follower : followers) follower->EarnXP(GetOwner(), reward.FollowerXP); } diff --git a/src/server/game/Garrison/GarrisonConstants.h b/src/server/game/Garrison/GarrisonConstants.h index 37abb4299ad64..224dca7b90d7b 100644 --- a/src/server/game/Garrison/GarrisonConstants.h +++ b/src/server/game/Garrison/GarrisonConstants.h @@ -39,7 +39,7 @@ enum GarrisonSite GARRISON_SITE_CLASS_HALL_HORDE = 163, }; -enum GarrisonType +enum GarrisonType : int32 { GARRISON_TYPE_NONE = 0, GARRISON_TYPE_GARRISON = 2, @@ -212,10 +212,13 @@ namespace GarrisonMission { enum State { - Available = 0, - InProgress = 1, - CompleteSuccess = 2, - CompleteFailed = 5 + Offered = 0, + InProgress = 1, + Completed = 2, + OvermaxRewardPending = 3, + Reward1Claimed = 4, + Reward2Claimed = 5, + Reward3Claimed = 6, }; enum Type @@ -284,9 +287,11 @@ namespace GarrisonMission enum Flags { - Rare = 0x01, - Unk2 = 0x02, - Exhausting = 0x04 + isRare = 0x01, + isElite = 0x02, + appliesFatigue = 0x04, + alwaysFail = 0x08, + isZoneSupport = 0x10, }; enum BonusRollResults diff --git a/src/server/game/Garrison/GarrisonMgr.cpp b/src/server/game/Garrison/GarrisonMgr.cpp index da8dac994fd2d..7d1ed3f388213 100644 --- a/src/server/game/Garrison/GarrisonMgr.cpp +++ b/src/server/game/Garrison/GarrisonMgr.cpp @@ -762,9 +762,9 @@ uint32 GarrisonMgr::GetClassByMissionType(uint32 missionType) case GarrisonMission::Type::ArtifactPriest: return CLASS_PRIEST; case GarrisonMission::Type::ArtifactDeathKnight: return CLASS_DEATH_KNIGHT; case GarrisonMission::Type::ArtifactWarrior: return CLASS_WARRIOR; + default: + return CLASS_NONE; } - - return CLASS_NONE; } uint32 GarrisonMgr::GetFactionByMissionType(uint32 missionType) @@ -773,9 +773,9 @@ uint32 GarrisonMgr::GetFactionByMissionType(uint32 missionType) { case GarrisonMission::Type::ZoneSupportAlliance: return TEAM_ALLIANCE; case GarrisonMission::Type::ZoneSupportHorde: return TEAM_HORDE; + default: + return TEAM_OTHER; } - - return TEAM_OTHER; } void GarrisonMgr::InitializeDbIdSequences() diff --git a/src/server/game/Garrison/WodGarrison/WodGarrison.cpp b/src/server/game/Garrison/WodGarrison/WodGarrison.cpp index d03f2836fd3ad..59e3ca77cedd4 100644 --- a/src/server/game/Garrison/WodGarrison/WodGarrison.cpp +++ b/src/server/game/Garrison/WodGarrison/WodGarrison.cpp @@ -278,10 +278,7 @@ bool WodGarrison::IsAllowedArea(AreaTableEntry const* area) const break; } - if (area->Flags[1] & AREA_FLAG_GARRISON && area->ContinentID == MAP_DRAENOR) - return true; - - return false; + return area->Flags[1] & AREA_FLAG_GARRISON && area->ContinentID == MAP_DRAENOR; } std::vector WodGarrison::GetPlots() @@ -466,6 +463,11 @@ void WodGarrison::ActivateBuilding(uint32 garrPlotInstanceId) } } +std::unordered_set const& WodGarrison::GetKnownBuildings() const +{ + return _knownBuildings; +} + void WodGarrison::SendBuildingLandmarks(Player* receiver) const { WorldPackets::Garrison::GarrisonBuildingLandmarks buildingLandmarks; @@ -508,13 +510,11 @@ GarrisonError WodGarrison::CheckBuildingPlacement(uint32 garrPlotInstanceId, uin else // Building is built as a quest reward return GARRISON_ERROR_INVALID_BUILDINGID; - // Check all plots to find if we already have this building - GarrBuildingEntry const* existingBuilding; for (auto const& p : _plots) { if (p.second.BuildingInfo.PacketInfo) { - existingBuilding = sGarrBuildingStore.AssertEntry(p.second.BuildingInfo.PacketInfo->GarrBuildingID); + GarrBuildingEntry const* existingBuilding = sGarrBuildingStore.AssertEntry(p.second.BuildingInfo.PacketInfo->GarrBuildingID); if (existingBuilding->BuildingType == building->BuildingType) if (p.first != garrPlotInstanceId || existingBuilding->UpgradeLevel + 1 != building->UpgradeLevel) // check if its an upgrade in same plot return GARRISON_ERROR_BUILDING_EXISTS; diff --git a/src/server/game/Garrison/WodGarrison/WodGarrison.h b/src/server/game/Garrison/WodGarrison/WodGarrison.h index cc344765302a3..0dbf93953feb2 100644 --- a/src/server/game/Garrison/WodGarrison/WodGarrison.h +++ b/src/server/game/Garrison/WodGarrison/WodGarrison.h @@ -103,7 +103,7 @@ class TC_GAME_API WodGarrison : public Garrison void PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId); void CancelBuildingConstruction(uint32 garrPlotInstanceId); void ActivateBuilding(uint32 garrPlotInstanceId); - std::unordered_set const& GetKnownBuildings() const { return _knownBuildings; } + std::unordered_set const& GetKnownBuildings() const; void SendBuildingLandmarks(Player* receiver) const; diff --git a/src/server/game/Server/Packets/GarrisonPackets.cpp b/src/server/game/Server/Packets/GarrisonPackets.cpp index d60037ed08a1d..df39ff1f84adc 100644 --- a/src/server/game/Server/Packets/GarrisonPackets.cpp +++ b/src/server/game/Server/Packets/GarrisonPackets.cpp @@ -436,10 +436,10 @@ WorldPacket const* WorldPackets::Garrison::GarrisonAddMissionResult::Write() _worldPacket << uint32(Rewards.size()); _worldPacket << uint32(BonusRewards.size()); - for (WorldPackets::Garrison::GarrisonMissionReward const& missionRewardItem : Rewards) + for (GarrisonMissionReward const& missionRewardItem : Rewards) _worldPacket << missionRewardItem; - for (WorldPackets::Garrison::GarrisonMissionReward const& missionRewardItem : BonusRewards) + for (GarrisonMissionReward const& missionRewardItem : BonusRewards) _worldPacket << missionRewardItem; _worldPacket.WriteBit(Success); diff --git a/src/server/game/Server/Packets/GarrisonPackets.h b/src/server/game/Server/Packets/GarrisonPackets.h index 72ce1f346e4a4..5e132167b8bf0 100644 --- a/src/server/game/Server/Packets/GarrisonPackets.h +++ b/src/server/game/Server/Packets/GarrisonPackets.h @@ -362,7 +362,7 @@ namespace WorldPackets void Read() override; - uint32 ID; + uint32 ID = 0; }; class GarrisonScoutingMapResult final : public ServerPacket @@ -378,7 +378,7 @@ namespace WorldPackets struct GarrisonBuildingLandmark { - GarrisonBuildingLandmark() : GarrBuildingPlotInstID(0), Pos() { } + GarrisonBuildingLandmark() : GarrBuildingPlotInstID(0) { } GarrisonBuildingLandmark(uint32 buildingPlotInstId, Position const& pos) : GarrBuildingPlotInstID(buildingPlotInstId), Pos(pos) { } uint32 GarrBuildingPlotInstID; @@ -470,13 +470,13 @@ namespace WorldPackets public: GarrisonAddMissionResult() : ServerPacket(SMSG_GARRISON_ADD_MISSION_RESULT, 4) { } - uint32 GarrType; - uint32 Result; - uint8 State; + uint32 GarrType = 0; + uint32 Result = 0; + uint8 State = 0; GarrisonMission Mission; - std::vector Rewards; - std::vector BonusRewards; + std::vector Rewards; + std::vector BonusRewards; bool Success = true; @@ -491,7 +491,7 @@ namespace WorldPackets void Read() override; ObjectGuid NpcGUID; - uint32 MissionID; + uint32 MissionID = 0; std::vector Followers; }; @@ -500,7 +500,7 @@ namespace WorldPackets public: GarrisonStartMissionResult() : ServerPacket(SMSG_GARRISON_START_MISSION_RESULT, 4) { } - uint32 Result; + uint32 Result = 0; uint16 FailReason = 1; GarrisonMission Mission; std::vector Followers; @@ -516,7 +516,7 @@ namespace WorldPackets void Read() override; ObjectGuid NpcGUID; - uint32 MissionID; + uint32 MissionID = 0; }; class GarrisonCompleteMissionResult final : public ServerPacket @@ -524,10 +524,10 @@ namespace WorldPackets public: GarrisonCompleteMissionResult() : ServerPacket(SMSG_GARRISON_COMPLETE_MISSION_RESULT, 4) { } - uint32 Result; + uint32 Result = 0; GarrisonMission Mission; std::map Followers; - bool Succeed; + bool Succeed = false; WorldPacket const* Write() override; }; @@ -540,7 +540,7 @@ namespace WorldPackets void Read() override; ObjectGuid NpcGUID; - uint32 MissionID; + uint32 MissionID = 0; }; class GarrisonMissionBonusRollResult final : public ServerPacket @@ -549,7 +549,7 @@ namespace WorldPackets GarrisonMissionBonusRollResult() : ServerPacket(SMSG_GARRISON_MISSION_BONUS_ROLL_RESULT, 4) { } GarrisonMission Mission; - uint32 Result; + uint32 Result = 0; WorldPacket const* Write() override; }; @@ -559,8 +559,8 @@ namespace WorldPackets public: GarrisonFollowerChangeXP() : ServerPacket(SMSG_GARRISON_FOLLOWER_CHANGED_XP, 4) { } - uint32 XP; - uint32 Unk; + uint32 XP = 0; + uint32 Unk = 0; GarrisonFollower OldFollower; GarrisonFollower NewFollower;