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

C++ Cap 0 container cpp

Lais Prad

Disgusting Scammer
Joined
Apr 12, 2017
Messages
153
Solutions
6
Reaction score
15
Some changes made in these 3 files caused the player to have 0 of cap, some experience looking at these files could say why?

/**
* The Forgotten Server - a free and open-source MMORPG server emulator
* Copyright (C) 2016 Mark Samman <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "otpch.h"

#include "container.h"
#include "iomap.h"
#include "game.h"

extern Game g_game;

/*Container::Container(uint16_t _type) : Item(_type)
{
maxSize = items[_type].maxItems;
totalWeight = 0;
serializationCount = 0;
unlocked = true;
pagination = false;
}*/

Container::Container(uint16_t _type) :
Container(_type, items[_type].maxItems) {}


/*Container::Container(uint16_t _type, uint16_t _size) : Item(_type)
{
maxSize = _size;
totalWeight = 0;
serializationCount = 0;
unlocked = true;
pagination = false;
}*/

Container::Container(uint16_t _type, uint16_t _size, bool unlocked /*= true*/, bool pagination /*= false*/) :
Item(_type),
maxSize(_size),
unlocked(unlocked),
pagination(pagination)
{}

Container::Container(Tile* tile) : Item(ITEM_BROWSEFIELD)
{
TileItemVector* itemVector = tile->getItemList();
if (itemVector) {
for (Item* item : *itemVector) {
if (item->getContainer() || item->hasProperty(CONST_PROP_MOVEABLE)) {
itemlist.push_front(item);
item->setParent(this);
}
}
}

maxSize = 30;
totalWeight = 0;
serializationCount = 0;
unlocked = false;
pagination = true;
setParent(tile);
}

Container::~Container()
{
if (getID() == ITEM_BROWSEFIELD) {
g_game.browseFields.erase(getTile());

for (Item* item : itemlist) {
item->setParent(parent);
}
} else {
for (Item* item : itemlist) {
item->setParent(nullptr);
item->decrementReferenceCounter();
}
}
}

Item* Container::clone() const
{
Container* clone = static_cast<Container*>(Item::clone());
for (Item* item : itemlist) {
clone->addItem(item->clone());
}
clone->totalWeight = totalWeight;
return clone;
}

Container* Container::getParentContainer()
{
Thing* thing = getParent();
if (!thing) {
return nullptr;
}
return thing->getContainer();
}

bool Container::hasParent() const
{
return getID() != ITEM_BROWSEFIELD && dynamic_cast<const Player*>(getParent()) == nullptr;
}

void Container::addItem(Item* item)
{
itemlist.push_back(item);
item->setParent(this);
}

Attr_ReadValue Container::readAttr(AttrTypes_t attr, PropStream& propStream)
{
if (attr == ATTR_CONTAINER_ITEMS) {
if (!propStream.read<uint32_t>(serializationCount)) {
return ATTR_READ_ERROR;
}
return ATTR_READ_END;
}
return Item::readAttr(attr, propStream);
}

bool Container::unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream)
{
bool ret = Item::unserializeItemNode(f, node, propStream);
if (!ret) {
return false;
}

uint32_t type;
NODE nodeItem = f.getChildNode(node, type);
while (nodeItem) {
//load container items
if (type != OTBM_ITEM) {
// unknown type
return false;
}

PropStream itemPropStream;
if (!f.getProps(nodeItem, itemPropStream)) {
return false;
}

Item* item = Item::CreateItem(itemPropStream);
if (!item) {
return false;
}

if (!item->unserializeItemNode(f, nodeItem, itemPropStream)) {
return false;
}

addItem(item);
updateItemWeight(item->getWeight());

nodeItem = f.getNextNode(nodeItem, type);
}
return true;
}

void Container::updateItemWeight(int32_t diff)
{
totalWeight += diff;
if (Container* parentContainer = getParentContainer()) {
parentContainer->updateItemWeight(diff);
}
}

uint32_t Container::getWeight() const
{
return Item::getWeight() + totalWeight;
}

std::string Container::getContentDescription() const
{
std::eek:stringstream os;
return getContentDescription(os).str();
}

std::eek:stringstream& Container::getContentDescription(std::eek:stringstream& os) const
{
bool firstitem = true;
for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) {
Item* item = *it;

Container* container = item->getContainer();
if (container && !container->empty()) {
continue;
}

if (firstitem) {
firstitem = false;
} else {
os << ", ";
}

os << item->getNameDescription();
}

if (firstitem) {
os << "nothing";
}
return os;
}

Item* Container::getItemByIndex(size_t index) const
{
if (index >= size()) {
return nullptr;
}
return itemlist[index];
}

uint32_t Container::getItemHoldingCount() const
{
uint32_t counter = 0;
for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) {
++counter;
}
return counter;
}

bool Container::isHoldingItem(const Item* item) const
{
for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) {
if (*it == item) {
return true;
}
}
return false;
}

void Container::eek:nAddContainerItem(Item* item)
{
SpectatorVec list;
g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2);

//send to client
for (Creature* spectator : list) {
spectator->getPlayer()->sendAddContainerItem(this, item);
}

//event methods
for (Creature* spectator : list) {
spectator->getPlayer()->onAddContainerItem(item);
}
}

void Container::eek:nUpdateContainerItem(uint32_t index, Item* oldItem, Item* newItem)
{
SpectatorVec list;
g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2);

//send to client
for (Creature* spectator : list) {
spectator->getPlayer()->sendUpdateContainerItem(this, index, newItem);
}

//event methods
for (Creature* spectator : list) {
spectator->getPlayer()->onUpdateContainerItem(this, oldItem, newItem);
}
}

void Container::eek:nRemoveContainerItem(uint32_t index, Item* item)
{
SpectatorVec list;
g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2);

//send change to client
for (Creature* spectator : list) {
spectator->getPlayer()->sendRemoveContainerItem(this, index);
}

//event methods
for (Creature* spectator : list) {
spectator->getPlayer()->onRemoveContainerItem(this, item);
}
}

ReturnValue Container::queryAdd(int32_t index, const Thing& thing, uint32_t count,
uint32_t flags, Creature* actor/* = nullptr*/) const
{
bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags);
if (childIsOwner) {
//a child container is querying, since we are the top container (not carried by a player)
//just return with no error.
return RETURNVALUE_NOERROR;
}

if (!unlocked) {
return RETURNVALUE_NOTPOSSIBLE;
}

const Item* item = thing.getItem();
if (item == nullptr) {
return RETURNVALUE_NOTPOSSIBLE;
}

if (!item->isPickupable()) {
return RETURNVALUE_CANNOTPICKUP;
}

if (item == this) {
return RETURNVALUE_THISISIMPOSSIBLE;
}

const Cylinder* cylinder = getParent();
if (!hasBitSet(FLAG_NOLIMIT, flags)) {
while (cylinder) {
if (cylinder == &thing) {
return RETURNVALUE_THISISIMPOSSIBLE;
}

if (dynamic_cast<const Inbox*>(cylinder)) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}

cylinder = cylinder->getParent();
}

//if (index == INDEX_WHEREEVER && size() >= capacity()) {
if (index == INDEX_WHEREEVER && size() >= capacity() && !hasPagination()) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}
} else {
while (cylinder) {
if (cylinder == &thing) {
return RETURNVALUE_THISISIMPOSSIBLE;
}

cylinder = cylinder->getParent();
}
}

const Cylinder* topParent = getTopParent();
if (topParent != this) {
return topParent->queryAdd(INDEX_WHEREEVER, *item, count, flags | FLAG_CHILDISOWNER, actor);
} else {
return RETURNVALUE_NOERROR;
}
}

ReturnValue Container::queryMaxCount(int32_t index, const Thing& thing, uint32_t count,
uint32_t& maxQueryCount, uint32_t flags) const
{
const Item* item = thing.getItem();
if (item == nullptr) {
maxQueryCount = 0;
return RETURNVALUE_NOTPOSSIBLE;
}

//if (hasBitSet(FLAG_NOLIMIT, flags)) {
if (hasBitSet(FLAG_NOLIMIT, flags) || hasPagination()) {
maxQueryCount = std::max<uint32_t>(1, count);
return RETURNVALUE_NOERROR;
}

int32_t freeSlots = std::max<int32_t>(capacity() - size(), 0);

if (item->isStackable()) {
uint32_t n = 0;

if (index == INDEX_WHEREEVER) {
//Iterate through every item and check how much free stackable slots there is.
uint32_t slotIndex = 0;
for (Item* containerItem : itemlist) {
if (containerItem != item && containerItem->equals(item) && containerItem->getItemCount() < 100) {
uint32_t remainder = (100 - containerItem->getItemCount());
if (queryAdd(slotIndex++, *item, remainder, flags) == RETURNVALUE_NOERROR) {
n += remainder;
}
}
}
} else {
const Item* destItem = getItemByIndex(index);
if (item->equals(destItem) && destItem->getItemCount() < 100) {
uint32_t remainder = 100 - destItem->getItemCount();
if (queryAdd(index, *item, remainder, flags) == RETURNVALUE_NOERROR) {
n = remainder;
}
}
}

maxQueryCount = freeSlots * 100 + n;
if (maxQueryCount < count) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}
} else {
maxQueryCount = freeSlots;
if (maxQueryCount == 0) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}
}
return RETURNVALUE_NOERROR;
}

ReturnValue Container::queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const
{
int32_t index = getThingIndex(&thing);
if (index == -1) {
return RETURNVALUE_NOTPOSSIBLE;
}

const Item* item = thing.getItem();
if (item == nullptr) {
return RETURNVALUE_NOTPOSSIBLE;
}

if (count == 0 || (item->isStackable() && count > item->getItemCount())) {
return RETURNVALUE_NOTPOSSIBLE;
}

if (!item->isMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)) {
return RETURNVALUE_NOTMOVEABLE;
}
return RETURNVALUE_NOERROR;
}

Cylinder* Container::queryDestination(int32_t& index, const Thing &thing, Item** destItem,
uint32_t& flags)
{
if (!unlocked) {
*destItem = nullptr;
return this;
}

if (index == 254 /*move up*/) {
index = INDEX_WHEREEVER;
*destItem = nullptr;

Container* parentContainer = dynamic_cast<Container*>(getParent());
if (parentContainer) {
return parentContainer;
}
return this;
}

if (index == 255 /*add wherever*/) {
index = INDEX_WHEREEVER;
*destItem = nullptr;
} else if ((index >= static_cast<int32_t>(capacity()) && !pagination) || index >= static_cast<int32_t>(size())) {
/*
if you have a container, maximize it to show all 20 slots
then you open a bag that is inside the container you will have a bag with 8 slots
and a "grey" area where the other 12 slots where from the container
if you drop the item on that grey area
the client calculates the slot position as if the bag has 20 slots
*/
index = INDEX_WHEREEVER;
*destItem = nullptr;
}

const Item* item = thing.getItem();
if (!item) {
return this;
}

bool autoStack = !hasBitSet(FLAG_IGNOREAUTOSTACK, flags);
if (autoStack && item->isStackable() && item->getParent() != this) {
//if (autoStack && item->isStackable() && item->getParent() != this && item->getActionId() > 0) {
//try find a suitable item to stack with
uint32_t n = 0;
for (Item* listItem : itemlist) {
if (listItem != item && listItem->equals(item) && listItem->getItemCount() < 100) {
*destItem = listItem;
index = n;
return this;
}
++n;
}
}

if (index != INDEX_WHEREEVER) {
Item* itemFromIndex = getItemByIndex(index);
if (itemFromIndex) {
*destItem = itemFromIndex;
}

Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem);
if (subCylinder) {
index = INDEX_WHEREEVER;
*destItem = nullptr;
return subCylinder; // se der errado mudar aqui em baixo
} else if (pagination) {
*destItem = nullptr;
index = INDEX_WHEREEVER;
}
}
return this;
}

void Container::addThing(Thing* thing)
{
return addThing(0, thing);
}

void Container::addThing(int32_t index, Thing* thing)
{
if (index >= static_cast<int32_t>(capacity())) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

Item* item = thing->getItem();
if (item == nullptr) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

item->setParent(this);
itemlist.push_front(item);
updateItemWeight(item->getWeight());

//send change to client
if (getParent() && (getParent() != VirtualCylinder::virtualCylinder)) {
onAddContainerItem(item);
}
}

void Container::addItemBack(Item* item)
{
addItem(item);
updateItemWeight(item->getWeight());

//send change to client
if (getParent() && (getParent() != VirtualCylinder::virtualCylinder)) {
onAddContainerItem(item);
}
}

void Container::updateThing(Thing* thing, uint16_t itemId, uint32_t count)
{
int32_t index = getThingIndex(thing);
if (index == -1) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

Item* item = thing->getItem();
if (item == nullptr) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

const int32_t oldWeight = item->getWeight();
item->setID(itemId);
item->setSubType(count);
updateItemWeight(-oldWeight + item->getWeight());

//send change to client
if (getParent()) {
onUpdateContainerItem(index, item, item);
}
}

void Container::replaceThing(uint32_t index, Thing* thing)
{
Item* item = thing->getItem();
if (!item) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

Item* replacedItem = getItemByIndex(index);
if (!replacedItem) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

itemlist[index] = item;
item->setParent(this);
updateItemWeight(-static_cast<int32_t>(replacedItem->getWeight()) + item->getWeight());

//send change to client
if (getParent()) {
onUpdateContainerItem(index, replacedItem, item);
}

replacedItem->setParent(nullptr);
}

void Container::removeThing(Thing* thing, uint32_t count)
{
Item* item = thing->getItem();
if (item == nullptr) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

int32_t index = getThingIndex(thing);
if (index == -1) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

if (item->isStackable() && count != item->getItemCount()) {
uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, item->getItemCount() - count));
const int32_t oldWeight = item->getWeight();
item->setItemCount(newCount);
updateItemWeight(-oldWeight + item->getWeight());

//send change to client
if (getParent()) {
onUpdateContainerItem(index, item, item);
}
} else {
updateItemWeight(-static_cast<int32_t>(item->getWeight()));

//send change to client
if (getParent()) {
onRemoveContainerItem(index, item);
}

item->setParent(nullptr);
itemlist.erase(itemlist.begin() + index);
}
}

int32_t Container::getThingIndex(const Thing* thing) const
{
int32_t index = 0;
for (Item* item : itemlist) {
if (item == thing) {
return index;
}
++index;
}
return -1;
}

size_t Container::getFirstIndex() const
{
return 0;
}

size_t Container::getLastIndex() const
{
return size();
}

uint32_t Container::getItemTypeCount(uint16_t itemId, int32_t subType/* = -1*/) const
{
uint32_t count = 0;
for (Item* item : itemlist) {
if (item->getID() == itemId) {
count += countByType(item, subType);
}
}
return count;
}

std::map<uint32_t, uint32_t>& Container::getAllItemTypeCount(std::map<uint32_t, uint32_t> &countMap) const
{
for (Item* item : itemlist) {
countMap[item->getID()] += item->getItemCount();
}
return countMap;
}

Thing* Container::getThing(size_t index) const
{
return getItemByIndex(index);
}

void Container::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t)
{
Cylinder* topParent = getTopParent();
if (topParent->getCreature()) {
topParent->postAddNotification(thing, oldParent, index, LINK_TOPPARENT);
} else if (topParent == this) {
//let the tile class notify surrounding players
if (topParent->getParent()) {
topParent->getParent()->postAddNotification(thing, oldParent, index, LINK_NEAR);
}
} else {
topParent->postAddNotification(thing, oldParent, index, LINK_PARENT);
}
}

void Container::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t)
{
Cylinder* topParent = getTopParent();
if (topParent->getCreature()) {
topParent->postRemoveNotification(thing, newParent, index, LINK_TOPPARENT);
} else if (topParent == this) {
//let the tile class notify surrounding players
if (topParent->getParent()) {
topParent->getParent()->postRemoveNotification(thing, newParent, index, LINK_NEAR);
}
} else {
topParent->postRemoveNotification(thing, newParent, index, LINK_PARENT);
}
}

void Container::internalAddThing(Thing* thing)
{
internalAddThing(0, thing);
}

void Container::internalAddThing(uint32_t, Thing* thing)
{
Item* item = thing->getItem();
if (item == nullptr) {
return;
}

item->setParent(this);
itemlist.push_front(item);
updateItemWeight(item->getWeight());
}

void Container::startDecaying()
{
for (Item* item : itemlist) {
item->startDecaying();
}
}

ContainerIterator Container::iterator() const
{
ContainerIterator cit;
if (!itemlist.empty()) {
cit.over.push_back(this);
cit.cur = itemlist.begin();
}
return cit;
}

Item* ContainerIterator::eek:perator*()
{
return *cur;
}

void ContainerIterator::advance()
{
if (Item* i = *cur) {
if (Container* c = i->getContainer()) {
if (!c->empty()) {
over.push_back(c);
}
}
}

++cur;

if (cur == over.front()->itemlist.end()) {
over.pop_front();
if (!over.empty()) {
cur = over.front()->itemlist.begin();
}
}
}


container.h link: hastebin


thanks, used tfs 1.2
 
Solution
Dosn't matter if you think anyone will experience this, they might do a serach for what a nil error means and end up with a bunch of "solved nvm"

I can delete the thread, but I won't.
I want you to fix the thread, revert the title and add what you did to solve it.

You have gotten alot of help in the support board, you could atleast do us the favor of following the rules.

I solved this by going back to the original file.
Do you want me to put the original file? Here goes:
otxserver/container.cpp at otxserv3 · mattyx14/otxserver · GitHub
otxserver/container.h at otxserv3 · mattyx14/otxserver · GitHub

Can I mark my own answer as the best? That's one of the reasons I asked you to delete the thread.


Used this, but for...
Some changes made in these 2 files caused the player to have 0 of cap, some experience looking at these files could say why?

/**
* The Forgotten Server - a free and open-source MMORPG server emulator
* Copyright (C) 2016 Mark Samman <[email protected]>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "otpch.h"

#include "container.h"
#include "iomap.h"
#include "game.h"

extern Game g_game;

/*Container::Container(uint16_t _type) : Item(_type)
{
maxSize = items[_type].maxItems;
totalWeight = 0;
serializationCount = 0;
unlocked = true;
pagination = false;
}*/

Container::Container(uint16_t _type) :
Container(_type, items[_type].maxItems) {}


/*Container::Container(uint16_t _type, uint16_t _size) : Item(_type)
{
maxSize = _size;
totalWeight = 0;
serializationCount = 0;
unlocked = true;
pagination = false;
}*/

Container::Container(uint16_t _type, uint16_t _size, bool unlocked /*= true*/, bool pagination /*= false*/) :
Item(_type),
maxSize(_size),
unlocked(unlocked),
pagination(pagination)
{}

Container::Container(Tile* tile) : Item(ITEM_BROWSEFIELD)
{
TileItemVector* itemVector = tile->getItemList();
if (itemVector) {
for (Item* item : *itemVector) {
if (item->getContainer() || item->hasProperty(CONST_PROP_MOVEABLE)) {
itemlist.push_front(item);
item->setParent(this);
}
}
}

maxSize = 30;
totalWeight = 0;
serializationCount = 0;
unlocked = false;
pagination = true;
setParent(tile);
}

Container::~Container()
{
if (getID() == ITEM_BROWSEFIELD) {
g_game.browseFields.erase(getTile());

for (Item* item : itemlist) {
item->setParent(parent);
}
} else {
for (Item* item : itemlist) {
item->setParent(nullptr);
item->decrementReferenceCounter();
}
}
}

Item* Container::clone() const
{
Container* clone = static_cast<Container*>(Item::clone());
for (Item* item : itemlist) {
clone->addItem(item->clone());
}
clone->totalWeight = totalWeight;
return clone;
}

Container* Container::getParentContainer()
{
Thing* thing = getParent();
if (!thing) {
return nullptr;
}
return thing->getContainer();
}

bool Container::hasParent() const
{
return getID() != ITEM_BROWSEFIELD && dynamic_cast<const Player*>(getParent()) == nullptr;
}

void Container::addItem(Item* item)
{
itemlist.push_back(item);
item->setParent(this);
}

Attr_ReadValue Container::readAttr(AttrTypes_t attr, PropStream& propStream)
{
if (attr == ATTR_CONTAINER_ITEMS) {
if (!propStream.read<uint32_t>(serializationCount)) {
return ATTR_READ_ERROR;
}
return ATTR_READ_END;
}
return Item::readAttr(attr, propStream);
}

bool Container::unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream)
{
bool ret = Item::unserializeItemNode(f, node, propStream);
if (!ret) {
return false;
}

uint32_t type;
NODE nodeItem = f.getChildNode(node, type);
while (nodeItem) {
//load container items
if (type != OTBM_ITEM) {
// unknown type
return false;
}

PropStream itemPropStream;
if (!f.getProps(nodeItem, itemPropStream)) {
return false;
}

Item* item = Item::CreateItem(itemPropStream);
if (!item) {
return false;
}

if (!item->unserializeItemNode(f, nodeItem, itemPropStream)) {
return false;
}

addItem(item);
updateItemWeight(item->getWeight());

nodeItem = f.getNextNode(nodeItem, type);
}
return true;
}

void Container::updateItemWeight(int32_t diff)
{
totalWeight += diff;
if (Container* parentContainer = getParentContainer()) {
parentContainer->updateItemWeight(diff);
}
}

uint32_t Container::getWeight() const
{
return Item::getWeight() + totalWeight;
}

std::string Container::getContentDescription() const
{
std::eek:stringstream os;
return getContentDescription(os).str();
}

std::eek:stringstream& Container::getContentDescription(std::eek:stringstream& os) const
{
bool firstitem = true;
for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) {
Item* item = *it;

Container* container = item->getContainer();
if (container && !container->empty()) {
continue;
}

if (firstitem) {
firstitem = false;
} else {
os << ", ";
}

os << item->getNameDescription();
}

if (firstitem) {
os << "nothing";
}
return os;
}

Item* Container::getItemByIndex(size_t index) const
{
if (index >= size()) {
return nullptr;
}
return itemlist[index];
}

uint32_t Container::getItemHoldingCount() const
{
uint32_t counter = 0;
for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) {
++counter;
}
return counter;
}

bool Container::isHoldingItem(const Item* item) const
{
for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) {
if (*it == item) {
return true;
}
}
return false;
}

void Container::eek:nAddContainerItem(Item* item)
{
SpectatorVec list;
g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2);

//send to client
for (Creature* spectator : list) {
spectator->getPlayer()->sendAddContainerItem(this, item);
}

//event methods
for (Creature* spectator : list) {
spectator->getPlayer()->onAddContainerItem(item);
}
}

void Container::eek:nUpdateContainerItem(uint32_t index, Item* oldItem, Item* newItem)
{
SpectatorVec list;
g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2);

//send to client
for (Creature* spectator : list) {
spectator->getPlayer()->sendUpdateContainerItem(this, index, newItem);
}

//event methods
for (Creature* spectator : list) {
spectator->getPlayer()->onUpdateContainerItem(this, oldItem, newItem);
}
}

void Container::eek:nRemoveContainerItem(uint32_t index, Item* item)
{
SpectatorVec list;
g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2);

//send change to client
for (Creature* spectator : list) {
spectator->getPlayer()->sendRemoveContainerItem(this, index);
}

//event methods
for (Creature* spectator : list) {
spectator->getPlayer()->onRemoveContainerItem(this, item);
}
}

ReturnValue Container::queryAdd(int32_t index, const Thing& thing, uint32_t count,
uint32_t flags, Creature* actor/* = nullptr*/) const
{
bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags);
if (childIsOwner) {
//a child container is querying, since we are the top container (not carried by a player)
//just return with no error.
return RETURNVALUE_NOERROR;
}

if (!unlocked) {
return RETURNVALUE_NOTPOSSIBLE;
}

const Item* item = thing.getItem();
if (item == nullptr) {
return RETURNVALUE_NOTPOSSIBLE;
}

if (!item->isPickupable()) {
return RETURNVALUE_CANNOTPICKUP;
}

if (item == this) {
return RETURNVALUE_THISISIMPOSSIBLE;
}

const Cylinder* cylinder = getParent();
if (!hasBitSet(FLAG_NOLIMIT, flags)) {
while (cylinder) {
if (cylinder == &thing) {
return RETURNVALUE_THISISIMPOSSIBLE;
}

if (dynamic_cast<const Inbox*>(cylinder)) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}

cylinder = cylinder->getParent();
}

//if (index == INDEX_WHEREEVER && size() >= capacity()) {
if (index == INDEX_WHEREEVER && size() >= capacity() && !hasPagination()) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}
} else {
while (cylinder) {
if (cylinder == &thing) {
return RETURNVALUE_THISISIMPOSSIBLE;
}

cylinder = cylinder->getParent();
}
}

const Cylinder* topParent = getTopParent();
if (topParent != this) {
return topParent->queryAdd(INDEX_WHEREEVER, *item, count, flags | FLAG_CHILDISOWNER, actor);
} else {
return RETURNVALUE_NOERROR;
}
}

ReturnValue Container::queryMaxCount(int32_t index, const Thing& thing, uint32_t count,
uint32_t& maxQueryCount, uint32_t flags) const
{
const Item* item = thing.getItem();
if (item == nullptr) {
maxQueryCount = 0;
return RETURNVALUE_NOTPOSSIBLE;
}

//if (hasBitSet(FLAG_NOLIMIT, flags)) {
if (hasBitSet(FLAG_NOLIMIT, flags) || hasPagination()) {
maxQueryCount = std::max<uint32_t>(1, count);
return RETURNVALUE_NOERROR;
}

int32_t freeSlots = std::max<int32_t>(capacity() - size(), 0);

if (item->isStackable()) {
uint32_t n = 0;

if (index == INDEX_WHEREEVER) {
//Iterate through every item and check how much free stackable slots there is.
uint32_t slotIndex = 0;
for (Item* containerItem : itemlist) {
if (containerItem != item && containerItem->equals(item) && containerItem->getItemCount() < 100) {
uint32_t remainder = (100 - containerItem->getItemCount());
if (queryAdd(slotIndex++, *item, remainder, flags) == RETURNVALUE_NOERROR) {
n += remainder;
}
}
}
} else {
const Item* destItem = getItemByIndex(index);
if (item->equals(destItem) && destItem->getItemCount() < 100) {
uint32_t remainder = 100 - destItem->getItemCount();
if (queryAdd(index, *item, remainder, flags) == RETURNVALUE_NOERROR) {
n = remainder;
}
}
}

maxQueryCount = freeSlots * 100 + n;
if (maxQueryCount < count) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}
} else {
maxQueryCount = freeSlots;
if (maxQueryCount == 0) {
return RETURNVALUE_CONTAINERNOTENOUGHROOM;
}
}
return RETURNVALUE_NOERROR;
}

ReturnValue Container::queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const
{
int32_t index = getThingIndex(&thing);
if (index == -1) {
return RETURNVALUE_NOTPOSSIBLE;
}

const Item* item = thing.getItem();
if (item == nullptr) {
return RETURNVALUE_NOTPOSSIBLE;
}

if (count == 0 || (item->isStackable() && count > item->getItemCount())) {
return RETURNVALUE_NOTPOSSIBLE;
}

if (!item->isMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)) {
return RETURNVALUE_NOTMOVEABLE;
}
return RETURNVALUE_NOERROR;
}

Cylinder* Container::queryDestination(int32_t& index, const Thing &thing, Item** destItem,
uint32_t& flags)
{
if (!unlocked) {
*destItem = nullptr;
return this;
}

if (index == 254 /*move up*/) {
index = INDEX_WHEREEVER;
*destItem = nullptr;

Container* parentContainer = dynamic_cast<Container*>(getParent());
if (parentContainer) {
return parentContainer;
}
return this;
}

if (index == 255 /*add wherever*/) {
index = INDEX_WHEREEVER;
*destItem = nullptr;
} else if ((index >= static_cast<int32_t>(capacity()) && !pagination) || index >= static_cast<int32_t>(size())) {
/*
if you have a container, maximize it to show all 20 slots
then you open a bag that is inside the container you will have a bag with 8 slots
and a "grey" area where the other 12 slots where from the container
if you drop the item on that grey area
the client calculates the slot position as if the bag has 20 slots
*/
index = INDEX_WHEREEVER;
*destItem = nullptr;
}

const Item* item = thing.getItem();
if (!item) {
return this;
}

bool autoStack = !hasBitSet(FLAG_IGNOREAUTOSTACK, flags);
if (autoStack && item->isStackable() && item->getParent() != this) {
//if (autoStack && item->isStackable() && item->getParent() != this && item->getActionId() > 0) {
//try find a suitable item to stack with
uint32_t n = 0;
for (Item* listItem : itemlist) {
if (listItem != item && listItem->equals(item) && listItem->getItemCount() < 100) {
*destItem = listItem;
index = n;
return this;
}
++n;
}
}

if (index != INDEX_WHEREEVER) {
Item* itemFromIndex = getItemByIndex(index);
if (itemFromIndex) {
*destItem = itemFromIndex;
}

Cylinder* subCylinder = dynamic_cast<Cylinder*>(*destItem);
if (subCylinder) {
index = INDEX_WHEREEVER;
*destItem = nullptr;
return subCylinder; // se der errado mudar aqui em baixo
} else if (pagination) {
*destItem = nullptr;
index = INDEX_WHEREEVER;
}
}
return this;
}

void Container::addThing(Thing* thing)
{
return addThing(0, thing);
}

void Container::addThing(int32_t index, Thing* thing)
{
if (index >= static_cast<int32_t>(capacity())) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

Item* item = thing->getItem();
if (item == nullptr) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

item->setParent(this);
itemlist.push_front(item);
updateItemWeight(item->getWeight());

//send change to client
if (getParent() && (getParent() != VirtualCylinder::virtualCylinder)) {
onAddContainerItem(item);
}
}

void Container::addItemBack(Item* item)
{
addItem(item);
updateItemWeight(item->getWeight());

//send change to client
if (getParent() && (getParent() != VirtualCylinder::virtualCylinder)) {
onAddContainerItem(item);
}
}

void Container::updateThing(Thing* thing, uint16_t itemId, uint32_t count)
{
int32_t index = getThingIndex(thing);
if (index == -1) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

Item* item = thing->getItem();
if (item == nullptr) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

const int32_t oldWeight = item->getWeight();
item->setID(itemId);
item->setSubType(count);
updateItemWeight(-oldWeight + item->getWeight());

//send change to client
if (getParent()) {
onUpdateContainerItem(index, item, item);
}
}

void Container::replaceThing(uint32_t index, Thing* thing)
{
Item* item = thing->getItem();
if (!item) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

Item* replacedItem = getItemByIndex(index);
if (!replacedItem) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

itemlist[index] = item;
item->setParent(this);
updateItemWeight(-static_cast<int32_t>(replacedItem->getWeight()) + item->getWeight());

//send change to client
if (getParent()) {
onUpdateContainerItem(index, replacedItem, item);
}

replacedItem->setParent(nullptr);
}

void Container::removeThing(Thing* thing, uint32_t count)
{
Item* item = thing->getItem();
if (item == nullptr) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

int32_t index = getThingIndex(thing);
if (index == -1) {
return /*RETURNVALUE_NOTPOSSIBLE*/;
}

if (item->isStackable() && count != item->getItemCount()) {
uint8_t newCount = static_cast<uint8_t>(std::max<int32_t>(0, item->getItemCount() - count));
const int32_t oldWeight = item->getWeight();
item->setItemCount(newCount);
updateItemWeight(-oldWeight + item->getWeight());

//send change to client
if (getParent()) {
onUpdateContainerItem(index, item, item);
}
} else {
updateItemWeight(-static_cast<int32_t>(item->getWeight()));

//send change to client
if (getParent()) {
onRemoveContainerItem(index, item);
}

item->setParent(nullptr);
itemlist.erase(itemlist.begin() + index);
}
}

int32_t Container::getThingIndex(const Thing* thing) const
{
int32_t index = 0;
for (Item* item : itemlist) {
if (item == thing) {
return index;
}
++index;
}
return -1;
}

size_t Container::getFirstIndex() const
{
return 0;
}

size_t Container::getLastIndex() const
{
return size();
}

uint32_t Container::getItemTypeCount(uint16_t itemId, int32_t subType/* = -1*/) const
{
uint32_t count = 0;
for (Item* item : itemlist) {
if (item->getID() == itemId) {
count += countByType(item, subType);
}
}
return count;
}

std::map<uint32_t, uint32_t>& Container::getAllItemTypeCount(std::map<uint32_t, uint32_t> &countMap) const
{
for (Item* item : itemlist) {
countMap[item->getID()] += item->getItemCount();
}
return countMap;
}

Thing* Container::getThing(size_t index) const
{
return getItemByIndex(index);
}

void Container::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t)
{
Cylinder* topParent = getTopParent();
if (topParent->getCreature()) {
topParent->postAddNotification(thing, oldParent, index, LINK_TOPPARENT);
} else if (topParent == this) {
//let the tile class notify surrounding players
if (topParent->getParent()) {
topParent->getParent()->postAddNotification(thing, oldParent, index, LINK_NEAR);
}
} else {
topParent->postAddNotification(thing, oldParent, index, LINK_PARENT);
}
}

void Container::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t)
{
Cylinder* topParent = getTopParent();
if (topParent->getCreature()) {
topParent->postRemoveNotification(thing, newParent, index, LINK_TOPPARENT);
} else if (topParent == this) {
//let the tile class notify surrounding players
if (topParent->getParent()) {
topParent->getParent()->postRemoveNotification(thing, newParent, index, LINK_NEAR);
}
} else {
topParent->postRemoveNotification(thing, newParent, index, LINK_PARENT);
}
}

void Container::internalAddThing(Thing* thing)
{
internalAddThing(0, thing);
}

void Container::internalAddThing(uint32_t, Thing* thing)
{
Item* item = thing->getItem();
if (item == nullptr) {
return;
}

item->setParent(this);
itemlist.push_front(item);
updateItemWeight(item->getWeight());
}

void Container::startDecaying()
{
for (Item* item : itemlist) {
item->startDecaying();
}
}

ContainerIterator Container::iterator() const
{
ContainerIterator cit;
if (!itemlist.empty()) {
cit.over.push_back(this);
cit.cur = itemlist.begin();
}
return cit;
}

Item* ContainerIterator::eek:perator*()
{
return *cur;
}

void ContainerIterator::advance()
{
if (Item* i = *cur) {
if (Container* c = i->getContainer()) {
if (!c->empty()) {
over.push_back(c);
}
}
}

++cur;

if (cur == over.front()->itemlist.end()) {
over.pop_front();
if (!over.empty()) {
cur = over.front()->itemlist.begin();
}
}
}


container.h link: hastebin


thanks, used tfs 1.2

Last warning, read the rules; Rules for the Support board
#8

Just because you solved it dosn't mean we will delete the thread, what if someone else runs into the same issue and uses the serach function?
 
Last warning, read the rules; Rules for the Support board
#8

Just because you solved it dosn't mean we will delete the thread, what if someone else runs into the same issue and uses the serach function?

I think nobody will experience this, I was made the changes and was with one error on cap, my mistake. Can you delete this thread?
 
I think nobody will experience this, I was made the changes and was with one error on cap, my mistake. Can you delete this thread?
you should block OTLand in your router seriously.
You shouldn't have permission to check any support thread or develope thread at all.

If everyone was like you, OTLand would just be a huge list of "solved" and "nvm" tiled threads containing "nvm, I fixed myself".
 
I think nobody will experience this, I was made the changes and was with one error on cap, my mistake. Can you delete this thread?

Dosn't matter if you think anyone will experience this, they might do a serach for what a nil error means and end up with a bunch of "solved nvm"

I can delete the thread, but I won't.
I want you to fix the thread, revert the title and add what you did to solve it.

You have gotten alot of help in the support board, you could atleast do us the favor of following the rules.
 
Dosn't matter if you think anyone will experience this, they might do a serach for what a nil error means and end up with a bunch of "solved nvm"

I can delete the thread, but I won't.
I want you to fix the thread, revert the title and add what you did to solve it.

You have gotten alot of help in the support board, you could atleast do us the favor of following the rules.

I solved this by going back to the original file.
Do you want me to put the original file? Here goes:
otxserver/container.cpp at otxserv3 · mattyx14/otxserver · GitHub
otxserver/container.h at otxserv3 · mattyx14/otxserver · GitHub

Can I mark my own answer as the best? That's one of the reasons I asked you to delete the thread.


Used this, but for tfs 1.2
 
Solution
Back
Top