finish market system

This commit is contained in:
ErikasKontenis
2022-04-10 22:15:53 +03:00
parent fadbf8b64d
commit 6e6b2dc4a6
25 changed files with 2670 additions and 1166 deletions

View File

@@ -283,7 +283,6 @@ enum item_t : uint16_t {
ITEM_DEPOT = 3502,
ITEM_LOCKER1 = 3497,
ITEM_INBOX = 7476,
ITEM_MARKET = 7477,
ITEM_MALE_CORPSE = 4240,

View File

@@ -19,8 +19,6 @@
#include "otpch.h"
#include "depotchest.h"
#include "inbox.h"
#include "container.h"
#include "iomap.h"
#include "game.h"
@@ -273,10 +271,6 @@ ReturnValue Container::queryAdd(int32_t index, const Thing& thing, uint32_t coun
return RETURNVALUE_THISISIMPOSSIBLE;
}
if (dynamic_cast<const Inbox*>(cylinder)) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}
cylinder = cylinder->getParent();
}

View File

@@ -23,7 +23,6 @@
#include "creature.h"
#include "player.h"
#include "tools.h"
#include "inbox.h"
DepotLocker::DepotLocker(uint16_t type) :
Container(type, 30), depotId(0) {}
@@ -87,13 +86,4 @@ void DepotLocker::postRemoveNotification(Thing* thing, const Cylinder* newParent
if (parent != nullptr) {
parent->postRemoveNotification(thing, newParent, index, LINK_PARENT);
}
}
void DepotLocker::removeInbox(Inbox* inbox)
{
auto cit = std::find(itemlist.begin(), itemlist.end(), inbox);
if (cit == itemlist.end()) {
return;
}
itemlist.erase(cit);
}
}

View File

@@ -22,8 +22,6 @@
#include "container.h"
class Inbox;
class DepotLocker final : public Container
{
public:
@@ -53,8 +51,6 @@ class DepotLocker final : public Container
void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) final;
void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) final;
void removeInbox(Inbox* inbox);
bool canRemove() const final {
return false;
}

View File

@@ -69,8 +69,8 @@ enum MarketAction_t {
};
enum MarketRequest_t {
MARKETREQUEST_OWN_HISTORY = 1,
MARKETREQUEST_OWN_OFFERS = 2,
MARKETREQUEST_OWN_HISTORY = 65535,
MARKETREQUEST_OWN_OFFERS = 65534,
MARKETREQUEST_ITEM = 3,
};

View File

@@ -38,8 +38,6 @@
#include "scheduler.h"
#include "databasetasks.h"
#include "movement.h"
#include "inbox.h"
#include "depotchest.h"
extern ConfigManager g_config;
extern Actions* g_actions;
@@ -4580,7 +4578,7 @@ void Game::playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t spr
return;
}
std::forward_list<Item*> itemList = getMarketItemList(it.id, amount, depotLocker, player->getInbox());
std::forward_list<Item*> itemList = getMarketItemList(it.id, amount, depotLocker);
if (itemList.empty()) {
return;
}
@@ -4660,7 +4658,7 @@ void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
while (tmpAmount > 0) {
int32_t stackCount = std::min<int32_t>(100, tmpAmount);
Item* item = Item::CreateItem(it.id, stackCount);
if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
if (internalAddItem(player->getDepotLocker(player->getLastDepotId(), false), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
delete item;
break;
}
@@ -4679,7 +4677,7 @@ void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
for (uint16_t i = 0; i < offer.amount; ++i) {
Item* item = Item::CreateItem(it.id, subType);
if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
if (internalAddItem(player->getDepotLocker(player->getLastDepotId(), false), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
delete item;
break;
}
@@ -4737,7 +4735,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
return;
}
std::forward_list<Item*> itemList = getMarketItemList(it.id, amount, depotLocker, player->getInbox());
std::forward_list<Item*> itemList = getMarketItemList(it.id, amount, depotLocker);
if (itemList.empty()) {
return;
}
@@ -4776,7 +4774,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
while (tmpAmount > 0) {
uint16_t stackCount = std::min<uint16_t>(100, tmpAmount);
Item* item = Item::CreateItem(it.id, stackCount);
if (internalAddItem(buyerPlayer->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
if (internalAddItem(buyerPlayer->getDepotLocker(buyerPlayer->getLastDepotId(), false), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
delete item;
break;
}
@@ -4795,7 +4793,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
for (uint16_t i = 0; i < amount; ++i) {
Item* item = Item::CreateItem(it.id, subType);
if (internalAddItem(buyerPlayer->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
if (internalAddItem(buyerPlayer->getDepotLocker(buyerPlayer->getLastDepotId(), false), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
delete item;
break;
}
@@ -4807,25 +4805,22 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
delete buyerPlayer;
}
else {
buyerPlayer->onReceiveMail();
buyerPlayer->onReceiveMail(buyerPlayer->getLastDepotId());
}
}
else {
if (totalPrice > (player->getMoney() + player->bankBalance)) {
if (totalPrice > player->bankBalance) {
return;
}
const auto debitCash = std::min(player->getMoney(), totalPrice);
const auto debitBank = totalPrice - debitCash;
removeMoney(player, debitCash);
player->bankBalance -= debitBank;
player->bankBalance -= totalPrice;
if (it.stackable) {
uint16_t tmpAmount = amount;
while (tmpAmount > 0) {
uint16_t stackCount = std::min<uint16_t>(100, tmpAmount);
Item* item = Item::CreateItem(it.id, stackCount);
if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
if (internalAddItem(player->getDepotLocker(player->getLastDepotId(), false), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
delete item;
break;
}
@@ -4844,7 +4839,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
for (uint16_t i = 0; i < amount; ++i) {
Item* item = Item::CreateItem(it.id, subType);
if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
if (internalAddItem(player->getDepotLocker(player->getLastDepotId(), false), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
delete item;
break;
}
@@ -4859,7 +4854,7 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
IOLoginData::increaseBankBalance(offer.playerId, totalPrice);
}
player->onReceiveMail();
player->onReceiveMail(player->getLastDepotId());
}
const int32_t marketOfferDuration = g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION);
@@ -4882,12 +4877,12 @@ void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16
player->sendMarketAcceptOffer(offer);
}
std::forward_list<Item*> Game::getMarketItemList(uint16_t wareId, uint16_t sufficientCount, DepotLocker* depotLocker, Inbox* inbox)
std::forward_list<Item*> Game::getMarketItemList(uint16_t wareId, uint16_t sufficientCount, DepotLocker* depotLocker)
{
std::forward_list<Item*> itemList;
uint16_t count = 0;
std::list<Container*> containers{ depotLocker, inbox };
std::list<Container*> containers{ depotLocker };
do {
Container* container = containers.front();
containers.pop_front();

View File

@@ -413,7 +413,7 @@ class Game
void playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t spriteId, uint16_t amount, uint64_t price, bool anonymous);
void playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter);
void playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter, uint16_t amount);
std::forward_list<Item*> getMarketItemList(uint16_t wareId, uint16_t sufficientCount, DepotLocker* depotLocker, Inbox* inbox);
std::forward_list<Item*> getMarketItemList(uint16_t wareId, uint16_t sufficientCount, DepotLocker* depotLocker);
void closeRuleViolationReport(Player* player);
void cancelRuleViolationReport(Player* player);

View File

@@ -26,7 +26,6 @@
#include "game.h"
#include "configmanager.h"
#include "bed.h"
#include "inbox.h"
extern ConfigManager g_config;
extern Game g_game;

View File

@@ -22,8 +22,6 @@
#include "iologindata.h"
#include "configmanager.h"
#include "game.h"
#include "depotchest.h"
#include "inbox.h"
#include <fmt/core.h>
extern ConfigManager g_config;
@@ -498,35 +496,6 @@ bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
}
}
//load inbox items
itemMap.clear();
if ((result = db->storeQuery(fmt::format("SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_inboxitems` WHERE `player_id` = {:d} ORDER BY `sid` DESC", player->getGUID())))) {
loadItems(itemMap, result);
for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) {
const std::pair<Item*, int32_t>& pair = it->second;
Item* item = pair.first;
int32_t pid = pair.second;
if (pid >= 0 && pid < 100) {
player->getInbox()->internalAddThing(item);
}
else {
ItemMap::const_iterator it2 = itemMap.find(pid);
if (it2 == itemMap.end()) {
continue;
}
Container* container = it2->second.first->getContainer();
if (container) {
container->internalAddThing(item);
}
}
}
}
//load storage map
query.str(std::string());
query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID();
@@ -794,41 +763,28 @@ bool IOLoginData::savePlayer(Player* player)
return false;
}
if (player->lastDepotId != -1) {
//save depot items
if (!db->executeQuery(fmt::format("DELETE FROM `player_depotitems` WHERE `player_id` = {:d}", player->getGUID()))) {
return false;
}
//save depot items
query.str(std::string());
query << "DELETE FROM `player_depotitems` WHERE `player_id` = " << player->getGUID();
DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
itemList.clear();
for (const auto& it : player->depotLockerMap) {
itemList.emplace_back(it.first, it.second);
}
if (!saveItems(player, itemList, depotQuery, propWriteStream)) {
return false;
}
}
//save inbox items
if (!db->executeQuery(fmt::format("DELETE FROM `player_inboxitems` WHERE `player_id` = {:d}", player->getGUID()))) {
if (!db->executeQuery(query.str())) {
return false;
}
DBInsert inboxQuery("INSERT INTO `player_inboxitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES ");
itemList.clear();
for (Item* item : player->getInbox()->getItemList()) {
itemList.emplace_back(0, item);
for (const auto& it : player->depotLockerMap) {
itemList.emplace_back(it.first, it.second);
}
if (!saveItems(player, itemList, inboxQuery, propWriteStream)) {
if (!saveItems(player, itemList, depotQuery, propWriteStream)) {
return false;
}
query.str(std::string());
query << "DELETE FROM `player_storage` WHERE `player_id` = " << player->getGUID();
if (!db->executeQuery(query.str())) {
return false;

View File

@@ -8,7 +8,6 @@
#include "configmanager.h"
#include "databasetasks.h"
#include "game.h"
#include "inbox.h"
#include "iologindata.h"
#include "scheduler.h"
#include <fmt/core.h>
@@ -128,7 +127,7 @@ void IOMarket::processExpiredOffers(DBResult_ptr result, bool)
while (tmpAmount > 0) {
uint16_t stackCount = std::min<uint16_t>(100, tmpAmount);
Item* item = Item::CreateItem(itemType.id, stackCount);
if (g_game.internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
if (g_game.internalAddItem(player->getDepotLocker(player->getLastDepotId(), false), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
delete item;
break;
}
@@ -147,7 +146,7 @@ void IOMarket::processExpiredOffers(DBResult_ptr result, bool)
for (uint16_t i = 0; i < amount; ++i) {
Item* item = Item::CreateItem(itemType.id, subType);
if (g_game.internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
if (g_game.internalAddItem(player->getDepotLocker(player->getLastDepotId(), false), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) {
delete item;
break;
}

View File

@@ -36,8 +36,6 @@
#include "monster.h"
#include "scheduler.h"
#include "databasetasks.h"
#include "inbox.h"
#include "depotchest.h"
extern Chat* g_chat;
extern Game g_game;
@@ -1996,7 +1994,6 @@ void LuaScriptInterface::registerFunctions()
registerMethod("Player", "getFreeCapacity", LuaScriptInterface::luaPlayerGetFreeCapacity);
registerMethod("Player", "getDepotChest", LuaScriptInterface::luaPlayerGetDepotChest);
registerMethod("Player", "getInbox", LuaScriptInterface::luaPlayerGetInbox);
registerMethod("Player", "getMurderTimestamps", LuaScriptInterface::luaPlayerGetMurderTimestamps);
registerMethod("Player", "getPlayerKillerEnd", LuaScriptInterface::luaPlayerGetPlayerKillerEnd);
@@ -2307,6 +2304,13 @@ void LuaScriptInterface::registerFunctions()
registerMethod("ItemType", "getDecayId", LuaScriptInterface::luaItemTypeGetDecayId);
registerMethod("ItemType", "getNutrition", LuaScriptInterface::luaItemTypeGetNutrition);
registerMethod("ItemType", "getRequiredLevel", LuaScriptInterface::luaItemTypeGetRequiredLevel);
registerMethod("ItemType", "getDuration", LuaScriptInterface::luaItemTypeGetDuration);
registerMethod("ItemType", "getMinReqLevel", LuaScriptInterface::luaItemTypeGetMinReqLevel);
registerMethod("ItemType", "getMinReqMagicLevel", LuaScriptInterface::luaItemTypeGetMinReqMagicLevel);
registerMethod("ItemType", "getRuneSpellName", LuaScriptInterface::luaItemTypeGetRuneSpellName);
registerMethod("ItemType", "getVocationString", LuaScriptInterface::luaItemTypeGetVocationString);
registerMethod("ItemType", "hasShowCharges", LuaScriptInterface::luaItemTypeHasShowCharges);
registerMethod("ItemType", "getAbilities", LuaScriptInterface::luaItemTypeGetAbilities);
registerMethod("ItemType", "getMarketBuyStatistics", LuaScriptInterface::luaItemTypeGetMarketBuyStatistics);
registerMethod("ItemType", "getMarketSellStatistics", LuaScriptInterface::luaItemTypeGetMarketSellStatistics);
@@ -7281,25 +7285,6 @@ int LuaScriptInterface::luaPlayerGetDepotChest(lua_State* L)
pushUserdata<Item>(L, depotLocker);
setItemMetatable(L, -1, depotLocker);
} else {
pushBoolean(L, false);
}
return 1;
}
int LuaScriptInterface::luaPlayerGetInbox(lua_State* L)
{
// player:getInbox()
Player* player = getUserdata<Player>(L, 1);
if (!player) {
lua_pushnil(L);
return 1;
}
Inbox* inbox = player->getInbox();
if (inbox) {
pushUserdata<Item>(L, inbox);
setItemMetatable(L, -1, inbox);
}
else {
pushBoolean(L, false);
@@ -7307,6 +7292,7 @@ int LuaScriptInterface::luaPlayerGetInbox(lua_State* L)
return 1;
}
int LuaScriptInterface::luaPlayerGetMurderTimestamps(lua_State * L)
{
// player:getMurderTimestamps()
@@ -10687,6 +10673,149 @@ int LuaScriptInterface::luaItemTypeGetRequiredLevel(lua_State* L)
return 1;
}
int LuaScriptInterface::luaItemTypeGetDuration(lua_State* L)
{
// itemType:getDuration()
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (itemType) {
lua_pushinteger(L, itemType->decayTime);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaItemTypeGetMinReqLevel(lua_State* L)
{
// itemType:getMinReqLevel()
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (itemType) {
lua_pushinteger(L, itemType->minReqLevel);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaItemTypeGetMinReqMagicLevel(lua_State* L)
{
// itemType:getMinReqMagicLevel()
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (itemType) {
lua_pushinteger(L, itemType->minReqMagicLevel);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaItemTypeGetRuneSpellName(lua_State* L)
{
// itemType:getRuneSpellName()
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (itemType && itemType->isRune()) {
pushString(L, itemType->runeSpellName);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaItemTypeGetVocationString(lua_State* L)
{
// itemType:getVocationString()
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (itemType) {
pushString(L, itemType->vocationString);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaItemTypeHasShowCharges(lua_State* L)
{
// itemType:hasShowCharges()
const ItemType* itemType = getUserdata<const ItemType>(L, 1);
if (itemType) {
pushBoolean(L, itemType->showCharges);
}
else {
lua_pushnil(L);
}
return 1;
}
int LuaScriptInterface::luaItemTypeGetAbilities(lua_State* L)
{
// itemType:getAbilities()
ItemType* itemType = getUserdata<ItemType>(L, 1);
if (itemType) {
Abilities& abilities = itemType->getAbilities();
lua_createtable(L, 6, 12);
setField(L, "healthGain", abilities.healthGain);
setField(L, "healthTicks", abilities.healthTicks);
setField(L, "manaGain", abilities.manaGain);
setField(L, "manaTicks", abilities.manaTicks);
setField(L, "conditionImmunities", abilities.conditionImmunities);
setField(L, "conditionSuppressions", abilities.conditionSuppressions);
setField(L, "speed", abilities.speed);
lua_pushboolean(L, abilities.manaShield);
lua_setfield(L, -2, "manaShield");
lua_pushboolean(L, abilities.invisible);
lua_setfield(L, -2, "invisible");
lua_pushboolean(L, abilities.regeneration);
lua_setfield(L, -2, "regeneration");
// Stats
lua_createtable(L, 0, STAT_LAST + 1);
for (int32_t i = STAT_FIRST; i <= STAT_LAST; i++) {
lua_pushnumber(L, abilities.stats[i]);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "stats");
// Stats percent
lua_createtable(L, 0, STAT_LAST + 1);
for (int32_t i = STAT_FIRST; i <= STAT_LAST; i++) {
lua_pushnumber(L, abilities.statsPercent[i]);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "statsPercent");
// Skills
lua_createtable(L, 0, SKILL_LAST + 1);
for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; i++) {
lua_pushnumber(L, abilities.skills[i]);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "skills");
// Field absorb percent
lua_createtable(L, 0, COMBAT_COUNT);
for (int32_t i = 0; i < COMBAT_COUNT; i++) {
lua_pushnumber(L, abilities.fieldAbsorbPercent[i]);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "fieldAbsorbPercent");
// Absorb percent
lua_createtable(L, 0, COMBAT_COUNT);
for (int32_t i = 0; i < COMBAT_COUNT; i++) {
lua_pushnumber(L, abilities.absorbPercent[i]);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "absorbPercent");
}
return 1;
}
int LuaScriptInterface::luaItemTypeGetMarketBuyStatistics(lua_State* L)
{
// itemType:getMarketBuyStatistics()

View File

@@ -807,7 +807,6 @@ class LuaScriptInterface
static int luaPlayerGetFreeCapacity(lua_State* L);
static int luaPlayerGetDepotChest(lua_State* L);
static int luaPlayerGetInbox(lua_State* L);
static int luaPlayerGetMurderTimestamps(lua_State* L);
static int luaPlayerGetPlayerKillerEnd(lua_State* L);
@@ -1110,6 +1109,13 @@ class LuaScriptInterface
static int luaItemTypeGetDecayId(lua_State* L);
static int luaItemTypeGetNutrition(lua_State* L);
static int luaItemTypeGetRequiredLevel(lua_State* L);
static int luaItemTypeGetDuration(lua_State* L);
static int luaItemTypeGetMinReqLevel(lua_State* L);
static int luaItemTypeGetMinReqMagicLevel(lua_State* L);
static int luaItemTypeGetRuneSpellName(lua_State* L);
static int luaItemTypeGetVocationString(lua_State* L);
static int luaItemTypeHasShowCharges(lua_State* L);
static int luaItemTypeGetAbilities(lua_State* L);
static int luaItemTypeGetMarketBuyStatistics(lua_State* L);
static int luaItemTypeGetMarketSellStatistics(lua_State* L);

View File

@@ -24,7 +24,6 @@
#include "player.h"
#include "iologindata.h"
#include "town.h"
#include "inbox.h"
extern Game g_game;
@@ -95,23 +94,29 @@ bool Mailbox::sendItem(Item* item) const
{
std::string receiver;
std::string townName;
townName = "thais";
if (!getDestination(item, receiver, townName)) {
return false;
}
/**No need to continue if its still empty**/
if (receiver.empty()) {
if (receiver.empty() || townName.empty()) {
return false;
}
Town* town = g_game.map.towns.getTown(townName);
if (!town) {
return false;
}
Player* player = g_game.getPlayerByName(receiver);
if (player) {
if (g_game.internalMoveItem(item->getParent(), player->getInbox(), INDEX_WHEREEVER,
item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RETURNVALUE_NOERROR) {
g_game.transformItem(item, item->getID() + 1);
player->onReceiveMail();
return true;
DepotLocker* depotLocker = player->getDepotLocker(town->getID(), true);
if (depotLocker) {
if (g_game.internalMoveItem(item->getParent(), depotLocker, INDEX_WHEREEVER,
item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RETURNVALUE_NOERROR) {
g_game.transformItem(item, item->getID() + 1);
player->onReceiveMail(town->getID());
return true;
}
}
}
else {
@@ -120,17 +125,20 @@ bool Mailbox::sendItem(Item* item) const
return false;
}
if (g_game.internalMoveItem(item->getParent(), tmpPlayer.getInbox(), INDEX_WHEREEVER,
item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RETURNVALUE_NOERROR) {
g_game.transformItem(item, item->getID() + 1);
IOLoginData::savePlayer(&tmpPlayer);
return true;
DepotLocker* depotLocker = tmpPlayer.getDepotLocker(town->getID(), true);
if (depotLocker) {
if (g_game.internalMoveItem(item->getParent(), depotLocker, INDEX_WHEREEVER,
item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RETURNVALUE_NOERROR) {
g_game.transformItem(item, item->getID() + 1);
IOLoginData::savePlayer(&tmpPlayer);
return true;
}
}
}
return false;
}
bool Mailbox::getDestination(Item* item, std::string& name, std::string& town) const
{
const Container* container = item->getContainer();
@@ -156,9 +164,11 @@ bool Mailbox::getDestination(Item* item, std::string& name, std::string& town) c
while (getline(iss, temp, '\n')) {
if (currentLine == 1) {
name = temp;
} else if (currentLine == 2) {
}
else if (currentLine == 2) {
town = temp;
} else {
}
else {
break;
}
@@ -170,6 +180,7 @@ bool Mailbox::getDestination(Item* item, std::string& name, std::string& town) c
return true;
}
bool Mailbox::canSend(const Item* item)
{
return item->getID() == ITEM_PARCEL || item->getID() == ITEM_LETTER;

View File

@@ -32,8 +32,6 @@
#include "monster.h"
#include "movement.h"
#include "scheduler.h"
#include "depotchest.h"
#include "inbox.h"
extern ConfigManager g_config;
extern Game g_game;
@@ -48,9 +46,9 @@ MuteCountMap Player::muteCountMap;
uint32_t Player::playerAutoID = 0x10000000;
Player::Player(ProtocolGame_ptr p) :
Creature(), lastPing(OTSYS_TIME()), lastPong(lastPing), client(std::move(p)), inbox(new Inbox(ITEM_INBOX))
Creature(), lastPing(OTSYS_TIME()), lastPong(lastPing), client(std::move(p))
{
inbox->incrementReferenceCounter();
}
Player::~Player()
@@ -63,15 +61,14 @@ Player::~Player()
}
for (const auto& it : depotLockerMap) {
it.second->removeInbox(inbox);
it.second->decrementReferenceCounter();
}
inbox->decrementReferenceCounter();
setWriteItem(nullptr);
setEditHouse(nullptr);
}
bool Player::setVocation(uint16_t vocId)
{
Vocation* voc = g_vocations.getVocation(vocId);
@@ -584,14 +581,14 @@ bool Player::canSeeCreature(const Creature* creature) const
return true;
}
void Player::onReceiveMail() const
void Player::onReceiveMail(uint32_t townId) const
{
if (isNearDepotBox()) {
if (isNearDepotBox(townId)) {
sendTextMessage(MESSAGE_EVENT_ADVANCE, "New mail has arrived.");
}
}
bool Player::isNearDepotBox() const
bool Player::isNearDepotBox(uint32_t townId) const
{
const Position& pos = getPosition();
for (int32_t cx = -1; cx <= 1; ++cx) {
@@ -602,43 +599,29 @@ bool Player::isNearDepotBox() const
}
if (DepotLocker* depotLocker = tile->getDepotLocker()) {
return true;
if (depotLocker->getDepotId() == townId) {
return true;
}
}
}
}
return false;
}
DepotChest* Player::getDepotChest(uint32_t depotId, bool autoCreate)
{
auto it = depotChests.find(depotId);
if (it != depotChests.end()) {
return it->second;
}
if (!autoCreate) {
return nullptr;
}
it = depotChests.emplace(depotId, new DepotChest(ITEM_DEPOT)).first;
it->second->setMaxDepotItems(getMaxDepotItems());
return it->second;
}
DepotLocker* Player::getDepotLocker(uint32_t depotId, bool autoCreate)
{
auto it = depotLockerMap.find(depotId);
if (it != depotLockerMap.end()) {
inbox->setParent(it->second);
return it->second;
}
if (autoCreate) {
DepotLocker* depotLocker = new DepotLocker(ITEM_LOCKER1);
depotLocker->setDepotId(depotId);
depotLocker->internalAddThing(Item::CreateItem(ITEM_MARKET));
depotLocker->internalAddThing(inbox);
Item* marketItem = Item::CreateItem(ITEM_MARKET);
if (marketItem) {
depotLocker->internalAddThing(marketItem);
}
Item* depotItem = Item::CreateItem(ITEM_DEPOT);
if (depotItem) {
depotLocker->internalAddThing(depotItem);

View File

@@ -35,7 +35,6 @@
#include "town.h"
class BehaviourDatabase;
class DepotChest;
class House;
class NetworkMessage;
class Weapon;
@@ -208,10 +207,6 @@ class Player final : public Creature, public Cylinder
bool isInWar(const Player* player) const;
bool isInWarList(uint32_t guild_id) const;
Inbox* getInbox() const {
return inbox;
}
uint16_t getClientIcons() const;
const GuildWarList& getGuildWarList() const {
@@ -322,6 +317,14 @@ class Player final : public Creature, public Cylinder
lastDepotId = newId;
}
int16_t getLastDepotId() const {
if (lastDepotId == -1) {
if (town) {
return town->getID();
}
else {
return 1; // Thais
}
}
return lastDepotId;
}
@@ -473,10 +476,9 @@ class Player final : public Creature, public Cylinder
void addConditionSuppressions(uint32_t conditions);
void removeConditionSuppressions(uint32_t conditions);
DepotChest* getDepotChest(uint32_t depotId, bool autoCreate);
DepotLocker* getDepotLocker(uint32_t depotId, bool autoCreate);
void onReceiveMail() const;
bool isNearDepotBox() const;
void onReceiveMail(uint32_t townId) const;
bool isNearDepotBox(uint32_t townId) const;
bool canSee(const Position& pos) const final;
bool canSeeCreature(const Creature* creature) const final;
@@ -1079,7 +1081,6 @@ class Player final : public Creature, public Cylinder
std::map<uint8_t, OpenContainer> openContainers;
std::map<uint32_t, DepotLocker*> depotLockerMap;
std::map<uint32_t, DepotChest*> depotChests;
std::map<uint32_t, int32_t> storageMap;
std::vector<OutfitEntry> outfits;
@@ -1118,7 +1119,6 @@ class Player final : public Creature, public Cylinder
Guild* guild = nullptr;
const GuildRank* guildRank = nullptr;
Group* group = nullptr;
Inbox* inbox;
Item* tradeItem = nullptr;
Item* inventory[CONST_SLOT_LAST + 1] = {};
Item* writeItem = nullptr;

View File

@@ -30,13 +30,11 @@
#include "configmanager.h"
#include "actions.h"
#include "game.h"
#include "inbox.h"
#include "iomarket.h"
#include "iologindata.h"
#include "waitlist.h"
#include "ban.h"
#include "scheduler.h"
#include "depotchest.h"
extern ConfigManager g_config;
extern Actions actions;
@@ -1012,7 +1010,7 @@ void ProtocolGame::parseMarketLeave()
void ProtocolGame::parseMarketBrowse(NetworkMessage& msg)
{
uint8_t browseId = msg.get<uint8_t>();
uint16_t browseId = msg.get<uint16_t>();
if (browseId == MARKETREQUEST_OWN_OFFERS) {
addGameTask(&Game::playerBrowseMarketOwnOffers, player->getID());
}
@@ -1020,8 +1018,8 @@ void ProtocolGame::parseMarketBrowse(NetworkMessage& msg)
addGameTask(&Game::playerBrowseMarketOwnHistory, player->getID());
}
else {
uint16_t spriteID = msg.get<uint16_t>();
addGameTask(&Game::playerBrowseMarket, player->getID(), spriteID);
//uint16_t spriteID = msg.get<uint16_t>();
addGameTask(&Game::playerBrowseMarket, player->getID(), browseId);
}
}
@@ -1034,10 +1032,6 @@ void ProtocolGame::parseMarketCreateOffer(NetworkMessage& msg)
if (it.id == 0) {
return;
}
// TODO:
//else if (it.classification > 0) {
// msg.getByte(); // item tier
//}
uint16_t amount = msg.get<uint16_t>();
uint64_t price = msg.get<uint64_t>();
@@ -1332,7 +1326,7 @@ void ProtocolGame::sendMarketEnter(uint32_t depotId)
msg.add<uint64_t>(player->getBankBalance());
std::map<uint16_t, uint32_t> depotItems;
std::forward_list<Container*> containerList{ depotLocker, player->getInbox() };
std::forward_list<Container*> containerList{ depotLocker };
do {
Container* container = containerList.front();
@@ -1369,10 +1363,6 @@ void ProtocolGame::sendMarketEnter(uint32_t depotId)
for (std::map<uint16_t, uint32_t>::const_iterator it = depotItems.begin(); i < itemsToSend; ++it, ++i) {
const ItemType& itemType = Item::items[it->first];
msg.add<uint16_t>(itemType.id);
// TODO
//if (itemType.classification > 0) {
// msg.addByte(0);
//}
msg.add<uint16_t>(std::min<uint32_t>(0xFFFF, it->second));
}
writeToOutputBuffer(msg);
@@ -1389,14 +1379,8 @@ void ProtocolGame::sendMarketBrowseItem(uint16_t itemId, const MarketOfferList&
{
NetworkMessage msg;
msg.addByte(0xF9);
msg.addByte(MARKETREQUEST_ITEM);
msg.addItemId(itemId);
// TODO
//if (Item::items[itemId].classification > 0) {
// msg.addByte(0); // item tier
//}
msg.add<uint32_t>(buyOffers.size());
for (const MarketOffer& offer : buyOffers) {
msg.add<uint32_t>(offer.timestamp);
@@ -1422,12 +1406,7 @@ void ProtocolGame::sendMarketAcceptOffer(const MarketOfferEx& offer)
{
NetworkMessage msg;
msg.addByte(0xF9);
msg.addByte(MARKETREQUEST_ITEM);
msg.addItemId(offer.itemId);
// TODO
//if (Item::items[offer.itemId].classification > 0) {
// msg.addByte(0);
//}
if (offer.type == MARKETACTION_BUY) {
msg.add<uint32_t>(0x01);
@@ -1455,17 +1434,13 @@ void ProtocolGame::sendMarketBrowseOwnOffers(const MarketOfferList& buyOffers, c
{
NetworkMessage msg;
msg.addByte(0xF9);
msg.addByte(MARKETREQUEST_OWN_OFFERS);
msg.add<uint16_t>(MARKETREQUEST_OWN_OFFERS);
msg.add<uint32_t>(buyOffers.size());
for (const MarketOffer& offer : buyOffers) {
msg.add<uint32_t>(offer.timestamp);
msg.add<uint16_t>(offer.counter);
msg.addItemId(offer.itemId);
// TODO
//if (Item::items[offer.itemId].classification > 0) {
// msg.addByte(0);
//}
msg.add<uint16_t>(offer.amount);
msg.add<uint64_t>(offer.price);
}
@@ -1475,10 +1450,6 @@ void ProtocolGame::sendMarketBrowseOwnOffers(const MarketOfferList& buyOffers, c
msg.add<uint32_t>(offer.timestamp);
msg.add<uint16_t>(offer.counter);
msg.addItemId(offer.itemId);
// TODO
//if (Item::items[offer.itemId].classification > 0) {
// msg.addByte(0);
//}
msg.add<uint16_t>(offer.amount);
msg.add<uint64_t>(offer.price);
}
@@ -1490,17 +1461,13 @@ void ProtocolGame::sendMarketCancelOffer(const MarketOfferEx& offer)
{
NetworkMessage msg;
msg.addByte(0xF9);
msg.addByte(MARKETREQUEST_OWN_OFFERS);
msg.add<uint16_t>(MARKETREQUEST_OWN_OFFERS);
if (offer.type == MARKETACTION_BUY) {
msg.add<uint32_t>(0x01);
msg.add<uint32_t>(offer.timestamp);
msg.add<uint16_t>(offer.counter);
msg.addItemId(offer.itemId);
// TODO
//if (Item::items[offer.itemId].classification > 0) {
// msg.addByte(0);
//}
msg.add<uint16_t>(offer.amount);
msg.add<uint64_t>(offer.price);
msg.add<uint32_t>(0x00);
@@ -1511,10 +1478,6 @@ void ProtocolGame::sendMarketCancelOffer(const MarketOfferEx& offer)
msg.add<uint32_t>(offer.timestamp);
msg.add<uint16_t>(offer.counter);
msg.addItemId(offer.itemId);
// TODO
//if (Item::items[offer.itemId].classification > 0) {
// msg.addByte(0);
//}
msg.add<uint16_t>(offer.amount);
msg.add<uint64_t>(offer.price);
}
@@ -1531,17 +1494,13 @@ void ProtocolGame::sendMarketBrowseOwnHistory(const HistoryMarketOfferList& buyO
NetworkMessage msg;
msg.addByte(0xF9);
msg.addByte(MARKETREQUEST_OWN_HISTORY);
msg.add<uint16_t>(MARKETREQUEST_OWN_HISTORY);
msg.add<uint32_t>(buyOffersToSend);
for (auto it = buyOffers.begin(); i < buyOffersToSend; ++it, ++i) {
msg.add<uint32_t>(it->timestamp);
msg.add<uint16_t>(counterMap[it->timestamp]++);
msg.addItemId(it->itemId);
// TODO
//if (Item::items[it->itemId].classification > 0) {
// msg.addByte(0);
//}
msg.add<uint16_t>(it->amount);
msg.add<uint64_t>(it->price);
msg.addByte(it->state);
@@ -1555,10 +1514,6 @@ void ProtocolGame::sendMarketBrowseOwnHistory(const HistoryMarketOfferList& buyO
msg.add<uint32_t>(it->timestamp);
msg.add<uint16_t>(counterMap[it->timestamp]++);
msg.addItemId(it->itemId);
// TODO
//if (Item::items[it->itemId].classification > 0) {
// msg.addByte(0);
//}
msg.add<uint16_t>(it->amount);
msg.add<uint64_t>(it->price);
msg.addByte(it->state);