• 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!

TFS 0.X NPC accept money on hands and bank money

gmstrikker

Well-Known Member
Joined
Jul 30, 2014
Messages
458
Solutions
1
Reaction score
50
Using 0.4 source pack, like Fir3element/3777

Should be possible to make when you buy stuff on NPC, like:
Code:
       <parameter key="shop_buyable" value="jagged sword,8602,300;steel axe,8601,300;daramanian mace,2439,300;crimson sword,7385,3000;barbarian axe,2429,3000;clerical mace,2423,3000" />

NPC accept money from your hands, and if you do not have, it accept money from your bank balance?

banknpc.lua
Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

local Topic, count, transfer = {}, {}, {}

function onCreatureAppear(cid)            npcHandler:onCreatureAppear(cid)        end
function onCreatureDisappear(cid)        npcHandler:onCreatureDisappear(cid)        end
function onCreatureSay(cid, type, msg)        npcHandler:onCreatureSay(cid, type, msg)    end
function onThink()                npcHandler:onThink()                end


local function getCount(s)
    local b, e = s:find('%d+')
    return b and e and math.min(4294967295, tonumber(s:sub(b, e))) or -1
end

local function findPlayer(name)
    local resultId = db.storeQuery('SELECT name FROM players WHERE name=' .. db.escapeString(name) .. ' LIMIT 1'), nil
    if resultId == false then
        return
    end
    local r = result.getDataString(resultId, "name")
    result.free(resultId)
    return r
end

local function getTown(name)
    local resultId = db.storeQuery('SELECT town_id FROM players WHERE name=' .. db.escapeString(name) .. ' LIMIT 1'), nil
    if resultId == false then
        return
    end
    local r = result.getDataInt(resultId, "town_id")
    result.free(resultId)
    return r
end

local function vocation(name)
    local resultId = db.storeQuery('SELECT vocation FROM players WHERE name=' .. db.escapeString(name) .. ' LIMIT 1'), nil
    if resultId == false then
        return
    end
    local r = result.getDataInt(resultId, "vocation")
    result.free(resultId)
    return r
end

local function updatePlayerBalance(name, value)
    db.query('UPDATE players SET balance=' .. value .. ' WHERE name=' .. db.escapeString(name) .. ' LIMIT 1')
end

function greet(cid)
    Topic[cid], count[cid], transfer[cid] = nil, nil, nil
    return true
end

function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    elseif msgcontains(msg, 'balance') then
        npcHandler:say('Your account balance is ' .. getPlayerBalance(cid) .. ' gold.', cid)
        Topic[cid] = nil
    elseif msgcontains(msg, 'deposit') and msgcontains(msg, 'all') then
        if getPlayerMoney(cid) == 0 then
            npcHandler:say('You don\'t have any gold with you.', cid)
            Topic[cid] = nil
        else
            count[cid] = getPlayerMoney(cid)
            npcHandler:say('Would you really like to deposit ' .. count[cid] .. ' gold?', cid)
            Topic[cid] = 2
        end
    elseif msgcontains(msg, 'deposit') then
        if getCount(msg) == 0 then
            npcHandler:say('You are joking, aren\'t you??', cid)
            Topic[cid] = nil
        elseif getCount(msg) ~= -1 then
            if getPlayerMoney(cid) >= getCount(msg) then
                count[cid] = getCount(msg)
                npcHandler:say('Would you really like to deposit ' .. count[cid] .. ' gold?', cid)
                Topic[cid] = 2
            else
                npcHandler:say('You do not have enough gold.', cid)
                Topic[cid] = nil
            end
        elseif getPlayerMoney(cid) == 0 then
            npcHandler:say('You don\'t have any gold with you.', cid)
            Topic[cid] = nil
        else
            npcHandler:say('Please tell me how much gold it is you would like to deposit.', cid)
            Topic[cid] = 1
        end
    elseif Topic[cid] == 1 then
        if getCount(msg) == -1 then
            npcHandler:say('Please tell me how much gold it is you would like to deposit.', cid)
            Topic[cid] = 1
        elseif getPlayerMoney(cid) >= getCount(msg) then
            count[cid] = getCount(msg)
            npcHandler:say('Would you really like to deposit ' .. count[cid] .. ' gold?', cid)
            Topic[cid] = 2
        else
            npcHandler:say('You do not have enough gold.', cid)
            Topic[cid] = nil
        end
    elseif msgcontains(msg, 'yes') and Topic[cid] == 2 then
        if doPlayerRemoveMoney(cid, count[cid]) then
            doPlayerSetBalance(cid, getPlayerBalance(cid) + count[cid])
            updatePlayerBalance(getCreatureByName(cid), getPlayerBalance(cid))
            npcHandler:say('Alright, we have added the amount of ' .. count[cid] .. ' gold to your balance. You can withdraw your money anytime you want to.', cid)
        else
            npcHandler:say('I am inconsolable, but it seems you have lost your gold. I hope you get it back.', cid)
        end
        Topic[cid] = nil
    elseif msgcontains(msg, 'no') and Topic[cid] == 2 then
        npcHandler:say('As you wish. Is there something else I can do for you?', cid)
        Topic[cid] = nil
    elseif msgcontains(msg, 'withdraw') then
        if getCount(msg) == 0 then
            npcHandler:say('Sure, you want nothing you get nothing!', cid)
            Topic[cid] = nil
        elseif getCount(msg) ~= -1 then
            if getPlayerBalance(cid) >= getCount(msg) then
                count[cid] = getCount(msg)
                npcHandler:say('Are you sure you wish to withdraw ' .. count[cid] .. ' gold from your bank account?', cid)
                Topic[cid] = 4
            else
                npcHandler:say('There is not enough gold on your account.', cid)
                Topic[cid] = nil
            end
        elseif getPlayerBalance(cid) == 0 then
            npcHandler:say('You don\'t have any money on your bank account.', cid)
            Topic[cid] = nil
        else
            npcHandler:say('Please tell me how much gold you would like to withdraw.', cid)
            Topic[cid] = 3
        end
    elseif Topic[cid] == 3 then
        if getCount(msg) == -1 then
            npcHandler:say('Please tell me how much gold you would like to withdraw.', cid)
            Topic[cid] = 3
        elseif getPlayerBalance(cid) >= getCount(msg) then
            count[cid] = getCount(msg)
            npcHandler:say('Are you sure you wish to withdraw ' .. count[cid] .. ' gold from your bank account?', cid)
            Topic[cid] = 4
        else
            npcHandler:say('There is not enough gold on your account.', cid)
            Topic[cid] = nil
        end
    elseif msgcontains(msg, 'yes') and Topic[cid] == 4 then
        if getPlayerBalance(cid) >= count[cid] then
            doPlayerAddMoney(cid, count[cid])
            doPlayerSetBalance(cid, getPlayerBalance(cid) - count[cid])
            updatePlayerBalance(getCreatureByName(cid), getPlayerBalance(cid))
            npcHandler:say('Here you are, ' .. count[cid] .. ' gold. Please let me know if there is something else I can do for you.', cid)
        else
            npcHandler:say('There is not enough gold on your account.', cid)
        end
        Topic[cid] = nil
    elseif msgcontains(msg, 'no') and Topic[cid] == 4 then
        npcHandler:say('The customer is king! Come back anytime you want to if you wish to withdraw your money.', cid)
        Topic[cid] = nil
    elseif msgcontains(msg, 'transfer') then
        if getCount(msg) == 0 then
            npcHandler:say('Please think about it. Okay?', cid)
            Topic[cid] = nil
        elseif getCount(msg) ~= -1 then
     
            count[cid] = getCount(msg)
            if getPlayerBalance(cid) >= count[cid] then
                npcHandler:say('Who would you like to transfer ' .. count[cid] .. ' gold to?', cid)
                Topic[cid] = 6
            else
                npcHandler:say('There is not enough gold on your account.', cid)
                Topic[cid] = nil
            end

        else
            npcHandler:say('Please tell me the amount of gold you would like to transfer.', cid)
            Topic[cid] = 5
        end
    elseif Topic[cid] == 5 then
        if getCount(msg) == -1 then
            npcHandler:say('Please tell me the amount of gold you would like to transfer.', cid)
            Topic[cid] = 5
        else
            count[cid] = getCount(msg)
            if getPlayerBalance(cid) >= count[cid] then
                npcHandler:say('Who would you like to transfer ' .. count[cid] .. ' gold to?', cid)
                Topic[cid] = 6
            else
                npcHandler:say('There is not enough gold on your account.', cid)
                Topic[cid] = nil
            end
        end
    elseif Topic[cid] == 6 then
        local v = getCreatureByName(msg)
        if getPlayerBalance(cid) >= count[cid] then
            local temp = (v and getCreatureName(v) or false)
            if temp then
                if getPlayerTown(v) == 7 then
                    if getPlayerTown(cid) ~= getPlayerTown(v) then
                        npcHandler:say('You can not transfer money to players from Rookgaardia if you are not from Rookgaardia.', cid)
                        Topic[cid] = nil
                        return true
                    end
                elseif getPlayerTown(v) == 9 then
                    if getPlayerTown(cid) ~= getPlayerTown(v) then
                        npcHandler:say('You can not transfer money to players from Dawn Hills if you are not from Dawn Hills.', cid)
                        Topic[cid] = nil
                        return true
                    end
                end


                transfer[cid] = msg
                npcHandler:say('Would you really like to transfer ' .. count[cid] .. ' gold to ' .. temp .. '?', cid)
                Topic[cid] = 7
            elseif getPlayerGUIDByName(msg:lower()) ~= 0 then
                if getTown(msg:lower()) == 7 then
                    if getPlayerTown(cid) ~= 7 then
                        npcHandler:say('You can not transfer money to players from Rookgaardia if you are not from Rookgaardia.', cid)
                        Topic[cid] = nil
                        return true
                    end
                elseif getTown(msg:lower()) == 9 then
                    if getPlayerTown(cid) ~= 9 then
                        npcHandler:say('You can not transfer money to players from Dawn Hills if you are not from Dawn Hills.', cid)
                        Topic[cid] = nil
                        return true
                    end
                end


                transfer[cid] = msg
                npcHandler:say('Would you really like to transfer ' .. count[cid] .. ' gold to ' .. findPlayer(msg) .. '?', cid)
                Topic[cid] = 7              
            else
                npcHandler:say('This player does not exist on this world!', cid)
                Topic[cid] = nil
            end
        else
            npcHandler:say('There is not enough gold on your account.', cid)
            Topic[cid] = nil
        end
    elseif Topic[cid] == 7 and msgcontains(msg, 'yes') then
        if getPlayerBalance(cid) >= count[cid] then
            local v = getCreatureByName(transfer[cid])
            if v then
                doPlayerSetBalance(cid, getPlayerBalance(cid) - count[cid])
                updatePlayerBalance(getCreatureName(cid), getPlayerBalance(cid))
                doPlayerSetBalance(v, getPlayerBalance(v) + count[cid])
                updatePlayerBalance(getCreatureName(v), getPlayerBalance(v))
                npcHandler:say('Very well. You have transferred ' .. count[cid] .. ' gold to ' .. getCreatureName(v) .. '.', cid)
            elseif findPlayer(transfer[cid]):lower() == transfer[cid]:lower() then
                doPlayerSetBalance(cid, getPlayerBalance(cid) - count[cid])
                updatePlayerBalance(getCreatureName(cid), getPlayerBalance(cid))
                db.query('UPDATE players SET balance=balance+' .. count[cid] .. ' WHERE name=' .. db.escapeString(transfer[cid]) .. ' LIMIT 1')
                npcHandler:say('Very well. You have transferred ' .. count[cid] .. ' gold to ' .. findPlayer(transfer[cid]) .. '.', cid)
            else
                npcHandler:say('This player does not exist.', cid)
            end
        else
            npcHandler:say('There is not enough gold on your account.', cid)
        end
        Topic[cid] = nil
    elseif Topic[cid] == 7 and msgcontains(msg, 'no') then
        npcHandler:say('Alright, is there something else I can do for you?', cid)
        Topic[cid] = nil
    elseif msgcontains(msg, 'change gold') then
        npcHandler:say('How many platinum coins would you like to get?', cid)
        Topic[cid] = 8
    elseif Topic[cid] == 8 then
        if getCount(msg) < 1 then
            npcHandler:say('Hmm, can I help you with something else?', cid)
            Topic[cid] = nil
        else
            count[cid] = math.min(500, getCount(msg))
            npcHandler:say('So you would like me to change ' .. count[cid] * 100 .. ' of your gold coins into ' .. count[cid] .. ' platinum coins?', cid)
            Topic[cid] = 9
        end
    elseif Topic[cid] == 9 then
        if msgcontains(msg, 'yes') then
            if doPlayerRemoveItem(cid, 2148, count[cid] * 100) then
                npcHandler:say('Here you are.', cid)
                doPlayerAddItem(cid, 2152, count[cid])
            else
                npcHandler:say('Sorry, you do not have enough gold coins.', cid)
            end
        else
            npcHandler:say('Well, can I help you with something else?', cid)
        end
        Topic[cid] = nil
    elseif msgcontains(msg, 'change platinum') then
        npcHandler:say('Would you like to change your platinum coins into gold or crystal?', cid)
        Topic[cid] = 10
    elseif Topic[cid] == 10 then
        if msgcontains(msg, 'gold') then
            npcHandler:say('How many platinum coins would you like to change into gold?', cid)
            Topic[cid] = 11
        elseif msgcontains(msg, 'crystal') then
            npcHandler:say('How many crystal coins would you like to get?', cid)
            Topic[cid] = 13
        else
            npcHandler:say('Well, can I help you with something else?', cid)
            Topic[cid] = nil
        end
    elseif Topic[cid] == 11 then
        if getCount(msg) < 1 then
            npcHandler:say('Hmm, can I help you with something else?', cid)
            Topic[cid] = nil
        else
            count[cid] = math.min(500, getCount(msg))
            npcHandler:say('So you would like me to change ' .. count[cid] .. ' of your platinum coins into ' .. count[cid] * 100 .. ' gold coins for you?', cid)
            Topic[cid] = 12
        end
    elseif Topic[cid] == 12 then
        if msgcontains(msg, 'yes') then
            if doPlayerRemoveItem(cid, 2152, count[cid]) then
                npcHandler:say('Here you are.', cid)
                doPlayerAddItem(cid, 2148, count[cid] * 100)
            else
                npcHandler:say('Sorry, you do not have enough platinum coins.', cid)
            end
        else
            npcHandler:say('Well, can I help you with something else?', cid)
        end
        Topic[cid] = nil
    elseif Topic[cid] == 13 then
        if getCount(msg) < 1 then
            npcHandler:say('Hmm, can I help you with something else?', cid)
            Topic[cid] = nil
        else
            count[cid] = math.min(500, getCount(msg))
            npcHandler:say('So you would like me to change ' .. count[cid] * 100 .. ' of your platinum coins into ' .. count[cid] .. ' crystal coins for you?', cid)
            Topic[cid] = 14
        end
    elseif Topic[cid] == 14 then
        if msgcontains(msg, 'yes') then
            if doPlayerRemoveItem(cid, 2152, count[cid] * 100) then
                npcHandler:say('Here you are.', cid)
                doPlayerAddItem(cid, 2160, count[cid])
            else
                npcHandler:say('Sorry, you do not have enough platinum coins.', cid)
            end
        else
            npcHandler:say('Well, can I help you with something else?', cid)
        end
        Topic[cid] = nil
    elseif msgcontains(msg, 'change crystal') then
        npcHandler:say('How many crystal coins would you like to change into platinum?', cid)
        Topic[cid] = 15
    elseif Topic[cid] == 15 then
        if getCount(msg) == -1 or getCount(msg) == 0 then
            npcHandler:say('Hmm, can I help you with something else?', cid)
            Topic[cid] = nil
        else
            count[cid] = math.min(500, getCount(msg))
            npcHandler:say('So you would like me to change ' .. count[cid] .. ' of your crystal coins into ' .. count[cid] * 100 .. ' platinum coins for you?', cid)
            Topic[cid] = 16
        end
    elseif Topic[cid] == 16 then
        if msgcontains(msg, 'yes') then
            if doPlayerRemoveItem(cid, 2160, count[cid]) then
                npcHandler:say('Here you are.', cid)
                doPlayerAddItem(cid, 2152, count[cid] * 100)
            else
                npcHandler:say('Sorry, you do not have enough crystal coins.', cid)
            end
        else
            npcHandler:say('Well, can I help you with something else?', cid)
        end
        Topic[cid] = nil
    elseif msgcontains(msg, 'change') then
        npcHandler:say('There are three different coin types in Tibia: 100 gold coins equal 1 platinum coin, 100 platinum coins equal 1 crystal coin. So if you\'d like to change 100 gold into 1 platinum, simply say \'{change gold}\' and then \'1 platinum\'.', cid)
        Topic[cid] = nil
    elseif msgcontains(msg, 'bank') then
        npcHandler:say('We can change money for you. You can also access your bank account.', cid)
        Topic[cid] = nil
    end
    return true
end

npcHandler:setCallback(CALLBACK_GREET, greet)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

- ps: without make buy items like on 7x, saying buy x item, i mean, should possible do it in 'trade' square?
 
you only need to add this indeed,
C++:
   // Not enough money
    if(moneyCount < money)
{
        return false;
}
  // if the player balance
  //  is greater than the Cost - money on hand
    if(player->balance  >  money - moneyCount)
{
    // remove the money that the player doesnt have
    // on hand
    player-> balance = player->balance - ( money -moneyCount)
  // set the cost to the money amount you have on hand.
money = moneycount;
       
}
else
{
// if the money on hand + player-> balance  is inferior to the cost, return false
return false
}



I dont have visual studio openned, so there might be synthax error, but that is what I meant
 
Srry i just don't know how to edit source, i just edit simple scripts in LUA, but would be nice have OT 8.6 with this function...

I've tried what u told to do, but asks to player reference, i tried to do like i saw in houses.cpp, but gave another error, i think i'm doing something wrong...

Code:
bool Game::removeMoney(Player* player, Cylinder* cylinder, int64_t money, uint32_t flags /*= 0*/)
{
   if(!cylinder)
       return false;

   if(money <= 0)
       return true;

   typedef std::multimap<int32_t, Item*, std::less<int32_t> > MoneyMultiMap;
   MoneyMultiMap moneyMap;

   std::list<Container*> listContainer;
   Container* tmpContainer = NULL;

   Thing* thing = NULL;
   Item* item = NULL;

   int64_t moneyCount = 0;
   for(int32_t i = cylinder->__getFirstIndex(); i < cylinder->__getLastIndex() && money > 0; ++i)
   {
       if(!(thing = cylinder->__getThing(i)) || !(item = thing->getItem()))
           continue;

       if((tmpContainer = item->getContainer()))
           listContainer.push_back(tmpContainer);
       else if(item->getWorth() != 0)
       {
           moneyCount += item->getWorth();
           moneyMap.insert(std::make_pair(item->getWorth(), item));
       }
   }

   while(listContainer.size() > 0 && money > 0)
   {
       Container* container = listContainer.front();
       listContainer.pop_front();
       for(int32_t i = 0; i < (int32_t)container->size() && money > 0; i++)
       {
           Item* item = container->getItem(i);
           if((tmpContainer = item->getContainer()))
               listContainer.push_back(tmpContainer);
           else if(item->getWorth() != 0)
           {
               moneyCount += item->getWorth();
               moneyMap.insert(std::make_pair(item->getWorth(), item));
           }
       }
   }

   // Not enough money
    if(moneyCount < money)
   {
       return false;
   }
   // if the player balance
   //  is greater than the Cost - money on hand
    if(player->balance  >  money - moneyCount)
   {
       // remove the money that the player doesnt have
       // on hand
       player-> balance = player->balance - ( money -moneyCount)
       // set the cost to the money amount you have on hand.
       money = moneycount;  
   }
   else
   {
       // if the money on hand + player-> balance  is inferior to the cost, return false
       return false
   }

   for(MoneyMultiMap::iterator mit = moneyMap.begin(); mit != moneyMap.end() && money > 0; ++mit)
   {
       Item* item = mit->second;
       if(!item)
           continue;

       internalRemoveItem(NULL, item);
       if(mit->first > money)
       {
           // Remove a monetary value from an item
           addMoney(cylinder, (int64_t)(item->getWorth() - money), flags);
           money = 0;
       }
       else
           money -= mit->first;

       mit->second = NULL;
   }

   moneyMap.clear();
   return money == 0;
}

Code:
game.cpp:1951:6: error: prototype for ‘bool Game::removeMoney(Player*, Cylinder*, int64_t, uint32_t)’ does not match any in class ‘Game’
 bool Game::removeMoney(Player* player, Cylinder* cylinder, int64_t money, uint32_t flags /*= 0*/)
      ^~~~
In file included from game.cpp:18:0:
game.h:399:8: error: candidate is: bool Game::removeMoney(Cylinder*, int64_t, uint32_t)
   bool removeMoney(Cylinder* cylinder, int64_t money, uint32_t flags = 0);
        ^~~~~~~~~~~
Makefile:33: recipe for target 'game.o' failed
make: *** [game.o] Error 1

The original one is
Code:
bool Game::removeMoney(Cylinder* cylinder, int64_t money, uint32_t flags /*= 0*/)

And do you guys know how to send a message in chat green showing bank balance:
Code:
    if(player->balance  >  money - moneyCount)
   {
       // remove the money that the player doesnt have
       // on hand
       player-> balance = player->balance - ( money -moneyCount)
       // set the cost to the money amount you have on hand.
       money = moneycount;  

      GREENMSG("Your bank balance now is: 159");
   }
 
Sources doesn't work like that, to call a function, the sources are separated in classes. every classes owns their functions. Every functions has some parameter defined and are required if you want to call the function... You must find which class own the function that you want to call, then you must pass the correct parameter to the function. Take time to read a bit about how C++ works, it will saves you a lot of time.
 
Sources doesn't work like that, to call a function, the sources are separated in classes. every classes owns their functions. Every functions has some parameter defined and are required if you want to call the function... You must find which class own the function that you want to call, then you must pass the correct parameter to the function. Take time to read a bit about how C++ works, it will saves you a lot of time.

I FINALLY FOUND!

in talkaction.cpp, line 1285:
player->sendTextMessage(MSG_INFO_DESCR, "Your bank balance now is: ". player->balance);

but i still have that bug to declare player, how to do?
Code:
game.cpp: In member function ‘bool Game::removeMoney(Cylinder*, int64_t, uint32_t)’:
game.cpp:2007:8: error: ‘player’ was not declared in this scope
     if(player->balance  >  money - moneyCount)
        ^~~~~~
game.cpp:2015:73: error: request for member ‘player’ in ‘"Your bank balance now is: "’, which is of non-class type ‘const char [27]’
   player->sendTextMessage(MSG_INFO_DESCR, "Your bank balance now is: ". player->balance);
                                                                         ^~~~~~
game.cpp:2021:2: error: expected ‘;’ before ‘}’ token
  }
  ^

Code:
bool Game::removeMoney(Cylinder* cylinder, int64_t money, uint32_t flags /*= 0*/)
{
   if(!cylinder)
       return false;

   if(money <= 0)
       return true;

   typedef std::multimap<int32_t, Item*, std::less<int32_t> > MoneyMultiMap;
   MoneyMultiMap moneyMap;

   std::list<Container*> listContainer;
   Container* tmpContainer = NULL;

   Thing* thing = NULL;
   Item* item = NULL;

   int64_t moneyCount = 0;
   for(int32_t i = cylinder->__getFirstIndex(); i < cylinder->__getLastIndex() && money > 0; ++i)
   {
       if(!(thing = cylinder->__getThing(i)) || !(item = thing->getItem()))
           continue;

       if((tmpContainer = item->getContainer()))
           listContainer.push_back(tmpContainer);
       else if(item->getWorth() != 0)
       {
           moneyCount += item->getWorth();
           moneyMap.insert(std::make_pair(item->getWorth(), item));
       }
   }

   while(listContainer.size() > 0 && money > 0)
   {
       Container* container = listContainer.front();
       listContainer.pop_front();
       for(int32_t i = 0; i < (int32_t)container->size() && money > 0; i++)
       {
           Item* item = container->getItem(i);
           if((tmpContainer = item->getContainer()))
               listContainer.push_back(tmpContainer);
           else if(item->getWorth() != 0)
           {
               moneyCount += item->getWorth();
               moneyMap.insert(std::make_pair(item->getWorth(), item));
           }
       }
   }

   // Not enough money
    if(moneyCount < money)
   {
       return false;
   }
   // if the player balance
   //  is greater than the Cost - money on hand
    if(player->balance  >  money - moneyCount)
   {
       // remove the money that the player doesnt have
       // on hand
       player-> balance = player->balance - ( money -moneyCount)
       // set the cost to the money amount you have on hand.
       money = moneycount;
       // message to player
       player->sendTextMessage(MSG_INFO_DESCR, "Your bank balance now is: ". player->balance);
   }
   else
   {
       // if the money on hand + player-> balance  is inferior to the cost, return false
       return false
   }

   for(MoneyMultiMap::iterator mit = moneyMap.begin(); mit != moneyMap.end() && money > 0; ++mit)
   {
       Item* item = mit->second;
       if(!item)
           continue;

       internalRemoveItem(NULL, item);
       if(mit->first > money)
       {
           // Remove a monetary value from an item
           addMoney(cylinder, (int64_t)(item->getWorth() - money), flags);
           money = 0;
       }
       else
           money -= mit->first;

       mit->second = NULL;
   }

   moneyMap.clear();
   return money == 0;
}
 
So, if you remember correctly, the function removeMoney was called by the class npc.cpp from case at line 1475, if you look closely, all the case are part of a the function that start a line 1306 : void Npc::executeResponse(Player* player, NpcState* npcState, const NpcResponse* response)
Which has the player defined. now,
At line 1524 in npc.cpp , you can find g_game.removeMoney(player, moneyCount);

but at line 1942 in game.cpp, you have: bool Game::removeMoney(Cylinder* cylinder, int64_t money, uint32_t flags /*= 0*/)
it use Cylinder class which I think is the parent class.

the virtual keyword used before the function below means that the function will be overridden by child class function (with the keyword override before the function name) if a child class exist with the same function , otherwise, it executes normally,
so,
in cylinder.h you have,
virtual Creature* getCreature() = 0;
and in creature.h you have,
virtual Player* getPlayer() {return NULL;}

Starting from the information passed to the method, you have a Cylinder,
so you could try to call something like this:
if (cylinder.getCreature() != null)
{
if ( cylinder.getCreature().getPlayer() != null)
{
Player* player = cylinder.getCreature().getPlayer();
}
}

Once again, I don't have visual studio openned cause I dont have C++ installed in it, and I am not an expert in C++, my only expertise are in C# which is quite simillar, so there might be some synthax error, hope it does help you!
 
Like this?
Code:
bool Game::removeMoney(Cylinder* cylinder, int64_t money, uint32_t flags /*= 0*/)
{
   if(!cylinder)
       return false;

   if(money <= 0)
       return true;

   typedef std::multimap<int32_t, Item*, std::less<int32_t> > MoneyMultiMap;
   MoneyMultiMap moneyMap;

   std::list<Container*> listContainer;
   Container* tmpContainer = NULL;

   Thing* thing = NULL;
   Item* item = NULL;

   int64_t moneyCount = 0;
   for(int32_t i = cylinder->__getFirstIndex(); i < cylinder->__getLastIndex() && money > 0; ++i)
   {
       if(!(thing = cylinder->__getThing(i)) || !(item = thing->getItem()))
           continue;

       if((tmpContainer = item->getContainer()))
           listContainer.push_back(tmpContainer);
       else if(item->getWorth() != 0)
       {
           moneyCount += item->getWorth();
           moneyMap.insert(std::make_pair(item->getWorth(), item));
       }
   }

   while(listContainer.size() > 0 && money > 0)
   {
       Container* container = listContainer.front();
       listContainer.pop_front();
       for(int32_t i = 0; i < (int32_t)container->size() && money > 0; i++)
       {
           Item* item = container->getItem(i);
           if((tmpContainer = item->getContainer()))
               listContainer.push_back(tmpContainer);
           else if(item->getWorth() != 0)
           {
               moneyCount += item->getWorth();
               moneyMap.insert(std::make_pair(item->getWorth(), item));
           }
       }
   }



   // Not enough money
    if(moneyCount < money)
   {
       return false;
   }
   // if the player balance
   //  is greater than the Cost - money on hand
   if (cylinder.getCreature() != NULL)
   {
       if ( cylinder.getCreature().getPlayer() != NULL)
       {
           Player* player = cylinder.getCreature().getPlayer();
       }
   }
    if(player->balance  >  money - moneyCount)
   {
       // remove the money that the player doesnt have
       // on hand
       player-> balance = player->balance - ( money -moneyCount);
       // set the cost to the money amount you have on hand.
       money = moneycount;
       // message to player
       player->sendTextMessage(MSG_INFO_DESCR, "Your bank balance now is: " << player->balance << ".");
   }
   else
   {
       // if the money on hand + player-> balance  is inferior to the cost, return false
       return false;
   }



   for(MoneyMultiMap::iterator mit = moneyMap.begin(); mit != moneyMap.end() && money > 0; ++mit)
   {
       Item* item = mit->second;
       if(!item)
           continue;

       internalRemoveItem(NULL, item);
       if(mit->first > money)
       {
           // Remove a monetary value from an item
           addMoney(cylinder, (int64_t)(item->getWorth() - money), flags);
           money = 0;
       }
       else
           money -= mit->first;

       mit->second = NULL;
   }

   moneyMap.clear();
   return money == 0;
}

I changed somethings i saw was wrong...
But still got some errors that i don't know what to do...
Do you do?

Code:
game.cpp: In member function ‘bool Game::removeMoney(Cylinder*, int64_t, uint32_t)’:
game.cpp:2009:15: error: request for member ‘getCreature’ in ‘cylinder’, which is of pointer type ‘Cylinder*’ (maybe you meant to use ‘->’ ?)
  if (cylinder.getCreature() != NULL)
               ^~~~~~~~~~~
game.cpp:2011:17: error: request for member ‘getCreature’ in ‘cylinder’, which is of pointer type ‘Cylinder*’ (maybe you meant to use ‘->’ ?)
   if ( cylinder.getCreature().getPlayer() != NULL)
                 ^~~~~~~~~~~
game.cpp:2013:30: error: request for member ‘getCreature’ in ‘cylinder’, which is of pointer type ‘Cylinder*’ (maybe you meant to use ‘->’ ?)
    Player* player = cylinder.getCreature().getPlayer();
                              ^~~~~~~~~~~
game.cpp:2013:12: warning: unused variable ‘player’ [-Wunused-variable]
    Player* player = cylinder.getCreature().getPlayer();
            ^~~~~~
game.cpp:2016:8: error: ‘player’ was not declared in this scope
     if(player->balance  >  money - moneyCount)
        ^~~~~~
game.cpp:2022:11: error: ‘moneycount’ was not declared in this scope
   money = moneycount;
           ^~~~~~~~~~
Makefile:33: recipe for target 'game.o' failed

2009 is
Code:
if (cylinder.getCreature() != NULL)

---

edit: thank you to still helping us
 
You mean, this:
Code:
...
bool Game::removeMoney(Cylinder* cylinder, int64_t money, uint32_t flags /*= 0*/)
{
   if(!cylinder)
       return false;

   if(money <= 0)
       return true;

   typedef std::multimap<int32_t, Item*, std::less<int32_t> > MoneyMultiMap;
   MoneyMultiMap moneyMap;

   std::list<Container*> listContainer;
   Container* tmpContainer = NULL;

   Thing* thing = NULL;
   Item* item = NULL;

   int64_t moneyCount = 0;
   for(int32_t i = cylinder->__getFirstIndex(); i < cylinder->__getLastIndex() && money > 0; ++i)
   {
       if(!(thing = cylinder->__getThing(i)) || !(item = thing->getItem()))
           continue;

       if((tmpContainer = item->getContainer()))
           listContainer.push_back(tmpContainer);
       else if(item->getWorth() != 0)
       {
           moneyCount += item->getWorth();
           moneyMap.insert(std::make_pair(item->getWorth(), item));
       }
   }

   while(listContainer.size() > 0 && money > 0)
   {
       Container* container = listContainer.front();
       listContainer.pop_front();
       for(int32_t i = 0; i < (int32_t)container->size() && money > 0; i++)
       {
           Item* item = container->getItem(i);
           if((tmpContainer = item->getContainer()))
               listContainer.push_back(tmpContainer);
           else if(item->getWorth() != 0)
           {
               moneyCount += item->getWorth();
               moneyMap.insert(std::make_pair(item->getWorth(), item));
           }
       }
   }



   // Not enough money
    if(moneyCount < money)
   {
       return false;
   }
   // if the player balance
   //  is greater than the Cost - money on hand
   if (cylinder.getCreature() != NULL)
   {
       if ( cylinder.getCreature().getPlayer() != NULL)
       {
           Player* player = cylinder->getCreature()->getPlayer();
       }
   }
    if(player->balance  >  money - moneyCount)
   {
       // remove the money that the player doesnt have
       // on hand
       player-> balance = player->balance - ( money -moneyCount);
       // set the cost to the money amount you have on hand.
       money = moneycount;
       // message to player
       player->sendTextMessage(MSG_INFO_DESCR, "Your bank balance now is: " << player->balance << ".");
   }
   else
   {
       // if the money on hand + player-> balance  is inferior to the cost, return false
       return false;
   }
...

Code:
game.cpp: In member function ‘bool Game::removeMoney(Cylinder*, int64_t, uint32_t)’:
game.cpp:2009:15: error: request for member ‘getCreature’ in ‘cylinder’, which is of pointer type ‘Cylinder*’ (maybe you meant to use ‘->’ ?)
  if (cylinder.getCreature() != NULL)
               ^~~~~~~~~~~
game.cpp:2011:17: error: request for member ‘getCreature’ in ‘cylinder’, which is of pointer type ‘Cylinder*’ (maybe you meant to use ‘->’ ?)
   if ( cylinder.getCreature().getPlayer() != NULL)
                 ^~~~~~~~~~~
game.cpp:2013:12: warning: unused variable ‘player’ [-Wunused-variable]
    Player* player = cylinder->getCreature()->getPlayer();
            ^~~~~~
game.cpp:2016:8: error: ‘player’ was not declared in this scope
     if(player->balance  >  money - moneyCount)
        ^~~~~~
game.cpp:2022:11: error: ‘moneycount’ was not declared in this scope
   money = moneycount;
           ^~~~~~~~~~
Makefile:33: recipe for target 'game.o' failed
make: *** [game.o] Error 1
 
yeah but you have to declare the variable Player* player in the same scope, and you have to replace it everywhere like this
C++:
Player* player = null;
if (cylinder->getCreature() != NULL)
{
if ( cylinder->getCreature()->getPlayer() != NULL)
{
player = cylinder->getCreature()->getPlayer();
}
}
 
Last edited:
Variable-scope-in-C.png


You can go read about variable scope but basicly it works like this

everything that is in local scope can read variable that are in his local scope and global scope,
If you declare a variable inside a if statement, only what is inside of this scope can access the variable, That is why you have to declare it in the same scope where you gonna use the variable.
So I'm simply declaring it like this Player* player = null, it gonna gets modified by the If statement, because it is in the same scope.
I'm having difficulty to vulgarize things, but if you don't understand, take a few minutes reading on google and i'm sure you will :p
 
Guys...
How to use the bank balance in the same variable message?
I need to do it, to send player bank balance

I've tried:
Code:
       // message to player
       char msg[64] = "Your bank balance now is: " + player->balance + ".";
       player->sendTextMessage(MSG_INFO_DESCR, msg);

But don't work:
Code:
game.cpp: In member function ‘bool Game::removeMoney(Cylinder*, int64_t, uint32_t)’:
game.cpp:2017:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     if(player->balance  >  money - moneyCount)
        ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
game.cpp:2025:65: error: invalid operands of types ‘const char*’ and ‘const char [2]’ to binary ‘operator+’
   char msg[64] = "Your bank balance now is: " + player->balance + ".";
                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
Makefile:33: recipe for target 'game.o' failed
make: *** [game.o] Error 1

And comenting it:
Code:
       //char msg[64] = "Your bank balance now is: " + player->balance + ".";
       //player->sendTextMessage(MSG_INFO_DESCR, msg);

To compile the function with
Code:
   // Not enough money
    if(moneyCount < money)
   {
       return false;
   }
   // if the player balance
   //  is greater than the Cost - money on hand
   Player* player = NULL;
   if (cylinder->getCreature() != NULL)
   {
       if ( cylinder->getCreature()->getPlayer() != NULL)
       {
           player = cylinder->getCreature()->getPlayer();
       }
   }
    if(player->balance  >  money - moneyCount)
   {
       // remove the money that the player doesnt have
       // on hand
       player-> balance = player->balance - ( money -moneyCount);
       // set the cost to the money amount you have on hand.
       money = moneyCount;
       // message to player
       //char msg[64] = "Your bank balance now is: " + player->balance + ".";
       //player->sendTextMessage(MSG_INFO_DESCR, msg);
   }
   else
   {
       // if the money on hand + player-> balance  is inferior to the cost, return false
       return false;
   }

I got this warnings:
Code:
game.cpp: In member function ‘bool Game::removeMoney(Cylinder*, int64_t, uint32_t)’:
game.cpp:2017:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     if(player->balance  >  money - moneyCount)
        ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
game.cpp: In constructor ‘Game::Game()’:
game.cpp:80:24: warning: iteration 2 invokes undefined behavior [-Waggressive-loop-optimizations]
   globalSaveMessage[i] = false;
   ~~~~~~~~~~~~~~~~~~~~~^~~~~~~
game.cpp:79:23: note: within this loop
  for(int32_t i = 0; i < 3; i++)
                     ~~^~~
In file included from game.cpp:18:0:
game.h: In member function ‘void Game::globalSave()’:
game.h:616:78: warning: iteration 2 invokes undefined behavior [-Waggressive-loop-optimizations]
   void setGlobalSaveMessage(int16_t key, bool value) {globalSaveMessage[key] = value;}
                                                       ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
game.cpp:6372:23: note: within this loop
  for(int16_t i = 0; i < 3; i++)
                     ~~^~~



And in game when i buy something with money in hands it buy with no remove money
And when i try buy something with no money on hands, the buy option was not able to press


Should i change something in npc/lib/npcsystem/modules.lua too?
I found it on forum: NPC working with balance.
 
Dude learn to read before learning programming...
you've got this error,
warning: comparison between signed and unsigned integer expressions.....
first of all,.. the errors is self explanatory...
second.. i'm sure that if you google those error, you will find tons of answers....
 
Back
Top