GWF_PowerUpInjector/mainwindow.cpp

309 lines
10 KiB
C++
Raw Normal View History

2025-12-16 15:03:30 -05:00
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QRandomGenerator>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, mSteamPath()
{
ui->setupUi(this);
findSteamPath();
QDir gwfWorkshopDir(mSteamPath + "/steamapps/workshop/content/431240");
if (!gwfWorkshopDir.exists()) { return; }
qDebug() << "Found Golf With Friends Workshop Path:" << gwfWorkshopDir.path();
foreach (const QString entry, gwfWorkshopDir.entryList({}, QDir::NoFilter, QDir::Time))
{
if (entry == "." || entry == "..") { continue; }
QFile newEntry(gwfWorkshopDir.path() + "/" + entry + "/Map");
if (!newEntry.open(QIODevice::ReadWrite))
{
qDebug() << "Failed to open workshop map:" << entry;
continue;
}
const QByteArray rawMapData = newEntry.readAll();
size_t headerSize = rawMapData.indexOf('{');
size_t footerSize = rawMapData.size() - rawMapData.lastIndexOf('}') - 1;
size_t payloadSize = rawMapData.size() - headerSize - footerSize;
const QByteArray mapData = rawMapData.mid(headerSize, payloadSize);
QJsonDocument loadDoc = QJsonDocument::fromJson(mapData);
QJsonObject loadObj = loadDoc.object();
LevelInfo newInfo;
newInfo.mLevelName = loadObj["levelName"].toString() + QString(" [%1]").arg(entry);
newInfo.mDescription = loadObj["description"].toString();
newInfo.mPublishedID = QString::number(loadObj["publishedID"].toInt());
newInfo.mMusic = loadObj["music"].toInt();
newInfo.mSkybox = loadObj["skybox"].toInt();
newInfo.mPreview = QPixmap(gwfWorkshopDir.path() + "/" + entry + "/Preview.jpg");
newInfo.mPowerUps = findPowerUps(loadObj);
newInfo.mMaxViewID = getMaxViewID(loadObj);
newInfo.mObjectPositions = getObjectPositions(loadObj);
newInfo.mMapPath = newEntry.fileName();
newInfo.mMapData = loadObj;
mLevels.push_back(newInfo);
}
updateLevels();
}
void MainWindow::findSteamPath()
{
QDir testDir("C:/Program Files (x86)/Steam");
if (testDir.exists())
{
mSteamPath = testDir.path();
}
else
{
mSteamPath = QFileDialog::getExistingDirectory(this, "Select Steam Directory", "C:/Program Files (x86)/", QFileDialog::ShowDirsOnly);
}
if (!mSteamPath.isEmpty())
{
ui->lineEdit_SteamPath->setText(QString("FOUND: %1").arg(mSteamPath));
ui->lineEdit_SteamPath->setEnabled(false);
}
}
void MainWindow::updateLevels()
{
ui->listWidget_MapSelect->clear();
for (int i = 0; i < mLevels.size(); i++)
{
ui->listWidget_MapSelect->addItem(mLevels[i].mLevelName);
}
}
QVector<QVector3D> MainWindow::getObjectPositions(QJsonObject aMapData)
{
QVector<QVector3D> result;
QJsonArray objData = aMapData["editorObjectData"].toArray();
for (int i = 0; i < objData.size(); i++)
{
QJsonObject currentObject = objData[i].toObject();
if (currentObject["obName"].toString().contains("base", Qt::CaseInsensitive))
{
QVector3D position;
position.setX(currentObject["pX"].toDouble());
position.setY(currentObject["pY"].toDouble());
position.setZ(currentObject["pZ"].toDouble());
result.push_back(position);
}
}
return result;
}
int MainWindow::getMaxViewID(QJsonObject aMapData)
{
QVector<QVector3D> result;
QJsonArray objData = aMapData["editorObjectData"].toArray();
int maxViewID = 0;
for (int i = 0; i < objData.size(); i++)
{
QJsonObject currentObject = objData[i].toObject();
QJsonArray viewIDs = currentObject["photonData"].toObject()["photonViewID"].toArray();
if (viewIDs.isEmpty()) { continue; }
maxViewID = fmax(viewIDs.first().toInt(), maxViewID);
}
return maxViewID;
}
QVector<PowerUpInfo> MainWindow::findPowerUps(QJsonObject aMapData)
{
QVector<PowerUpInfo> result;
QJsonArray objData = aMapData["editorObjectData"].toArray();
for (int i = 0; i < objData.size(); i++)
{
QJsonObject currentObject = objData[i].toObject();
const QString objName = currentObject["obName"].toString();
if (objName == "Powerup Spawner")
{
PowerUpInfo newPowerUp;
newPowerUp.mPosition.setX(currentObject["pX"].toDouble());
newPowerUp.mPosition.setY(currentObject["pY"].toDouble());
newPowerUp.mPosition.setZ(currentObject["pZ"].toDouble());
newPowerUp.mRotation.setW(currentObject["rW"].toDouble());
newPowerUp.mRotation.setX(currentObject["rX"].toDouble());
newPowerUp.mRotation.setY(currentObject["rY"].toDouble());
newPowerUp.mRotation.setZ(currentObject["rZ"].toDouble());
newPowerUp.mScale.setX(currentObject["sX"].toDouble());
newPowerUp.mScale.setY(currentObject["sY"].toDouble());
newPowerUp.mScale.setZ(currentObject["sZ"].toDouble());
result.push_back(newPowerUp);
}
}
return result;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_listWidget_MapSelect_currentRowChanged(int currentRow)
{
LevelInfo selectedLevel = mLevels[currentRow];
ui->lineEdit_LevelName->setText(selectedLevel.mLevelName);
ui->lineEdit_Description->setText(selectedLevel.mDescription);
ui->lineEdit_ID->setText(selectedLevel.mPublishedID);
ui->spinBox_Music->setValue(selectedLevel.mMusic);
ui->spinBox_Skybox->setValue(selectedLevel.mSkybox);
ui->spinBox_PowerupCount->setValue(selectedLevel.mPowerUps.size());
QPixmap scaledPreview = selectedLevel.mPreview.scaled(ui->label_MapPreview->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
ui->label_MapPreview->setPixmap(scaledPreview);
for (int i = 0; i < selectedLevel.mPowerUps.size(); i++)
{
ui->listWidget_powerups->addItem(QString("Powerup %1").arg(i));
}
}
void MainWindow::on_listWidget_powerups_currentRowChanged(int currentRow)
{
LevelInfo selectedLevel = mLevels[ui->listWidget_MapSelect->currentRow()];
PowerUpInfo selectedPowerUp = selectedLevel.mPowerUps[currentRow];
ui->doubleSpinBox_PosX->setValue(selectedPowerUp.mPosition.x());
ui->doubleSpinBox_PosY->setValue(selectedPowerUp.mPosition.y());
ui->doubleSpinBox_PosZ->setValue(selectedPowerUp.mPosition.z());
ui->doubleSpinBox_RotW->setValue(selectedPowerUp.mRotation.w());
ui->doubleSpinBox_RotX->setValue(selectedPowerUp.mRotation.x());
ui->doubleSpinBox_RotY->setValue(selectedPowerUp.mRotation.y());
ui->doubleSpinBox_RotZ->setValue(selectedPowerUp.mRotation.z());
ui->doubleSpinBox_ScaleX->setValue(selectedPowerUp.mScale.x());
ui->doubleSpinBox_ScaleY->setValue(selectedPowerUp.mScale.y());
ui->doubleSpinBox_ScaleZ->setValue(selectedPowerUp.mScale.z());
}
void MainWindow::saveMap(LevelInfo aLevelInfo, bool aBackup)
{
const QString mapPath = aLevelInfo.mMapPath;
if (!QFile::exists(mapPath))
{
qDebug() << "File doesn't exist: " << mapPath;
return;
}
const QString backupMapPath = aLevelInfo.mMapPath + ".old";
if (!QFile::exists(backupMapPath) && aBackup)
{
QFile::copy(mapPath, backupMapPath);
}
QFile backupMapFile(backupMapPath);
if (!backupMapFile.open(QIODevice::ReadOnly))
{
qDebug() << "Failed to open backup file: " << mapPath;
return;
}
const QByteArray backupData = backupMapFile.readAll().simplified();
backupMapFile.close();
QFile mapFile(mapPath);
if (!mapFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
{
qDebug() << "Failed to open file: " << mapPath;
return;
}
QByteArray powerUpsData = ",";
for (int i = 0; i < aLevelInfo.mPowerUps.size(); i++)
{
PowerUpInfo powerUp = aLevelInfo.mPowerUps[i];
const QString powerUpData = QString("{\"sType\":%1,\"pX\":%2,\"pY\":%3,\"pZ\":%4,\"rW\":%5,\"rX\":%6,\"rY\":%7,\"rZ\":%8,\"sX\":%9,\"sY\":%10,\"sZ\":%11,\"obName\":\"Powerup Spawner\",\"photonData\":{\"photonViewID\":[%12]}},")
.arg(0)
.arg(powerUp.mPosition.x(), 0, 'f', 1)
.arg(powerUp.mPosition.y(), 0, 'f', 1)
.arg(powerUp.mPosition.z(), 0, 'f', 1)
.arg(powerUp.mRotation.w(), 0, 'f', 1)
.arg(powerUp.mRotation.x(), 0, 'f', 1)
.arg(powerUp.mRotation.y(), 0, 'f', 1)
.arg(powerUp.mRotation.z(), 0, 'f', 1)
.arg(powerUp.mScale.x(), 0, 'f', 1)
.arg(powerUp.mScale.y(), 0, 'f', 1)
.arg(powerUp.mScale.z(), 0, 'f', 1)
.arg(i + 4 + aLevelInfo.mMaxViewID);
powerUpsData.append(powerUpData.toUtf8());
}
powerUpsData = powerUpsData.mid(0, powerUpsData.size() - 1);
int injectionPoint = backupData.lastIndexOf(']');
QByteArray mapData;
mapData.append(backupData.mid(0, injectionPoint));
mapData.append(powerUpsData);
mapData.append(backupData.mid(injectionPoint));
mapFile.write(mapData);
mapFile.close();
}
void MainWindow::on_pushButton_Generate_clicked()
{
int currentListRow = ui->listWidget_MapSelect->currentRow();
LevelInfo selectedLevel = mLevels[currentListRow];
QVector<QVector3D> shuffledPositions = selectedLevel.mObjectPositions;
auto rng = QRandomGenerator::global();
std::shuffle(shuffledPositions.begin(), shuffledPositions.end(), *rng);
for (int i = 0; i < shuffledPositions.size(); i++)
{
if (i == MAX_POWERUPS)
{
break;
}
if ((rand() % 100) < 75)
{
QVector3D pos = shuffledPositions[i];
int sign = 1;
if ((rand() % 100) < 50)
{
sign = -1;
}
pos.setX(pos.x() + sign * (rand() % 2));
pos.setY(pos.y() + sign * (rand() % 2));
PowerUpInfo newPowerUp;
newPowerUp.mPosition = QVector3D(pos.x(), pos.y() + 0.25, pos.z());
newPowerUp.mScale = QVector3D(1, 1, 1);
selectedLevel.mPowerUps.push_back(newPowerUp);
}
}
saveMap(selectedLevel, true);
mLevels[ui->listWidget_MapSelect->currentRow()] = selectedLevel;
ui->listWidget_MapSelect->setCurrentRow(currentListRow);
}