Support reading/saving pokefirered heal locations
This commit is contained in:
parent
083874ce9e
commit
d365ebb664
4 changed files with 134 additions and 39 deletions
|
@ -9,14 +9,18 @@ class HealLocation {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HealLocation()=default;
|
HealLocation()=default;
|
||||||
HealLocation(QString, int, uint16_t, uint16_t);
|
HealLocation(QString, QString, int, uint16_t, uint16_t);
|
||||||
|
HealLocation(QString, QString, int, uint16_t, uint16_t, QString, uint16_t);
|
||||||
friend QDebug operator<<(QDebug debug, const HealLocation &hl);
|
friend QDebug operator<<(QDebug debug, const HealLocation &hl);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QString name;
|
QString idName;
|
||||||
|
QString mapName;
|
||||||
int index;
|
int index;
|
||||||
uint16_t x;
|
uint16_t x;
|
||||||
uint16_t y;
|
uint16_t y;
|
||||||
|
QString respawnMap;
|
||||||
|
uint16_t respawnNPC;
|
||||||
static HealLocation fromEvent(Event*);
|
static HealLocation fromEvent(Event*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -87,10 +87,16 @@ Event* Event::createNewWarpEvent(QString map_name)
|
||||||
Event* Event::createNewHealLocationEvent(QString map_name)
|
Event* Event::createNewHealLocationEvent(QString map_name)
|
||||||
{
|
{
|
||||||
Event *event = new Event;
|
Event *event = new Event;
|
||||||
|
QString mapConstant = QString(Map::mapConstantFromName(map_name)).remove(0,4);
|
||||||
event->put("event_group_type", "heal_event_group");
|
event->put("event_group_type", "heal_event_group");
|
||||||
event->put("event_type", EventType::HealLocation);
|
event->put("event_type", EventType::HealLocation);
|
||||||
event->put("loc_name", QString(Map::mapConstantFromName(map_name)).remove(0,4));
|
event->put("loc_name", mapConstant);
|
||||||
|
event->put("id_name", map_name.replace(QRegularExpression("([a-z])([A-Z])"), "\\1_\\2").toUpper());
|
||||||
event->put("elevation", 3);
|
event->put("elevation", 3);
|
||||||
|
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||||
|
event->put("respawn_map", mapConstant);
|
||||||
|
event->put("respawn_npc", 1);
|
||||||
|
}
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,33 @@
|
||||||
#include "heallocation.h"
|
#include "heallocation.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
HealLocation::HealLocation(QString map, int i, uint16_t x, uint16_t y)
|
HealLocation::HealLocation(QString id, QString map, int i, uint16_t x, uint16_t y)
|
||||||
{
|
{
|
||||||
this->name = map;
|
this->idName = id;
|
||||||
|
this->mapName = map;
|
||||||
this->index = i;
|
this->index = i;
|
||||||
this->x = x;
|
this->x = x;
|
||||||
this->y = y;
|
this->y = y;
|
||||||
|
this->respawnMap = "";
|
||||||
|
this->respawnNPC = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HealLocation::HealLocation(QString id, QString map, int i, uint16_t x, uint16_t y, QString respawnMap, uint16_t respawnNPC)
|
||||||
|
{
|
||||||
|
this->idName = id;
|
||||||
|
this->mapName = map;
|
||||||
|
this->index = i;
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
this->respawnMap = respawnMap;
|
||||||
|
this->respawnNPC = respawnNPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
HealLocation HealLocation::fromEvent(Event *event)
|
HealLocation HealLocation::fromEvent(Event *event)
|
||||||
{
|
{
|
||||||
HealLocation hl;
|
HealLocation hl;
|
||||||
hl.name = event->get("loc_name");
|
hl.idName = event->get("id_name");
|
||||||
|
hl.mapName = event->get("loc_name");
|
||||||
try {
|
try {
|
||||||
hl.index = event->get("index").toInt();
|
hl.index = event->get("index").toInt();
|
||||||
}
|
}
|
||||||
|
@ -20,11 +36,15 @@ HealLocation HealLocation::fromEvent(Event *event)
|
||||||
}
|
}
|
||||||
hl.x = event->getU16("x");
|
hl.x = event->getU16("x");
|
||||||
hl.y = event->getU16("y");
|
hl.y = event->getU16("y");
|
||||||
|
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||||
|
hl.respawnNPC = event->getU16("respawn_npc");
|
||||||
|
hl.respawnMap = event->get("respawn_map");
|
||||||
|
}
|
||||||
return hl;
|
return hl;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug debug, const HealLocation &hl)
|
QDebug operator<<(QDebug debug, const HealLocation &hl)
|
||||||
{
|
{
|
||||||
debug << "HealLocation_" + hl.name << "(" << hl.x << ',' << hl.y << ")";
|
debug << "HealLocation_" + hl.mapName << "(" << hl.x << ',' << hl.y << ")";
|
||||||
return debug;
|
return debug;
|
||||||
}
|
}
|
||||||
|
|
115
src/project.cpp
115
src/project.cpp
|
@ -259,17 +259,22 @@ bool Project::loadMapData(Map* map) {
|
||||||
HealLocation loc = *it;
|
HealLocation loc = *it;
|
||||||
|
|
||||||
//if TRUE map is flyable / has healing location
|
//if TRUE map is flyable / has healing location
|
||||||
if (loc.name == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) {
|
if (loc.mapName == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) {
|
||||||
Event *heal = new Event;
|
Event *heal = new Event;
|
||||||
heal->put("map_name", map->name);
|
heal->put("map_name", map->name);
|
||||||
heal->put("x", loc.x);
|
heal->put("x", loc.x);
|
||||||
heal->put("y", loc.y);
|
heal->put("y", loc.y);
|
||||||
heal->put("loc_name", loc.name);
|
heal->put("loc_name", loc.mapName);
|
||||||
|
heal->put("id_name", loc.idName);
|
||||||
heal->put("index", loc.index);
|
heal->put("index", loc.index);
|
||||||
heal->put("elevation", 3); // TODO: change this?
|
heal->put("elevation", 3); // TODO: change this?
|
||||||
heal->put("destination_map_name", mapConstantsToMapNames->value(map->name));
|
heal->put("destination_map_name", mapConstantsToMapNames->value(map->name));
|
||||||
heal->put("event_group_type", "heal_event_group");
|
heal->put("event_group_type", "heal_event_group");
|
||||||
heal->put("event_type", EventType::HealLocation);
|
heal->put("event_type", EventType::HealLocation);
|
||||||
|
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||||
|
heal->put("respawn_map", loc.respawnMap);
|
||||||
|
heal->put("respawn_npc", loc.respawnNPC);
|
||||||
|
}
|
||||||
map->events["heal_event_group"].append(heal);
|
map->events["heal_event_group"].append(heal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,9 +786,19 @@ void Project::saveMapConstantsHeader() {
|
||||||
// saves heal location coords in root + /src/data/heal_locations.h
|
// saves heal location coords in root + /src/data/heal_locations.h
|
||||||
// and indexes as defines in root + /include/constants/heal_locations.h
|
// and indexes as defines in root + /include/constants/heal_locations.h
|
||||||
void Project::saveHealLocationStruct(Map *map) {
|
void Project::saveHealLocationStruct(Map *map) {
|
||||||
QString data_text = QString("%1%2struct HealLocation sHealLocations[] =\n{\n")
|
QString constantPrefix, arrayName;
|
||||||
|
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||||
|
constantPrefix = "SPAWN_";
|
||||||
|
arrayName = "sSpawnPoints";
|
||||||
|
} else {
|
||||||
|
constantPrefix = "HEAL_LOCATION_";
|
||||||
|
arrayName = "sHealLocations";
|
||||||
|
}
|
||||||
|
|
||||||
|
QString data_text = QString("%1%2struct HealLocation %3[] =\n{\n")
|
||||||
.arg(dataQualifiers.value("heal_locations").isStatic ? "static " : "")
|
.arg(dataQualifiers.value("heal_locations").isStatic ? "static " : "")
|
||||||
.arg(dataQualifiers.value("heal_locations").isConst ? "const " : "");
|
.arg(dataQualifiers.value("heal_locations").isConst ? "const " : "")
|
||||||
|
.arg(arrayName);
|
||||||
|
|
||||||
QString constants_text = QString("#ifndef GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
|
QString constants_text = QString("#ifndef GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
|
||||||
constants_text += QString("#define GUARD_CONSTANTS_HEAL_LOCATIONS_H\n\n");
|
constants_text += QString("#define GUARD_CONSTANTS_HEAL_LOCATIONS_H\n\n");
|
||||||
|
@ -794,7 +809,7 @@ void Project::saveHealLocationStruct(Map *map) {
|
||||||
// set flyableMapsDupes and flyableMapsUnique
|
// set flyableMapsDupes and flyableMapsUnique
|
||||||
for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) {
|
for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) {
|
||||||
HealLocation loc = *it;
|
HealLocation loc = *it;
|
||||||
QString xname = loc.name;
|
QString xname = loc.idName;
|
||||||
if (flyableMapsUnique.contains(xname)) {
|
if (flyableMapsUnique.contains(xname)) {
|
||||||
flyableMapsDupes[xname] = 1;
|
flyableMapsDupes[xname] = 1;
|
||||||
}
|
}
|
||||||
|
@ -810,33 +825,58 @@ void Project::saveHealLocationStruct(Map *map) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
for (auto map_in : flyableMaps) {
|
for (auto map_in : flyableMaps) {
|
||||||
data_text += QString(" {MAP_GROUP(%1), MAP_NUM(%1), %2, %3},\n")
|
// add numbered suffix for duplicate constants
|
||||||
.arg(map_in.name)
|
if (flyableMapsDupes.keys().contains(map_in.idName)) {
|
||||||
|
map_in.idName += QString("_%1").arg(flyableMapsDupes[map_in.idName]);
|
||||||
|
flyableMapsDupes[map_in.idName]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save first array (heal location coords), only data array in RSE
|
||||||
|
data_text += QString(" [%1%2 - 1] = {MAP_GROUP(%3), MAP_NUM(%3), %4, %5},\n")
|
||||||
|
.arg(constantPrefix)
|
||||||
|
.arg(map_in.idName)
|
||||||
|
.arg(map_in.mapName)
|
||||||
.arg(map_in.x)
|
.arg(map_in.x)
|
||||||
.arg(map_in.y);
|
.arg(map_in.y);
|
||||||
|
|
||||||
QString ending = QString("");
|
// Save constants
|
||||||
|
|
||||||
// must add _1 / _2 for maps that have duplicates
|
|
||||||
if (flyableMapsDupes.keys().contains(map_in.name)) {
|
|
||||||
// map contains multiple heal locations
|
|
||||||
ending += QString("_%1").arg(flyableMapsDupes[map_in.name]);
|
|
||||||
flyableMapsDupes[map_in.name]++;
|
|
||||||
}
|
|
||||||
if (map_in.index != 0) {
|
if (map_in.index != 0) {
|
||||||
constants_text += QString("#define HEAL_LOCATION_%1 %2\n")
|
constants_text += QString("#define %1%2 %3\n")
|
||||||
.arg(map_in.name + ending)
|
.arg(constantPrefix)
|
||||||
|
.arg(map_in.idName)
|
||||||
.arg(map_in.index);
|
.arg(map_in.index);
|
||||||
}
|
} else {
|
||||||
else {
|
constants_text += QString("#define %1%2 %3\n")
|
||||||
constants_text += QString("#define HEAL_LOCATION_%1 %2\n")
|
.arg(constantPrefix)
|
||||||
.arg(map_in.name + ending)
|
.arg(map_in.idName)
|
||||||
.arg(i);
|
.arg(i);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||||
|
// Save second array (map where player respawns for each heal location)
|
||||||
|
data_text += QString("};\n\n%1%2u16 sWhiteoutRespawnHealCenterMapIdxs[][2] =\n{\n")
|
||||||
|
.arg(dataQualifiers.value("heal_locations").isStatic ? "static " : "")
|
||||||
|
.arg(dataQualifiers.value("heal_locations").isConst ? "const " : "");
|
||||||
|
for (auto map_in : flyableMaps) {
|
||||||
|
data_text += QString(" [%1%2 - 1] = {MAP_GROUP(%3), MAP_NUM(%3)},\n")
|
||||||
|
.arg(constantPrefix)
|
||||||
|
.arg(map_in.idName)
|
||||||
|
.arg(map_in.respawnMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save third array (object id of NPC player speaks to upon respawning for each heal location)
|
||||||
|
data_text += QString("};\n\n%1%2u8 sWhiteoutRespawnHealerNpcIds[] =\n{\n")
|
||||||
|
.arg(dataQualifiers.value("heal_locations").isStatic ? "static " : "")
|
||||||
|
.arg(dataQualifiers.value("heal_locations").isConst ? "const " : "");
|
||||||
|
for (auto map_in : flyableMaps) {
|
||||||
|
data_text += QString(" [%1%2 - 1] = %3,\n")
|
||||||
|
.arg(constantPrefix)
|
||||||
|
.arg(map_in.idName)
|
||||||
|
.arg(map_in.respawnNPC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data_text += QString("};\n");
|
data_text += QString("};\n");
|
||||||
constants_text += QString("\n#endif // GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
|
constants_text += QString("\n#endif // GUARD_CONSTANTS_HEAL_LOCATIONS_H\n");
|
||||||
|
@ -1928,21 +1968,46 @@ bool Project::readRegionMapSections() {
|
||||||
bool Project::readHealLocations() {
|
bool Project::readHealLocations() {
|
||||||
dataQualifiers.clear();
|
dataQualifiers.clear();
|
||||||
flyableMaps.clear();
|
flyableMaps.clear();
|
||||||
|
|
||||||
QString filename = "src/data/heal_locations.h";
|
QString filename = "src/data/heal_locations.h";
|
||||||
QString text = parser.readTextFile(root + "/" + filename);
|
QString text = parser.readTextFile(root + "/" + filename);
|
||||||
text.replace(QRegularExpression("//.*?(\r\n?|\n)|/\\*.*?\\*/", QRegularExpression::DotMatchesEverythingOption), "");
|
text.replace(QRegularExpression("//.*?(\r\n?|\n)|/\\*.*?\\*/", QRegularExpression::DotMatchesEverythingOption), "");
|
||||||
|
|
||||||
|
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
||||||
|
dataQualifiers.insert("heal_locations", getDataQualifiers(text, "sSpawnPoints"));
|
||||||
|
QRegularExpression spawnRegex("SPAWN_(?<id>[A-Za-z0-9_]+)\\s*- 1\\]\\s* = \\{MAP_GROUP[\\(\\s]+(?<map>[A-Za-z0-9_]+)[\\s\\)]+,\\s*MAP_NUM[\\(\\s]+(\\2)[\\s\\)]+,\\s*(?<x>[0-9A-Fa-fx]+),\\s*(?<y>[0-9A-Fa-fx]+)");
|
||||||
|
QRegularExpression respawnMapRegex("SPAWN_(?<id>[A-Za-z0-9_]+)\\s*- 1\\]\\s* = \\{MAP_GROUP[\\(\\s]+(?<map>[A-Za-z0-9_]+)[\\s\\)]+,\\s*MAP_NUM[\\(\\s]+(\\2)[\\s\\)]+}");
|
||||||
|
QRegularExpression respawnNPCRegex("SPAWN_(?<id>[A-Za-z0-9_]+)\\s*- 1\\]\\s* = (?<npc>[0-9]+)");
|
||||||
|
QRegularExpressionMatchIterator spawns = spawnRegex.globalMatch(text);
|
||||||
|
QRegularExpressionMatchIterator respawnMaps = respawnMapRegex.globalMatch(text);
|
||||||
|
QRegularExpressionMatchIterator respawnNPCs = respawnNPCRegex.globalMatch(text);
|
||||||
|
|
||||||
|
// This would be better if idName was used to look up data from the other two arrays
|
||||||
|
// As it is, element total and order needs to be the same in the 3 arrays to work. This should always be true though
|
||||||
|
for (int i = 1; spawns.hasNext(); i++) {
|
||||||
|
QRegularExpressionMatch spawn = spawns.next();
|
||||||
|
QRegularExpressionMatch respawnMap = respawnMaps.next();
|
||||||
|
QRegularExpressionMatch respawnNPC = respawnNPCs.next();
|
||||||
|
QString idName = spawn.captured("id");
|
||||||
|
QString mapName = spawn.captured("map");
|
||||||
|
QString respawnMapName = respawnMap.captured("map");
|
||||||
|
unsigned x = spawn.captured("x").toUShort();
|
||||||
|
unsigned y = spawn.captured("y").toUShort();
|
||||||
|
unsigned npc = respawnNPC.captured("npc").toUShort();
|
||||||
|
flyableMaps.append(HealLocation(idName, mapName, i, x, y, respawnMapName, npc));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
dataQualifiers.insert("heal_locations", getDataQualifiers(text, "sHealLocations"));
|
dataQualifiers.insert("heal_locations", getDataQualifiers(text, "sHealLocations"));
|
||||||
|
|
||||||
QRegularExpression regex("MAP_GROUP[\\(\\s]+(?<map>[A-Za-z0-9_]+)[\\s\\)]+,\\s*MAP_NUM[\\(\\s]+(\\1)[\\s\\)]+,\\s*(?<x>[0-9A-Fa-fx]+),\\s*(?<y>[0-9A-Fa-fx]+)");
|
QRegularExpression regex("HEAL_LOCATION_(?<id>[A-Za-z0-9_]+)\\s*- 1\\]\\s* = \\{MAP_GROUP[\\(\\s]+(?<map>[A-Za-z0-9_]+)[\\s\\)]+,\\s*MAP_NUM[\\(\\s]+(\\2)[\\s\\)]+,\\s*(?<x>[0-9A-Fa-fx]+),\\s*(?<y>[0-9A-Fa-fx]+)");
|
||||||
QRegularExpressionMatchIterator iter = regex.globalMatch(text);
|
QRegularExpressionMatchIterator iter = regex.globalMatch(text);
|
||||||
for (int i = 1; iter.hasNext(); i++) {
|
for (int i = 1; iter.hasNext(); i++) {
|
||||||
QRegularExpressionMatch match = iter.next();
|
QRegularExpressionMatch match = iter.next();
|
||||||
|
QString idName = match.captured("id");
|
||||||
QString mapName = match.captured("map");
|
QString mapName = match.captured("map");
|
||||||
unsigned x = match.captured("x").toUShort();
|
unsigned x = match.captured("x").toUShort();
|
||||||
unsigned y = match.captured("y").toUShort();
|
unsigned y = match.captured("y").toUShort();
|
||||||
flyableMaps.append(HealLocation(mapName, i, x, y));
|
flyableMaps.append(HealLocation(idName, mapName, i, x, y));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue