engine/ext/gui/battle.cpp
2020-07-04 00:00:00 -05:00

1522 lines
58 KiB
C++

#include "battle.h"
#include "gui.h"
#include <uf/utils/hook/hook.h>
#include <uf/utils/time/time.h>
#include <uf/utils/serialize/serializer.h>
#include <uf/utils/userdata/userdata.h>
#include <uf/utils/window/window.h>
#include <uf/utils/camera/camera.h>
#include <uf/utils/mesh/mesh.h>
#include <uf/utils/string/ext.h>
// #include <uf/gl/glyph/glyph.h>
#include "../world/world.h"
#include "../world//battle.h"
#include "../asset/asset.h"
#include <unordered_map>
#include <uf/ext/vulkan/vulkan.h>
#include <uf/ext/vulkan/graphics/gui.h>
#include <uf/utils/http/http.h>
#include <uf/utils/audio/audio.h>
#include <sys/stat.h>
#include <fstream>
namespace {
ext::Gui* circleIn;
ext::Gui* circleOut;
ext::Gui* battleMessage;
ext::Gui* commandOptions;
ext::Gui* battleOptions;
ext::Gui* targetOptions;
ext::Gui* optionsBackground;
ext::Gui* turnCounters;
ext::Gui* partyMemberCommandCircle;
ext::Gui* critCutInBackground;
ext::Gui* critCutIn;
std::vector<ext::Gui*> partyMemberButtons(5);
// std::vector<ext::Gui*> partyMemberIcons(5);
// std::vector<ext::Gui*> partyMemberTexts(5);
std::vector<ext::Gui*> particles;
ext::HousamoBattle* battleManager;
ext::World* world;
uf::Serializer masterTableGet( const std::string& table ) {
if ( !world ) world = (ext::World*) uf::Entity::globalFindByName("World");
if ( !world ) return std::string();
uf::Serializer& mastertable = world->getComponent<uf::Serializer>();
return mastertable["system"]["mastertable"][table];
}
uf::Serializer masterDataGet( const std::string& table, const std::string& key ) {
if ( !world ) world = (ext::World*) uf::Entity::globalFindByName("World");
if ( !world ) return std::string();
uf::Serializer& mastertable = world->getComponent<uf::Serializer>();
return mastertable["system"]["mastertable"][table][key];
}
inline int64_t parseInt( const std::string& str ) {
return atoi(str.c_str());
}
inline std::string colorString( const std::string& hex ) {
return "%#" + hex + "%";
}
void playSound( ext::GuiBattle& entity, const std::string& id, const std::string& key ) {
if ( !world ) world = (ext::World*) uf::Entity::globalFindByName("World");
if ( !world ) return;
uf::Serializer& masterdata = world->getComponent<uf::Serializer>();
uf::Serializer cardData = masterDataGet("Card", id);
uf::Serializer charaData = masterDataGet("Chara", cardData["character_id"].asString());
std::string name = charaData["filename"].asString();
if ( name == "none" ) return;
std::string url = "https://cdn..xyz//unity/Android/voice/voice_" + name + "_"+key+".ogg";
if ( charaData["internal"].asBool() ) {
url = "./data/smtsamo/voice/voice_" + name + "_" + key + ".ogg";
}
ext::Asset& assetLoader = world->getComponent<ext::Asset>();
assetLoader.cache(url, "asset:Cache.Voice." + std::to_string(entity.getUid()));
}
void playSound( ext::GuiBattle& entity, std::size_t uid, const std::string& key ) {
if ( !world ) world = (ext::World*) uf::Entity::globalFindByName("World");
if ( !world ) return;
uf::Serializer& pMetadata = entity.getComponent<uf::Serializer>();
uf::Serializer& masterdata = world->getComponent<uf::Serializer>();
uf::Entity* = world->findByUid(uid);
if ( ! ) return;
uf::Serializer& metadata = ->getComponent<uf::Serializer>();
std::string id = metadata[""]["id"].asString();
playSound( entity, id, key );
}
void playSound( ext::GuiBattle& entity, const std::string& key ) {
if ( !world ) world = (ext::World*) uf::Entity::globalFindByName("World");
if ( !world ) return;
uf::Serializer& metadata = entity.getComponent<uf::Serializer>();
uf::Serializer& masterdata = world->getComponent<uf::Serializer>();
std::string url = "./data/audio/ui/" + key + ".ogg";
ext::Asset& assetLoader = world->getComponent<ext::Asset>();
assetLoader.cache(url, "asset:Cache.SFX." + std::to_string(entity.getUid()));
}
void playMusic( ext::GuiBattle& entity, const std::string& filename ) {
if ( !world ) world = (ext::World*) uf::Entity::globalFindByName("World");
if ( !world ) return;
ext::Asset& assetLoader = world->getComponent<ext::Asset>();
uf::Serializer& masterdata = world->getComponent<uf::Serializer>();
assetLoader.load(filename, "asset:Load." + std::to_string(world->getUid()));
}
std::string getKeyFromIndex( uf::Serializer& object, uint64_t index ) {
uint64_t i = 0;
std::string key = "";
for ( auto it = object.begin(); it != object.end(); ++it ) {
if ( i++ == index ) key = it.key().asString();
}
return key;
}
uf::Audio sfx;
uf::Audio voice;
struct BattleStats {
struct {
int selection = 0;
int selectionsMax = 3;
std::vector<std::string> invalids;
} skill;
struct {
int selection = 0;
int selectionsMax = 3;
std::vector<std::string> invalids;
uf::Serializer current;
} actions;
struct {
int selection = 0;
int selectionsMax = 3;
std::vector<std::string> invalids;
uf::Serializer current;
} targets;
uf::Serializer currentMember;
uf::Serializer previousMember;
std::string state = "open";
bool initialized = false;
};
static BattleStats stats;
}
void ext::GuiBattle::initialize() {
ext::Gui::initialize();
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
battleManager = (ext::HousamoBattle*) this->getRootParent().findByName( "Battle Manager" );
partyMemberButtons = std::vector<ext::Gui*>(5);
this->addHook( "asset:Cache.SFX." + std::to_string(this->getUid()), [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
if ( uf::string::extension(filename) != "ogg" ) return "false";
if ( filename == "" ) return "false";
uf::Serializer& masterdata = world->getComponent<uf::Serializer>();
uf::Audio& sfx = this->getComponent<uf::SoundEmitter>().add(filename);
/*
uf::Audio& sfx = this->getComponent<uf::Audio>();
if ( sfx.playing() ) sfx.stop();
sfx = uf::Audio();
sfx.load(filename);
*/
sfx.setVolume(masterdata["volumes"]["sfx"].asFloat());
sfx.play();
return "true";
});
this->addHook( "asset:Cache.Voice." + std::to_string(this->getUid()), [&](const std::string& event)->std::string{
uf::Serializer json = event;
std::string filename = json["filename"].asString();
if ( uf::string::extension(filename) != "ogg" ) return "false";
if ( filename == "" ) return "false";
uf::Serializer& masterdata = world->getComponent<uf::Serializer>();
uf::Audio& voice = this->getComponent<uf::Audio>();
if ( voice.playing() ) voice.stop();
voice = uf::Audio();
voice.load(filename);
voice.setVolume(masterdata["volumes"]["voice"].asFloat());
voice.play();
return "true";
});
// lock control
{
uf::Serializer payload;
payload["state"] = true;
uf::hooks.call("window:Mouse.CursorVisibility", payload);
uf::hooks.call("window:Mouse.Lock");
}
{
battleMessage = new ext::Gui;
this->addChild(*battleMessage);
battleMessage->load("./entities/gui/battle/battle-text.json");
battleMessage->initialize();
}
/* Magic Circle Outter */ {
circleOut = new ext::Gui;
this->addChild(*circleOut);
circleOut->load("./entities/gui/battle/circle-out.json");
circleOut->initialize();
}
/* Magic Circle Inner */ {
circleIn = new ext::Gui;
this->addChild(*circleIn);
circleIn->load("./entities/gui/battle/circle-in.json");
circleIn->initialize();
}
/* Command Circle */ {
partyMemberCommandCircle = new ext::Gui;
this->addChild(*partyMemberCommandCircle);
partyMemberCommandCircle->load("./entities/gui/battle/partyMemberCommandCircle.json");
partyMemberCommandCircle->initialize();
}
/* Command Circle */ {
optionsBackground = new ext::Gui;
this->addChild(*optionsBackground);
optionsBackground->load("./entities/gui/battle/optionsBackground.json");
optionsBackground->initialize();
}
/* Turn Counter Container */ {
turnCounters = new ext::Gui;
this->addChild(*turnCounters);
turnCounters->load("./entities/gui/battle/turnCounters.json");
turnCounters->initialize();
}
this->addHook("world:Battle.TurnStart.%UID%", [&](const std::string& event) -> std::string {
uf::Serializer json = event;
// turn start, play sfx
if ( json["battle"]["turn"]["start of turn"].asBool() ) {
playSound(*this, "turn");
}
return "true";
});
this->addHook("world:Battle.Damage.%UID%", [&](const std::string& event) -> std::string {
uf::Serializer json = event;
std::string uid = json["target"]["uid"].asString();
std::string damage = json["target"]["damage"].asString();
pod::Transform<> pTransform;
pTransform.position = { 0, 0, 0 };
for ( auto* pointerButton : partyMemberButtons ) {
if ( !pointerButton ) continue;
if ( pointerButton->getUid() == 0 ) continue;
for ( auto* pointer : pointerButton->getChildren() ) {
if ( !pointer ) continue;
if ( pointer->getUid() == 0 ) continue;
if ( pointer->getName() == "Menu: Party Member Icon" ) {
uf::Serializer& pMetadata = pointer->getComponent<uf::Serializer>();
if ( pMetadata[""]["uid"].asString() != uid ) continue;
pTransform = pointer->getComponent<pod::Transform<>>();
pTransform.position.y -= (0.1);
}
}
}
ext::Gui* particle = new ext::Gui;
this->addChild(*particle);
uf::Serializer& pMetadata = particle->getComponent<uf::Serializer>();
particle->load("./entities/gui/battle/damageText.json");
std::string color = json["color"].isString() ? json["color"].asString() : "FF0000";
pMetadata["text settings"]["string"] = "%#"+color+"%" + damage;
pod::Transform<>& transform = particle->getComponent<pod::Transform<>>();
transform = pTransform;
pMetadata["system"]["percent"] = 0;
particle->initialize();
particles.push_back(particle);
return "true";
});
this->addHook("world:Battle.Message.%UID%", [&](const std::string& event) -> std::string {
uf::Serializer json = event;
std::string message = json["message"].asString();
if ( battleMessage ) {
battleMessage->destroy();
this->removeChild(*battleMessage);
delete battleMessage;
}
battleMessage = new ext::Gui;
this->addChild(*battleMessage);
uf::Serializer& pMetadata = battleMessage->getComponent<uf::Serializer>();
battleMessage->load("./entities/gui/battle/battle-text.json");
pMetadata["text settings"]["string"] = message;
battleMessage->initialize();
// std::cout << message << std::endl;
return "true";
});
this->addHook("world:Battle.RemoveOnCrit.%UID%", [&](const std::string& event) -> std::string {
if ( critCutInBackground && critCutInBackground->getUid() != 0 ) {
critCutInBackground->destroy();
this->removeChild(*critCutInBackground);
delete critCutInBackground;
critCutInBackground = NULL;
}
if ( critCutIn && critCutIn->getUid() != 0 ) {
critCutIn->destroy();
this->removeChild(*critCutIn);
delete critCutIn;
critCutIn = NULL;
}
return "true";
});
this->addHook("world:Battle.OnCrit.%UID%", [&](const std::string& event) -> std::string {
uf::Serializer json = event;
if ( critCutInBackground && critCutInBackground->getUid() != 0 ) {
critCutInBackground->destroy();
this->removeChild(*critCutInBackground);
delete critCutInBackground;
critCutInBackground = NULL;
}
if ( critCutIn && critCutIn->getUid() != 0 ) {
critCutIn->destroy();
this->removeChild(*critCutIn);
delete critCutIn;
critCutIn = NULL;
}
{
critCutInBackground = new ext::Gui;
this->addChild(*critCutInBackground);
critCutInBackground->load("./entities/gui/battle/critCutInBackground.json");
critCutInBackground->initialize();
}
{
critCutIn = new ext::Gui;
this->addChild(*critCutIn);
uf::Serializer& pMetadata = critCutIn->getComponent<uf::Serializer>();
uf::Serializer cardData = masterDataGet("Card", json["id"].asString());
pMetadata["system"]["assets"][0] = "./data/smtsamo/ci/ci_"+ cardData["filename"].asString() +".png";
if ( !uf::string::exists( pMetadata["system"]["assets"][0].asString() ) ) pMetadata["system"]["assets"][0] = Json::nullValue;
critCutIn->load("./entities/gui/battle/critCutIn.json");
critCutIn->initialize();
}
playSound(*this, "crit");
this->queueHook("world:Battle.RemoveOnCrit.%UID%", "", 1.0);
return "true";
});
this->addHook("world:Battle.Update.%UID%", [&](const std::string& event) -> std::string {
uf::Serializer json = event;
{
float turns = json["battle"]["turn"]["counter"].asFloat();
if ( turnCounters && turnCounters->getUid() != 0 ) {
this->removeChild(*turnCounters);
turnCounters->destroy();
delete turnCounters;
}
{
turnCounters = new ext::Gui;
this->addChild(*turnCounters);
turnCounters->load("./entities/gui/battle/turnCounters.json");
turnCounters->initialize();
}
// show full counters
float i = 0;
while ( turns > 0 ) {
ext::Gui* counter = new ext::Gui;
turnCounters->addChild(*counter);
counter->load("./entities/gui/battle/turnCounter.json");
counter->initialize();
pod::Transform<>& pTransform = counter->getComponent<pod::Transform<>>();
pTransform.position.x -= 0.142716f * (i++);
uf::Serializer& pMetadata = counter->getComponent<uf::Serializer>();
if ( json["battle"]["turn"]["phase"] == "enemy" ) {
pMetadata["color"][0] = 1.0f;
pMetadata["color"][1] = 0.4f;
pMetadata["color"][2] = 0.4f;
pMetadata["color"][3] = 1.0f;
} else {
pMetadata["color"][0] = 0.4f;
pMetadata["color"][1] = 0.0f;
pMetadata["color"][2] = 0.8f;
pMetadata["color"][3] = 1.0f;
}
// if ( turns < 1.0f && turns > 0 ) pMetadata["uv"][0] = 0.5f;
if ( turns < 1.0f && turns > 0 ) {
pMetadata["half counter"] = true;
if ( json["battle"]["turn"]["phase"] == "enemy" ) {
pMetadata["color"][0] = 1.0f;
pMetadata["color"][1] = 0.7f;
pMetadata["color"][2] = 0.7f;
pMetadata["color"][3] = 1.0f;
} else {
pMetadata["color"][0] = 0.4f;
pMetadata["color"][1] = 0.3f;
pMetadata["color"][2] = 0.9f;
pMetadata["color"][3] = 1.0f;
}
}
turns = turns - 1.0f;
}
}
int i = 0;
for ( auto& member : json["battle"]["transients"] ) {
if ( member["uid"].isNull() ) continue;
if ( member["type"] == "enemy" ) continue;
if ( member["hp"].asFloat() <= 0 ) continue;
if ( i >= 4 ) break;
uf::Serializer cardData = masterDataGet("Card", member["id"].asString());
std::string name = cardData["filename"].asString();
if ( member["skin"].isString() ) name += "_" + member["skin"].asString();
std::string filename = "https://cdn..xyz//unity/Android/icon/icon_" + name + ".png";
if ( cardData["internal"].asBool() ) {
filename = "./data/smtsamo/icon/icon_" + name + ".png";
}
ext::Gui* partyMemberButton = NULL;
pod::Transform<> bTransform;
// completely recreate if different transient
if ( partyMemberButtons[i] != NULL ) {
partyMemberButton = partyMemberButtons[i];
uf::Serializer& pMetadata = partyMemberButton->getComponent<uf::Serializer>();
if ( pMetadata[""]["id"] != member["id"] ) {
this->removeChild(*partyMemberButton);
partyMemberButton->destroy();
delete partyMemberButton;
partyMemberButton = NULL;
} else {
pod::Transform<>& transform = partyMemberButton->getComponent<pod::Transform<>>();
bTransform = transform;
}
}
// update
if ( partyMemberButton ) {
{
ext::Gui* partyMemberText = (ext::Gui*) partyMemberButton->findByName("Menu: Party Member Text");
if ( partyMemberText ) {
partyMemberButton->removeChild(*partyMemberText);
partyMemberText->destroy();
delete partyMemberText;
partyMemberText = NULL;
}
partyMemberText = new ext::Gui;
partyMemberButton->addChild(*partyMemberText);
uf::Serializer& pMetadata = partyMemberText->getComponent<uf::Serializer>();
partyMemberText->load("./entities/gui/battle/partyMemberText.json");
pMetadata["text settings"]["string"] = "" + colorString("00FF00") + "" + member["hp"].asString() + "\n" + colorString("0000FF") + "" + member["mp"].asString();
pMetadata[""] = member;
pod::Transform<>& transform = partyMemberText->getComponent<pod::Transform<>>();
transform.position = bTransform.position;
transform.position.x += (-0.781352 - -0.694634) + 0.1;
partyMemberText->initialize();
}
ext::Gui* partyMemberHP = (ext::Gui*) partyMemberButton->findByName("Menu: Party Member HP Bar");
if ( partyMemberHP ) {
uf::Serializer& pMetadata = partyMemberHP->getComponent<uf::Serializer>();
float percentage = 1.0f;
percentage = member["hp"].asFloat() / member["max hp"].asFloat();
// uv[0, 0] -> uv[09.43, 23.81]
// uv[1, 1] -> uv[84.91, 68.25]
pMetadata["uv"][2] = (percentage * 0.8491) + 0.0660;
// pMetadata["uv"][3] = (percentage * 0.6808) + (1 - 0.0952);
}
ext::Gui* partyMemberMP = (ext::Gui*) partyMemberButton->findByName("Menu: Party Member MP Bar");
if ( partyMemberMP ) {
uf::Serializer& pMetadata = partyMemberMP->getComponent<uf::Serializer>();
float percentage = 1.0f;
percentage = member["mp"].asFloat() / member["max mp"].asFloat();
// uv[0, 0] -> uv[09.43, 23.81]
// uv[1, 1] -> uv[84.91, 68.25]
pMetadata["uv"][2] = (percentage * 0.8491) + 0.0943;
// pMetadata["uv"][3] = (percentage * 0.6825) + (1 - 0.2381);
}
// recreate
} else {
{
partyMemberButton = new ext::Gui;
this->addChild(*partyMemberButton);
partyMemberButton->load("./entities/gui/battle/partyMemberButton.json");
pod::Transform<>& transform = partyMemberButton->getComponent<pod::Transform<>>();
transform.position.y += (i * 0.45);
bTransform = transform;
partyMemberButton->initialize();
uf::Serializer& pMetadata = partyMemberButton->getComponent<uf::Serializer>();
pMetadata[""] = member;
partyMemberButtons[i] = partyMemberButton;
}
{
ext::Gui* partyMemberIconShadow = NULL;
partyMemberIconShadow = new ext::Gui;
partyMemberButton->addChild(*partyMemberIconShadow);
uf::Serializer& pMetadata = partyMemberIconShadow->getComponent<uf::Serializer>();
pMetadata["system"]["assets"][0] = filename;
partyMemberIconShadow->load("./entities/gui/battle/partyMemberIconShadow.json");
pMetadata[""] = member;
pod::Transform<>& transform = partyMemberIconShadow->getComponent<pod::Transform<>>();
transform.position = bTransform.position;
transform.position.x += (-0.781352 - -0.694634) + 0.01;
transform.position.y -= 0.01;
partyMemberIconShadow->initialize();
}
{
ext::Gui* partyMemberIcon = NULL;
partyMemberIcon = new ext::Gui;
partyMemberButton->addChild(*partyMemberIcon);
uf::Serializer& pMetadata = partyMemberIcon->getComponent<uf::Serializer>();
pMetadata["system"]["assets"][0] = filename;
partyMemberIcon->load("./entities/gui/battle/partyMemberIcon.json");
pMetadata[""] = member;
pod::Transform<>& transform = partyMemberIcon->getComponent<pod::Transform<>>();
transform.position = bTransform.position;
transform.position.x += (-0.781352 - -0.694634);
partyMemberIcon->initialize();
}
{
ext::Gui* partyMemberText = NULL;
partyMemberText = new ext::Gui;
partyMemberButton->addChild(*partyMemberText);
uf::Serializer& pMetadata = partyMemberText->getComponent<uf::Serializer>();
partyMemberText->load("./entities/gui/battle/partyMemberText.json");
pMetadata["text settings"]["string"] = "" + colorString("FF0000") + "" + member["hp"].asString() + "\n" + colorString("0000FF") + "" + member["mp"].asString();
pMetadata[""] = member;
pod::Transform<>& transform = partyMemberText->getComponent<pod::Transform<>>();
transform.position = bTransform.position;
transform.position.x += (-0.781352 - -0.694634) + 0.1;
partyMemberText->initialize();
}
{
ext::Gui* partyMemberBar = new ext::Gui;
partyMemberButton->addChild(*partyMemberBar);
partyMemberBar->load("./entities/gui/battle/partyMemberBars.json");
pod::Transform<>& transform = partyMemberBar->getComponent<pod::Transform<>>();
transform.position = bTransform.position;
transform.position.x = 0.742573;
transform.position.y += 0.1;
partyMemberBar->initialize();
}
{
ext::Gui* partyMemberHP = new ext::Gui;
partyMemberButton->addChild(*partyMemberHP);
partyMemberHP->load("./entities/gui/battle/partyMemberHP.json");
pod::Transform<>& transform = partyMemberHP->getComponent<pod::Transform<>>();
transform.position = bTransform.position;
transform.position.x = 0.742573;
transform.position.y += 0.1;
partyMemberHP->initialize();
uf::Serializer& pMetadata = partyMemberHP->getComponent<uf::Serializer>();
float percentage = 1.0f;
percentage = member["hp"].asFloat() / member["max hp"].asFloat();
// uv[0, 0] -> uv[09.43, 23.81]
// uv[1, 1] -> uv[84.91, 68.25]
pMetadata["uv"][2] = (percentage * 0.8491) + 0.0660;
// pMetadata["uv"][3] = (percentage * 0.6808) + (1 - 0.0952);
}
{
ext::Gui* partyMemberMP = new ext::Gui;
partyMemberButton->addChild(*partyMemberMP);
partyMemberMP->load("./entities/gui/battle/partyMemberMP.json");
pod::Transform<>& transform = partyMemberMP->getComponent<pod::Transform<>>();
transform.position = bTransform.position;
transform.position.x = 0.742573;
transform.position.y += 0.1;
partyMemberMP->initialize();
uf::Serializer& pMetadata = partyMemberMP->getComponent<uf::Serializer>();
float percentage = 1.0f;
percentage = member["mp"].asFloat() / member["max mp"].asFloat();
// uv[0, 0] -> uv[09.43, 23.81]
// uv[1, 1] -> uv[84.91, 68.25]
pMetadata["uv"][2] = (percentage * 0.8491) + 0.0943;
// pMetadata["uv"][3] = (percentage * 0.6825) + (1 - 0.2381);
}
}
++i;
};
for ( ; i < 4; ++i ) {
if ( partyMemberButtons[i] != NULL ) {
ext::Gui*& partyMemberButton = partyMemberButtons[i];
this->removeChild(*partyMemberButton);
partyMemberButton->destroy();
delete partyMemberButton;
partyMemberButton = NULL;
}
}
return "true";
});
this->addHook("menu:Close.%UID%", [&]( const std::string& event ) -> std::string {
// kill
this->getParent().removeChild(*this);
this->destroy();
delete this;
return "true";
});
stats = BattleStats();
}
void ext::GuiBattle::tick() {
if ( !battleManager ) return;
ext::World& world = this->getRootParent<ext::World>();
uf::Serializer& masterdata = world.getComponent<uf::Serializer>();
uf::Serializer& bMetadata = this->getComponent<uf::Serializer>();
static float alpha = 0.0f;
static uf::Timer<long long> timer(false);
static float timeout = 1.0f;
if ( !timer.running() ) timer.start();
static std::string queuedAction;
std::function<void(uf::Serializer&)> postParseResult = [&]( uf::Serializer& result ) {
if ( result["end"].asBool() ) bMetadata["system"]["closing"] = true;
if ( !result["timeout"].isNull() ) timeout = result["timeout"].asFloat();
else timeout = 1;
// modify timeout based on string length
if ( result["message"].isString() && !result["target"].isNull() ) {
uint64_t size = result["message"].asString().size();
float modified = size * 0.025f;
if ( timeout < modified ) timeout = modified;
}
uf::Serializer payload;
payload["message"] = result["message"];
this->callHook("world:Battle.Message.%UID%", payload);
timer.reset();
};
std::function<void(uf::Serializer)> renderSkillOptions = [&]( uf::Serializer member ) {
if ( battleOptions ) {
this->removeChild(*battleOptions);
battleOptions->destroy();
delete battleOptions;
battleOptions = NULL;
}
if ( member["uid"].isNull() ) {
stats.previousMember = stats.currentMember;
return;
}
stats.currentMember = member;
std::string string = "";
std::size_t counter = 0;
std::size_t start = stats.skill.selection;
stats.actions.invalids.clear();
stats.currentMember["skills"] = Json::arrayValue;
for ( int i = 0; i < member["skills"].size(); ++i ) {
std::string id = member["skills"][i].asString();
uf::Serializer skillData = masterDataGet("Skill", id);
bool add = false;
if ( skillData["type"].asInt() > 0 && skillData["type"].asInt() < 16 ) add = true;
if ( add ) stats.currentMember["skills"].append(id);
}
std::string skillDescription = "";
for ( int i = start; i < stats.currentMember["skills"].size(); ++i ) {
std::string id = stats.currentMember["skills"][i].asString();
std::string text = "";
if ( std::find( stats.skill.invalids.begin(), stats.skill.invalids.end(), id ) != stats.skill.invalids.end() ) continue;
if ( ++counter > stats.skill.selectionsMax ) break;
uf::Serializer cardData = masterDataGet("Card", member["id"].asString());
uf::Serializer charaData = masterDataGet("Chara", cardData["character_id"].asString());
uf::Serializer skillData = masterDataGet("Skill", id);
if ( id != "0" ) {
text = skillData["name"].asString();
} else {
text = "攻撃";
}
if ( i != stats.skill.selection ) {
text = "" + colorString("FFFFFF") + "" + text;
}
else {
text = "" + colorString("FF0000") + "" + text;
skillDescription = skillData["effect"].asString();
if ( skillData["mp"].isNumeric() ) {
int64_t cost = skillData["mp"].asInt64();
skillDescription = skillData["effect"].asString() + "\nCost: " + colorString("0000FF") + ""+std::to_string(cost)+" MP" + colorString("FFFFFF") + "";
}
if ( skillData["hp%"].isNumeric() ) {
int64_t cost = skillData["hp%"].asInt64();
cost = member["max hp"].asFloat() * ( cost / 100.0f );
skillDescription = skillData["effect"].asString() + "\nCost: " + colorString("00FF00") + ""+std::to_string(cost)+" HP" + colorString("FFFFFF") + "";
}
}
string += "\n" + text;
}
if ( stats.currentMember["skills"].size() > stats.skill.selectionsMax ) {
for ( int i = 0; i < i < stats.currentMember["skills"].size(); ++i ) {
std::string id = stats.currentMember["skills"][i].asString();
std::string text = "";
if ( std::find( stats.skill.invalids.begin(), stats.skill.invalids.end(), id ) != stats.skill.invalids.end() ) continue;
if ( ++counter > stats.skill.selectionsMax ) break;
if ( id != "0" ) {
uf::Serializer cardData = masterDataGet("Card", member["id"].asString());
uf::Serializer charaData = masterDataGet("Chara", cardData["character_id"].asString());
uf::Serializer skillData = masterDataGet("Skill", id);
text = skillData["name"].asString();
} else {
uf::Serializer cardData = masterDataGet("Card", member["id"].asString());
uf::Serializer charaData = masterDataGet("Chara", cardData["character_id"].asString());
text = "攻撃";
}
if ( i != stats.skill.selection ) text = "" + colorString("FFFFFF") + "" + text;
else text = "" + colorString("FF0000") + "" + text;
string += "\n" + text;
}
}
if ( string != "" ) {
string = string.substr(1);
battleOptions = new ext::Gui;
this->addChild(*battleOptions);
uf::Serializer& pMetadata = battleOptions->getComponent<uf::Serializer>();
battleOptions->load("./entities/gui/battle/battle-option.json");
pMetadata["text settings"]["string"] = string;
pod::Transform<>& pTransform = battleOptions->getComponent<pod::Transform<>>();
battleOptions->initialize();
}
if ( skillDescription != "" ) {
uf::Serializer payload;
payload["message"] = skillDescription;
this->callHook("world:Battle.Message.%UID%", payload);
}
};
std::function<void(uf::Serializer)> renderCommandOptions = [&]( uf::Serializer actions ) {
if ( commandOptions ) {
this->removeChild(*commandOptions);
commandOptions->destroy();
delete commandOptions;
commandOptions = NULL;
}
if ( actions.isNull() ) {
stats.actions.selection = 0;
queuedAction = "";
return;
}
stats.actions.current = actions;
std::string string = "";
std::size_t counter = 0;
std::size_t start = stats.actions.selection;
auto keys = actions.getMemberNames();
for ( int i = start; i < keys.size(); ++i ) {
std::string key = getKeyFromIndex( actions, i );
std::string text = actions[key].asString();
if ( std::find( stats.actions.invalids.begin(), stats.actions.invalids.end(), key ) != stats.actions.invalids.end() ) continue;
if ( ++counter > stats.actions.selectionsMax ) break;
if ( i != stats.actions.selection ) text = "" + colorString("FFFFFF") + "" + text;
else text = "" + colorString("FF0000") + "" + text;
string += "\n" + text;
}
if ( keys.size() > stats.actions.selectionsMax ) {
for ( int i = 0; i < keys.size(); ++i ) {
std::string key = getKeyFromIndex( actions, i );
std::string text = actions[key].asString();
if ( std::find( stats.actions.invalids.begin(), stats.actions.invalids.end(), key ) != stats.actions.invalids.end() ) continue;
if ( ++counter > stats.actions.selectionsMax ) break;
if ( i != stats.actions.selection ) text = "" + colorString("FFFFFF") + "" + text;
else text = "" + colorString("FF0000") + "" + text;
string += "\n" + text;
}
}
if ( string != "" ) {
string = string.substr(1);
commandOptions = new ext::Gui;
this->addChild(*commandOptions);
uf::Serializer& pMetadata = commandOptions->getComponent<uf::Serializer>();
commandOptions->load("./entities/gui/battle/battle-option.json");
pMetadata["text settings"]["string"] = string;
pod::Transform<>& pTransform = commandOptions->getComponent<pod::Transform<>>();
commandOptions->initialize();
}
};
std::function<void(uf::Serializer)> renderTargetOptions = [&]( uf::Serializer actions ) {
if ( targetOptions ) {
this->removeChild(*targetOptions);
targetOptions->destroy();
delete targetOptions;
targetOptions = NULL;
}
if ( actions.isNull() ) {
stats.skill.selection = 0;
stats.targets.selection = 0;
return;
}
stats.targets.current = actions;
std::string string = "";
std::size_t counter = 0;
std::size_t start = stats.targets.selection;
stats.skill.invalids.clear();
stats.actions.invalids.clear();
std::string targetDescription = "";
for ( int i = start; i < actions.size(); ++i ) {
uf::Serializer cardData = masterDataGet("Card", actions[i]["id"].asString());
uf::Serializer charaData = masterDataGet("Chara", cardData["character_id"].asString());
std::string text = charaData["name"].asString();
if ( std::find( stats.targets.invalids.begin(), stats.targets.invalids.end(), text ) != stats.targets.invalids.end() ) continue;
if ( ++counter > stats.targets.selectionsMax ) break;
if ( i != stats.targets.selection ) text = "" + colorString("FFFFFF") + "" + text;
else text = "" + colorString("FF0000") + "" + text;
string += "\n" + text;
}
if ( actions.size() > stats.targets.selectionsMax ) {
for ( int i = 0; i < actions.size(); ++i ) {
uf::Serializer cardData = masterDataGet("Card", actions[i]["id"].asString());
uf::Serializer charaData = masterDataGet("Chara", cardData["character_id"].asString());
std::string text = charaData["name"].asString();
if ( std::find( stats.targets.invalids.begin(), stats.targets.invalids.end(), text ) != stats.targets.invalids.end() ) continue;
if ( ++counter > stats.targets.selectionsMax ) break;
if ( i != stats.targets.selection ) text = "" + colorString("FFFFFF") + "" + text;
else text = "" + colorString("FF0000") + "" + text;
string += "\n" + text;
}
}
if ( string != "" ) {
string = string.substr(1);
targetOptions = new ext::Gui;
this->addChild(*targetOptions);
uf::Serializer& pMetadata = targetOptions->getComponent<uf::Serializer>();
targetOptions->load("./entities/gui/battle/battle-option.json");
pMetadata["text settings"]["string"] = string;
pod::Transform<>& pTransform = targetOptions->getComponent<pod::Transform<>>();
targetOptions->initialize();
}
if ( queuedAction == "analyze" ) {
uf::Serializer payload;
payload["uid"] = stats.targets.current[stats.targets.selection]["uid"].asString();
// if ( payload["uid"].asString() == "")
payload["action"] = "analyze";
uf::Serializer result = battleManager->callHook("world:Battle.Action.%UID%", payload)[0];
targetDescription = result["message"].asString();
}
if ( targetDescription != "" ) {
uf::Serializer payload;
payload["message"] = targetDescription;
this->callHook("world:Battle.Message.%UID%", payload);
}
};
if ( !stats.initialized ) {
stats.initialized = true;
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
this->addHook("world:Battle.Turn.%UID%", [&](const std::string& event) -> std::string {
uf::Serializer json = event;
uf::Serializer payload;
payload["action"] = "turn-start";
if ( !stats.previousMember["uid"].isNull() ) payload["uid"] = stats.previousMember["uid"].asUInt64() + 1;
auto hookCall = battleManager->callHook("world:Battle.Action.%UID%", payload);
if ( hookCall.empty() ) {
metadata["system"]["closing"] = true;
return "false";
}
uf::Serializer result = hookCall[0];
if ( result["end"].asBool() ) {
if ( metadata.isObject() ) metadata["system"]["closing"] = true;
return "false";
}
postParseResult(result);
if ( result["uid"].isNull() ) return "false";
uint64_t uid = result["uid"].asUInt64();
renderCommandOptions(std::string(""));
renderSkillOptions(std::string(""));
renderTargetOptions(std::string(""));
payload = uf::Serializer{};
payload["uid"] = uid;
if ( result[""]["type"] == "enemy" ) {
payload["action"] = "enemy-attack";
} else if ( result["skipped"].asBool() ) {
payload["action"] = "forced-pass";
} else {
stats.currentMember = result[""];
renderCommandOptions(result["actions"]);
return "true";
}
result = battleManager->callHook("world:Battle.Action.%UID%", payload)[0];
postParseResult(result);
stats.previousMember = uf::Serializer{};
timer.reset();
stats.state = "waiting";
this->queueHook("world:Battle.Turn.%UID%", "", timeout);
return "true";
});
this->queueHook("world:Battle.Turn.%UID%");
}
{
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( metadata["system"]["closing"].asBool() ) {
if ( alpha >= 1.0f ) {
ext::Asset assetLoader;
std::string canonical = assetLoader.load("./data/audio/ui/menu close.ogg");
uf::Audio& sfx = assetLoader.get<uf::Audio>(canonical);
sfx.setVolume(masterdata["volumes"]["sfx"].asFloat());
sfx.play();
}
if ( alpha <= 0.0f ) {
alpha = 0.0f;
metadata["system"]["closing"] = false;
metadata["system"]["closed"] = true;
} else alpha -= uf::physics::time::delta;
metadata["color"][3] = alpha;
} else if ( metadata["system"]["closed"].asBool() ) {
ext::Object& parent = this->getParent<ext::Object>();
parent.getComponent<uf::Serializer>()["system"]["closed"] = true;
this->destroy();
parent.removeChild(*this);
} else {
if ( !metadata["initialized"].asBool() ) alpha = 0.0f;
metadata["initialized"] = true;
if ( alpha >= 1.0f ) alpha = 1.0f;
else alpha += uf::physics::time::delta * 1.5f;
metadata["color"][3] = alpha;
}
}
if ( circleIn ) {
pod::Transform<>& transform = circleIn->getComponent<pod::Transform<>>();
static float time = 0.0f;
float speed = 0.0125f;
uf::Serializer& metadata = circleIn->getComponent<uf::Serializer>();
if ( metadata["hovered"].asBool() ) speed = -0.25f;
time += uf::physics::time::delta * speed;
transform.orientation = uf::quaternion::axisAngle( { 0.0f, 0.0f, 1.0f }, time );
static pod::Vector3f start = { transform.position.x, -2.0f, 0.0f };
static pod::Vector3f end = transform.position;
static float delta = 0.0f;
if ( !metadata["initialized"].asBool() ) delta = 0.0f;
metadata["initialized"] = true;
if ( delta >= 1 ) delta = 1;
else {
delta += uf::physics::time::delta * 1.5f;
transform.position = uf::vector::lerp( start, end, delta );
}
metadata["color"][3] = alpha * 0.1f;
}
if ( circleOut ) {
pod::Transform<>& transform = circleOut->getComponent<pod::Transform<>>();
uf::Serializer& metadata = circleOut->getComponent<uf::Serializer>();
static float time = 0.0f;
float speed = 0.0125f;
if ( metadata["hovered"].asBool() ) speed = 0.25f;
time += uf::physics::time::delta * speed;
transform.orientation = uf::quaternion::axisAngle( { 0.0f, 0.0f, 1.0f }, time );
static pod::Vector3f start = { transform.position.x, 2.0f, 0.0f };
static pod::Vector3f end = transform.position;
static float delta = 0.0f;
if ( !metadata["initialized"].asBool() ) delta = 0.0f;
metadata["initialized"] = true;
if ( delta >= 1 ) delta = 1;
else {
delta += uf::physics::time::delta * 1.5f;
transform.position = uf::vector::lerp( start, end, delta );
}
metadata["color"][3] = alpha * 0.1f;
}
if ( turnCounters ) {
static float time = 0.0f;
time += uf::physics::time::delta;
for ( uf::Entity* pointer : turnCounters->getChildren() ) {
uf::Serializer& pMetadata = pointer->getComponent<uf::Serializer>();
float coeff = 2.0f;
// if ( pMetadata["half counter"].asBool() ) coeff = 4.0f;
// pMetadata["color"][3] = sin(time * coeff) * 0.25f + 0.75f;
pMetadata["color"][3] = std::min( 1.0f, (float) sin(time * coeff) * 0.5f + 1.0f );
}
}
if ( optionsBackground ) {
pod::Transform<>& transform = optionsBackground->getComponent<pod::Transform<>>();
uf::Serializer& metadata = optionsBackground->getComponent<uf::Serializer>();
static pod::Vector3f start = { transform.position.x, 2.0f, 0.0f };
static pod::Vector3f end = transform.position;
static float delta = 0.0f;
if ( !metadata["initialized"].asBool() ) delta = 0.0f;
metadata["initialized"] = true;
if ( delta >= 1 ) delta = 1;
else {
delta += uf::physics::time::delta * 1.5f;
transform.position = uf::vector::lerp( start, end, delta );
}
metadata["color"][3] = alpha;
if ( !commandOptions && !battleOptions && !targetOptions ) {
metadata["color"][3] = 0.1f;
}
}
for ( auto* pointerButton : partyMemberButtons ) {
if ( !pointerButton ) continue;
if ( pointerButton->getUid() == 0 ) continue;
for ( auto* pointer : pointerButton->getChildren() ) {
if ( !pointer ) continue;
if ( pointer->getUid() == 0 ) continue;
if ( pointer->getName() == "Menu: Party Member Icon" ) {
pod::Transform<>& transform = pointer->getComponent<pod::Transform<>>();
uf::Serializer& metadata = pointer->getComponent<uf::Serializer>();
metadata["color"][3] = alpha;
if ( metadata["clicked"].asBool() && timer.elapsed().asDouble() >= timeout ) {
}
static float color = 0.0f;
// std::cout << pointer << ": " << metadata << ": " << stats.currentMember << std::endl;
if ( metadata[""]["uid"] == stats.currentMember["uid"] ) {
color += uf::physics::time::delta * 4.0f;
float factor = (1 - (1.0f + cos(color)) / 8.0f);
metadata["color"][0] = 1.0f * factor;
metadata["color"][1] = 1.0f * factor;
metadata["color"][2] = 0.6f * factor;
if ( partyMemberCommandCircle && partyMemberCommandCircle->getUid() != 0 ) {
uf::Serializer& metadata = partyMemberCommandCircle->getComponent<uf::Serializer>();
pod::Transform<>& pTransform = partyMemberCommandCircle->getComponent<pod::Transform<>>();
if ( pTransform.position.x == 0 && pTransform.position.y == 0 ) {
pTransform.position.x = transform.position.x;
pTransform.position.y = transform.position.y;
}
metadata["system"]["lerp"]["delta"] = 0;
metadata["system"]["lerp"]["start"][0] = pTransform.position.x;
metadata["system"]["lerp"]["start"][1] = pTransform.position.y;
metadata["system"]["lerp"]["start"][2] = pTransform.position.z;
metadata["system"]["lerp"]["end"][0] = transform.position.x;
metadata["system"]["lerp"]["end"][1] = transform.position.y;
metadata["system"]["lerp"]["end"][2] = transform.position.z;
}
} else {
metadata["color"][0] = 1.0f;
metadata["color"][2] = 1.0f;
metadata["color"][2] = 1.0f;
}
} else if ( pointer->getName() == "Menu: Party Member Text" ) {
pod::Transform<>& transform = pointer->getComponent<pod::Transform<>>();
uf::Serializer& metadata = pointer->getComponent<uf::Serializer>();
metadata["color"][3] = alpha;
if ( metadata["clicked"].asBool() && timer.elapsed().asDouble() >= timeout ) {
}
static float color = 0.0f;
// std::cout << pointer << ": " << metadata << ": " << stats.currentMember << std::endl;
if ( metadata[""]["uid"] == stats.currentMember["uid"] ) {
color += uf::physics::time::delta * 4.0f;
float factor = (1 - (1.0f + cos(color)) / 8.0f);
metadata["color"][0] = 1.0f * factor;
metadata["color"][1] = 1.0f * factor;
metadata["color"][2] = 0.6f * factor;
} else {
metadata["color"][0] = 1.0f;
metadata["color"][2] = 1.0f;
metadata["color"][2] = 1.0f;
}
}
}
}
/* particles */ for ( auto it = particles.begin(); it != particles.end(); ++it ) {
ext::Gui* particle = *it;
if ( !particle ) { particles.erase( it ); return; }
if ( particle->getUid() == 0 ) { particles.erase( it ); return; }
uf::Serializer& metadata = particle->getComponent<uf::Serializer>();
pod::Transform<>& transform = particle->getComponent<pod::Transform<>>();
// state 1
// std::cout << particle << ": " << metadata["system"]["percent"] << ": " << metadata["text settings"]["string"] << std::endl;
// std::cout << transform.position.x << ", " << transform.position.y << ", " << transform.position.z << std::endl;
try {
if ( !metadata["system"].isObject() ) {
this->removeChild(*particle);
particle->destroy();
delete particle;
*it = NULL;
continue;
}
if ( metadata["system"]["percent"] < 0.25f ) {
transform.position.y -= uf::physics::time::delta / 2.0f;
} else if ( metadata["system"]["percent"] < 0.5f ) {
transform.position.y += uf::physics::time::delta / 2.0f;
} else if ( metadata["system"]["percent"] < 1.0f ) {
} else {
this->removeChild(*particle);
particle->destroy();
delete particle;
*it = NULL;
continue;
}
metadata["system"]["percent"] = metadata["system"]["percent"].asFloat() + uf::physics::time::delta;
} catch ( ... ) {
if ( particle ) {
this->removeChild(*particle);
particle->destroy();
delete particle;
*it = NULL;
}
}
}
for ( auto* pointer : partyMemberButtons ) {
if ( !pointer ) continue;
if ( pointer->getUid() == 0 ) continue;
pod::Transform<>& transform = pointer->getComponent<pod::Transform<>>();
uf::Serializer& metadata = pointer->getComponent<uf::Serializer>();
metadata["color"][3] = alpha;
}
if ( partyMemberCommandCircle && partyMemberCommandCircle->getUid() != 0 ) {
pod::Transform<>& transform = partyMemberCommandCircle->getComponent<pod::Transform<>>();
uf::Serializer& metadata = partyMemberCommandCircle->getComponent<uf::Serializer>();
static float time = 0.0f;
float speed = 0.5f;
if ( metadata["hovered"].asBool() ) speed = 0.75f;
time += uf::physics::time::delta * speed;
transform.orientation = uf::quaternion::axisAngle( { 0.0f, 0.0f, 1.0f }, time );
metadata["color"][3] = alpha;
{
pod::Vector3f start = {
metadata["system"]["lerp"]["start"][0].asFloat(),
metadata["system"]["lerp"]["start"][1].asFloat(),
metadata["system"]["lerp"]["start"][2].asFloat(),
};
pod::Vector3f end = {
metadata["system"]["lerp"]["end"][0].asFloat(),
metadata["system"]["lerp"]["end"][1].asFloat(),
metadata["system"]["lerp"]["end"][2].asFloat(),
};
float delta = metadata["system"]["lerp"]["delta"].asFloat();
if ( delta >= 1 ) delta = 1;
else {
delta += uf::physics::time::delta * 8.0f;
transform.position = uf::vector::lerp( start, end, delta );
}
metadata["system"]["lerp"]["delta"] = delta;
}
}
ext::Gui::tick();
if ( stats.state != "open" ) {
if ( timer.elapsed().asDouble() >= timeout ) stats.state = "open";
return;
}
struct {
bool up = uf::Window::isKeyPressed("W");
bool down = uf::Window::isKeyPressed("S");
bool back = uf::Window::isKeyPressed("Escape");
bool select = uf::Window::isKeyPressed("Enter");
} keys;
if ( targetOptions ) {
bool delta = false;
bool invalid = false;
pod::Transform<>& transform = targetOptions->getComponent<pod::Transform<>>();
uf::Serializer& metadata = targetOptions->getComponent<uf::Serializer>();
metadata["color"][3] = alpha;
for ( uf::Entity* pointer : targetOptions->getChildren() ) {
uf::Serializer& cMetadata = pointer->getComponent<uf::Serializer>();
cMetadata["text settings"]["color"][3] = alpha;
}
static bool released = true;
if ( keys.up ) {
if ( released ) {
delta = true;
released = false;
do {
--stats.targets.selection;
if ( stats.targets.selection < 0 ) { stats.targets.selection = stats.targets.current.size() - 1; }
} while ( std::find( stats.targets.invalids.begin(), stats.targets.invalids.end(), stats.targets.current[stats.targets.selection]["id"].asString() ) != stats.targets.invalids.end() );
}
}
else if ( keys.down ) {
if ( released ) {
delta = true;
released = false;
do {
++stats.targets.selection;
if ( stats.targets.selection >= stats.targets.current.size() ) { stats.targets.selection = 0; }
} while ( std::find( stats.targets.invalids.begin(), stats.targets.invalids.end(), stats.targets.current[stats.targets.selection]["id"].asString() ) != stats.targets.invalids.end() );
}
}
else released = true;
if ( stats.targets.selection < 0 ) { stats.targets.selection = stats.targets.current.size() - 1; }
else if ( stats.targets.selection >= stats.targets.current.size() ) { stats.targets.selection = 0; }
if ( queuedAction == "analyze" ) keys.select = false;
if ( !released ) {
if ( invalid ) {
playSound(*this, "invalid select");
} else if ( delta ) {
playSound(*this, "menu flip");
renderTargetOptions(stats.targets.current);
}
} else if ( keys.back && timer.elapsed().asDouble() >= timeout ) {
playSound(*this, "menu close");
renderTargetOptions(std::string(""));
if ( queuedAction == "analyze" ) {
renderSkillOptions(std::string(""));
renderCommandOptions(stats.actions.current);
} else renderSkillOptions(stats.currentMember);
timer.reset();
} else if ( keys.select && timer.elapsed().asDouble() >= timeout ) {
playSound(*this, "menu close");
uf::Serializer payload;
payload["action"] = "member-attack";
payload["uid"] = stats.currentMember["uid"];
payload["target"] = Json::arrayValue;
payload["target"].append(stats.targets.current[stats.targets.selection]["uid"]);
payload["skill"] = stats.currentMember["skills"][stats.skill.selection];
uf::Serializer result = battleManager->callHook("world:Battle.Action.%UID%", payload)[0];
postParseResult(result);
renderTargetOptions(std::string(""));
renderCommandOptions(std::string(""));
renderSkillOptions(std::string(""));
timer.reset();
stats.state = "waiting";
if ( result["invalid"].asBool() ) {
// stats.actions.invalids.push_back(action);
renderCommandOptions(stats.actions.current);
// this->queueHook("world:Battle.Turn.%UID%", "", timeout);
} else {
this->queueHook("world:Battle.Turn.%UID%", "", timeout);
}
}
} else if ( battleOptions ) {
bool delta = false;
bool invalid = false;
pod::Transform<>& transform = battleOptions->getComponent<pod::Transform<>>();
uf::Serializer& metadata = battleOptions->getComponent<uf::Serializer>();
metadata["color"][3] = alpha;
for ( uf::Entity* pointer : battleOptions->getChildren() ) {
uf::Serializer& cMetadata = pointer->getComponent<uf::Serializer>();
cMetadata["text settings"]["color"][3] = alpha;
}
static bool released = true;
if ( keys.up ) {
if ( released ) {
delta = true;
released = false;
do {
--stats.skill.selection;
if ( stats.skill.selection < 0 ) { stats.skill.selection = stats.currentMember["skills"].size()- 1; }
} while ( std::find( stats.skill.invalids.begin(), stats.skill.invalids.end(), stats.currentMember["skills"][stats.skill.selection].asString() ) != stats.skill.invalids.end() );
}
}
else if ( keys.down ) {
if ( released ) {
delta = true;
released = false;
do {
++stats.skill.selection;
if ( stats.skill.selection >= stats.currentMember["skills"].size()) { stats.skill.selection = 0; }
} while ( std::find( stats.skill.invalids.begin(), stats.skill.invalids.end(), stats.currentMember["skills"][stats.skill.selection].asString() ) != stats.skill.invalids.end() );
}
}
else released = true;
if ( !released ) {
if ( invalid ) {
playSound(*this, "menu close");
} else if ( delta ) {
playSound(*this, "menu flip");
renderSkillOptions(stats.currentMember);
}
} else if ( keys.back && timer.elapsed().asDouble() >= timeout ) {
playSound(*this, "menu close");
renderSkillOptions(std::string(""));
renderCommandOptions(stats.actions.current);
timer.reset();
} else if ( keys.select && timer.elapsed().asDouble() >= timeout ) {
playSound(*this, "menu close");
bool allRanged = false;
renderSkillOptions(std::string(""));
renderCommandOptions(std::string(""));
uf::Serializer payload;
payload["action"] = "member-targets";
payload["uid"] = stats.currentMember["uid"];
payload["skill"] = stats.currentMember["skills"][stats.skill.selection];
uf::Serializer result = battleManager->callHook("world:Battle.Action.%UID%", payload)[0];
std::string skillId = stats.currentMember["skills"][stats.skill.selection].asString();
uf::Serializer skillData = masterDataGet("Skill", skillId);
if ( result["range"].isNumeric() ) skillData["range"] = result["range"];
if ( skillData["range"].asInt64() > 1 ) {
uf::Serializer payload;
payload["action"] = "member-attack";
payload["uid"] = stats.currentMember["uid"];
payload["skill"] = stats.currentMember["skills"][stats.skill.selection];
uf::Serializer result = battleManager->callHook("world:Battle.Action.%UID%", payload)[0];
postParseResult(result);
timer.reset();
stats.state = "waiting";
if ( result["invalid"].asBool() ) {
// stats.actions.invalids.push_back(action);
renderCommandOptions(stats.actions.current);
// this->queueHook("world:Battle.Turn.%UID%", "", timeout);
} else {
this->queueHook("world:Battle.Turn.%UID%", "", timeout);
}
} else {
postParseResult(result);
renderTargetOptions(result["targets"]);
}
}
} else if ( commandOptions ) {
/*
bool delta = false;
bool invalid = false;
pod::Transform<>& transform = commandOptions->getComponent<pod::Transform<>>();
uf::Serializer& metadata = commandOptions->getComponent<uf::Serializer>();
metadata["color"][3] = alpha;
for ( uf::Entity* pointer : commandOptions->getChildren() ) {
uf::Serializer& cMetadata = pointer->getComponent<uf::Serializer>();
cMetadata["text settings"]["color"][3] = alpha;
}
static bool released = true;
if ( keys.up ) {
if ( released ) {
delta = true;
released = false;
do {
--stats.actions.selection;
if ( stats.actions.selection < 0 ) { stats.actions.selection = stats.actions.current.size() - 1; }
} while ( std::find( stats.actions.invalids.begin(), stats.actions.invalids.end(), stats.actions.current[stats.actions.selection].asString() ) != stats.actions.invalids.end() );
}
}
else if ( keys.down ) {
if ( released ) {
delta = true;
released = false;
do {
++stats.actions.selection;
if ( stats.actions.selection >= stats.actions.current.size() ) { stats.actions.selection = 0; }
} while ( std::find( stats.actions.invalids.begin(), stats.actions.invalids.end(), stats.actions.current[stats.actions.selection].asString() ) != stats.actions.invalids.end() );
}
}
else released = true;
if ( stats.actions.selection < 0 ) { stats.actions.selection = stats.actions.current.size() - 1; }
else if ( stats.actions.selection >= stats.actions.current.size() ) { stats.actions.selection = 0; }
if ( !released ) {
if ( invalid ) {
playSound(*this, "invalid select");
} else if ( delta ) {
playSound(*this, "menu flip");
renderCommandOptions(stats.actions.current);
}
} else if ( keys.back && timer.elapsed().asDouble() >= timeout ) {
playSound(*this, "invalid select");
timer.reset();
} else if ( keys.select && timer.elapsed().asDouble() >= timeout ) {
playSound(*this, "menu close");
uf::Serializer payload;
std::string action = stats.actions.current[stats.actions.selection].asString();
payload["action"] = action;
if ( payload["action"] == "member-attack" ) {
payload["uid"] = stats.currentMember["uid"];
payload["skill"] = stats.currentMember["skills"][stats.skill.selection];
}
uf::Serializer result = battleManager->callHook("world:Battle.Action.%UID%", payload)[0];
postParseResult(result);
timer.reset();
renderCommandOptions(std::string(""));
stats.state = "waiting";
if ( result["invalid"].asBool() ) {
stats.actions.invalids.push_back(action);
renderCommandOptions(stats.actions.current);
// this->queueHook("world:Battle.Turn.%UID%", "", timeout);
} else if ( payload["action"] == "member-attack" ) {
renderSkillOptions(std::string(""));
stats.state = "waiting";
this->queueHook("world:Battle.Turn.%UID%", "", timeout);
} else if ( payload["action"] == "member-skill" ) {
renderSkillOptions(stats.currentMember);
} else if ( payload["action"] == "pass" ) {
stats.previousMember = stats.currentMember;
this->queueHook("world:Battle.Turn.%UID%", "", timeout);
}
}
}
*/
bool delta = false;
bool invalid = false;
pod::Transform<>& transform = commandOptions->getComponent<pod::Transform<>>();
uf::Serializer& metadata = commandOptions->getComponent<uf::Serializer>();
metadata["color"][3] = alpha;
for ( uf::Entity* pointer : commandOptions->getChildren() ) {
uf::Serializer& cMetadata = pointer->getComponent<uf::Serializer>();
cMetadata["text settings"]["color"][3] = alpha;
}
static bool released = true;
if ( keys.up ) {
if ( released ) {
delta = true;
released = false;
do {
--stats.actions.selection;
if ( stats.actions.selection < 0 ) { stats.actions.selection = stats.actions.current.size() - 1; }
} while ( std::find( stats.actions.invalids.begin(), stats.actions.invalids.end(), getKeyFromIndex(stats.actions.current, stats.actions.selection) ) != stats.actions.invalids.end() );
}
}
else if ( keys.down ) {
if ( released ) {
delta = true;
released = false;
do {
++stats.actions.selection;
if ( stats.actions.selection >= stats.actions.current.size() ) { stats.actions.selection = 0; }
} while ( std::find( stats.actions.invalids.begin(), stats.actions.invalids.end(), getKeyFromIndex(stats.actions.current, stats.actions.selection) ) != stats.actions.invalids.end() );
}
}
else released = true;
if ( stats.actions.selection < 0 ) { stats.actions.selection = stats.actions.current.size() - 1; }
else if ( stats.actions.selection >= stats.actions.current.size() ) { stats.actions.selection = 0; }
if ( stats.actions.current.size() == 0 ) released = true;
if ( !released ) {
if ( invalid ) {
playSound(*this, "invalid select");
} else if ( delta ) {
playSound(*this, "menu flip");
renderCommandOptions(stats.actions.current);
}
} else if ( keys.back && timer.elapsed().asDouble() >= timeout ) {
playSound(*this, "invalid select");
timer.reset();
} else if ( keys.select && timer.elapsed().asDouble() >= timeout ) {
playSound(*this, "menu close");
uf::Serializer payload;
std::string action = getKeyFromIndex(stats.actions.current, stats.actions.selection);
action = uf::string::extension(action);
payload["action"] = action;
payload["uid"] = stats.currentMember["uid"];
if ( payload["action"] == "member-attack" ) {
// payload["skill"] = stats.currentMember["skills"][0];
payload["skill"] = 0;
}
if ( payload["action"] == "analyze" ) {
payload["action"] = "member-targets";
}
uf::Serializer result = battleManager->callHook("world:Battle.Action.%UID%", payload)[0];
// std::cout << payload << ": " << result << std::endl;
postParseResult(result);
timer.reset();
renderCommandOptions(std::string(""));
queuedAction = action;
stats.state = "waiting";
if ( result["invalid"].asBool() ) {
stats.actions.invalids.push_back(action);
renderCommandOptions(stats.actions.current);
} else if ( payload["action"] == "member-attack" ) {
renderSkillOptions(std::string(""));
stats.state = "waiting";
this->queueHook("world:Battle.Turn.%UID%", "", timeout);
} else if ( payload["action"] == "member-skill" ) {
renderSkillOptions(stats.currentMember);
} else if ( payload["action"] == "member-targets" ) {
renderTargetOptions(result["targets"]);
} else if ( payload["action"] == "pass" ) {
stats.previousMember = stats.currentMember;
this->queueHook("world:Battle.Turn.%UID%", "", timeout);
} else {
renderCommandOptions(stats.actions.current);
}
}
}
}
void ext::GuiBattle::render() {
ext::Gui::render();
}
void ext::GuiBattle::destroy() {
ext::Gui::destroy();
}