diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 90b0cc15..e1e8810a 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -47,7 +47,7 @@ 0 0 272 - 539 + 625 @@ -198,30 +198,31 @@ false - - + + Metatile Label (Optional) - - - - - + + - Metatile Behavior + Layer Type - - - - - + + - Bottom/Top + Encounter Type + + + + + + + Terrain Type @@ -247,15 +248,15 @@ - - + + - Layer Type + Bottom/Top - - + + @@ -270,6 +271,38 @@ + + + + + + + + + + + + + Metatile Behavior + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -377,8 +410,8 @@ 0 0 - 400 - 367 + 384 + 265 @@ -394,19 +427,6 @@ 0 - - - - Qt::Horizontal - - - - 40 - 20 - - - - @@ -420,16 +440,6 @@ - - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - @@ -443,6 +453,29 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + @@ -471,7 +504,7 @@ 0 0 700 - 21 + 22 @@ -572,6 +605,13 @@ + + + NoScrollComboBox + QWidget +
noscrollcombobox.h
+
+
diff --git a/include/core/metatile.h b/include/core/metatile.h index b1be4d75..77a3c687 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -11,8 +11,10 @@ public: Metatile(); public: QList *tiles = nullptr; - uint8_t behavior; + uint16_t behavior; // 8 bits RSE, 9 bits FRLG uint8_t layerType; + uint8_t encounterType; // FRLG only + uint8_t terrainType; // FRLG only QString label; Metatile *copy(); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 1095b0be..f4205b38 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -77,6 +77,10 @@ private slots: void on_comboBox_layerType_activated(int arg1); + void on_comboBox_encounterType_activated(int arg1); + + void on_comboBox_terrainType_activated(int arg1); + void on_actionExport_Primary_Tiles_Image_triggered(); void on_actionExport_Secondary_Tiles_Image_triggered(); diff --git a/src/core/map.cpp b/src/core/map.cpp index 4f89c6c6..8573cc29 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -412,7 +412,6 @@ void Map::undo() { if (!commit) return; - if (layout->blockdata) { layout->blockdata->copyFrom(commit->metatiles); if (commit->layoutWidth != this->getWidth() || commit->layoutHeight != this->getHeight()) { diff --git a/src/core/metatile.cpp b/src/core/metatile.cpp index c35a7fcf..7bf3030d 100644 --- a/src/core/metatile.cpp +++ b/src/core/metatile.cpp @@ -11,6 +11,8 @@ Metatile* Metatile::copy() { Metatile *copy = new Metatile; copy->behavior = this->behavior; copy->layerType = this->layerType; + copy->encounterType = this->encounterType; + copy->terrainType = this->terrainType; copy->tiles = new QList; copy->label = this->label; for (Tile tile : *this->tiles) { @@ -22,6 +24,8 @@ Metatile* Metatile::copy() { void Metatile::copyInPlace(Metatile *other) { this->behavior = other->behavior; this->layerType = other->layerType; + this->encounterType = other->encounterType; + this->terrainType = other->terrainType; this->label = other->label; for (int i = 0; i < this->tiles->length(); i++) { (*this->tiles)[i] = other->tiles->at(i); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 89bc9bc5..c5130f2e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -995,6 +995,8 @@ void MainWindow::on_actionNew_Tileset_triggered() { } mt->behavior = 0; mt->layerType = 0; + mt->encounterType = 0; + mt->terrainType = 0; newSet->metatiles->append(mt); } diff --git a/src/project.cpp b/src/project.cpp index d48616b7..85640f2b 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -941,9 +941,21 @@ void Project::saveTilesetMetatileAttributes(Tileset *tileset) { QFile attrs_file(tileset->metatile_attrs_path); if (attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { QByteArray data; - for (Metatile *metatile : *tileset->metatiles) { - data.append(static_cast(metatile->behavior)); - data.append(static_cast((metatile->layerType << 4) & 0xF0)); + + if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) { + for (Metatile *metatile : *tileset->metatiles) { + data.append(static_cast(metatile->behavior)); + data.append(static_cast(metatile->behavior >> 8) | + static_cast(metatile->terrainType << 1)); + data.append(static_cast(0)); + data.append(static_cast(metatile->encounterType) | + static_cast(metatile->layerType << 5)); + } + } else { + for (Metatile *metatile : *tileset->metatiles) { + data.append(static_cast(metatile->behavior)); + data.append(static_cast((metatile->layerType << 4) & 0xF0)); + } } attrs_file.write(data); } else { @@ -1483,15 +1495,22 @@ void Project::loadTilesetMetatiles(Tileset* tileset) { if (num_metatileAttrs > num_metatiles) num_metatileAttrs = num_metatiles; } + bool unusedAttribute = false; for (int i = 0; i < num_metatileAttrs; i++) { int value = (static_cast(data.at(i * 4 + 3)) << 24) | (static_cast(data.at(i * 4 + 2)) << 16) | (static_cast(data.at(i * 4 + 1)) << 8) | (static_cast(data.at(i * 4 + 0))); - tileset->metatiles->at(i)->behavior = value & 0x1FF; + tileset->metatiles->at(i)->terrainType = (value & 0x3E00) >> 9; + tileset->metatiles->at(i)->encounterType = (value & 0x7000000) >> 24; tileset->metatiles->at(i)->layerType = (value & 0x60000000) >> 29; + if (value & ~(0x67003FFF)) + unusedAttribute = true; + logInfo(QString("").arg(tileset->metatiles->at(i)->terrainType)); } + if (unusedAttribute) + logWarn(QString("Unrecognized metatile attributes in %1 will not be saved.").arg(tileset->metatile_attrs_path)); } else { int num_metatileAttrs = data.length() / 2; if (num_metatiles != num_metatileAttrs) { @@ -1503,6 +1522,8 @@ void Project::loadTilesetMetatiles(Tileset* tileset) { int value = (static_cast(data.at(i * 2 + 1)) << 8) | static_cast(data.at(i * 2)); tileset->metatiles->at(i)->behavior = value & 0xFF; tileset->metatiles->at(i)->layerType = (value & 0xF000) >> 12; + tileset->metatiles->at(i)->encounterType = 0; + tileset->metatiles->at(i)->terrainType = 0; } } } else { @@ -1974,7 +1995,7 @@ bool Project::readMovementTypes() { } bool Project::readInitialFacingDirections() { - // TODO: This file is not yet decompiled in pokefirered. Remove once resolved + // TODO: This array is not yet decompiled in pokefirered. Remove once resolved if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) return true; QString filename = "src/event_object_movement.c"; diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 85b94c35..1c36e60d 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -5,6 +5,7 @@ #include "metatileparser.h" #include "paletteutil.h" #include "imageexport.h" +#include "config.h" #include #include #include @@ -61,6 +62,25 @@ void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString this->ui->spinBox_paletteSelector->setMinimum(0); this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1); + if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) { + this->ui->comboBox_encounterType->setVisible(true); + this->ui->label_encounterType->setVisible(true); + this->ui->comboBox_encounterType->addItem("None", 0); + this->ui->comboBox_encounterType->addItem("Grass", 1); + this->ui->comboBox_encounterType->addItem("Surf", 2); + this->ui->comboBox_terrainType->setVisible(true); + this->ui->label_terrainType->setVisible(true); + this->ui->comboBox_terrainType->addItem("Normal", 0); + this->ui->comboBox_terrainType->addItem("Grass", 1); + this->ui->comboBox_terrainType->addItem("Water", 2); + this->ui->comboBox_terrainType->addItem("Waterfall", 3); + } else { + this->ui->comboBox_encounterType->setVisible(false); + this->ui->label_encounterType->setVisible(false); + this->ui->comboBox_terrainType->setVisible(false); + this->ui->label_terrainType->setVisible(false); + } + //only allow characters valid for a symbol QRegExp expression("[_A-Za-z0-9]*$"); QRegExpValidator *validator = new QRegExpValidator(expression); @@ -206,6 +226,10 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->ui->comboBox_metatileBehaviors->setCurrentIndex(this->ui->comboBox_metatileBehaviors->findData(this->metatile->behavior)); this->ui->lineEdit_metatileLabel->setText(this->metatile->label); this->ui->comboBox_layerType->setCurrentIndex(this->ui->comboBox_layerType->findData(this->metatile->layerType)); + if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) { + this->ui->comboBox_encounterType->setCurrentIndex(this->ui->comboBox_encounterType->findData(this->metatile->encounterType)); + this->ui->comboBox_terrainType->setCurrentIndex(this->ui->comboBox_terrainType->findData(this->metatile->terrainType)); + } } void TilesetEditor::onHoveredTileChanged(uint16_t tile) { @@ -355,6 +379,26 @@ void TilesetEditor::on_comboBox_layerType_activated(int layerType) } } +void TilesetEditor::on_comboBox_encounterType_activated(int encounterType) +{ + if (this->metatile) { + Metatile *prevMetatile = this->metatile->copy(); + this->metatile->encounterType = static_cast(encounterType); + MetatileHistoryItem *commit = new MetatileHistoryItem(metatileSelector->getSelectedMetatile(), prevMetatile, this->metatile->copy()); + metatileHistory.push(commit); + } +} + +void TilesetEditor::on_comboBox_terrainType_activated(int terrainType) +{ + if (this->metatile) { + Metatile *prevMetatile = this->metatile->copy(); + this->metatile->terrainType = static_cast(terrainType); + MetatileHistoryItem *commit = new MetatileHistoryItem(metatileSelector->getSelectedMetatile(), prevMetatile, this->metatile->copy()); + metatileHistory.push(commit); + } +} + void TilesetEditor::on_actionSave_Tileset_triggered() { saveMetatileLabel(); @@ -559,6 +603,8 @@ void TilesetEditor::on_actionChange_Metatiles_Count_triggered() Metatile *metatile = new Metatile; metatile->behavior = 0; metatile->layerType = 0; + metatile->encounterType = 0; + metatile->terrainType = 0; for (int i = 0; i < 8; i++) { metatile->tiles->append(tile); } @@ -577,6 +623,8 @@ void TilesetEditor::on_actionChange_Metatiles_Count_triggered() Metatile *metatile = new Metatile; metatile->behavior = 0; metatile->layerType = 0; + metatile->encounterType = 0; + metatile->terrainType = 0; for (int i = 0; i < 8; i++) { metatile->tiles->append(tile); }