projecteq-projecteqquests/lua_modules/items.lua
hg 2600236b26 Fix returned item data in items module
The return_data table is being used by table.concat to join a string of
returned items. Since accepted trade items were not being set in this
table, it left gaps so the array part was only valid to the first
accepted item slot.

This caused two issues:

- Depending on the gaps in the return item table, concat could error
  which would halt any event_trade that used it. For example if an
  item was accepted in slot 1 (t[1] nil) with a returned item in t[2],
  concat errored:  `invalid value (nil) at index 1 in table for 'concat'`.

  Since this error only occurs with some gaps, it may be an edge case
  with lua 5.1 that was fixed in later versions.

- Any returned items that were traded in slots after the first accepted
  trade slot were not added to the returned item string for player events
2023-09-27 21:49:51 -04:00

306 lines
No EOL
8.1 KiB
Lua

local items = {}
function items.check_turn_in(trade, trade_check)
--create trade_return table == trade
--shallow copy
local trade_return = {};
for key, value in pairs(trade) do
trade_return[key] = value;
end
-- Handin table for source
local handin_data = {};
for x = 1, 4 do
local inst = trade["item" .. x];
if (inst.valid) then
local is_attuned = 0;
if inst:IsInstNoDrop() then
is_attuned = 1;
end
handin_data[x] = string.format("%d|%d|%d", inst:GetID(), inst:GetCharges(), is_attuned);
else
handin_data[x] = "0|0|0";
end
end
trade.other:SetEntityVariable("HANDIN_ITEMS", items.get_handin_items_serialized(handin_data))
trade.other:SetEntityVariable("HANDIN_MONEY", string.format("%d|%d|%d|%d", trade.copper, trade.silver, trade.gold, trade.platinum))
--for every item in trade_check check trade_return
--if item exists in trade_return then
--remove that item from trade_return
--else
--failure
for i = 1, 4 do
local key = "item" .. i;
if(trade_check[key] ~= nil and trade_check[key] ~= 0) then
local found = false;
for j = 1, 4 do
local inst = trade_return["item" .. j];
if(inst.valid and trade_check[key] == inst:GetID()) then
trade_return["item" .. j] = ItemInst();
found = true;
break;
end
end
if(not found) then
return false;
end
end
end
--convert our money into copper then check that we have enough then convert change back
local trade_check_money = 0;
local return_money = 0;
if(trade_check["platinum"] ~= nil and trade_check["platinum"] ~= 0) then
trade_check_money = trade_check_money + (trade_check["platinum"] * 1000);
end
if(trade_check["gold"] ~= nil and trade_check["gold"] ~= 0) then
trade_check_money = trade_check_money + (trade_check["gold"] * 100);
end
if(trade_check["silver"] ~= nil and trade_check["silver"] ~= 0) then
trade_check_money = trade_check_money + (trade_check["silver"] * 10);
end
if(trade_check["copper"] ~= nil and trade_check["copper"] ~= 0) then
trade_check_money = trade_check_money + trade_check["copper"];
end
return_money = return_money + trade_return["platinum"] * 1000 + trade_return["gold"] * 100;
return_money = return_money + trade_return["silver"] * 10 + trade_return["copper"];
if(return_money < trade_check_money) then
return false;
else
return_money = return_money - trade_check_money;
end
--replace trade with trade_return
trade.item1 = trade_return.item1;
trade.item2 = trade_return.item2;
trade.item3 = trade_return.item3;
trade.item4 = trade_return.item4;
trade.platinum = math.floor(return_money / 1000);
return_money = return_money - (trade.platinum * 1000);
trade.gold = math.floor(return_money / 100);
return_money = return_money - (trade.gold * 100);
trade.silver = math.floor(return_money / 10);
return_money = return_money - (trade.silver * 10);
trade.copper = return_money;
return true;
end
function items.return_items(npc, client, trade, text)
text = text or true;
local returned = false;
-- Handin table for source
local return_data = {};
for i = 1, 4 do
local inst = trade["item" .. i];
if(inst.valid) then
local is_attuned = 0;
if inst:IsInstNoDrop() then
is_attuned = 1;
end
-- remove delivered task items from return for this slot
local return_count = inst:RemoveTaskDeliveredItems()
if(eq.is_disc_tome(inst:GetID()) and npc:GetClass() >= 19 and npc:GetClass() < 36) then
if(client:GetClass() == npc:GetClass() - 19) then
client:TrainDisc(inst:GetID());
else
return_data[#return_data+1] = string.format("%d|%d|%d", inst:GetID(), inst:GetCharges(), is_attuned);
npc:Say(string.format("You are not a member of my guild. I will not train you!"));
if return_count > 0 then
client:PushItemOnCursor(inst);
returned = true;
end
end
elseif return_count > 0 then
return_data[#return_data+1] = string.format("%d|%d|%d", inst:GetID(), inst:GetCharges(), is_attuned);
client:PushItemOnCursor(inst);
if text then
npc:Say(string.format("I have no need for this %s, you can have it back.", client:GetCleanName()));
end
returned = true;
end
end
end
client:SetEntityVariable("RETURN_ITEMS", items.get_handin_items_serialized(return_data))
local money = false;
if(trade.platinum ~= 0) then
returned = true;
money = true;
end
if(trade.gold ~= 0) then
returned = true;
money = true;
end
if(trade.silver ~= 0) then
returned = true;
money = true;
end
if(trade.copper ~= 0) then
returned = true;
money = true;
end
if money then
client:SetEntityVariable("RETURN_MONEY", string.format("%d|%d|%d|%d", trade.copper, trade.silver, trade.gold, trade.platinum));
client:AddMoneyToPP(trade.copper, trade.silver, trade.gold, trade.platinum, true);
end
eq.send_player_handin_event();
return returned;
end
function items.return_bot_items(bot, client, trade, text)
text = text or true;
local returned = false;
for i = 1, 8 do
local inst = trade["item" .. i];
if (inst.valid) then
client:PushItemOnCursor(inst);
returned = true;
end
end
local money = false;
if (trade.platinum ~= 0) then
returned = true;
money = true;
end
if (trade.gold ~= 0) then
returned = true;
money = true;
end
if (trade.silver ~= 0) then
returned = true;
money = true;
end
if (trade.copper ~= 0) then
returned = true;
money = true;
end
if (money) then
client:AddMoneyToPP(trade.copper, trade.silver, trade.gold, trade.platinum, true);
end
if (text and returned) then
bot:OwnerMessage("I have no need for this, you can have it back.")
end
return returned;
end
function items.check_bot_turn_in(trade, trade_check)
--create trade_return table == trade
--shallow copy
local trade_return = {};
for key, value in pairs(trade) do
trade_return[key] = value;
end
--for every item in trade_check check trade_return
--if item exists in trade_return then
--remove that item from trade_return
--else
--failure
for i = 1, 8 do
local key = "item" .. i;
if(trade_check[key] ~= nil and trade_check[key] ~= 0) then
local found = false;
for j = 1, 8 do
local inst = trade_return["item" .. j];
if(inst.valid and trade_check[key] == inst:GetID()) then
trade_return["item" .. j] = ItemInst();
found = true;
break;
end
end
if(not found) then
return false;
end
end
end
--convert our money into copper then check that we have enough then convert change back
local trade_check_money = 0;
local return_money = 0;
if(trade_check["platinum"] ~= nil and trade_check["platinum"] ~= 0) then
trade_check_money = trade_check_money + (trade_check["platinum"] * 1000);
end
if(trade_check["gold"] ~= nil and trade_check["gold"] ~= 0) then
trade_check_money = trade_check_money + (trade_check["gold"] * 100);
end
if(trade_check["silver"] ~= nil and trade_check["silver"] ~= 0) then
trade_check_money = trade_check_money + (trade_check["silver"] * 10);
end
if(trade_check["copper"] ~= nil and trade_check["copper"] ~= 0) then
trade_check_money = trade_check_money + trade_check["copper"];
end
return_money = return_money + trade_return["platinum"] * 1000 + trade_return["gold"] * 100;
return_money = return_money + trade_return["silver"] * 10 + trade_return["copper"];
if(return_money < trade_check_money) then
return false;
else
return_money = return_money - trade_check_money;
end
--replace trade with trade_return
trade.item1 = trade_return.item1;
trade.item2 = trade_return.item2;
trade.item3 = trade_return.item3;
trade.item4 = trade_return.item4;
trade.item5 = trade_return.item5;
trade.item6 = trade_return.item6;
trade.item7 = trade_return.item7;
trade.item8 = trade_return.item8;
trade.platinum = math.floor(return_money / 1000);
return_money = return_money - (trade.platinum * 1000);
trade.gold = math.floor(return_money / 100);
return_money = return_money - (trade.gold * 100);
trade.silver = math.floor(return_money / 10);
return_money = return_money - (trade.silver * 10);
trade.copper = return_money;
return true;
end
function items.get_handin_items_serialized(handin_table)
return table.concat(handin_table, ",")
end
return items;