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) {