[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 <kinglykrab@gmail.com>
Co-authored-by: Chris Miles <akkadius1@gmail.com>
This commit is contained in:
Bemvaras 2025-06-25 12:03:23 -06:00 committed by GitHub
parent ea96cbf885
commit 46b43a990f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 129 additions and 29 deletions

View File

@ -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);
}

View File

@ -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)

View File

@ -337,24 +337,29 @@ bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst)
!RuleB(EvolvingItems, DestroyAugmentsOnEvolve) &&
inst.IsAugmented()
) {
auto const augs = inst.GetAugmentIDs();
std::vector<CharacterParcelsRepository::CharacterParcels> parcels;
for (auto const &item_id: augs) {
if (!item_id) {
continue;
}
auto const augs = inst.GetAugmentIDs();
std::vector<CharacterParcelsRepository::CharacterParcels> 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();

View File

@ -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);

View File

@ -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(

View File

@ -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)

View File

@ -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);

View File

@ -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),

View File

@ -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);

View File

@ -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();

View File

@ -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<int>& task_ids);

View File

@ -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);

View File

@ -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; }