From 46b43a990f0c15b25b5f9ee30c40924a8af52bd4 Mon Sep 17 00:00:00 2001 From: Bemvaras <169070864+Barathos@users.noreply.github.com> Date: Wed, 25 Jun 2025 12:03:23 -0600 Subject: [PATCH] [Quest API] Add CompleteTask and UncompleteTask methods to Perl/Lua (#4921) * Add quest::uncompletetask to quest API * Remove CMakeSettings.json (local build config) from PR * Push * Final * Update embparser_api.cpp * Update questmgr.cpp * Update lua_client.cpp * Fix parcel slot duplication for evolving item augments --------- Co-authored-by: Kinglykrab Co-authored-by: Chris Miles --- zone/client.cpp | 15 ++++++++++++ zone/client.h | 1 + zone/client_evolving_items.cpp | 45 ++++++++++++++++++++-------------- zone/embparser_api.cpp | 12 +++++++++ zone/gm_commands/task.cpp | 11 +-------- zone/lua_client.cpp | 15 ++++++++++++ zone/lua_client.h | 2 ++ zone/lua_general.cpp | 10 ++++++++ zone/perl_client.cpp | 12 +++++++++ zone/questmgr.cpp | 22 +++++++++++++++++ zone/questmgr.h | 2 ++ zone/task_client_state.cpp | 10 ++++++++ zone/task_client_state.h | 1 + 13 files changed, 129 insertions(+), 29 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 0d53b7ce5..85ee97434 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -68,6 +68,7 @@ extern volatile bool RunLoops; #include "../common/repositories/character_disciplines_repository.h" #include "../common/repositories/character_data_repository.h" #include "../common/repositories/character_pet_name_repository.h" +#include "../common/repositories/completed_tasks_repository.h" #include "../common/repositories/discovered_items_repository.h" #include "../common/repositories/inventory_repository.h" #include "../common/repositories/keyring_repository.h" @@ -13253,3 +13254,17 @@ void Client::CheckItemDiscoverability(uint32 item_id) DiscoverItem(item_id); } + +bool Client::UncompleteTask(int task_id) +{ + CompletedTasksRepository::DeleteWhere( + database, + fmt::format( + "charid = {} AND taskid = {}", + CharacterID(), + task_id + ) + ); + + return task_state->UncompleteTask(task_id); +} diff --git a/zone/client.h b/zone/client.h index bd409444e..b75fb56f0 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1500,6 +1500,7 @@ public: { return task_state ? task_state->CompleteTask(this, task_id) : false; } + bool UncompleteTask(int task_id); inline void FailTask(int task_id) { if (task_state) { task_state->FailTask(this, task_id); }} inline int TaskTimeLeft(int task_id) { return (task_state ? task_state->TaskTimeLeft(task_id) : 0); } inline int EnabledTaskCount(int task_set_id) diff --git a/zone/client_evolving_items.cpp b/zone/client_evolving_items.cpp index e1259c77f..fef8fa085 100644 --- a/zone/client_evolving_items.cpp +++ b/zone/client_evolving_items.cpp @@ -337,24 +337,29 @@ bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst) !RuleB(EvolvingItems, DestroyAugmentsOnEvolve) && inst.IsAugmented() ) { - auto const augs = inst.GetAugmentIDs(); - std::vector parcels; - for (auto const &item_id: augs) { - if (!item_id) { - continue; - } + auto const augs = inst.GetAugmentIDs(); + std::vector parcels; + int32 next_slot = FindNextFreeParcelSlotUsingMemory(); + for (auto const &item_id: augs) { + if (!item_id) { + continue; + } - CharacterParcelsRepository::CharacterParcels p{}; - p.char_id = CharacterID(); - p.from_name = "Evolving Item Sub-System"; - p.note = fmt::format( - "System automatically removed from {} which recently evolved.", - inst.GetItem()->Name - ); - p.slot_id = FindNextFreeParcelSlotUsingMemory(); - p.sent_date = time(nullptr); - p.item_id = item_id; - p.quantity = 1; + if (next_slot == INVALID_INDEX) { + break; + } + + CharacterParcelsRepository::CharacterParcels p{}; + p.char_id = CharacterID(); + p.from_name = "Evolving Item Sub-System"; + p.note = fmt::format( + "System automatically removed from {} which recently evolved.", + inst.GetItem()->Name + ); + p.slot_id = next_slot; + p.sent_date = time(nullptr); + p.item_id = item_id; + p.quantity = 1; if (player_event_logs.IsEventEnabled(PlayerEvent::PARCEL_SEND)) { PlayerEvent::ParcelSend e{}; @@ -367,8 +372,10 @@ bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst) RecordPlayerEventLog(PlayerEvent::PARCEL_SEND, e); } - parcels.push_back(p); - } + parcels.push_back(p); + m_parcels.emplace(p.slot_id, p); + next_slot = FindNextFreeParcelSlotUsingMemory(); + } CharacterParcelsRepository::InsertMany(database, parcels); SendParcelStatus(); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 135b6227e..44acfb6e4 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1271,6 +1271,16 @@ void Perl__failtask(int task_id) quest_manager.failtask(task_id); } +bool Perl__completetask(int task_id) +{ + return quest_manager.completetask(task_id); +} + +bool Perl__uncompletetask(int task_id) +{ + return quest_manager.uncompletetask(task_id); +} + int Perl__tasktimeleft(int task_id) { return quest_manager.tasktimeleft(task_id); @@ -6628,6 +6638,8 @@ void perl_register_quest() package.add("faction", (void(*)(int, int, int))&Perl__faction); package.add("factionvalue", &Perl__FactionValue); package.add("failtask", &Perl__failtask); + package.add("completetask", &Perl__completetask); + package.add("uncompletetask", &Perl__uncompletetask); package.add("firsttaskinset", &Perl__firsttaskinset); package.add("follow", (void(*)(int))&Perl__follow); package.add("follow", (void(*)(int, int))&Perl__follow); diff --git a/zone/gm_commands/task.cpp b/zone/gm_commands/task.cpp index 6e71a59ae..407184f59 100755 --- a/zone/gm_commands/task.cpp +++ b/zone/gm_commands/task.cpp @@ -304,16 +304,7 @@ void command_task(Client *c, const Seperator *sep) return; } - if ( - CompletedTasksRepository::DeleteWhere( - database, - fmt::format( - "charid = {} AND taskid = {}", - t->CharacterID(), - task_id - ) - ) - ) { + if (t->UncompleteTask(task_id)) { c->Message( Chat::White, fmt::format( diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 418492372..b99636f19 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -3584,6 +3584,19 @@ bool Lua_Client::KeyRingRemove(uint32 item_id) return self->KeyRingRemove(item_id); } + +bool Lua_Client::CompleteTask(int task_id) +{ + Lua_Safe_Call_Bool(); + return self->CompleteTask(task_id); +} + +bool Lua_Client::UncompleteTask(int task_id) +{ + Lua_Safe_Call_Bool(); + return self->UncompleteTask(task_id); +} + void Lua_Client::EnableTitleSet(uint32 title_set) { Lua_Safe_Call_Void(); self->EnableTitle(title_set); @@ -3668,6 +3681,7 @@ luabind::scope lua_register_client() { .def("ClearPEQZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearPEQZoneFlag) .def("ClearXTargets", (void(Lua_Client::*)(void))&Lua_Client::ClearXTargets) .def("ClearZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearZoneFlag) + .def("CompleteTask", (bool(Lua_Client::*)(int))&Lua_Client::CompleteTask) .def("Connected", (bool(Lua_Client::*)(void))&Lua_Client::Connected) .def("CountAugmentEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID) .def("CountItem", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountItem) @@ -4162,6 +4176,7 @@ luabind::scope lua_register_client() { .def("TrainDisc", (void(Lua_Client::*)(int))&Lua_Client::TrainDisc) .def("TrainDiscBySpellID", (void(Lua_Client::*)(int32))&Lua_Client::TrainDiscBySpellID) .def("UnFreeze", (void(Lua_Client::*)(void))&Lua_Client::UnFreeze) + .def("UncompleteTask", (bool(Lua_Client::*)(int))&Lua_Client::UncompleteTask) .def("Undye", (void(Lua_Client::*)(void))&Lua_Client::Undye) .def("UnmemSpell", (void(Lua_Client::*)(int))&Lua_Client::UnmemSpell) .def("UnmemSpell", (void(Lua_Client::*)(int,bool))&Lua_Client::UnmemSpell) diff --git a/zone/lua_client.h b/zone/lua_client.h index 932e279c6..04b9da273 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -522,6 +522,8 @@ public: bool KeyRingClear(); void KeyRingList(); bool KeyRingRemove(uint32 item_id); + bool CompleteTask(int task_id); + bool UncompleteTask(int task_id); // account data buckets void SetAccountBucket(std::string bucket_name, std::string bucket_value); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 90c0c33be..5b26dd9b0 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -722,6 +722,14 @@ void lua_fail_task(int task_id) { quest_manager.failtask(task_id); } +bool lua_complete_task(int task_id) { + return quest_manager.completetask(task_id); +} + +bool lua_uncomplete_task(int task_id) { + return quest_manager.uncompletetask(task_id); +} + int lua_task_time_left(int task_id) { return quest_manager.tasktimeleft(task_id); } @@ -5970,6 +5978,8 @@ luabind::scope lua_register_general() { luabind::def("reset_task_activity", &lua_reset_task_activity), luabind::def("assign_task", &lua_assign_task), luabind::def("fail_task", &lua_fail_task), + luabind::def("complete_task", &lua_complete_task), + luabind::def("uncomplete_task", &lua_uncomplete_task), luabind::def("task_time_left", &lua_task_time_left), luabind::def("is_task_completed", &lua_is_task_completed), luabind::def("enabled_task_count", &lua_enabled_task_count), diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 20ff56fe3..2f853c9cb 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3336,6 +3336,16 @@ bool Perl_Client_KeyRingRemove(Client* self, uint32 item_id) return self->KeyRingRemove(item_id); } +bool Perl_Client_CompleteTask(Client* self, int task_id) +{ + return self->CompleteTask(task_id); +} + +bool Perl_Client_UncompleteTask(Client* self, int task_id) +{ + return self->UncompleteTask(task_id); +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3418,6 +3428,7 @@ void perl_register_client() package.add("ClearPEQZoneFlag", &Perl_Client_ClearPEQZoneFlag); package.add("ClearXTargets", &Perl_Client_ClearXTargets); package.add("ClearZoneFlag", &Perl_Client_ClearZoneFlag); + package.add("CompleteTask", &Perl_Client_CompleteTask); package.add("Connected", &Perl_Client_Connected); package.add("CountAugmentEquippedByID", &Perl_Client_CountAugmentEquippedByID); package.add("CountItem", &Perl_Client_CountItem); @@ -3909,6 +3920,7 @@ void perl_register_client() package.add("Thirsty", &Perl_Client_Thirsty); package.add("TrainDiscBySpellID", &Perl_Client_TrainDiscBySpellID); package.add("UnFreeze", &Perl_Client_UnFreeze); + package.add("UncompleteTask", &Perl_Client_UncompleteTask); package.add("Undye", &Perl_Client_Undye); package.add("UnmemSpell", (void(*)(Client*, int))&Perl_Client_UnmemSpell); package.add("UnmemSpell", (void(*)(Client*, int, bool))&Perl_Client_UnmemSpell); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 1e6e3fc3f..ac17e68d3 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -40,6 +40,7 @@ #include "dialogue_window.h" #include "../common/repositories/account_repository.h" +#include "../common/repositories/completed_tasks_repository.h" #include "../common/repositories/tradeskill_recipe_repository.h" #include "../common/repositories/instance_list_repository.h" #include "../common/repositories/grid_entries_repository.h" @@ -2958,6 +2959,27 @@ void QuestManager::failtask(int taskid) { initiator->FailTask(taskid); } +bool QuestManager::completetask(int task_id) { + QuestManagerCurrentQuestVars(); + + if (!RuleB(TaskSystem, EnableTaskSystem) || !initiator) { + return false; + + } + + return initiator->CompleteTask(task_id); +} + +bool QuestManager::uncompletetask(int task_id) { + QuestManagerCurrentQuestVars(); + + if (!RuleB(TaskSystem, EnableTaskSystem) || !initiator) { + return false; + } + + return initiator->UncompleteTask(task_id); +} + int QuestManager::tasktimeleft(int taskid) { QuestManagerCurrentQuestVars(); diff --git a/zone/questmgr.h b/zone/questmgr.h index 5148b44f5..0e3cd4a4f 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -224,6 +224,8 @@ public: void resettaskactivity(int task, int activity); void assigntask(int taskid, bool enforce_level_requirement = false); void failtask(int taskid); + bool completetask(int task_id); + bool uncompletetask(int task_id); int tasktimeleft(int taskid); bool istaskcompleted(int task_id); bool aretaskscompleted(const std::vector& task_ids); diff --git a/zone/task_client_state.cpp b/zone/task_client_state.cpp index 16205187a..42d504ec5 100644 --- a/zone/task_client_state.cpp +++ b/zone/task_client_state.cpp @@ -1396,6 +1396,16 @@ bool ClientTaskState::CompleteTask(Client *c, uint32 task_id) return true; } +bool ClientTaskState::UncompleteTask(int task_id) +{ + return std::erase_if( + m_completed_tasks, + [&](const CompletedTaskInformation& task) { + return task.task_id == task_id; + } + ); +} + void ClientTaskState::ShowClientTaskInfoMessage(ClientTaskInformation *task, Client *c) { const auto task_data = TaskManager::Instance()->GetTaskData(task->task_id); diff --git a/zone/task_client_state.h b/zone/task_client_state.h index c43329734..30c5dd69c 100644 --- a/zone/task_client_state.h +++ b/zone/task_client_state.h @@ -86,6 +86,7 @@ public: bool HasExploreTask(Client* client) const; void EndSharedTask(Client* client, bool send_fail); bool CompleteTask(Client *c, uint32 task_id); + bool UncompleteTask(int task_id); inline bool HasFreeTaskSlot() { return m_active_task.task_id == TASKSLOTEMPTY; }