mirror of
https://github.com/opentibiabr/remeres-map-editor
synced 2026-08-15 18:26:04 -04:00
Created the complete organization of npcs, that way, it is possible to create own files for npcs, no longer depending on being together with the monsters this pull request was made to be worked together with the canary project: https://github.com/opentibiabr/canary The spawns npcs is "yellow" and spawns monsters is "red" (the old) With this change, the map will automatically create an "npc.xml" the first time it is saved. It is possible to edit only the xml, it is not necessary to add or modify the npc by opening the editor map Thus, there is a script for npcs, similar to how it works with old spawns
399 lines
8.4 KiB
C++
399 lines
8.4 KiB
C++
//////////////////////////////////////////////////////////////////////
|
|
// This file is part of Remere's Map Editor
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Remere's Map Editor 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.
|
|
//
|
|
// Remere's Map Editor 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/>.
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "main.h"
|
|
|
|
#include "selection.h"
|
|
#include "tile.h"
|
|
#include "monster.h"
|
|
#include "npc.h"
|
|
#include "item.h"
|
|
#include "editor.h"
|
|
#include "gui.h"
|
|
|
|
Selection::Selection(Editor& editor) :
|
|
busy(false),
|
|
editor(editor),
|
|
session(nullptr),
|
|
subsession(nullptr)
|
|
{
|
|
////
|
|
}
|
|
|
|
Selection::~Selection()
|
|
{
|
|
delete subsession;
|
|
delete session;
|
|
}
|
|
|
|
Position Selection::minPosition() const
|
|
{
|
|
Position minPos(0x10000, 0x10000, 0x10);
|
|
for(TileSet::const_iterator tile = tiles.begin(); tile != tiles.end(); ++tile) {
|
|
Position pos((*tile)->getPosition());
|
|
if(minPos.x > pos.x)
|
|
minPos.x = pos.x;
|
|
if(minPos.y > pos.y)
|
|
minPos.y = pos.y;
|
|
if(minPos.z > pos.z)
|
|
minPos.z = pos.z;
|
|
}
|
|
return minPos;
|
|
}
|
|
|
|
Position Selection::maxPosition() const
|
|
{
|
|
Position maxPos(0, 0, 0);
|
|
for(TileSet::const_iterator tile = tiles.begin(); tile != tiles.end(); ++tile) {
|
|
Position pos((*tile)->getPosition());
|
|
if(maxPos.x < pos.x)
|
|
maxPos.x = pos.x;
|
|
if(maxPos.y < pos.y)
|
|
maxPos.y = pos.y;
|
|
if(maxPos.z < pos.z)
|
|
maxPos.z = pos.z;
|
|
}
|
|
return maxPos;
|
|
}
|
|
|
|
void Selection::add(Tile* tile, Item* item)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(item);
|
|
|
|
if(item->isSelected()) return;
|
|
|
|
// Make a copy of the tile with the item selected
|
|
item->select();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
item->deselect();
|
|
|
|
if(g_settings.getInteger(Config::BORDER_IS_GROUND))
|
|
if(item->isBorder())
|
|
new_tile->selectGround();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::add(Tile* tile, SpawnMonster* spawnMonster)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(spawnMonster);
|
|
|
|
if(spawnMonster->isSelected()) return;
|
|
|
|
// Make a copy of the tile with the item selected
|
|
spawnMonster->select();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
spawnMonster->deselect();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::add(Tile* tile, SpawnNpc* spawnNpc)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(spawnNpc);
|
|
|
|
if(spawnNpc->isSelected()) return;
|
|
|
|
// Make a copy of the tile with the item selected
|
|
spawnNpc->select();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
spawnNpc->deselect();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::add(Tile* tile, Monster* monster)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(monster);
|
|
|
|
if(monster->isSelected()) return;
|
|
|
|
// Make a copy of the tile with the item selected
|
|
monster->select();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
monster->deselect();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::add(Tile* tile, Npc* npc)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(npc);
|
|
|
|
if(npc->isSelected()) return;
|
|
|
|
// Make a copy of the tile with the item selected
|
|
npc->select();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
npc->deselect();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::add(Tile* tile)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
new_tile->select();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile, Item* item)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(item);
|
|
|
|
bool tmp = item->isSelected();
|
|
item->deselect();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
if(tmp) item->select();
|
|
if(item->isBorder() && g_settings.getInteger(Config::BORDER_IS_GROUND)) new_tile->deselectGround();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile, SpawnMonster* spawnMonster)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(spawnMonster);
|
|
|
|
bool tmp = spawnMonster->isSelected();
|
|
spawnMonster->deselect();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
if(tmp) spawnMonster->select();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile, SpawnNpc* spawnNpc)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(spawnNpc);
|
|
|
|
bool tmp = spawnNpc->isSelected();
|
|
spawnNpc->deselect();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
if(tmp) spawnNpc->select();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile, Monster* monster)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(monster);
|
|
|
|
bool tmp = monster->isSelected();
|
|
monster->deselect();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
if(tmp) monster->select();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile, Npc* npc)
|
|
{
|
|
ASSERT(subsession);
|
|
ASSERT(tile);
|
|
ASSERT(npc);
|
|
|
|
bool tmp = npc->isSelected();
|
|
npc->deselect();
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
if(tmp) npc->select();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::remove(Tile* tile)
|
|
{
|
|
ASSERT(subsession);
|
|
|
|
Tile* new_tile = tile->deepCopy(editor.map);
|
|
new_tile->deselect();
|
|
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
|
|
void Selection::addInternal(Tile* tile)
|
|
{
|
|
ASSERT(tile);
|
|
|
|
tiles.insert(tile);
|
|
}
|
|
|
|
void Selection::removeInternal(Tile* tile)
|
|
{
|
|
ASSERT(tile);
|
|
tiles.erase(tile);
|
|
}
|
|
|
|
void Selection::clear()
|
|
{
|
|
if(session) {
|
|
for(TileSet::iterator it = tiles.begin(); it != tiles.end(); it++) {
|
|
Tile* new_tile = (*it)->deepCopy(editor.map);
|
|
new_tile->deselect();
|
|
subsession->addChange(newd Change(new_tile));
|
|
}
|
|
} else {
|
|
for(TileSet::iterator it = tiles.begin(); it != tiles.end(); it++) {
|
|
(*it)->deselect();
|
|
}
|
|
tiles.clear();
|
|
}
|
|
}
|
|
|
|
void Selection::start(SessionFlags flags)
|
|
{
|
|
if(!(flags & INTERNAL)) {
|
|
if(flags & SUBTHREAD) {
|
|
;
|
|
} else {
|
|
session = editor.actionQueue->createBatch(ACTION_SELECT);
|
|
}
|
|
subsession = editor.actionQueue->createAction(ACTION_SELECT);
|
|
}
|
|
busy = true;
|
|
}
|
|
|
|
void Selection::commit()
|
|
{
|
|
if(session) {
|
|
ASSERT(subsession);
|
|
// We need to step out of the session before we do the action, else peril awaits us!
|
|
BatchAction* tmp = session;
|
|
session = nullptr;
|
|
|
|
// Do the action
|
|
tmp->addAndCommitAction(subsession);
|
|
|
|
// Create a newd action for subsequent selects
|
|
subsession = editor.actionQueue->createAction(ACTION_SELECT);
|
|
session = tmp;
|
|
}
|
|
}
|
|
|
|
void Selection::finish(SessionFlags flags)
|
|
{
|
|
if(!(flags & INTERNAL)) {
|
|
if(flags & SUBTHREAD) {
|
|
ASSERT(subsession);
|
|
subsession = nullptr;
|
|
} else {
|
|
ASSERT(session);
|
|
ASSERT(subsession);
|
|
// We need to exit the session before we do the action, else peril awaits us!
|
|
BatchAction* tmp = session;
|
|
session = nullptr;
|
|
|
|
tmp->addAndCommitAction(subsession);
|
|
editor.addBatch(tmp, 2);
|
|
|
|
session = nullptr;
|
|
subsession = nullptr;
|
|
}
|
|
}
|
|
busy = false;
|
|
}
|
|
|
|
void Selection::updateSelectionCount()
|
|
{
|
|
if(size() > 0) {
|
|
wxString ss;
|
|
if(size() == 1) {
|
|
ss << "One tile selected.";
|
|
} else {
|
|
ss << size() << " tiles selected.";
|
|
}
|
|
g_gui.SetStatusText(ss);
|
|
}
|
|
}
|
|
|
|
void Selection::join(SelectionThread* thread)
|
|
{
|
|
thread->Wait();
|
|
|
|
ASSERT(session);
|
|
session->addAction(thread->result);
|
|
thread->selection.subsession = nullptr;
|
|
|
|
delete thread;
|
|
}
|
|
|
|
SelectionThread::SelectionThread(Editor& editor, Position start, Position end) :
|
|
wxThread(wxTHREAD_JOINABLE),
|
|
editor(editor),
|
|
start(start),
|
|
end(end),
|
|
selection(editor),
|
|
result(nullptr)
|
|
{
|
|
////
|
|
}
|
|
|
|
SelectionThread::~SelectionThread()
|
|
{
|
|
////
|
|
}
|
|
|
|
void SelectionThread::Execute()
|
|
{
|
|
Create();
|
|
Run();
|
|
}
|
|
|
|
wxThread::ExitCode SelectionThread::Entry()
|
|
{
|
|
selection.start(Selection::SUBTHREAD);
|
|
for(int z = start.z; z >= end.z; --z) {
|
|
for(int x = start.x; x <= end.x; ++x) {
|
|
for(int y = start.y; y <= end.y; ++y) {
|
|
Tile* tile = editor.map.getTile(x, y, z);
|
|
if(!tile)
|
|
continue;
|
|
|
|
selection.add(tile);
|
|
}
|
|
}
|
|
if(z <= GROUND_LAYER && g_settings.getInteger(Config::COMPENSATED_SELECT)) {
|
|
++start.x; ++start.y;
|
|
++end.x; ++end.y;
|
|
}
|
|
}
|
|
result = selection.subsession;
|
|
selection.finish(Selection::SUBTHREAD);
|
|
|
|
return nullptr;
|
|
}
|