tibia-rme/source/tile.cpp
Hampus Joakim Nilsson 8dbc487ef2 Initial commit of RME 3.0.
Clean git repository since the old svn / git mess was pretty much
unrecoverable unfortunetly. I would have liked to keep the history
for posterity, but that proved to be a futile quest.
2012-06-29 16:45:30 +02:00

625 lines
11 KiB
C++

//////////////////////////////////////////////////////////////////////
// This file is part of Remere's Map Editor
//////////////////////////////////////////////////////////////////////
// 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 3 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, see <http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////////
// $URL: http://svn.rebarp.se/svn/RME/trunk/source/tile.hpp $
// $Id: tile.hpp 298 2010-02-23 17:09:13Z admin $
#include "main.h"
#include "brush.h"
#include "tile.h"
#include "creature.h"
#include "house.h"
#include "basemap.h"
#include "spawn.h"
#include "ground_brush.h"
#include "wall_brush.h"
#include "carpet_brush.h"
#include "table_brush.h"
Tile::Tile(int x, int y, int z) :
location(NULL),
ground(NULL),
creature(NULL),
spawn(NULL),
house_id(0),
mapflags(0),
statflags(0)
{
}
Tile::Tile(TileLocation& loc) :
location(&loc),
ground(NULL),
creature(NULL),
spawn(NULL),
house_id(0),
mapflags(0),
statflags(0)
{
}
Tile::~Tile()
{
while(items.empty() == false) {
delete items.back();
items.pop_back();
}
delete creature;
//printf("%d,%d,%d,%p\n", tilePos.x, tilePos.y, tilePos.z, ground);
delete ground;
delete spawn;
}
Tile* Tile::deepCopy(BaseMap& map)
{
Tile* copy = map.allocator.allocateTile(location);
copy->flags = flags;
copy->house_id = house_id;
if(spawn) copy->spawn = spawn->deepCopy();
if(creature) copy->creature = creature->deepCopy();
// Spawncount & exits are not transferred on copy!
if(ground) copy->ground = ground->deepCopy();
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
copy->items.push_back((*it)->deepCopy());
++it;
}
return copy;
}
uint Tile::memsize() const
{
uint mem = sizeof(*this);
if(ground) mem += ground->memsize();
ItemVector::const_iterator it;
it = items.begin();
while(it != items.end()) {
mem += (*it)->memsize();
++it;
}
mem += sizeof(Item*) * items.capacity();
return mem;
}
int Tile::size() const
{
int sz = 0;
if(ground) ++sz;
sz += items.size();
if(creature) ++sz;
if(spawn) ++sz;
if(location)
{
if(location->getHouseExits()) ++sz;
if(location->getSpawnCount()) ++sz;
if(location->getWaypointCount()) ++ sz;
}
return sz;
}
void Tile::merge(Tile* other) {
if(other->isPZ()) setPZ(true);
if(other->house_id) {
house_id = other->house_id;
}
if(other->ground) {
delete ground;
ground = other->ground;
other->ground = NULL;
}
if(other->creature) {
delete creature;
creature = other->creature;
other->creature = NULL;
}
if(other->spawn) {
delete spawn;
spawn = other->spawn;
other->spawn = NULL;
}
if(other->creature) {
delete creature;
creature = other->creature;
other->creature = NULL;
}
ItemVector::iterator it;
it = other->items.begin();
while(it != other->items.end()) {
addItem(*it);
++it;
}
other->items.clear();
}
bool Tile::hasProperty(enum ITEMPROPERTY prop) const
{
if(prop == PROTECTIONZONE && isPZ())
return true;
if(ground && ground->hasProperty(prop)){
return true;
}
ItemVector::const_iterator iit;
for(iit = items.begin(); iit != items.end(); ++iit){
if((*iit)->hasProperty(prop))
return true;
}
return false;
}
Item* Tile::getTopItem() {
if(items.size() > 0 && items.back()->isMetaItem() == false)
return items.back();
if(ground && ground->isMetaItem() == false) {
return ground;
}
return NULL;
}
void Tile::addItem(Item* item) {
if(!item) return;
if(item->isGroundTile()) {
//printf("ADDING GROUND\n");
delete ground;
ground = item;
return;
}
ItemVector::iterator it;
uint16_t gid = item->getGroundEquivalent();
if(gid != 0) {
delete ground;
ground = Item::Create(gid);
// At the very bottom!
it = items.begin();
} else {
if(item->isAlwaysOnBottom()) {
it = items.begin();
while(true) {
if(it == items.end()) {
break;
} else if((*it)->isAlwaysOnBottom()) {
if(item->getTopOrder() < (*it)->getTopOrder()) {
break;
}
} else { // Always on top
break;
}
++it;
}
} else {
it = items.end();
}
}
items.insert(it, item);
if(item->isSelected()) {
statflags |= TILESTATE_SELECTED;
}
}
void Tile::select() {
if(size() == 0) return;
if(ground) ground->select();
if(spawn) spawn->select();
if(creature) creature->select();
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
(*it)->select();
++it;
}
statflags |= TILESTATE_SELECTED;
}
void Tile::deselect() {
if(ground) ground->deselect();
if(spawn) spawn->deselect();
if(creature) creature->deselect();
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
(*it)->deselect();
++it;
}
statflags &= ~TILESTATE_SELECTED;
}
Item* Tile::getTopSelectedItem() {
for(ItemVector::reverse_iterator iter = items.rbegin();
iter != items.rend();
++iter)
{
if((*iter)->isSelected() && (*iter)->isMetaItem() == false) {
return *iter;
}
}
if(ground && ground->isSelected() && ground->isMetaItem() == false) {
return ground;
}
return NULL;
}
ItemVector Tile::popSelectedItems() {
ItemVector pop_items;
if(!isSelected()) return pop_items;
if(ground && ground->isSelected()) {
pop_items.push_back(ground);
ground = NULL;
}
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isSelected()) {
pop_items.push_back(*it);
it = items.erase(it);
} else {
++it;
}
}
statflags &= ~TILESTATE_SELECTED;
return pop_items;
}
ItemVector Tile::getSelectedItems() {
ItemVector selected_items;
if(!isSelected()) return selected_items;
if(ground && ground->isSelected()) {
selected_items.push_back(ground);
}
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isSelected()) {
selected_items.push_back(*it);
} it++;
}
return selected_items;
}
uint8_t Tile::getMiniMapColor() const {
for(ItemVector::const_reverse_iterator item_iter = items.rbegin();
item_iter != items.rend();
++item_iter)
{
if((*item_iter)->getMiniMapColor()) {
return (*item_iter)->getMiniMapColor();
break;
}
}
// check ground too
if(hasGround()) {
return ground->getMiniMapColor();
}
return 0;
}
bool tilePositionLessThan(const Tile* a, const Tile* b)
{
return a->getPosition() < b->getPosition();
}
bool tilePositionVisualLessThan(const Tile* a, const Tile* b)
{
Position pa = a->getPosition();
Position pb = b->getPosition();
if(pa.z > pb.z)
return true;
if(pa.z < pb.z)
return false;
if(pa.y < pb.y)
return true;
if(pa.y > pb.y)
return false;
if(pa.x < pb.x)
return true;
return false;
}
void Tile::update()
{
statflags &= TILESTATE_MODIFIED;
if(spawn && spawn->isSelected()) {
statflags |= TILESTATE_SELECTED;
}
if(creature && creature->isSelected()) {
statflags |= TILESTATE_SELECTED;
}
if(ground) {
if(ground->isSelected()) {
statflags |= TILESTATE_SELECTED;
}
if(ground->isBlocking()) {
statflags |= TILESTATE_BLOCKING;
}
if(ground->getUniqueID() != 0) {
statflags |= TILESTATE_UNIQUE;
}
}
ItemVector::const_iterator iter = items.begin();
while(iter != items.end()) {
Item* i = *iter;
if(i->isSelected()) {
statflags |= TILESTATE_SELECTED;
}
if(i->getUniqueID() != 0) {
statflags |= TILESTATE_UNIQUE;
}
ItemType& it = item_db[i->getID()];
if(it.blockSolid) {
statflags |= TILESTATE_BLOCKING;
}
if(it.isOptionalBorder) {
statflags |= TILESTATE_OP_BORDER;
}
if(it.isTable) {
statflags |= TILESTATE_HAS_TABLE;
}
if(it.isCarpet) {
statflags |= TILESTATE_HAS_CARPET;
}
++iter;
}
if((statflags & TILESTATE_BLOCKING) == 0) {
if(ground == NULL && items.size() == 0) {
statflags |= TILESTATE_BLOCKING;
}
}
}
void Tile::borderize(BaseMap* parent) {
GroundBrush::doBorders(parent, this);
}
void Tile::addBorderItem(Item* item) {
if(!item) return;
ASSERT(item->isBorder());
items.insert(items.begin(), item);
}
GroundBrush* Tile::getGroundBrush() const {
if(ground) {
if(ground->getGroundBrush()) {
return ground->getGroundBrush();
}
}
return NULL;
}
void Tile::cleanBorders() {
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isBorder()) {
delete *it;
it = items.erase(it);
} else {
// Borders should only be on the bottom, we can ignore the rest of the items
return;
}
}
}
void Tile::wallize(BaseMap* parent) {
WallBrush::doWalls(parent, this);
}
Item* Tile::getWall() const {
ItemVector::const_iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isWall()) {
return *it;
} ++it;
}
return NULL;
}
Item* Tile::getCarpet() const {
ItemVector::const_iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isCarpet()) {
return *it;
} ++it;
}
return NULL;
}
Item* Tile::getTable() const {
ItemVector::const_iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isTable()) {
return *it;
} ++it;
}
return NULL;
}
void Tile::addWallItem(Item* item) {
if(!item) {
return;
}
ASSERT(item->isWall());
addItem(item);
}
void Tile::cleanWalls(bool dontdelete) {
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isWall()) {
if(dontdelete == false) {
delete *it;
}
it = items.erase(it);
} else ++it;
}
}
void Tile::cleanWalls(WallBrush* wb) {
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isWall() && wb->hasWall(*it)) {
delete *it;
it = items.erase(it);
} else ++it;
}
}
void Tile::cleanTables(bool dontdelete) {
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isTable()) {
if(dontdelete == false) {
delete *it;
}
it = items.erase(it);
} else ++it;
}
}
void Tile::tableize(BaseMap* parent) {
TableBrush::doTables(parent, this);
}
void Tile::carpetize(BaseMap* parent) {
CarpetBrush::doCarpets(parent, this);
}
void Tile::selectGround() {
bool selected_ = false;
if(ground) {
ground->select();
selected_ = true;
}
ItemVector::iterator it;
it = items.begin();
while(it != items.end()) {
if((*it)->isBorder()) {
(*it)->select();
selected_ = true;
} else {
break;
}
++it;
}
if(selected_) statflags |= TILESTATE_SELECTED;
}
void Tile::deselectGround() {
if(ground) {
ground->deselect();
}
ItemVector::iterator it = items.begin();
while(it != items.end()) {
if((*it)->isBorder()) {
(*it)->deselect();
} else {
break;
}
++it;
}
}
void Tile::setHouse(House* _house) {
house_id = (_house? _house->id : 0);
}
void Tile::addHouseExit(House* h) {
if(!h)
return;
HouseExitList* house_exits = location->createHouseExits();
house_exits->push_back(h->id);
}
void Tile::removeHouseExit(House* h) {
if(!h)
return;
HouseExitList* house_exits = location->getHouseExits();
if(!house_exits)
return;
for(std::vector<uint32_t>::iterator it = house_exits->begin();
it != house_exits->end();
++it)
{
if(*it == h->id) {
house_exits->erase(it);
return;
}
}
}