Add Fiesta mode, bump version to 0.8

main
Síle Ekaterin Liszka 2021-06-13 00:04:22 -05:00
parent aa95157904
commit 583e305103
7 changed files with 409 additions and 10 deletions

View File

@ -1,6 +1,6 @@
HEADERS += src/exdeath.hh src/data.hh src/randodata.hh src/randomizer.hh
SOURCES += src/exdeath.cc src/main.cc src/randomizer.cc
HEADERS += src/exdeath.hh src/data.hh src/randodata.hh src/randomizer.hh src/fiesta.hh
SOURCES += src/exdeath.cc src/main.cc src/randomizer.cc src/fiesta.cc
RESOURCES += patches.qrc
CONFIG += release

View File

@ -1,4 +1,4 @@
enum Job {
enum Innate {
Passages = 0x01,
Pitfalls = 0x02,
LiteStep = 0x04,

View File

@ -149,6 +149,30 @@ void Exdeath::initRandom(void) {
chkRandom = new QCheckBox("Yes");
layRandom->addRow("Abilities:", chkRandom);
chkFiesta = new QCheckBox("Yes");
layRandom->addRow("Fiesta:", chkFiesta);
selFiesta = new QComboBox();
selFiesta->addItem("Normal", RunNormal);
selFiesta->setCurrentIndex(0);
selFiesta->addItem("Normal 750", Run750);
selFiesta->addItem("Normal No750", RunNo750);
selFiesta->addItem("Random", RunRandom);
selFiesta->addItem("Random 750", RunRandom750);
selFiesta->addItem("Random No750", RunRandomNo750);
selFiesta->addItem("Chaos", RunChaos);
selFiesta->addItem("Chaos 750", RunChaos750);
selFiesta->addItem("Chaos No750", RunChaosNo750);
selFiesta->addItem("Pure Chaos", RunPure);
selFiesta->addItem("Advance", RunAdvance);
layRandom->addRow("Run:", selFiesta);
selModifier = new QComboBox();
selModifier->addItem("None", ModNone);
selModifier->addItem("Fifth Job", ModFifth);
//selModifier->addItem("Forbidden", ModVoid);
layRandom->addRow("Modifier:", selModifier);
}
void Exdeath::initInnates(void) {
@ -230,6 +254,9 @@ void Exdeath::initConfig(void) {
chkDash->setChecked(_cfg->value("innate/dash", false).toBool());
chkLearning->setChecked(_cfg->value("innate/learning", false).toBool());
chkFiesta->setChecked(_cfg->value("fiesta/enable", false).toBool());
selFiesta->setCurrentIndex(_cfg->value("fiesta/mode", 0).toInt());
butsXP->button(_cfg->value("multi/xp", 1).toInt())->setChecked(true);
butsAP->button(_cfg->value("multi/ap", 1).toInt())->setChecked(true);
butsGil->button(_cfg->value("multi/gil", 1).toInt())->setChecked(true);
@ -275,6 +302,9 @@ void Exdeath::btnSave_clicked(bool trigger) {
_cfg->setValue("innate/dash", chkDash->isChecked());
_cfg->setValue("innate/learning", chkLearning->isChecked());
_cfg->setValue("fiesta/enable", chkFiesta->isChecked());
_cfg->setValue("fiesta/mode", selFiesta->currentIndex());
_cfg->setValue("multi/xp", butsXP->checkedId());
_cfg->setValue("multi/ap", butsAP->checkedId());
_cfg->setValue("multi/gil", butsGil->checkedId());
@ -383,7 +413,7 @@ void Exdeath::btnApply_clicked(bool trigger) {
bool global_innates = innates_enabled && (chkPassages->isChecked() || chkPitfalls->isChecked() || chkLiteStep->isChecked() || chkDash->isChecked() || chkLearning->isChecked());
if (chkRandom->isChecked() && chkRandom->isEnabled()) {
Randomizer *rando = new Randomizer(rand);
QFile *pfile = new QFile(output + ".ips");
QFile *pfile = new QFile(output + ".random.ips");
pfile->open(QIODevice::WriteOnly);
QBuffer *patch = rando->makeRandom(global_innates);
pfile->write(patch->readAll());
@ -391,6 +421,18 @@ void Exdeath::btnApply_clicked(bool trigger) {
pfile->close();
applyPatch(target, patch);
}
if (chkFiesta->isChecked()) {
Fiesta *fiesta = new Fiesta(rand);
QFile *pfile = new QFile(output + ".fiesta.ips");
pfile->open(QIODevice::WriteOnly);
QBuffer *patch = fiesta->makeRun((RunType)selFiesta->currentIndex(), ModNone);
pfile->write(patch->readAll());
patch->seek(0);
pfile->close();
applyPatch(target, patch);
}
if (global_innates) {
applyInnates(target);
}
@ -437,11 +479,11 @@ void Exdeath::applyPatch(QFile *file, QIODevice *data) {
void Exdeath::applyInnates(QFile *file) {
unsigned char base = 0;
if (chkPassages->isChecked()) base |= Job::Passages;
if (chkPitfalls->isChecked()) base |= Job::Pitfalls;
if (chkLiteStep->isChecked()) base |= Job::LiteStep;
if (chkDash->isChecked()) base |= Job::Dash;
if (chkLearning->isChecked()) base |= Job::ILearning;
if (chkPassages->isChecked()) base |= Innate::Passages;
if (chkPitfalls->isChecked()) base |= Innate::Pitfalls;
if (chkLiteStep->isChecked()) base |= Innate::LiteStep;
if (chkDash->isChecked()) base |= Innate::Dash;
if (chkLearning->isChecked()) base |= Innate::ILearning;
for (int i = 0; i < 26; i++) {
char temp[2];

View File

@ -25,6 +25,7 @@
#include "data.hh"
#include "randomizer.hh"
#include "fiesta.hh"
class Exdeath : public QWidget {
public:
@ -64,6 +65,10 @@ private:
QSpinBox *numSeed;
QComboBox *selNED;
QCheckBox *chkRandom;
QCheckBox *chkFiesta;
QComboBox *selFiesta;
QComboBox *selModifier;
//QCheckBox *chkVoid;
// Innate abilities
QGroupBox *grpInnates;

284
src/fiesta.cc Normal file
View File

@ -0,0 +1,284 @@
/*
* Copyright (c) 202BER, Sheila Aman.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the software nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fiesta.hh"
Fiesta::Fiesta(std::mt19937 rand) {
rng = rand;
}
Fiesta::~Fiesta() {}
const int wind_addr[7] = {
0x3d6060,
0x3d6062,
0x3d6064,
0x3d6066,
0x3d6068,
0x3d606a,
0x4aa87,
};
const int job_addr[2] = {
0x4AFC2,
0x4AA46,
};
const int water_addr[6] = {
0x3d152e,
0x3d153a,
0x3d1546,
0x3d1552,
0x3d155e,
0x3ce4c4,
};
const int fire_addr[5] = {
0x3d8285,
0x3d8287,
0x3d8289,
0x3d0c62,
0x3d0c64,
};
const int earth_addr[4] = {
0x3cb039,
0x3cb03b,
0x3cb03d,
0x3cb03f,
};
const int adv_addr[3] = {
0x3e2a45,
0x3e2a62,
0x3e2a7d,
};
QMap<int,int> id2menu = {
{KNI, 0x00},
{MNK, 0x01},
{THF, 0x02},
{DRG, 0x03},
{NIN, 0x04},
{SAM, 0x05},
{BER, 0x06},
{RNG, 0x07},
{MYS, 0x08},
{WHT, 0x09},
{BLK, 0x0a},
{TIM, 0x0b},
{SUM, 0x0c},
{BLU, 0x0d},
{RED, 0x0e},
{BST, 0x0f},
{CHM, 0x10},
{GEO, 0x11},
{BRD, 0x12},
{DNC, 0x13},
{MIM, 0x14},
{FRL, 0x15},
// bold assumptions, Cotton
{GLD, 0x16},
{CAN, 0x17},
{ORC, 0x18},
{NCR, 0x19},
};
QBuffer *Fiesta::makeRun(RunType type, RunModifier modifier) {
QBuffer *patch = new QBuffer();
QVector<char> wind, water, fire, earth;
char jobI, jobA, jobF, jobE, jobK;
switch (type) {
default:
case RunNormal:
wind = {THF, MNK, KNI, BLU, BLK, WHT};
water = {BER, RED, TIM, SUM, MYS};
fire = {RNG, NIN, BST, GEO, BRD};
earth = {SAM, DRG, DNC, CHM};
break;
case Run750:
wind = {BLU, BLK, WHT};
water = {RED, TIM, SUM};
fire = {GEO, BRD};
earth = {DNC, CHM};
break;
case RunNo750:
wind = {THF, MNK, KNI};
water = {BER, MYS};
fire = {RNG, NIN, BST};
earth = {SAM, DRG};
break;
case RunRandom:
wind = {THF, MNK, KNI, BLU, BLK, WHT};
water = {THF, MNK, KNI, BLU, BLK, WHT, BER, RED, TIM, SUM, MYS};
fire = {THF, MNK, KNI, BLU, BLK, WHT, BER, RED, TIM, SUM, MYS, RNG, NIN, BST, GEO, BRD};
earth = {THF, MNK, KNI, BLU, BLK, WHT, BER, RED, TIM, SUM, MYS, RNG, NIN, BST, GEO, BRD, SAM, DRG, DNC, CHM};
break;
case RunRandom750:
wind = {BLU, BLK, WHT};
water = {BLU, BLK, WHT, RED, TIM, SUM};
fire = {BLU, BLK, WHT, RED, TIM, SUM, GEO, BRD};
earth = {BLU, BLK, WHT, RED, TIM, SUM, GEO, BRD, DNC, CHM};
break;
case RunRandomNo750:
wind = {THF, MNK, KNI};
water = {THF, MNK, KNI, BER, MYS};
fire = {THF, MNK, KNI, BER, MYS, RNG, NIN, BST};
earth = {THF, MNK, KNI, BER, MYS, RNG, NIN, BST, SAM, DRG};
break;
case RunChaos:
wind = {THF, MNK, KNI, BLU, BLK, WHT, BER, RED, TIM, SUM, MYS, RNG, NIN, BST, GEO, BRD, SAM, DRG, DNC, CHM};
water = wind;
fire = water;
earth = fire;
break;
case RunChaos750:
wind = {BLU, BLK, WHT, RED, TIM, SUM, GEO, BRD, DNC, CHM};
water = wind;
fire = water;
earth = fire;
break;
case RunChaosNo750:
wind = {THF, MNK, KNI, BER, MYS, RNG, NIN, BST, SAM, DRG};
water = wind;
fire = water;
earth = fire;
break;
case RunPure:
wind = {THF, MNK, KNI, BLU, BLK, WHT, BER, RED, TIM, SUM, MYS, RNG, NIN, BST, GEO, BRD, SAM, DRG, DNC, CHM, MIM, FRL};
break;
case RunAdvance:
wind = {THF, MNK, KNI, BLU, BLK, WHT, TIM};
water = {BER, RED, SUM, MYS, NIN, BST, GEO};
fire = {RNG, BRD, SAM, DRG, DNC, CHM};
earth = {GLD, CAN, ORC};
break;
}
// pick Jobs
std::shuffle(wind.begin(), wind.end(), rng);
if (type != RunPure) {
std::shuffle(water.begin(), water.end(), rng);
std::shuffle(fire.begin(), fire.end(), rng);
std::shuffle(earth.begin(), earth.end(), rng);
jobI = wind.first();
jobA = water.first();
jobF = fire.first();
jobE = earth.first();
if (modifier == ModVoid) {
// nix a job
} else if (modifier == ModFifth) {
earth.removeFirst();
jobK = earth.first();
}
} else {
jobI = wind.first();
wind.removeFirst();
jobA = wind.first();
wind.removeFirst();
jobF = wind.first();
wind.removeFirst();
jobE = wind.first();
if (modifier == ModVoid) {
// nix a job
} else {
wind.removeFirst();
jobK = wind.first();
}
}
// write patch
patch->open(QIODevice::ReadWrite);
patch->write("PATCH", 5);
// nix gaining FRL outside of actually rolling it
patch->write(be24(0x3d4f6d));
patch->write("\x00\x02", 2);
patch->write("\x32\xfe", 2);
patch->write(be24(0x55202));
patch->write("\x00\x02", 2);
patch->write("\x00\x00", 2);
// job menu adjustments
for (int i = 0; i < 2; i++) {
char temp[2] = {static_cast<char>(id2menu[jobI] & 0xFF), '\0'};
patch->write(be24(job_addr[i]));
patch->write("\x00\x01", 2);
patch->write(temp, 1);
}
// job assignments
for (int i = 0; i < 7; i++) {
char temp[2] = {jobI, '\0'};
patch->write(be24(wind_addr[i] + 1));
patch->write("\x00\x01", 2);
patch->write(temp, 1);
}
for (int i = 0; i < 6; i++) {
char temp[2] = {jobA, '\0'};
patch->write(be24(water_addr[i] + 1));
patch->write("\x00\x01", 2);
patch->write(temp, 1);
}
for (int i = 0; i < 5; i++) {
char temp[2] = {jobF, '\0'};
patch->write(be24(fire_addr[i] + 1));
patch->write("\x00\x01", 2);
patch->write(temp, 1);
}
for (int i = 0; i < 4; i++) {
char temp[2] = {jobE, '\0'};
patch->write(be24(earth_addr[i] + 1));
patch->write("\x00\x01", 2);
patch->write(temp, 1);
}
for (int i = 0; i < 3; i++) {
char temp[2];
if (modifier == ModFifth) {
temp[0] = jobK;
} else {
temp[0] = jobE;
}
temp[1] = '\0';
patch->write(be24(adv_addr[i] + 1));
patch->write("\x00\x01", 2);
patch->write(temp,1);
}
patch->write("EOF", 3);
patch->seek(0);
return patch;
}
// KNI MNK THF DRG NIN SAM
// BER RNG MYS WHT BLK TIM SUM
// BLU RED BST CHM GEO BRD
// DNC NCR ORC CAN GLD MIM FRL
// 07 06 05 04 03 02
// 01 00 0F 0E 0D 0C 0B
// 0A 09 08 1A 1B 19
// 18 BLK SUM TIM BLU 17 16
// MYS WHT 01 02

68
src/fiesta.hh Normal file
View File

@ -0,0 +1,68 @@
#pragma once
#include <random>
#include <QBuffer>
#include "randodata.hh"
enum RunType {
RunNormal = 0,
Run750,
RunNo750,
RunRandom,
RunRandom750,
RunRandomNo750,
RunChaos,
RunChaos750,
RunChaosNo750,
RunPure,
RunAdvance
};
enum RunModifier {
ModNone,
ModFifth,
ModVoid
};
extern QByteArray be24(int num);
enum Job {
RNG = 0x00,
BER = 0x01,
SAM = 0x02,
NIN = 0x03,
DRG = 0x04,
THF = 0x05,
MNK = 0x06,
KNI = 0x07,
BST = 0x08,
RED = 0x09,
BLU = 0x0a,
SUM = 0x0b,
TIM = 0x0c,
BLK = 0x0d,
WHT = 0x0e,
MYS = 0x0f,
FRL = 0x12,
MIM = 0x13,
DNC = 0x14,
BRD = 0x15,
GEO = 0x16,
CHM = 0x17,
GLD = 0x18,
CAN = 0x19,
ORC = 0x1a,
NCR = 0x1b
};
class Fiesta {
public:
Fiesta(std::mt19937 rand);
~Fiesta();
QBuffer *makeRun(RunType type, RunModifier modifier);
private:
std::mt19937 rng;
};

View File

@ -35,7 +35,7 @@ int main(int argc, char **argv) {
QApplication::setOrganizationDomain("aerdan.org");
QApplication::setApplicationName("Exdeath");
QApplication::setApplicationDisplayName("Exdeath");
QApplication::setApplicationVersion("0.5");
QApplication::setApplicationVersion("0.8");
QSettings *cfg = new QSettings();
Exdeath *win = new Exdeath(cfg);