[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_disciplines_repository.h"
#include "../common/repositories/character_data_repository.h" #include "../common/repositories/character_data_repository.h"
#include "../common/repositories/character_pet_name_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/discovered_items_repository.h"
#include "../common/repositories/inventory_repository.h" #include "../common/repositories/inventory_repository.h"
#include "../common/repositories/keyring_repository.h" #include "../common/repositories/keyring_repository.h"
@ -13253,3 +13254,17 @@ void Client::CheckItemDiscoverability(uint32 item_id)
DiscoverItem(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; 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 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 TaskTimeLeft(int task_id) { return (task_state ? task_state->TaskTimeLeft(task_id) : 0); }
inline int EnabledTaskCount(int task_set_id) inline int EnabledTaskCount(int task_set_id)

View File

@ -337,24 +337,29 @@ bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst)
!RuleB(EvolvingItems, DestroyAugmentsOnEvolve) && !RuleB(EvolvingItems, DestroyAugmentsOnEvolve) &&
inst.IsAugmented() inst.IsAugmented()
) { ) {
auto const augs = inst.GetAugmentIDs(); auto const augs = inst.GetAugmentIDs();
std::vector<CharacterParcelsRepository::CharacterParcels> parcels; std::vector<CharacterParcelsRepository::CharacterParcels> parcels;
for (auto const &item_id: augs) { int32 next_slot = FindNextFreeParcelSlotUsingMemory();
if (!item_id) { for (auto const &item_id: augs) {
continue; if (!item_id) {
} continue;
}
CharacterParcelsRepository::CharacterParcels p{}; if (next_slot == INVALID_INDEX) {
p.char_id = CharacterID(); break;
p.from_name = "Evolving Item Sub-System"; }
p.note = fmt::format(
"System automatically removed from {} which recently evolved.", CharacterParcelsRepository::CharacterParcels p{};
inst.GetItem()->Name p.char_id = CharacterID();
); p.from_name = "Evolving Item Sub-System";
p.slot_id = FindNextFreeParcelSlotUsingMemory(); p.note = fmt::format(
p.sent_date = time(nullptr); "System automatically removed from {} which recently evolved.",
p.item_id = item_id; inst.GetItem()->Name
p.quantity = 1; );
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)) { if (player_event_logs.IsEventEnabled(PlayerEvent::PARCEL_SEND)) {
PlayerEvent::ParcelSend e{}; PlayerEvent::ParcelSend e{};
@ -367,8 +372,10 @@ bool Client::DoEvolveCheckProgression(EQ::ItemInstance &inst)
RecordPlayerEventLog(PlayerEvent::PARCEL_SEND, e); 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); CharacterParcelsRepository::InsertMany(database, parcels);
SendParcelStatus(); SendParcelStatus();

View File

@ -1271,6 +1271,16 @@ void Perl__failtask(int task_id)
quest_manager.failtask(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) int Perl__tasktimeleft(int task_id)
{ {
return quest_manager.tasktimeleft(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("faction", (void(*)(int, int, int))&Perl__faction);
package.add("factionvalue", &Perl__FactionValue); package.add("factionvalue", &Perl__FactionValue);
package.add("failtask", &Perl__failtask); package.add("failtask", &Perl__failtask);
package.add("completetask", &Perl__completetask);
package.add("uncompletetask", &Perl__uncompletetask);
package.add("firsttaskinset", &Perl__firsttaskinset); package.add("firsttaskinset", &Perl__firsttaskinset);
package.add("follow", (void(*)(int))&Perl__follow); package.add("follow", (void(*)(int))&Perl__follow);
package.add("follow", (void(*)(int, 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; return;
} }
if ( if (t->UncompleteTask(task_id)) {
CompletedTasksRepository::DeleteWhere(
database,
fmt::format(
"charid = {} AND taskid = {}",
t->CharacterID(),
task_id
)
)
) {
c->Message( c->Message(
Chat::White, Chat::White,
fmt::format( fmt::format(

View File

@ -3584,6 +3584,19 @@ bool Lua_Client::KeyRingRemove(uint32 item_id)
return self->KeyRingRemove(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) { void Lua_Client::EnableTitleSet(uint32 title_set) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->EnableTitle(title_set); self->EnableTitle(title_set);
@ -3668,6 +3681,7 @@ luabind::scope lua_register_client() {
.def("ClearPEQZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearPEQZoneFlag) .def("ClearPEQZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearPEQZoneFlag)
.def("ClearXTargets", (void(Lua_Client::*)(void))&Lua_Client::ClearXTargets) .def("ClearXTargets", (void(Lua_Client::*)(void))&Lua_Client::ClearXTargets)
.def("ClearZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearZoneFlag) .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("Connected", (bool(Lua_Client::*)(void))&Lua_Client::Connected)
.def("CountAugmentEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID) .def("CountAugmentEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID)
.def("CountItem", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountItem) .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("TrainDisc", (void(Lua_Client::*)(int))&Lua_Client::TrainDisc)
.def("TrainDiscBySpellID", (void(Lua_Client::*)(int32))&Lua_Client::TrainDiscBySpellID) .def("TrainDiscBySpellID", (void(Lua_Client::*)(int32))&Lua_Client::TrainDiscBySpellID)
.def("UnFreeze", (void(Lua_Client::*)(void))&Lua_Client::UnFreeze) .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("Undye", (void(Lua_Client::*)(void))&Lua_Client::Undye)
.def("UnmemSpell", (void(Lua_Client::*)(int))&Lua_Client::UnmemSpell) .def("UnmemSpell", (void(Lua_Client::*)(int))&Lua_Client::UnmemSpell)
.def("UnmemSpell", (void(Lua_Client::*)(int,bool))&Lua_Client::UnmemSpell) .def("UnmemSpell", (void(Lua_Client::*)(int,bool))&Lua_Client::UnmemSpell)

View File

@ -522,6 +522,8 @@ public:
bool KeyRingClear(); bool KeyRingClear();
void KeyRingList(); void KeyRingList();
bool KeyRingRemove(uint32 item_id); bool KeyRingRemove(uint32 item_id);
bool CompleteTask(int task_id);
bool UncompleteTask(int task_id);
// account data buckets // account data buckets
void SetAccountBucket(std::string bucket_name, std::string bucket_value); 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); 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) { int lua_task_time_left(int task_id) {
return quest_manager.tasktimeleft(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("reset_task_activity", &lua_reset_task_activity),
luabind::def("assign_task", &lua_assign_task), luabind::def("assign_task", &lua_assign_task),
luabind::def("fail_task", &lua_fail_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("task_time_left", &lua_task_time_left),
luabind::def("is_task_completed", &lua_is_task_completed), luabind::def("is_task_completed", &lua_is_task_completed),
luabind::def("enabled_task_count", &lua_enabled_task_count), 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); 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() void perl_register_client()
{ {
perl::interpreter perl(PERL_GET_THX); perl::interpreter perl(PERL_GET_THX);
@ -3418,6 +3428,7 @@ void perl_register_client()
package.add("ClearPEQZoneFlag", &Perl_Client_ClearPEQZoneFlag); package.add("ClearPEQZoneFlag", &Perl_Client_ClearPEQZoneFlag);
package.add("ClearXTargets", &Perl_Client_ClearXTargets); package.add("ClearXTargets", &Perl_Client_ClearXTargets);
package.add("ClearZoneFlag", &Perl_Client_ClearZoneFlag); package.add("ClearZoneFlag", &Perl_Client_ClearZoneFlag);
package.add("CompleteTask", &Perl_Client_CompleteTask);
package.add("Connected", &Perl_Client_Connected); package.add("Connected", &Perl_Client_Connected);
package.add("CountAugmentEquippedByID", &Perl_Client_CountAugmentEquippedByID); package.add("CountAugmentEquippedByID", &Perl_Client_CountAugmentEquippedByID);
package.add("CountItem", &Perl_Client_CountItem); package.add("CountItem", &Perl_Client_CountItem);
@ -3909,6 +3920,7 @@ void perl_register_client()
package.add("Thirsty", &Perl_Client_Thirsty); package.add("Thirsty", &Perl_Client_Thirsty);
package.add("TrainDiscBySpellID", &Perl_Client_TrainDiscBySpellID); package.add("TrainDiscBySpellID", &Perl_Client_TrainDiscBySpellID);
package.add("UnFreeze", &Perl_Client_UnFreeze); package.add("UnFreeze", &Perl_Client_UnFreeze);
package.add("UncompleteTask", &Perl_Client_UncompleteTask);
package.add("Undye", &Perl_Client_Undye); package.add("Undye", &Perl_Client_Undye);
package.add("UnmemSpell", (void(*)(Client*, int))&Perl_Client_UnmemSpell); package.add("UnmemSpell", (void(*)(Client*, int))&Perl_Client_UnmemSpell);
package.add("UnmemSpell", (void(*)(Client*, int, bool))&Perl_Client_UnmemSpell); package.add("UnmemSpell", (void(*)(Client*, int, bool))&Perl_Client_UnmemSpell);

View File

@ -40,6 +40,7 @@
#include "dialogue_window.h" #include "dialogue_window.h"
#include "../common/repositories/account_repository.h" #include "../common/repositories/account_repository.h"
#include "../common/repositories/completed_tasks_repository.h"
#include "../common/repositories/tradeskill_recipe_repository.h" #include "../common/repositories/tradeskill_recipe_repository.h"
#include "../common/repositories/instance_list_repository.h" #include "../common/repositories/instance_list_repository.h"
#include "../common/repositories/grid_entries_repository.h" #include "../common/repositories/grid_entries_repository.h"
@ -2958,6 +2959,27 @@ void QuestManager::failtask(int taskid) {
initiator->FailTask(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) { int QuestManager::tasktimeleft(int taskid) {
QuestManagerCurrentQuestVars(); QuestManagerCurrentQuestVars();

View File

@ -224,6 +224,8 @@ public:
void resettaskactivity(int task, int activity); void resettaskactivity(int task, int activity);
void assigntask(int taskid, bool enforce_level_requirement = false); void assigntask(int taskid, bool enforce_level_requirement = false);
void failtask(int taskid); void failtask(int taskid);
bool completetask(int task_id);
bool uncompletetask(int task_id);
int tasktimeleft(int taskid); int tasktimeleft(int taskid);
bool istaskcompleted(int task_id); bool istaskcompleted(int task_id);
bool aretaskscompleted(const std::vector<int>& task_ids); bool aretaskscompleted(const std::vector<int>& task_ids);

View File

@ -1396,6 +1396,16 @@ bool ClientTaskState::CompleteTask(Client *c, uint32 task_id)
return true; 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) void ClientTaskState::ShowClientTaskInfoMessage(ClientTaskInformation *task, Client *c)
{ {
const auto task_data = TaskManager::Instance()->GetTaskData(task->task_id); const auto task_data = TaskManager::Instance()->GetTaskData(task->task_id);

View File

@ -86,6 +86,7 @@ public:
bool HasExploreTask(Client* client) const; bool HasExploreTask(Client* client) const;
void EndSharedTask(Client* client, bool send_fail); void EndSharedTask(Client* client, bool send_fail);
bool CompleteTask(Client *c, uint32 task_id); bool CompleteTask(Client *c, uint32 task_id);
bool UncompleteTask(int task_id);
inline bool HasFreeTaskSlot() { return m_active_task.task_id == TASKSLOTEMPTY; } inline bool HasFreeTaskSlot() { return m_active_task.task_id == TASKSLOTEMPTY; }