• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

NPC working with balance.

Mkalo

ボーカロイド
Senator
Joined
Jun 1, 2011
Messages
1,118
Solutions
55
Reaction score
946
Location
Japan
After 10.94:
Premium players no longer need to bring any money to pay for services or wares, as the concerned NPCs now deducts any money missing from their inventory from their Bank Account.

Place this at the first line of npc/lib/npcsystem/modules.lua:
Code:
function Player.removeMoneyNpc(self, amount)
    local moneyCount = self:getMoney()
    local bankCount = self:getBankBalance()
    if amount > moneyCount + bankCount then
        return false
    end

    self:removeMoney(math.min(amount, moneyCount))
    if amount > moneyCount then
        self:setBankBalance(bankCount - math.max(amount - moneyCount, 0))
        if moneyCount == 0 then
            self:sendTextMessage(MESSAGE_INFO_DESCR, ("Paid %d gold from bank account. Your account balance is now %d gold."):format(amount, self:getBankBalance()))
        else
            self:sendTextMessage(MESSAGE_INFO_DESCR, ("Paid %d from inventory and %d gold from bank account. Your account balance is now %d gold."):format(moneyCount, amount - moneyCount, self:getBankBalance()))
        end
    end
    return true
end

local function getPlayerMoney(cid)
    local player = Player(cid)
    if player then
        return player:getMoney() + player:getBankBalance()
    end
    return 0
end

local function doPlayerRemoveMoney(cid, amount)
    local player = Player(cid)
    if player then
        return player:removeMoneyNpc(amount)
    end
    return false
end

Use your text editor to replace every occurence of:
Code:
player:removeMoney(
To:
Code:
player:removeMoneyNpc(

Change:
Code:
void ProtocolGame::sendSaleItemList(const std::list<ShopInfo>& shop)
{
    NetworkMessage msg;
    msg.addByte(0x7B);
    msg.add<uint64_t>(player->getMoney());

To:
Code:
void ProtocolGame::sendSaleItemList(const std::list<ShopInfo>& shop)
{
    NetworkMessage msg;
    msg.addByte(0x7B);
    msg.add<uint64_t>(player->getMoney() + player->getBankBalance());
 
haha did you read my question ?
Great work mate :)
Btw. you are missing this:
Code:
if player:getMoney() < totalCost then
            local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY)
            msg = self.npcHandler:parseMessage(msg, parseInfo)
            player:sendCancelMessage(msg)
            return false
        end
to
Code:
if getPlayerMoney(cid) < totalCost then
            local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY)
            msg = self.npcHandler:parseMessage(msg, parseInfo)
            player:sendCancelMessage(msg)
            return false
        end
 
Last edited:
haha did you read my question ?
Great work mate :)
Btw. you are missing this:
Code:
if player:getMoney() < totalCost then
            local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY)
            msg = self.npcHandler:parseMessage(msg, parseInfo)
            player:sendCancelMessage(msg)
            return false
        end
to
Code:
if getPlayerMoney(cid) < totalCost then
            local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY)
            msg = self.npcHandler:parseMessage(msg, parseInfo)
            player:sendCancelMessage(msg)
            return false
        end
that's the exact same code
 
haha did you read my question ?
Great work mate :)
Btw. you are missing this:
Code:
if player:getMoney() < totalCost then
            local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY)
            msg = self.npcHandler:parseMessage(msg, parseInfo)
            player:sendCancelMessage(msg)
            return false
        end
to
Code:
if getPlayerMoney(cid) < totalCost then
            local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY)
            msg = self.npcHandler:parseMessage(msg, parseInfo)
            player:sendCancelMessage(msg)
            return false
        end
No, I'm not missing anything as I'm using the npcsystem that is in the main repo for TFS 1.2 and there is not player:getMoney() there, however if it does have in yours you should change it.

https://github.com/otland/forgottenserver/blob/master/data/npc/lib/npcsystem/modules.lua#L939-L944

that's the exact same code

Nope it's not the same code as getPlayerMoney is locally edited to work with balance but only inside modules.lua as Player.getMoney is not, as you cannot change this function locally because it is inside a global table (Player)
 
No, I'm not missing anything as I'm using the npcsystem that is in the main repo for TFS 1.2 and there is not player:getMoney() there, however if it does have in yours you should change it.

https://github.com/otland/forgottenserver/blob/master/data/npc/lib/npcsystem/modules.lua#L939-L944



Nope it's not the same code as getPlayerMoney is locally edited to work with balance but only inside modules.lua as Player.getMoney is not, as you cannot change this function locally because it is inside a global table (Player)
I looked inside the if statement im dumb
anyways nice work boi
 
I got this working for TFS 1.0. I don't know if this is the best way but it works, please correct me if wrong. Anyways here are the changes if someone ever needs it.

Place this at the first line of npc/lib/npcsystem/modules.lua:
Code:
function removeMoneyNpc(cid, amount)
    local player = Player(cid)
    local moneyCount = player:getMoney()
      local bankCount = player:getBankBalance()

    if amount > moneyCount + bankCount then
        return false
    end

    player:removeMoney(math.min(amount, moneyCount))
    if amount > moneyCount then
        player:setBankBalance(bankCount - math.max(amount - moneyCount, 0))
        if moneyCount == 0 then
            player:sendTextMessage(MESSAGE_INFO_DESCR, ("Paid %d gold from bank account. Your account balance is now %d gold."):format(amount, player:getBankBalance()))
        else
            player:sendTextMessage(MESSAGE_INFO_DESCR, ("Paid %d from inventory and %d gold from bank account. Your account balance is now %d gold."):format(moneyCount, amount - moneyCount, player:getBankBalance()))
        end
    end
    return true
end

local function getPlayerMoney(cid)
    local player = Player(cid)
    if player then
        return player:getMoney() + player:getBankBalance()
    end
    return false
end

Code:
doPlayerRemoveMoney(cid,
To:
Code:
removeMoneyNpc(cid,

C++ part is the same as the post stated.

14805b84526e746258c36d4b8dfd92a6.png


Full credit goes to MatheusMkalo.
 
I got this working for TFS 1.0. I don't know if this is the best way but it works, please correct me if wrong. Anyways here are the changes if someone ever needs it.

Place this at the first line of npc/lib/npcsystem/modules.lua:
Code:
function removeMoneyNpc(cid, amount)
    local player = Player(cid)
    local moneyCount = player:getMoney()
      local bankCount = player:getBankBalance()

    if amount > moneyCount + bankCount then
        return false
    end

    player:removeMoney(math.min(amount, moneyCount))
    if amount > moneyCount then
        player:setBankBalance(bankCount - math.max(amount - moneyCount, 0))
        if moneyCount == 0 then
            player:sendTextMessage(MESSAGE_INFO_DESCR, ("Paid %d gold from bank account. Your account balance is now %d gold."):format(amount, player:getBankBalance()))
        else
            player:sendTextMessage(MESSAGE_INFO_DESCR, ("Paid %d from inventory and %d gold from bank account. Your account balance is now %d gold."):format(moneyCount, amount - moneyCount, player:getBankBalance()))
        end
    end
    return true
end

local function getPlayerMoney(cid)
    local player = Player(cid)
    if player then
        return player:getMoney() + player:getBankBalance()
    end
    return false
end

Code:
doPlayerRemoveMoney(cid,
To:
Code:
removeMoneyNpc(cid,

C++ part is the same as the post stated.

14805b84526e746258c36d4b8dfd92a6.png


Full credit goes to MatheusMkalo.
Thanks, that's just because npcsystems may vary but the idea is the same, you have to change all the functions that get player money and the ones that remove to the ones that I posted.
 
Im using TFS 1.2 and cannot find the line

void ProtocolGame::sendSaleItemList(const std::list<ShopInfo>& shop)
{
NetworkMessage msg;
msg.addByte(0x7B);
msg.add<uint64_t>(player->getMoney());

tried searching most of the files in folders for parts of that line but i cannot find it, anyone know where to look?
 
Im using TFS 1.2 and cannot find the line

void ProtocolGame::sendSaleItemList(const std::list<ShopInfo>& shop)
{
NetworkMessage msg;
msg.addByte(0x7B);
msg.add<uint64_t>(player->getMoney());

tried searching most of the files in folders for parts of that line but i cannot find it, anyone know where to look?
https://github.com/otland/forgotten...6cfc4e4f2a37257f3e/src/protocolgame.cpp#L1475
https://github.com/otland/forgotten...6cfc4e4f2a37257f3e/src/protocolgame.cpp#L1479
 
The items apear white instead of greyed out when no money on backpack, but when i press buy, i still get client error msg, you dont have enough money.
even tho my bank has millions...

i changed all occurances. i use latest version of TFS and RL map DATAPACK. does it only work with official tfs datapack?
 
@Androico, I got the same problem. Tried to fix this, checked source codes but there everything looks fine.

I have found solution at github
you need to add 1 line code to fix this issue
Lua:
function Player.removeMoneyNpc(self, amount)
+    amount = tonumber(amount) -- ADD THIS LINE
     local moneyCount = self:getMoney()
     local bankCount = self:getBankBalance()
     if amount > moneyCount + bankCount then
 
Last edited by a moderator:
I can't seem to locate where the npc is removing player money on ShopModule:addBuyableItemContainer. Npc is not registering my bank balance and returning MESSAGE_NEEDMONEY.
 
Added the local function to the npc.lua, resolved my issue.

Code:
local function doPlayerRemoveMoney(cid, amount)
    local player = Player(cid)
    if player then
        return player:removeMoneyNpc(amount)
    end
    return false
end
 
A small update for this code for free & premium accounts.

Change this.
C++:
void ProtocolGame::sendSaleItemList(const std::list<ShopInfo>& shop)
{
    NetworkMessage msg;
    msg.addByte(0x7B);
    msg.add<uint64_t>(player->getMoney() + player->getBankBalance());

To this.
C++:
void ProtocolGame::sendSaleItemList(const std::list<ShopInfo>& shop)
{
    NetworkMessage msg;
    msg.addByte(0x7B);
    if (player->isPremium()) {
        msg.add<uint64_t>(player->getMoney() + player->getBankBalance());
    } else {
        msg.add<uint64_t>(player->getMoney());
    }
 
Back
Top