mirror of
https://github.com/huderlem/porymap.git
synced 2026-03-21 17:45:44 -05:00
Add search feature to wild pokemon tab
This commit is contained in:
parent
de78a1172d
commit
3bbb81e436
|
|
@ -122,6 +122,7 @@ In addition to these files, there are some specific symbol and macro names that
|
|||
``define_map_section_prefix``, ``MAPSEC_``, expected prefix for location macro names
|
||||
``define_map_section_empty``, ``NONE``, macro name after prefix for empty region map sections
|
||||
``define_species_prefix``, ``SPECIES_``, expected prefix for species macro names
|
||||
``define_species_empty``, ``NONE``, macro name after prefix for the default species
|
||||
``regex_behaviors``, ``\bMB_``, regex to find metatile behavior macro names
|
||||
``regex_obj_event_gfx``, ``\bOBJ_EVENT_GFX_``, regex to find Object Event graphics ID macro names
|
||||
``regex_items``, ``\bITEM_(?!(B_)?USE_)``, regex to find item macro names
|
||||
|
|
|
|||
|
|
@ -1740,7 +1740,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -1834,7 +1834,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -1928,7 +1928,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -2028,7 +2028,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -2122,7 +2122,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
|
|
@ -2700,8 +2700,8 @@
|
|||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>100</width>
|
||||
<height>30</height>
|
||||
<width>204</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="layout_ConnectionsList">
|
||||
|
|
@ -2845,6 +2845,17 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="toolButton_WildMonSearch">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/magnifier.ico</normaloff>:/icons/magnifier.ico</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
|||
94
forms/wildmonsearch.ui
Normal file
94
forms/wildmonsearch.ui
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>WildMonSearch</class>
|
||||
<widget class="QDialog" name="WildMonSearch">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>547</width>
|
||||
<height>329</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Wild Pokémon Search</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="searchBar">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Shape::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="speciesIcon">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../resources/images.qrc">:/images/pokemon_icon_placeholder.png</pixmap>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="NoScrollComboBox" name="comboBox_Search">
|
||||
<property name="editable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="insertPolicy">
|
||||
<enum>QComboBox::InsertPolicy::NoInsert</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="table_Results">
|
||||
<property name="columnCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>NoScrollComboBox</class>
|
||||
<extends>QComboBox</extends>
|
||||
<header>noscrollcombobox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../resources/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -221,6 +221,7 @@ enum ProjectIdentifier {
|
|||
define_map_section_prefix,
|
||||
define_map_section_empty,
|
||||
define_species_prefix,
|
||||
define_species_empty,
|
||||
regex_behaviors,
|
||||
regex_obj_event_gfx,
|
||||
regex_items,
|
||||
|
|
|
|||
|
|
@ -5,10 +5,14 @@
|
|||
#include <QtWidgets>
|
||||
#include "orderedmap.h"
|
||||
|
||||
struct WildPokemon {
|
||||
int minLevel = 5;
|
||||
int maxLevel = 5;
|
||||
QString species = "SPECIES_NONE"; // TODO: Use define_species_prefix
|
||||
class WildPokemon {
|
||||
public:
|
||||
WildPokemon();
|
||||
WildPokemon(int minLevel, int maxLevel, const QString &species);
|
||||
|
||||
int minLevel;
|
||||
int maxLevel;
|
||||
QString species;
|
||||
};
|
||||
|
||||
struct WildMonInfo {
|
||||
|
|
@ -30,7 +34,8 @@ struct EncounterField {
|
|||
typedef QVector<EncounterField> EncounterFields;
|
||||
|
||||
void setDefaultEncounterRate(QString fieldName, int rate);
|
||||
WildMonInfo getDefaultMonInfo(EncounterField field);
|
||||
WildMonInfo getDefaultMonInfo(const EncounterField &field);
|
||||
QVector<double> getWildEncounterPercentages(const EncounterField &field);
|
||||
void combineEncounters(WildMonInfo &to, WildMonInfo from);
|
||||
|
||||
#endif // GUARD_WILDMONINFO_H
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "gridsettings.h"
|
||||
#include "customscriptseditor.h"
|
||||
#include "wildmonchart.h"
|
||||
#include "wildmonsearch.h"
|
||||
#include "updatepromoter.h"
|
||||
#include "aboutporymap.h"
|
||||
#include "mapheaderform.h"
|
||||
|
|
@ -282,6 +283,7 @@ private slots:
|
|||
void on_pushButton_DeleteWildMonGroup_clicked();
|
||||
void on_pushButton_SummaryChart_clicked();
|
||||
void on_pushButton_ConfigureEncountersJSON_clicked();
|
||||
void on_toolButton_WildMonSearch_clicked();
|
||||
void on_pushButton_CreatePrefab_clicked();
|
||||
void on_spinBox_SelectedElevation_valueChanged(int elevation);
|
||||
void on_spinBox_SelectedCollision_valueChanged(int collision);
|
||||
|
|
@ -294,6 +296,7 @@ private slots:
|
|||
void reloadScriptEngine();
|
||||
void on_actionShow_Grid_triggered();
|
||||
void on_actionGrid_Settings_triggered();
|
||||
void openWildMonTable(const QString &mapName, const QString &groupName, const QString &fieldName);
|
||||
|
||||
public:
|
||||
Ui::MainWindow *ui;
|
||||
|
|
@ -321,6 +324,7 @@ private:
|
|||
QPointer<NetworkAccessManager> networkAccessManager = nullptr;
|
||||
QPointer<AboutPorymap> aboutWindow = nullptr;
|
||||
QPointer<WildMonChart> wildMonChart = nullptr;
|
||||
QPointer<WildMonSearch> wildMonSearch = nullptr;
|
||||
|
||||
QAction *undoAction = nullptr;
|
||||
QAction *redoAction = nullptr;
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ public:
|
|||
QVector<poryjson::Json::object> extraEncounterGroups;
|
||||
|
||||
bool readSpeciesIconPaths();
|
||||
QPixmap getSpeciesIcon(const QString &species) const;
|
||||
QMap<QString, QString> speciesToIconPath;
|
||||
|
||||
void addNewMapsec(const QString &idName);
|
||||
|
|
@ -238,6 +239,7 @@ public:
|
|||
static QString getEmptyMapDefineName();
|
||||
static QString getDynamicMapDefineName();
|
||||
static QString getDynamicMapName();
|
||||
static QString getEmptySpeciesName();
|
||||
static int getNumTilesPrimary();
|
||||
static int getNumTilesTotal();
|
||||
static int getNumMetatilesPrimary();
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class EncounterTableModel : public QAbstractTableModel {
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EncounterTableModel(WildMonInfo monInfo, EncounterFields allFields, int fieldIndex, QObject *parent = nullptr);
|
||||
EncounterTableModel(const WildMonInfo &monInfo, const EncounterField &field, QObject *parent = nullptr);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
|
@ -28,22 +28,17 @@ public:
|
|||
Slot, Group, Species, MinLevel, MaxLevel, EncounterChance, SlotRatio, EncounterRate, Count
|
||||
};
|
||||
|
||||
WildMonInfo encounterData() const { return this->monInfo; }
|
||||
EncounterField encounterField() const { return this->encounterFields.at(this->fieldIndex); }
|
||||
QList<double> percentages() const { return this->slotPercentages; }
|
||||
void resize(int rows, int cols);
|
||||
WildMonInfo encounterData() const { return m_monInfo; }
|
||||
EncounterField encounterField() const { return m_encounterField; }
|
||||
QList<double> percentages() const { return m_slotPercentages; }
|
||||
|
||||
private:
|
||||
WildMonInfo monInfo;
|
||||
EncounterFields encounterFields;
|
||||
int fieldIndex;
|
||||
|
||||
int numRows = 0;
|
||||
int numCols = 0;
|
||||
|
||||
QVector<int> slotRatios;
|
||||
QList<QString> groupNames;
|
||||
QList<double> slotPercentages;
|
||||
int m_numRows = 0;
|
||||
int m_numCols = 0;
|
||||
WildMonInfo m_monInfo;
|
||||
EncounterField m_encounterField;
|
||||
QMap<int,QString> m_groupNames;
|
||||
QList<double> m_slotPercentages;
|
||||
|
||||
signals:
|
||||
void edited();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ public:
|
|||
void copy(int index);
|
||||
void paste(int index);
|
||||
|
||||
void setCurrentField(const QString &fieldName);
|
||||
|
||||
public slots:
|
||||
void setTabActive(int index, bool active = true);
|
||||
void deactivateTab(int tabIndex);
|
||||
|
|
@ -38,6 +40,7 @@ private:
|
|||
QVector<bool> activeTabs;
|
||||
QVector<QPushButton *> addDeleteTabButtons;
|
||||
QVector<QPushButton *> copyTabButtons;
|
||||
QMap<QString,int> fieldNameToIndex;
|
||||
|
||||
Editor *editor;
|
||||
};
|
||||
|
|
|
|||
47
include/ui/wildmonsearch.h
Normal file
47
include/ui/wildmonsearch.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef WILDMONSEARCH_H
|
||||
#define WILDMONSEARCH_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class Project;
|
||||
|
||||
namespace Ui {
|
||||
class WildMonSearch;
|
||||
}
|
||||
|
||||
class WildMonSearch : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit WildMonSearch(Project *project, QWidget *parent = nullptr);
|
||||
~WildMonSearch();
|
||||
|
||||
void refresh();
|
||||
|
||||
signals:
|
||||
void openWildMonTableRequested(const QString &mapName, const QString &groupName, const QString &fieldName);
|
||||
|
||||
private:
|
||||
struct RowData {
|
||||
QString mapName;
|
||||
QString groupName;
|
||||
QString fieldName;
|
||||
QString levelRange;
|
||||
QString chance;
|
||||
};
|
||||
|
||||
Ui::WildMonSearch *ui;
|
||||
Project *const project;
|
||||
QMap<QString,QMap<int,QString>> percentageStrings;
|
||||
QMap<QString,QList<RowData>> resultsCache;
|
||||
|
||||
void addTableEntry(const RowData &rowData);
|
||||
QList<RowData> search(const QString &species) const;
|
||||
void updatePercentageStrings();
|
||||
void updateResults(const QString &species);
|
||||
void cellDoubleClicked(int row, int column);
|
||||
|
||||
};
|
||||
|
||||
#endif // WILDMONSEARCH_H
|
||||
|
|
@ -139,7 +139,8 @@ SOURCES += src/core/advancemapparser.cpp \
|
|||
src/log.cpp \
|
||||
src/ui/uintspinbox.cpp \
|
||||
src/ui/updatepromoter.cpp \
|
||||
src/ui/wildmonchart.cpp
|
||||
src/ui/wildmonchart.cpp \
|
||||
src/ui/wildmonsearch.cpp
|
||||
|
||||
HEADERS += include/core/advancemapparser.h \
|
||||
include/core/block.h \
|
||||
|
|
@ -251,7 +252,8 @@ HEADERS += include/core/advancemapparser.h \
|
|||
include/log.h \
|
||||
include/ui/uintspinbox.h \
|
||||
include/ui/updatepromoter.h \
|
||||
include/ui/wildmonchart.h
|
||||
include/ui/wildmonchart.h \
|
||||
include/ui/wildmonsearch.h
|
||||
|
||||
FORMS += forms/mainwindow.ui \
|
||||
forms/colorinputwidget.ui \
|
||||
|
|
@ -281,7 +283,8 @@ FORMS += forms/mainwindow.ui \
|
|||
forms/customscriptseditor.ui \
|
||||
forms/customscriptslistitem.ui \
|
||||
forms/updatepromoter.ui \
|
||||
forms/wildmonchart.ui
|
||||
forms/wildmonchart.ui \
|
||||
forms/wildmonsearch.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources/images.qrc \
|
||||
|
|
|
|||
BIN
resources/icons/magnifier.ico
Executable file
BIN
resources/icons/magnifier.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
|
|
@ -25,6 +25,7 @@
|
|||
<file>icons/help.ico</file>
|
||||
<file>icons/link_broken.ico</file>
|
||||
<file>icons/link.ico</file>
|
||||
<file>icons/magnifier.ico</file>
|
||||
<file>icons/map_edited.ico</file>
|
||||
<file>icons/map_opened.ico</file>
|
||||
<file>icons/map.ico</file>
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
|||
{ProjectIdentifier::define_map_section_prefix, {"define_map_section_prefix", "MAPSEC_"}},
|
||||
{ProjectIdentifier::define_map_section_empty, {"define_map_section_empty", "NONE"}},
|
||||
{ProjectIdentifier::define_species_prefix, {"define_species_prefix", "SPECIES_"}},
|
||||
{ProjectIdentifier::define_species_empty, {"define_species_empty", "NONE"}},
|
||||
// Regex
|
||||
{ProjectIdentifier::regex_behaviors, {"regex_behaviors", "\\bMB_"}},
|
||||
{ProjectIdentifier::regex_obj_event_gfx, {"regex_obj_event_gfx", "\\bOBJ_EVENT_GFX_"}},
|
||||
|
|
|
|||
|
|
@ -1,12 +1,22 @@
|
|||
#include "wildmoninfo.h"
|
||||
#include "montabwidget.h"
|
||||
#include "project.h"
|
||||
|
||||
WildPokemon::WildPokemon(int minLevel, int maxLevel, const QString &species)
|
||||
: minLevel(minLevel),
|
||||
maxLevel(maxLevel),
|
||||
species(species)
|
||||
{}
|
||||
|
||||
WildPokemon::WildPokemon() : WildPokemon(5, 5, Project::getEmptySpeciesName())
|
||||
{}
|
||||
|
||||
QMap<QString, int> defaultEncounterRates;
|
||||
void setDefaultEncounterRate(QString fieldName, int rate) {
|
||||
defaultEncounterRates[fieldName] = rate;
|
||||
}
|
||||
|
||||
WildMonInfo getDefaultMonInfo(EncounterField field) {
|
||||
WildMonInfo getDefaultMonInfo(const EncounterField &field) {
|
||||
WildMonInfo newInfo;
|
||||
newInfo.active = true;
|
||||
newInfo.encounterRate = defaultEncounterRates.value(field.name, 1);
|
||||
|
|
@ -18,6 +28,38 @@ WildMonInfo getDefaultMonInfo(EncounterField field) {
|
|||
return newInfo;
|
||||
}
|
||||
|
||||
QVector<double> getWildEncounterPercentages(const EncounterField &field) {
|
||||
QVector<double> percentages(field.encounterRates.size(), 0);
|
||||
|
||||
if (!field.groups.empty()) {
|
||||
// This encounter field is broken up into groups (e.g. for fishing rod types).
|
||||
// Each group's percentages will be relative to the group total, not the overall total.
|
||||
for (auto groupKeyPair : field.groups) {
|
||||
int groupTotal = 0;
|
||||
for (int slot : groupKeyPair.second) {
|
||||
groupTotal += field.encounterRates.value(slot, 0);
|
||||
}
|
||||
if (groupTotal != 0) {
|
||||
for (int slot : groupKeyPair.second) {
|
||||
percentages[slot] = static_cast<double>(field.encounterRates.value(slot, 0)) / static_cast<double>(groupTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This encounter field has a single group, percentages are relative to the overall total.
|
||||
int groupTotal = 0;
|
||||
for (int chance : field.encounterRates) {
|
||||
groupTotal += chance;
|
||||
}
|
||||
if (groupTotal != 0) {
|
||||
for (int slot = 0; slot < percentages.count(); slot++) {
|
||||
percentages[slot] = static_cast<double>(field.encounterRates.value(slot, 0)) / static_cast<double>(groupTotal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return percentages;
|
||||
}
|
||||
|
||||
void combineEncounters(WildMonInfo &to, WildMonInfo from) {
|
||||
to.encounterRate = from.encounterRate;
|
||||
|
||||
|
|
|
|||
|
|
@ -302,7 +302,7 @@ void Editor::addNewWildMonGroup(QWidget *window) {
|
|||
form.addRow(new QLabel("Group Base Label:"), lineEdit);
|
||||
lineEdit->setValidator(new IdentifierValidator(lineEdit));
|
||||
connect(lineEdit, &QLineEdit::textChanged, [this, &lineEdit, &buttonBox](QString text){
|
||||
if (this->project->encounterGroupLabels.contains(text)) {
|
||||
if (!this->project->isIdentifierUnique(text)) {
|
||||
lineEdit->setStyleSheet("QLineEdit { background-color: rgba(255, 0, 0, 25%) }");
|
||||
buttonBox.button(QDialogButtonBox::Ok)->setDisabled(true);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -2537,6 +2537,25 @@ void MainWindow::on_pushButton_SummaryChart_clicked() {
|
|||
openSubWindow(this->wildMonChart);
|
||||
}
|
||||
|
||||
void MainWindow::on_toolButton_WildMonSearch_clicked() {
|
||||
if (!this->wildMonSearch) {
|
||||
this->wildMonSearch = new WildMonSearch(this->editor->project, this);
|
||||
connect(this->wildMonSearch, &WildMonSearch::openWildMonTableRequested, this, &MainWindow::openWildMonTable);
|
||||
connect(this->editor, &Editor::wildMonTableEdited, this->wildMonSearch, &WildMonSearch::refresh);
|
||||
}
|
||||
openSubWindow(this->wildMonSearch);
|
||||
}
|
||||
|
||||
void MainWindow::openWildMonTable(const QString &mapName, const QString &groupName, const QString &fieldName) {
|
||||
if (userSetMap(mapName)) {
|
||||
// Switch to the correct main tab, wild encounter group, and wild encounter type tab.
|
||||
on_mainTabBar_tabBarClicked(MainTab::WildPokemon);
|
||||
ui->comboBox_EncounterGroupLabel->setCurrentText(groupName);
|
||||
QWidget *w = ui->stackedWidget_WildMons->currentWidget();
|
||||
if (w) static_cast<MonTabWidget *>(w)->setCurrentField(fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_pushButton_ConfigureEncountersJSON_clicked() {
|
||||
editor->configureEncounterJSON(this);
|
||||
}
|
||||
|
|
@ -2984,33 +3003,21 @@ void MainWindow::clearOverlay() {
|
|||
// delete is happening too late and some of the pointers haven't been cleared by the time we need them to,
|
||||
// so we nullify them all here anyway.
|
||||
bool MainWindow::closeSupplementaryWindows() {
|
||||
if (this->tilesetEditor && !this->tilesetEditor->close())
|
||||
return false;
|
||||
this->tilesetEditor = nullptr;
|
||||
#define SAFE_CLOSE(window) \
|
||||
do { \
|
||||
if ((window) && !(window)->close()) \
|
||||
return false; \
|
||||
window = nullptr; \
|
||||
} while (0);
|
||||
|
||||
if (this->regionMapEditor && !this->regionMapEditor->close())
|
||||
return false;
|
||||
this->regionMapEditor = nullptr;
|
||||
|
||||
if (this->mapImageExporter && !this->mapImageExporter->close())
|
||||
return false;
|
||||
this->mapImageExporter = nullptr;
|
||||
|
||||
if (this->shortcutsEditor && !this->shortcutsEditor->close())
|
||||
return false;
|
||||
this->shortcutsEditor = nullptr;
|
||||
|
||||
if (this->preferenceEditor && !this->preferenceEditor->close())
|
||||
return false;
|
||||
this->preferenceEditor = nullptr;
|
||||
|
||||
if (this->customScriptsEditor && !this->customScriptsEditor->close())
|
||||
return false;
|
||||
this->customScriptsEditor = nullptr;
|
||||
|
||||
if (this->wildMonChart && !this->wildMonChart->close())
|
||||
return false;
|
||||
this->wildMonChart = nullptr;
|
||||
SAFE_CLOSE(this->tilesetEditor);
|
||||
SAFE_CLOSE(this->regionMapEditor);
|
||||
SAFE_CLOSE(this->mapImageExporter);
|
||||
SAFE_CLOSE(this->shortcutsEditor);
|
||||
SAFE_CLOSE(this->preferenceEditor);
|
||||
SAFE_CLOSE(this->customScriptsEditor);
|
||||
SAFE_CLOSE(this->wildMonChart);
|
||||
SAFE_CLOSE(this->wildMonSearch);
|
||||
|
||||
if (this->projectSettingsEditor) this->projectSettingsEditor->closeQuietly();
|
||||
this->projectSettingsEditor = nullptr;
|
||||
|
|
|
|||
|
|
@ -1721,11 +1721,11 @@ bool Project::readWildMonData() {
|
|||
for (OrderedJson subObjectRef : wildMonObj["wild_encounter_groups"].array_items()) {
|
||||
OrderedJson::object subObject = subObjectRef.object_items();
|
||||
if (!subObject["for_maps"].bool_value()) {
|
||||
extraEncounterGroups.push_back(subObject);
|
||||
this->extraEncounterGroups.push_back(subObject);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (OrderedJson field : subObject["fields"].array_items()) {
|
||||
for (const OrderedJson &field : subObject["fields"].array_items()) {
|
||||
EncounterField encounterField;
|
||||
OrderedJson::object fieldObj = field.object_items();
|
||||
encounterField.name = fieldObj["type"].string_value();
|
||||
|
|
@ -1744,17 +1744,17 @@ bool Project::readWildMonData() {
|
|||
}
|
||||
}
|
||||
encounterRateFrequencyMaps.insert(encounterField.name, QMap<int, int>());
|
||||
wildMonFields.append(encounterField);
|
||||
this->wildMonFields.append(encounterField);
|
||||
}
|
||||
|
||||
auto encounters = subObject["encounters"].array_items();
|
||||
for (auto encounter : encounters) {
|
||||
for (const auto &encounter : encounters) {
|
||||
OrderedJson::object encounterObj = encounter.object_items();
|
||||
QString mapConstant = encounterObj["map"].string_value();
|
||||
|
||||
WildPokemonHeader header;
|
||||
|
||||
for (EncounterField monField : wildMonFields) {
|
||||
for (const EncounterField &monField : this->wildMonFields) {
|
||||
QString field = monField.name;
|
||||
if (!encounterObj[field].is_null()) {
|
||||
OrderedJson::object encounterFieldObj = encounterObj[field].object_items();
|
||||
|
|
@ -1776,8 +1776,8 @@ bool Project::readWildMonData() {
|
|||
}
|
||||
}
|
||||
}
|
||||
wildMonData[mapConstant].insert({encounterObj["base_label"].string_value(), header});
|
||||
encounterGroupLabels.append(encounterObj["base_label"].string_value());
|
||||
this->wildMonData[mapConstant].insert({encounterObj["base_label"].string_value(), header});
|
||||
this->encounterGroupLabels.append(encounterObj["base_label"].string_value());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1975,6 +1975,8 @@ bool Project::isIdentifierUnique(const QString &identifier) const {
|
|||
}
|
||||
if (identifier == getEmptyMapDefineName())
|
||||
return false;
|
||||
if (this->encounterGroupLabels.contains(identifier))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2981,6 +2983,31 @@ bool Project::readSpeciesIconPaths() {
|
|||
return true;
|
||||
}
|
||||
|
||||
QPixmap Project::getSpeciesIcon(const QString &species) const {
|
||||
QPixmap pixmap;
|
||||
if (!QPixmapCache::find(species, &pixmap)) {
|
||||
// Prefer path from config. If not present, use the path parsed from project files
|
||||
QString path = projectConfig.getPokemonIconPath(species);
|
||||
if (path.isEmpty()) {
|
||||
path = this->speciesToIconPath.value(species);
|
||||
} else {
|
||||
path = Project::getExistingFilepath(path);
|
||||
}
|
||||
|
||||
QImage img(path);
|
||||
if (img.isNull()) {
|
||||
// No icon for this species, use placeholder
|
||||
static const QPixmap placeholder = QPixmap(QStringLiteral(":images/pokemon_icon_placeholder.png"));
|
||||
pixmap = placeholder;
|
||||
} else {
|
||||
img.setColor(0, qRgba(0, 0, 0, 0));
|
||||
pixmap = QPixmap::fromImage(img).copy(0, 0, 32, 32);
|
||||
QPixmapCache::insert(species, pixmap);
|
||||
}
|
||||
}
|
||||
return pixmap;
|
||||
}
|
||||
|
||||
int Project::getNumTilesPrimary()
|
||||
{
|
||||
return Project::num_tiles_primary;
|
||||
|
|
@ -3067,19 +3094,21 @@ int Project::getMaxObjectEvents()
|
|||
}
|
||||
|
||||
QString Project::getEmptyMapDefineName() {
|
||||
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
||||
return prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_empty);
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_map_empty);
|
||||
}
|
||||
|
||||
QString Project::getDynamicMapDefineName() {
|
||||
const QString prefix = projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix);
|
||||
return prefix + projectConfig.getIdentifier(ProjectIdentifier::define_map_dynamic);
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::define_map_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_map_dynamic);
|
||||
}
|
||||
|
||||
QString Project::getDynamicMapName() {
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::symbol_dynamic_map_name);
|
||||
}
|
||||
|
||||
QString Project::getEmptySpeciesName() {
|
||||
return projectConfig.getIdentifier(ProjectIdentifier::define_species_prefix) + projectConfig.getIdentifier(ProjectIdentifier::define_species_empty);
|
||||
}
|
||||
|
||||
// If the provided filepath is an absolute path to an existing file, return filepath.
|
||||
// If not, and the provided filepath is a relative path from the project dir to an existing file, return the relative path.
|
||||
// Otherwise return empty string.
|
||||
|
|
|
|||
|
|
@ -12,30 +12,8 @@ SpeciesComboDelegate::SpeciesComboDelegate(Project *project, QObject *parent) :
|
|||
}
|
||||
|
||||
void SpeciesComboDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
|
||||
QString species = index.data(Qt::DisplayRole).toString();
|
||||
|
||||
QPixmap pm;
|
||||
if (!QPixmapCache::find(species, &pm)) {
|
||||
// Prefer path from config. If not present, use the path parsed from project files
|
||||
QString path = projectConfig.getPokemonIconPath(species);
|
||||
if (path.isEmpty()) {
|
||||
path = this->project->speciesToIconPath.value(species);
|
||||
} else {
|
||||
path = Project::getExistingFilepath(path);
|
||||
}
|
||||
|
||||
QImage img(path);
|
||||
if (img.isNull()) {
|
||||
// No icon for this species, use placeholder
|
||||
pm = QPixmap(":images/pokemon_icon_placeholder.png");
|
||||
} else {
|
||||
img.setColor(0, qRgba(0, 0, 0, 0));
|
||||
pm = QPixmap::fromImage(img);
|
||||
}
|
||||
QPixmapCache::insert(species, pm);
|
||||
}
|
||||
QPixmap monIcon = pm.copy(0, 0, 32, 32);
|
||||
|
||||
const QString species = index.data(Qt::DisplayRole).toString();
|
||||
const QPixmap monIcon = this->project->getSpeciesIcon(species);
|
||||
painter->drawText(QRect(option.rect.topLeft() + QPoint(36, 0), option.rect.bottomRight()), Qt::AlignLeft | Qt::AlignVCenter, species);
|
||||
painter->drawPixmap(QRect(option.rect.topLeft(), QSize(32, 32)), monIcon, monIcon.rect());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,52 +3,27 @@
|
|||
|
||||
|
||||
|
||||
EncounterTableModel::EncounterTableModel(WildMonInfo info, EncounterFields fields, int index, QObject *parent) : QAbstractTableModel(parent) {
|
||||
this->fieldIndex = index;
|
||||
this->encounterFields = fields;
|
||||
this->monInfo = info;
|
||||
|
||||
this->resize(this->monInfo.wildPokemon.size(), ColumnType::Count);
|
||||
|
||||
for (int r = 0; r < this->numRows; r++) {
|
||||
this->groupNames.append(QString());
|
||||
this->slotPercentages.append(0.0);
|
||||
this->slotRatios.append(fields[fieldIndex].encounterRates.value(r, 0));
|
||||
}
|
||||
|
||||
if (!this->encounterFields[this->fieldIndex].groups.empty()) {
|
||||
for (auto groupKeyPair : fields[fieldIndex].groups) {
|
||||
int groupTotal = 0;
|
||||
for (int i : groupKeyPair.second) {
|
||||
this->groupNames[i] = groupKeyPair.first;
|
||||
groupTotal += this->slotRatios[i];
|
||||
}
|
||||
for (int i : groupKeyPair.second) {
|
||||
this->slotPercentages[i] = static_cast<double>(this->slotRatios[i]) / static_cast<double>(groupTotal);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int groupTotal = 0;
|
||||
for (int chance : this->encounterFields[this->fieldIndex].encounterRates) {
|
||||
groupTotal += chance;
|
||||
}
|
||||
for (int i = 0; i < this->slotPercentages.count(); i++) {
|
||||
this->slotPercentages[i] = static_cast<double>(this->slotRatios[i]) / static_cast<double>(groupTotal);
|
||||
EncounterTableModel::EncounterTableModel(const WildMonInfo &info, const EncounterField &field, QObject *parent)
|
||||
: QAbstractTableModel(parent),
|
||||
m_numRows(info.wildPokemon.size()),
|
||||
m_numCols(ColumnType::Count),
|
||||
m_monInfo(info),
|
||||
m_encounterField(field),
|
||||
m_slotPercentages(getWildEncounterPercentages(field))
|
||||
{
|
||||
for (const auto &groupKeyPair : m_encounterField.groups) {
|
||||
for (const auto &slot : groupKeyPair.second) {
|
||||
m_groupNames.insert(slot, groupKeyPair.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EncounterTableModel::resize(int rows, int cols) {
|
||||
this->numRows = rows;
|
||||
this->numCols = cols;
|
||||
}
|
||||
|
||||
int EncounterTableModel::rowCount(const QModelIndex &) const {
|
||||
return this->numRows;
|
||||
return m_numRows;
|
||||
}
|
||||
|
||||
int EncounterTableModel::columnCount(const QModelIndex &) const {
|
||||
return this->numCols;
|
||||
return m_numCols;
|
||||
}
|
||||
|
||||
QVariant EncounterTableModel::data(const QModelIndex &index, int role) const {
|
||||
|
|
@ -61,26 +36,26 @@ QVariant EncounterTableModel::data(const QModelIndex &index, int role) const {
|
|||
return row;
|
||||
|
||||
case ColumnType::Group:
|
||||
return this->groupNames[row];
|
||||
return m_groupNames.value(row);
|
||||
|
||||
case ColumnType::Species:
|
||||
return this->monInfo.wildPokemon[row].species;
|
||||
return m_monInfo.wildPokemon.value(row).species;
|
||||
|
||||
case ColumnType::MinLevel:
|
||||
return this->monInfo.wildPokemon[row].minLevel;
|
||||
return m_monInfo.wildPokemon.value(row).minLevel;
|
||||
|
||||
case ColumnType::MaxLevel:
|
||||
return this->monInfo.wildPokemon[row].maxLevel;
|
||||
return m_monInfo.wildPokemon.value(row).maxLevel;
|
||||
|
||||
case ColumnType::EncounterChance:
|
||||
return QString::number(this->slotPercentages[row] * 100.0, 'f', 2) + "%";
|
||||
return QString::number(m_slotPercentages.value(row, 0) * 100, 'f', 2) + "%";
|
||||
|
||||
case ColumnType::SlotRatio:
|
||||
return this->slotRatios[row];
|
||||
return m_encounterField.encounterRates.value(row);
|
||||
|
||||
case ColumnType::EncounterRate:
|
||||
if (row == 0) {
|
||||
return this->monInfo.encounterRate;
|
||||
return m_monInfo.encounterRate;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
|
|
@ -92,17 +67,17 @@ QVariant EncounterTableModel::data(const QModelIndex &index, int role) const {
|
|||
else if (role == Qt::EditRole) {
|
||||
switch (col) {
|
||||
case ColumnType::Species:
|
||||
return this->monInfo.wildPokemon[row].species;
|
||||
return m_monInfo.wildPokemon.value(row).species;
|
||||
|
||||
case ColumnType::MinLevel:
|
||||
return this->monInfo.wildPokemon[row].minLevel;
|
||||
return m_monInfo.wildPokemon.value(row).minLevel;
|
||||
|
||||
case ColumnType::MaxLevel:
|
||||
return this->monInfo.wildPokemon[row].maxLevel;
|
||||
return m_monInfo.wildPokemon.value(row).maxLevel;
|
||||
|
||||
case ColumnType::EncounterRate:
|
||||
if (row == 0) {
|
||||
return this->monInfo.encounterRate;
|
||||
return m_monInfo.encounterRate;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
|
|
@ -149,12 +124,13 @@ bool EncounterTableModel::setData(const QModelIndex &index, const QVariant &valu
|
|||
|
||||
int row = index.row();
|
||||
int col = index.column();
|
||||
auto wildMon = &m_monInfo.wildPokemon[row];
|
||||
|
||||
switch (col) {
|
||||
case ColumnType::Species: {
|
||||
QString species = value.toString();
|
||||
if (this->monInfo.wildPokemon[row].species != species) {
|
||||
this->monInfo.wildPokemon[row].species = species;
|
||||
if (wildMon->species != species) {
|
||||
wildMon->species = species;
|
||||
emit edited();
|
||||
}
|
||||
break;
|
||||
|
|
@ -162,9 +138,9 @@ bool EncounterTableModel::setData(const QModelIndex &index, const QVariant &valu
|
|||
|
||||
case ColumnType::MinLevel: {
|
||||
int minLevel = value.toInt();
|
||||
if (this->monInfo.wildPokemon[row].minLevel != minLevel) {
|
||||
this->monInfo.wildPokemon[row].minLevel = minLevel;
|
||||
this->monInfo.wildPokemon[row].maxLevel = qMax(minLevel, this->monInfo.wildPokemon[row].maxLevel);
|
||||
if (wildMon->minLevel != minLevel) {
|
||||
wildMon->minLevel = minLevel;
|
||||
wildMon->maxLevel = qMax(minLevel, wildMon->maxLevel);
|
||||
emit edited();
|
||||
}
|
||||
break;
|
||||
|
|
@ -172,9 +148,9 @@ bool EncounterTableModel::setData(const QModelIndex &index, const QVariant &valu
|
|||
|
||||
case ColumnType::MaxLevel: {
|
||||
int maxLevel = value.toInt();
|
||||
if (this->monInfo.wildPokemon[row].maxLevel != maxLevel) {
|
||||
this->monInfo.wildPokemon[row].maxLevel = maxLevel;
|
||||
this->monInfo.wildPokemon[row].minLevel = qMin(maxLevel, this->monInfo.wildPokemon[row].minLevel);
|
||||
if (wildMon->maxLevel != maxLevel) {
|
||||
wildMon->maxLevel = maxLevel;
|
||||
wildMon->minLevel = qMin(maxLevel, wildMon->minLevel);
|
||||
emit edited();
|
||||
}
|
||||
break;
|
||||
|
|
@ -182,8 +158,8 @@ bool EncounterTableModel::setData(const QModelIndex &index, const QVariant &valu
|
|||
|
||||
case ColumnType::EncounterRate: {
|
||||
int encounterRate = value.toInt();
|
||||
if (this->monInfo.encounterRate != encounterRate) {
|
||||
this->monInfo.encounterRate = encounterRate;
|
||||
if (m_monInfo.encounterRate != encounterRate) {
|
||||
m_monInfo.encounterRate = encounterRate;
|
||||
emit edited();
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ void MonTabWidget::populate() {
|
|||
copyTabButtons.resize(fields.size());
|
||||
copyTabButtons.fill(nullptr);
|
||||
|
||||
this->fieldNameToIndex.clear();
|
||||
|
||||
int index = 0;
|
||||
for (EncounterField field : fields) {
|
||||
QTableView *table = new QTableView(this);
|
||||
|
|
@ -45,7 +47,7 @@ void MonTabWidget::populate() {
|
|||
connect(buttonCopy, &QPushButton::clicked, [=]() {actionCopyTab(index); });
|
||||
copyTabButtons[index] = buttonCopy;
|
||||
this->tabBar()->setTabButton(index, QTabBar::LeftSide, buttonCopy);
|
||||
|
||||
this->fieldNameToIndex.insert(field.name, index);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
|
@ -111,7 +113,7 @@ void MonTabWidget::deactivateTab(int tabIndex) {
|
|||
EncounterTableModel *oldModel = static_cast<EncounterTableModel *>(speciesTable->model());
|
||||
WildMonInfo monInfo = oldModel->encounterData();
|
||||
monInfo.active = false;
|
||||
EncounterTableModel *newModel = new EncounterTableModel(monInfo, editor->project->wildMonFields, tabIndex, this);
|
||||
EncounterTableModel *newModel = new EncounterTableModel(monInfo, editor->project->wildMonFields[tabIndex], this);
|
||||
speciesTable->setModel(newModel);
|
||||
|
||||
setTabActive(tabIndex, false);
|
||||
|
|
@ -120,7 +122,7 @@ void MonTabWidget::deactivateTab(int tabIndex) {
|
|||
void MonTabWidget::populateTab(int tabIndex, WildMonInfo monInfo) {
|
||||
QTableView *speciesTable = tableAt(tabIndex);
|
||||
|
||||
EncounterTableModel *model = new EncounterTableModel(monInfo, editor->project->wildMonFields, tabIndex, this);
|
||||
EncounterTableModel *model = new EncounterTableModel(monInfo, editor->project->wildMonFields[tabIndex], this);
|
||||
connect(model, &EncounterTableModel::edited, editor, &Editor::saveEncounterTabData);
|
||||
connect(model, &EncounterTableModel::edited, editor, &Editor::wildMonTableEdited);
|
||||
speciesTable->setModel(model);
|
||||
|
|
@ -167,3 +169,8 @@ void MonTabWidget::setTabActive(int index, bool active) {
|
|||
this->copyTabButtons[index]->show();
|
||||
}
|
||||
}
|
||||
|
||||
void MonTabWidget::setCurrentField(const QString &fieldName) {
|
||||
int index = this->fieldNameToIndex.value(fieldName, -1);
|
||||
if (index >= 0) setCurrentIndex(index);
|
||||
}
|
||||
|
|
|
|||
158
src/ui/wildmonsearch.cpp
Normal file
158
src/ui/wildmonsearch.cpp
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
#include "wildmonsearch.h"
|
||||
#include "ui_wildmonsearch.h"
|
||||
#include "project.h"
|
||||
|
||||
enum ResultsColumn {
|
||||
Group,
|
||||
Field,
|
||||
Level,
|
||||
Chance,
|
||||
};
|
||||
|
||||
enum ResultsDataRole {
|
||||
MapName = Qt::UserRole,
|
||||
};
|
||||
|
||||
WildMonSearch::WildMonSearch(Project *project, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::WildMonSearch),
|
||||
project(project)
|
||||
{
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
ui->setupUi(this);
|
||||
|
||||
// Set up species combo box
|
||||
ui->comboBox_Search->addItems(project->speciesToIconPath.keys());
|
||||
ui->comboBox_Search->setCurrentText(QString());
|
||||
ui->comboBox_Search->lineEdit()->setPlaceholderText(Project::getEmptySpeciesName());
|
||||
connect(ui->comboBox_Search, &QComboBox::currentTextChanged, this, &WildMonSearch::updateResults);
|
||||
|
||||
// Set up table header
|
||||
static const QStringList labels = {"Group", "Field", "Level", "Chance"};
|
||||
ui->table_Results->setHorizontalHeaderLabels(labels);
|
||||
ui->table_Results->horizontalHeader()->setSectionResizeMode(ResultsColumn::Group, QHeaderView::Stretch);
|
||||
ui->table_Results->horizontalHeader()->setSectionResizeMode(ResultsColumn::Field, QHeaderView::ResizeToContents);
|
||||
ui->table_Results->horizontalHeader()->setSectionResizeMode(ResultsColumn::Level, QHeaderView::ResizeToContents);
|
||||
ui->table_Results->horizontalHeader()->setSectionResizeMode(ResultsColumn::Chance, QHeaderView::ResizeToContents);
|
||||
|
||||
// Table is read-only
|
||||
ui->table_Results->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
ui->table_Results->setSelectionMode(QAbstractItemView::NoSelection);
|
||||
|
||||
connect(ui->table_Results, &QTableWidget::cellDoubleClicked, this, &WildMonSearch::cellDoubleClicked);
|
||||
|
||||
refresh();
|
||||
}
|
||||
|
||||
WildMonSearch::~WildMonSearch() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void WildMonSearch::refresh() {
|
||||
this->resultsCache.clear();
|
||||
updatePercentageStrings();
|
||||
updateResults(ui->comboBox_Search->currentText());
|
||||
}
|
||||
|
||||
void WildMonSearch::addTableEntry(const RowData &rowData) {
|
||||
int row = ui->table_Results->rowCount();
|
||||
ui->table_Results->insertRow(row);
|
||||
|
||||
auto groupItem = new QTableWidgetItem(rowData.groupName);
|
||||
groupItem->setData(ResultsDataRole::MapName, rowData.mapName);
|
||||
|
||||
ui->table_Results->setItem(row, ResultsColumn::Group, groupItem);
|
||||
ui->table_Results->setItem(row, ResultsColumn::Field, new QTableWidgetItem(rowData.fieldName));
|
||||
ui->table_Results->setItem(row, ResultsColumn::Level, new QTableWidgetItem(rowData.levelRange));
|
||||
ui->table_Results->setItem(row, ResultsColumn::Chance, new QTableWidgetItem(rowData.chance));
|
||||
}
|
||||
|
||||
QList<WildMonSearch::RowData> WildMonSearch::search(const QString &species) const {
|
||||
QList<RowData> results;
|
||||
for (const auto &keyPair : this->project->wildMonData) {
|
||||
QString mapConstant = keyPair.first;
|
||||
for (const auto &grouplLabelPair : this->project->wildMonData[mapConstant]) {
|
||||
QString groupName = grouplLabelPair.first;
|
||||
WildPokemonHeader encounterHeader = this->project->wildMonData[mapConstant][groupName];
|
||||
for (const auto &fieldNamePair : encounterHeader.wildMons) {
|
||||
QString fieldName = fieldNamePair.first;
|
||||
WildMonInfo monInfo = encounterHeader.wildMons[fieldName];
|
||||
for (int slot = 0; slot < monInfo.wildPokemon.length(); slot++) {
|
||||
const WildPokemon wildMon = monInfo.wildPokemon.at(slot);
|
||||
if (wildMon.species == species) {
|
||||
RowData rowData;
|
||||
rowData.groupName = groupName;
|
||||
rowData.fieldName = fieldName;
|
||||
rowData.mapName = this->project->mapConstantsToMapNames.value(mapConstant, mapConstant);
|
||||
|
||||
// If min and max level are the same display a single number, otherwise display a level range.
|
||||
rowData.levelRange = (wildMon.minLevel == wildMon.maxLevel) ? QString::number(wildMon.minLevel)
|
||||
: QString("%1-%2").arg(wildMon.minLevel).arg(wildMon.maxLevel);
|
||||
rowData.chance = this->percentageStrings[fieldName][slot];
|
||||
results.append(rowData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
void WildMonSearch::updatePercentageStrings() {
|
||||
this->percentageStrings.clear();
|
||||
for (const EncounterField &monField : this->project->wildMonFields) {
|
||||
QMap<int,QString> slotToPercentString;
|
||||
auto percentages = getWildEncounterPercentages(monField);
|
||||
for (int i = 0; i < percentages.length(); i++) {
|
||||
slotToPercentString.insert(i, QString::number(percentages.at(i) * 100, 'f', 2) + "%");
|
||||
}
|
||||
this->percentageStrings[monField.name] = slotToPercentString;
|
||||
}
|
||||
}
|
||||
|
||||
void WildMonSearch::updateResults(const QString &species) {
|
||||
ui->speciesIcon->setPixmap(this->project->getSpeciesIcon(species));
|
||||
|
||||
ui->table_Results->clearContents();
|
||||
ui->table_Results->setRowCount(0);
|
||||
|
||||
// Note: Per Qt docs, sorting should be disabled while populating the table to avoid it interfering with insertion order.
|
||||
ui->table_Results->setSortingEnabled(false);
|
||||
|
||||
if (ui->comboBox_Search->findText(species) < 0)
|
||||
return; // Not a species name, no need to search wild encounter data.
|
||||
|
||||
const QList<RowData> results = this->resultsCache.value(species, search(species));
|
||||
if (results.isEmpty()) {
|
||||
static const RowData noResults = {
|
||||
.groupName = QStringLiteral("Species not found."),
|
||||
.fieldName = QStringLiteral("--"),
|
||||
.levelRange = QStringLiteral("--"),
|
||||
.chance = QStringLiteral("--"),
|
||||
};
|
||||
addTableEntry(noResults);
|
||||
} else {
|
||||
for (const auto &entry : results) {
|
||||
addTableEntry(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This does a lexical sort... We might need custom item delegates to get proper numerical sorting in this table.
|
||||
ui->table_Results->setSortingEnabled(true);
|
||||
|
||||
this->resultsCache.insert(species, results);
|
||||
}
|
||||
|
||||
// Double-clicking row data opens the corresponding map/table on the Wild Pokémon tab.
|
||||
void WildMonSearch::cellDoubleClicked(int row, int) {
|
||||
auto groupItem = ui->table_Results->item(row, ResultsColumn::Group);
|
||||
auto fieldItem = ui->table_Results->item(row, ResultsColumn::Field);
|
||||
if (!groupItem || !fieldItem)
|
||||
return;
|
||||
|
||||
const QString mapName = groupItem->data(ResultsDataRole::MapName).toString();
|
||||
if (mapName.isEmpty())
|
||||
return;
|
||||
|
||||
emit openWildMonTableRequested(mapName, groupItem->text(), fieldItem->text());
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user