Oi gente! =)
Criei um buy/sell system que tem um monte de opções e está funcionando perfeitamente...
No meu buy/sell:
* Você pode comprar infinitos items [por exemplo: buy 121 maces, buy 267 apples]
* Você pode vender infinitos items [por exemplo: sell 456 hams, sell 21 ropes]
* Você pode comprar/vender items com Subtype [por exemplo: manafluids, runas]
* LuaScript "haveItem(cid, itemid, count, subtype, iscountable)" [checka se o player tem algum determinado item, funciona pra todos luascripts(npcs,actions,etc)]
* Novas Funções em data/npc/script/lib/npc.lua
* Você pode configurar as mensagems que o npc vai falar no NpcScript [por exemplo: Here you are.]
* Você pode configurar o máximo de items que podem ser comprados no config.lua
* O npc pergunta se você quer comprar/vender o item
* e muito mais!!
Primeiro, você precisa da função getCountNumber(msg) feita pelo Soulblaster:
No final de data/npc/scripts/lib/npc.lua adicione:
function getCountNumber(msg) b, e = string.find(msg, "%d+") if b == nil or e == nil then count = 1 else count = tonumber(string.sub(msg, b, e)) end return count end
------------------------------------------
Vamos começar com o code?? Gogogo
No final de game.cpp adicione:
#ifdef ZORZIN_BUY_SELL uint32_t Game::haveItem(Cylinder* cylinder, uint32_t item_id, uint16_t subtype, uint16_t type) { if(cylinder == NULL){ return 0; } std::list<Container*> listContainer; ItemList::const_iterator it; Container* tmpContainer = NULL; Thing* thing = NULL; Item* item = NULL; unsigned int itemCount = 0; for(int i = cylinder->__getFirstIndex(); i < cylinder->__getLastIndex(); ++i){ if(!(thing = cylinder->__getThing(i))) continue; if(!(item = thing->getItem())) continue; if(tmpContainer = item->getContainer()){ listContainer.push_back(tmpContainer); } else{ if(item->getID() == item_id) { if(type == 0){ if(item->hasSubType() && item->getItemCountOrSubtype() == subtype) ++itemCount; else if(!item->hasSubType()) ++itemCount; } else if(type == 1){ if(item->getItemCount() > 0) itemCount += item->getItemCount(); } } } } while(listContainer.size() > 0){ Container* container = listContainer.front(); listContainer.pop_front(); for(it = container->getItems(); it != container->getEnd(); ++it){ Item* item = *it; if(tmpContainer = item->getContainer()){ listContainer.push_back(tmpContainer); } else if(item->getID() == item_id) { if(type == 0){ if(item->hasSubType() && item->getItemCountOrSubtype() == subtype) ++itemCount; else if(!item->hasSubType()) ++itemCount; } else if(type == 1){ if(item->getItemCount() > 0) itemCount += item->getItemCount(); } } } } return itemCount; } void Game::deleteItemSubType(Cylinder* cylinder, uint32_t item_id, uint16_t subtype, uint32_t how_many) { if(cylinder == NULL){ return; } int xx = 0; std::list<Container*> listContainer; ItemList::const_iterator it; Container* tmpContainer = NULL; Thing* thing = NULL; Item* item = NULL; unsigned int itemCount = 0; for(int i = cylinder->__getFirstIndex(); i < cylinder->__getLastIndex(); ++i){ if(!(thing = cylinder->__getThing(i))) continue; if(!(item = thing->getItem())) continue; if(tmpContainer = item->getContainer()){ listContainer.push_back(tmpContainer); } else{ if(item->getID() == item_id && subtype != 0 && item->hasSubType() && item->getItemCountOrSubtype() == subtype && xx < how_many){ removeItemOfType(cylinder, item_id, 1); ++xx; } } } while(listContainer.size() > 0){ Container* container = listContainer.front(); listContainer.pop_front(); for(it = container->getItems(); it != container->getEnd(); ++it){ Item* item = *it; if(tmpContainer = item->getContainer()){ listContainer.push_back(tmpContainer); } else if(item->getID() == item_id && subtype != 0 && item->hasSubType() && item->getItemCountOrSubtype() == subtype && xx < how_many){ removeItemOfType(cylinder, item_id, 1); ++xx; } } } } #endif
------------------------------------------
Em game.h, depois de:
class Game { public: Game(); ~Game();
Adicione:
#ifdef ZORZIN_BUY_SELL uint32_t haveItem(Cylinder* cylinder, uint32_t item_id, uint16_t subtype, uint16_t type); void deleteItemSubType(Cylinder* cylinder, uint32_t item_id, uint16_t subtype, uint32_t how_many); #endif
------------------------------------------
Em configmanager.cpp, depois de:
m_confString[LOGIN_MSG] = getGlobalString(L, "loginmsg", "Welcome.");
Adicione:
#ifdef ZORZIN_BUY_SELL m_confInteger[MAX_ITEMS_COUNTABLE] = getGlobalNumber(L, "max_items_countable", 200); m_confInteger[MAX_ITEMS_NOTCOUNTABLE] = getGlobalNumber(L, "max_items_not_countable", 2000); m_confString[MAX_ITEMS_MSG] = getGlobalString(L, "max_items_msg", "Sorry, you can not buy more than "); #endif
------------------------------------------
Em configmanager.h, depois de:
OTSERV_DB_HOST,
Adicione:
#ifdef ZORZIN_BUY_SELL MAX_ITEMS_MSG, #endif
Em configmanager.h, depois de:
OTSERV_DB_ENABLED,
Adicione:
#ifdef ZORZIN_BUY_SELL MAX_ITEMS_COUNTABLE, MAX_ITEMS_NOTCOUNTABLE, #endif
------------------------------------------
Em Luascript.cpp, depois de:
//getPlayerFood(uid) lua_register(m_luaState, "getPlayerFood", LuaScriptInterface::luaGetPlayerFood);
Add:
#ifdef ZORZIN_BUY_SELL //haveItem(cid, itemid, count, subtype, iscountable) lua_register(m_luaState, "haveItem", LuaScriptInterface::haveItem); #endif
------------------------------------------
No final de Luascript.cpp adicione:
#ifdef ZORZIN_BUY_SELL int LuaScriptInterface::haveItem(lua_State *L) { uint16_t type = (uint16_t)popNumber(L); uint16_t subtype = (uint16_t)popNumber(L); uint16_t count = (uint16_t)popNumber(L); uint32_t itemId = (uint32_t)popNumber(L); uint32_t cid = (uint32_t)popNumber(L); ScriptEnviroment* env = getScriptEnv(); Player* player = env->getPlayerByUID(cid); if(player){ if(g_game.haveItem(player, itemId, subtype, type) >= count){ lua_pushnumber(L, LUA_TRUE); } else{ lua_pushnumber(L, LUA_FALSE); } } else{ reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushnumber(L, LUA_ERROR); } return 1; } #endif
------------------------------------------
Em Luascript.h, depois de:
static int luaGetPlayerFood(lua_State *L);
Adicione:
#ifdef ZORZIN_BUY_SELL static int haveItem(lua_State *L); #endif
------------------------------------------
Em Npc.cpp, depois de:
lua_register(m_luaState, "selfSay", NpcScriptInterface::luaActionSay);
Adicione:
#ifdef ZORZIN_BUY_SELL lua_register(m_luaState, "buy", NpcScriptInterface::luaBuyItem); lua_register(m_luaState, "sell", NpcScriptInterface::luaSellItem); #endif
------------------------------------------
No final de Npc.cpp, adicione:
#ifdef ZORZIN_BUY_SELL int NpcScriptInterface::luaBuyItem(lua_State* L) { //Buy/Sell System by Zorzin std::string name(popString(L)); short type = (short)popNumber(L); long price = (int)popNumber(L); int how_many = (int)popNumber(L); int count_or_subtype = (short)popNumber(L); int item_id = (int)popNumber(L); int cid = (int)popNumber(L); Player* player = g_game.getPlayerByID(cid); uint32_t getPlayerMoney = g_game.getMoney(player); short add_count = 0; #ifdef USING_OLD_CVS Npc* mynpc = getNpc(); #else ScriptEnviroment* env = getScriptEnv(); Npc* mynpc = env->getNpc(); #endif Tile* ground = player->getTile(); if(type == 1 && count_or_subtype == 0) count_or_subtype = 1; std::stringstream textMsg; if(type == 0 && how_many > g_config.getNumber(ConfigManager::MAX_ITEMS_NOTCOUNTABLE)){ textMsg << g_config.getString(ConfigManager::MAX_ITEMS_MSG) << g_config.getNumber(ConfigManager::MAX_ITEMS_NOTCOUNTABLE) << " " << name << "."; mynpc->doSay(textMsg.str().c_str()); } else if(type == 1 && count_or_subtype > g_config.getNumber(ConfigManager::MAX_ITEMS_COUNTABLE)){ textMsg << g_config.getString(ConfigManager::MAX_ITEMS_MSG) << g_config.getNumber(ConfigManager::MAX_ITEMS_COUNTABLE) << " " << name << "."; mynpc->doSay(textMsg.str().c_str()); } else{ if(getPlayerMoney >= price){ //Checks if the player has the money if(type == 1 && count_or_subtype <= 100) how_many = 1; else if(type == 1 && count_or_subtype > 100){ how_many = count_or_subtype/100; add_count = count_or_subtype% 100; count_or_subtype = 100; } g_game.removeMoney(player, price); for(int cont = 0; cont < how_many; ++cont){ ReturnValue ret = g_game.internalPlayerAddItem(player, Item::CreateItem(item_id, count_or_subtype)); if(ret != RET_NOERROR) ground->__internalAddThing(Item::CreateItem(item_id, count_or_subtype)); if(add_count != 0 && how_many == cont+1){ ret = g_game.internalPlayerAddItem(player, Item::CreateItem(item_id, add_count)); if(ret != RET_NOERROR) ret = g_game.internalAddItem(ground, Item::CreateItem(item_id, add_count), INDEX_WHEREEVER, FLAG_NOLIMIT); } } lua_pushnumber(L, 1); //return 1 on the NpcScript :P } else lua_pushnumber(L, 0); //return 0 on the NpcScript :P } return 1; } int NpcScriptInterface::luaSellItem(lua_State* L) { //Buy/Sell System by Zorzin short type = (short)popNumber(L); long price = (int)popNumber(L); int how_many = (int)popNumber(L); short count_or_subtype = (short)popNumber(L); int item_id = (int)popNumber(L); int cid = (int)popNumber(L); short sub_type = 0; if(type == 0) sub_type = count_or_subtype; Player* player = g_game.getPlayerByID(cid); uint32_t getPlayerItem = g_game.haveItem(player, item_id, sub_type, type); short remove_count = 0; #ifdef USING_OLD_CVS Npc* mynpc = getNpc(); #else ScriptEnviroment* env = getScriptEnv(); Npc* mynpc = env->getNpc(); #endif Tile* ground = player->getTile(); if((type == 0 && getPlayerItem >= how_many) || (type == 1 && getPlayerItem >= count_or_subtype)){ //checks if the players has the items if(type == 1 && count_or_subtype <= 100) how_many = 1; else if(type == 1 && count_or_subtype > 100){ how_many = count_or_subtype/100; remove_count = count_or_subtype% 100; count_or_subtype = 100; } if(type == 0 && count_or_subtype != 0) g_game.deleteItemSubType(player, item_id, count_or_subtype, how_many); else{ if(type == 0 && count_or_subtype == 0) count_or_subtype = 1; for(int cont = 0; cont < how_many; ++cont){ g_game.removeItemOfType(player, item_id, count_or_subtype); if(remove_count != 0 && how_many == cont+1) g_game.removeItemOfType(player, item_id, remove_count); } } if(price > 9999){ ReturnValue ret = g_game.internalPlayerAddItem(player, Item::CreateItem(2160, price/10000)); if(ret != RET_NOERROR) ret = g_game.internalAddItem(ground, Item::CreateItem(2160, price/10000), INDEX_WHEREEVER, FLAG_NOLIMIT); price = price%10000; } if(price > 99){ ReturnValue ret = g_game.internalPlayerAddItem(player, Item::CreateItem(2152, price/100)); if(ret != RET_NOERROR) ret = g_game.internalAddItem(ground, Item::CreateItem(2152, price/100), INDEX_WHEREEVER, FLAG_NOLIMIT); price = price%100; } if(price > 0){ ReturnValue ret = g_game.internalPlayerAddItem(player, Item::CreateItem(2148, price)); if(ret != RET_NOERROR) ret = g_game.internalAddItem(ground, Item::CreateItem(2148, price), INDEX_WHEREEVER, FLAG_NOLIMIT); price = 0; } lua_pushnumber(L, 1); } else lua_pushnumber(L, 0); return 1; } #endif
------------------------------------------
Em Npc.h, depois de:
static int luaActionSay(lua_State *L);
Add:
#ifdef ZORZIN_BUY_SELL static int luaBuyItem(lua_State *L); static int luaSellItem(lua_State *L); #endif
------------------------------------------
Agora, cria um novo arquivo em data/npc/ named: "test.xml" e adicione nesse arquivo:
<?xml version="1.0"?> <npc name="Test" script="data/npc/scripts/test.lua" access="3"> <mana now="800" max="800"/> <health now="800" max="800"/> <look type="144" head="96" body="109" legs="90" feet="128" addons="3"/> </npc>
------------------------------------------
Agora, cria um novo arquivo em data/npc/scripts/ named: "test.lua" e adicione nesse arquivo:
-- Npc by Zorzin =)local focus = 0
local talk_start = 0
local target = 0
local following = false
local attacking = false
function onThingMove(creature, thing, oldpos, oldstackpos)
end
function onCreatureAppear(creature)
end
function onCreatureDisappear(cid, pos)
if focus == cid then
selfSay('Good bye then.')
focus = 0
talk_start = 0
end
end
function onCreatureTurn(creature)
end
function msgcontains(txt, str)
return (string.find(txt, str) and not string.find(txt, '(%w+)' .. str) and not string.find(txt, str .. '(%w+)'))
end
function onCreatureSay(cid, type, msg)
msg = string.lower(msg)
-- greeting phrase
if string.find(msg, '(%a*)hi(%a*)') and focus == 0 and string.len(msg) == 2 and getDistanceToCreature(cid) < 4 then
selfSay('Hello ' .. creatureGetName(cid) .. '! I sell meat, lifefluids. Also, I buy manafluids, ropes and apples.')
focus = cid
talk_start = os.clock()
elseif msgcontains(msg, 'hi') and (focus ~= cid) and getDistanceToCreature(cid) < 4 then
selfSay('Sorry, ' .. creatureGetName(cid) .. '! I talk to you in a minute.')
elseif focus == cid then
talk_start = os.clock()
-- Mensages:
buy_error = 'Sorry, you dont have enough money.'
buy_ok = 'Here you are.'
buy_no = 'Ok. Maybe another time.'
--
sell_error = 'Sorry, you dont have that item.'
sell_ok = 'Thanks for this item.'
sell_no = 'Ok. Maybe another time.'
--
if msgcontains(msg, 'check') then
selfSay('I can check if you have 120 apple and if you have 14 manafluids. Say "chk_apples" or "chk_manafluids" to see.')
elseif msgcontains(msg, 'chk_apple') or msgcontains(msg, 'chk_apples') then
if haveItem(cid,2674,120,0,1) == 1 then -- haveItem(cid,itemid,count,subtype,iscountable)
selfSay('You have 120 apples.')
else
selfSay('You dont have 120 apples.')
end
elseif msgcontains(msg, 'chk_manafluid') or msgcontains(msg, 'chk_manafluids') then
if haveItem(cid,2006,14,7,0) == 1 then -- haveItem(cid,itemid,count,subtype,iscountable)
selfSay('You have 14 manafluids.')
else
selfSay('You dont have 14 manafluids.')
end
elseif msgcontains(msg, 'meat') or msgcontains(msg, 'meats') then
bs,itemid,count,subtype,price,iscountable,article,name,plural = 'buy',2666,getCountNumber(msg),0,5,1,'a','meat','meats'
sendMsgBuySell(cid,itemid,count,price,article,name,plural,bs)
talk_state = 999
elseif msgcontains(msg, 'lifefluid') or msgcontains(msg, 'lifefluids') then
bs,itemid,count,subtype,price,iscountable,article,name,plural = 'buy',2006,getCountNumber(msg),10,70,0,'a','lifefluid','lifefluids'
sendMsgBuySell(cid,itemid,count,price,article,name,plural,bs)
talk_state = 999
elseif msgcontains(msg, 'sell') and msgcontains(msg, 'manafluid') or msgcontains(msg, 'manafluids') then
bs,itemid,count,subtype,price,iscountable,article,name,plural = 'sell',2006,getCountNumber(msg),7,50,0,'a','manafluid','manafluids'
sendMsgBuySell(cid,itemid,count,price,article,name,plural,bs)
talk_state = 999
elseif msgcontains(msg, 'sell') and msgcontains(msg, 'rope') or msgcontains(msg, 'ropes') then
bs,itemid,count,subtype,price,iscountable,article,name,plural = 'sell',2120,getCountNumber(msg),0,10,0,'a','rope','ropes'
sendMsgBuySell(cid,itemid,count,price,article,name,plural,bs)
talk_state = 999
elseif msgcontains(msg, 'sell') and msgcontains(msg, 'apple') or msgcontains(msg, 'apples') then
bs,itemid,count,subtype,price,iscountable,article,name,plural = 'sell',2674,getCountNumber(msg),0,2,1,'an','apple','apples'
sendMsgBuySell(cid,itemid,count,price,article,name,plural,bs)
talk_state = 999
elseif talk_state == 999 then
if msgcontains(msg, 'yes') or msgcontains(msg, 'no') then
if bs == 'buy' then
buyItem(cid,itemid,count,subtype,price,iscountable,name,plural,buy_error,buy_ok,
buy_no,msg)
else
sellItem(cid,itemid,count,subtype,price,iscountable,sell_error,sell_ok,sell_no,m
sg)
end
talk_state = 0
end
elseif msgcontains(msg, 'bye') and getDistanceToCreature(cid) < 4 then
selfSay('Good bye, ' .. creatureGetName(cid) .. '!')
focus = 0
talk_start = 0
end
end
end
function onCreatureChangeOutfit(creature)
end
function onThink()
if (os.clock() - talk_start) > 30 then
if focus > 0 then
selfSay('Next Please...')
end
focus = 0
end
if focus ~= 0 then
if getDistanceToCreature(focus) > 5 then
selfSay('Good bye then.')
focus = 0
end
end
end
------------------------------------------
No final de data/npc/scripts/lib/npc.lua Adicione:
function sendMsgBuySell(cid,itemid,count,price,article,name,plural,b_s) price = price*count if b_s ~= 'buy' and b_s ~= 'sell' then b_s = 'sell' end if count == 1 then selfSay('Do you want to '.. b_s ..' '.. article ..' '.. name ..' for '.. price ..' gold?') else name = plural selfSay('Do you want to '.. b_s ..' '.. count ..' '.. name ..' for '.. price ..' gold?') end end function buyItem(cid,itemid,count,subtype,price,type,name,plural,msgerror,msgok,msgno,msg) price = price*count if count > 1 then name = plural end if msgcontains(msg, 'yes') then if type == 0 then buy_status = buy(cid,itemid,subtype,count,price,0,name) else buy_status = buy(cid,itemid,count,subtype,price,1,name) end if buy_status == 1 then selfSay(msgok) elseif buy_status == 0 then selfSay(msgerror) end elseif msgcontains(msg, 'no') then selfSay(msgno) end -- msgcontains end --function function sellItem(cid,itemid,count,subtype,price,type,msgerror,msgok,msgno,msg) price = price*count if msgcontains(msg, 'yes') then if type == 0 then sell_status = sell(cid,itemid,subtype,count,price,0) else sell_status = sell(cid,itemid,count,subtype,price,1) end if sell_status == 1 then selfSay(msgok) else selfSay(msgerror) end talk_state = 0 elseif msgcontains(msg, 'no') then selfSay(msgno) end end
------------------------------------------
Em Project Options (Alt+P) > Parameters > C++ Compiler adicione:
-DZORZIN_BUY_SELL
------------------------------------------
Adicione no config.lua:
----------------------------------------- --- Buy/Sell System by Zorzin =) --- ----------------------------------------- -- Max Items to buy (if item is not countable - Ex: rope, crown armor) -- ||| Default: 200 ||| -- max_items_notcountable = 200 -- Max Items to buy (if item is countable - Ex: meat, ham) -- ||| Default: 2000 ||| -- max_items_countable = 2000 -- The message that will be sent when the player try to buy more then the max items -- ||| Default: "Sorry, you can not buy more than " ||| -- max_items_msg = "Sorry, you can not buy more than " -----------------------------------------
------------------------------------------
Agora dê rebuild all
---------------------------
Se você ta tendo compilers errors no npc.cpp, vai em Project Options (Alt+P) > Parameters > C++ Compiler e adicione:
-DUSING_OLD_CVS
---------------------------
É isso ai.. Agora vou explicar o meu buy/sell system (em data/npc/scripts/test.lua)...
-- Mensages: buy_error = 'Sorry, you dont have enough money.' buy_ok = 'Here you are.' buy_no = 'Ok. Maybe another time.' -- sell_error = 'Sorry, you dont have that item.' sell_ok = 'Thanks for this item.' sell_no = 'Ok. Maybe another time.' --
buy_error e sell_error -> é a mensagem que vai ser mandada para o player quanto ele nao tiver dinheiro ou o item necessário
buy_ok e sell_ok -> é a mensagem que vai ser mandada quando o buy/sell for concluído
buy_no e sell_no, é a mensagem que vai ser mandada quando o player dizer no
'sell',2006,getCountNumber(msg),7,50,0,'a','manafluid','manafluids'
bs,itemid,count,subtype,price,iscountable,article,name,plural
'sell' -> o tipo (pode ser sell ou buy)
2006 -> itemID
getCountNumber(msg) -> não mude isso!
7 -> subtype
50 -> preço de 1 item
0 -> iscountable (se o Item é Contável, coloque 1... se o Item não é Contável, coloque 0 [Ex: Manafluid não é Contável.. Para Manafluid coloque 0])
'a' -> o artigo (pode ser a ou an)
'manafluid' -> nome do item no singular
'manafluids' -> nome do item no plural
haveItem(cid,2674,120,0,1)
haveItem(cid,itemid,count,subtype,iscountable)
cid -> não mude isso!
2674 -> itemID
120 -> count
0 -> subtype
1 -> iscountable (se o Item é Contável, coloque 1... se o Item não é Contável, coloque 0 [Ex: Manafluid não é Contável.. Para Manafluid coloque 0])
------------------------------------------
Credits: Zorzin
Espero que vocês tenham gostado.. =)
Comments plz :icon1:
Obrigado,
Zorzin