mirror of
https://github.com/opentibiabr/remeres-map-editor
synced 2026-08-15 18:26:04 -04:00
Removed libxml2 to use pugixml. Fixed a bug with the progress bar. Changed some things in most xml files that pugixml did not like. Updated the Visual Studio project. Any NULL symbol has been changed to nullptr. This most probably broke the CMake that was recently added. And probably some other things.
625 lines
11 KiB
C++
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(nullptr),
|
|
ground(nullptr),
|
|
creature(nullptr),
|
|
spawn(nullptr),
|
|
house_id(0),
|
|
mapflags(0),
|
|
statflags(0)
|
|
{
|
|
}
|
|
|
|
Tile::Tile(TileLocation& loc) :
|
|
location(&loc),
|
|
ground(nullptr),
|
|
creature(nullptr),
|
|
spawn(nullptr),
|
|
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 = nullptr;
|
|
}
|
|
|
|
if(other->creature) {
|
|
delete creature;
|
|
creature = other->creature;
|
|
other->creature = nullptr;
|
|
}
|
|
|
|
if(other->spawn) {
|
|
delete spawn;
|
|
spawn = other->spawn;
|
|
other->spawn = nullptr;
|
|
}
|
|
|
|
if(other->creature) {
|
|
delete creature;
|
|
creature = other->creature;
|
|
other->creature = nullptr;
|
|
}
|
|
|
|
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 nullptr;
|
|
}
|
|
|
|
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 nullptr;
|
|
}
|
|
|
|
ItemVector Tile::popSelectedItems() {
|
|
ItemVector pop_items;
|
|
|
|
if(!isSelected()) return pop_items;
|
|
|
|
if(ground && ground->isSelected()) {
|
|
pop_items.push_back(ground);
|
|
ground = nullptr;
|
|
}
|
|
|
|
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 == nullptr && 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 nullptr;
|
|
}
|
|
|
|
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 nullptr;
|
|
}
|
|
|
|
Item* Tile::getCarpet() const {
|
|
ItemVector::const_iterator it;
|
|
|
|
it = items.begin();
|
|
while(it != items.end()) {
|
|
if((*it)->isCarpet()) {
|
|
return *it;
|
|
} ++it;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Item* Tile::getTable() const {
|
|
ItemVector::const_iterator it;
|
|
|
|
it = items.begin();
|
|
while(it != items.end()) {
|
|
if((*it)->isTable()) {
|
|
return *it;
|
|
} ++it;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|