From 1b832929b2a655cceb2279d68de98df75f9a7c36 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 10 Jul 2020 16:34:42 -0400 Subject: [PATCH] Enforce limit for object events --- CHANGELOG.md | 1 + docsrc/manual/project-files.rst | 1 + include/editor.h | 1 + include/project.h | 2 ++ src/editor.cpp | 28 +++++++++++++++++++++++----- src/mainwindow.cpp | 19 +++++++++++++++---- src/project.cpp | 28 ++++++++++++++++++++++++++++ 7 files changed, 71 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3ab4ee7..6598de65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d ### Changed - The tileset editor now syncs its metatile selection with the map's metatile selector. +- The number of object events per map is now limited to OBJECT_EVENT_TEMPLATES_COUNT ### Fixed - Fix a crash that occured when creating a new tileset using triple layer mode. diff --git a/docsrc/manual/project-files.rst b/docsrc/manual/project-files.rst index 92201854..7d1d85c6 100644 --- a/docsrc/manual/project-files.rst +++ b/docsrc/manual/project-files.rst @@ -26,6 +26,7 @@ to a file, it probably is not a good idea to edit yourself unless otherwise note src/data/graphics/pokemon.h, yes, no, for pokemon sprite icons src/data/heal_locations.h, yes, yes, src/data/region_map/region_map_entries.h, yes, yes, + include/constants/global.h, yes, no, include/constants/map_groups.h, no, yes, include/constants/items.h, yes, no, include/constants/flags.h, yes, no, diff --git a/include/editor.h b/include/editor.h index ba54e917..b6e60585 100644 --- a/include/editor.h +++ b/include/editor.h @@ -170,6 +170,7 @@ private: Event* createNewSecretBaseEvent(); QString getMovementPermissionText(uint16_t collision, uint16_t elevation); QString getMetatileDisplayMessage(uint16_t metatileId); + bool eventLimitReached(Map *, QString); private slots: void onMapStartPaint(QGraphicsSceneMouseEvent *event, MapPixmapItem *item); diff --git a/include/project.h b/include/project.h index 4b584250..179a5a93 100644 --- a/include/project.h +++ b/include/project.h @@ -192,6 +192,7 @@ public: static int getMapDataSize(int width, int height); static bool mapDimensionsValid(int width, int height); bool calculateDefaultMapSize(); + static int getMaxObjectEvents(); private: void updateMapLayout(Map*); @@ -213,6 +214,7 @@ private: static int num_pals_total; static int max_map_data_size; static int default_map_size; + static int max_object_events; QWidget *parent; diff --git a/src/editor.cpp b/src/editor.cpp index 1e303f02..adbff955 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -1887,18 +1887,26 @@ void Editor::duplicateSelectedEvents() { QList *duplicates = new QList; for (int i = 0; i < selected_events->length(); i++) { - Event *duplicate = new Event(*selected_events->at(i)->event); + Event *original = selected_events->at(i)->event; + QString eventType = original->get("event_type"); + if (eventLimitReached(map, eventType)) { + logWarn(QString("Skipping duplication, the map limit for events of type '%1' has been reached.").arg(eventType)); + continue; + } + Event *duplicate = new Event(*original); map->addEvent(duplicate); DraggablePixmapItem *object = addMapEvent(duplicate); duplicates->append(object); } - selected_events->clear(); - selected_events = duplicates; - updateSelectedEvents(); + if (duplicates->length()) { + selected_events->clear(); + selected_events = duplicates; + updateSelectedEvents(); + } } DraggablePixmapItem* Editor::addNewEvent(QString event_type) { - if (project && map && !event_type.isEmpty()) { + if (project && map && !event_type.isEmpty() && !eventLimitReached(map, event_type)) { Event *event = Event::createNewEvent(event_type, map->name, project); event->put("map_name", map->name); if (event_type == EventType::HealLocation) { @@ -1914,6 +1922,16 @@ DraggablePixmapItem* Editor::addNewEvent(QString event_type) { return nullptr; } +// Currently only object events have an explicit limit +bool Editor::eventLimitReached(Map *map, QString event_type) +{ + if (project && map && !event_type.isEmpty()) { + if (event_type == EventType::Object) + return map->events.value("object_event_group").length() >= project->getMaxObjectEvents(); + } + return false; +} + void Editor::deleteEvent(Event *event) { Map *map = project->getMap(event->get("map_name")); if (map) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index af8fe381..9a616e58 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -980,7 +980,7 @@ void MainWindow::onNewMapCreated() { setMap(newMapName, true); if (newMap->isFlyable == "TRUE") { - addNewEvent("event_heal_location"); + addNewEvent(EventType::HealLocation); editor->project->saveHealLocationStruct(newMap); editor->save();// required } @@ -1413,11 +1413,22 @@ void MainWindow::resetMapViewScale() { void MainWindow::addNewEvent(QString event_type) { - if (editor) { + if (editor && editor->project) { DraggablePixmapItem *object = editor->addNewEvent(event_type); - updateObjects(); if (object) { + updateObjects(); editor->selectMapEvent(object, false); + } else { + QMessageBox msgBox(this); + msgBox.setText("Failed to add new event"); + if (event_type == EventType::Object) { + msgBox.setInformativeText(QString("The limit for object events (%1) has been reached.\n\n" + "This limit can be adjusted with OBJECT_EVENT_TEMPLATES_COUNT in 'include/constants/global.h'.") + .arg(editor->project->getMaxObjectEvents())); + } + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Icon::Warning); + msgBox.exec(); } } } @@ -1534,7 +1545,7 @@ void MainWindow::updateSelectedObjects() { QString event_group_type = item->event->get("event_group_type"); QString map_name = item->event->get("map_name"); int event_offs; - if (event_type == "event_warp") { event_offs = 0; } + if (event_type == EventType::Warp) { event_offs = 0; } else { event_offs = 1; } frame->ui->label_name->setText(QString("%1 Id").arg(event_type)); diff --git a/src/project.cpp b/src/project.cpp index e22222c4..cf8fdc6b 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -35,6 +35,7 @@ int Project::num_pals_primary = 6; int Project::num_pals_total = 13; int Project::max_map_data_size = 10240; // 0x2800 int Project::default_map_size = 20; +int Project::max_object_events = 64; Project::Project(QWidget *parent) : parent(parent) { @@ -2365,6 +2366,28 @@ bool Project::readMiscellaneousConstants() { miscConstants.insert("max_level_define", pokemonDefines.value("MAX_LEVEL") > pokemonDefines.value("MIN_LEVEL") ? pokemonDefines.value("MAX_LEVEL") : 100); miscConstants.insert("min_level_define", pokemonDefines.value("MIN_LEVEL") < pokemonDefines.value("MAX_LEVEL") ? pokemonDefines.value("MIN_LEVEL") : 1); } + + QString filename = "include/constants/global.h"; + fileWatcher.addPath(root + "/" + filename); + QStringList definePrefixes; + definePrefixes << "OBJECT_"; + QMap defines = parser.readCDefines(filename, definePrefixes); + + auto it = defines.find("OBJECT_EVENT_TEMPLATES_COUNT"); + if (it != defines.end()) { + if (it.value() > 0) { + Project::max_object_events = it.value(); + } else { + logWarn(QString("Value for 'OBJECT_EVENT_TEMPLATES_COUNT' is %1, must be greater than 0. Using default (%2) instead.") + .arg(it.value()) + .arg(Project::max_object_events)); + } + } + else { + logWarn(QString("Value for 'OBJECT_EVENT_TEMPLATES_COUNT' not found. Using default (%1) instead.") + .arg(Project::max_object_events)); + } + return true; } @@ -2583,3 +2606,8 @@ bool Project::calculateDefaultMapSize(){ } return true; } + +int Project::getMaxObjectEvents() +{ + return Project::max_object_events; +}