diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game-server/buysell.cpp | 38 | ||||
-rw-r--r-- | src/game-server/buysell.hpp | 12 | ||||
-rw-r--r-- | src/scripting/lua.cpp | 87 | ||||
-rw-r--r-- | src/scripting/luautil.cpp | 13 | ||||
-rw-r--r-- | src/scripting/luautil.hpp | 3 |
5 files changed, 133 insertions, 20 deletions
diff --git a/src/game-server/buysell.cpp b/src/game-server/buysell.cpp index 5622514b..2ae64618 100644 --- a/src/game-server/buysell.cpp +++ b/src/game-server/buysell.cpp @@ -23,6 +23,8 @@ #include "game-server/character.hpp" #include "game-server/gamehandler.hpp" #include "game-server/inventory.hpp" +#include "game-server/itemmanager.hpp" +#include "game-server/item.hpp" #include "net/messageout.hpp" #include <algorithm> @@ -43,27 +45,54 @@ void BuySell::cancel() delete this; } -void BuySell::registerItem(int id, int amount, int cost) +bool BuySell::registerItem(int id, int amount, int cost) { if (mSell) { int nb = Inventory(mChar).count(id); if (nb == 0) - return; + return false; if (!amount || nb < amount) amount = nb; } TradedItem it = { id, amount, cost }; mItems.push_back(it); + return true; } -void BuySell::start(Actor *actor) +int BuySell::registerPlayerItems() +{ + int nbItemsToSell = 0; + if (mSell) + { + for (int i = 0; i < EQUIPMENT_SLOTS; ++i) + { + int id = Inventory(mChar).getItem(i); + int nb = Inventory(mChar).count(id); + if (nb > 0) + { + int cost = -1; + if (ItemManager::getItem(id)) + cost = ItemManager::getItem(id)->getCost(); + if (cost > 0) + { + TradedItem it = { id, nb, cost }; + mItems.push_back(it); + nbItemsToSell++; + } + } + } + } + return nbItemsToSell; +} + +bool BuySell::start(Actor *actor) { if (mItems.empty()) { cancel(); - return; + return false; } MessageOut msg(mSell ? GPMSG_NPC_SELL : GPMSG_NPC_BUY); @@ -76,6 +105,7 @@ void BuySell::start(Actor *actor) msg.writeShort(i->cost); } mChar->getClient()->send(msg); + return true; } void BuySell::perform(int id, int amount) diff --git a/src/game-server/buysell.hpp b/src/game-server/buysell.hpp index dc1df16d..514200ac 100644 --- a/src/game-server/buysell.hpp +++ b/src/game-server/buysell.hpp @@ -43,13 +43,21 @@ class BuySell /** * Registers an item and indicates how many the NPC is ready to trade * and how much it will cost. + * @return true if at least one item was registered. */ - void registerItem(int id, int amount, int cost); + bool registerItem(int id, int amount, int cost); + + /** + * Registers every player's item at an average cost given by the ItemDB. + * @return the number of different soldable items. + */ + int registerPlayerItems(); /** * Sends the item list to player. + * @return true if at least one item was registered before start. */ - void start(Actor *actor); + bool start(Actor *actor); /** * Performs the trade. diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 790d6d91..da47d931 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -59,7 +59,6 @@ extern "C" { * http://doc.manasource.org/scripting */ - /** * Callback for sending a NPC_MESSAGE. * mana.npc_message(npc, character, string) @@ -79,7 +78,7 @@ static int npc_message(lua_State *s) msg.writeShort(p->getPublicID()); msg.writeString(std::string(m), l); gameHandler->sendTo(q, msg); - return 0; + return 1; } /** @@ -442,44 +441,106 @@ static int chr_inv_count(lua_State *s) /** * Callback for trading between a player and an NPC. * mana.npc_trade(npc, character, bool sell, table items) + * Let the player buy or sell only a subset of predeterminded items. + * @param table items: a subset of buyable/sellable items. + * When selling, if the 4 parameter is omitted or invalid, + * everything in the player inventory can be sold. + * @return 0 if something to buy/sell, 1 if no items, 2 in case of errors. */ static int npc_trade(lua_State *s) { NPC *p = getNPC(s, 1); Character *q = getCharacter(s, 2); - if (!p || !q || !lua_isboolean(s, 3) || !lua_istable(s, 4)) + if (!p || !q || !lua_isboolean(s, 3)) { - raiseScriptError(s, "npc_trade called with incorrect parameters."); - return 0; + raiseWarning(s, "npc_trade called with incorrect parameters."); + lua_pushinteger(s, 2); // return value + return 1; // Returns 1 parameter } - BuySell *t = new BuySell(q, lua_toboolean(s, 3)); + + bool sellMode = lua_toboolean(s, 3); + BuySell *t = new BuySell(q, sellMode); + if (!lua_istable(s, 4)) + { + if (sellMode) + { + // Can sell everything + if (!t->registerPlayerItems()) + { + // No items to sell in player inventory + t->cancel(); + lua_pushinteger(s, 1); + return 1; + } + + if (t->start(p)) + { + lua_pushinteger(s, 0); + return 1; + } + else + { + lua_pushinteger(s, 1); + return 1; + } + } + else + { + raiseWarning(s, "npc_trade[Buy] called with invalid or empty items table parameter."); + t->cancel(); + lua_pushinteger(s, 2); + return 1; + } + } + + int nbItems = 0; + lua_pushnil(s); while (lua_next(s, 4)) { if (!lua_istable(s, -1)) { - raiseScriptError(s, "npc_trade called with incorrect parameters."); + raiseWarning(s, "npc_trade called with invalid or empty items table parameter."); t->cancel(); - return 0; + lua_pushinteger(s, 2); + return 1; } + int v[3]; for (int i = 0; i < 3; ++i) { lua_rawgeti(s, -1, i + 1); if (!lua_isnumber(s, -1)) { - raiseScriptError(s, "rpc_trade called with incorrect parameters."); + raiseWarning(s, "npc_trade called with incorrect parameters in item table."); t->cancel(); - return 0; + lua_pushinteger(s, 2); + return 1; } v[i] = lua_tointeger(s, -1); lua_pop(s, 1); } - t->registerItem(v[0], v[1], v[2]); + if (t->registerItem(v[0], v[1], v[2])) + nbItems++; lua_pop(s, 1); } - t->start(p); - return 0; + + if (nbItems == 0) + { + t->cancel(); + lua_pushinteger(s, 1); + return 1; + } + if (t->start(p)) + { + lua_pushinteger(s, 0); + return 1; + } + else + { + lua_pushinteger(s, 1); + return 1; + } } /** diff --git a/src/scripting/luautil.cpp b/src/scripting/luautil.cpp index 02de6adc..a3602d2a 100644 --- a/src/scripting/luautil.cpp +++ b/src/scripting/luautil.cpp @@ -34,10 +34,21 @@ void raiseScriptError(lua_State *s, const char *format, ...) vsprintf(message, format, args); va_end( args ); - LOG_WARN("Lua script error: "<<message); + LOG_WARN("Lua script error: "<< message); luaL_error(s, message); } +void raiseWarning(lua_State *s, const char *format, ...) +{ + va_list args; + va_start(args, format); + char message[1024]; + vsprintf(message, format, args); + va_end( args ); + + LOG_WARN("Lua script error: "<< message); +} + /* Functions below are unsafe, as they assume the script has passed pointers to objects which have not yet been destroyed. If the script never keeps pointers around, there will be no problem. In order to be safe, the engine diff --git a/src/scripting/luautil.hpp b/src/scripting/luautil.hpp index de138e24..aec2c5c2 100644 --- a/src/scripting/luautil.hpp +++ b/src/scripting/luautil.hpp @@ -36,8 +36,11 @@ class NPC; class Character; class Thing; +// Report script errors and interrupt the script. void raiseScriptError(lua_State *s, const char *format, ...); +void raiseWarning(lua_State *s, const char *format, ...); + NPC *getNPC(lua_State *s, int p); Character *getCharacter(lua_State *s, int p); Being *getBeing(lua_State *s, int p); |