mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 13:41:31 +00:00
[Tasks] Remove delivered task items from trades (#2405)
This commit is contained in:
parent
e011864ed5
commit
7cf96ca2d8
@ -1158,13 +1158,9 @@ public:
|
|||||||
{
|
{
|
||||||
return task_state && task_state->UpdateTasksOnSpeakWith(this, npc);
|
return task_state && task_state->UpdateTasksOnSpeakWith(this, npc);
|
||||||
}
|
}
|
||||||
inline bool UpdateTasksOnDeliver(
|
inline bool UpdateTasksOnDeliver(std::vector<EQ::ItemInstance*>& items, Trade& trade, NPC* npc)
|
||||||
std::list<EQ::ItemInstance *> &items,
|
|
||||||
int cash,
|
|
||||||
NPC* npc
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
return task_state && task_state->UpdateTasksOnDeliver(this, items, cash, npc);
|
return task_state && task_state->UpdateTasksOnDeliver(this, items, trade, npc);
|
||||||
}
|
}
|
||||||
void UpdateTasksOnTouchSwitch(int dz_switch_id)
|
void UpdateTasksOnTouchSwitch(int dz_switch_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -210,6 +210,7 @@
|
|||||||
#define EATING_MESSAGE 1091 //Chomp, chomp, chomp... %1 takes a bite from a %2.
|
#define EATING_MESSAGE 1091 //Chomp, chomp, chomp... %1 takes a bite from a %2.
|
||||||
#define DRINKING_MESSAGE 1093 //Glug, glug, glug... %1 takes a drink from a %2.
|
#define DRINKING_MESSAGE 1093 //Glug, glug, glug... %1 takes a drink from a %2.
|
||||||
#define SUCCESSFUL_TAUNT 1095 //I'll teach you to interfere with me %3.
|
#define SUCCESSFUL_TAUNT 1095 //I'll teach you to interfere with me %3.
|
||||||
|
#define TRADE_BACK 1105 //I have no need for this %3, you can have it back.
|
||||||
#define PET_SIT_STRING 1130 //Changing position, Master.
|
#define PET_SIT_STRING 1130 //Changing position, Master.
|
||||||
#define PET_CALMING 1131 //Sorry, Master..calming down.
|
#define PET_CALMING 1131 //Sorry, Master..calming down.
|
||||||
#define PET_FOLLOWING 1132 //Following you, Master.
|
#define PET_FOLLOWING 1132 //Following you, Master.
|
||||||
|
|||||||
@ -558,14 +558,14 @@ bool ClientTaskState::CanUpdate(Client* client, const TaskUpdateFilter& filter,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientTaskState::UpdateTasks(Client* client, const TaskUpdateFilter& filter, int count)
|
int ClientTaskState::UpdateTasks(Client* client, const TaskUpdateFilter& filter, int count)
|
||||||
{
|
{
|
||||||
if (!task_manager)
|
if (!task_manager)
|
||||||
{
|
{
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool any_updated = false;
|
int max_updated = 0;
|
||||||
|
|
||||||
for (const auto& client_task : m_active_tasks)
|
for (const auto& client_task : m_active_tasks)
|
||||||
{
|
{
|
||||||
@ -591,14 +591,14 @@ bool ClientTaskState::UpdateTasks(Client* client, const TaskUpdateFilter& filter
|
|||||||
LogTasks("[UpdateTasks] client [{}] task [{}] activity [{}] increment [{}]",
|
LogTasks("[UpdateTasks] client [{}] task [{}] activity [{}] increment [{}]",
|
||||||
client->GetName(), client_task.task_id, client_activity.activity_id, count);
|
client->GetName(), client_task.task_id, client_activity.activity_id, count);
|
||||||
|
|
||||||
IncrementDoneCount(client, task, client_task.slot, client_activity.activity_id, count);
|
int updated = IncrementDoneCount(client, task, client_task.slot, client_activity.activity_id, count);
|
||||||
any_updated = true;
|
max_updated = std::max(max_updated, updated);
|
||||||
break; // only one element updated per task, move to next task
|
break; // only one element updated per task, move to next task
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return any_updated;
|
return max_updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<int, int> ClientTaskState::FindTask(Client* client, const TaskUpdateFilter& filter) const
|
std::pair<int, int> ClientTaskState::FindTask(Client* client, const TaskUpdateFilter& filter) const
|
||||||
@ -653,7 +653,7 @@ bool ClientTaskState::UpdateTasksByNPC(Client* client, TaskActivityType type, NP
|
|||||||
filter.type = type;
|
filter.type = type;
|
||||||
filter.npc = npc;
|
filter.npc = npc;
|
||||||
|
|
||||||
return UpdateTasks(client, filter);
|
return UpdateTasks(client, filter) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClientTaskState::ActiveSpeakTask(Client* client, NPC* npc)
|
int ClientTaskState::ActiveSpeakTask(Client* client, NPC* npc)
|
||||||
@ -719,12 +719,7 @@ void ClientTaskState::UpdateTasksOnExplore(Client* client, const glm::vec4& pos)
|
|||||||
UpdateTasks(client, filter);
|
UpdateTasks(client, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientTaskState::UpdateTasksOnDeliver(
|
bool ClientTaskState::UpdateTasksOnDeliver(Client* client, std::vector<EQ::ItemInstance*>& items, Trade& trade, NPC* npc)
|
||||||
Client *client,
|
|
||||||
std::list<EQ::ItemInstance *> &items,
|
|
||||||
int cash,
|
|
||||||
NPC* npc
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
LogTasks("[UpdateTasksOnDeliver] npc [{}]", npc->GetName());
|
LogTasks("[UpdateTasksOnDeliver] npc [{}]", npc->GetName());
|
||||||
|
|
||||||
@ -733,10 +728,12 @@ bool ClientTaskState::UpdateTasksOnDeliver(
|
|||||||
TaskUpdateFilter filter{};
|
TaskUpdateFilter filter{};
|
||||||
filter.npc = npc;
|
filter.npc = npc;
|
||||||
|
|
||||||
|
int cash = trade.cp + (trade.sp * 10) + (trade.gp * 100) + (trade.pp * 1000);
|
||||||
if (cash != 0)
|
if (cash != 0)
|
||||||
{
|
{
|
||||||
filter.type = TaskActivityType::GiveCash;
|
filter.type = TaskActivityType::GiveCash;
|
||||||
if (UpdateTasks(client, filter, cash))
|
int updated_count = UpdateTasks(client, filter, cash);
|
||||||
|
if (updated_count > 0)
|
||||||
{
|
{
|
||||||
// todo: remove used coin and use Deliver with explicit coin fields instead of custom type
|
// todo: remove used coin and use Deliver with explicit coin fields instead of custom type
|
||||||
is_updated = true;
|
is_updated = true;
|
||||||
@ -744,14 +741,26 @@ bool ClientTaskState::UpdateTasksOnDeliver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
filter.type = TaskActivityType::Deliver;
|
filter.type = TaskActivityType::Deliver;
|
||||||
for (EQ::ItemInstance* item : items)
|
for (EQ::ItemInstance*& item : items)
|
||||||
{
|
{
|
||||||
|
// items may have gaps for unused trade slots
|
||||||
|
if (!item)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
filter.item_id = item->GetID();
|
filter.item_id = item->GetID();
|
||||||
|
|
||||||
int count = item->IsStackable() ? item->GetCharges() : 1;
|
int count = item->IsStackable() ? item->GetCharges() : 1;
|
||||||
if (UpdateTasks(client, filter, count))
|
int updated_count = UpdateTasks(client, filter, count);
|
||||||
|
if (updated_count > 0)
|
||||||
{
|
{
|
||||||
// todo: remove items used in update (highest in case multiple tasks consume same item)
|
// remove items used in updates
|
||||||
|
item->SetCharges(count - updated_count);
|
||||||
|
if (count == updated_count)
|
||||||
|
{
|
||||||
|
item = nullptr; // all items in trade slot consumed
|
||||||
|
}
|
||||||
is_updated = true;
|
is_updated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -782,7 +791,7 @@ void ClientTaskState::UpdateTasksOnKill(Client* client, Client* exp_client, NPC*
|
|||||||
UpdateTasks(client, filter);
|
UpdateTasks(client, filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientTaskState::IncrementDoneCount(
|
int ClientTaskState::IncrementDoneCount(
|
||||||
Client *client,
|
Client *client,
|
||||||
const TaskInformation* task_information,
|
const TaskInformation* task_information,
|
||||||
int task_index,
|
int task_index,
|
||||||
@ -793,7 +802,7 @@ void ClientTaskState::IncrementDoneCount(
|
|||||||
{
|
{
|
||||||
auto info = GetClientTaskInfo(task_information->type, task_index);
|
auto info = GetClientTaskInfo(task_information->type, task_index);
|
||||||
if (info == nullptr) {
|
if (info == nullptr) {
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogTasks(
|
LogTasks(
|
||||||
@ -804,6 +813,9 @@ void ClientTaskState::IncrementDoneCount(
|
|||||||
count
|
count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
int remaining = task_information->activity_information[activity_id].goal_count - info->activity[activity_id].done_count;
|
||||||
|
count = std::min(count, remaining);
|
||||||
|
|
||||||
// shared task shim
|
// shared task shim
|
||||||
// intercept and pass to world first before processing normally
|
// intercept and pass to world first before processing normally
|
||||||
if (!client->m_shared_task_update && task_information->type == TaskType::Shared) {
|
if (!client->m_shared_task_update && task_information->type == TaskType::Shared) {
|
||||||
@ -840,15 +852,11 @@ void ClientTaskState::IncrementDoneCount(
|
|||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
|
|
||||||
return;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->activity[activity_id].done_count += count;
|
info->activity[activity_id].done_count += count;
|
||||||
|
|
||||||
if (info->activity[activity_id].done_count > task_information->activity_information[activity_id].goal_count) {
|
|
||||||
info->activity[activity_id].done_count = task_information->activity_information[activity_id].goal_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ignore_quest_update) {
|
if (!ignore_quest_update) {
|
||||||
std::string export_string = fmt::format(
|
std::string export_string = fmt::format(
|
||||||
"{} {} {}",
|
"{} {} {}",
|
||||||
@ -952,6 +960,8 @@ void ClientTaskState::IncrementDoneCount(
|
|||||||
}
|
}
|
||||||
|
|
||||||
task_manager->SaveClientState(client, this);
|
task_manager->SaveClientState(client, this);
|
||||||
|
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientTaskState::DispatchEventTaskComplete(Client* client, ClientTaskInformation& info, int activity_id)
|
void ClientTaskState::DispatchEventTaskComplete(Client* client, ClientTaskInformation& info, int activity_id)
|
||||||
|
|||||||
@ -59,7 +59,7 @@ public:
|
|||||||
void UpdateTasksForItem(Client* client, TaskActivityType type, NPC* npc, int item_id, int count = 1);
|
void UpdateTasksForItem(Client* client, TaskActivityType type, NPC* npc, int item_id, int count = 1);
|
||||||
void UpdateTasksOnExplore(Client* client, const glm::vec4& loc);
|
void UpdateTasksOnExplore(Client* client, const glm::vec4& loc);
|
||||||
bool UpdateTasksOnSpeakWith(Client* client, NPC* npc);
|
bool UpdateTasksOnSpeakWith(Client* client, NPC* npc);
|
||||||
bool UpdateTasksOnDeliver(Client* client, std::list<EQ::ItemInstance*>& items, int cash, NPC* npc);
|
bool UpdateTasksOnDeliver(Client* client, std::vector<EQ::ItemInstance*>& items, Trade& trade, NPC* npc);
|
||||||
void UpdateTasksOnTouch(Client *client, int dz_switch_id);
|
void UpdateTasksOnTouch(Client *client, int dz_switch_id);
|
||||||
void ProcessTaskProximities(Client *client, float x, float y, float z);
|
void ProcessTaskProximities(Client *client, float x, float y, float z);
|
||||||
bool TaskOutOfTime(TaskType task_type, int index);
|
bool TaskOutOfTime(TaskType task_type, int index);
|
||||||
@ -110,9 +110,9 @@ private:
|
|||||||
std::pair<int, int> FindTask(Client* client, const TaskUpdateFilter& filter) const;
|
std::pair<int, int> FindTask(Client* client, const TaskUpdateFilter& filter) const;
|
||||||
void RecordCompletedTask(uint32_t character_id, const TaskInformation& task, const ClientTaskInformation& client_task);
|
void RecordCompletedTask(uint32_t character_id, const TaskInformation& task, const ClientTaskInformation& client_task);
|
||||||
void UpdateTasksOnKill(Client* client, Client* exp_client, NPC* npc);
|
void UpdateTasksOnKill(Client* client, Client* exp_client, NPC* npc);
|
||||||
bool UpdateTasks(Client* client, const TaskUpdateFilter& filter, int count = 1);
|
int UpdateTasks(Client* client, const TaskUpdateFilter& filter, int count = 1);
|
||||||
|
|
||||||
void IncrementDoneCount(
|
int IncrementDoneCount(
|
||||||
Client *client,
|
Client *client,
|
||||||
const TaskInformation* task_information,
|
const TaskInformation* task_information,
|
||||||
int task_index,
|
int task_index,
|
||||||
|
|||||||
@ -880,20 +880,36 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
|||||||
quest_npc = true;
|
quest_npc = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::any> item_list;
|
// take ownership of all trade slot items
|
||||||
std::list<EQ::ItemInstance*> items;
|
EQ::ItemInstance* insts[4] = { 0 };
|
||||||
for (int i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_NPC_END; ++i) {
|
for (int i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_NPC_END; ++i) {
|
||||||
EQ::ItemInstance *inst = m_inv.GetItem(i);
|
insts[i - EQ::invslot::TRADE_BEGIN] = m_inv.PopItem(i);
|
||||||
if(inst) {
|
database.SaveInventory(CharacterID(), nullptr, i);
|
||||||
items.push_back(inst);
|
}
|
||||||
item_list.push_back(inst);
|
|
||||||
} else {
|
// copy to be filtered by task updates, null trade slots preserved for quest event arg
|
||||||
item_list.push_back((EQ::ItemInstance*)nullptr);
|
std::vector<EQ::ItemInstance*> items(insts, insts + std::size(insts));
|
||||||
|
|
||||||
|
if (RuleB(TaskSystem, EnableTaskSystem)) {
|
||||||
|
if (UpdateTasksOnDeliver(items, *trade, tradingWith->CastToNPC())) {
|
||||||
|
if (!tradingWith->IsMoving())
|
||||||
|
tradingWith->FaceTarget(this);
|
||||||
|
|
||||||
|
EVENT_ITEM_ScriptStopReturn();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo: rule or npc field to auto return normal items also
|
||||||
|
if (!quest_npc)
|
||||||
|
{
|
||||||
|
for (const EQ::ItemInstance* inst : items) {
|
||||||
|
if (!inst || !inst->GetItem()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EQ::ItemData* item = inst->GetItem();
|
const EQ::ItemData* item = inst->GetItem();
|
||||||
if(item && quest_npc == false) {
|
|
||||||
bool isPetAndCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) &&
|
bool isPetAndCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) &&
|
||||||
_CLIENTPET(tradingWith) &&
|
_CLIENTPET(tradingWith) &&
|
||||||
tradingWith->GetPetType()<=petOther);
|
tradingWith->GetPetType()<=petOther);
|
||||||
@ -920,6 +936,7 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (RuleB(NPC, ReturnNonQuestNoDropItems)) {
|
else if (RuleB(NPC, ReturnNonQuestNoDropItems)) {
|
||||||
|
tradingWith->SayString(TRADE_BACK, GetCleanName());
|
||||||
PushItemOnCursor(*baginst, true);
|
PushItemOnCursor(*baginst, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -939,23 +956,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
|||||||
}
|
}
|
||||||
// Return NO DROP and Attuned items being handed into a non-quest NPC if the rule is true
|
// Return NO DROP and Attuned items being handed into a non-quest NPC if the rule is true
|
||||||
else if (RuleB(NPC, ReturnNonQuestNoDropItems)) {
|
else if (RuleB(NPC, ReturnNonQuestNoDropItems)) {
|
||||||
|
tradingWith->SayString(TRADE_BACK, GetCleanName());
|
||||||
PushItemOnCursor(*inst, true);
|
PushItemOnCursor(*inst, true);
|
||||||
DeleteItemInInventory(i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(RuleB(TaskSystem, EnableTaskSystem)) {
|
|
||||||
int Cash = trade->cp + (trade->sp * 10) + (trade->gp * 100) + (trade->pp * 1000);
|
|
||||||
if (UpdateTasksOnDeliver(items, Cash, tradingWith->CastToNPC())) {
|
|
||||||
if(!tradingWith->IsMoving())
|
|
||||||
tradingWith->FaceTarget(this);
|
|
||||||
|
|
||||||
EVENT_ITEM_ScriptStopReturn();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char temp1[100] = { 0 };
|
char temp1[100] = { 0 };
|
||||||
char temp2[100] = { 0 };
|
char temp2[100] = { 0 };
|
||||||
snprintf(temp1, 100, "copper.%d", tradingWith->GetNPCTypeID());
|
snprintf(temp1, 100, "copper.%d", tradingWith->GetNPCTypeID());
|
||||||
@ -975,12 +981,8 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st
|
|||||||
tradingWith->FaceTarget(this);
|
tradingWith->FaceTarget(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
EQ::ItemInstance *insts[4] = { 0 };
|
// quest items are filtered by task deliver updates
|
||||||
for (int i = EQ::invslot::TRADE_BEGIN; i <= EQ::invslot::TRADE_NPC_END; ++i) {
|
std::vector<std::any> item_list(items.begin(), items.end());
|
||||||
insts[i - EQ::invslot::TRADE_BEGIN] = m_inv.PopItem(i);
|
|
||||||
database.SaveInventory(CharacterID(), nullptr, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
parse->EventNPC(EVENT_TRADE, tradingWith->CastToNPC(), this, "", 0, &item_list);
|
parse->EventNPC(EVENT_TRADE, tradingWith->CastToNPC(), this, "", 0, &item_list);
|
||||||
|
|
||||||
for(int i = 0; i < 4; ++i) {
|
for(int i = 0; i < 4; ++i) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user