From a906783f6864753cf3d848f67b6083e543cb3527 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 7 May 2025 12:17:09 -0400 Subject: [PATCH] Remove last MAP_ prefix requirement --- include/project.h | 1 + src/mainwindow.cpp | 19 ++++++++++++------- src/project.cpp | 37 +++++++++++++++++++++++++++++++------ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/include/project.h b/include/project.h index 6f981a85..8b739858 100644 --- a/include/project.h +++ b/include/project.h @@ -115,6 +115,7 @@ public: QString getMapConstant(const QString &mapName, const QString &defaultValue = QString()) const; QString getMapLayoutId(const QString &mapName, const QString &defaultValue = QString()) const; QString getMapLocation(const QString &mapName, const QString &defaultValue = QString()) const; + QString secretBaseIdToMapName(const QString &secretBaseId) const; struct NewMapSettings { QString name; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 4e7e5238..ee792d5d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1135,24 +1135,29 @@ void MainWindow::openEventMap(Event *sourceEvent) { Event::Type eventType = sourceEvent->getEventType(); if (eventType == Event::Type::Warp) { // Warp events open to their destination warp event. - WarpEvent *warp = dynamic_cast(sourceEvent); + auto warp = dynamic_cast(sourceEvent); targetMapName = warp->getDestinationMap(); targetEventIdName = warp->getDestinationWarpID(); targetEventGroup = Event::Group::Warp; } else if (eventType == Event::Type::CloneObject) { // Clone object events open to their target object event. - CloneObjectEvent *clone = dynamic_cast(sourceEvent); + auto clone = dynamic_cast(sourceEvent); targetMapName = clone->getTargetMap(); targetEventIdName = clone->getTargetID(); targetEventGroup = Event::Group::Object; } else if (eventType == Event::Type::SecretBase) { // Secret Bases open to their secret base entrance - const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix); - SecretBaseEvent *base = dynamic_cast(sourceEvent); + auto base = dynamic_cast(sourceEvent); // Extract the map name from the secret base ID. QString baseId = base->getBaseID(); - targetMapName = this->editor->project->mapConstantsToMapNames.value(mapPrefix + baseId.left(baseId.lastIndexOf("_"))); + if (baseId.isEmpty()) + return; + targetMapName = this->editor->project->secretBaseIdToMapName(baseId); + if (targetMapName.isEmpty()) { + WarningMessage::show(QString("Failed to determine which map '%1' refers to.").arg(baseId), this); + return; + } // Just select the first warp. Normally the only warp event on every secret base map is the entrance/exit, so this is usually correct. // The warp IDs for secret bases are specified in the project's C code, not in the map data, so we don't have an easy way to read the actual IDs. @@ -1160,7 +1165,7 @@ void MainWindow::openEventMap(Event *sourceEvent) { targetEventGroup = Event::Group::Warp; } else if (eventType == Event::Type::HealLocation && projectConfig.healLocationRespawnDataEnabled) { // Heal location events open to their respawn NPC - HealLocationEvent *heal = dynamic_cast(sourceEvent); + auto heal = dynamic_cast(sourceEvent); targetMapName = heal->getRespawnMapName(); targetEventIdName = heal->getRespawnNPC(); targetEventGroup = Event::Group::Object; @@ -1168,7 +1173,7 @@ void MainWindow::openEventMap(Event *sourceEvent) { // Other event types have no target map to open. return; } - if (!userSetMap(targetMapName)) + if (targetMapName.isEmpty() || !userSetMap(targetMapName)) return; // Map opened successfully, now try to select the targeted event on that map. diff --git a/src/project.cpp b/src/project.cpp index f378cfcb..ab22de36 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1975,12 +1975,6 @@ bool Project::readMapGroups() { failedMapNames.append(mapName); continue; } - const QString expectedPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix); - if (!mapConstant.startsWith(expectedPrefix)) { - logWarn(QString("Map '%1' has invalid \"id\" value '%2' and will be ignored. Value must begin with '%3'.").arg(mapName).arg(mapConstant).arg(expectedPrefix)); - failedMapNames.append(mapName); - continue; - } auto it = this->mapConstantsToMapNames.constFind(mapConstant); if (it != this->mapConstantsToMapNames.constEnd()) { logWarn(QString("Map '%1' has the same \"id\" value '%2' as map '%3' and will be ignored.").arg(mapName).arg(it.key()).arg(it.value())); @@ -2081,6 +2075,37 @@ QString Project::getMapLocation(const QString &mapName, const QString &defaultVa return map ? map->header()->location() : defaultValue; } +// Determining which map a secret base ID refers to relies on assumptions about its name. +// The default format is for a secret base ID of 'SECRET_BASE_FOO_#' to refer to a map with the constant +// 'MAP_SECRET_BASE_FOO', so we strip the `_#` suffix and add the default map prefix 'MAP_'. If this fails, +// we'll try every combination of that prefix, suffix, and 'SECRET_BASE_FOO'. +QString Project::secretBaseIdToMapName(const QString &secretBaseId) const { + const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix); + QString baseIdNoSuffix = secretBaseId.left(secretBaseId.lastIndexOf("_")); + + auto it = this->mapConstantsToMapNames.constFind(mapPrefix + baseIdNoSuffix); + if (it != this->mapConstantsToMapNames.constEnd()) { + // Found a result of the format 'SECRET_BASE_FOO_#' -> 'MAP_SECRET_BASE_FOO'. + return it.value(); + } + it = this->mapConstantsToMapNames.constFind(baseIdNoSuffix); + if (it != this->mapConstantsToMapNames.constEnd()) { + // Found a result of the format 'SECRET_BASE_FOO_#' -> 'SECRET_BASE_FOO'. + return it.value(); + } + it = this->mapConstantsToMapNames.constFind(mapPrefix + secretBaseId); + if (it != this->mapConstantsToMapNames.constEnd()) { + // Found a result of the format 'SECRET_BASE_FOO_#' -> 'MAP_SECRET_BASE_FOO_#'. + return it.value(); + } + it = this->mapConstantsToMapNames.constFind(secretBaseId); + if (it != this->mapConstantsToMapNames.constEnd()) { + // 'SECRET_BASE_FOO_#' is already a map constant. + return it.value(); + } + return QString(); +} + // When we ask the user to provide a new identifier for something (like a map name or MAPSEC id) // we use this to make sure that it doesn't collide with any known identifiers first. // Porymap knows of many more identifiers than this, but for simplicity we only check the lists that users can add to via Porymap.