From 0ad71286b11a8ecbc47d88029fa22db59eb20123 Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 12 Jun 2019 22:20:28 -0400 Subject: [PATCH] begin work on wild pokemon editor --- forms/mainwindow.ui | 60 +++++++++++++----- include/core/wildmoninfo.h | 31 +++++++++ include/editor.h | 2 + include/project.h | 7 +++ porymap.pro | 2 + src/core/wildmoninfo.cpp | 126 +++++++++++++++++++++++++++++++++++++ src/editor.cpp | 51 +++++++++++++++ src/mainwindow.cpp | 4 ++ src/project.cpp | 86 +++++++++++++++++++++++++ 9 files changed, 355 insertions(+), 14 deletions(-) create mode 100644 include/core/wildmoninfo.h create mode 100644 src/core/wildmoninfo.cpp diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 144e8268..36f07e34 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -237,7 +237,7 @@ - 0 + 4 false @@ -561,8 +561,8 @@ 0 0 - 522 - 601 + 545 + 587 @@ -876,8 +876,8 @@ 0 0 - 259 - 70 + 256 + 74 @@ -1064,10 +1064,10 @@ - 0 + 8 0 - 263 - 338 + 221 + 328 @@ -1344,8 +1344,8 @@ 0 0 - 385 - 652 + 371 + 643 @@ -1617,8 +1617,8 @@ 0 0 - 432 - 554 + 430 + 534 @@ -2531,8 +2531,8 @@ 0 0 - 829 - 543 + 818 + 539 @@ -2693,6 +2693,38 @@ + + + Wild Pokemon + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + 0 + + + + Land Mons + + + + + + + + + + diff --git a/include/core/wildmoninfo.h b/include/core/wildmoninfo.h new file mode 100644 index 00000000..de24cbcc --- /dev/null +++ b/include/core/wildmoninfo.h @@ -0,0 +1,31 @@ +#ifndef GUARD_WILDMONINFO_H +#define GUARD_WILDMONINFO_H + +#include + +struct WildPokemon { + int minLevel; + int maxLevel; + QString species; +}; + +struct WildMonInfo { + // + bool active = false; + int encounterRate; + QVector wildPokemon; +}; + +struct WildPokemonHeader { + WildMonInfo landMons; + WildMonInfo waterMons; + WildMonInfo rockSmashMons; + WildMonInfo fishingMons; +}; + +class Project; +QWidget *newSpeciesTableEntry(Project *project, WildPokemon mon, int index); +void createSpeciesTableRow(Project *, QTableWidget *, WildPokemon, int); +void clearTabWidget(QLayout *tab); + +#endif // GUARD_WILDMONINFO_H diff --git a/include/editor.h b/include/editor.h index 553868f2..002c9302 100644 --- a/include/editor.h +++ b/include/editor.h @@ -61,6 +61,8 @@ public: void setEditingCollision(); void setEditingObjects(); void setEditingConnections(); + void setEditingWildMons(); + void clearWildMonTabWidgets(); void setCurrentConnectionDirection(QString curDirection); void updateCurrentConnectionDirection(QString curDirection); void setConnectionsVisibility(bool visible); diff --git a/include/project.h b/include/project.h index da0ea2b0..83bc89db 100644 --- a/include/project.h +++ b/include/project.h @@ -5,6 +5,7 @@ #include "blockdata.h" #include "heallocation.h" #include "event.h" +#include "wildmoninfo.h" #include "parseutil.h" #include @@ -83,6 +84,12 @@ public: QString readMapLayoutId(QString map_name); QString readMapLocation(QString map_name); + void readWildMonData(); + QMap wildMonData;// "MAP_CONSTANT": wild_encounter_json + // when saving, preserve the extra fields for gBattlePyramidWildMonHeaders, gBattlePikeWildMonHeaders + void readSpeciesIconPaths(); + QMap speciesToIconPath; + QMap getTopLevelMapFields(); bool loadMapData(Map*); void readMapLayouts(); diff --git a/porymap.pro b/porymap.pro index 8a9574df..25401d79 100644 --- a/porymap.pro +++ b/porymap.pro @@ -29,6 +29,7 @@ SOURCES += src/core/block.cpp \ src/core/tile.cpp \ src/core/tileset.cpp \ src/core/regionmap.cpp \ + src/core/wildmoninfo.cpp \ src/ui/aboutporymap.cpp \ src/ui/bordermetatilespixmapitem.cpp \ src/ui/collisionpixmapitem.cpp \ @@ -88,6 +89,7 @@ HEADERS += include/core/block.h \ include/core/tile.h \ include/core/tileset.h \ include/core/regionmap.h \ + include/core/wildmoninfo.h \ include/ui/aboutporymap.h \ include/ui/bordermetatilespixmapitem.h \ include/ui/collisionpixmapitem.h \ diff --git a/src/core/wildmoninfo.cpp b/src/core/wildmoninfo.cpp new file mode 100644 index 00000000..509e01bd --- /dev/null +++ b/src/core/wildmoninfo.cpp @@ -0,0 +1,126 @@ +// + +#include "wildmoninfo.h" +#include "project.h" + + + +static QMap landPercentages = QMap({ + {1, "20"}, {2, "20"}, + {3, "10"}, {4, "10"}, {5, "10"}, {6, "10"}, + {7, "5"}, {8, "5"}, + {9, "4"}, {10, "4"}, + {11, "1"}, {12, "1"} +}); + +void clearTabWidget(QLayout *tab) { + QLayoutItem *item = tab->itemAt(0); + if (item) tab->removeItem(item); +} + +void createSpeciesTableRow(Project *project, QTableWidget *table, WildPokemon mon, int index) { + // + + + // + //QHBoxLayout *speciesHBox = new QHBoxLayout; + //QTableWidgetItem *monItem = new QTableWidgetItem(); + + QPixmap monIcon = QPixmap(project->speciesToIconPath.value(mon.species)).copy(0, 0, 32, 32); + + QLabel *monNum = new QLabel(QString("%1.").arg(QString::number(index))); + + QLabel *monLabel = new QLabel(); + monLabel->setPixmap(monIcon); + + QComboBox *monSelector = new QComboBox; + monSelector->addItems(project->speciesToIconPath.keys()); + monSelector->setCurrentText(mon.species); + monSelector->setEditable(true); + + QObject::connect(monSelector, &QComboBox::currentTextChanged, [=](QString newSpecies){ + QPixmap monIcon = QPixmap(project->speciesToIconPath.value(newSpecies)).copy(0, 0, 32, 32); + monLabel->setPixmap(monIcon); + }); + + QSpinBox *minLevel = new QSpinBox; + QSpinBox *maxLevel = new QSpinBox; + minLevel->setMinimum(1); + minLevel->setMaximum(100); + maxLevel->setMinimum(1); + maxLevel->setMaximum(100); + minLevel->setValue(mon.minLevel); + maxLevel->setValue(mon.maxLevel); + + // percentage -- add to json settings + QLabel *percentLabel = new QLabel(landPercentages[index]); + + QFrame *speciesSelector = new QFrame; + QHBoxLayout *speciesSelectorLayout = new QHBoxLayout; + speciesSelectorLayout->addWidget(monLabel); + speciesSelectorLayout->addWidget(monSelector); + speciesSelector->setLayout(speciesSelectorLayout); + + table->setCellWidget(index - 1, 0, monNum); + table->setCellWidget(index - 1, 1, speciesSelector); + //table->setCellWidget(index, 1, monLabel); + //table->setCellWidget(index, 2, monSelector); + table->setCellWidget(index - 1, 2, minLevel); + table->setCellWidget(index - 1, 3, maxLevel); + table->setCellWidget(index - 1, 4, percentLabel); +} + + +// +QWidget *newSpeciesTableEntry(Project *project, WildPokemon mon, int index) { + + QMap landPercentages = QMap({ + {1, "20"}, {2, "20"}, + {3, "10"}, {4, "10"}, {5, "10"}, {6, "10"}, + {7, "5"}, {8, "5"}, + {9, "4"}, {10, "4"}, + {11, "1"}, {12, "1"} + }); + + // + QHBoxLayout *speciesHBox = new QHBoxLayout; + QTableWidgetItem *monItem = new QTableWidgetItem(); + + QPixmap monIcon = QPixmap(project->speciesToIconPath.value(mon.species)).copy(0, 0, 32, 32); + + QLabel *monNum = new QLabel(QString("%1.").arg(QString::number(index))); + + QLabel *monLabel = new QLabel(); + monLabel->setPixmap(monIcon); + + QComboBox *monSelector = new QComboBox; + monSelector->addItems(project->speciesToIconPath.keys()); + monSelector->setCurrentText(mon.species); + monSelector->setEditable(true); + + QObject::connect(monSelector, &QComboBox::currentTextChanged, [=](QString newSpecies){ + QPixmap monIcon = QPixmap(project->speciesToIconPath.value(newSpecies)).copy(0, 0, 32, 32); + monLabel->setPixmap(monIcon); + }); + + QSpinBox *minLevel = new QSpinBox; + QSpinBox *maxLevel = new QSpinBox; + minLevel->setMinimum(1); + minLevel->setMaximum(100); + maxLevel->setMinimum(1); + maxLevel->setMaximum(100); + minLevel->setValue(mon.minLevel); + maxLevel->setValue(mon.maxLevel); + + // percentage + QLabel *percentLabel = new QLabel(landPercentages[index]); + + speciesHBox->addWidget(monNum); + speciesHBox->addWidget(monLabel); + speciesHBox->addWidget(monSelector); + speciesHBox->addWidget(minLevel); + speciesHBox->addWidget(maxLevel); + speciesHBox->addWidget(percentLabel); + + return (QWidget *)speciesHBox; +} diff --git a/src/editor.cpp b/src/editor.cpp index 06361e30..c7bf03b8 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -150,6 +150,57 @@ void Editor::setEditingConnections() { this->cursorMapTileRect->setVisibility(false); } +void Editor::setEditingWildMons() { + // clear the current layout + // + // move to loadMap? no because loadMap calls this anyways if it's open + + if (!project->wildMonData.contains(map->constantName)) return; + + //return;// TODO: REMOVE! + + //QFrame *landMonFrame = ui->frame_LandMonInfo; + + QLayout *landMonTab = ui->tab_LandMons->layout(); + + QTableWidget *landMonTable = new QTableWidget;//ui->tableWidget_RockSmashMonInfo; + + clearTabWidget(landMonTab); + + //QGridLayout *gridLayout = new QGridLayout(landMonFrame); + landMonTab->addWidget(landMonTable); + + //if (!landMonTable) + + //for (auto mon : project->wildMonData.value(map->constantName)) + WildPokemonHeader header = project->wildMonData.value(map->constantName); + + if (header.landMons.active) { // else, + int i = 1; + + landMonTable->setRowCount(header.landMons.wildPokemon.size()); + landMonTable->setColumnCount(5);// + 1 for last column stretch + + QStringList landMonTableHeaders; + landMonTableHeaders << "Index" << "Species" << "Min Level" << "Max Level" << "Catch Percentage"; + landMonTable->setHorizontalHeaderLabels(landMonTableHeaders); + landMonTable->verticalHeader()->hide(); + landMonTable->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + landMonTable->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + + landMonTable->setShowGrid(false); + + for (WildPokemon mon : header.landMons.wildPokemon) { + createSpeciesTableRow(project, landMonTable, mon, i); + i++; + } + } +} + +void Editor::clearWildMonTabWidgets() { + // +} + void Editor::setDiveEmergeControls() { ui->comboBox_DiveMap->blockSignals(true); ui->comboBox_EmergeMap->blockSignals(true); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 2cff4862..5cca1e11 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -612,6 +612,8 @@ void MainWindow::loadDataStructures() { project->readMetatileBehaviors(); project->readTilesetProperties(); project->readHealLocations(); + project->readSpeciesIconPaths(); + project->readWildMonData(); } void MainWindow::populateMapList() { @@ -1083,6 +1085,8 @@ void MainWindow::on_tabWidget_currentChanged(int index) editor->setEditingObjects(); } else if (index == 3) { editor->setEditingConnections(); + } else if (index == 4) { + editor->setEditingWildMons(); } } diff --git a/src/project.cpp b/src/project.cpp index cdb2769e..7ce40962 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -1305,6 +1305,84 @@ void Project::deleteFile(QString path) { } } +void Project::readWildMonData() { + // + QString wildMonJsonFilepath = QString("%1/src/data/wild_encounters.json").arg(root); + QJsonDocument wildMonsJsonDoc; + if (!parser.tryParseJsonFile(&wildMonsJsonDoc, wildMonJsonFilepath)) { + logError(QString("Failed to read wild encounters from %1").arg(wildMonJsonFilepath)); + return; + } + + QJsonObject wildMonObj = wildMonsJsonDoc.object(); + + for (auto subObjectRef : wildMonObj["wild_encounter_groups"].toArray()) { + QJsonObject subObject = subObjectRef.toObject(); + if (!subObject["for_maps"].toBool()) continue; + + //qDebug() << subObject["label"].toString(); + QJsonArray encounters = subObject["encounters"].toArray(); + for (QJsonValue encounter : encounters) { + // + //qDebug() << encounter["map"].toString(); + QString mapConstant = encounter["map"].toString(); + //QString mapName = mapConstantsToMapNames->value(mapConstant); + + WildPokemonHeader header; + + // land_mons, water_mons, rock_smash_mons, fishing_mons + if (encounter["land_mons"] != QJsonValue::Undefined) { + header.landMons.active = true; + header.landMons.encounterRate = encounter["land_mons"]["encounter_rate"].toInt(); + for (QJsonValue mon : encounter["land_mons"]["mons"].toArray()) { + header.landMons.wildPokemon.append({ + mon["min_level"].toInt(), + mon["max_level"].toInt(), + mon["species"].toString() + }); + } + } + if (encounter["water_mons"] != QJsonValue::Undefined) { + header.waterMons.active = true; + header.waterMons.encounterRate = encounter["water_mons"]["encounter_rate"].toInt(); + for (QJsonValue mon : encounter["water_mons"]["mons"].toArray()) { + header.waterMons.wildPokemon.append({ + mon["min_level"].toInt(), + mon["max_level"].toInt(), + mon["species"].toString() + }); + } + } + if (encounter["rock_smash_mons"] != QJsonValue::Undefined) { + header.rockSmashMons.active = true; + header.rockSmashMons.encounterRate = encounter["rock_smash_mons"]["encounter_rate"].toInt(); + for (QJsonValue mon : encounter["rock_smash_mons"]["mons"].toArray()) { + header.rockSmashMons.wildPokemon.append({ + mon["min_level"].toInt(), + mon["max_level"].toInt(), + mon["species"].toString() + }); + } + } + if (encounter["fishing_mons"] != QJsonValue::Undefined) { + header.fishingMons.active = true; + header.fishingMons.encounterRate = encounter["fishing_mons"]["encounter_rate"].toInt(); + for (QJsonValue mon : encounter["fishing_mons"]["mons"].toArray()) { + header.fishingMons.wildPokemon.append({ + mon["min_level"].toInt(), + mon["max_level"].toInt(), + mon["species"].toString() + }); + } + } + + wildMonData.insert(mapConstant, header); + } + } + + // +} + void Project::readMapGroups() { QString mapGroupsFilepath = QString("%1/data/maps/map_groups.json").arg(root); QJsonDocument mapGroupsDoc; @@ -1716,6 +1794,14 @@ void Project::loadEventPixmaps(QList objects) { } } +void Project::readSpeciesIconPaths() { + QMap monIconNames = parser.readNamedIndexCArray("src/pokemon_icon.c", "gMonIconTable"); + for (QString species : monIconNames.keys()) { + QString path = parser.readCIncbin("src/data/graphics/pokemon.h", monIconNames.value(species)); + speciesToIconPath.insert(species, root + "/" + path.replace("4bpp", "png")); + } +} + void Project::saveMapHealEvents(Map *map) { // save heal event changes if (map->events["heal_event_group"].length() > 0) {