diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 2e7910f2..2bd0946b 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -25,6 +25,7 @@ ${CMAKE_CURRENT_LIST_DIR}/editor.h ${CMAKE_CURRENT_LIST_DIR}/editor_tabs.h ${CMAKE_CURRENT_LIST_DIR}/extension.h ${CMAKE_CURRENT_LIST_DIR}/extension_window.h +${CMAKE_CURRENT_LIST_DIR}/find_item_window.h ${CMAKE_CURRENT_LIST_DIR}/filehandle.h ${CMAKE_CURRENT_LIST_DIR}/graphics.h ${CMAKE_CURRENT_LIST_DIR}/ground_brush.h @@ -125,6 +126,7 @@ ${CMAKE_CURRENT_LIST_DIR}/editor_tabs.cpp ${CMAKE_CURRENT_LIST_DIR}/eraser_brush.cpp ${CMAKE_CURRENT_LIST_DIR}/extension.cpp ${CMAKE_CURRENT_LIST_DIR}/extension_window.cpp +${CMAKE_CURRENT_LIST_DIR}/find_item_window.cpp ${CMAKE_CURRENT_LIST_DIR}/filehandle.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics.cpp ${CMAKE_CURRENT_LIST_DIR}/ground_brush.cpp diff --git a/source/common_windows.cpp b/source/common_windows.cpp index f5f38a53..c46c7104 100644 --- a/source/common_windows.cpp +++ b/source/common_windows.cpp @@ -773,113 +773,6 @@ void FindDialog::RefreshContents() RefreshContentsInternal(); } -// ============================================================================ -// Find Item Dialog (Jump to item) - -FindItemDialog::FindItemDialog(wxWindow* parent, wxString title) : FindDialog(parent, title) -{ - extra_condition = nullptr; - RefreshContents(); -} - -FindItemDialog::~FindItemDialog() -{ - //// -} - -void FindItemDialog::setCondition(bool condition(const ItemType&)) { - extra_condition = condition; -} - -void FindItemDialog::OnClickListInternal(wxCommandEvent& event) -{ - Brush* brush = item_list->GetSelectedBrush(); - if(brush && brush->isRaw()) { - result_brush = brush; - result_id = brush->asRaw()->getItemID(); - EndModal(result_id); - } -} - -void FindItemDialog::OnClickOKInternal() -{ - // This is kind of stupid as it would fail unless the "Please enter a search string" wasn't there - if(item_list->GetItemCount() > 0) { - if(item_list->GetSelection() == wxNOT_FOUND) { - item_list->SetSelection(0); - } - - Brush* brush = item_list->GetSelectedBrush(); - if (brush && brush->isRaw()) { - result_brush = brush; - result_id = brush->asRaw()->getItemID(); - } else { - // It's either "Please enter a search string" or "No matches" - // Perhaps we can refresh now? - std::string search_string = as_lower_str(nstr(search_field->GetValue())); - bool do_search = (search_string.size() >= 2); - - if(do_search) { - for(int id = 0; id <= g_items.getMaxID(); ++id) { - ItemType& it = g_items[id]; - if(it.id == 0 || (extra_condition && !extra_condition(it))) - continue; - - RAWBrush* raw_brush = it.raw_brush; - if(!raw_brush) - continue; - - if(as_lower_str(raw_brush->getName()).find(search_string) == std::string::npos) - continue; - - // Found one! - result_brush = raw_brush; - result_id = raw_brush->getItemID(); - break; - } - } - } - } - EndModal(result_id); -} - -void FindItemDialog::RefreshContentsInternal() -{ - item_list->Clear(); - - std::string search_string = as_lower_str(nstr(search_field->GetValue())); - bool do_search = (search_string.size() >= 2); - - if(do_search) { - - bool found_search_results = false; - - for(int id = 0; id <= g_items.getMaxID(); ++id) { - ItemType& it = g_items[id]; - if(it.id == 0 || (extra_condition && !extra_condition(it))) - continue; - - RAWBrush* raw_brush = it.raw_brush; - if(!raw_brush) - continue; - - if(as_lower_str(raw_brush->getName()).find(search_string) == std::string::npos) - continue; - - found_search_results = true; - item_list->AddBrush(raw_brush); - } - - - if(found_search_results) - item_list->SetSelection(0); - else - item_list->SetNoMatches(); - - } - item_list->Refresh(); -} - // ============================================================================ // Find Brush Dialog (Jump to brush) diff --git a/source/common_windows.h b/source/common_windows.h index 14af129e..1301805a 100644 --- a/source/common_windows.h +++ b/source/common_windows.h @@ -240,26 +240,6 @@ class FindBrushDialog : public FindDialog virtual void OnClickOKInternal(); }; -/** - * Select an item dialog - * Find out what item was selected through return value of ShowModal() or getResultID - */ -class FindItemDialog : public FindDialog -{ -public: - FindItemDialog(wxWindow* parent, wxString title = "Jump to Item"); - virtual ~FindItemDialog(); - - void setCondition(bool condition(const ItemType&)); - - virtual void RefreshContentsInternal(); - virtual void OnClickListInternal(wxCommandEvent&); - virtual void OnClickOKInternal(); - -protected: - bool (*extra_condition)(const ItemType&); -}; - /** * Select two items * Will return the two selected items through GetResultFindID() and GetResultWithID() diff --git a/source/container_properties_window.cpp b/source/container_properties_window.cpp index 14c602bd..ce65b4c3 100644 --- a/source/container_properties_window.cpp +++ b/source/container_properties_window.cpp @@ -8,6 +8,7 @@ #include "old_properties_window.h" #include "properties_window.h" +#include "find_item_window.h" #include "gui.h" #include "complexitem.h" #include "map.h" @@ -70,32 +71,23 @@ void ContainerItemButton::OnMouseRightRelease(wxMouseEvent& WXUNUSED(event)) void ContainerItemButton::OnAddItem(wxCommandEvent& WXUNUSED(event)) { - FindItemDialog* itemDialog = newd FindItemDialog(GetParent(), "Choose Item to add"); - itemDialog->setCondition([](const ItemType& itemType) -> bool { - return itemType.pickupable; - }); + FindItemDialog dialog(GetParent(), "Choose Item to add", true); - int32_t id = itemDialog->ShowModal(); - itemDialog->Destroy(); + if(dialog.ShowModal() != 0) { + Container* container = getParentContainer(); + ItemVector& itemVector = container->getVector(); - if(id == 0) { - return; - } - - Container* container = getParentContainer(); - ItemVector& itemVector = container->getVector(); + Item* item = Item::Create(dialog.getResultID()); + if(index < itemVector.size()) + itemVector.insert(itemVector.begin() + index, item); + else + itemVector.push_back(item); - Item* item = Item::Create(id); - if(index < itemVector.size()) { - itemVector.insert(itemVector.begin() + index, item); - } else { - itemVector.push_back(item); - } - - ObjectPropertiesWindowBase* propertyWindow = getParentContainerWindow(); - if(propertyWindow) { - propertyWindow->Update(); + ObjectPropertiesWindowBase* propertyWindow = getParentContainerWindow(); + if(propertyWindow) + propertyWindow->Update(); } + dialog.Destroy(); } void ContainerItemButton::OnEditItem(wxCommandEvent& WXUNUSED(event)) diff --git a/source/find_item_window.cpp b/source/find_item_window.cpp new file mode 100644 index 00000000..97129af8 --- /dev/null +++ b/source/find_item_window.cpp @@ -0,0 +1,430 @@ +////////////////////////////////////////////////////////////////////// +// 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 . +////////////////////////////////////////////////////////////////////// + +#include "main.h" +#include "find_item_window.h" +#include "common_windows.h" +#include "gui.h" +#include "items.h" +#include "brush.h" +#include "raw_brush.h" + +BEGIN_EVENT_TABLE(FindItemDialog, wxDialog) + EVT_BUTTON(wxID_OK, FindItemDialog::OnClickOK) + EVT_BUTTON(wxID_CANCEL, FindItemDialog::OnClickCancel) +END_EVENT_TABLE() + +FindItemDialog::FindItemDialog(wxWindow* parent, const wxString& title, bool onlyPickupables/* = false*/) : + wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxSize(800, 600), wxDEFAULT_DIALOG_STYLE), + result_brush(nullptr), + result_id(0) +{ + this->SetSizeHints(wxDefaultSize, wxDefaultSize); + + wxBoxSizer* box_sizer = newd wxBoxSizer(wxHORIZONTAL); + + wxBoxSizer* options_box_sizer = newd wxBoxSizer(wxVERTICAL); + + wxString radio_boxChoices[] = { "Find by Server ID", + "Find by Client ID", + "Find by Name", + "Find by Types", + "Find by Properties" }; + + int radio_boxNChoices = sizeof(radio_boxChoices) / sizeof(wxString); + options_radio_box = newd wxRadioBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, radio_boxNChoices, radio_boxChoices, 1, wxRA_SPECIFY_COLS); + options_radio_box->SetSelection(onlyPickupables ? SearchMode::Properties : SearchMode::ServerIDs); + options_radio_box->Enable(!onlyPickupables); + options_box_sizer->Add(options_radio_box, 0, wxALL | wxEXPAND, 5); + + wxStaticBoxSizer* server_id_box_sizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, "Server ID"), wxVERTICAL); + server_id_spin = newd wxSpinCtrl(server_id_box_sizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 100, g_items.getMaxID(), 100); + server_id_spin->Enable(!onlyPickupables); + server_id_box_sizer->Add(server_id_spin, 0, wxALL | wxEXPAND, 5); + options_box_sizer->Add(server_id_box_sizer, 1, wxALL | wxEXPAND, 5); + + wxStaticBoxSizer* client_id_box_sizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, "Client ID"), wxVERTICAL); + client_id_spin = newd wxSpinCtrl(client_id_box_sizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 100, g_gui.gfx.getItemSpriteMaxID(), 100); + client_id_spin->Enable(false); + client_id_box_sizer->Add(client_id_spin, 0, wxALL | wxEXPAND, 5); + options_box_sizer->Add(client_id_box_sizer, 1, wxALL | wxEXPAND, 5); + + wxStaticBoxSizer* name_box_sizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, "Name"), wxVERTICAL); + name_text_input = newd wxTextCtrl(name_box_sizer->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0); + name_text_input->Enable(false); + name_box_sizer->Add(name_text_input, 0, wxALL | wxEXPAND, 5); + options_box_sizer->Add(name_box_sizer, 1, wxALL | wxEXPAND, 5); + + // spacer + options_box_sizer->Add(0, 0, 4, wxALL | wxEXPAND, 5); + + buttons_box_sizer = newd wxStdDialogButtonSizer(); + ok_button = newd wxButton(this, wxID_OK); + buttons_box_sizer->AddButton(ok_button); + cancel_button = newd wxButton(this, wxID_CANCEL); + buttons_box_sizer->AddButton(cancel_button); + buttons_box_sizer->Realize(); + options_box_sizer->Add(buttons_box_sizer, 0, wxALIGN_CENTER | wxALL, 5); + + box_sizer->Add(options_box_sizer, 1, wxALL, 5); + + // --------------- Types --------------- + + wxStaticBoxSizer* type_box_sizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, "Types"), wxVERTICAL); + + wxString types_choices[] = { "Depot", + "Mailbox", + "Trash Holder", + "Container", + "Door", + "Magic Field", + "Teleport", + "Bed", + "Key" }; + + int types_choices_count = sizeof(types_choices) / sizeof(wxString); + types_radio_box = newd wxRadioBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, types_choices_count, types_choices, 1, wxRA_SPECIFY_COLS); + types_radio_box->SetSelection(0); + types_radio_box->Enable(false); + type_box_sizer->Add(types_radio_box, 0, wxALL | wxEXPAND, 5); + + box_sizer->Add(type_box_sizer, 1, wxALL | wxEXPAND, 5); + + // --------------- Properties --------------- + + wxStaticBoxSizer* properties_box_sizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, "Properties"), wxVERTICAL); + + unpassable = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Unpassable", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(unpassable, 0, wxALL, 5); + + unmovable = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Unmovable", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(unmovable, 0, wxALL, 5); + + block_missiles = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Block Missiles", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(block_missiles, 0, wxALL, 5); + + block_pathfinder = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Block Pathfinder", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(block_pathfinder, 0, wxALL, 5); + + pickupable = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Pickupable", wxDefaultPosition, wxDefaultSize, 0); + pickupable->SetValue(onlyPickupables); + properties_box_sizer->Add(pickupable, 0, wxALL, 5); + + stackable = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Stackable", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(stackable, 0, wxALL, 5); + + rotatable = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Rotatable", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(rotatable, 0, wxALL, 5); + + hangable = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Hangable", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(hangable, 0, wxALL, 5); + + hook_east = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Hook East", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(hook_east, 0, wxALL, 5); + + hook_south = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Hook South", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(hook_south, 0, wxALL, 5); + + has_elevation = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Has Elevation", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(has_elevation, 0, wxALL, 5); + + ignore_look = newd wxCheckBox(properties_box_sizer->GetStaticBox(), wxID_ANY, "Ignore Look", wxDefaultPosition, wxDefaultSize, 0); + properties_box_sizer->Add(ignore_look, 0, wxALL, 5); + + box_sizer->Add(properties_box_sizer, 1, wxALL | wxEXPAND, 5); + + // --------------- Items list --------------- + + wxStaticBoxSizer* result_box_sizer = newd wxStaticBoxSizer(newd wxStaticBox(this, wxID_ANY, "Result"), wxVERTICAL); + items_list = newd FindDialogListBox(result_box_sizer->GetStaticBox(), wxID_ANY); + items_list->SetMinSize(wxSize(230, 512)); + result_box_sizer->Add(items_list, 0, wxALL, 5); + box_sizer->Add(result_box_sizer, 1, wxALL | wxEXPAND, 5); + + this->SetSizer(box_sizer); + this->Layout(); + this->Centre(wxBOTH); + this->EnableProperties(false); + this->RefreshContentsInternal(); + + // Connect Events + options_radio_box->Connect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(FindItemDialog::OnOptionChange), NULL, this); + server_id_spin->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler(FindItemDialog::OnServerIdChange), NULL, this); + server_id_spin->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FindItemDialog::OnServerIdChange), NULL, this); + client_id_spin->Connect(wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler(FindItemDialog::OnClientIdChange), NULL, this); + client_id_spin->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FindItemDialog::OnClientIdChange), NULL, this); + name_text_input->Connect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FindItemDialog::OnText), NULL, this); + + types_radio_box->Connect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(FindItemDialog::OnTypeChange), NULL, this); + + unpassable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + unmovable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + block_missiles->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + block_pathfinder->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + pickupable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + stackable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + rotatable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + hangable->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + hook_east->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + hook_south->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + has_elevation->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + ignore_look->Connect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); +} + +FindItemDialog::~FindItemDialog() +{ + // Disconnect Events + options_radio_box->Disconnect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(FindItemDialog::OnOptionChange), NULL, this); + server_id_spin->Disconnect(wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler(FindItemDialog::OnServerIdChange), NULL, this); + server_id_spin->Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FindItemDialog::OnServerIdChange), NULL, this); + client_id_spin->Disconnect(wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler(FindItemDialog::OnClientIdChange), NULL, this); + client_id_spin->Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FindItemDialog::OnClientIdChange), NULL, this); + name_text_input->Disconnect(wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(FindItemDialog::OnText), NULL, this); + + types_radio_box->Disconnect(wxEVT_COMMAND_RADIOBOX_SELECTED, wxCommandEventHandler(FindItemDialog::OnTypeChange), NULL, this); + + unpassable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + unmovable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + block_missiles->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + block_pathfinder->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + pickupable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + stackable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + rotatable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + hangable->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + hook_east->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + hook_south->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + has_elevation->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); + ignore_look->Disconnect(wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(FindItemDialog::OnPropertyChange), NULL, this); +} + +FindItemDialog::SearchMode FindItemDialog::getSearchMode() const +{ + return (SearchMode)options_radio_box->GetSelection(); +} + +void FindItemDialog::setSearchMode(FindItemDialog::SearchMode mode) +{ + if((SearchMode)options_radio_box->GetSelection() != mode) + options_radio_box->SetSelection(mode); + + server_id_spin->Enable(mode == SearchMode::ServerIDs); + client_id_spin->Enable(mode == SearchMode::ClientIDs); + name_text_input->Enable(mode == SearchMode::Names); + types_radio_box->Enable(mode == SearchMode::Types); + EnableProperties(mode == SearchMode::Properties); + RefreshContentsInternal(); +} + +void FindItemDialog::EnableProperties(bool enable) +{ + unpassable->Enable(enable); + unmovable->Enable(enable); + block_missiles->Enable(enable); + block_pathfinder->Enable(enable); + pickupable->Enable(enable); + stackable->Enable(enable); + rotatable->Enable(enable); + hangable->Enable(enable); + hook_east->Enable(enable); + hook_south->Enable(enable); + has_elevation->Enable(enable); + ignore_look->Enable(enable); +} + +void FindItemDialog::RefreshContentsInternal() +{ + items_list->Clear(); + + SearchMode selection = (SearchMode)options_radio_box->GetSelection(); + bool found_search_results = false; + + if(selection == SearchMode::ServerIDs) { + uint16_t serverID = (uint16_t)server_id_spin->GetValue(); + for(int id = 100; id <= g_items.getMaxID(); ++id) { + ItemType& item = g_items.getItemType(id); + if(item.id != serverID) + continue; + + RAWBrush* raw_brush = item.raw_brush; + if (!raw_brush) + continue; + + found_search_results = true; + items_list->AddBrush(raw_brush); + } + } + else if(selection == SearchMode::ClientIDs) { + uint16_t clientID = (uint16_t)client_id_spin->GetValue(); + for (int id = 100; id <= g_items.getMaxID(); ++id) { + ItemType& item = g_items.getItemType(id); + if (item.id == 0 || item.clientID != clientID) + continue; + + RAWBrush* raw_brush = item.raw_brush; + if (!raw_brush) + continue; + + found_search_results = true; + items_list->AddBrush(raw_brush); + } + } + else if(selection == SearchMode::Names) { + std::string search_string = as_lower_str(nstr(name_text_input->GetValue())); + if(search_string.size() >= 2) { + for(int id = 100; id <= g_items.getMaxID(); ++id) { + ItemType& item = g_items.getItemType(id); + if(item.id == 0) + continue; + + RAWBrush* raw_brush = item.raw_brush; + if(!raw_brush) + continue; + + if(as_lower_str(raw_brush->getName()).find(search_string) == std::string::npos) + continue; + + found_search_results = true; + items_list->AddBrush(raw_brush); + } + } + } + else if(selection == SearchMode::Types) { + for(int id = 100; id <= g_items.getMaxID(); ++id) { + ItemType& item = g_items.getItemType(id); + if (item.id == 0) + continue; + + RAWBrush* raw_brush = item.raw_brush; + if(!raw_brush) + continue; + + SearchItemType selection = (SearchItemType)types_radio_box->GetSelection(); + if ((selection == SearchItemType::Depot && !item.isDepot()) || + (selection == SearchItemType::Mailbox && !item.isMailbox()) || + (selection == SearchItemType::TrashHolder && !item.isTrashHolder()) || + (selection == SearchItemType::Container && !item.isContainer()) || + (selection == SearchItemType::Door && !item.isDoor()) || + (selection == SearchItemType::MagicField && !item.isMagicField()) || + (selection == SearchItemType::Teleport && !item.isTeleport()) || + (selection == SearchItemType::Bed && !item.isBed()) || + (selection == SearchItemType::Key && !item.isKey())) { + continue; + } + + found_search_results = true; + items_list->AddBrush(raw_brush); + } + } + else if(selection == SearchMode::Properties) { + bool has_selected = (unpassable->GetValue() || + unmovable->GetValue() || + block_missiles->GetValue() || + block_pathfinder->GetValue() || + pickupable->GetValue() || + stackable->GetValue() || + rotatable->GetValue() || + hangable->GetValue() || + hook_east->GetValue() || + hook_south->GetValue() || + has_elevation->GetValue() || + ignore_look->GetValue()); + + if(has_selected) { + for(int id = 100; id <= g_items.getMaxID(); ++id) { + ItemType& item = g_items.getItemType(id); + if(item.id == 0) + continue; + + RAWBrush* raw_brush = item.raw_brush; + if(!raw_brush) + continue; + + if((unpassable->GetValue() && !item.unpassable) || + (unmovable->GetValue() && item.moveable) || + (block_missiles->GetValue() && !item.blockMissiles) || + (block_pathfinder->GetValue() && !item.blockPathfinder) || + (pickupable->GetValue() && !item.pickupable) || + (stackable->GetValue() && !item.stackable) || + (rotatable->GetValue() && !item.rotable) || + (hangable->GetValue() && !item.isHangable) || + (hook_east->GetValue() && !item.hookEast) || + (hook_south->GetValue() && !item.hookSouth) || + (has_elevation->GetValue() && !item.hasElevation) || + (ignore_look->GetValue() && !item.ignoreLook)) { + continue; + } + + found_search_results = true; + items_list->AddBrush(raw_brush); + } + } + } + + if(found_search_results) + items_list->SetSelection(0); + else + items_list->SetNoMatches(); + + items_list->Refresh(); +} + +void FindItemDialog::OnOptionChange(wxCommandEvent& event) +{ + setSearchMode((SearchMode)options_radio_box->GetSelection()); +} + +void FindItemDialog::OnServerIdChange(wxCommandEvent& event) +{ + RefreshContentsInternal(); +} + +void FindItemDialog::OnClientIdChange(wxCommandEvent& event) +{ + RefreshContentsInternal(); +} + +void FindItemDialog::OnText(wxCommandEvent& event) +{ + RefreshContentsInternal(); +} + +void FindItemDialog::OnTypeChange(wxCommandEvent& event) +{ + RefreshContentsInternal(); +} + +void FindItemDialog::OnPropertyChange(wxCommandEvent& event) +{ + RefreshContentsInternal(); +} + +void FindItemDialog::OnClickOK(wxCommandEvent& event) +{ + if(items_list->GetItemCount() != 0) { + Brush* brush = items_list->GetSelectedBrush(); + if(brush) { + result_brush = brush; + result_id = brush->asRaw()->getItemID(); + EndModal(wxID_OK); + } + } +} + +void FindItemDialog::OnClickCancel(wxCommandEvent& event) +{ + EndModal(wxID_CANCEL); +} diff --git a/source/find_item_window.h b/source/find_item_window.h new file mode 100644 index 00000000..c6da2439 --- /dev/null +++ b/source/find_item_window.h @@ -0,0 +1,107 @@ +////////////////////////////////////////////////////////////////////// +// 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 . +////////////////////////////////////////////////////////////////////// + +#ifndef RME_FIND_ITEM_WINDOW_H_ +#define RME_FIND_ITEM_WINDOW_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +class FindDialogListBox; + +class FindItemDialog : public wxDialog +{ +public: + enum SearchMode { + ServerIDs = 0, + ClientIDs, + Names, + Types, + Properties, + }; + + enum SearchItemType { + Depot, + Mailbox, + TrashHolder, + Container, + Door, + MagicField, + Teleport, + Bed, + Key + }; + + FindItemDialog(wxWindow* parent, const wxString& title, bool onlyPickupables = false); + ~FindItemDialog(); + + Brush* getResult() const { return result_brush; } + uint16_t getResultID() const { return result_id; } + + SearchMode getSearchMode() const; + void setSearchMode(SearchMode mode); + +private: + void EnableProperties(bool enable); + void RefreshContentsInternal(); + + void OnOptionChange(wxCommandEvent& event); + void OnServerIdChange(wxCommandEvent& event); + void OnClientIdChange(wxCommandEvent& event); + void OnText(wxCommandEvent& event); + void OnTypeChange(wxCommandEvent& event); + void OnPropertyChange(wxCommandEvent& event); + void OnClickOK(wxCommandEvent& event); + void OnClickCancel(wxCommandEvent& event); + + wxRadioBox* options_radio_box; + + wxRadioBox* types_radio_box; + + wxSpinCtrl* server_id_spin; + wxSpinCtrl* client_id_spin; + wxTextCtrl* name_text_input; + wxCheckBox* unpassable; + wxCheckBox* unmovable; + wxCheckBox* block_missiles; + wxCheckBox* block_pathfinder; + wxCheckBox* pickupable; + wxCheckBox* stackable; + wxCheckBox* rotatable; + wxCheckBox* hangable; + wxCheckBox* hook_east; + wxCheckBox* hook_south; + wxCheckBox* has_elevation; + wxCheckBox* ignore_look; + + FindDialogListBox* items_list; + wxStdDialogButtonSizer* buttons_box_sizer; + wxButton* ok_button; + wxButton* cancel_button; + Brush* result_brush; + uint16_t result_id; + + DECLARE_EVENT_TABLE() +}; + +#endif // RME_FIND_ITEM_WINDOW_H_ diff --git a/source/graphics.cpp b/source/graphics.cpp index 38c4423c..7e837104 100644 --- a/source/graphics.cpp +++ b/source/graphics.cpp @@ -383,9 +383,9 @@ bool GraphicManager::loadSpriteMetadata(const FileName& datafile, wxString& erro file.getU16(effect_count); file.getU16(distance_count); - uint32_t minclientID = 100; // tibia.dat start with id 100 + uint32_t minID = 100; // tibia.dat start with id 100 // We don't load distance/effects, if we would, just add effect_count & distance_count here - uint32_t maxclientID = item_count + creature_count; + uint32_t maxID = item_count + creature_count; dat_format = client_version->getDatFormatForSignature(datSignature); @@ -395,9 +395,9 @@ bool GraphicManager::loadSpriteMetadata(const FileName& datafile, wxString& erro has_frame_groups = dat_format >= DAT_FORMAT_1057; } - uint16_t id = minclientID; + uint16_t id = minID; // loop through all ItemDatabase until we reach the end of file - while(id <= maxclientID) { + while(id <= maxID) { GameSprite* sType = newd GameSprite(); sprite_space[id] = sType; diff --git a/source/item.cpp b/source/item.cpp index 3bcf0a82..ca8d5d1d 100644 --- a/source/item.cpp +++ b/source/item.cpp @@ -185,7 +185,7 @@ bool Item::hasProperty(enum ITEMPROPERTY prop) const const ItemType& it = g_items[id]; switch(prop){ case BLOCKSOLID: - if(it.blockSolid) + if(it.unpassable) return true; break; @@ -200,27 +200,27 @@ bool Item::hasProperty(enum ITEMPROPERTY prop) const break; */ case BLOCKPROJECTILE: - if(it.blockProjectile) + if(it.blockMissiles) return true; break; case BLOCKPATHFIND: - if(it.blockPathFind) + if(it.blockPathfinder) return true; break; - case ISVERTICAL: - if(it.isVertical) + case HOOK_SOUTH: + if(it.hookSouth) return true; break; - case ISHORIZONTAL: - if(it.isHorizontal) + case HOOK_EAST: + if(it.hookEast) return true; break; case BLOCKINGANDNOTMOVEABLE: - if(it.blockSolid && (!it.moveable || getUniqueID() != 0)) + if(it.unpassable && (!it.moveable || getUniqueID() != 0)) return true; break; diff --git a/source/item.h b/source/item.h index 120e8cab..e087ffa2 100644 --- a/source/item.h +++ b/source/item.h @@ -35,8 +35,8 @@ enum ITEMPROPERTY { BLOCKPROJECTILE, BLOCKPATHFIND, PROTECTIONZONE, - ISVERTICAL, - ISHORIZONTAL, + HOOK_SOUTH, + HOOK_EAST, MOVEABLE, BLOCKINGANDNOTMOVEABLE }; @@ -178,7 +178,7 @@ class Item : public ItemAttributes // Item types bool hasProperty(enum ITEMPROPERTY prop) const; - bool isBlocking() const {return g_items[id].blockSolid;} + bool isBlocking() const {return g_items[id].unpassable;} bool isStackable() const {return g_items[id].stackable;} bool isClientCharged() const {return g_items[id].isClientCharged();} bool isExtraCharged() const {return g_items[id].isExtraCharged();} diff --git a/source/items.cpp b/source/items.cpp index def1b25e..fe341ca3 100644 --- a/source/items.cpp +++ b/source/items.cpp @@ -57,10 +57,11 @@ ItemType::ItemType() : charges(0), client_chargeable(false), extra_chargeable(false), + ignoreLook(false), - isVertical(false), - isHorizontal(false), isHangable(false), + hookSouth(false), + hookEast(false), canReadText(false), canWriteText(false), replaceable(true), @@ -84,10 +85,11 @@ ItemType::ItemType() : floorChangeEast(false), floorChangeWest(false), - blockSolid(false), + unpassable(false), blockPickupable(false), - blockProjectile(false), - blockPathFind(false), + blockMissiles(false), + blockPathfinder(false), + hasElevation(false), alwaysOnTopOrder(0), rotateTo(0), @@ -152,7 +154,7 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra t->group = ItemGroup_t(u8); switch(t->group) { - case ITEM_GROUP_NONE: + case ITEM_GROUP_NONE: case ITEM_GROUP_GROUND: case ITEM_GROUP_SPLASH: case ITEM_GROUP_FLUID: @@ -173,11 +175,10 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra uint32_t flags; if(itemNode->getU32(flags)) { - t->blockSolid = ((flags & FLAG_BLOCK_SOLID) == FLAG_BLOCK_SOLID); - t->blockProjectile = ((flags & FLAG_BLOCK_PROJECTILE) == FLAG_BLOCK_PROJECTILE); - t->blockPathFind = ((flags & FLAG_BLOCK_PATHFIND) == FLAG_BLOCK_PATHFIND); - // These are irrelevant - //t->hasHeight = ((flags & FLAG_HAS_HEIGHT) == FLAG_HAS_HEIGHT); + t->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); + t->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); + t->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); + t->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); //t->useable = ((flags & FLAG_USEABLE) == FLAG_USEABLE); t->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); t->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); @@ -189,9 +190,9 @@ bool ItemDatabase::loadFromOtbVer1(BinaryNode* itemNode, wxString& error, wxArra t->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); // Now this is confusing, just accept that the ALWAYSONTOP flag means it's always on bottom, got it?! t->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); - t->isVertical = ((flags & FLAG_VERTICAL) == FLAG_VERTICAL); - t->isHorizontal = ((flags & FLAG_HORIZONTAL) == FLAG_HORIZONTAL); t->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); + t->hookSouth = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); + t->hookEast = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); t->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); t->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); t->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); @@ -411,25 +412,26 @@ bool ItemDatabase::loadFromOtbVer2(BinaryNode* itemNode, wxString& error, wxArra t->group = ItemGroup_t(u8); switch(t->group) { - case ITEM_GROUP_NONE: + case ITEM_GROUP_NONE: case ITEM_GROUP_GROUND: case ITEM_GROUP_SPLASH: case ITEM_GROUP_FLUID: break; - case ITEM_GROUP_DOOR: t->type = ITEM_TYPE_DOOR; break; - case ITEM_GROUP_CONTAINER: t->type = ITEM_TYPE_CONTAINER; break; - case ITEM_GROUP_RUNE: t->client_chargeable = true; break; - case ITEM_GROUP_TELEPORT: t->type = ITEM_TYPE_TELEPORT; break; - case ITEM_GROUP_MAGICFIELD: t->type = ITEM_TYPE_MAGICFIELD; break; + case ITEM_GROUP_DOOR: t->type = ITEM_TYPE_DOOR; break; + case ITEM_GROUP_CONTAINER: t->type = ITEM_TYPE_CONTAINER; break; + case ITEM_GROUP_RUNE: t->client_chargeable = true; break; + case ITEM_GROUP_TELEPORT: t->type = ITEM_TYPE_TELEPORT; break; + case ITEM_GROUP_MAGICFIELD: t->type = ITEM_TYPE_MAGICFIELD; break; default: warnings.push_back("Unknown item group declaration"); } uint32_t flags; if(itemNode->getU32(flags)) { - t->blockSolid = ((flags & FLAG_BLOCK_SOLID) == FLAG_BLOCK_SOLID); - t->blockProjectile = ((flags & FLAG_BLOCK_PROJECTILE) == FLAG_BLOCK_PROJECTILE); - t->blockPathFind = ((flags & FLAG_BLOCK_PATHFIND) == FLAG_BLOCK_PATHFIND); + t->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); + t->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); + t->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); + t->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); t->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); t->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); t->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); @@ -440,9 +442,9 @@ bool ItemDatabase::loadFromOtbVer2(BinaryNode* itemNode, wxString& error, wxArra t->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); // Now this is confusing, just accept that the ALWAYSONTOP flag means it's always on bottom, got it?! t->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); - t->isVertical = ((flags & FLAG_VERTICAL) == FLAG_VERTICAL); - t->isHorizontal = ((flags & FLAG_HORIZONTAL) == FLAG_HORIZONTAL); t->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); + t->hookSouth = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); + t->hookEast = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); t->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); t->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); t->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); @@ -573,9 +575,10 @@ bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArra uint32_t flags; if(itemNode->getU32(flags)) { - t->blockSolid = ((flags & FLAG_BLOCK_SOLID) == FLAG_BLOCK_SOLID); - t->blockProjectile = ((flags & FLAG_BLOCK_PROJECTILE) == FLAG_BLOCK_PROJECTILE); - t->blockPathFind = ((flags & FLAG_BLOCK_PATHFIND) == FLAG_BLOCK_PATHFIND); + t->unpassable = ((flags & FLAG_UNPASSABLE) == FLAG_UNPASSABLE); + t->blockMissiles = ((flags & FLAG_BLOCK_MISSILES) == FLAG_BLOCK_MISSILES); + t->blockPathfinder = ((flags & FLAG_BLOCK_PATHFINDER) == FLAG_BLOCK_PATHFINDER); + t->hasElevation = ((flags & FLAG_HAS_ELEVATION) == FLAG_HAS_ELEVATION); t->pickupable = ((flags & FLAG_PICKUPABLE) == FLAG_PICKUPABLE); t->moveable = ((flags & FLAG_MOVEABLE) == FLAG_MOVEABLE); t->stackable = ((flags & FLAG_STACKABLE) == FLAG_STACKABLE); @@ -586,9 +589,9 @@ bool ItemDatabase::loadFromOtbVer3(BinaryNode* itemNode, wxString& error, wxArra t->floorChangeWest = ((flags & FLAG_FLOORCHANGEWEST) == FLAG_FLOORCHANGEWEST); // Now this is confusing, just accept that the ALWAYSONTOP flag means it's always on bottom, got it?! t->alwaysOnBottom = ((flags & FLAG_ALWAYSONTOP) == FLAG_ALWAYSONTOP); - t->isVertical = ((flags & FLAG_VERTICAL) == FLAG_VERTICAL); - t->isHorizontal = ((flags & FLAG_HORIZONTAL) == FLAG_HORIZONTAL); t->isHangable = ((flags & FLAG_HANGABLE) == FLAG_HANGABLE); + t->hookSouth = ((flags & FLAG_HOOK_EAST) == FLAG_HOOK_EAST); + t->hookEast = ((flags & FLAG_HOOK_SOUTH) == FLAG_HOOK_SOUTH); t->allowDistRead = ((flags & FLAG_ALLOWDISTREAD) == FLAG_ALLOWDISTREAD); t->rotable = ((flags & FLAG_ROTABLE) == FLAG_ROTABLE); t->canReadText = ((flags & FLAG_READABLE) == FLAG_READABLE); @@ -784,22 +787,25 @@ bool ItemDatabase::loadItemFromGameXml(pugi::xml_node itemNode, int id) std::string typeValue = attribute.as_string(); to_lower_str(key); - if(typeValue == "magicfield") { + if(typeValue == "depot") { + it.type = ITEM_TYPE_DEPOT; + } else if(typeValue == "mailbox") { + it.type = ITEM_TYPE_MAILBOX; + } else if(typeValue == "trashholder") { + it.type = ITEM_TYPE_TRASHHOLDER; + } else if (typeValue == "container") { + it.type = ITEM_TYPE_CONTAINER; + } else if (typeValue == "door") { + it.type = ITEM_TYPE_DOOR; + } else if (typeValue == "magicfield") { it.group = ITEM_GROUP_MAGICFIELD; it.type = ITEM_TYPE_MAGICFIELD; - } else if(typeValue == "key") { - it.type = ITEM_TYPE_KEY; - } else if(typeValue == "depot") { - it.type = ITEM_TYPE_DEPOT; - } else if(typeValue == "teleport") { + } else if (typeValue == "teleport") { it.type = ITEM_TYPE_TELEPORT; - } else if(typeValue == "bed") { + } else if (typeValue == "bed") { it.type = ITEM_TYPE_BED; - } else if(typeValue == "door") { - it.type = ITEM_TYPE_DOOR; - } else { - // We ignore many types, no need to complain - //warnings.push_back("items.xml: Unknown type " + typeValue); + } else if (typeValue == "key") { + it.type = ITEM_TYPE_KEY; } } else if(key == "name") { if((attribute = itemAttributesNode.attribute("value"))) { diff --git a/source/items.h b/source/items.h index 28dd03b2..f7dd7035 100644 --- a/source/items.h +++ b/source/items.h @@ -127,29 +127,30 @@ enum itemattrib_t { }; enum itemflags_t { - FLAG_BLOCK_SOLID = 1, - FLAG_BLOCK_PROJECTILE = 2, - FLAG_BLOCK_PATHFIND = 4, - FLAG_HAS_HEIGHT = 8, - FLAG_USEABLE = 16, - FLAG_PICKUPABLE = 32, - FLAG_MOVEABLE = 64, - FLAG_STACKABLE = 128, - FLAG_FLOORCHANGEDOWN = 256, - FLAG_FLOORCHANGENORTH = 512, - FLAG_FLOORCHANGEEAST = 1024, - FLAG_FLOORCHANGESOUTH = 2048, - FLAG_FLOORCHANGEWEST = 4096, - FLAG_ALWAYSONTOP = 8192, - FLAG_READABLE = 16384, - FLAG_ROTABLE = 32768, - FLAG_HANGABLE = 65536, - FLAG_VERTICAL = 131072, - FLAG_HORIZONTAL = 262144, - FLAG_CANNOTDECAY = 524288, - FLAG_ALLOWDISTREAD = 1048576, - FLAG_UNUSED = 2097152, - FLAG_CLIENTCHARGES = 4194304, + FLAG_UNPASSABLE = 1 << 0, + FLAG_BLOCK_MISSILES = 1 << 1, + FLAG_BLOCK_PATHFINDER = 1 << 2, + FLAG_HAS_ELEVATION = 1 << 3, + FLAG_USEABLE = 1 << 4, + FLAG_PICKUPABLE = 1 << 5, + FLAG_MOVEABLE = 1 << 6, + FLAG_STACKABLE = 1 << 7, + FLAG_FLOORCHANGEDOWN = 1 << 8, + FLAG_FLOORCHANGENORTH = 1 << 9, + FLAG_FLOORCHANGEEAST = 1 << 10, + FLAG_FLOORCHANGESOUTH = 1 << 11, + FLAG_FLOORCHANGEWEST = 1 << 12, + FLAG_ALWAYSONTOP = 1 << 13, + FLAG_READABLE = 1 << 14, + FLAG_ROTABLE = 1 << 15, + FLAG_HANGABLE = 1 << 16, + FLAG_HOOK_SOUTH = 1 << 17, + FLAG_HOOK_EAST = 1 << 18, + FLAG_CANNOTDECAY = 1 << 19, + FLAG_ALLOWDISTREAD = 1 << 20, + FLAG_UNUSED = 1 << 21, + FLAG_CLIENTCHARGES = 1 << 22, + FLAG_IGNORE_LOOK = 1 << 23 }; enum slotsOTB_t{ @@ -245,18 +246,25 @@ class ItemType { ItemType(); ~ItemType(); - bool isGroundTile() const {return (group == ITEM_GROUP_GROUND);} - bool isSplash() const {return (group == ITEM_GROUP_SPLASH);} - bool isFluidContainer() const {return (group == ITEM_GROUP_FLUID);} - bool isContainer() const {return (type == ITEM_TYPE_CONTAINER);} - bool isDoor() const {return (type == ITEM_TYPE_DOOR);} - bool isClientCharged() const {return client_chargeable;} - bool isExtraCharged() const {return !client_chargeable && extra_chargeable;} - bool isTeleport() const {return (type == ITEM_TYPE_TELEPORT);} - bool isMagicField() const {return (type == ITEM_TYPE_MAGICFIELD);} - bool isStackable() const {return stackable;} - bool isDepot() const {return (type == ITEM_TYPE_DEPOT);} - bool isMetaItem() const {return is_metaitem;} + bool isGroundTile() const { return (group == ITEM_GROUP_GROUND); } + bool isSplash() const { return (group == ITEM_GROUP_SPLASH); } + bool isFluidContainer() const { return (group == ITEM_GROUP_FLUID); } + + bool isClientCharged() const { return client_chargeable; } + bool isExtraCharged() const { return !client_chargeable && extra_chargeable; } + + bool isDepot() const { return (type == ITEM_TYPE_DEPOT); } + bool isMailbox() const { return (type == ITEM_TYPE_MAILBOX); } + bool isTrashHolder() const { return (type == ITEM_TYPE_TRASHHOLDER); } + bool isContainer() const { return (type == ITEM_TYPE_CONTAINER); } + bool isDoor() const { return (type == ITEM_TYPE_DOOR); } + bool isMagicField() const { return (type == ITEM_TYPE_MAGICFIELD); } + bool isTeleport() const { return (type == ITEM_TYPE_TELEPORT); } + bool isBed() const { return (type == ITEM_TYPE_BED); } + bool isKey() const { return (type == ITEM_TYPE_KEY); } + + bool isStackable() const { return stackable; } + bool isMetaItem() const { return is_metaitem; } GameSprite* sprite; uint16_t id; @@ -274,66 +282,69 @@ class ItemType { ItemGroup_t group; ItemTypes_t type; - uint16_t volume; - uint16_t maxTextLen; - //uint16_t writeOnceItemId; - uint16_t ground_equivalent; - uint32_t border_group; - bool has_equivalent; // True if any item has this as ground_equivalent - bool wall_hate_me; // (For wallbrushes, regard this as not part of the wall) + uint16_t volume; + uint16_t maxTextLen; + //uint16_t writeOnceItemId; + uint16_t ground_equivalent; + uint32_t border_group; + bool has_equivalent; // True if any item has this as ground_equivalent + bool wall_hate_me; // (For wallbrushes, regard this as not part of the wall) - std::string name; - std::string editorsuffix; - std::string description; + std::string name; + std::string editorsuffix; + std::string description; - float weight; + float weight; // It might be useful to be able to extrapolate this information in the future - int attack; - int defense; - int armor; - uint32_t charges; - bool client_chargeable; - bool extra_chargeable; - - bool isVertical; - bool isHorizontal; - bool isHangable; - bool canReadText; - bool canWriteText; - bool allowDistRead; - bool replaceable; - bool decays; - - bool stackable; - bool moveable; - bool alwaysOnBottom; - bool pickupable; - bool rotable; - bool isBorder; - bool isOptionalBorder; - bool isWall; - bool isBrushDoor; - bool isOpen; - bool isTable; - bool isCarpet; - - bool floorChangeDown; - bool floorChangeNorth; - bool floorChangeSouth; - bool floorChangeEast; - bool floorChangeWest; - - bool blockSolid; - bool blockPickupable; - bool blockProjectile; - bool blockPathFind; - - int alwaysOnTopOrder; - int rotateTo; - BorderType border_alignment; + int attack; + int defense; + int armor; + uint32_t charges; + bool client_chargeable; + bool extra_chargeable; + bool ignoreLook; + + bool isHangable; + bool hookEast; + bool hookSouth; + bool canReadText; + bool canWriteText; + bool allowDistRead; + bool replaceable; + bool decays; + + bool stackable; + bool moveable; + bool alwaysOnBottom; + bool pickupable; + bool rotable; + bool isBorder; + bool isOptionalBorder; + bool isWall; + bool isBrushDoor; + bool isOpen; + bool isTable; + bool isCarpet; + + bool floorChangeDown; + bool floorChangeNorth; + bool floorChangeSouth; + bool floorChangeEast; + bool floorChangeWest; + + bool unpassable; + bool blockPickupable; + bool blockMissiles; + bool blockPathfinder; + bool hasElevation; + + int alwaysOnTopOrder; + int rotateTo; + BorderType border_alignment; }; -class ItemDatabase { +class ItemDatabase +{ public: ItemDatabase(); ~ItemDatabase(); @@ -369,13 +380,13 @@ class ItemDatabase { protected: // Count of GameSprite types - int32_t item_count; - int32_t effect_count; - int32_t monster_count; - int32_t distance_count; + uint16_t item_count; + uint16_t effect_count; + uint16_t monster_count; + uint16_t distance_count; - int32_t minclientID; - int32_t maxclientID; + uint16_t minclientID; + uint16_t maxclientID; uint16_t max_item_id; friend class GameSprite; diff --git a/source/main_menubar.cpp b/source/main_menubar.cpp index f70c043a..a20c3a8a 100644 --- a/source/main_menubar.cpp +++ b/source/main_menubar.cpp @@ -27,6 +27,8 @@ #include "dat_debug_view.h" #include "result_window.h" #include "extension_window.h" +#include "find_item_window.h" +#include "settings.h" #include "gui.h" @@ -836,17 +838,18 @@ void MainMenuBar::OnSearchForItem(wxCommandEvent& WXUNUSED(event)) if(!g_gui.IsEditorOpen()) return; - FindItemDialog finder(frame, "Search for Item"); - if(finder.ShowModal() != 0) { - OnSearchForItem::Finder func(finder.getResultID()); + FindItemDialog dialog(frame, "Search for Item"); + dialog.setSearchMode((FindItemDialog::SearchMode)g_settings.getInteger(Config::FIND_ITEM_MODE)); + if(dialog.ShowModal() == wxID_OK) { + OnSearchForItem::Finder finder(dialog.getResultID()); g_gui.CreateLoadBar("Searching map..."); - foreach_ItemOnMap(g_gui.GetCurrentMap(), func, false); - std::vector >& found = func.found; + foreach_ItemOnMap(g_gui.GetCurrentMap(), finder, false); + std::vector >& found = finder.found; g_gui.DestroyLoadBar(); - if(func.more_than_value) { + if(finder.more_than_value) { wxString msg; msg << "Only the first " << size_t(g_settings.getInteger(Config::REPLACE_SIZE)) << " results will be displayed."; g_gui.PopupDialog("Notice", msg, wxOK); @@ -859,7 +862,10 @@ void MainMenuBar::OnSearchForItem(wxCommandEvent& WXUNUSED(event)) Item* item = iter->second; result->AddPosition(wxstr(item->getName()), tile->getPosition()); } + + g_settings.setInteger(Config::FIND_ITEM_MODE, (int)dialog.getSearchMode()); } + dialog.Destroy(); } void MainMenuBar::OnReplaceItem(wxCommandEvent& WXUNUSED(event)) { @@ -868,7 +874,7 @@ void MainMenuBar::OnReplaceItem(wxCommandEvent& WXUNUSED(event)) ReplaceItemDialog dlg(frame, "Replace Item"); - if(dlg.ShowModal() != 0) { + if(dlg.ShowModal() == wxID_OK) { uint16_t find_id = dlg.GetResultFindID(); uint16_t with_id = dlg.GetResultWithID(); @@ -1144,17 +1150,16 @@ void MainMenuBar::OnJumpToItemBrush(wxCommandEvent& WXUNUSED(event)) return; // Create the jump to dialog - FindDialog* dlg = newd FindItemDialog(frame); - - // Display dialog to user - dlg->ShowModal(); - - // Retrieve result, if null user canceled - const Brush* brush = dlg->getResult(); - if(brush) { - g_gui.SelectBrush(brush, TILESET_RAW); + FindItemDialog dialog(frame, "Jump to Item"); + dialog.setSearchMode((FindItemDialog::SearchMode)g_settings.getInteger(Config::JUMP_TO_ITEM_MODE)); + if(dialog.ShowModal() == wxID_OK) { + // Retrieve result, if null user canceled + const Brush* brush = dialog.getResult(); + if(brush) + g_gui.SelectBrush(brush, TILESET_RAW); + g_settings.setInteger(Config::JUMP_TO_ITEM_MODE, (int)dialog.getSearchMode()); } - delete dlg; + dialog.Destroy(); } void MainMenuBar::OnGotoPreviousPosition(wxCommandEvent& WXUNUSED(event)) @@ -1195,18 +1200,17 @@ void MainMenuBar::OnMapRemoveItems(wxCommandEvent& WXUNUSED(event)) if(!g_gui.IsEditorOpen()) return; - FindItemDialog finder(frame, "Item Type to Remove"); - finder.ShowModal(); - uint16_t itemid = finder.getResultID(); + FindItemDialog dialog(frame, "Item Type to Remove"); + if(dialog.ShowModal() == wxID_OK) { + uint16_t itemid = dialog.getResultID(); - if(itemid != 0) { g_gui.GetCurrentEditor()->selection.clear(); g_gui.GetCurrentEditor()->actionQueue->clear(); - OnMapRemoveItems::condition func(itemid); + OnMapRemoveItems::condition finder(itemid); g_gui.CreateLoadBar("Searching map for items to remove..."); - long long removed = remove_if_ItemOnMap(g_gui.GetCurrentMap(), func); + long long removed = remove_if_ItemOnMap(g_gui.GetCurrentMap(), finder); g_gui.DestroyLoadBar(); @@ -1217,6 +1221,7 @@ void MainMenuBar::OnMapRemoveItems(wxCommandEvent& WXUNUSED(event)) g_gui.GetCurrentMap().doChange(); } + dialog.Destroy(); } namespace OnMapRemoveCorpses diff --git a/source/map_drawer.cpp b/source/map_drawer.cpp index 665cca8e..d21391e9 100644 --- a/source/map_drawer.cpp +++ b/source/map_drawer.cpp @@ -1063,9 +1063,9 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Tile* tile, const Item* if(it.isSplash() || it.isFluidContainer()) { subtype = item->getSubtype(); } else if(it.isHangable) { - if(tile->hasProperty(ISVERTICAL)) { + if(tile->hasProperty(HOOK_SOUTH)) { pattern_x = 2; - } else if(tile->hasProperty(ISHORIZONTAL)) { + } else if(tile->hasProperty(HOOK_EAST)) { pattern_x = 1; } else { pattern_x = -0; @@ -1163,9 +1163,9 @@ void MapDrawer::BlitItem(int& draw_x, int& draw_y, const Position& pos, const It } else if(it.isHangable) { pattern_x = 0; /* - if(tile->hasProperty(ISVERTICAL)) { + if(tile->hasProperty(HOOK_SOUTH)) { pattern_x = 2; - } else if(tile->hasProperty(ISHORIZONTAL)) { + } else if(tile->hasProperty(HOOK_EAST)) { pattern_x = 1; } else { pattern_x = -0; diff --git a/source/settings.cpp b/source/settings.cpp index e369d80c..91992907 100644 --- a/source/settings.cpp +++ b/source/settings.cpp @@ -318,6 +318,9 @@ void Settings::IO(IOMode mode) String(RECENT_EDITED_MAP_PATH, ""); String(RECENT_EDITED_MAP_POSITION, ""); + Int(FIND_ITEM_MODE, 0); + Int(JUMP_TO_ITEM_MODE, 0); + #undef section #undef Int #undef IntToSave diff --git a/source/settings.h b/source/settings.h index 7f17db74..b4a353b2 100644 --- a/source/settings.h +++ b/source/settings.h @@ -135,6 +135,9 @@ namespace Config { RECENT_EDITED_MAP_PATH, RECENT_EDITED_MAP_POSITION, + FIND_ITEM_MODE, + JUMP_TO_ITEM_MODE, + LAST, }; } diff --git a/source/tile.cpp b/source/tile.cpp index c6254f8f..4b8214e8 100644 --- a/source/tile.cpp +++ b/source/tile.cpp @@ -407,7 +407,7 @@ void Tile::update() } ItemType& it = g_items[i->getID()]; - if(it.blockSolid) { + if(it.unpassable) { statflags |= TILESTATE_BLOCKING; } if(it.isOptionalBorder) { diff --git a/vcproj/Project/RME.vcxproj b/vcproj/Project/RME.vcxproj index 259e1b7d..f96a0ab5 100644 --- a/vcproj/Project/RME.vcxproj +++ b/vcproj/Project/RME.vcxproj @@ -293,6 +293,7 @@ + @@ -481,6 +482,7 @@ + diff --git a/vcproj/Project/RME.vcxproj.filters b/vcproj/Project/RME.vcxproj.filters index af3c04b8..756cb64b 100644 --- a/vcproj/Project/RME.vcxproj.filters +++ b/vcproj/Project/RME.vcxproj.filters @@ -76,7 +76,7 @@ common - + common @@ -356,9 +356,12 @@ gui\dialogs - + gui\controls + + gui\dialogs + @@ -624,9 +627,12 @@ gui\dialogs - + gui\controls + + gui\dialogs +