mirror of
https://github.com/huderlem/porymap.git
synced 2026-04-25 07:18:02 -05:00
Read encounter/terrain types
This commit is contained in:
parent
ef6eb69c72
commit
969c9d8e5a
|
|
@ -242,6 +242,8 @@ enum ProjectIdentifier {
|
|||
regex_sign_facing_directions,
|
||||
regex_trainer_types,
|
||||
regex_music,
|
||||
regex_encounter_types,
|
||||
regex_terrain_types,
|
||||
regex_gbapal,
|
||||
regex_bpp,
|
||||
pals_output_extension,
|
||||
|
|
|
|||
|
|
@ -11,27 +11,6 @@
|
|||
|
||||
class Project;
|
||||
|
||||
enum {
|
||||
METATILE_LAYER_MIDDLE_TOP,
|
||||
METATILE_LAYER_BOTTOM_MIDDLE,
|
||||
METATILE_LAYER_BOTTOM_TOP,
|
||||
NUM_METATILE_LAYER_TYPES
|
||||
};
|
||||
|
||||
enum {
|
||||
ENCOUNTER_NONE,
|
||||
ENCOUNTER_LAND,
|
||||
ENCOUNTER_WATER,
|
||||
NUM_METATILE_ENCOUNTER_TYPES
|
||||
};
|
||||
|
||||
enum {
|
||||
TERRAIN_NONE,
|
||||
TERRAIN_GRASS,
|
||||
TERRAIN_WATER,
|
||||
TERRAIN_WATERFALL,
|
||||
NUM_METATILE_TERRAIN_TYPES
|
||||
};
|
||||
|
||||
class Metatile
|
||||
{
|
||||
|
|
@ -41,6 +20,13 @@ public:
|
|||
Metatile &operator=(const Metatile &other) = default;
|
||||
Metatile(const int numTiles);
|
||||
|
||||
enum LayerType {
|
||||
Normal,
|
||||
Covered,
|
||||
Split,
|
||||
Count
|
||||
};
|
||||
|
||||
enum Attr {
|
||||
Behavior,
|
||||
TerrainType,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ public:
|
|||
QStringList globalScriptLabels;
|
||||
QStringList mapSectionIdNamesSaveOrder;
|
||||
QStringList mapSectionIdNames;
|
||||
QMap<uint32_t, QString> encounterTypeToName;
|
||||
QMap<uint32_t, QString> terrainTypeToName;
|
||||
QMap<QString, MapSectionEntry> regionMapEntries;
|
||||
QMap<QString, QMap<QString, uint16_t>> metatileLabelsMap;
|
||||
QMap<QString, uint16_t> unusedMetatileLabels;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,8 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
|||
{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_encounter_types, {"regex_encounter_types", "\\bTILE_ENCOUNTER_"}},
|
||||
{ProjectIdentifier::regex_terrain_types, {"regex_terrain_types", "\\bTILE_TERRAIN_"}},
|
||||
{ProjectIdentifier::regex_gbapal, {"regex_gbapal", "\\.gbapal(\\.[\\w]+)?$"}},
|
||||
{ProjectIdentifier::regex_bpp, {"regex_bpp", "\\.[\\d]+bpp(\\.[\\w]+)?$"}},
|
||||
// Other
|
||||
|
|
|
|||
|
|
@ -128,34 +128,39 @@ void Metatile::setLayout(Project * project) {
|
|||
if (behaviorMask && !project->metatileBehaviorMapInverse.isEmpty()) {
|
||||
uint32_t maxBehavior = project->metatileBehaviorMapInverse.lastKey();
|
||||
if (packer.clamp(maxBehavior) != maxBehavior)
|
||||
logWarn(QString("Metatile Behavior mask '%1' is insufficient to contain all available options.")
|
||||
.arg(Util::toHexString(behaviorMask)));
|
||||
logWarn(QString("Metatile Behavior mask '%1' is insufficient to contain largest value '%2'.")
|
||||
.arg(Util::toHexString(behaviorMask))
|
||||
.arg(Util::toHexString(maxBehavior)));
|
||||
}
|
||||
attributePackers.insert(Metatile::Attr::Behavior, packer);
|
||||
|
||||
// Validate terrain type mask
|
||||
packer.setMask(terrainTypeMask);
|
||||
const uint32_t maxTerrainType = NUM_METATILE_TERRAIN_TYPES - 1;
|
||||
if (terrainTypeMask && packer.clamp(maxTerrainType) != maxTerrainType) {
|
||||
logWarn(QString("Metatile Terrain Type mask '%1' is insufficient to contain all %2 available options.")
|
||||
if (terrainTypeMask && !project->terrainTypeToName.isEmpty()) {
|
||||
uint32_t maxTerrainType = project->terrainTypeToName.lastKey();
|
||||
if (packer.clamp(maxTerrainType) != maxTerrainType) {
|
||||
logWarn(QString("Metatile Terrain Type mask '%1' is insufficient to contain largest value '%2'.")
|
||||
.arg(Util::toHexString(terrainTypeMask))
|
||||
.arg(maxTerrainType + 1));
|
||||
.arg(Util::toHexString(maxTerrainType)));
|
||||
}
|
||||
}
|
||||
attributePackers.insert(Metatile::Attr::TerrainType, packer);
|
||||
|
||||
// Validate encounter type mask
|
||||
packer.setMask(encounterTypeMask);
|
||||
const uint32_t maxEncounterType = NUM_METATILE_ENCOUNTER_TYPES - 1;
|
||||
if (encounterTypeMask && packer.clamp(maxEncounterType) != maxEncounterType) {
|
||||
logWarn(QString("Metatile Encounter Type mask '%1' is insufficient to contain all %2 available options.")
|
||||
if (encounterTypeMask && !project->encounterTypeToName.isEmpty()) {
|
||||
uint32_t maxEncounterType = project->encounterTypeToName.lastKey();
|
||||
if (packer.clamp(maxEncounterType) != maxEncounterType) {
|
||||
logWarn(QString("Metatile Encounter Type mask '%1' is insufficient to contain largest value '%2'.")
|
||||
.arg(Util::toHexString(encounterTypeMask))
|
||||
.arg(maxEncounterType + 1));
|
||||
.arg(Util::toHexString(maxEncounterType)));
|
||||
}
|
||||
}
|
||||
attributePackers.insert(Metatile::Attr::EncounterType, packer);
|
||||
|
||||
// Validate terrain type mask
|
||||
// Validate layer type mask
|
||||
packer.setMask(layerTypeMask);
|
||||
const uint32_t maxLayerType = NUM_METATILE_LAYER_TYPES - 1;
|
||||
const uint32_t maxLayerType = Metatile::LayerType::Count - 1;
|
||||
if (layerTypeMask && packer.clamp(maxLayerType) != maxLayerType) {
|
||||
logWarn(QString("Metatile Layer Type mask '%1' is insufficient to contain all %2 available options.")
|
||||
.arg(Util::toHexString(layerTypeMask))
|
||||
|
|
|
|||
|
|
@ -98,19 +98,8 @@ QString ParseUtil::loadTextFile(const QString &path, QString *error) {
|
|||
auto it = this->fileCache.constFind(path);
|
||||
if (it != this->fileCache.constEnd()) {
|
||||
// Load text file from cache
|
||||
//logWarn(QString("CACHE HIT ON %1").arg(path));
|
||||
return it.value();
|
||||
}
|
||||
|
||||
/* TODO: Remove
|
||||
static QSet<QString> parsedFiles;
|
||||
if (parsedFiles.contains(path)) {
|
||||
logWarn(QString("CACHE MISS ON %1").arg(path));
|
||||
} else {
|
||||
parsedFiles.insert(path);
|
||||
}
|
||||
*/
|
||||
|
||||
return readTextFile(pathWithRoot(path), error);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ void Project::resetFileCache() {
|
|||
projectConfig.getFilePath(ProjectFilePath::tilesets_metatiles),
|
||||
// We need separate sets of constants from these files
|
||||
projectConfig.getFilePath(ProjectFilePath::constants_map_types),
|
||||
projectConfig.getFilePath(ProjectFilePath::global_fieldmap),
|
||||
};
|
||||
for (const auto &path : filepaths) {
|
||||
this->parser.cacheFile(path);
|
||||
|
|
@ -2185,6 +2186,9 @@ bool Project::readFieldmapProperties() {
|
|||
|
||||
// Read data masks for Blocks and metatile attributes.
|
||||
bool Project::readFieldmapMasks() {
|
||||
this->encounterTypeToName.clear();
|
||||
this->terrainTypeToName.clear();
|
||||
|
||||
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);
|
||||
|
|
@ -2197,7 +2201,7 @@ bool Project::readFieldmapMasks() {
|
|||
behaviorMaskName,
|
||||
layerTypeMaskName,
|
||||
};
|
||||
QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
|
||||
const QString globalFieldmap = projectConfig.getFilePath(ProjectFilePath::global_fieldmap);
|
||||
fileWatcher.addPath(root + "/" + globalFieldmap);
|
||||
QMap<QString, int> defines = parser.readCDefinesByName(globalFieldmap, searchNames);
|
||||
|
||||
|
|
@ -2281,6 +2285,32 @@ bool Project::readFieldmapMasks() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read #defines for encounter and terrain types to populate in the Tileset Editor dropdowns (if necessary)
|
||||
QString error;
|
||||
if (projectConfig.metatileEncounterTypeMask) {
|
||||
QMap<QString, int> defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_encounter_types)}, &error);
|
||||
if (!error.isEmpty()) {
|
||||
logWarn(QString("Failed to read encounter type constants from '%1': %2").arg(globalFieldmap).arg(error));
|
||||
error = QString();
|
||||
} else {
|
||||
for (auto i = defines.constBegin(); i != defines.constEnd(); i++) {
|
||||
this->encounterTypeToName.insert(static_cast<uint32_t>(i.value()), i.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (projectConfig.metatileTerrainTypeMask) {
|
||||
QMap<QString, int> defines = parser.readCDefinesByRegex(globalFieldmap, {projectConfig.getIdentifier(ProjectIdentifier::regex_terrain_types)}, &error);
|
||||
if (!error.isEmpty()) {
|
||||
logWarn(QString("Failed to read terrain type constants from '%1': %2").arg(globalFieldmap).arg(error));
|
||||
error = QString();
|
||||
} else {
|
||||
for (auto i = defines.constBegin(); i != defines.constEnd(); i++) {
|
||||
this->terrainTypeToName.insert(static_cast<uint32_t>(i.value()), i.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,19 +72,19 @@ QImage getMetatileImage(
|
|||
switch (layerType)
|
||||
{
|
||||
default:
|
||||
case METATILE_LAYER_MIDDLE_TOP:
|
||||
case Metatile::LayerType::Normal:
|
||||
if (l == 0)
|
||||
tile = Tile(projectConfig.unusedTileNormal);
|
||||
else // Tiles are on layers 1 and 2
|
||||
tile = metatile->tiles.value(tileOffset + ((l - 1) * 4));
|
||||
break;
|
||||
case METATILE_LAYER_BOTTOM_MIDDLE:
|
||||
case Metatile::LayerType::Covered:
|
||||
if (l == 2)
|
||||
tile = Tile(projectConfig.unusedTileCovered);
|
||||
else // Tiles are on layers 0 and 1
|
||||
tile = metatile->tiles.value(tileOffset + (l * 4));
|
||||
break;
|
||||
case METATILE_LAYER_BOTTOM_TOP:
|
||||
case Metatile::LayerType::Split:
|
||||
if (l == 1)
|
||||
tile = Tile(projectConfig.unusedTileSplit);
|
||||
else // Tiles are on layers 0 and 2
|
||||
|
|
|
|||
|
|
@ -134,10 +134,9 @@ void TilesetEditor::setAttributesUi() {
|
|||
|
||||
// Terrain Type
|
||||
if (projectConfig.metatileTerrainTypeMask) {
|
||||
this->ui->comboBox_terrainType->addItem("Normal", TERRAIN_NONE);
|
||||
this->ui->comboBox_terrainType->addItem("Grass", TERRAIN_GRASS);
|
||||
this->ui->comboBox_terrainType->addItem("Water", TERRAIN_WATER);
|
||||
this->ui->comboBox_terrainType->addItem("Waterfall", TERRAIN_WATERFALL);
|
||||
for (auto i = project->terrainTypeToName.constBegin(); i != project->terrainTypeToName.constEnd(); i++) {
|
||||
this->ui->comboBox_terrainType->addItem(i.value(), i.key());
|
||||
}
|
||||
this->ui->comboBox_terrainType->setEditable(false);
|
||||
this->ui->comboBox_terrainType->setMinimumContentsLength(0);
|
||||
} else {
|
||||
|
|
@ -147,9 +146,9 @@ void TilesetEditor::setAttributesUi() {
|
|||
|
||||
// Encounter Type
|
||||
if (projectConfig.metatileEncounterTypeMask) {
|
||||
this->ui->comboBox_encounterType->addItem("None", ENCOUNTER_NONE);
|
||||
this->ui->comboBox_encounterType->addItem("Land", ENCOUNTER_LAND);
|
||||
this->ui->comboBox_encounterType->addItem("Water", ENCOUNTER_WATER);
|
||||
for (auto i = project->encounterTypeToName.constBegin(); i != project->encounterTypeToName.constEnd(); i++) {
|
||||
this->ui->comboBox_encounterType->addItem(i.value(), i.key());
|
||||
}
|
||||
this->ui->comboBox_encounterType->setEditable(false);
|
||||
this->ui->comboBox_encounterType->setMinimumContentsLength(0);
|
||||
} else {
|
||||
|
|
@ -159,9 +158,9 @@ void TilesetEditor::setAttributesUi() {
|
|||
|
||||
// Layer Type
|
||||
if (!projectConfig.tripleLayerMetatilesEnabled) {
|
||||
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", METATILE_LAYER_MIDDLE_TOP);
|
||||
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", METATILE_LAYER_BOTTOM_MIDDLE);
|
||||
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", METATILE_LAYER_BOTTOM_TOP);
|
||||
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", Metatile::LayerType::Normal);
|
||||
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", Metatile::LayerType::Covered);
|
||||
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", Metatile::LayerType::Split);
|
||||
this->ui->comboBox_layerType->setEditable(false);
|
||||
this->ui->comboBox_layerType->setMinimumContentsLength(0);
|
||||
if (!projectConfig.metatileLayerTypeMask) {
|
||||
|
|
@ -607,6 +606,7 @@ void TilesetEditor::on_comboBox_layerType_activated(int layerType)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Needs to read data from item, not index of item.
|
||||
void TilesetEditor::on_comboBox_encounterType_activated(int encounterType)
|
||||
{
|
||||
if (this->metatile) {
|
||||
|
|
@ -616,6 +616,7 @@ void TilesetEditor::on_comboBox_encounterType_activated(int encounterType)
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Needs to read data from item, not index of item.
|
||||
void TilesetEditor::on_comboBox_terrainType_activated(int terrainType)
|
||||
{
|
||||
if (this->metatile) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user