2012-06-29 16:44:26 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
// This file is part of Remere's Map Editor
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
2020-07-30 11:42:28 -03:00
|
|
|
// Remere's Map Editor is free software: you can redistribute it and/or modify
|
2012-06-29 16:44:26 +02:00
|
|
|
// 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.
|
|
|
|
|
//
|
2020-07-30 11:42:28 -03:00
|
|
|
// Remere's Map Editor is distributed in the hope that it will be useful,
|
2012-06-29 16:44:26 +02:00
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2020-07-30 11:42:28 -03:00
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2012-06-29 16:44:26 +02:00
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU General Public License
|
2020-07-30 11:42:28 -03:00
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2012-06-29 16:44:26 +02:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
|
|
#include "brush.h"
|
|
|
|
|
#include "carpet_brush.h"
|
|
|
|
|
#include "creature_brush.h"
|
|
|
|
|
#include "doodad_brush.h"
|
|
|
|
|
#include "ground_brush.h"
|
|
|
|
|
#include "house_brush.h"
|
|
|
|
|
#include "house_exit_brush.h"
|
|
|
|
|
#include "raw_brush.h"
|
|
|
|
|
#include "spawn_brush.h"
|
|
|
|
|
#include "table_brush.h"
|
|
|
|
|
#include "wall_brush.h"
|
|
|
|
|
#include "waypoint_brush.h"
|
|
|
|
|
|
|
|
|
|
#include "settings.h"
|
|
|
|
|
|
|
|
|
|
#include "sprites.h"
|
|
|
|
|
|
|
|
|
|
#include "item.h"
|
|
|
|
|
#include "complexitem.h"
|
|
|
|
|
#include "creatures.h"
|
|
|
|
|
#include "creature.h"
|
|
|
|
|
#include "map.h"
|
|
|
|
|
|
|
|
|
|
#include "gui.h"
|
|
|
|
|
|
2016-10-25 10:19:42 -03:00
|
|
|
Brushes g_brushes;
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2014-03-01 14:44:11 +01:00
|
|
|
Brushes::Brushes()
|
|
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-01 14:44:11 +01:00
|
|
|
Brushes::~Brushes()
|
|
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-01 14:44:11 +01:00
|
|
|
void Brushes::clear()
|
|
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
for(auto brushEntry : brushes) {
|
2014-03-01 14:44:11 +01:00
|
|
|
delete brushEntry.second;
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
brushes.clear();
|
2014-03-01 14:44:11 +01:00
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
for(auto borderEntry : borders) {
|
2014-03-01 14:44:11 +01:00
|
|
|
delete borderEntry.second;
|
|
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
borders.clear();
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-01 14:44:11 +01:00
|
|
|
void Brushes::init()
|
|
|
|
|
{
|
2016-09-29 20:30:54 -03:00
|
|
|
addBrush(g_gui.optional_brush = newd OptionalBorderBrush());
|
|
|
|
|
addBrush(g_gui.eraser = newd EraserBrush());
|
|
|
|
|
addBrush(g_gui.spawn_brush = newd SpawnBrush());
|
|
|
|
|
addBrush(g_gui.normal_door_brush = newd DoorBrush(WALL_DOOR_NORMAL));
|
|
|
|
|
addBrush(g_gui.locked_door_brush = newd DoorBrush(WALL_DOOR_LOCKED));
|
|
|
|
|
addBrush(g_gui.magic_door_brush = newd DoorBrush(WALL_DOOR_MAGIC));
|
|
|
|
|
addBrush(g_gui.quest_door_brush = newd DoorBrush(WALL_DOOR_QUEST));
|
|
|
|
|
addBrush(g_gui.hatch_door_brush = newd DoorBrush(WALL_HATCH_WINDOW));
|
|
|
|
|
addBrush(g_gui.window_door_brush = newd DoorBrush(WALL_WINDOW));
|
|
|
|
|
addBrush(g_gui.house_brush = newd HouseBrush());
|
|
|
|
|
addBrush(g_gui.house_exit_brush = newd HouseExitBrush());
|
|
|
|
|
addBrush(g_gui.waypoint_brush = newd WaypointBrush());
|
|
|
|
|
|
|
|
|
|
addBrush(g_gui.pz_brush = newd FlagBrush(TILESTATE_PROTECTIONZONE));
|
|
|
|
|
addBrush(g_gui.rook_brush = newd FlagBrush(TILESTATE_NOPVP));
|
|
|
|
|
addBrush(g_gui.nolog_brush = newd FlagBrush(TILESTATE_NOLOGOUT));
|
|
|
|
|
addBrush(g_gui.pvp_brush = newd FlagBrush(TILESTATE_PVPZONE));
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
GroundBrush::init();
|
|
|
|
|
WallBrush::init();
|
|
|
|
|
TableBrush::init();
|
|
|
|
|
CarpetBrush::init();
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-22 20:16:17 +01:00
|
|
|
bool Brushes::unserializeBrush(pugi::xml_node node, wxArrayString& warnings)
|
|
|
|
|
{
|
|
|
|
|
pugi::xml_attribute attribute;
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!(attribute = node.attribute("name"))) {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back("Brush node without name.");
|
2012-06-29 16:44:26 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-22 20:16:17 +01:00
|
|
|
const std::string& brushName = attribute.as_string();
|
2015-12-06 11:42:37 -03:00
|
|
|
if(brushName == "all" || brushName == "none") {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back(wxString("Using reserved brushname \"") << wxstr(brushName) << "\".");
|
2012-06-29 16:44:26 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-22 20:16:17 +01:00
|
|
|
Brush* brush = getBrush(brushName);
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!brush) {
|
|
|
|
|
if(!(attribute = node.attribute("type"))) {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back("Couldn't read brush type");
|
2012-06-29 16:44:26 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-22 20:16:17 +01:00
|
|
|
const std::string brushType = attribute.as_string();
|
2015-12-06 11:42:37 -03:00
|
|
|
if(brushType == "border" || brushType == "ground") {
|
2014-01-22 20:16:17 +01:00
|
|
|
brush = newd GroundBrush();
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(brushType == "wall") {
|
2014-01-22 20:16:17 +01:00
|
|
|
brush = newd WallBrush();
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(brushType == "wall decoration") {
|
2014-01-22 20:16:17 +01:00
|
|
|
brush = newd WallDecorationBrush();
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(brushType == "carpet") {
|
2014-01-22 20:16:17 +01:00
|
|
|
brush = newd CarpetBrush();
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(brushType == "table") {
|
2014-01-22 20:16:17 +01:00
|
|
|
brush = newd TableBrush();
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(brushType == "doodad") {
|
2014-01-22 20:16:17 +01:00
|
|
|
brush = newd DoodadBrush();
|
|
|
|
|
} else {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back(wxString("Unknown brush type ") << wxstr(brushType));
|
2014-01-22 20:16:17 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ASSERT(brush);
|
|
|
|
|
brush->setName(brushName);
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!node.first_child()) {
|
2012-06-29 16:44:26 +02:00
|
|
|
brushes.insert(std::make_pair(brush->getName(), brush));
|
2014-01-22 20:16:17 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2014-01-22 20:16:17 +01:00
|
|
|
wxArrayString subWarnings;
|
|
|
|
|
brush->load(node, subWarnings);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2014-01-22 20:16:17 +01:00
|
|
|
if(!subWarnings.empty()) {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back(wxString("Errors while loading brush \"") << wxstr(brush->getName()) << "\"");
|
2014-01-22 20:16:17 +01:00
|
|
|
warnings.insert(warnings.end(), subWarnings.begin(), subWarnings.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(brush->getName() == "all" || brush->getName() == "none") {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back(wxString("Using reserved brushname '") << wxstr(brush->getName()) << "'.");
|
2014-01-22 20:16:17 +01:00
|
|
|
delete brush;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Brush* otherBrush = getBrush(brush->getName());
|
|
|
|
|
if(otherBrush) {
|
|
|
|
|
if(otherBrush != brush) {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back(wxString("Duplicate brush name ") << wxstr(brush->getName()) << ". Undefined behaviour may ensue.");
|
2014-01-22 20:16:17 +01:00
|
|
|
} else {
|
|
|
|
|
// Don't insert
|
|
|
|
|
return true;
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
2014-01-22 20:16:17 +01:00
|
|
|
|
|
|
|
|
brushes.insert(std::make_pair(brush->getName(), brush));
|
2012-06-29 16:44:26 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-22 20:16:17 +01:00
|
|
|
bool Brushes::unserializeBorder(pugi::xml_node node, wxArrayString& warnings)
|
|
|
|
|
{
|
|
|
|
|
pugi::xml_attribute attribute = node.attribute("id");
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!attribute) {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back("Couldn't read border id node");
|
2014-01-22 20:16:17 +01:00
|
|
|
return false;
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2021-06-06 23:45:46 -03:00
|
|
|
uint32_t id = attribute.as_uint();
|
2015-12-06 11:42:37 -03:00
|
|
|
if(borders[id]) {
|
2016-11-05 15:28:14 +01:00
|
|
|
warnings.push_back("Border ID " + std::to_string(id) + " already exists");
|
2014-01-22 20:16:17 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AutoBorder* border = newd AutoBorder(id);
|
|
|
|
|
border->load(node, warnings);
|
|
|
|
|
borders[id] = border;
|
|
|
|
|
return true;
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
void Brushes::addBrush(Brush *brush)
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
brushes.insert(std::make_pair(brush->getName(), brush));
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-01 14:44:11 +01:00
|
|
|
Brush* Brushes::getBrush(const std::string& name) const
|
|
|
|
|
{
|
|
|
|
|
auto it = brushes.find(name);
|
2015-12-06 11:42:37 -03:00
|
|
|
if(it != brushes.end()) {
|
2012-06-29 16:44:26 +02:00
|
|
|
return it->second;
|
2014-03-01 14:44:11 +01:00
|
|
|
}
|
2014-01-22 20:16:17 +01:00
|
|
|
return nullptr;
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-09 16:53:29 +01:00
|
|
|
// Brush
|
2014-02-28 22:34:25 +01:00
|
|
|
uint32_t Brush::id_counter = 0;
|
2012-06-29 16:44:26 +02:00
|
|
|
Brush::Brush() :
|
2014-03-09 16:53:29 +01:00
|
|
|
id(++id_counter), visible(false)
|
2012-06-29 16:44:26 +02:00
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-09 16:53:29 +01:00
|
|
|
Brush::~Brush()
|
|
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-09 16:53:29 +01:00
|
|
|
// TerrainBrush
|
2012-06-29 16:44:26 +02:00
|
|
|
TerrainBrush::TerrainBrush() :
|
2014-03-09 16:53:29 +01:00
|
|
|
look_id(0), hate_friends(false)
|
2012-06-29 16:44:26 +02:00
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-09 16:53:29 +01:00
|
|
|
TerrainBrush::~TerrainBrush()
|
|
|
|
|
{
|
2015-12-06 11:42:37 -03:00
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2014-03-09 16:53:29 +01:00
|
|
|
bool TerrainBrush::friendOf(TerrainBrush* other)
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
uint32_t borderID = other->getID();
|
2015-12-06 11:42:37 -03:00
|
|
|
for(uint32_t friendId : friends) {
|
|
|
|
|
if(friendId == borderID) {
|
2012-06-29 16:44:26 +02:00
|
|
|
//printf("%s is friend of %s\n", getName().c_str(), other->getName().c_str());
|
|
|
|
|
return !hate_friends;
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(friendId == 0xFFFFFFFF) {
|
2012-06-29 16:44:26 +02:00
|
|
|
//printf("%s is generic friend of %s\n", getName().c_str(), other->getName().c_str());
|
|
|
|
|
return !hate_friends;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//printf("%s is enemy of %s\n", getName().c_str(), other->getName().c_str());
|
|
|
|
|
return hate_friends;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
// Flag brush
|
|
|
|
|
// draws pz etc.
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
FlagBrush::FlagBrush(uint32_t _flag) : flag(_flag)
|
|
|
|
|
{
|
|
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
FlagBrush::~FlagBrush()
|
|
|
|
|
{
|
|
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
std::string FlagBrush::getName() const
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
switch(flag) {
|
|
|
|
|
case TILESTATE_PROTECTIONZONE: return "PZ brush (0x01)";
|
|
|
|
|
case TILESTATE_NOPVP: return "No combat zone brush (0x04)";
|
|
|
|
|
case TILESTATE_NOLOGOUT: return "No logout zone brush (0x08)";
|
|
|
|
|
case TILESTATE_PVPZONE: return "PVP Zone brush (0x10)";
|
|
|
|
|
}
|
|
|
|
|
return "Unknown flag brush";
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
int FlagBrush::getLookID() const
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
switch(flag) {
|
|
|
|
|
case TILESTATE_PROTECTIONZONE: return EDITOR_SPRITE_PZ_TOOL;
|
|
|
|
|
case TILESTATE_NOPVP: return EDITOR_SPRITE_NOPVP_TOOL;
|
|
|
|
|
case TILESTATE_NOLOGOUT: return EDITOR_SPRITE_NOLOG_TOOL;
|
|
|
|
|
case TILESTATE_PVPZONE: return EDITOR_SPRITE_PVPZ_TOOL;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
bool FlagBrush::canDraw(BaseMap* map, const Position& position) const
|
|
|
|
|
{
|
2014-03-01 14:44:11 +01:00
|
|
|
Tile* tile = map->getTile(position);
|
2012-06-29 16:44:26 +02:00
|
|
|
return tile && tile->hasGround();
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
void FlagBrush::undraw(BaseMap* map, Tile* tile)
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
tile->unsetMapFlags(flag);
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
void FlagBrush::draw(BaseMap* map, Tile* tile, void* parameter)
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
if(tile->hasGround()) {
|
|
|
|
|
tile->setMapFlags(flag);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
// Door brush
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
DoorBrush::DoorBrush(DoorType _doortype) : doortype(_doortype)
|
|
|
|
|
{
|
|
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
DoorBrush::~DoorBrush()
|
|
|
|
|
{
|
|
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
std::string DoorBrush::getName() const
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
switch(doortype) {
|
|
|
|
|
case WALL_DOOR_NORMAL: return "Normal door brush";
|
|
|
|
|
case WALL_DOOR_LOCKED: return "Locked door brush";
|
|
|
|
|
case WALL_DOOR_MAGIC: return "Magic door brush";
|
|
|
|
|
case WALL_DOOR_QUEST: return "Quest door brush";
|
|
|
|
|
case WALL_WINDOW: return "Window brush";
|
|
|
|
|
case WALL_HATCH_WINDOW: return "Hatch window brush";
|
|
|
|
|
default: return "Unknown door brush";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
int DoorBrush::getLookID() const
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
switch(doortype) {
|
|
|
|
|
case WALL_DOOR_NORMAL: return EDITOR_SPRITE_DOOR_NORMAL;
|
|
|
|
|
case WALL_DOOR_LOCKED: return EDITOR_SPRITE_DOOR_LOCKED;
|
|
|
|
|
case WALL_DOOR_MAGIC: return EDITOR_SPRITE_DOOR_MAGIC;
|
|
|
|
|
case WALL_DOOR_QUEST: return EDITOR_SPRITE_DOOR_QUEST;
|
|
|
|
|
case WALL_WINDOW: return EDITOR_SPRITE_WINDOW_NORMAL;
|
|
|
|
|
case WALL_HATCH_WINDOW: return EDITOR_SPRITE_WINDOW_HATCH;
|
|
|
|
|
default: return EDITOR_SPRITE_DOOR_NORMAL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
void DoorBrush::switchDoor(Item* item)
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
ASSERT(item);
|
|
|
|
|
ASSERT(item->isBrushDoor());
|
|
|
|
|
|
|
|
|
|
WallBrush* wb = item->getWallBrush();
|
|
|
|
|
if(!wb) return;
|
|
|
|
|
|
|
|
|
|
bool new_open = !item->isOpen();
|
|
|
|
|
BorderType wall_alignment = item->getWallAlignment();
|
|
|
|
|
DoorType doortype = WALL_UNDEFINED;
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
for(std::vector<WallBrush::DoorType>::iterator iter = wb->door_items[wall_alignment].begin(); iter != wb->door_items[wall_alignment].end(); ++iter) {
|
2012-06-29 16:44:26 +02:00
|
|
|
WallBrush::DoorType& dt = *iter;
|
|
|
|
|
if(dt.id == item->getID()) {
|
|
|
|
|
doortype = dt.type;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(doortype == WALL_UNDEFINED) return;
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
for(std::vector<WallBrush::DoorType>::iterator iter = wb->door_items[wall_alignment].begin(); iter != wb->door_items[wall_alignment].end(); ++iter) {
|
2012-06-29 16:44:26 +02:00
|
|
|
WallBrush::DoorType& dt = *iter;
|
|
|
|
|
if(dt.type == doortype) {
|
|
|
|
|
ASSERT(dt.id);
|
2023-01-25 23:45:36 -03:00
|
|
|
const ItemType& type = g_items.getItemType(dt.id);
|
|
|
|
|
ASSERT(type.id != 0);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2023-01-25 23:45:36 -03:00
|
|
|
if(type.isOpen == new_open) {
|
2012-06-29 16:44:26 +02:00
|
|
|
item->setID(dt.id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-01 14:44:11 +01:00
|
|
|
bool DoorBrush::canDraw(BaseMap* map, const Position& position) const
|
|
|
|
|
{
|
|
|
|
|
Tile* tile = map->getTile(position);
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!tile) {
|
2014-03-01 14:44:11 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-29 16:44:26 +02:00
|
|
|
Item* item = tile->getWall();
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!item) {
|
2014-03-01 14:44:11 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-29 16:44:26 +02:00
|
|
|
WallBrush* wb = item->getWallBrush();
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!wb) {
|
2014-03-01 14:44:11 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
BorderType wall_alignment = item->getWallAlignment();
|
|
|
|
|
|
|
|
|
|
uint16_t discarded_id = 0; // The id of a discarded match
|
|
|
|
|
bool close_match = false;
|
|
|
|
|
|
|
|
|
|
bool open = false;
|
|
|
|
|
if(item->isBrushDoor()) {
|
|
|
|
|
open = item->isOpen();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WallBrush* test_brush = wb;
|
|
|
|
|
do {
|
|
|
|
|
for(std::vector<WallBrush::DoorType>::iterator iter = test_brush->door_items[wall_alignment].begin();
|
|
|
|
|
iter != test_brush->door_items[wall_alignment].end();
|
2015-12-06 11:42:37 -03:00
|
|
|
++iter) {
|
2012-06-29 16:44:26 +02:00
|
|
|
WallBrush::DoorType& dt = *iter;
|
|
|
|
|
if(dt.type == doortype) {
|
|
|
|
|
ASSERT(dt.id);
|
2023-01-25 23:45:36 -03:00
|
|
|
const ItemType& type = g_items.getItemType(dt.id);
|
|
|
|
|
ASSERT(type.id != 0);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2023-01-25 23:45:36 -03:00
|
|
|
if(type.isOpen == open) {
|
2012-06-29 16:44:26 +02:00
|
|
|
return true;
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(!close_match) {
|
2012-06-29 16:44:26 +02:00
|
|
|
discarded_id = dt.id;
|
|
|
|
|
close_match = true;
|
|
|
|
|
}
|
|
|
|
|
if(!close_match && discarded_id == 0) {
|
|
|
|
|
discarded_id = dt.id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
test_brush = test_brush->redirect_to;
|
2014-01-22 20:16:17 +01:00
|
|
|
} while(test_brush != wb && test_brush != nullptr);
|
2012-06-29 16:44:26 +02:00
|
|
|
// If we've found no perfect match, use a close-to perfect
|
|
|
|
|
if(discarded_id) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
void DoorBrush::undraw(BaseMap* map, Tile* tile)
|
|
|
|
|
{
|
|
|
|
|
for(ItemVector::iterator it = tile->items.begin(); it != tile->items.end(); ++it) {
|
2012-06-29 16:44:26 +02:00
|
|
|
Item* item = *it;
|
|
|
|
|
if(item->isBrushDoor()) {
|
2014-01-22 20:16:17 +01:00
|
|
|
item->getWallBrush()->draw(map, tile, nullptr);
|
2016-09-29 20:37:43 -03:00
|
|
|
if(g_settings.getInteger(Config::USE_AUTOMAGIC)) {
|
2012-06-29 16:44:26 +02:00
|
|
|
tile->wallize(map);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
void DoorBrush::draw(BaseMap* map, Tile* tile, void* parameter)
|
|
|
|
|
{
|
|
|
|
|
for(ItemVector::iterator item_iter = tile->items.begin(); item_iter != tile->items.end();) {
|
2012-06-29 16:44:26 +02:00
|
|
|
Item* item = *item_iter;
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!item->isWall()) {
|
2012-06-29 16:44:26 +02:00
|
|
|
++item_iter;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
WallBrush* wb = item->getWallBrush();
|
|
|
|
|
if(!wb) {
|
|
|
|
|
++item_iter;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BorderType wall_alignment = item->getWallAlignment();
|
|
|
|
|
|
|
|
|
|
uint16_t discarded_id = 0; // The id of a discarded match
|
|
|
|
|
bool close_match = false;
|
|
|
|
|
bool perfect_match = false;
|
|
|
|
|
|
|
|
|
|
bool open = false;
|
|
|
|
|
if(parameter) {
|
|
|
|
|
open = *reinterpret_cast<bool*>(parameter);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(item->isBrushDoor()) {
|
|
|
|
|
open = item->isOpen();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WallBrush* test_brush = wb;
|
|
|
|
|
do {
|
|
|
|
|
for(std::vector<WallBrush::DoorType>::iterator iter = test_brush->door_items[wall_alignment].begin();
|
|
|
|
|
iter != test_brush->door_items[wall_alignment].end();
|
|
|
|
|
++iter)
|
|
|
|
|
{
|
|
|
|
|
WallBrush::DoorType& dt = *iter;
|
|
|
|
|
if(dt.type == doortype) {
|
|
|
|
|
ASSERT(dt.id);
|
2023-01-25 23:45:36 -03:00
|
|
|
const ItemType& type = g_items.getItemType(dt.id);
|
|
|
|
|
ASSERT(type.id != 0);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2023-01-25 23:45:36 -03:00
|
|
|
if(type.isOpen == open) {
|
2012-06-29 16:44:26 +02:00
|
|
|
item = transformItem(item, dt.id, tile);
|
|
|
|
|
perfect_match = true;
|
|
|
|
|
break;
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(!close_match) {
|
2012-06-29 16:44:26 +02:00
|
|
|
discarded_id = dt.id;
|
|
|
|
|
close_match = true;
|
|
|
|
|
}
|
|
|
|
|
if(!close_match && discarded_id == 0) {
|
|
|
|
|
discarded_id = dt.id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
test_brush = test_brush->redirect_to;
|
|
|
|
|
if(perfect_match) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2014-01-22 20:16:17 +01:00
|
|
|
} while(test_brush != wb && test_brush != nullptr);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
// If we've found no perfect match, use a close-to perfect
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!perfect_match && discarded_id) {
|
2012-06-29 16:44:26 +02:00
|
|
|
item = transformItem(item, discarded_id, tile);
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-29 20:37:43 -03:00
|
|
|
if(g_settings.getInteger(Config::AUTO_ASSIGN_DOORID) && tile->isHouseTile()) {
|
2012-06-29 16:44:26 +02:00
|
|
|
Map* mmap = dynamic_cast<Map*>(map);
|
|
|
|
|
Door* door = dynamic_cast<Door*>(item);
|
|
|
|
|
if(mmap && door) {
|
|
|
|
|
House* house = mmap->houses.getHouse(tile->getHouseID());
|
|
|
|
|
ASSERT(house);
|
|
|
|
|
Map* real_map = dynamic_cast<Map*>(map);
|
|
|
|
|
if(real_map) {
|
|
|
|
|
door->setDoorID(house->getEmptyDoorID());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We need to consider decorations!
|
|
|
|
|
while(true) {
|
|
|
|
|
// Vector has been modified, before we can use the iterator again we need to find the wall item again
|
|
|
|
|
item_iter = tile->items.begin();
|
|
|
|
|
while(true) {
|
|
|
|
|
if(item_iter == tile->items.end()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if(*item_iter == item) {
|
|
|
|
|
++item_iter;
|
|
|
|
|
if(item_iter == tile->items.end()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++item_iter;
|
|
|
|
|
}
|
|
|
|
|
// Now it points to the correct item!
|
|
|
|
|
|
|
|
|
|
item = *item_iter;
|
|
|
|
|
if(item->isWall()) {
|
2016-11-12 10:30:06 -03:00
|
|
|
WallBrush* brush = item->getWallBrush();
|
|
|
|
|
if(brush && brush->isWallDecoration()) {
|
2012-06-29 16:44:26 +02:00
|
|
|
// We got a decoration!
|
2023-01-25 21:44:24 -03:00
|
|
|
for(std::vector<WallBrush::DoorType>::iterator it = brush->door_items[wall_alignment].begin(); it != brush->door_items[wall_alignment].end(); ++it) {
|
2016-11-12 10:30:06 -03:00
|
|
|
WallBrush::DoorType& dt = (*it);
|
2012-06-29 16:44:26 +02:00
|
|
|
if(dt.type == doortype) {
|
|
|
|
|
ASSERT(dt.id);
|
2023-01-25 23:45:36 -03:00
|
|
|
const ItemType& type = g_items.getItemType(dt.id);
|
|
|
|
|
ASSERT(type.id != 0);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
2023-01-25 23:45:36 -03:00
|
|
|
if(type.isOpen == open) {
|
2012-06-29 16:44:26 +02:00
|
|
|
item = transformItem(item, dt.id, tile);
|
|
|
|
|
perfect_match = true;
|
|
|
|
|
break;
|
2015-12-06 11:42:37 -03:00
|
|
|
} else if(!close_match) {
|
2012-06-29 16:44:26 +02:00
|
|
|
discarded_id = dt.id;
|
|
|
|
|
close_match = true;
|
|
|
|
|
}
|
|
|
|
|
if(!close_match && discarded_id == 0) {
|
|
|
|
|
discarded_id = dt.id;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If we've found no perfect match, use a close-to perfect
|
2015-12-06 11:42:37 -03:00
|
|
|
if(!perfect_match && discarded_id) {
|
2012-06-29 16:44:26 +02:00
|
|
|
item = transformItem(item, discarded_id, tile);
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// If we get this far in the loop we should return
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
// Gravel brush
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
OptionalBorderBrush::OptionalBorderBrush()
|
|
|
|
|
{
|
|
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
OptionalBorderBrush::~OptionalBorderBrush()
|
|
|
|
|
{
|
|
|
|
|
////
|
2012-06-29 16:44:26 +02:00
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
std::string OptionalBorderBrush::getName() const
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
return "Optional Border Tool";
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
int OptionalBorderBrush::getLookID() const
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
return EDITOR_SPRITE_OPTIONAL_BORDER_TOOL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-01 14:44:11 +01:00
|
|
|
bool OptionalBorderBrush::canDraw(BaseMap* map, const Position& position) const
|
|
|
|
|
{
|
|
|
|
|
Tile* tile = map->getTile(position);
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
// You can't do gravel on a mountain tile
|
|
|
|
|
if(tile) {
|
|
|
|
|
if(GroundBrush* bb = tile->getGroundBrush()) {
|
|
|
|
|
if(bb->hasOptionalBorder()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-01 14:44:11 +01:00
|
|
|
uint32_t x = position.x;
|
|
|
|
|
uint32_t y = position.y;
|
|
|
|
|
uint32_t z = position.z;
|
2012-06-29 16:44:26 +02:00
|
|
|
|
|
|
|
|
tile = map->getTile(x - 1, y - 1, z);
|
|
|
|
|
if(tile) if(GroundBrush* bb = tile->getGroundBrush()) if(bb->hasOptionalBorder()) return true;
|
|
|
|
|
tile = map->getTile(x , y - 1, z);
|
|
|
|
|
if(tile) if(GroundBrush* bb = tile->getGroundBrush()) if(bb->hasOptionalBorder()) return true;
|
|
|
|
|
tile = map->getTile(x + 1, y - 1, z);
|
|
|
|
|
if(tile) if(GroundBrush* bb = tile->getGroundBrush()) if(bb->hasOptionalBorder()) return true;
|
|
|
|
|
tile = map->getTile(x - 1, y , z);
|
|
|
|
|
if(tile) if(GroundBrush* bb = tile->getGroundBrush()) if(bb->hasOptionalBorder()) return true;
|
|
|
|
|
tile = map->getTile(x + 1, y , z);
|
|
|
|
|
if(tile) if(GroundBrush* bb = tile->getGroundBrush()) if(bb->hasOptionalBorder()) return true;
|
|
|
|
|
tile = map->getTile(x - 1, y + 1, z);
|
|
|
|
|
if(tile) if(GroundBrush* bb = tile->getGroundBrush()) if(bb->hasOptionalBorder()) return true;
|
|
|
|
|
tile = map->getTile(x , y + 1, z);
|
|
|
|
|
if(tile) if(GroundBrush* bb = tile->getGroundBrush()) if(bb->hasOptionalBorder()) return true;
|
|
|
|
|
tile = map->getTile(x + 1, y + 1, z);
|
|
|
|
|
if(tile) if(GroundBrush* bb = tile->getGroundBrush()) if(bb->hasOptionalBorder()) return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
void OptionalBorderBrush::undraw(BaseMap* map, Tile* tile)
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
tile->setOptionalBorder(false); // The bordering algorithm will handle this automagicaly
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-06 11:42:37 -03:00
|
|
|
void OptionalBorderBrush::draw(BaseMap* map, Tile* tile, void* parameter)
|
|
|
|
|
{
|
2012-06-29 16:44:26 +02:00
|
|
|
tile->setOptionalBorder(true); // The bordering algorithm will handle this automagicaly
|
|
|
|
|
}
|
|
|
|
|
|