Add identifier config settings
This commit is contained in:
parent
bfb827b736
commit
6d995cee9b
20 changed files with 439 additions and 213 deletions
|
@ -170,6 +170,61 @@ enum BaseGameVersion {
|
|||
pokeemerald,
|
||||
};
|
||||
|
||||
enum ProjectIdentifier {
|
||||
symbol_facing_directions,
|
||||
symbol_obj_event_gfx_pointers,
|
||||
symbol_pokemon_icon_table,
|
||||
symbol_wild_encounters,
|
||||
symbol_heal_locations,
|
||||
symbol_spawn_points,
|
||||
symbol_spawn_maps,
|
||||
symbol_spawn_npcs,
|
||||
symbol_attribute_table,
|
||||
symbol_tilesets_prefix,
|
||||
define_obj_event_count,
|
||||
define_min_level,
|
||||
define_max_level,
|
||||
define_tiles_primary,
|
||||
define_tiles_total,
|
||||
define_metatiles_primary,
|
||||
define_pals_primary,
|
||||
define_pals_total,
|
||||
define_map_size,
|
||||
define_mask_metatile,
|
||||
define_mask_collision,
|
||||
define_mask_elevation,
|
||||
define_mask_behavior,
|
||||
define_mask_layer,
|
||||
define_attribute_behavior,
|
||||
define_attribute_layer,
|
||||
define_attribute_terrain,
|
||||
define_attribute_encounter,
|
||||
define_metatile_label_prefix,
|
||||
define_heal_locations_prefix,
|
||||
define_spawn_prefix,
|
||||
define_map_prefix,
|
||||
define_map_dynamic,
|
||||
define_map_empty,
|
||||
define_map_section_prefix,
|
||||
define_map_section_empty,
|
||||
define_map_section_count,
|
||||
regex_behaviors,
|
||||
regex_obj_event_gfx,
|
||||
regex_items,
|
||||
regex_flags,
|
||||
regex_vars,
|
||||
regex_movement_types,
|
||||
regex_map_types,
|
||||
regex_battle_scenes,
|
||||
regex_weather,
|
||||
regex_coord_event_weather,
|
||||
regex_secret_bases,
|
||||
regex_sign_facing_directions,
|
||||
regex_trainer_types,
|
||||
regex_music,
|
||||
regex_species,
|
||||
};
|
||||
|
||||
enum ProjectFilePath {
|
||||
data_map_folders,
|
||||
data_scripts_folders,
|
||||
|
@ -250,11 +305,12 @@ public:
|
|||
this->blockElevationMask = 0xF000;
|
||||
this->warpBehaviors = defaultWarpBehaviors;
|
||||
this->warpBehaviorWarningDisabled = false;
|
||||
this->identifiers.clear();
|
||||
this->readKeys.clear();
|
||||
}
|
||||
static const QMap<ProjectIdentifier, QPair<QString, QString>> defaultIdentifiers;
|
||||
static const QMap<ProjectFilePath, std::pair<QString, QString>> defaultPaths;
|
||||
static const QStringList versionStrings;
|
||||
static const QStringList defaultWarpBehaviors;
|
||||
void reset(BaseGameVersion baseGameVersion);
|
||||
void setBaseGameVersion(BaseGameVersion baseGameVersion);
|
||||
BaseGameVersion getBaseGameVersion();
|
||||
|
@ -299,10 +355,16 @@ public:
|
|||
QString getDefaultSecondaryTileset();
|
||||
void setDefaultPrimaryTileset(QString tilesetName);
|
||||
void setDefaultSecondaryTileset(QString tilesetName);
|
||||
void setFilePath(QString pathId, QString path);
|
||||
void setFilePath(ProjectFilePath pathId, QString path);
|
||||
QString getFilePath(QString defaultPath, bool customOnly = false);
|
||||
QString getFilePath(ProjectFilePath pathId, bool customOnly = false);
|
||||
void setFilePath(const QString &pathId, const QString &path);
|
||||
void setFilePath(ProjectFilePath pathId, const QString &path);
|
||||
QString getCustomFilePath(ProjectFilePath pathId);
|
||||
QString getCustomFilePath(const QString &pathId);
|
||||
QString getFilePath(ProjectFilePath pathId);
|
||||
void setIdentifier(ProjectIdentifier id, const QString &text);
|
||||
void setIdentifier(const QString &id, const QString &text);
|
||||
QString getCustomIdentifier(ProjectIdentifier id);
|
||||
QString getCustomIdentifier(const QString &id);
|
||||
QString getIdentifier(ProjectIdentifier id);
|
||||
void setPrefabFilepath(QString filepath);
|
||||
QString getPrefabFilepath();
|
||||
void setPrefabImportPrompted(bool prompted);
|
||||
|
@ -345,18 +407,6 @@ public:
|
|||
void setWarpBehaviorWarningDisabled(bool disabled);
|
||||
bool getWarpBehaviorWarningDisabled();
|
||||
|
||||
// TODO: Replace these once there's generic support for editing project names
|
||||
static const QString metatileIdMaskName;
|
||||
static const QString collisionMaskName;
|
||||
static const QString elevationMaskName;
|
||||
static const QString behaviorMaskName;
|
||||
static const QString layerTypeMaskName;
|
||||
static const QString behaviorTableName;
|
||||
static const QString layerTypeTableName;
|
||||
static const QString terrainTypeTableName;
|
||||
static const QString encounterTypeTableName;
|
||||
static const QString attrTableName;
|
||||
|
||||
protected:
|
||||
virtual QString getConfigFilepath() override;
|
||||
virtual void parseConfigKeyValue(QString key, QString value) override;
|
||||
|
@ -364,8 +414,11 @@ protected:
|
|||
virtual void onNewConfigFileCreated() override;
|
||||
virtual void setUnreadKeys() override;
|
||||
private:
|
||||
static const QStringList defaultWarpBehaviors;
|
||||
|
||||
BaseGameVersion baseGameVersion;
|
||||
QString projectDir;
|
||||
QMap<ProjectIdentifier, QString> identifiers;
|
||||
QMap<ProjectFilePath, QString> filePaths;
|
||||
bool usePoryScript;
|
||||
bool useCustomBorderSize;
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
QList<int> metatileLayerOrder;
|
||||
QList<float> metatileLayerOpacity;
|
||||
void setName(QString mapName);
|
||||
static QString mapConstantFromName(QString mapName);
|
||||
static QString mapConstantFromName(QString mapName, bool includePrefix = true);
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
int getBorderWidth();
|
||||
|
|
|
@ -54,8 +54,8 @@ public:
|
|||
QString readCIncbin(const QString &text, const QString &label);
|
||||
QMap<QString, QString> readCIncbinMulti(const QString &filepath);
|
||||
QStringList readCIncbinArray(const QString &filename, const QString &label);
|
||||
QMap<QString, int> readCDefinesByPrefix(const QString &filename, const QStringList &prefixes);
|
||||
QMap<QString, int> readCDefinesByName(const QString &filename, const QStringList &defineNames);
|
||||
QMap<QString, int> readCDefinesByPrefix(const QString &filename, QStringList prefixes);
|
||||
QMap<QString, int> readCDefinesByName(const QString &filename, QStringList names);
|
||||
QStringList readCDefineNames(const QString&, const QStringList&);
|
||||
QMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { });
|
||||
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
|
||||
|
|
|
@ -21,7 +21,10 @@ class Project;
|
|||
|
||||
struct LayoutSquare
|
||||
{
|
||||
LayoutSquare() : map_section("MAPSEC_NONE"), x(-1), y(-1), has_map(false) {}
|
||||
LayoutSquare() : x(-1), y(-1), has_map(false) {
|
||||
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix);
|
||||
map_section = prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty);
|
||||
}
|
||||
QString map_section;
|
||||
int x;
|
||||
int y;
|
||||
|
@ -144,6 +147,10 @@ public:
|
|||
|
||||
void emitDisplay();
|
||||
|
||||
const QString section_prefix;
|
||||
const QString default_map_section;
|
||||
const QString count_map_section;
|
||||
|
||||
signals:
|
||||
void mapNeedsDisplaying();
|
||||
|
||||
|
|
|
@ -26,8 +26,7 @@ struct EventGraphics
|
|||
bool inanimate;
|
||||
};
|
||||
|
||||
// The constant and displayed name of the special map value used by warps with multiple potential destinations
|
||||
static QString DYNAMIC_MAP_CONSTANT = "MAP_DYNAMIC";
|
||||
// The displayed name of the special map value used by warps with multiple potential destinations
|
||||
static QString DYNAMIC_MAP_NAME = "Dynamic";
|
||||
|
||||
class Project : public QObject
|
||||
|
@ -215,7 +214,7 @@ public:
|
|||
|
||||
QString getDefaultPrimaryTilesetLabel();
|
||||
QString getDefaultSecondaryTilesetLabel();
|
||||
|
||||
QString getDynamicMapDefineName();
|
||||
void updateTilesetMetatileLabels(Tileset *tileset);
|
||||
QString buildMetatileLabelsText(const QMap<QString, int> defines);
|
||||
QString findMetatileLabelsTileset(QString label);
|
||||
|
@ -248,6 +247,7 @@ private:
|
|||
|
||||
void saveHealLocationsData(Map *map);
|
||||
void saveHealLocationsConstants();
|
||||
QString getHealLocationsTableName();
|
||||
|
||||
void ignoreWatchedFileTemporarily(QString filepath);
|
||||
|
||||
|
|
135
src/config.cpp
135
src/config.cpp
|
@ -47,16 +47,64 @@ const QStringList ProjectConfig::defaultWarpBehaviors = {
|
|||
"MB_BRIDGE_OVER_OCEAN",
|
||||
};
|
||||
|
||||
const QString ProjectConfig::metatileIdMaskName = "MAPGRID_METATILE_ID_MASK";
|
||||
const QString ProjectConfig::collisionMaskName = "MAPGRID_COLLISION_MASK";
|
||||
const QString ProjectConfig::elevationMaskName = "MAPGRID_ELEVATION_MASK";
|
||||
const QString ProjectConfig::behaviorMaskName = "METATILE_ATTR_BEHAVIOR_MASK";
|
||||
const QString ProjectConfig::layerTypeMaskName = "METATILE_ATTR_LAYER_MASK";
|
||||
const QString ProjectConfig::behaviorTableName = "METATILE_ATTRIBUTE_BEHAVIOR";
|
||||
const QString ProjectConfig::layerTypeTableName = "METATILE_ATTRIBUTE_LAYER_TYPE";
|
||||
const QString ProjectConfig::terrainTypeTableName = "METATILE_ATTRIBUTE_TERRAIN";
|
||||
const QString ProjectConfig::encounterTypeTableName = "METATILE_ATTRIBUTE_ENCOUNTER_TYPE";
|
||||
const QString ProjectConfig::attrTableName = "sMetatileAttrMasks";
|
||||
// TODO: symbol_wild_encounters should ultimately be removed from the table below. We can determine this name when we read the project.
|
||||
const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIdentifiers = {
|
||||
// Symbols
|
||||
{ProjectIdentifier::symbol_facing_directions, {"symbol_facing_directions", "gInitialMovementTypeFacingDirections"}},
|
||||
{ProjectIdentifier::symbol_obj_event_gfx_pointers, {"symbol_obj_event_gfx_pointers", "gObjectEventGraphicsInfoPointers"}},
|
||||
{ProjectIdentifier::symbol_pokemon_icon_table, {"symbol_pokemon_icon_table", "gMonIconTable"}},
|
||||
{ProjectIdentifier::symbol_wild_encounters, {"symbol_wild_encounters", "gWildMonHeaders"}},
|
||||
{ProjectIdentifier::symbol_heal_locations, {"symbol_heal_locations", "sHealLocations"}},
|
||||
{ProjectIdentifier::symbol_spawn_points, {"symbol_spawn_points", "sSpawnPoints"}},
|
||||
{ProjectIdentifier::symbol_spawn_maps, {"symbol_spawn_maps", "sWhiteoutRespawnHealCenterMapIdxs"}},
|
||||
{ProjectIdentifier::symbol_spawn_npcs, {"symbol_spawn_npcs", "sWhiteoutRespawnHealerNpcIds"}},
|
||||
{ProjectIdentifier::symbol_attribute_table, {"symbol_attribute_table", "sMetatileAttrMasks"}},
|
||||
{ProjectIdentifier::symbol_tilesets_prefix, {"symbol_tilesets_prefix", "gTileset_"}},
|
||||
// Defines
|
||||
{ProjectIdentifier::define_obj_event_count, {"define_obj_event_count", "OBJECT_EVENT_TEMPLATES_COUNT"}},
|
||||
{ProjectIdentifier::define_min_level, {"define_min_level", "MIN_LEVEL"}},
|
||||
{ProjectIdentifier::define_max_level, {"define_max_level", "MAX_LEVEL"}},
|
||||
{ProjectIdentifier::define_tiles_primary, {"define_tiles_primary", "NUM_TILES_IN_PRIMARY"}},
|
||||
{ProjectIdentifier::define_tiles_total, {"define_tiles_total", "NUM_TILES_TOTAL"}},
|
||||
{ProjectIdentifier::define_metatiles_primary, {"define_metatiles_primary", "NUM_METATILES_IN_PRIMARY"}},
|
||||
{ProjectIdentifier::define_pals_primary, {"define_pals_primary", "NUM_PALS_IN_PRIMARY"}},
|
||||
{ProjectIdentifier::define_pals_total, {"define_pals_total", "NUM_PALS_TOTAL"}},
|
||||
{ProjectIdentifier::define_map_size, {"define_map_size", "MAX_MAP_DATA_SIZE"}},
|
||||
{ProjectIdentifier::define_mask_metatile, {"define_mask_metatile", "MAPGRID_METATILE_ID_MASK"}},
|
||||
{ProjectIdentifier::define_mask_collision, {"define_mask_collision", "MAPGRID_COLLISION_MASK"}},
|
||||
{ProjectIdentifier::define_mask_elevation, {"define_mask_elevation", "MAPGRID_ELEVATION_MASK"}},
|
||||
{ProjectIdentifier::define_mask_behavior, {"define_mask_behavior", "METATILE_ATTR_BEHAVIOR_MASK"}},
|
||||
{ProjectIdentifier::define_mask_layer, {"define_mask_layer", "METATILE_ATTR_LAYER_MASK"}},
|
||||
{ProjectIdentifier::define_attribute_behavior, {"define_attribute_behavior", "METATILE_ATTRIBUTE_BEHAVIOR"}},
|
||||
{ProjectIdentifier::define_attribute_layer, {"define_attribute_layer", "METATILE_ATTRIBUTE_LAYER_TYPE"}},
|
||||
{ProjectIdentifier::define_attribute_terrain, {"define_attribute_terrain", "METATILE_ATTRIBUTE_TERRAIN"}},
|
||||
{ProjectIdentifier::define_attribute_encounter, {"define_attribute_encounter", "METATILE_ATTRIBUTE_ENCOUNTER_TYPE"}},
|
||||
{ProjectIdentifier::define_metatile_label_prefix, {"define_metatile_label_prefix", "METATILE_"}},
|
||||
{ProjectIdentifier::define_heal_locations_prefix, {"define_heal_locations_prefix", "HEAL_LOCATION_"}},
|
||||
{ProjectIdentifier::define_spawn_prefix, {"define_spawn_prefix", "SPAWN_"}},
|
||||
{ProjectIdentifier::define_map_prefix, {"define_map_prefix", "MAP_"}},
|
||||
{ProjectIdentifier::define_map_dynamic, {"define_map_dynamic", "DYNAMIC"}},
|
||||
{ProjectIdentifier::define_map_empty, {"define_map_empty", "UNDEFINED"}},
|
||||
{ProjectIdentifier::define_map_section_prefix, {"define_map_section_prefix", "MAPSEC_"}},
|
||||
{ProjectIdentifier::define_map_section_empty, {"define_map_section_empty", "NONE"}},
|
||||
{ProjectIdentifier::define_map_section_count, {"define_map_section_count", "COUNT"}},
|
||||
// Regex
|
||||
{ProjectIdentifier::regex_behaviors, {"regex_behaviors", "\\bMB_"}},
|
||||
{ProjectIdentifier::regex_obj_event_gfx, {"regex_obj_event_gfx", "\\bOBJ_EVENT_GFX_"}},
|
||||
{ProjectIdentifier::regex_items, {"regex_items", "\\bITEM_(?!(B_)?USE_)"}}, // Exclude ITEM_USE_ and ITEM_B_USE_ constants
|
||||
{ProjectIdentifier::regex_flags, {"regex_flags", "\\bFLAG_"}},
|
||||
{ProjectIdentifier::regex_vars, {"regex_vars", "\\bVAR_"}},
|
||||
{ProjectIdentifier::regex_movement_types, {"regex_movement_types", "\\bMOVEMENT_TYPE_"}},
|
||||
{ProjectIdentifier::regex_map_types, {"regex_map_types", "\\bMAP_TYPE_"}},
|
||||
{ProjectIdentifier::regex_battle_scenes, {"regex_battle_scenes", "\\bMAP_BATTLE_SCENE_"}},
|
||||
{ProjectIdentifier::regex_weather, {"regex_weather", "\\bWEATHER_"}},
|
||||
{ProjectIdentifier::regex_coord_event_weather, {"regex_coord_event_weather", "\\bCOORD_EVENT_WEATHER_"}},
|
||||
{ProjectIdentifier::regex_secret_bases, {"regex_secret_bases", "\\bSECRET_BASE_[A-Za-z0-9_]*_[0-9]+"}},
|
||||
{ProjectIdentifier::regex_sign_facing_directions, {"regex_sign_facing_directions", "\\bBG_EVENT_PLAYER_FACING_"}},
|
||||
{ProjectIdentifier::regex_trainer_types, {"regex_trainer_types", "\\bTRAINER_TYPE_"}},
|
||||
{ProjectIdentifier::regex_music, {"regex_music", "\\b(SE|MUS)_"}},
|
||||
{ProjectIdentifier::regex_species, {"regex_species", "\\bSPECIES_"}},
|
||||
};
|
||||
|
||||
const QMap<ProjectFilePath, std::pair<QString, QString>> ProjectConfig::defaultPaths = {
|
||||
{ProjectFilePath::data_map_folders, { "data_map_folders", "data/maps/"}},
|
||||
|
@ -108,6 +156,13 @@ const QMap<ProjectFilePath, std::pair<QString, QString>> ProjectConfig::defaultP
|
|||
{ProjectFilePath::pokemon_gfx, { "pokemon_gfx", "graphics/pokemon/"}},
|
||||
};
|
||||
|
||||
ProjectIdentifier reverseDefaultIdentifier(QString str) {
|
||||
for (auto i = ProjectConfig::defaultIdentifiers.cbegin(), end = ProjectConfig::defaultIdentifiers.cend(); i != end; i++) {
|
||||
if (i.value().first == str) return i.key();
|
||||
}
|
||||
return static_cast<ProjectIdentifier>(-1);
|
||||
}
|
||||
|
||||
ProjectFilePath reverseDefaultPaths(QString str) {
|
||||
for (auto it = ProjectConfig::defaultPaths.constKeyValueBegin(); it != ProjectConfig::defaultPaths.constKeyValueEnd(); ++it) {
|
||||
if ((*it).second.first == str) return (*it).first;
|
||||
|
@ -751,6 +806,13 @@ void ProjectConfig::parseConfigKeyValue(QString key, QString value) {
|
|||
} else {
|
||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
||||
}
|
||||
} else if (key.startsWith("ident/")) {
|
||||
auto identifierId = reverseDefaultIdentifier(key.mid(6));
|
||||
if (identifierId != static_cast<ProjectIdentifier>(-1)) {
|
||||
this->setIdentifier(identifierId, value);
|
||||
} else {
|
||||
logWarn(QString("Invalid config key found in config file %1: '%2'").arg(this->getConfigFilepath()).arg(key));
|
||||
}
|
||||
} else if (key == "prefabs_filepath") {
|
||||
this->prefabFilepath = value;
|
||||
} else if (key == "prefabs_import_prompted") {
|
||||
|
@ -863,6 +925,10 @@ QMap<QString, QString> ProjectConfig::getKeyValueMap() {
|
|||
const QString path = i.value();
|
||||
if (!path.isEmpty()) map.insert("pokemon_icon_path/" + i.key(), path);
|
||||
}
|
||||
for (auto i = this->identifiers.cbegin(), end = this->identifiers.cend(); i != end; i++) {
|
||||
// TODO: Test to ensure empties aren't output in config
|
||||
map.insert("ident/"+defaultIdentifiers.value(i.key()).first, i.value());
|
||||
}
|
||||
map.insert("collision_sheet_path", this->collisionSheetPath);
|
||||
map.insert("collision_sheet_width", QString::number(this->collisionSheetWidth));
|
||||
map.insert("collision_sheet_height", QString::number(this->collisionSheetHeight));
|
||||
|
@ -909,7 +975,7 @@ QString ProjectConfig::getProjectDir() {
|
|||
return this->projectDir;
|
||||
}
|
||||
|
||||
void ProjectConfig::setFilePath(ProjectFilePath pathId, QString path) {
|
||||
void ProjectConfig::setFilePath(ProjectFilePath pathId, const QString &path) {
|
||||
if (!defaultPaths.contains(pathId)) return;
|
||||
if (path.isEmpty()) {
|
||||
this->filePaths.remove(pathId);
|
||||
|
@ -918,18 +984,20 @@ void ProjectConfig::setFilePath(ProjectFilePath pathId, QString path) {
|
|||
}
|
||||
}
|
||||
|
||||
void ProjectConfig::setFilePath(QString defaultPath, QString newPath) {
|
||||
this->setFilePath(reverseDefaultPaths(defaultPath), newPath);
|
||||
void ProjectConfig::setFilePath(const QString &pathId, const QString &path) {
|
||||
this->setFilePath(reverseDefaultPaths(pathId), path);
|
||||
}
|
||||
|
||||
QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool customOnly) {
|
||||
const QString customPath = this->filePaths.value(pathId);
|
||||
QString ProjectConfig::getCustomFilePath(ProjectFilePath pathId) {
|
||||
return this->filePaths.value(pathId);
|
||||
}
|
||||
|
||||
// When reading custom filepaths for the settings editor we don't care
|
||||
// about the default path or whether the custom path exists.
|
||||
if (customOnly)
|
||||
return customPath;
|
||||
QString ProjectConfig::getCustomFilePath(const QString &pathId) {
|
||||
return this->getCustomFilePath(reverseDefaultPaths(pathId));
|
||||
}
|
||||
|
||||
QString ProjectConfig::getFilePath(ProjectFilePath pathId) {
|
||||
const QString customPath = this->getCustomFilePath(pathId);
|
||||
if (!customPath.isEmpty()) {
|
||||
// A custom filepath has been specified. If the file/folder exists, use that.
|
||||
const QString absCustomPath = this->projectDir + QDir::separator() + customPath;
|
||||
|
@ -943,8 +1011,33 @@ QString ProjectConfig::getFilePath(ProjectFilePath pathId, bool customOnly) {
|
|||
|
||||
}
|
||||
|
||||
QString ProjectConfig::getFilePath(QString defaultPath, bool customOnly) {
|
||||
return this->getFilePath(reverseDefaultPaths(defaultPath), customOnly);
|
||||
void ProjectConfig::setIdentifier(ProjectIdentifier id, const QString &text) {
|
||||
if (!defaultIdentifiers.contains(id)) return;
|
||||
QString copy(text);
|
||||
if (copy.isEmpty()) {
|
||||
this->identifiers.remove(id);
|
||||
} else {
|
||||
this->identifiers[id] = copy;
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectConfig::setIdentifier(const QString &id, const QString &text) {
|
||||
this->setIdentifier(reverseDefaultIdentifier(id), text);
|
||||
}
|
||||
|
||||
QString ProjectConfig::getCustomIdentifier(ProjectIdentifier id) {
|
||||
return this->identifiers.value(id);
|
||||
}
|
||||
|
||||
QString ProjectConfig::getCustomIdentifier(const QString &id) {
|
||||
return this->getCustomIdentifier(reverseDefaultIdentifier(id));
|
||||
}
|
||||
|
||||
QString ProjectConfig::getIdentifier(ProjectIdentifier id) {
|
||||
const QString customText = this->getCustomIdentifier(id);
|
||||
if (!customText.isEmpty())
|
||||
return customText;
|
||||
return defaultIdentifiers.contains(id) ? defaultIdentifiers[id].second : QString();
|
||||
}
|
||||
|
||||
void ProjectConfig::setBaseGameVersion(BaseGameVersion baseGameVersion) {
|
||||
|
|
|
@ -372,13 +372,14 @@ bool CloneObjectEvent::loadFromJson(QJsonObject json, Project *project) {
|
|||
this->setTargetID(ParseUtil::jsonToInt(json["target_local_id"]));
|
||||
|
||||
// Ensure the target map constant is valid before adding it to the events.
|
||||
const QString dynamicMapConstant = project->getDynamicMapDefineName();
|
||||
QString mapConstant = ParseUtil::jsonToQString(json["target_map"]);
|
||||
if (project->mapConstantsToMapNames.contains(mapConstant)) {
|
||||
this->setTargetMap(project->mapConstantsToMapNames.value(mapConstant));
|
||||
} else if (mapConstant == DYNAMIC_MAP_CONSTANT) {
|
||||
} else if (mapConstant == dynamicMapConstant) {
|
||||
this->setTargetMap(DYNAMIC_MAP_NAME);
|
||||
} else {
|
||||
logWarn(QString("Target Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(DYNAMIC_MAP_CONSTANT));
|
||||
logWarn(QString("Target Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(dynamicMapConstant));
|
||||
this->setTargetMap(DYNAMIC_MAP_NAME);
|
||||
}
|
||||
|
||||
|
@ -483,13 +484,14 @@ bool WarpEvent::loadFromJson(QJsonObject json, Project *project) {
|
|||
this->setDestinationWarpID(ParseUtil::jsonToQString(json["dest_warp_id"]));
|
||||
|
||||
// Ensure the warp destination map constant is valid before adding it to the warps.
|
||||
const QString dynamicMapConstant = project->getDynamicMapDefineName();
|
||||
QString mapConstant = ParseUtil::jsonToQString(json["dest_map"]);
|
||||
if (project->mapConstantsToMapNames.contains(mapConstant)) {
|
||||
this->setDestinationMap(project->mapConstantsToMapNames.value(mapConstant));
|
||||
} else if (mapConstant == DYNAMIC_MAP_CONSTANT) {
|
||||
} else if (mapConstant == dynamicMapConstant) {
|
||||
this->setDestinationMap(DYNAMIC_MAP_NAME);
|
||||
} else {
|
||||
logWarn(QString("Destination Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(DYNAMIC_MAP_CONSTANT));
|
||||
logWarn(QString("Destination Map constant '%1' is invalid. Using default '%2'.").arg(mapConstant).arg(dynamicMapConstant));
|
||||
this->setDestinationMap(DYNAMIC_MAP_NAME);
|
||||
}
|
||||
|
||||
|
@ -913,15 +915,16 @@ OrderedJson::object HealLocationEvent::buildEventJson(Project *) {
|
|||
}
|
||||
|
||||
void HealLocationEvent::setDefaultValues(Project *) {
|
||||
this->setElevation(3);
|
||||
this->setElevation(projectConfig.getDefaultElevation());
|
||||
if (!this->getMap())
|
||||
return;
|
||||
bool respawnEanbled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
QString mapConstant = Map::mapConstantFromName(this->getMap()->name).remove(0,4);
|
||||
QString prefix = respawnEanbled ? "SPAWN_" : "HEAL_LOCATION_";
|
||||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
const QString mapConstant = Map::mapConstantFromName(this->getMap()->name, false);
|
||||
const QString prefix = projectConfig.getIdentifier(respawnEnabled ? ProjectIdentifier::define_spawn_prefix
|
||||
: ProjectIdentifier::define_heal_locations_prefix);
|
||||
this->setLocationName(mapConstant);
|
||||
this->setIdName(prefix + mapConstant);
|
||||
if (respawnEanbled) {
|
||||
if (respawnEnabled) {
|
||||
this->setRespawnMap(this->getMap()->name);
|
||||
this->setRespawnNPC(1);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ HealLocation HealLocation::fromEvent(Event *fromEvent) {
|
|||
healLocation.y = event->getY();
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled()) {
|
||||
healLocation.respawnNPC = event->getRespawnNPC();
|
||||
healLocation.respawnMap = Map::mapConstantFromName(event->getRespawnMap()).remove(0,4);
|
||||
healLocation.respawnMap = Map::mapConstantFromName(event->getRespawnMap(), false);
|
||||
}
|
||||
return healLocation;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,12 @@ void Map::setName(QString mapName) {
|
|||
constantName = mapConstantFromName(mapName);
|
||||
}
|
||||
|
||||
QString Map::mapConstantFromName(QString mapName) {
|
||||
QString Map::mapConstantFromName(QString mapName, bool includePrefix) {
|
||||
// Transform map names of the form 'GraniteCave_B1F` into map constants like 'MAP_GRANITE_CAVE_B1F'.
|
||||
static const QRegularExpression caseChange("([a-z])([A-Z])");
|
||||
QString nameWithUnderscores = mapName.replace(caseChange, "\\1_\\2");
|
||||
QString withMapAndUppercase = "MAP_" + nameWithUnderscores.toUpper();
|
||||
const QString prefix = includePrefix ? projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix) : "";
|
||||
QString withMapAndUppercase = prefix + nameWithUnderscores.toUpper();
|
||||
static const QRegularExpression underscores("_+");
|
||||
QString constantName = withMapAndUppercase.replace(underscores, "_");
|
||||
|
||||
|
|
|
@ -425,12 +425,14 @@ QMap<QString, int> ParseUtil::readCDefines(const QString &filename, const QStrin
|
|||
}
|
||||
|
||||
// Find and evaluate an unknown list of defines with a known name prefix.
|
||||
QMap<QString, int> ParseUtil::readCDefinesByPrefix(const QString &filename, const QStringList &prefixes) {
|
||||
QMap<QString, int> ParseUtil::readCDefinesByPrefix(const QString &filename, QStringList prefixes) {
|
||||
prefixes.removeDuplicates();
|
||||
return this->readCDefines(filename, prefixes, false);
|
||||
}
|
||||
|
||||
// Find and evaluate a specific set of defines with known names.
|
||||
QMap<QString, int> ParseUtil::readCDefinesByName(const QString &filename, const QStringList &names) {
|
||||
QMap<QString, int> ParseUtil::readCDefinesByName(const QString &filename, QStringList names) {
|
||||
names.removeDuplicates();
|
||||
return this->readCDefines(filename, names, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,11 @@ using std::make_shared;
|
|||
|
||||
|
||||
|
||||
RegionMap::RegionMap(Project *project) {
|
||||
RegionMap::RegionMap(Project *project) :
|
||||
section_prefix(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix)),
|
||||
default_map_section(section_prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_empty)),
|
||||
count_map_section(section_prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_section_count))
|
||||
{
|
||||
this->project = project;
|
||||
}
|
||||
|
||||
|
@ -146,7 +150,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
|
|||
|
||||
LayoutSquare square;
|
||||
square.map_section = square_section_name;
|
||||
square.has_map = (square_section_name != "MAPSEC_NONE" && !square_section_name.isEmpty());
|
||||
square.has_map = (square_section_name != this->default_map_section && !square_section_name.isEmpty());
|
||||
square.x = x;
|
||||
square.y = y;
|
||||
|
||||
|
@ -204,7 +208,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
|
|||
|
||||
LayoutSquare square;
|
||||
square.map_section = square_section_name;
|
||||
square.has_map = (square_section_name != "MAPSEC_NONE" && !square_section_name.isEmpty());
|
||||
square.has_map = (square_section_name != this->default_map_section && !square_section_name.isEmpty());
|
||||
square.x = x;
|
||||
square.y = y;
|
||||
layout.append(square);
|
||||
|
@ -228,7 +232,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
|
|||
this->layout_qualifiers = qualifiers + " " + type;
|
||||
this->layout_array_label = label;
|
||||
|
||||
static const QRegularExpression reSec("(?<sec>MAPSEC_[A-Za-z0-9_]+)");
|
||||
static const QRegularExpression reSec(QString("(?<sec>%1[A-Za-z0-9_]+)").arg(this->section_prefix));
|
||||
QRegularExpressionMatchIterator k = reSec.globalMatch(text);
|
||||
|
||||
QList<LayoutSquare> layout;
|
||||
|
@ -242,7 +246,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
|
|||
|
||||
LayoutSquare square;
|
||||
square.map_section = sec;
|
||||
square.has_map = (sec != "MAPSEC_NONE" && !sec.isEmpty());
|
||||
square.has_map = (sec != this->default_map_section && !sec.isEmpty());
|
||||
square.x = x;
|
||||
square.y = y;
|
||||
layout.append(square);
|
||||
|
@ -283,7 +287,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
|
|||
QString square_section_name = section.trimmed();
|
||||
LayoutSquare square;
|
||||
square.map_section = square_section_name;
|
||||
square.has_map = (square_section_name != "MAPSEC_NONE" && !square_section_name.isEmpty());
|
||||
square.has_map = (square_section_name != this->default_map_section && !square_section_name.isEmpty());
|
||||
square.x = x;
|
||||
square.y = y;
|
||||
layout.append(square);
|
||||
|
@ -454,7 +458,7 @@ void RegionMap::saveLayout() {
|
|||
}
|
||||
|
||||
void RegionMap::resetSquare(int index) {
|
||||
this->layouts[this->current_layer][index].map_section = "MAPSEC_NONE";
|
||||
this->layouts[this->current_layer][index].map_section = this->default_map_section;
|
||||
this->layouts[this->current_layer][index].has_map = false;
|
||||
}
|
||||
|
||||
|
@ -473,7 +477,7 @@ void RegionMap::replaceSection(QString oldSection, QString newSection) {
|
|||
for (auto &square : this->layouts[this->current_layer]) {
|
||||
if (square.map_section == oldSection) {
|
||||
square.map_section = newSection;
|
||||
square.has_map = (newSection != "MAPSEC_NONE");
|
||||
square.has_map = (newSection != this->default_map_section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -482,11 +486,11 @@ void RegionMap::swapSections(QString secA, QString secB) {
|
|||
for (auto &square : this->layouts[this->current_layer]) {
|
||||
if (square.map_section == secA) {
|
||||
square.map_section = secB;
|
||||
square.has_map = (square.map_section != "MAPSEC_NONE");
|
||||
square.has_map = (square.map_section != this->default_map_section);
|
||||
}
|
||||
else if (square.map_section == secB) {
|
||||
square.map_section = secA;
|
||||
square.has_map = (square.map_section != "MAPSEC_NONE");
|
||||
square.has_map = (square.map_section != this->default_map_section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -725,7 +729,7 @@ void RegionMap::setSquareMapSection(int index, QString section) {
|
|||
int layoutIndex = tilemapToLayoutIndex(index);
|
||||
if (!(layoutIndex < 0 || !this->layouts.contains(this->current_layer))) {
|
||||
this->layouts[this->current_layer][layoutIndex].map_section = section;
|
||||
this->layouts[this->current_layer][layoutIndex].has_map = !(section == "MAPSEC_NONE" || section.isEmpty());
|
||||
this->layouts[this->current_layer][layoutIndex].has_map = !(section == this->default_map_section || section.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -780,7 +784,7 @@ QString RegionMap::fixCase(QString caps) {
|
|||
QString camel;
|
||||
|
||||
static const QRegularExpression re_braced("({.*})");
|
||||
for (auto ch : caps.remove(re_braced).remove("MAPSEC")) {
|
||||
for (auto ch : caps.remove(re_braced).remove(this->section_prefix)) {
|
||||
if (ch == '_' || ch == ' ') {
|
||||
big = true;
|
||||
continue;
|
||||
|
|
|
@ -168,7 +168,10 @@ QString Tileset::getMetatileLabelPrefix()
|
|||
|
||||
QString Tileset::getMetatileLabelPrefix(const QString &name)
|
||||
{
|
||||
return QString("METATILE_%1_").arg(QString(name).replace("gTileset_", ""));
|
||||
// Default is "gTileset_Name" --> "METATILE_Name_"
|
||||
const QString tilesetPrefix = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix);
|
||||
const QString labelPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_metatile_label_prefix);
|
||||
return QString("%1%2_").arg(labelPrefix).arg(QString(name).replace(tilesetPrefix, ""));
|
||||
}
|
||||
|
||||
bool Tileset::metatileIsValid(uint16_t metatileId, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
|
@ -343,7 +346,8 @@ QString Tileset::getExpectedDir(QString tilesetName, bool isSecondary)
|
|||
static const QRegularExpression re("([a-z])([A-Z0-9])");
|
||||
const QString category = isSecondary ? "secondary" : "primary";
|
||||
const QString basePath = projectConfig.getFilePath(ProjectFilePath::data_tilesets_folders) + category + "/";
|
||||
return basePath + tilesetName.replace("gTileset_", "").replace(re, "\\1_\\2").toLower();
|
||||
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix);
|
||||
return basePath + tilesetName.replace(prefix, "").replace(re, "\\1_\\2").toLower();
|
||||
}
|
||||
|
||||
// Get the expected positions of the members in struct Tileset.
|
||||
|
|
|
@ -1867,8 +1867,9 @@ void MainWindow::addNewEvent(Event::Type type) {
|
|||
msgBox.setText("Failed to add new event");
|
||||
if (Event::typeToGroup(type) == Event::Group::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 '%2'.")
|
||||
"This limit can be adjusted with %2 in '%3'.")
|
||||
.arg(editor->project->getMaxObjectEvents())
|
||||
.arg(projectConfig.getIdentifier(ProjectIdentifier::define_obj_event_count))
|
||||
.arg(projectConfig.getFilePath(ProjectFilePath::constants_global)));
|
||||
}
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
|
|
266
src/project.cpp
266
src/project.cpp
|
@ -289,10 +289,12 @@ bool Project::loadMapData(Map* map) {
|
|||
}
|
||||
|
||||
map->events[Event::Group::Heal].clear();
|
||||
|
||||
const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
||||
for (auto it = healLocations.begin(); it != healLocations.end(); it++) {
|
||||
HealLocation loc = *it;
|
||||
//if TRUE map is flyable / has healing location
|
||||
if (loc.mapName == QString(mapNamesToMapConstants.value(map->name)).remove(0,4)) {
|
||||
if (loc.mapName == Map::mapConstantFromName(map->name, false)) {
|
||||
HealLocationEvent *heal = new HealLocationEvent();
|
||||
heal->setMap(map);
|
||||
heal->setX(loc.x);
|
||||
|
@ -301,12 +303,8 @@ bool Project::loadMapData(Map* map) {
|
|||
heal->setLocationName(loc.mapName);
|
||||
heal->setIdName(loc.idName);
|
||||
heal->setIndex(loc.index);
|
||||
|
||||
// TODO: what is this
|
||||
// heal->put("destination_map_name", mapConstantsToMapNames.value(map->name));
|
||||
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled()) {
|
||||
heal->setRespawnMap(mapConstantsToMapNames.value(QString("MAP_" + loc.respawnMap)));
|
||||
heal->setRespawnMap(mapConstantsToMapNames.value(QString(mapPrefix + loc.respawnMap)));
|
||||
heal->setRespawnNPC(loc.respawnNPC);
|
||||
}
|
||||
map->events[Event::Group::Heal].append(heal);
|
||||
|
@ -630,9 +628,8 @@ void Project::saveWildMonData() {
|
|||
OrderedJson::object wildEncountersObject;
|
||||
OrderedJson::array wildEncounterGroups;
|
||||
|
||||
// gWildMonHeaders label is not mutable
|
||||
OrderedJson::object monHeadersObject;
|
||||
monHeadersObject["label"] = "gWildMonHeaders";
|
||||
monHeadersObject["label"] = projectConfig.getIdentifier(ProjectIdentifier::symbol_wild_encounters);
|
||||
monHeadersObject["for_maps"] = true;
|
||||
|
||||
OrderedJson::array fieldsInfoArray;
|
||||
|
@ -751,6 +748,12 @@ void Project::saveHealLocations(Map *map) {
|
|||
this->saveHealLocationsConstants();
|
||||
}
|
||||
|
||||
QString Project::getHealLocationsTableName() {
|
||||
if (projectConfig.getHealLocationRespawnDataEnabled())
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_points);
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::symbol_heal_locations);
|
||||
}
|
||||
|
||||
// Saves heal location maps/coords/respawn data in root + /src/data/heal_locations.h
|
||||
void Project::saveHealLocationsData(Map *map) {
|
||||
// Update heal locations from map
|
||||
|
@ -774,20 +777,19 @@ void Project::saveHealLocationsData(Map *map) {
|
|||
|
||||
// Create the definition text for each data table
|
||||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
QString arrayName = respawnEnabled ? "sSpawnPoints" : "sHealLocations";
|
||||
const QString qualifiers = QString(healLocationDataQualifiers.isStatic ? "static " : "")
|
||||
+ QString(healLocationDataQualifiers.isConst ? "const " : "");
|
||||
|
||||
QString locationTableText = QString("%1struct HealLocation %2[] =\n{\n").arg(qualifiers).arg(arrayName);
|
||||
QString locationTableText = QString("%1struct HealLocation %2[] =\n{\n").arg(qualifiers).arg(this->getHealLocationsTableName());
|
||||
QString respawnMapTableText, respawnNPCTableText;
|
||||
if (respawnEnabled) {
|
||||
respawnMapTableText = QString("\n%1u16 sWhiteoutRespawnHealCenterMapIdxs[][2] =\n{\n").arg(qualifiers);
|
||||
respawnNPCTableText = QString("\n%1u8 sWhiteoutRespawnHealerNpcIds[] =\n{\n").arg(qualifiers);
|
||||
respawnMapTableText = QString("\n%1u16 %2[][2] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_maps));
|
||||
respawnNPCTableText = QString("\n%1u8 %2[] =\n{\n").arg(qualifiers).arg(projectConfig.getIdentifier(ProjectIdentifier::symbol_spawn_npcs));
|
||||
}
|
||||
|
||||
// Populate the data tables with the heal location data
|
||||
int i = 0;
|
||||
const QString emptyMapName = "UNDEFINED"; // TODO: Use a project-wide constant here?
|
||||
const QString emptyMapName = projectConfig.getIdentifier(ProjectIdentifier::define_map_empty);
|
||||
for (auto hl : this->healLocations) {
|
||||
// Add numbered suffix for duplicate constants
|
||||
if (healLocationsDupes.keys().contains(hl.idName)) {
|
||||
|
@ -1505,7 +1507,7 @@ bool Project::readTilesetMetatileLabels() {
|
|||
QString metatileLabelsFilename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_labels);
|
||||
fileWatcher.addPath(root + "/" + metatileLabelsFilename);
|
||||
|
||||
static const QStringList prefixes = {"METATILE_"};
|
||||
const QStringList prefixes = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_metatile_label_prefix))};
|
||||
QMap<QString, int> defines = parser.readCDefinesByPrefix(metatileLabelsFilename, prefixes);
|
||||
|
||||
for (QString label : defines.keys()) {
|
||||
|
@ -1719,8 +1721,9 @@ bool Project::readMapGroups() {
|
|||
}
|
||||
}
|
||||
|
||||
mapConstantsToMapNames.insert(DYNAMIC_MAP_CONSTANT, DYNAMIC_MAP_NAME);
|
||||
mapNamesToMapConstants.insert(DYNAMIC_MAP_NAME, DYNAMIC_MAP_CONSTANT);
|
||||
const QString defineName = this->getDynamicMapDefineName();
|
||||
mapConstantsToMapNames.insert(defineName, DYNAMIC_MAP_NAME);
|
||||
mapNamesToMapConstants.insert(DYNAMIC_MAP_NAME, defineName);
|
||||
maps.append(DYNAMIC_MAP_NAME);
|
||||
|
||||
groupNames = groups;
|
||||
|
@ -1862,62 +1865,72 @@ bool Project::readTilesetLabels() {
|
|||
return success;
|
||||
}
|
||||
|
||||
// TODO: Names to config
|
||||
bool Project::readTilesetProperties() {
|
||||
static const QStringList names = {
|
||||
"NUM_TILES_IN_PRIMARY",
|
||||
"NUM_TILES_TOTAL",
|
||||
"NUM_METATILES_IN_PRIMARY",
|
||||
"NUM_PALS_IN_PRIMARY",
|
||||
"NUM_PALS_TOTAL",
|
||||
"MAX_MAP_DATA_SIZE",
|
||||
const QString numTilesPrimaryName = projectConfig.getIdentifier(ProjectIdentifier::define_tiles_primary);
|
||||
const QString numTilesTotalName = projectConfig.getIdentifier(ProjectIdentifier::define_tiles_total);
|
||||
const QString numMetatilesPrimaryName = projectConfig.getIdentifier(ProjectIdentifier::define_metatiles_primary);
|
||||
const QString numPalsPrimaryName = projectConfig.getIdentifier(ProjectIdentifier::define_pals_primary);
|
||||
const QString numPalsTotalName = projectConfig.getIdentifier(ProjectIdentifier::define_pals_total);
|
||||
const QString maxMapSizeName = projectConfig.getIdentifier(ProjectIdentifier::define_map_size);
|
||||
const QStringList names = {
|
||||
numTilesPrimaryName,
|
||||
numTilesTotalName,
|
||||
numMetatilesPrimaryName,
|
||||
numPalsPrimaryName,
|
||||
numPalsTotalName,
|
||||
maxMapSizeName,
|
||||
};
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_fieldmap);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> defines = parser.readCDefinesByName(filename, names);
|
||||
|
||||
auto it = defines.find("NUM_TILES_IN_PRIMARY");
|
||||
auto it = defines.find(numTilesPrimaryName);
|
||||
if (it != defines.end()) {
|
||||
Project::num_tiles_primary = it.value();
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for tileset property 'NUM_TILES_IN_PRIMARY' not found. Using default (%1) instead.")
|
||||
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
|
||||
.arg(numTilesPrimaryName)
|
||||
.arg(Project::num_tiles_primary));
|
||||
}
|
||||
it = defines.find("NUM_TILES_TOTAL");
|
||||
it = defines.find(numTilesTotalName);
|
||||
if (it != defines.end()) {
|
||||
Project::num_tiles_total = it.value();
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for tileset property 'NUM_TILES_TOTAL' not found. Using default (%1) instead.")
|
||||
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
|
||||
.arg(numTilesTotalName)
|
||||
.arg(Project::num_tiles_total));
|
||||
}
|
||||
it = defines.find("NUM_METATILES_IN_PRIMARY");
|
||||
it = defines.find(numMetatilesPrimaryName);
|
||||
if (it != defines.end()) {
|
||||
Project::num_metatiles_primary = it.value();
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for tileset property 'NUM_METATILES_IN_PRIMARY' not found. Using default (%1) instead.")
|
||||
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
|
||||
.arg(numMetatilesPrimaryName)
|
||||
.arg(Project::num_metatiles_primary));
|
||||
}
|
||||
it = defines.find("NUM_PALS_IN_PRIMARY");
|
||||
it = defines.find(numPalsPrimaryName);
|
||||
if (it != defines.end()) {
|
||||
Project::num_pals_primary = it.value();
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for tileset property 'NUM_PALS_IN_PRIMARY' not found. Using default (%1) instead.")
|
||||
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
|
||||
.arg(numPalsPrimaryName)
|
||||
.arg(Project::num_pals_primary));
|
||||
}
|
||||
it = defines.find("NUM_PALS_TOTAL");
|
||||
it = defines.find(numPalsTotalName);
|
||||
if (it != defines.end()) {
|
||||
Project::num_pals_total = it.value();
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for tileset property 'NUM_PALS_TOTAL' not found. Using default (%1) instead.")
|
||||
logWarn(QString("Value for tileset property '%1' not found. Using default (%2) instead.")
|
||||
.arg(numPalsTotalName)
|
||||
.arg(Project::num_pals_total));
|
||||
}
|
||||
|
||||
it = defines.find("MAX_MAP_DATA_SIZE");
|
||||
it = defines.find(maxMapSizeName);
|
||||
if (it != defines.end()) {
|
||||
int min = getMapDataSize(1, 1);
|
||||
if (it.value() >= min) {
|
||||
|
@ -1925,29 +1938,35 @@ bool Project::readTilesetProperties() {
|
|||
calculateDefaultMapSize();
|
||||
} else {
|
||||
// must be large enough to support a 1x1 map
|
||||
logWarn(QString("Value for map property 'MAX_MAP_DATA_SIZE' is %1, must be at least %2. Using default (%3) instead.")
|
||||
logWarn(QString("Value for map property '%1' is %2, must be at least %3. Using default (%4) instead.")
|
||||
.arg(maxMapSizeName)
|
||||
.arg(it.value())
|
||||
.arg(min)
|
||||
.arg(Project::max_map_data_size));
|
||||
}
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for map property 'MAX_MAP_DATA_SIZE' not found. Using default (%1) instead.")
|
||||
logWarn(QString("Value for map property '%1' not found. Using default (%2) instead.")
|
||||
.arg(maxMapSizeName)
|
||||
.arg(Project::max_map_data_size));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Update for config
|
||||
// Read data masks for Blocks and metatile attributes.
|
||||
bool Project::readFieldmapMasks() {
|
||||
static const QStringList searchNames = {
|
||||
ProjectConfig::metatileIdMaskName,
|
||||
ProjectConfig::collisionMaskName,
|
||||
ProjectConfig::elevationMaskName,
|
||||
ProjectConfig::behaviorMaskName,
|
||||
ProjectConfig::layerTypeMaskName,
|
||||
const QString metatileIdMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_metatile);
|
||||
const QString collisionMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_collision);
|
||||
const QString elevationMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_elevation);
|
||||
const QString behaviorMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_behavior);
|
||||
const QString layerTypeMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_layer);
|
||||
const QStringList searchNames = {
|
||||
metatileIdMaskName,
|
||||
collisionMaskName,
|
||||
elevationMaskName,
|
||||
behaviorMaskName,
|
||||
layerTypeMaskName,
|
||||
};
|
||||
QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
|
||||
fileWatcher.addPath(root + "/" + globalFieldmap);
|
||||
|
@ -1963,57 +1982,63 @@ bool Project::readFieldmapMasks() {
|
|||
projectConfig.setSaveDisabled(true);
|
||||
|
||||
// Read Block masks
|
||||
auto it = defines.find(ProjectConfig::metatileIdMaskName);
|
||||
auto it = defines.find(metatileIdMaskName);
|
||||
if (it != defines.end())
|
||||
projectConfig.setBlockMetatileIdMask(static_cast<uint16_t>(it.value()));
|
||||
it = defines.find(ProjectConfig::collisionMaskName);
|
||||
it = defines.find(collisionMaskName);
|
||||
if (it != defines.end())
|
||||
projectConfig.setBlockCollisionMask(static_cast<uint16_t>(it.value()));
|
||||
it = defines.find(ProjectConfig::elevationMaskName);
|
||||
it = defines.find(elevationMaskName);
|
||||
if (it != defines.end())
|
||||
projectConfig.setBlockElevationMask(static_cast<uint16_t>(it.value()));
|
||||
|
||||
// Read RSE metatile attribute masks
|
||||
it = defines.find(ProjectConfig::behaviorMaskName);
|
||||
it = defines.find(behaviorMaskName);
|
||||
if (it != defines.end())
|
||||
projectConfig.setMetatileBehaviorMask(static_cast<uint32_t>(it.value()));
|
||||
it = defines.find(ProjectConfig::layerTypeMaskName);
|
||||
it = defines.find(layerTypeMaskName);
|
||||
if (it != defines.end())
|
||||
projectConfig.setMetatileLayerTypeMask(static_cast<uint32_t>(it.value()));
|
||||
|
||||
// pokefirered keeps its attribute masks in a separate table, parse this too.
|
||||
QString srcFieldmap = projectConfig.getFilePath(ProjectFilePath::fieldmap);
|
||||
const QMap<QString, QString> attrTable = parser.readNamedIndexCArray(srcFieldmap, ProjectConfig::attrTableName);
|
||||
const QString attrTableName = projectConfig.getIdentifier(ProjectIdentifier::symbol_attribute_table);
|
||||
const QString srcFieldmap = projectConfig.getFilePath(ProjectFilePath::fieldmap);
|
||||
const QMap<QString, QString> attrTable = parser.readNamedIndexCArray(srcFieldmap, attrTableName);
|
||||
if (!attrTable.isEmpty()) {
|
||||
const QString terrainTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_behavior);
|
||||
const QString encounterTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_layer);
|
||||
const QString behaviorTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_terrain);
|
||||
const QString layerTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_encounter);
|
||||
fileWatcher.addPath(root + "/" + srcFieldmap);
|
||||
|
||||
bool ok;
|
||||
// Read terrain type mask
|
||||
uint32_t mask = attrTable.value(ProjectConfig::terrainTypeTableName).toUInt(&ok, 0);
|
||||
uint32_t mask = attrTable.value(terrainTypeTableName).toUInt(&ok, 0);
|
||||
if (ok) {
|
||||
projectConfig.setMetatileTerrainTypeMask(mask);
|
||||
this->disabledSettingsNames.insert(ProjectConfig::terrainTypeTableName);
|
||||
this->disabledSettingsNames.insert(terrainTypeTableName);
|
||||
}
|
||||
// Read encounter type mask
|
||||
mask = attrTable.value(ProjectConfig::encounterTypeTableName).toUInt(&ok, 0);
|
||||
mask = attrTable.value(encounterTypeTableName).toUInt(&ok, 0);
|
||||
if (ok) {
|
||||
projectConfig.setMetatileEncounterTypeMask(mask);
|
||||
this->disabledSettingsNames.insert(ProjectConfig::encounterTypeTableName);
|
||||
this->disabledSettingsNames.insert(encounterTypeTableName);
|
||||
}
|
||||
// If we haven't already parsed behavior and layer type then try those too
|
||||
if (!this->disabledSettingsNames.contains(ProjectConfig::behaviorMaskName)) {
|
||||
if (!this->disabledSettingsNames.contains(behaviorMaskName)) {
|
||||
// Read behavior mask
|
||||
mask = attrTable.value(ProjectConfig::behaviorTableName).toUInt(&ok, 0);
|
||||
mask = attrTable.value(behaviorTableName).toUInt(&ok, 0);
|
||||
if (ok) {
|
||||
projectConfig.setMetatileBehaviorMask(mask);
|
||||
this->disabledSettingsNames.insert(ProjectConfig::behaviorTableName);
|
||||
this->disabledSettingsNames.insert(behaviorTableName);
|
||||
}
|
||||
}
|
||||
if (!this->disabledSettingsNames.contains(ProjectConfig::layerTypeMaskName)) {
|
||||
if (!this->disabledSettingsNames.contains(layerTypeMaskName)) {
|
||||
// Read layer type mask
|
||||
mask = attrTable.value(ProjectConfig::layerTypeTableName).toUInt(&ok, 0);
|
||||
mask = attrTable.value(layerTypeTableName).toUInt(&ok, 0);
|
||||
if (ok) {
|
||||
projectConfig.setMetatileLayerTypeMask(mask);
|
||||
this->disabledSettingsNames.insert(ProjectConfig::layerTypeTableName);
|
||||
this->disabledSettingsNames.insert(layerTypeTableName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2025,7 +2050,7 @@ bool Project::readRegionMapSections() {
|
|||
this->mapSectionNameToValue.clear();
|
||||
this->mapSectionValueToName.clear();
|
||||
|
||||
static const QStringList prefixes = {"\\bMAPSEC_"};
|
||||
const QStringList prefixes = {QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_section_prefix))};
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_region_map_sections);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
this->mapSectionNameToValue = parser.readCDefinesByPrefix(filename, prefixes);
|
||||
|
@ -2043,7 +2068,10 @@ bool Project::readRegionMapSections() {
|
|||
// Read the constants to preserve any "unused" heal locations when writing the file later
|
||||
bool Project::readHealLocationConstants() {
|
||||
this->healLocationNameToValue.clear();
|
||||
static const QStringList prefixes = {"\\bSPAWN_", "\\bHEAL_LOCATION_"};
|
||||
const QStringList prefixes = {
|
||||
QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_heal_locations_prefix)),
|
||||
QString("\\b%1").arg(projectConfig.getIdentifier(ProjectIdentifier::define_spawn_prefix))
|
||||
};
|
||||
QString constantsFilename = projectConfig.getFilePath(ProjectFilePath::constants_heal_locations);
|
||||
fileWatcher.addPath(root + "/" + constantsFilename);
|
||||
this->healLocationNameToValue = parser.readCDefinesByPrefix(constantsFilename, prefixes);
|
||||
|
@ -2051,6 +2079,7 @@ bool Project::readHealLocationConstants() {
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO: Simplify using the new C struct parsing functions (and indexed array parsing functions)
|
||||
bool Project::readHealLocations() {
|
||||
this->healLocationDataQualifiers = {};
|
||||
this->healLocations.clear();
|
||||
|
@ -2069,11 +2098,12 @@ bool Project::readHealLocations() {
|
|||
bool respawnEnabled = projectConfig.getHealLocationRespawnDataEnabled();
|
||||
|
||||
// Get data qualifiers for the location data table
|
||||
QString tableName = respawnEnabled ? "sSpawnPoints" : "sHealLocations";
|
||||
this->healLocationDataQualifiers = this->getDataQualifiers(text, tableName);
|
||||
this->healLocationDataQualifiers = this->getDataQualifiers(text, this->getHealLocationsTableName());
|
||||
|
||||
// Create regex pattern for the constants (ex: "SPAWN_PALLET_TOWN" or "HEAL_LOCATION_PETALBURG_CITY")
|
||||
static const QRegularExpression constantsExpr("(SPAWN|HEAL_LOCATION)_[A-Za-z0-9_]+");
|
||||
const QString spawnPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_spawn_prefix);
|
||||
const QString healLocPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_heal_locations_prefix);
|
||||
const QRegularExpression constantsExpr(QString("\\b(%1|%2)[A-Za-z0-9_]+").arg(spawnPrefix).arg(healLocPrefix));
|
||||
|
||||
// Find all the unique heal location constants used in the data tables.
|
||||
// Porymap doesn't care whether or not a constant appeared in the heal locations constants file.
|
||||
|
@ -2133,8 +2163,8 @@ bool Project::readHealLocations() {
|
|||
}
|
||||
|
||||
bool Project::readItemNames() {
|
||||
QStringList prefixes("\\bITEM_(?!(B_)?USE_)"); // Exclude ITEM_USE_ and ITEM_B_USE_ constants
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_items);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_items)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_items);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
itemNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (itemNames.isEmpty()) {
|
||||
|
@ -2145,8 +2175,8 @@ bool Project::readItemNames() {
|
|||
}
|
||||
|
||||
bool Project::readFlagNames() {
|
||||
QStringList prefixes("\\bFLAG_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_flags);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_flags)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_flags);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
flagNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (flagNames.isEmpty()) {
|
||||
|
@ -2157,8 +2187,8 @@ bool Project::readFlagNames() {
|
|||
}
|
||||
|
||||
bool Project::readVarNames() {
|
||||
QStringList prefixes("\\bVAR_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_vars);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_vars)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_vars);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
varNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (varNames.isEmpty()) {
|
||||
|
@ -2169,8 +2199,8 @@ bool Project::readVarNames() {
|
|||
}
|
||||
|
||||
bool Project::readMovementTypes() {
|
||||
QStringList prefixes("\\bMOVEMENT_TYPE_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_event_movement);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_movement_types)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_event_movement);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
movementTypes = parser.readCDefineNames(filename, prefixes);
|
||||
if (movementTypes.isEmpty()) {
|
||||
|
@ -2183,7 +2213,7 @@ bool Project::readMovementTypes() {
|
|||
bool Project::readInitialFacingDirections() {
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::initial_facing_table);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
facingDirections = parser.readNamedIndexCArray(filename, "gInitialMovementTypeFacingDirections");
|
||||
facingDirections = parser.readNamedIndexCArray(filename, projectConfig.getIdentifier(ProjectIdentifier::symbol_facing_directions));
|
||||
if (facingDirections.isEmpty()) {
|
||||
logError(QString("Failed to read initial movement type facing directions from %1").arg(filename));
|
||||
return false;
|
||||
|
@ -2192,8 +2222,8 @@ bool Project::readInitialFacingDirections() {
|
|||
}
|
||||
|
||||
bool Project::readMapTypes() {
|
||||
QStringList prefixes("\\bMAP_TYPE_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_map_types)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
mapTypes = parser.readCDefineNames(filename, prefixes);
|
||||
if (mapTypes.isEmpty()) {
|
||||
|
@ -2204,8 +2234,8 @@ bool Project::readMapTypes() {
|
|||
}
|
||||
|
||||
bool Project::readMapBattleScenes() {
|
||||
QStringList prefixes("\\bMAP_BATTLE_SCENE_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_battle_scenes)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_map_types);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
mapBattleScenes = parser.readCDefineNames(filename, prefixes);
|
||||
if (mapBattleScenes.isEmpty()) {
|
||||
|
@ -2216,8 +2246,8 @@ bool Project::readMapBattleScenes() {
|
|||
}
|
||||
|
||||
bool Project::readWeatherNames() {
|
||||
QStringList prefixes("\\bWEATHER_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_weather)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
weatherNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (weatherNames.isEmpty()) {
|
||||
|
@ -2231,8 +2261,8 @@ bool Project::readCoordEventWeatherNames() {
|
|||
if (!projectConfig.getEventWeatherTriggerEnabled())
|
||||
return true;
|
||||
|
||||
QStringList prefixes("\\bCOORD_EVENT_WEATHER_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_coord_event_weather)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_weather);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
coordEventWeatherNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (coordEventWeatherNames.isEmpty()) {
|
||||
|
@ -2246,8 +2276,8 @@ bool Project::readSecretBaseIds() {
|
|||
if (!projectConfig.getEventSecretBaseEnabled())
|
||||
return true;
|
||||
|
||||
QStringList prefixes("\\bSECRET_BASE_[A-Za-z0-9_]*_[0-9]+");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_secret_bases);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_secret_bases)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_secret_bases);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
secretBaseIds = parser.readCDefineNames(filename, prefixes);
|
||||
if (secretBaseIds.isEmpty()) {
|
||||
|
@ -2258,8 +2288,8 @@ bool Project::readSecretBaseIds() {
|
|||
}
|
||||
|
||||
bool Project::readBgEventFacingDirections() {
|
||||
QStringList prefixes("\\bBG_EVENT_PLAYER_FACING_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_event_bg);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_sign_facing_directions)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_event_bg);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
bgEventFacingDirections = parser.readCDefineNames(filename, prefixes);
|
||||
if (bgEventFacingDirections.isEmpty()) {
|
||||
|
@ -2270,8 +2300,8 @@ bool Project::readBgEventFacingDirections() {
|
|||
}
|
||||
|
||||
bool Project::readTrainerTypes() {
|
||||
QStringList prefixes("\\bTRAINER_TYPE_");
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_trainer_types);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_trainer_types)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_trainer_types);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
trainerTypes = parser.readCDefineNames(filename, prefixes);
|
||||
if (trainerTypes.isEmpty()) {
|
||||
|
@ -2285,7 +2315,7 @@ bool Project::readMetatileBehaviors() {
|
|||
this->metatileBehaviorMap.clear();
|
||||
this->metatileBehaviorMapInverse.clear();
|
||||
|
||||
static const QStringList prefixes = {"\\bMB_"};
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_behaviors)};
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_metatile_behaviors);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
this->metatileBehaviorMap = parser.readCDefinesByPrefix(filename, prefixes);
|
||||
|
@ -2312,22 +2342,22 @@ bool Project::readMetatileBehaviors() {
|
|||
}
|
||||
|
||||
bool Project::readSongNames() {
|
||||
QStringList songDefinePrefixes{ "\\bSE_", "\\bMUS_" };
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_songs);
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_music)};
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_songs);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
this->songNames = parser.readCDefineNames(filename, songDefinePrefixes);
|
||||
this->defaultSong = this->songNames.value(0, "MUS_DUMMY");
|
||||
this->songNames = parser.readCDefineNames(filename, prefixes);
|
||||
if (this->songNames.isEmpty()) {
|
||||
logError(QString("Failed to read song names from %1.").arg(filename));
|
||||
return false;
|
||||
}
|
||||
this->defaultSong = this->songNames.value(0);
|
||||
// Song names don't have a very useful order (esp. if we include SE_* values), so sort them alphabetically.
|
||||
this->songNames.sort();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Project::readObjEventGfxConstants() {
|
||||
static const QStringList prefixes = {"\\bOBJ_EVENT_GFX_"};
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_obj_event_gfx)};
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_obj_events);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
this->gfxDefines = parser.readCDefinesByPrefix(filename, prefixes);
|
||||
|
@ -2338,33 +2368,37 @@ bool Project::readObjEventGfxConstants() {
|
|||
return true;
|
||||
}
|
||||
|
||||
// TODO: Names to config
|
||||
bool Project::readMiscellaneousConstants() {
|
||||
miscConstants.clear();
|
||||
if (userConfig.getEncounterJsonActive()) {
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_pokemon);
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_pokemon);
|
||||
const QString minLevelName = projectConfig.getIdentifier(ProjectIdentifier::define_min_level);
|
||||
const QString maxLevelName = projectConfig.getIdentifier(ProjectIdentifier::define_max_level);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> pokemonDefines = parser.readCDefinesByName(filename, {"MIN_LEVEL", "MAX_LEVEL"});
|
||||
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);
|
||||
QMap<QString, int> pokemonDefines = parser.readCDefinesByName(filename, {minLevelName, maxLevelName});
|
||||
miscConstants.insert("max_level_define", pokemonDefines.value(maxLevelName) > pokemonDefines.value(minLevelName) ? pokemonDefines.value(maxLevelName) : 100);
|
||||
miscConstants.insert("min_level_define", pokemonDefines.value(minLevelName) < pokemonDefines.value(maxLevelName) ? pokemonDefines.value(minLevelName) : 1);
|
||||
}
|
||||
|
||||
QString filename = projectConfig.getFilePath(ProjectFilePath::constants_global);
|
||||
const QString filename = projectConfig.getFilePath(ProjectFilePath::constants_global);
|
||||
const QString maxObjectEventsName = projectConfig.getIdentifier(ProjectIdentifier::define_obj_event_count);
|
||||
fileWatcher.addPath(root + "/" + filename);
|
||||
QMap<QString, int> defines = parser.readCDefinesByName(filename, {"OBJECT_EVENT_TEMPLATES_COUNT"});
|
||||
QMap<QString, int> defines = parser.readCDefinesByName(filename, {maxObjectEventsName});
|
||||
|
||||
auto it = defines.find("OBJECT_EVENT_TEMPLATES_COUNT");
|
||||
auto it = defines.find(maxObjectEventsName);
|
||||
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.")
|
||||
logWarn(QString("Value for '%1' is %2, must be greater than 0. Using default (%3) instead.")
|
||||
.arg(maxObjectEventsName)
|
||||
.arg(it.value())
|
||||
.arg(Project::max_object_events));
|
||||
}
|
||||
}
|
||||
else {
|
||||
logWarn(QString("Value for 'OBJECT_EVENT_TEMPLATES_COUNT' not found. Using default (%1) instead.")
|
||||
logWarn(QString("Value for '%1' not found. Using default (%2) instead.")
|
||||
.arg(maxObjectEventsName)
|
||||
.arg(Project::max_object_events));
|
||||
}
|
||||
|
||||
|
@ -2471,7 +2505,9 @@ bool Project::readEventGraphics() {
|
|||
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_pic_tables)
|
||||
<< root + "/" + projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx));
|
||||
|
||||
QMap<QString, QString> pointerHash = parser.readNamedIndexCArray(projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_pointers), "gObjectEventGraphicsInfoPointers");
|
||||
const QString pointersFilepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_pointers);
|
||||
const QString pointersName = projectConfig.getIdentifier(ProjectIdentifier::symbol_obj_event_gfx_pointers);
|
||||
QMap<QString, QString> pointerHash = parser.readNamedIndexCArray(pointersFilepath, pointersName);
|
||||
|
||||
qDeleteAll(eventGraphicsMap);
|
||||
eventGraphicsMap.clear();
|
||||
|
@ -2479,7 +2515,7 @@ bool Project::readEventGraphics() {
|
|||
|
||||
// The positions of each of the required members for the gfx info struct.
|
||||
// For backwards compatibility if the struct doesn't use initializers.
|
||||
const auto gfxInfoMemberMap = QHash<int, QString>{
|
||||
static const auto gfxInfoMemberMap = QHash<int, QString>{
|
||||
{8, "inanimate"},
|
||||
{11, "oam"},
|
||||
{12, "subspriteTables"},
|
||||
|
@ -2546,21 +2582,23 @@ bool Project::readSpeciesIconPaths() {
|
|||
// Read map of species constants to icon names
|
||||
const QString srcfilename = projectConfig.getFilePath(ProjectFilePath::pokemon_icon_table);
|
||||
fileWatcher.addPath(root + "/" + srcfilename);
|
||||
const QMap<QString, QString> monIconNames = parser.readNamedIndexCArray(srcfilename, "gMonIconTable");
|
||||
const QString tableName = projectConfig.getIdentifier(ProjectIdentifier::symbol_pokemon_icon_table);
|
||||
const QMap<QString, QString> monIconNames = parser.readNamedIndexCArray(srcfilename, tableName);
|
||||
|
||||
// Read map of icon names to filepaths. These are spread between two different files
|
||||
// Read map of icon names to filepaths
|
||||
const QString incfilename = projectConfig.getFilePath(ProjectFilePath::data_pokemon_gfx);
|
||||
fileWatcher.addPath(root + "/" + incfilename);
|
||||
const QMap<QString, QString> iconIncbins = parser.readCIncbinMulti(incfilename);
|
||||
|
||||
// Read species constants. If this fails we can get them from the icon table (but we shouldn't rely on it).
|
||||
static const QStringList prefixes("\\bSPECIES_");
|
||||
const QStringList prefixes = {projectConfig.getIdentifier(ProjectIdentifier::regex_species)};
|
||||
const QString constantsFilename = projectConfig.getFilePath(ProjectFilePath::constants_species);
|
||||
fileWatcher.addPath(root + "/" + constantsFilename);
|
||||
QStringList speciesNames = parser.readCDefineNames(constantsFilename, prefixes);
|
||||
if (speciesNames.isEmpty())
|
||||
speciesNames = monIconNames.keys();
|
||||
|
||||
// For each species, use the information gathered above to find the icon image.
|
||||
bool missingIcons = false;
|
||||
for (auto species : speciesNames) {
|
||||
QString path = QString();
|
||||
|
@ -2705,7 +2743,8 @@ bool Project::calculateDefaultMapSize(){
|
|||
// x^2 + 29x + (210 - max), then complete the square and simplify
|
||||
default_map_size = qFloor((qSqrt(4 * getMaxMapDataSize() + 1) - 29) / 2);
|
||||
} else {
|
||||
logError(QString("'MAX_MAP_DATA_SIZE' of %1 is too small to support a 1x1 map. Must be at least %2.")
|
||||
logError(QString("'%1' of %2 is too small to support a 1x1 map. Must be at least %3.")
|
||||
.arg(projectConfig.getIdentifier(ProjectIdentifier::define_map_size))
|
||||
.arg(max)
|
||||
.arg(getMapDataSize(1, 1)));
|
||||
return false;
|
||||
|
@ -2718,6 +2757,11 @@ int Project::getMaxObjectEvents()
|
|||
return Project::max_object_events;
|
||||
}
|
||||
|
||||
QString Project::getDynamicMapDefineName() {
|
||||
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
||||
return prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_dynamic);
|
||||
}
|
||||
|
||||
void Project::setImportExportPath(QString filename)
|
||||
{
|
||||
this->importExportPath = QFileInfo(filename).absolutePath();
|
||||
|
|
|
@ -94,9 +94,10 @@ void DraggablePixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
|
|||
emit editor->warpEventDoubleClicked(clone->getTargetMap(), clone->getTargetID(), Event::Group::Object);
|
||||
}
|
||||
else if (eventType == Event::Type::SecretBase) {
|
||||
const QString mapPrefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
||||
SecretBaseEvent *base = dynamic_cast<SecretBaseEvent *>(this->event);
|
||||
QString baseId = base->getBaseID();
|
||||
QString destMap = editor->project->mapConstantsToMapNames.value("MAP_" + baseId.left(baseId.lastIndexOf("_")));
|
||||
QString destMap = editor->project->mapConstantsToMapNames.value(mapPrefix + baseId.left(baseId.lastIndexOf("_")));
|
||||
emit editor->warpEventDoubleClicked(destMap, 0, Event::Group::Warp);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -258,9 +258,9 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
|
|||
newMap->location = this->ui->comboBox_NewMap_Location->currentText();
|
||||
newMap->song = this->ui->comboBox_NewMap_Song->currentText();
|
||||
newMap->requiresFlash = false;
|
||||
newMap->weather = this->project->weatherNames.value(0, "WEATHER_NONE");
|
||||
newMap->weather = this->project->weatherNames.value(0);
|
||||
newMap->show_location = this->ui->checkBox_NewMap_Show_Location->isChecked();
|
||||
newMap->battle_scene = this->project->mapBattleScenes.value(0, "MAP_BATTLE_SCENE_NORMAL");
|
||||
newMap->battle_scene = this->project->mapBattleScenes.value(0);
|
||||
|
||||
if (this->existingLayout) {
|
||||
layout = this->project->mapLayouts.value(this->layoutId);
|
||||
|
|
|
@ -38,7 +38,7 @@ void NewTilesetDialog::SecondaryChanged(){
|
|||
|
||||
void NewTilesetDialog::NameOrSecondaryChanged() {
|
||||
this->friendlyName = this->ui->nameLineEdit->text();
|
||||
this->fullSymbolName = "gTileset_" + this->friendlyName;
|
||||
this->fullSymbolName = projectConfig.getIdentifier(ProjectIdentifier::symbol_tilesets_prefix) + this->friendlyName;
|
||||
this->ui->symbolNameLineEdit->setText(this->fullSymbolName);
|
||||
this->path = Tileset::getExpectedDir(this->fullSymbolName, this->isSecondary);
|
||||
this->ui->pathLineEdit->setText(this->path);
|
||||
|
|
|
@ -135,32 +135,42 @@ void ProjectSettingsEditor::initUi() {
|
|||
if (project) {
|
||||
const QString maskFilepath = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
|
||||
const QString attrTableFilepath = projectConfig.getFilePath(ProjectFilePath::fieldmap);
|
||||
const QString metatileIdMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_metatile);
|
||||
const QString collisionMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_collision);
|
||||
const QString elevationMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_elevation);
|
||||
const QString behaviorMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_behavior);
|
||||
const QString layerTypeMaskName = projectConfig.getIdentifier(ProjectIdentifier::define_mask_layer);
|
||||
const QString terrainTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_behavior);
|
||||
const QString encounterTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_layer);
|
||||
const QString behaviorTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_terrain);
|
||||
const QString layerTypeTableName = projectConfig.getIdentifier(ProjectIdentifier::define_attribute_encounter);
|
||||
const QString attrTableName = projectConfig.getIdentifier(ProjectIdentifier::symbol_attribute_table);
|
||||
|
||||
// Block masks
|
||||
if (project->disabledSettingsNames.contains(ProjectConfig::metatileIdMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_MetatileIdMask, ProjectConfig::metatileIdMaskName, maskFilepath);
|
||||
if (project->disabledSettingsNames.contains(ProjectConfig::collisionMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_CollisionMask, ProjectConfig::collisionMaskName, maskFilepath);
|
||||
if (project->disabledSettingsNames.contains(ProjectConfig::elevationMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_ElevationMask, ProjectConfig::elevationMaskName, maskFilepath);
|
||||
if (project->disabledSettingsNames.contains(metatileIdMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_MetatileIdMask, metatileIdMaskName, maskFilepath);
|
||||
if (project->disabledSettingsNames.contains(collisionMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_CollisionMask, collisionMaskName, maskFilepath);
|
||||
if (project->disabledSettingsNames.contains(elevationMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_ElevationMask, elevationMaskName, maskFilepath);
|
||||
|
||||
// Behavior mask
|
||||
if (project->disabledSettingsNames.contains(ProjectConfig::behaviorMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_BehaviorMask, ProjectConfig::behaviorMaskName, maskFilepath);
|
||||
else if (project->disabledSettingsNames.contains(ProjectConfig::behaviorTableName))
|
||||
this->disableParsedSetting(ui->spinBox_BehaviorMask, ProjectConfig::attrTableName, attrTableFilepath);
|
||||
if (project->disabledSettingsNames.contains(behaviorMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_BehaviorMask, behaviorMaskName, maskFilepath);
|
||||
else if (project->disabledSettingsNames.contains(behaviorTableName))
|
||||
this->disableParsedSetting(ui->spinBox_BehaviorMask, attrTableName, attrTableFilepath);
|
||||
|
||||
// Layer type mask
|
||||
if (project->disabledSettingsNames.contains(ProjectConfig::layerTypeMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_LayerTypeMask, ProjectConfig::layerTypeMaskName, maskFilepath);
|
||||
else if (project->disabledSettingsNames.contains(ProjectConfig::layerTypeTableName))
|
||||
this->disableParsedSetting(ui->spinBox_LayerTypeMask, ProjectConfig::attrTableName, attrTableFilepath);
|
||||
if (project->disabledSettingsNames.contains(layerTypeMaskName))
|
||||
this->disableParsedSetting(ui->spinBox_LayerTypeMask, layerTypeMaskName, maskFilepath);
|
||||
else if (project->disabledSettingsNames.contains(layerTypeTableName))
|
||||
this->disableParsedSetting(ui->spinBox_LayerTypeMask, attrTableName, attrTableFilepath);
|
||||
|
||||
// Encounter and terrain type masks
|
||||
if (project->disabledSettingsNames.contains(ProjectConfig::terrainTypeTableName))
|
||||
this->disableParsedSetting(ui->spinBox_TerrainTypeMask, ProjectConfig::attrTableName, attrTableFilepath);
|
||||
if (project->disabledSettingsNames.contains(ProjectConfig::encounterTypeTableName))
|
||||
this->disableParsedSetting(ui->spinBox_EncounterTypeMask, ProjectConfig::attrTableName, attrTableFilepath);
|
||||
if (project->disabledSettingsNames.contains(terrainTypeTableName))
|
||||
this->disableParsedSetting(ui->spinBox_TerrainTypeMask, attrTableName, attrTableFilepath);
|
||||
if (project->disabledSettingsNames.contains(encounterTypeTableName))
|
||||
this->disableParsedSetting(ui->spinBox_EncounterTypeMask, attrTableName, attrTableFilepath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -440,7 +450,7 @@ void ProjectSettingsEditor::refresh() {
|
|||
ui->lineEdit_BGsIcon->setText(projectConfig.getEventIconPath(Event::Group::Bg));
|
||||
ui->lineEdit_HealspotsIcon->setText(projectConfig.getEventIconPath(Event::Group::Heal));
|
||||
for (auto lineEdit : ui->scrollAreaContents_ProjectPaths->findChildren<QLineEdit*>())
|
||||
lineEdit->setText(projectConfig.getFilePath(lineEdit->objectName(), true));
|
||||
lineEdit->setText(projectConfig.getCustomFilePath(lineEdit->objectName()));
|
||||
this->setWarpBehaviorsList(projectConfig.getWarpBehaviors());
|
||||
|
||||
this->refreshing = false; // Allow signals
|
||||
|
|
|
@ -796,14 +796,17 @@ void RegionMapEditor::displayRegionMapEntryOptions() {
|
|||
void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
|
||||
if (!this->region_map->layoutEnabled()) return;
|
||||
|
||||
bool enabled = ((section != "MAPSEC_NONE") && (section != "MAPSEC_COUNT")) && (this->region_map_entries.contains(section));
|
||||
bool isSpecialSection = (section == this->region_map->default_map_section
|
||||
|| section == this->region_map->count_map_section);
|
||||
|
||||
bool enabled = (!isSpecialSection && this->region_map_entries.contains(section));
|
||||
|
||||
this->ui->lineEdit_RM_MapName->setEnabled(enabled);
|
||||
this->ui->spinBox_RM_Entry_x->setEnabled(enabled);
|
||||
this->ui->spinBox_RM_Entry_y->setEnabled(enabled);
|
||||
this->ui->spinBox_RM_Entry_width->setEnabled(enabled);
|
||||
this->ui->spinBox_RM_Entry_height->setEnabled(enabled);
|
||||
this->ui->pushButton_entryActivate->setEnabled(section != "MAPSEC_NONE" && section != "MAPSEC_COUNT");
|
||||
this->ui->pushButton_entryActivate->setEnabled(!isSpecialSection);
|
||||
this->ui->pushButton_entryActivate->setText(enabled ? "Remove" : "Add");
|
||||
|
||||
this->ui->lineEdit_RM_MapName->blockSignals(true);
|
||||
|
@ -831,7 +834,7 @@ void RegionMapEditor::updateRegionMapEntryOptions(QString section) {
|
|||
|
||||
void RegionMapEditor::on_pushButton_entryActivate_clicked() {
|
||||
QString section = this->ui->comboBox_RM_Entry_MapSection->currentText();
|
||||
if (section == "MAPSEC_NONE") return;
|
||||
if (section == this->region_map->default_map_section) return;
|
||||
|
||||
if (this->region_map_entries.contains(section)) {
|
||||
// disable
|
||||
|
@ -1297,7 +1300,7 @@ void RegionMapEditor::on_action_RegionMap_ClearLayout_triggered() {
|
|||
QMessageBox::StandardButton result = QMessageBox::question(
|
||||
this,
|
||||
"WARNING",
|
||||
"This action will reset the entire map layout to MAPSEC_NONE, continue?",
|
||||
QString("This action will reset the entire map layout to %1, continue?").arg(this->region_map->default_map_section),
|
||||
QMessageBox::Yes | QMessageBox::Cancel,
|
||||
QMessageBox::Yes
|
||||
);
|
||||
|
|
|
@ -8,7 +8,7 @@ void RegionMapEntriesPixmapItem::draw() {
|
|||
|
||||
int entry_x, entry_y, entry_w, entry_h;
|
||||
|
||||
if (!entry.valid || entry.name == "MAPSEC_NONE") {
|
||||
if (!entry.valid || entry.name == region_map->default_map_section) {
|
||||
entry_x = entry_y = 0;
|
||||
entry_w = entry_h = 1;
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue