world quest changes

This commit is contained in:
luis
2026-03-15 17:26:25 -03:00
parent aa9f12cb17
commit d08f65b834
5 changed files with 180 additions and 11 deletions
+113 -1
View File
@@ -159,6 +159,7 @@
#include "HousingNeighborhoodMirrorEntity.h"
#include "HousingPlayerHouseEntity.h"
#include "QueryPackets.h"
#include "WorldQuestMgr.h"
//WowCommunity
// corpse reclaim times
#define DEATH_EXPIRE_STEP (5*MINUTE)
@@ -6300,6 +6301,9 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t
if (!Unit::UpdatePosition(x, y, z, orientation, teleport))
return false;
//WowCommunity
UpdateWorldQuestPosition(x, y);
//WowCommunity
//if (movementInfo.flags & MOVEMENTFLAG_MOVING)
// mover->RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags::Moving);
//if (movementInfo.flags & MOVEMENTFLAG_TURNING)
@@ -9306,7 +9310,9 @@ void Player::SendInitWorldStates(uint32 zoneId, uint32 areaId)
packet.SubareaID = areaId;
sWorldStateMgr->FillInitialWorldStates(packet, GetMap(), areaId);
//WowCommunity
sWorldQuestMgr->FillInitWorldStates(packet);
//WowCommunity
TC_LOG_INFO("housing", "Player::SendInitWorldStates: Map={} Zone={} Area={} WorldStateCount={}",
mapId, zoneId, areaId, uint32(packet.Worldstates.size()));
@@ -15190,6 +15196,13 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
else if (quest->IsSeasonal())
SetSeasonalQuestStatus(quest_id);
else if (!quest->IsWorldQuest() && !quest->IsEmissaryQuest())
{
m_RewardedQuests.insert(quest_id);
// m_accountQuests.insert(quest_id);
m_RewardedQuestsSave[quest_id] = QUEST_DEFAULT_SAVE_TYPE;
}
RemoveTimedQuest(quest_id);
RemoveActiveQuest(quest_id, false);
if (quest->CanIncreaseRewardedQuestCounters())
@@ -15339,6 +15352,10 @@ void Player::RewardQuest(Quest const* quest, LootItemType rewardType, uint32 rew
if (uint32 honor = quest->CalculateHonorGain(GetLevel()))
RewardHonor(nullptr, 0, honor, HonorGainSource::Quest);
//wq reward
if (quest->IsWorldQuest())
sWorldQuestMgr->RewardQuestForPlayer(this, quest->GetQuestId());
// title reward
if (quest->GetRewTitle())
{
@@ -18658,6 +18675,9 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
_LoadSeasonalQuestStatus(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SEASONAL_QUEST_STATUS));
_LoadMonthlyQuestStatus(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_MONTHLY_QUEST_STATUS));
_LoadRandomBGStatus(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_RANDOM_BG));
//WowCommunity
// _LoadWorldQuestStatus(holder.GetPreparedResult(PLAYER_LOGIN_QUERY_LOADWORLDQUESTSTATUS)); todo thor
//WowCommunity
// after spell and quest load
InitTalentForLevel();
@@ -19188,6 +19208,9 @@ bool Player::LoadFromDB(ObjectGuid guid, CharacterDatabaseQueryHolder const& hol
_restMgr->AddRestBonus(REST_TYPE_XP, time_diff * _restMgr->CalcExtraPerSec(REST_TYPE_XP, bubble));
}
// Add active emissary quests on player at login
sWorldQuestMgr->AddEmissaryQuestsOnPlayerIfNeeded(this);
// Unlock battle pet system if it's enabled in bnet account
if (GetSession()->GetBattlePetMgr()->IsBattlePetSystemEnabled())
LearnSpell(BattlePets::SPELL_BATTLE_PET_TRAINING, false);
@@ -21241,6 +21264,7 @@ void Player::SaveToDB(LoginDatabaseTransaction loginTransaction, CharacterDataba
_SaveBGData(trans);
_SaveInventory(trans);
_SaveQuestStatus(trans);
// _SaveWorldQuestStatus(trans); todo thor
_SaveDailyQuestStatus(trans);
_SaveWeeklyQuestStatus(trans);
_SaveSeasonalQuestStatus(trans);
@@ -32594,4 +32618,92 @@ bool Player::HasQuest(uint32 questID) const
return false;
}
void Player::UpdateWorldQuestPosition(float x, float y)
{
// Throttle updates to avoid excessive processing
if (time(nullptr) < m_areaQuestTimer)
return;
// Set next update time to 2 seconds from now
m_areaQuestTimer = time(nullptr) + 2;
std::vector<uint32> questsToRemove;
// Process all bonus quests with area restrictions
//for (auto bonus_quest : sObjectMgr->BonusQuestsRects)
//{
// uint32 questId = bonus_quest.first;
// // Skip quests already completed
// if (IsQuestRewarded(questId))
// continue;
// // Get quest template
// Quest const* quest = sObjectMgr->GetQuestTemplate(questId);
// if (!quest)
// continue;
// // Check if player is in any of the quest's valid areas
// bool isInQuestArea = false;
// for (uint32 i = 0; i < bonus_quest.second.size(); ++i)
// {
// if (bonus_quest.second[i].IsIn(GetMapId(), x, y))
// {
// isInQuestArea = true;
// break;
// }
// }
// uint32 slot = FindQuestSlot(questId);
// bool hasQuest = (slot < MAX_QUEST_LOG_SIZE);
// // Player left quest area - remove quest
// if (!isInQuestArea && hasQuest)
// {
// questsToRemove.push_back(slot);
// RemoveActiveQuest(questId, true);
// }
// // Player entered quest area - add quest if eligible
// else if (isInQuestArea && !hasQuest)
// {
// // Check if player can take this quest
// if (!CanTakeQuest(quest, false))
// continue;
// // Additional checks for world quests
// if (quest->IsWorldQuest())
// {
// // Check if player has unlocked world quests for this expansion
// if (!HasWorldQuestEnabled(quest->GetExpansion()))
// {
// // TC_LOG_DEBUG("entities.player.worldquests", "Player %s cannot take world quest %u - world quests not enabled for expansion %u",
// // GetGUID().ToString().c_str(), questId, quest->GetExpansion());
// continue;
// }
// // Check if the world quest is currently active
// if (!sWorldQuestMgr->IsQuestActive(quest->GetQuestId()))
// {
// // TC_LOG_DEBUG("entities.player.worldquests", "Player %s cannot take world quest %u - quest is not active",
// // GetGUID().ToString().c_str(), questId);
// continue;
// }
// }
// // Add the quest to player's quest log
// AddQuest(quest, this);
// /* TC_LOG_DEBUG("entities.player.worldquests", "Player %s automatically added quest %u when entering quest area at [%.2f, %.2f]",
// GetGUID().ToString().c_str(), questId, x, y);*/
// }
//}
// Clear quest slots for removed quests
for (uint32 slot : questsToRemove)
{
SetQuestSlot(slot, 0);
TC_LOG_DEBUG("entities.player.worldquests", "Player %s removed quest in slot %u when leaving quest area",
GetGUID().ToString().c_str(), slot);
}
}
//WowCommunity
+4
View File
@@ -3425,6 +3425,10 @@ class TC_GAME_API Player final : public Unit, public GridObject<Player>
//WowCommunity
bool HasQuest(uint32 questID) const;
void UpdateWorldQuestPosition(float x, float y);
protected:
uint32 m_areaQuestTimer;
//WowCommunity
private:
std::unique_ptr<SpellCastRequest> _pendingSpellCastRequest;
+53
View File
@@ -578,6 +578,50 @@ bool WorldQuestMgr::IsQuestActive(uint32 questId)
return false;
}
void WorldQuestMgr::RewardQuestForPlayer(Player* player, uint32 questId)
{
ActiveWorldQuest const* activeWorldQuest = GetActiveWorldQuest(questId);
if (!activeWorldQuest)
return;
player->TakeQuestSourceItem(questId, false);
std::vector<WorldQuestReward const*> worldQuestRewards = GetRewardsForPlayerById(player, activeWorldQuest->RewardId);
for (WorldQuestReward const* worldQuestReward : worldQuestRewards)
{
switch (worldQuestReward->Type)
{
case WORLD_QUEST_REWARD_ITEM:
{
ItemPosCountVec dest;
if (player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, worldQuestReward->Id, worldQuestReward->Count) == EQUIP_ERR_OK)
{
std::vector<int32> bonusListIDs = ItemBonusMgr::GetAllBonusListsForTree(worldQuestReward->Id);
Item* item = player->StoreNewItem(dest, worldQuestReward->Id, true, GenerateItemRandomBonusListId(worldQuestReward->ItemBonusListID), GuidSet(), ItemContext::World_Quest_13, &bonusListIDs);
player->SendNewItem(item, worldQuestReward->Count, true, false);
}
break;
}
case WORLD_QUEST_REWARD_CURRENCY:
{
player->ModifyCurrency(worldQuestReward->Id, worldQuestReward->Count);
break;
}
case WORLD_QUEST_REWARD_GOLD:
{
uint64 moneyRew = worldQuestReward->Count * sWorld->getRate(RATE_MONEY_QUEST);
player->ModifyMoney(moneyRew);
if (moneyRew > 0)
player->UpdateCriteria(CriteriaType::MoneyEarnedFromQuesting, uint32(moneyRew));
break;
}
default:
break;
}
}
}
WorldQuestTemplate* WorldQuestMgr::GetWorldQuestTemplate(uint32 questId)
{
for (auto& expansionTemplates : _worldQuestTemplates)
@@ -656,3 +700,12 @@ TeamId WorldQuestMgr::GetQuestTeamId(Quest const* quest)
// For now, return neutral as default
return TEAM_NEUTRAL;
}
void WorldQuestMgr::FillInitWorldStates(WorldPackets::WorldState::InitWorldStates& packet) const
{
for (auto const& [_, expansionWorldQuests] : _activeWorldQuests)
for (auto const& [_, teamWorldQuests] : expansionWorldQuests)
for (auto const& [_, activeWorldQuest] : teamWorldQuests)
if (WorldQuestTemplate const* worldQuestTemplate = activeWorldQuest->GetTemplate())
packet.Worldstates.emplace_back(worldQuestTemplate->Variable, worldQuestTemplate->Value);
}
+8
View File
@@ -21,6 +21,7 @@
#include "Common.h"
#include "QuestDef.h"
#include "GameTime.h"
#include "WorldStatePackets.h"
#include <vector>
#include <unordered_map>
#include <set>
@@ -102,6 +103,8 @@ struct ActiveWorldQuest
uint32 EndTime;
bool IsCompleted;
WorldQuestTemplate const* GetTemplate() const;
uint32 GetRemainingTime() const
{
uint32 currentTime = GameTime::GetGameTime();
@@ -165,6 +168,9 @@ public:
// Timer (public - used by external code)
uint32 GetTimerForQuest(uint32 questId);
//packet
void FillInitWorldStates(WorldPackets::WorldState::InitWorldStates& packet) const;
// Team (public - used by external code)
TeamId GetQuestTeamId(Quest const* quest);
WorldQuestTemplate* GetWorldQuestTemplate(uint32 questId);
@@ -191,4 +197,6 @@ private:
#define sWorldQuestMgr WorldQuestMgr::instance()
inline WorldQuestTemplate const* ActiveWorldQuest::GetTemplate() const { return sWorldQuestMgr->GetWorldQuestTemplate(QuestId); }
#endif // TRINITYCORE_WORLD_QUEST_MGR_H
@@ -695,14 +695,6 @@ namespace WorldPackets
int32 QuestID = 0;
};
class RequestWorldQuestUpdate final : public ClientPacket
{
public:
explicit RequestWorldQuestUpdate(WorldPacket&& packet) : ClientPacket(CMSG_REQUEST_WORLD_QUEST_UPDATE, std::move(packet)) { }
void Read() override { }
};
struct PlayerChoiceResponseRewardEntry
{
WorldPackets::Item::ItemInstance Item;