mirror of
https://github.com/opentibiabr/remeres-map-editor
synced 2026-08-15 18:26:04 -04:00
This adds the possibility to add stacked monsters and set weight into the stacked monsters to randomize their spawn.
755 lines
29 KiB
C++
755 lines
29 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 "tile.h"
|
|
#include "item.h"
|
|
#include "complexitem.h"
|
|
#include "town.h"
|
|
#include "house.h"
|
|
#include "map.h"
|
|
#include "editor.h"
|
|
#include "monster.h"
|
|
#include "npc.h"
|
|
|
|
#include "gui.h"
|
|
#include "application.h"
|
|
#include "old_properties_window.h"
|
|
#include "container_properties_window.h"
|
|
|
|
// ============================================================================
|
|
// Old Properties Window
|
|
|
|
BEGIN_EVENT_TABLE(OldPropertiesWindow, wxDialog)
|
|
EVT_SET_FOCUS(OldPropertiesWindow::OnFocusChange)
|
|
EVT_BUTTON(wxID_OK, OldPropertiesWindow::OnClickOK)
|
|
EVT_BUTTON(wxID_CANCEL, OldPropertiesWindow::OnClickCancel)
|
|
END_EVENT_TABLE()
|
|
|
|
OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, const Tile* tile_parent, Item* item, wxPoint pos) :
|
|
ObjectPropertiesWindowBase(win_parent, "Item Properties", map, tile_parent, item, pos),
|
|
count_field(nullptr),
|
|
direction_field(nullptr),
|
|
action_id_field(nullptr),
|
|
unique_id_field(nullptr),
|
|
door_id_field(nullptr),
|
|
depot_id_field(nullptr),
|
|
splash_type_field(nullptr),
|
|
text_field(nullptr),
|
|
description_field(nullptr),
|
|
destination_field(nullptr) {
|
|
ASSERT(edit_item);
|
|
|
|
wxSizer* topsizer = newd wxBoxSizer(wxVERTICAL);
|
|
if (Container* container = dynamic_cast<Container*>(edit_item)) {
|
|
// Container
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Container Properties");
|
|
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
subsizer->AddGrowableCol(1);
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "ID " + i2ws(item->getID())));
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "\"" + wxstr(item->getName()) + "\""));
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Action ID"));
|
|
action_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getActionID()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getActionID());
|
|
subsizer->Add(action_id_field, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Unique ID"));
|
|
unique_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getUniqueID()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getUniqueID());
|
|
subsizer->Add(unique_id_field, wxSizerFlags(1).Expand());
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(0).Expand());
|
|
|
|
// Now we add the subitems!
|
|
wxSizer* contents_sizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Contents");
|
|
|
|
bool use_large_sprites = g_settings.getBoolean(Config::USE_LARGE_CONTAINER_ICONS);
|
|
wxSizer* horizontal_sizer = nullptr;
|
|
const int additional_height_increment = (use_large_sprites ? 40 : 24);
|
|
int additional_height = 0;
|
|
|
|
int32_t maxColumns;
|
|
if (use_large_sprites) {
|
|
maxColumns = 6;
|
|
} else {
|
|
maxColumns = 12;
|
|
}
|
|
|
|
for (uint32_t index = 0; index < container->getVolume(); ++index) {
|
|
if (!horizontal_sizer) {
|
|
horizontal_sizer = newd wxBoxSizer(wxHORIZONTAL);
|
|
}
|
|
|
|
Item* item = container->getItem(index);
|
|
ContainerItemButton* containerItemButton = newd ContainerItemButton(this, use_large_sprites, index, map, item);
|
|
|
|
container_items.push_back(containerItemButton);
|
|
horizontal_sizer->Add(containerItemButton);
|
|
|
|
if (((index + 1) % maxColumns) == 0) {
|
|
contents_sizer->Add(horizontal_sizer);
|
|
horizontal_sizer = nullptr;
|
|
additional_height += additional_height_increment;
|
|
}
|
|
}
|
|
|
|
if (horizontal_sizer != nullptr) {
|
|
contents_sizer->Add(horizontal_sizer);
|
|
additional_height += additional_height_increment;
|
|
}
|
|
|
|
boxsizer->Add(contents_sizer, wxSizerFlags(2).Expand());
|
|
|
|
topsizer->Add(boxsizer, wxSizerFlags(0).Expand().Border(wxALL, 20));
|
|
|
|
// SetSize(260, 150 + additional_height);
|
|
} else if (edit_item->canHoldText() || edit_item->canHoldDescription()) {
|
|
// Book
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Writeable Properties");
|
|
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
subsizer->AddGrowableCol(1);
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "ID " + i2ws(item->getID())));
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "\"" + wxstr(item->getName()) + "\""));
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Action ID"));
|
|
action_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getActionID()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getActionID());
|
|
action_id_field->SetSelection(-1, -1);
|
|
subsizer->Add(action_id_field, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Unique ID"));
|
|
unique_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getUniqueID()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getUniqueID());
|
|
subsizer->Add(unique_id_field, wxSizerFlags(1).Expand());
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(1).Expand());
|
|
|
|
wxSizer* textsizer = newd wxBoxSizer(wxVERTICAL);
|
|
textsizer->Add(newd wxStaticText(this, wxID_ANY, "Text"), wxSizerFlags(1).Center());
|
|
text_field = newd wxTextCtrl(this, wxID_ANY, wxstr(item->getText()), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
|
|
textsizer->Add(text_field, wxSizerFlags(7).Expand());
|
|
|
|
boxsizer->Add(textsizer, wxSizerFlags(2).Expand());
|
|
|
|
topsizer->Add(boxsizer, wxSizerFlags(0).Expand().Border(wxALL, 20));
|
|
|
|
// SetSize(220, 310);
|
|
} else if (edit_item->isSplash() || edit_item->isFluidContainer()) {
|
|
|
|
const auto subTypeName = edit_item->isSplash() ? "Splash" : "Fluid Container";
|
|
|
|
// Splash
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, wxString::Format("%s Properties", subTypeName));
|
|
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
subsizer->AddGrowableCol(1);
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "ID " + i2ws(item->getID())));
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "\"" + wxstr(item->getName()) + "\""));
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Type"));
|
|
|
|
const auto liquidNoneName = wxstr(Item::LiquidID2Name(LIQUID_NONE));
|
|
const auto liquidNoneUInt = newd uint8_t(LIQUID_NONE);
|
|
|
|
// Splash types
|
|
splash_type_field = newd wxChoice(this, wxID_ANY);
|
|
if (edit_item->isFluidContainer()) {
|
|
splash_type_field->Append(liquidNoneName, liquidNoneUInt);
|
|
}
|
|
|
|
for (SplashType splashType = LIQUID_FIRST; splashType <= LIQUID_LAST; ++splashType) {
|
|
const auto splashTypeName = wxstr(Item::LiquidID2Name(splashType));
|
|
if (splashTypeName != "Unknown") {
|
|
splash_type_field->Append(splashTypeName, newd uint8_t(splashType));
|
|
}
|
|
}
|
|
|
|
if (item->getSubtype()) {
|
|
const std::string &what = Item::LiquidID2Name(item->getSubtype());
|
|
if (what == "Unknown") {
|
|
splash_type_field->Append(what, liquidNoneUInt);
|
|
}
|
|
splash_type_field->SetStringSelection(what);
|
|
} else {
|
|
splash_type_field->SetSelection(0);
|
|
}
|
|
|
|
subsizer->Add(splash_type_field, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Action ID"));
|
|
action_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getActionID()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getActionID());
|
|
subsizer->Add(action_id_field, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Unique ID"));
|
|
unique_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getUniqueID()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getUniqueID());
|
|
subsizer->Add(unique_id_field, wxSizerFlags(1).Expand());
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(1).Expand());
|
|
|
|
topsizer->Add(boxsizer, wxSizerFlags(0).Expand().Border(wxALL, 20));
|
|
|
|
// SetSize(220, 190);
|
|
} else if (Depot* depot = dynamic_cast<Depot*>(edit_item)) {
|
|
// Depot
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Depot Properties");
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
|
|
subsizer->AddGrowableCol(1);
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "ID " + i2ws(item->getID())));
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "\"" + wxstr(item->getName()) + "\""));
|
|
|
|
const Towns &towns = map->towns;
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Depot ID"));
|
|
depot_id_field = newd wxChoice(this, wxID_ANY);
|
|
int to_select_index = 0;
|
|
if (towns.count() > 0) {
|
|
bool found = false;
|
|
for (TownMap::const_iterator town_iter = towns.begin();
|
|
town_iter != towns.end();
|
|
++town_iter) {
|
|
if (town_iter->second->getID() == depot->getDepotID()) {
|
|
found = true;
|
|
}
|
|
depot_id_field->Append(wxstr(town_iter->second->getName()), newd int(town_iter->second->getID()));
|
|
if (!found) {
|
|
++to_select_index;
|
|
}
|
|
}
|
|
if (!found) {
|
|
if (depot->getDepotID() != 0) {
|
|
depot_id_field->Append("Undefined Town (id:" + i2ws(depot->getDepotID()) + ")", newd int(depot->getDepotID()));
|
|
}
|
|
}
|
|
}
|
|
depot_id_field->Append("No Town", newd int(0));
|
|
if (depot->getDepotID() == 0) {
|
|
to_select_index = depot_id_field->GetCount() - 1;
|
|
}
|
|
depot_id_field->SetSelection(to_select_index);
|
|
|
|
subsizer->Add(depot_id_field, wxSizerFlags(1).Expand());
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(5).Expand());
|
|
topsizer->Add(boxsizer, wxSizerFlags(0).Expand().Border(wxALL, 20));
|
|
// SetSize(220, 140);
|
|
} else {
|
|
// Normal item
|
|
Door* door = dynamic_cast<Door*>(edit_item);
|
|
Teleport* teleport = dynamic_cast<Teleport*>(edit_item);
|
|
|
|
wxString description;
|
|
if (door) {
|
|
ASSERT(tile_parent);
|
|
description = "Door Properties";
|
|
} else if (teleport) {
|
|
description = "Teleport Properties";
|
|
} else {
|
|
description = "Item Properties";
|
|
}
|
|
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, description);
|
|
|
|
int num_items = 4;
|
|
// if(item->canHoldDescription()) num_items += 1;
|
|
if (door) {
|
|
num_items += 1;
|
|
}
|
|
if (teleport) {
|
|
num_items += 1;
|
|
}
|
|
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
subsizer->AddGrowableCol(1);
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "ID " + i2ws(item->getID())));
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "\"" + wxstr(item->getName()) + "\""));
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, (item->isCharged() ? "Charges" : "Count")));
|
|
int max_count = 100;
|
|
if (item->isClientCharged()) {
|
|
max_count = 250;
|
|
}
|
|
if (item->isExtraCharged()) {
|
|
max_count = 65500;
|
|
}
|
|
count_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getCount()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, max_count, edit_item->getCount());
|
|
if (!item->isStackable() && !item->isCharged()) {
|
|
count_field->Enable(false);
|
|
}
|
|
subsizer->Add(count_field, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Action ID"));
|
|
action_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getActionID()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getActionID());
|
|
subsizer->Add(action_id_field, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Unique ID"));
|
|
unique_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_item->getUniqueID()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getUniqueID());
|
|
subsizer->Add(unique_id_field, wxSizerFlags(1).Expand());
|
|
|
|
/*
|
|
if(item->canHoldDescription()) {
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Description"));
|
|
description_field = newd wxTextCtrl(this, wxID_ANY, edit_item->getText(), wxDefaultPosition, wxSize(-1, 20));
|
|
subsizer->Add(description_field, wxSizerFlags(1).Expand());
|
|
}
|
|
*/
|
|
|
|
if (door) {
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Door ID"));
|
|
door_id_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(door->getDoorID()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, 0xFF, door->getDoorID());
|
|
if (!edit_tile || !edit_tile->isHouseTile()) {
|
|
door_id_field->Disable();
|
|
}
|
|
subsizer->Add(door_id_field, wxSizerFlags(1).Expand());
|
|
}
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(1).Expand());
|
|
topsizer->Add(boxsizer, wxSizerFlags(0).Expand().Border(wxLEFT | wxRIGHT, 20));
|
|
|
|
if (teleport) {
|
|
destination_field = new PositionCtrl(this, "Destination", teleport->getX(), teleport->getY(), teleport->getZ(), map->getWidth(), map->getHeight());
|
|
topsizer->Add(destination_field, wxSizerFlags(0).Expand().Border(wxLEFT | wxRIGHT, 20));
|
|
}
|
|
}
|
|
|
|
// Others attributes
|
|
const ItemType &type = g_items.getItemType(edit_item->getID());
|
|
wxStaticBoxSizer* others_sizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Others");
|
|
wxFlexGridSizer* others_subsizer = newd wxFlexGridSizer(2, 5, 10);
|
|
others_subsizer->AddGrowableCol(1);
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, "Stackable"));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, b2yn(type.stackable)));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, "Movable"));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, b2yn(type.moveable)));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, "Pickupable"));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, b2yn(type.pickupable)));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, "Hangable"));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, b2yn(type.isHangable)));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, "Block Missiles"));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, b2yn(type.blockMissiles)));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, "Block Pathfinder"));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, b2yn(type.blockPathfinder)));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, "Has Elevation"));
|
|
others_subsizer->Add(newd wxStaticText(this, wxID_ANY, b2yn(type.hasElevation)));
|
|
others_sizer->Add(others_subsizer, wxSizerFlags(1).Expand());
|
|
topsizer->Add(others_sizer, wxSizerFlags(0).Expand().Border(wxLEFT | wxRIGHT | wxBOTTOM, 20));
|
|
|
|
wxSizer* subsizer = newd wxBoxSizer(wxHORIZONTAL);
|
|
subsizer->Add(newd wxButton(this, wxID_OK, "OK"), wxSizerFlags(1).Center());
|
|
subsizer->Add(newd wxButton(this, wxID_CANCEL, "Cancel"), wxSizerFlags(1).Center());
|
|
topsizer->Add(subsizer, wxSizerFlags(0).Center().Border(wxLEFT | wxRIGHT | wxBOTTOM, 20));
|
|
|
|
SetSizerAndFit(topsizer);
|
|
Centre(wxBOTH);
|
|
}
|
|
|
|
OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, const Tile* tile_parent, Monster* monster, wxPoint pos) :
|
|
ObjectPropertiesWindowBase(win_parent, "Monster Properties", map, tile_parent, monster, pos),
|
|
count_field(nullptr),
|
|
direction_field(nullptr),
|
|
action_id_field(nullptr),
|
|
unique_id_field(nullptr),
|
|
door_id_field(nullptr),
|
|
depot_id_field(nullptr),
|
|
splash_type_field(nullptr),
|
|
text_field(nullptr),
|
|
description_field(nullptr),
|
|
destination_field(nullptr) {
|
|
ASSERT(edit_monster);
|
|
|
|
wxSizer* topsizer = newd wxBoxSizer(wxVERTICAL);
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Monster Properties");
|
|
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
subsizer->AddGrowableCol(1);
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Monster name "));
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "\"" + wxstr(edit_monster->getName()) + "\""), wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Spawn interval"));
|
|
count_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_monster->getSpawnMonsterTime()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 10, 3600, edit_monster->getSpawnMonsterTime());
|
|
// count_field->SetSelection(-1, -1);
|
|
subsizer->Add(count_field, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Weight"));
|
|
monsterWeightField = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_monster->getWeight()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100);
|
|
subsizer->Add(monsterWeightField, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Direction"));
|
|
direction_field = newd wxChoice(this, wxID_ANY);
|
|
|
|
for (Direction dir = DIRECTION_FIRST; dir <= DIRECTION_LAST; ++dir) {
|
|
direction_field->Append(wxstr(Monster::DirID2Name(dir)), newd int32_t(dir));
|
|
}
|
|
direction_field->SetSelection(edit_monster->getDirection());
|
|
subsizer->Add(direction_field, wxSizerFlags(1).Expand());
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(1).Expand());
|
|
|
|
topsizer->Add(boxsizer, wxSizerFlags(3).Expand().Border(wxALL, 20));
|
|
// SetSize(220, 0);
|
|
|
|
wxSizer* std_sizer = newd wxBoxSizer(wxHORIZONTAL);
|
|
std_sizer->Add(newd wxButton(this, wxID_OK, "OK"), wxSizerFlags(1).Center());
|
|
std_sizer->Add(newd wxButton(this, wxID_CANCEL, "Cancel"), wxSizerFlags(1).Center());
|
|
topsizer->Add(std_sizer, wxSizerFlags(0).Center().Border(wxLEFT | wxRIGHT | wxBOTTOM, 20));
|
|
|
|
SetSizerAndFit(topsizer);
|
|
Centre(wxBOTH);
|
|
}
|
|
|
|
OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, const Tile* tile_parent, SpawnMonster* spawnMonster, wxPoint pos) :
|
|
ObjectPropertiesWindowBase(win_parent, "Spawn Monster Properties", map, tile_parent, spawnMonster, pos),
|
|
count_field(nullptr),
|
|
direction_field(nullptr),
|
|
action_id_field(nullptr),
|
|
unique_id_field(nullptr),
|
|
door_id_field(nullptr),
|
|
depot_id_field(nullptr),
|
|
splash_type_field(nullptr),
|
|
text_field(nullptr),
|
|
description_field(nullptr),
|
|
destination_field(nullptr) {
|
|
ASSERT(edit_spawn_monster);
|
|
|
|
wxSizer* topsizer = newd wxBoxSizer(wxVERTICAL);
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Spawn Monster Properties");
|
|
|
|
// if(item->canHoldDescription()) num_items += 1;
|
|
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
subsizer->AddGrowableCol(1);
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Spawn size"));
|
|
count_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_spawn_monster->getSize()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, g_settings.getInteger(Config::MAX_SPAWN_MONSTER_RADIUS), edit_spawn_monster->getSize());
|
|
// count_field->SetSelection(-1, -1);
|
|
subsizer->Add(count_field, wxSizerFlags(1).Expand());
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(1).Expand());
|
|
|
|
topsizer->Add(boxsizer, wxSizerFlags(3).Expand().Border(wxALL, 20));
|
|
|
|
wxSizer* std_sizer = newd wxBoxSizer(wxHORIZONTAL);
|
|
std_sizer->Add(newd wxButton(this, wxID_OK, "OK"), wxSizerFlags(1).Center());
|
|
std_sizer->Add(newd wxButton(this, wxID_CANCEL, "Cancel"), wxSizerFlags(1).Center());
|
|
topsizer->Add(std_sizer, wxSizerFlags(0).Center().Border(wxLEFT | wxRIGHT | wxBOTTOM, 20));
|
|
|
|
SetSizerAndFit(topsizer);
|
|
Centre(wxBOTH);
|
|
}
|
|
|
|
OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, const Tile* tile_parent, Npc* npc, wxPoint pos) :
|
|
ObjectPropertiesWindowBase(win_parent, "Npc Properties", map, tile_parent, npc, pos),
|
|
count_field(nullptr),
|
|
direction_field(nullptr),
|
|
action_id_field(nullptr),
|
|
unique_id_field(nullptr),
|
|
door_id_field(nullptr),
|
|
depot_id_field(nullptr),
|
|
splash_type_field(nullptr),
|
|
text_field(nullptr),
|
|
description_field(nullptr),
|
|
destination_field(nullptr) {
|
|
ASSERT(edit_npc);
|
|
|
|
wxSizer* topsizer = newd wxBoxSizer(wxVERTICAL);
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Npc Properties");
|
|
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
subsizer->AddGrowableCol(1);
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Npc name "));
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "\"" + wxstr(edit_npc->getName()) + "\""), wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Spawn interval"));
|
|
count_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_npc->getSpawnNpcTime()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 10, 3600, edit_npc->getSpawnNpcTime());
|
|
// count_field->SetSelection(-1, -1);
|
|
subsizer->Add(count_field, wxSizerFlags(1).Expand());
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Direction"));
|
|
direction_field = newd wxChoice(this, wxID_ANY);
|
|
|
|
for (Direction dir = DIRECTION_FIRST; dir <= DIRECTION_LAST; ++dir) {
|
|
direction_field->Append(wxstr(Npc::DirID2Name(dir)), newd int32_t(dir));
|
|
}
|
|
direction_field->SetSelection(edit_npc->getDirection());
|
|
subsizer->Add(direction_field, wxSizerFlags(1).Expand());
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(1).Expand());
|
|
|
|
topsizer->Add(boxsizer, wxSizerFlags(3).Expand().Border(wxALL, 20));
|
|
// SetSize(220, 0);
|
|
|
|
wxSizer* std_sizer = newd wxBoxSizer(wxHORIZONTAL);
|
|
std_sizer->Add(newd wxButton(this, wxID_OK, "OK"), wxSizerFlags(1).Center());
|
|
std_sizer->Add(newd wxButton(this, wxID_CANCEL, "Cancel"), wxSizerFlags(1).Center());
|
|
topsizer->Add(std_sizer, wxSizerFlags(0).Center().Border(wxLEFT | wxRIGHT | wxBOTTOM, 20));
|
|
|
|
SetSizerAndFit(topsizer);
|
|
Centre(wxBOTH);
|
|
}
|
|
|
|
OldPropertiesWindow::OldPropertiesWindow(wxWindow* win_parent, const Map* map, const Tile* tile_parent, SpawnNpc* spawnNpc, wxPoint pos) :
|
|
ObjectPropertiesWindowBase(win_parent, "Spawn Npc Properties", map, tile_parent, spawnNpc, pos),
|
|
count_field(nullptr),
|
|
direction_field(nullptr),
|
|
action_id_field(nullptr),
|
|
unique_id_field(nullptr),
|
|
door_id_field(nullptr),
|
|
depot_id_field(nullptr),
|
|
splash_type_field(nullptr),
|
|
text_field(nullptr),
|
|
description_field(nullptr),
|
|
destination_field(nullptr) {
|
|
ASSERT(edit_spawn_npc);
|
|
|
|
wxSizer* topsizer = newd wxBoxSizer(wxVERTICAL);
|
|
wxSizer* boxsizer = newd wxStaticBoxSizer(wxVERTICAL, this, "Npc Spawn Properties");
|
|
|
|
// if(item->canHoldDescription()) num_items += 1;
|
|
|
|
wxFlexGridSizer* subsizer = newd wxFlexGridSizer(2, 10, 10);
|
|
subsizer->AddGrowableCol(1);
|
|
|
|
subsizer->Add(newd wxStaticText(this, wxID_ANY, "Spawn size"));
|
|
count_field = newd wxSpinCtrl(this, wxID_ANY, i2ws(edit_spawn_npc->getSize()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 1, g_settings.getInteger(Config::MAX_SPAWN_NPC_RADIUS), edit_spawn_npc->getSize());
|
|
// count_field->SetSelection(-1, -1);
|
|
subsizer->Add(count_field, wxSizerFlags(1).Expand());
|
|
|
|
boxsizer->Add(subsizer, wxSizerFlags(1).Expand());
|
|
|
|
topsizer->Add(boxsizer, wxSizerFlags(3).Expand().Border(wxALL, 20));
|
|
|
|
wxSizer* std_sizer = newd wxBoxSizer(wxHORIZONTAL);
|
|
std_sizer->Add(newd wxButton(this, wxID_OK, "OK"), wxSizerFlags(1).Center());
|
|
std_sizer->Add(newd wxButton(this, wxID_CANCEL, "Cancel"), wxSizerFlags(1).Center());
|
|
topsizer->Add(std_sizer, wxSizerFlags(0).Center().Border(wxLEFT | wxRIGHT | wxBOTTOM, 20));
|
|
|
|
SetSizerAndFit(topsizer);
|
|
Centre(wxBOTH);
|
|
}
|
|
|
|
OldPropertiesWindow::~OldPropertiesWindow() {
|
|
// Warning: edit_item may no longer be valid, DONT USE IT!
|
|
if (splash_type_field) {
|
|
for (uint8_t i = 0; i < splash_type_field->GetCount(); ++i) {
|
|
delete reinterpret_cast<int*>(splash_type_field->GetClientData(i));
|
|
}
|
|
}
|
|
if (direction_field) {
|
|
for (uint32_t i = 0; i < direction_field->GetCount(); ++i) {
|
|
delete reinterpret_cast<int*>(direction_field->GetClientData(i));
|
|
}
|
|
}
|
|
if (depot_id_field) {
|
|
for (uint32_t i = 0; i < depot_id_field->GetCount(); ++i) {
|
|
delete reinterpret_cast<int*>(depot_id_field->GetClientData(i));
|
|
}
|
|
}
|
|
}
|
|
|
|
void OldPropertiesWindow::OnFocusChange(wxFocusEvent &event) {
|
|
wxWindow* win = event.GetWindow();
|
|
if (wxSpinCtrl* spin = dynamic_cast<wxSpinCtrl*>(win)) {
|
|
spin->SetSelection(-1, -1);
|
|
} else if (wxTextCtrl* text = dynamic_cast<wxTextCtrl*>(win)) {
|
|
text->SetSelection(-1, -1);
|
|
}
|
|
}
|
|
|
|
void OldPropertiesWindow::OnClickOK(wxCommandEvent &WXUNUSED(event)) {
|
|
if (edit_item) {
|
|
int new_uid = (unique_id_field ? unique_id_field->GetValue() : 0);
|
|
int new_aid = (action_id_field ? action_id_field->GetValue() : 0);
|
|
bool uid_changed = false;
|
|
bool aid_changed = false;
|
|
|
|
if (!edit_item->getDepot()) {
|
|
uid_changed = new_uid != edit_item->getUniqueID();
|
|
aid_changed = new_aid != edit_item->getActionID();
|
|
|
|
if (uid_changed) {
|
|
if (new_uid != 0 && (new_uid < rme::MinUniqueId || new_uid > rme::MaxUniqueId)) {
|
|
wxString message = "Unique ID must be between %d and %d.";
|
|
g_gui.PopupDialog(this, "Error", wxString::Format(message, rme::MinUniqueId, rme::MaxUniqueId), wxOK);
|
|
return;
|
|
}
|
|
if (g_gui.GetCurrentMap().hasUniqueId(new_uid)) {
|
|
g_gui.PopupDialog(this, "Error", "Unique ID must be unique, this UID is already taken.", wxOK);
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (aid_changed) {
|
|
if (new_aid != 0 && (new_aid < rme::MinActionId || new_aid > rme::MaxActionId)) {
|
|
wxString message = "Action ID must be between %d and %d.";
|
|
g_gui.PopupDialog(this, "Error", wxString::Format(message, rme::MinActionId, rme::MaxActionId), wxOK);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (edit_item->canHoldText() || edit_item->canHoldDescription()) {
|
|
// Book
|
|
std::string text = nstr(text_field->GetValue());
|
|
if (text.length() >= 0xFFFF) {
|
|
g_gui.PopupDialog(this, "Error", "Text is longer than 65535 characters, this is not supported by OpenTibia. Reduce the length of the text.", wxOK);
|
|
return;
|
|
}
|
|
if (edit_item->canHoldText() && text.length() > edit_item->getMaxWriteLength()) {
|
|
int ret = g_gui.PopupDialog(this, "Error", "Text is longer than the maximum supported length of this book type, do you still want to change it?", wxYES | wxNO);
|
|
if (ret != wxID_YES) {
|
|
return;
|
|
}
|
|
}
|
|
edit_item->setText(text);
|
|
} else if (edit_item->isSplash() || edit_item->isFluidContainer()) {
|
|
// Splash
|
|
int* new_type = reinterpret_cast<int*>(splash_type_field->GetClientData(splash_type_field->GetSelection()));
|
|
if (new_type) {
|
|
edit_item->setSubtype(*new_type);
|
|
}
|
|
// Clean up client data
|
|
} else if (Depot* depot = edit_item->getDepot()) {
|
|
// Depot
|
|
int* new_depotid = reinterpret_cast<int*>(depot_id_field->GetClientData(depot_id_field->GetSelection()));
|
|
depot->setDepotID(*new_depotid);
|
|
} else {
|
|
// Normal item
|
|
Door* door = edit_item->getDoor();
|
|
Teleport* teleport = edit_item->getTeleport();
|
|
|
|
int new_count = count_field ? count_field->GetValue() : 1;
|
|
std::string new_desc;
|
|
if (edit_item->canHoldDescription() && description_field) {
|
|
description_field->GetValue();
|
|
}
|
|
uint8_t new_door_id = 0;
|
|
if (door) {
|
|
new_door_id = door_id_field->GetValue();
|
|
}
|
|
|
|
/*
|
|
if(edit_item->canHoldDescription()) {
|
|
if(new_desc.length() > 127) {
|
|
g_gui.PopupDialog("Error", "Description must be shorter than 127 characters.", wxOK);
|
|
return;
|
|
}
|
|
}
|
|
*/
|
|
|
|
if (door && g_settings.getInteger(Config::WARN_FOR_DUPLICATE_ID)) {
|
|
if (edit_tile && edit_tile->isHouseTile()) {
|
|
const House* house = edit_map->houses.getHouse(edit_tile->getHouseID());
|
|
if (house) {
|
|
Position pos = house->getDoorPositionByID(new_door_id);
|
|
if (pos.isValid() && pos != edit_tile->getPosition()) {
|
|
int ret = g_gui.PopupDialog(this, "Warning", "This doorid conflicts with another one in this house, are you sure you want to continue?", wxYES | wxNO);
|
|
if (ret == wxID_NO) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (teleport) {
|
|
Position destination = destination_field->GetPosition();
|
|
if (!edit_map->getTile(destination) || edit_map->getTile(destination)->isBlocking()) {
|
|
int ret = g_gui.PopupDialog(this, "Warning", "This teleport leads nowhere, or to an invalid location. Do you want to change the destination?", wxYES | wxNO);
|
|
if (ret == wxID_YES) {
|
|
return;
|
|
}
|
|
}
|
|
teleport->setDestination(destination);
|
|
}
|
|
|
|
// Done validating, set the values.
|
|
if (edit_item->canHoldDescription()) {
|
|
edit_item->setText(new_desc);
|
|
}
|
|
if (edit_item->isStackable() || edit_item->isCharged()) {
|
|
edit_item->setSubtype(new_count);
|
|
}
|
|
if (door) {
|
|
door->setDoorID(new_door_id);
|
|
}
|
|
}
|
|
|
|
if (uid_changed) {
|
|
edit_item->setUniqueID(new_uid);
|
|
}
|
|
|
|
if (aid_changed) {
|
|
edit_item->setActionID(new_aid);
|
|
}
|
|
} else if (edit_monster) {
|
|
const auto new_spawn_monster_time = count_field->GetValue();
|
|
const auto newWeight = static_cast<uint8_t>(monsterWeightField->GetValue());
|
|
edit_monster->setSpawnMonsterTime(new_spawn_monster_time);
|
|
|
|
int* new_dir = reinterpret_cast<int*>(direction_field->GetClientData(
|
|
direction_field->GetSelection()
|
|
));
|
|
|
|
if (newWeight) {
|
|
edit_monster->setWeight(newWeight);
|
|
}
|
|
|
|
if (new_dir) {
|
|
edit_monster->setDirection((Direction)*new_dir);
|
|
}
|
|
} else if (edit_npc) {
|
|
int new_spawn_npc_time = count_field->GetValue();
|
|
edit_npc->setSpawnNpcTime(new_spawn_npc_time);
|
|
|
|
int* new_dir = reinterpret_cast<int*>(direction_field->GetClientData(
|
|
direction_field->GetSelection()
|
|
));
|
|
|
|
if (new_dir) {
|
|
edit_npc->setDirection((Direction)*new_dir);
|
|
}
|
|
} else if (edit_spawn_monster) {
|
|
int new_spawn_monster_size = count_field->GetValue();
|
|
edit_spawn_monster->setSize(new_spawn_monster_size);
|
|
} else if (edit_spawn_npc) {
|
|
int new_spawn_npc_size = count_field->GetValue();
|
|
edit_spawn_npc->setSize(new_spawn_npc_size);
|
|
}
|
|
EndModal(1);
|
|
}
|
|
|
|
void OldPropertiesWindow::OnClickCancel(wxCommandEvent &WXUNUSED(event)) {
|
|
// Just close this window
|
|
EndModal(0);
|
|
}
|
|
|
|
void OldPropertiesWindow::Update() {
|
|
Container* container = dynamic_cast<Container*>(edit_item);
|
|
if (container) {
|
|
for (uint32_t i = 0; i < container->getVolume(); ++i) {
|
|
container_items[i]->setItem(container->getItem(i));
|
|
}
|
|
}
|
|
wxDialog::Update();
|
|
}
|