Merge pull request #74 from jeromkiller/AddArchipelagoClientLib
Merge in jerom's progress
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 3.7 KiB |
@@ -466,6 +466,10 @@ static const ALIGN_ASSET(2) char gShipLogoDL[] = dgShipLogoDL;
|
|||||||
#define dnintendo_rogo_static_Tex_LUS_000000 "__OTR__textures/nintendo_rogo_static/nintendo_rogo_static_Tex_LUS_000000"
|
#define dnintendo_rogo_static_Tex_LUS_000000 "__OTR__textures/nintendo_rogo_static/nintendo_rogo_static_Tex_LUS_000000"
|
||||||
static const ALIGN_ASSET(2) char nintendo_rogo_static_Tex_LUS_000000[] = dnintendo_rogo_static_Tex_LUS_000000;
|
static const ALIGN_ASSET(2) char nintendo_rogo_static_Tex_LUS_000000[] = dnintendo_rogo_static_Tex_LUS_000000;
|
||||||
|
|
||||||
|
// Archipelago Item Icons
|
||||||
|
#define dgArchipelagoItemTex "__OTR__textures/parameter_static/gArchipelagoOutline"
|
||||||
|
static const ALIGN_ASSET(2) char gArchipelagoItemTex[] = dgArchipelagoItemTex;
|
||||||
|
|
||||||
// Archipelago Item Models
|
// Archipelago Item Models
|
||||||
#define dgArchipelagoItemDL "__OTR__objects/object_archipelago_item/gArchipelagoItemDL"
|
#define dgArchipelagoItemDL "__OTR__objects/object_archipelago_item/gArchipelagoItemDL"
|
||||||
static const ALIGN_ASSET(2) char gArchipelagoItemDL[] = dgArchipelagoItemDL;
|
static const ALIGN_ASSET(2) char gArchipelagoItemDL[] = dgArchipelagoItemDL;
|
||||||
|
|||||||
@@ -1069,6 +1069,7 @@ void Interface_LoadItemIcon1(PlayState* play, u16 button);
|
|||||||
void Interface_LoadItemIcon2(PlayState* play, u16 button);
|
void Interface_LoadItemIcon2(PlayState* play, u16 button);
|
||||||
void func_80084BF4(PlayState* play, u16 flag);
|
void func_80084BF4(PlayState* play, u16 flag);
|
||||||
uint16_t Interface_DrawTextLine(GraphicsContext* gfx, char text[], int16_t x, int16_t y, uint16_t colorR, uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale, uint8_t textShadow);
|
uint16_t Interface_DrawTextLine(GraphicsContext* gfx, char text[], int16_t x, int16_t y, uint16_t colorR, uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale, uint8_t textShadow);
|
||||||
|
uint16_t Interface_DrawTextLine_overlay(GraphicsContext* gfx, char text[], int16_t x, int16_t y, uint16_t colorR, uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale, uint8_t textShadow);
|
||||||
u8 Item_Give(PlayState* play, u8 item);
|
u8 Item_Give(PlayState* play, u8 item);
|
||||||
u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry);
|
u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry);
|
||||||
u8 Item_CheckObtainability(u8 item);
|
u8 Item_CheckObtainability(u8 item);
|
||||||
|
|||||||
@@ -178,6 +178,8 @@ typedef struct ShipArchipelagoSaveContextData {
|
|||||||
u32 lastReceivedItemIndex;
|
u32 lastReceivedItemIndex;
|
||||||
char roomHash[100];
|
char roomHash[100];
|
||||||
char slotName[17];
|
char slotName[17];
|
||||||
|
char archiUri[50];
|
||||||
|
char roomPass[50];
|
||||||
ArchipelagoLocationData locations[RC_MAX];
|
ArchipelagoLocationData locations[RC_MAX];
|
||||||
} ShipArchipelagoSaveContextData;
|
} ShipArchipelagoSaveContextData;
|
||||||
|
|
||||||
|
|||||||
@@ -111,6 +111,24 @@ std::array<std::string, LANGUAGE_MAX> ArchipelagoSettingsMenuText[ASM_MAX]{
|
|||||||
"Todo",
|
"Todo",
|
||||||
"Todo",
|
"Todo",
|
||||||
},
|
},
|
||||||
|
//ASM_CHAR_START_TO_CONNECT
|
||||||
|
{
|
||||||
|
"Start to automatically connect to this slot",
|
||||||
|
"Todo",
|
||||||
|
"Todo",
|
||||||
|
},
|
||||||
|
//ASM_CHAR_SELECT_CONNECTED_TO_OTHER_SLOT
|
||||||
|
{
|
||||||
|
"Connected to a different slot",
|
||||||
|
"Todo",
|
||||||
|
"Todo",
|
||||||
|
},
|
||||||
|
// ASM_CHAR_SELECT_CHANGE_CONNECTION_INFO
|
||||||
|
{
|
||||||
|
"Z-Connection Settings",
|
||||||
|
"Z-Todo",
|
||||||
|
"Z-Todo",
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* SohFileSelect_GetRandomizerSettingText(uint8_t optionIndex, uint8_t language) {
|
const char* SohFileSelect_GetRandomizerSettingText(uint8_t optionIndex, uint8_t language) {
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ typedef enum {
|
|||||||
ASM_CONNECTING,
|
ASM_CONNECTING,
|
||||||
ASM_CONNECTED,
|
ASM_CONNECTED,
|
||||||
ASM_STATUS,
|
ASM_STATUS,
|
||||||
|
ASM_CHAR_START_TO_CONNECT,
|
||||||
|
ASM_CHAR_SELECT_CONNECTED_TO_OTHER_SLOT,
|
||||||
|
ASM_CHAR_SELECT_CHANGE_CONNECTION_INFO,
|
||||||
ASM_MAX
|
ASM_MAX
|
||||||
} ArchipelagoSettingsMenuEnums;
|
} ArchipelagoSettingsMenuEnums;
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
#include "soh/Notification/Notification.h"
|
#include "soh/Notification/Notification.h"
|
||||||
#include "soh/ShipInit.hpp"
|
#include "soh/ShipInit.hpp"
|
||||||
#include "soh/SaveManager.h"
|
#include "soh/SaveManager.h"
|
||||||
|
#include "soh/util.h"
|
||||||
|
#include "soh/SohGui/SohGui.hpp"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
@@ -31,6 +33,8 @@ ArchipelagoClient::ArchipelagoClient() {
|
|||||||
itemQueued = false;
|
itemQueued = false;
|
||||||
disconnecting = false;
|
disconnecting = false;
|
||||||
isDeathLinkedDeath = false;
|
isDeathLinkedDeath = false;
|
||||||
|
uri = "";
|
||||||
|
password = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
ArchipelagoClient& ArchipelagoClient::GetInstance() {
|
ArchipelagoClient& ArchipelagoClient::GetInstance() {
|
||||||
@@ -39,15 +43,18 @@ ArchipelagoClient& ArchipelagoClient::GetInstance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ArchipelagoClient::StartClient() {
|
bool ArchipelagoClient::StartClient() {
|
||||||
if (apClient != NULL) {
|
if (apClient != nullptr) {
|
||||||
apClient.reset();
|
apClient.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnecting = false;
|
disconnecting = false;
|
||||||
retries = 0;
|
retries = 0;
|
||||||
|
uri = CVarGetString(CVAR_REMOTE_ARCHIPELAGO("ServerAddress"), "localhost:38281");
|
||||||
|
password = CVarGetString(CVAR_REMOTE_ARCHIPELAGO("Password"), "");
|
||||||
|
|
||||||
apClient = std::unique_ptr<APClient>(
|
apClient = std::unique_ptr<APClient>(
|
||||||
new APClient(uuid, AP_Client_consts::AP_GAME_NAME,
|
new APClient(uuid, AP_Client_consts::AP_GAME_NAME,
|
||||||
CVarGetString(CVAR_REMOTE_ARCHIPELAGO("ServerAddress"), "localhost:38281"), "cacert.pem"));
|
uri, "cacert.pem"));
|
||||||
|
|
||||||
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 1); // Connecting
|
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 1); // Connecting
|
||||||
|
|
||||||
@@ -58,6 +65,10 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
"server address and slot name correct?");
|
"server address and slot name correct?");
|
||||||
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 2); // Connection error
|
CVarSetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 2); // Connection error
|
||||||
disconnecting = true;
|
disconnecting = true;
|
||||||
|
|
||||||
|
if(GameInteractor::IsSaveLoaded) {
|
||||||
|
SohGui::ShowArchipelagoSettingsMenu();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ArchipelagoConsole_SendMessage("[ERROR] Could not connect to server, retrying...");
|
ArchipelagoConsole_SendMessage("[ERROR] Could not connect to server, retrying...");
|
||||||
@@ -69,7 +80,7 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
tags.push_back("DeathLink");
|
tags.push_back("DeathLink");
|
||||||
}
|
}
|
||||||
apClient->ConnectSlot(CVarGetString(CVAR_REMOTE_ARCHIPELAGO("SlotName"), ""),
|
apClient->ConnectSlot(CVarGetString(CVAR_REMOTE_ARCHIPELAGO("SlotName"), ""),
|
||||||
CVarGetString(CVAR_REMOTE_ARCHIPELAGO("Password"), ""), 0b001, tags);
|
password, 0b001, tags);
|
||||||
});
|
});
|
||||||
|
|
||||||
apClient->set_slot_connected_handler([&](const nlohmann::json data) {
|
apClient->set_slot_connected_handler([&](const nlohmann::json data) {
|
||||||
@@ -88,6 +99,14 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save the connection details in case they changed
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.archiUri, uri,
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.archiUri));
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, GetSlotName(),
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.roomPass, password,
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomPass));
|
||||||
|
|
||||||
SynchSentLocations();
|
SynchSentLocations();
|
||||||
SynchReceivedLocations();
|
SynchReceivedLocations();
|
||||||
}
|
}
|
||||||
@@ -146,64 +165,64 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ColoredTextNode> coloredNodes;
|
std::vector<AP_Text::ColoredTextNode> coloredNodes;
|
||||||
|
|
||||||
for (const APClient::TextNode& node : arg.data) {
|
for (const APClient::TextNode& node : arg.data) {
|
||||||
APClient* client = apClient.get();
|
APClient* client = apClient.get();
|
||||||
std::string color;
|
AP_Text::TextColor color = AP_Text::TextColor::COLOR_DEFAULT;
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
if (node.type == "player_id") {
|
if (node.type == "player_id") {
|
||||||
int id = std::stoi(node.text);
|
int id = std::stoi(node.text);
|
||||||
if (color.empty() && id == client->get_player_number())
|
if (color == AP_Text::TextColor::COLOR_DEFAULT && id == client->get_player_number())
|
||||||
color = "magenta";
|
color = AP_Text::TextColor::COLOR_MAGENTA;
|
||||||
else if (color.empty())
|
else if (color == AP_Text::TextColor::COLOR_DEFAULT)
|
||||||
color = "yellow";
|
color = AP_Text::TextColor::COLOR_YELLOW;
|
||||||
text = client->get_player_alias(id);
|
text = client->get_player_alias(id);
|
||||||
} else if (node.type == "item_id") {
|
} else if (node.type == "item_id") {
|
||||||
int64_t id = std::stoll(node.text);
|
int64_t id = std::stoll(node.text);
|
||||||
if (color.empty()) {
|
if (color == AP_Text::TextColor::COLOR_DEFAULT) {
|
||||||
if (node.flags & APClient::ItemFlags::FLAG_ADVANCEMENT)
|
if (node.flags & APClient::ItemFlags::FLAG_ADVANCEMENT)
|
||||||
color = "plum";
|
color = AP_Text::TextColor::COLOR_PLUM;
|
||||||
else if (node.flags & APClient::ItemFlags::FLAG_NEVER_EXCLUDE)
|
else if (node.flags & APClient::ItemFlags::FLAG_NEVER_EXCLUDE)
|
||||||
color = "slateblue";
|
color = AP_Text::TextColor::COLOR_SLATEBLUE;
|
||||||
else if (node.flags & APClient::ItemFlags::FLAG_TRAP)
|
else if (node.flags & APClient::ItemFlags::FLAG_TRAP)
|
||||||
color = "salmon";
|
color = AP_Text::TextColor::COLOR_SALMON;
|
||||||
else
|
else
|
||||||
color = "cyan";
|
color = AP_Text::TextColor::COLOR_CYAN;
|
||||||
}
|
}
|
||||||
text = client->get_item_name(id, client->get_player_game(node.player));
|
text = client->get_item_name(id, client->get_player_game(node.player));
|
||||||
} else if (node.type == "location_id") {
|
} else if (node.type == "location_id") {
|
||||||
int64_t id = std::stoll(node.text);
|
int64_t id = std::stoll(node.text);
|
||||||
if (color.empty())
|
if (color == AP_Text::TextColor::COLOR_DEFAULT)
|
||||||
color = "blue";
|
color = AP_Text::TextColor::COLOR_BLUE;
|
||||||
text = client->get_location_name(id, client->get_player_game(node.player));
|
text = client->get_location_name(id, client->get_player_game(node.player));
|
||||||
} else if (node.type == "hint_status") {
|
} else if (node.type == "hint_status") {
|
||||||
text = node.text;
|
text = node.text;
|
||||||
if (node.hintStatus == APClient::HINT_FOUND)
|
if (node.hintStatus == APClient::HINT_FOUND)
|
||||||
color = "green";
|
color = AP_Text::TextColor::COLOR_GREEN;
|
||||||
else if (node.hintStatus == APClient::HINT_UNSPECIFIED)
|
else if (node.hintStatus == APClient::HINT_UNSPECIFIED)
|
||||||
color = "grey";
|
color = AP_Text::TextColor::COLOR_GRAY;
|
||||||
else if (node.hintStatus == APClient::HINT_NO_PRIORITY)
|
else if (node.hintStatus == APClient::HINT_NO_PRIORITY)
|
||||||
color = "slateblue";
|
color = AP_Text::TextColor::COLOR_SLATEBLUE;
|
||||||
else if (node.hintStatus == APClient::HINT_AVOID)
|
else if (node.hintStatus == APClient::HINT_AVOID)
|
||||||
color = "salmon";
|
color = AP_Text::TextColor::COLOR_SALMON;
|
||||||
else if (node.hintStatus == APClient::HINT_PRIORITY)
|
else if (node.hintStatus == APClient::HINT_PRIORITY)
|
||||||
color = "plum";
|
color = AP_Text::TextColor::COLOR_PLUM;
|
||||||
else
|
else
|
||||||
color = "red"; // unknown status -> red
|
color = AP_Text::TextColor::COLOR_RED; // unknown status -> red
|
||||||
} else if (node.type == "ERROR") {
|
} else if (node.type == "ERROR") {
|
||||||
color = "ERROR";
|
color = AP_Text::TextColor::COLOR_ERROR;
|
||||||
text = node.text;
|
text = node.text;
|
||||||
} else if (node.type == "LOG") {
|
} else if (node.type == "LOG") {
|
||||||
color = "LOG";
|
color = AP_Text::TextColor::COLOR_LOG;
|
||||||
text = node.text;
|
text = node.text;
|
||||||
} else {
|
} else {
|
||||||
color = "white";
|
color = AP_Text::TextColor::COLOR_WHITE;
|
||||||
text = node.text;
|
text = node.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColoredTextNode Colornode;
|
AP_Text::ColoredTextNode Colornode;
|
||||||
Colornode.color = color;
|
Colornode.color = color;
|
||||||
Colornode.text = text;
|
Colornode.text = text;
|
||||||
coloredNodes.push_back(Colornode);
|
coloredNodes.push_back(Colornode);
|
||||||
@@ -213,6 +232,7 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
apClient->set_bounced_handler([&](const nlohmann::json data) {
|
apClient->set_bounced_handler([&](const nlohmann::json data) {
|
||||||
|
if(data.contains("tags")) {
|
||||||
std::list<std::string> tags = data["tags"];
|
std::list<std::string> tags = data["tags"];
|
||||||
bool deathLink = (std::find(tags.begin(), tags.end(), "DeathLink") != tags.end());
|
bool deathLink = (std::find(tags.begin(), tags.end(), "DeathLink") != tags.end());
|
||||||
|
|
||||||
@@ -228,6 +248,7 @@ bool ArchipelagoClient::StartClient() {
|
|||||||
isDeathLinkedDeath = true;
|
isDeathLinkedDeath = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -240,6 +261,12 @@ bool ArchipelagoClient::StopClient() {
|
|||||||
|
|
||||||
void ArchipelagoClient::GameLoaded() {
|
void ArchipelagoClient::GameLoaded() {
|
||||||
if (apClient == nullptr) {
|
if (apClient == nullptr) {
|
||||||
|
if(IS_ARCHIPELAGO) {
|
||||||
|
CVarSetString(CVAR_REMOTE_ARCHIPELAGO("ServerAddress"), gSaveContext.ship.quest.data.archipelago.archiUri);
|
||||||
|
CVarSetString(CVAR_REMOTE_ARCHIPELAGO("SlotName"), gSaveContext.ship.quest.data.archipelago.slotName);
|
||||||
|
CVarSetString(CVAR_REMOTE_ARCHIPELAGO("Password"), gSaveContext.ship.quest.data.archipelago.roomPass);
|
||||||
|
StartClient();
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,8 +278,12 @@ void ArchipelagoClient::GameLoaded() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isRightSaveLoaded()) {
|
if (!isRightSaveLoaded()) {
|
||||||
ArchipelagoConsole_SendMessage("[ERROR] Loaded save is not associated with connected slot, disconnecting...");
|
ArchipelagoConsole_SendMessage("Connec");
|
||||||
disconnecting = true;
|
//disconnecting = true;
|
||||||
|
CVarSetString(CVAR_REMOTE_ARCHIPELAGO("ServerAddress"), gSaveContext.ship.quest.data.archipelago.archiUri);
|
||||||
|
CVarSetString(CVAR_REMOTE_ARCHIPELAGO("SlotName"), gSaveContext.ship.quest.data.archipelago.slotName);
|
||||||
|
CVarSetString(CVAR_REMOTE_ARCHIPELAGO("Password"), gSaveContext.ship.quest.data.archipelago.roomPass);
|
||||||
|
StartClient();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,6 +403,10 @@ void ArchipelagoClient::QueueItem(const ApItem item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ArchipelagoClient::SendGameWon() {
|
void ArchipelagoClient::SendGameWon() {
|
||||||
|
if(apClient == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!gameWon) {
|
if (!gameWon) {
|
||||||
apClient->StatusUpdate(APClient::ClientStatus::GOAL);
|
apClient->StatusUpdate(APClient::ClientStatus::GOAL);
|
||||||
gameWon = true;
|
gameWon = true;
|
||||||
@@ -418,6 +453,23 @@ void ArchipelagoClient::Poll() {
|
|||||||
apClient->poll();
|
apClient->poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ArchipelagoClient::slotMatch(const std::string& slotName, const std::string& roomHash) {
|
||||||
|
if (apClient == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(disconnecting) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string seed = apClient->get_seed();
|
||||||
|
const std::string slot = GetSlotName();
|
||||||
|
|
||||||
|
const bool seedMatch = apClient->get_seed().compare(roomHash) == 0;
|
||||||
|
const bool slotMatch = GetSlotName().compare(slotName) == 0;
|
||||||
|
return seedMatch && slotMatch;
|
||||||
|
}
|
||||||
|
|
||||||
bool ArchipelagoClient::isRightSaveLoaded() const {
|
bool ArchipelagoClient::isRightSaveLoaded() const {
|
||||||
const bool seedMatch = apClient->get_seed().compare(gSaveContext.ship.quest.data.archipelago.roomHash) == 0;
|
const bool seedMatch = apClient->get_seed().compare(gSaveContext.ship.quest.data.archipelago.roomHash) == 0;
|
||||||
const bool slotMatch = GetSlotName().compare(gSaveContext.ship.quest.data.archipelago.slotName) == 0;
|
const bool slotMatch = GetSlotName().compare(gSaveContext.ship.quest.data.archipelago.slotName) == 0;
|
||||||
@@ -425,7 +477,7 @@ bool ArchipelagoClient::isRightSaveLoaded() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const std::string ArchipelagoClient::GetSlotName() const {
|
const std::string ArchipelagoClient::GetSlotName() const {
|
||||||
if (apClient == NULL) {
|
if (apClient == nullptr) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,7 +534,7 @@ void ArchipelagoClient::OnItemGiven(uint32_t rc, GetItemEntry gi, uint8_t isGiSk
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ArchipelagoClient::SendDeathLink() {
|
void ArchipelagoClient::SendDeathLink() {
|
||||||
if (apClient && CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("DeathLink"), 0) && !isDeathLinkedDeath) {
|
if (apClient != nullptr && CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("DeathLink"), 0) && !isDeathLinkedDeath) {
|
||||||
nlohmann::json data{ { "time", apClient->get_server_time() },
|
nlohmann::json data{ { "time", apClient->get_server_time() },
|
||||||
{ "cause", "Shipwrecked by King Harkinian." },
|
{ "cause", "Shipwrecked by King Harkinian." },
|
||||||
{ "source", apClient->get_slot() } };
|
{ "source", apClient->get_slot() } };
|
||||||
@@ -518,6 +570,10 @@ extern "C" void Archipelago_InitSaveFile() {
|
|||||||
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
|
||||||
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, client.apClient->get_slot(),
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, client.apClient->get_slot(),
|
||||||
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.archiUri, client.uri,
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.archiUri));
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.roomPass, client.password,
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomPass));
|
||||||
|
|
||||||
for (uint32_t i = 0; i < scoutedItems.size(); i++) {
|
for (uint32_t i = 0; i < scoutedItems.size(); i++) {
|
||||||
RandomizerCheck rc = Rando::StaticData::locationNameToEnum[scoutedItems[i].locationName];
|
RandomizerCheck rc = Rando::StaticData::locationNameToEnum[scoutedItems[i].locationName];
|
||||||
@@ -540,6 +596,10 @@ void LoadArchipelagoData() {
|
|||||||
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
|
||||||
SaveManager::Instance->LoadCharArray("slotName", gSaveContext.ship.quest.data.archipelago.slotName,
|
SaveManager::Instance->LoadCharArray("slotName", gSaveContext.ship.quest.data.archipelago.slotName,
|
||||||
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
|
||||||
|
SaveManager::Instance->LoadCharArray("archiUri", gSaveContext.ship.quest.data.archipelago.archiUri,
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.archiUri));
|
||||||
|
SaveManager::Instance->LoadCharArray("roomPass", gSaveContext.ship.quest.data.archipelago.roomPass,
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomPass));
|
||||||
|
|
||||||
SaveManager::Instance->LoadArray(
|
SaveManager::Instance->LoadArray(
|
||||||
"locations", ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.locations), [](size_t i) {
|
"locations", ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.locations), [](size_t i) {
|
||||||
@@ -561,6 +621,8 @@ void SaveArchipelagoData(SaveContext* saveContext, int sectionID, bool fullSave)
|
|||||||
|
|
||||||
SaveManager::Instance->SaveData("roomHash", saveContext->ship.quest.data.archipelago.roomHash);
|
SaveManager::Instance->SaveData("roomHash", saveContext->ship.quest.data.archipelago.roomHash);
|
||||||
SaveManager::Instance->SaveData("slotName", saveContext->ship.quest.data.archipelago.slotName);
|
SaveManager::Instance->SaveData("slotName", saveContext->ship.quest.data.archipelago.slotName);
|
||||||
|
SaveManager::Instance->SaveData("archiUri", saveContext->ship.quest.data.archipelago.archiUri);
|
||||||
|
SaveManager::Instance->SaveData("roomPass", gSaveContext.ship.quest.data.archipelago.roomPass);
|
||||||
|
|
||||||
SaveManager::Instance->SaveArray(
|
SaveManager::Instance->SaveArray(
|
||||||
"locations", ARRAY_COUNT(saveContext->ship.quest.data.archipelago.locations), [&](size_t i) {
|
"locations", ARRAY_COUNT(saveContext->ship.quest.data.archipelago.locations), [&](size_t i) {
|
||||||
@@ -581,6 +643,10 @@ void InitArchipelagoData(bool isDebug) {
|
|||||||
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomHash));
|
||||||
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, "",
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.slotName, "",
|
||||||
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.slotName));
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.archiUri, "",
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.archiUri));
|
||||||
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.roomHash, "",
|
||||||
|
ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.roomPass));
|
||||||
|
|
||||||
for (uint32_t i = 0; i < ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.locations); i++) {
|
for (uint32_t i = 0; i < ARRAY_COUNT(gSaveContext.ship.quest.data.archipelago.locations); i++) {
|
||||||
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.locations[i].itemName, "",
|
SohUtils::CopyStringToCharArray(gSaveContext.ship.quest.data.archipelago.locations[i].itemName, "",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include "ArchipelagoTypes.h"
|
||||||
|
|
||||||
// Forward declaration
|
// Forward declaration
|
||||||
class APClient;
|
class APClient;
|
||||||
@@ -28,11 +29,6 @@ class ArchipelagoClient {
|
|||||||
uint64_t index;
|
uint64_t index;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ColoredTextNode {
|
|
||||||
std::string text;
|
|
||||||
std::string color;
|
|
||||||
};
|
|
||||||
|
|
||||||
static ArchipelagoClient& GetInstance();
|
static ArchipelagoClient& GetInstance();
|
||||||
|
|
||||||
bool StartClient();
|
bool StartClient();
|
||||||
@@ -65,11 +61,15 @@ class ArchipelagoClient {
|
|||||||
void SendMessageToConsole(const std::string message);
|
void SendMessageToConsole(const std::string message);
|
||||||
void Poll();
|
void Poll();
|
||||||
|
|
||||||
|
bool slotMatch(const std::string& slotName, const std::string& roomHash);
|
||||||
|
|
||||||
std::unique_ptr<APClient> apClient;
|
std::unique_ptr<APClient> apClient;
|
||||||
bool itemQueued;
|
bool itemQueued;
|
||||||
bool disconnecting;
|
bool disconnecting;
|
||||||
bool isDeathLinkedDeath;
|
bool isDeathLinkedDeath;
|
||||||
int retries;
|
int retries;
|
||||||
|
std::string uri;
|
||||||
|
std::string password;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ArchipelagoClient();
|
ArchipelagoClient();
|
||||||
|
|||||||
@@ -3,8 +3,9 @@
|
|||||||
#include "soh/SohGui/UIWidgets.hpp"
|
#include "soh/SohGui/UIWidgets.hpp"
|
||||||
#include "soh/SohGui/SohGui.hpp"
|
#include "soh/SohGui/SohGui.hpp"
|
||||||
#include "soh/OTRGlobals.h"
|
#include "soh/OTRGlobals.h"
|
||||||
|
#include "ArchipelagoTypes.h"
|
||||||
|
|
||||||
std::vector<std::vector<ArchipelagoClient::ColoredTextNode>> Items;
|
std::vector<std::vector<AP_Text::ColoredTextNode>> Items;
|
||||||
bool autoScroll = true;
|
bool autoScroll = true;
|
||||||
|
|
||||||
using namespace UIWidgets;
|
using namespace UIWidgets;
|
||||||
@@ -16,15 +17,15 @@ void ArchipelagoConsole_SendMessage(const char* fmt, ...) {
|
|||||||
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
|
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
|
||||||
buf[IM_ARRAYSIZE(buf) - 1] = 0;
|
buf[IM_ARRAYSIZE(buf) - 1] = 0;
|
||||||
va_end(args);
|
va_end(args);
|
||||||
ArchipelagoClient::ColoredTextNode node;
|
AP_Text::ColoredTextNode node;
|
||||||
node.text = std::string(buf);
|
node.text = std::string(buf);
|
||||||
node.color = "white";
|
node.color = AP_Text::TextColor::COLOR_WHITE;
|
||||||
if (strstr(buf, "[ERROR]")) {
|
if (strstr(buf, "[ERROR]")) {
|
||||||
node.color = "ERROR";
|
node.color = AP_Text::TextColor::COLOR_ERROR;
|
||||||
} else if (strstr(buf, "[LOG]")) {
|
} else if (strstr(buf, "[LOG]")) {
|
||||||
node.color = "LOG";
|
node.color = AP_Text::TextColor::COLOR_LOG;
|
||||||
}
|
}
|
||||||
std::vector<ArchipelagoClient::ColoredTextNode> line;
|
std::vector<AP_Text::ColoredTextNode> line;
|
||||||
line.push_back(node);
|
line.push_back(node);
|
||||||
Items.push_back(line);
|
Items.push_back(line);
|
||||||
if (Items.size() > 50) {
|
if (Items.size() > 50) {
|
||||||
@@ -32,7 +33,7 @@ void ArchipelagoConsole_SendMessage(const char* fmt, ...) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchipelagoConsole_PrintJson(const std::vector<ArchipelagoClient::ColoredTextNode> nodes) {
|
void ArchipelagoConsole_PrintJson(const std::vector<AP_Text::ColoredTextNode> nodes) {
|
||||||
Items.push_back(nodes);
|
Items.push_back(nodes);
|
||||||
if (Items.size() > 50) {
|
if (Items.size() > 50) {
|
||||||
Items.erase(Items.begin());
|
Items.erase(Items.begin());
|
||||||
@@ -50,8 +51,8 @@ void ArchipelagoConsoleWindow::DrawElement() {
|
|||||||
if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, 400), ImGuiChildFlags_AlwaysUseWindowPadding,
|
if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, 400), ImGuiChildFlags_AlwaysUseWindowPadding,
|
||||||
ImGuiWindowFlags_HorizontalScrollbar)) {
|
ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||||
|
|
||||||
for (const std::vector<ArchipelagoClient::ColoredTextNode>& line : Items) {
|
for (const std::vector<AP_Text::ColoredTextNode>& line : Items) {
|
||||||
for (const ArchipelagoClient::ColoredTextNode& node : line) {
|
for (const AP_Text::ColoredTextNode& node : line) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, getColorVal(node.color));
|
ImGui::PushStyleColor(ImGuiCol_Text, getColorVal(node.color));
|
||||||
ImGui::TextUnformatted(node.text.c_str());
|
ImGui::TextUnformatted(node.text.c_str());
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@@ -99,35 +100,41 @@ void ArchipelagoConsoleWindow::DrawElement() {
|
|||||||
ImGui::PopStyleVar(4);
|
ImGui::PopStyleVar(4);
|
||||||
};
|
};
|
||||||
|
|
||||||
ImVec4 getColorVal(const std::string& color) { // TODO change color strings to an enum
|
ImVec4 ArchipelagoConsoleWindow::getColorVal(const AP_Text::TextColor color) {
|
||||||
if (color == "ERROR") {
|
using apt = AP_Text::TextColor;
|
||||||
|
switch(color) {
|
||||||
|
case apt::COLOR_ERROR:
|
||||||
return ImVec4(1.0f, 0.4f, 0.4f, 1.0f);
|
return ImVec4(1.0f, 0.4f, 0.4f, 1.0f);
|
||||||
} else if (color == "LOG") {
|
case apt::COLOR_LOG:
|
||||||
return ImVec4(0.7f, 0.7f, 1.0f, 1.0f);
|
return ImVec4(0.7f, 0.7f, 1.0f, 1.0f);
|
||||||
} else if (color == "black") {
|
case apt::COLOR_BLACK:
|
||||||
return ImVec4(0.000f, 0.000f, 0.000f, 1.00f);
|
return ImVec4(0.000f, 0.000f, 0.000f, 1.00f);
|
||||||
} else if (color == "red") {
|
case apt::COLOR_RED:
|
||||||
return ImVec4(0.933f, 0.000f, 0.000f, 1.00f);
|
return ImVec4(0.933f, 0.000f, 0.000f, 1.00f);
|
||||||
} else if (color == "green") {
|
case apt::COLOR_GREEN:
|
||||||
return ImVec4(0.000f, 1.000f, 0.498f, 1.00f);
|
return ImVec4(0.000f, 1.000f, 0.498f, 1.00f);
|
||||||
} else if (color == "yellow") {
|
case apt::COLOR_YELLOW:
|
||||||
return ImVec4(0.980f, 0.980f, 0.824f, 1.00f);
|
return ImVec4(0.980f, 0.980f, 0.824f, 1.00f);
|
||||||
} else if (color == "blue") {
|
case apt::COLOR_BLUE:
|
||||||
return ImVec4(0.392f, 0.584f, 0.929f, 1.00f);
|
return ImVec4(0.392f, 0.584f, 0.929f, 1.00f);
|
||||||
} else if (color == "cyan") {
|
case apt::COLOR_CYAN:
|
||||||
return ImVec4(0.000f, 0.933f, 0.933f, 1.00f);
|
return ImVec4(0.000f, 0.933f, 0.933f, 1.00f);
|
||||||
} else if (color == "magenta") {
|
case apt::COLOR_MAGENTA:
|
||||||
return ImVec4(0.933f, 0.000f, 0.933f, 1.00f);
|
return ImVec4(0.933f, 0.000f, 0.933f, 1.00f);
|
||||||
} else if (color == "slateblue") {
|
case apt::COLOR_SLATEBLUE:
|
||||||
return ImVec4(0.427f, 0.545f, 0.910f, 1.00f);
|
return ImVec4(0.427f, 0.545f, 0.910f, 1.00f);
|
||||||
} else if (color == "plum") {
|
case apt::COLOR_PLUM:
|
||||||
return ImVec4(0.686f, 0.600f, 0.937f, 1.00f);
|
return ImVec4(0.686f, 0.600f, 0.937f, 1.00f);
|
||||||
} else if (color == "salmon") {
|
case apt::COLOR_SALMON:
|
||||||
return ImVec4(0.980f, 0.502f, 0.447f, 1.00f);
|
return ImVec4(0.980f, 0.502f, 0.447f, 1.00f);
|
||||||
} else if (color == "white") {
|
case apt::COLOR_ORANGE:
|
||||||
return ImVec4(0.93f, 0.93f, 0.93f, 1.00f);
|
|
||||||
} else if (color == "orange") {
|
|
||||||
return ImVec4(1.000, 0.467f, 0.000f, 1.000f);
|
return ImVec4(1.000, 0.467f, 0.000f, 1.000f);
|
||||||
}
|
case apt::COLOR_GRAY:
|
||||||
|
return ImVec4(0.53f, 0.53f, 0.53f, 1.00f);
|
||||||
|
case apt::COLOR_WHITE:
|
||||||
|
case apt::COLOR_DEFAULT:
|
||||||
|
default:
|
||||||
return ImVec4(0.93f, 0.93f, 0.93f, 1.00f);
|
return ImVec4(0.93f, 0.93f, 0.93f, 1.00f);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3,15 +3,18 @@
|
|||||||
#define ARCHIPELAGO_CONSOLE_WINDOW_H
|
#define ARCHIPELAGO_CONSOLE_WINDOW_H
|
||||||
|
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
#include "Archipelago.h"
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include "window/gui/GuiWindow.h"
|
||||||
|
#include "ArchipelagoTypes.h"
|
||||||
|
|
||||||
class ArchipelagoConsoleWindow final : public Ship::GuiWindow {
|
class ArchipelagoConsoleWindow final : public Ship::GuiWindow {
|
||||||
public:
|
public:
|
||||||
using GuiWindow::GuiWindow;
|
using GuiWindow::GuiWindow;
|
||||||
~ArchipelagoConsoleWindow(){};
|
~ArchipelagoConsoleWindow(){};
|
||||||
|
|
||||||
|
static ImVec4 getColorVal(const AP_Text::TextColor color);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InitElement() override{};
|
void InitElement() override{};
|
||||||
void DrawElement() override;
|
void DrawElement() override;
|
||||||
@@ -19,7 +22,6 @@ class ArchipelagoConsoleWindow final : public Ship::GuiWindow {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void ArchipelagoConsole_SendMessage(const char* fmt, ...);
|
void ArchipelagoConsole_SendMessage(const char* fmt, ...);
|
||||||
void ArchipelagoConsole_PrintJson(const std::vector<ArchipelagoClient::ColoredTextNode> nodes);
|
void ArchipelagoConsole_PrintJson(const std::vector<AP_Text::ColoredTextNode> nodes);
|
||||||
ImVec4 getColorVal(const std::string& color);
|
|
||||||
|
|
||||||
#endif // ARCHIPELAGO_CONSOLE_WINDOW_H
|
#endif // ARCHIPELAGO_CONSOLE_WINDOW_H
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#define ARCHIPELAGO_SETTINGS_WINDOW_H
|
#define ARCHIPELAGO_SETTINGS_WINDOW_H
|
||||||
|
|
||||||
#include <libultraship/libultraship.h>
|
#include <libultraship/libultraship.h>
|
||||||
|
#include "window/gui/GuiWindow.h"
|
||||||
|
|
||||||
class ArchipelagoSettingsWindow final : public Ship::GuiWindow {
|
class ArchipelagoSettingsWindow final : public Ship::GuiWindow {
|
||||||
public:
|
public:
|
||||||
|
|||||||
30
soh/soh/Network/Archipelago/ArchipelagoTypes.h
Normal file
30
soh/soh/Network/Archipelago/ArchipelagoTypes.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifdef __cplusplus
|
||||||
|
|
||||||
|
namespace AP_Text {
|
||||||
|
enum class TextColor : char {
|
||||||
|
COLOR_DEFAULT = 0,
|
||||||
|
COLOR_ERROR,
|
||||||
|
COLOR_LOG,
|
||||||
|
COLOR_BLACK,
|
||||||
|
COLOR_RED,
|
||||||
|
COLOR_GREEN,
|
||||||
|
COLOR_YELLOW,
|
||||||
|
COLOR_BLUE,
|
||||||
|
COLOR_CYAN,
|
||||||
|
COLOR_MAGENTA,
|
||||||
|
COLOR_SLATEBLUE,
|
||||||
|
COLOR_PLUM,
|
||||||
|
COLOR_SALMON,
|
||||||
|
COLOR_WHITE,
|
||||||
|
COLOR_ORANGE,
|
||||||
|
COLOR_GRAY
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ColoredTextNode {
|
||||||
|
std::string text;
|
||||||
|
AP_Text::TextColor color;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -2728,6 +2728,12 @@ extern "C" void ParseArchipelago() {
|
|||||||
OTRGlobals::Instance->gRandoContext->ParseArchipelago();
|
OTRGlobals::Instance->gRandoContext->ParseArchipelago();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" bool checkArchipelagoSlotInfo(const char* slotName, const char* roomHash) {
|
||||||
|
const std::string slot = std::string(slotName);
|
||||||
|
const std::string room = std::string(roomHash);
|
||||||
|
return ArchipelagoClient::GetInstance().slotMatch(slot, room);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void CheckTracker_RecalculateAvailableChecks() {
|
extern "C" void CheckTracker_RecalculateAvailableChecks() {
|
||||||
CheckTracker::RecalculateAvailableChecks();
|
CheckTracker::RecalculateAvailableChecks();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ void CheckTracker_RecalculateAvailableChecks();
|
|||||||
GetItemID RetrieveGetItemIDFromItemID(ItemID itemID);
|
GetItemID RetrieveGetItemIDFromItemID(ItemID itemID);
|
||||||
RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID);
|
RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID);
|
||||||
void ParseArchipelago();
|
void ParseArchipelago();
|
||||||
|
bool checkArchipelagoSlotInfo(const char* slotName, const char* roomHash);
|
||||||
void Messagebox_ShowErrorBox(char* title, char* body);
|
void Messagebox_ShowErrorBox(char* title, char* body);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -154,6 +154,9 @@ SaveManager::SaveManager() {
|
|||||||
info.buildVersionMinor = 0;
|
info.buildVersionMinor = 0;
|
||||||
info.buildVersionPatch = 0;
|
info.buildVersionPatch = 0;
|
||||||
memset(&info.buildVersion, 0, sizeof(info.buildVersion));
|
memset(&info.buildVersion, 0, sizeof(info.buildVersion));
|
||||||
|
|
||||||
|
memset(&info.archiUri, 0, sizeof(info.archiUri));
|
||||||
|
memset(&info.slotName, 0, sizeof(info.slotName));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,6 +512,13 @@ void SaveManager::InitMeta(int fileNum) {
|
|||||||
fileMetaInfo[fileNum].buildVersionPatch = gSaveContext.ship.stats.buildVersionPatch;
|
fileMetaInfo[fileNum].buildVersionPatch = gSaveContext.ship.stats.buildVersionPatch;
|
||||||
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].buildVersion, gSaveContext.ship.stats.buildVersion,
|
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].buildVersion, gSaveContext.ship.stats.buildVersion,
|
||||||
ARRAY_COUNT(fileMetaInfo[fileNum].buildVersion));
|
ARRAY_COUNT(fileMetaInfo[fileNum].buildVersion));
|
||||||
|
|
||||||
|
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].archiUri, gSaveContext.ship.quest.data.archipelago.archiUri,
|
||||||
|
ARRAY_COUNT(fileMetaInfo[fileNum].archiUri));
|
||||||
|
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].slotName, gSaveContext.ship.quest.data.archipelago.slotName,
|
||||||
|
ARRAY_COUNT(fileMetaInfo[fileNum].slotName));
|
||||||
|
SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].archiRoomSeed, gSaveContext.ship.quest.data.archipelago.roomHash,
|
||||||
|
ARRAY_COUNT(fileMetaInfo[fileNum].archiRoomSeed));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveManager::InitFile(bool isDebug) {
|
void SaveManager::InitFile(bool isDebug) {
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ typedef struct {
|
|||||||
s32 filenameLanguage;
|
s32 filenameLanguage;
|
||||||
s32 gregFound;
|
s32 gregFound;
|
||||||
s32 hasWallet;
|
s32 hasWallet;
|
||||||
|
|
||||||
|
char archiRoomSeed[100];
|
||||||
|
char slotName[17];
|
||||||
|
char archiUri[50];
|
||||||
} SaveFileMetaInfo;
|
} SaveFileMetaInfo;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h"
|
#include "soh/Enhancements/custom-message/CustomMessageInterfaceAddon.h"
|
||||||
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
|
#include "soh/Enhancements/cosmetics/cosmeticsTypes.h"
|
||||||
#include "soh/Enhancements/enhancementTypes.h"
|
#include "soh/Enhancements/enhancementTypes.h"
|
||||||
|
#include "soh/Enhancements/FileSelectEnhancements.h"
|
||||||
#include "soh/ShipUtils.h"
|
#include "soh/ShipUtils.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -3424,6 +3425,45 @@ void Interface_DrawLineupTick(PlayState* play) {
|
|||||||
CLOSE_DISPS(play->state.gfxCtx);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Interface_DrawArchipelagoStatusString(PlayState* play) {
|
||||||
|
s16 posX = OTRGetRectDimensionFromLeftEdge(28);
|
||||||
|
s16 posY = SCREEN_HEIGHT - 15;
|
||||||
|
|
||||||
|
int32_t scale = R_TEXT_CHAR_SCALE * 0.2f;
|
||||||
|
int32_t sTexSize = (scale / 100.0f) * 64.0f;
|
||||||
|
int32_t sTexScale = 1024.0f / (scale / 100.0f);
|
||||||
|
|
||||||
|
gDPLoadTextureBlock(play->state.gfxCtx->overlay.p++, gArchipelagoItemTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 64, 64, 0,
|
||||||
|
G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 0, 0, G_TX_NOLOD, G_TX_NOLOD);
|
||||||
|
|
||||||
|
gSPWideTextureRectangle(play->state.gfxCtx->overlay.p++, posX << 2, posY << 2, (posX + sTexSize) << 2,
|
||||||
|
(posY + sTexSize) << 2, G_TX_RENDERTILE, 0, 0, sTexScale, sTexScale);
|
||||||
|
|
||||||
|
//SPWideTextureRectangle(OVERLAY_DISP++, ((rMagicBarX + gSaveContext.magicCapacity) + 8) << 2, magicBarY << 2,
|
||||||
|
// ((rMagicBarX + gSaveContext.magicCapacity) + 16) << 2, (magicBarY + 16) << 2,
|
||||||
|
// G_TX_RENDERTILE, 256, 0, 1 << 10, 1 << 10);
|
||||||
|
posX += 13;
|
||||||
|
|
||||||
|
uint8_t language = (gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : gSaveContext.language;
|
||||||
|
char* statusText = SohFileSelect_GetArchipelagoSettingText(ASM_NOT_CONNECTED, language);
|
||||||
|
switch(CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 0)) {
|
||||||
|
case 0: // Not Connected
|
||||||
|
statusText = SohFileSelect_GetArchipelagoSettingText(ASM_NOT_CONNECTED, language);
|
||||||
|
break;
|
||||||
|
case 1: // Connecting
|
||||||
|
case 2: // Connection error, retrying
|
||||||
|
case 3: // Connected
|
||||||
|
statusText = SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTING, language);
|
||||||
|
break;
|
||||||
|
case 4: // Connected + Locations Scouted
|
||||||
|
statusText = SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTED, language);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Interface_DrawTextLine_overlay(play->state.gfxCtx, statusText, posX, posY, 255, 255, 255, 255, 0.8f, true);
|
||||||
|
}
|
||||||
|
|
||||||
void Interface_DrawMagicBar(PlayState* play) {
|
void Interface_DrawMagicBar(PlayState* play) {
|
||||||
InterfaceContext* interfaceCtx = &play->interfaceCtx;
|
InterfaceContext* interfaceCtx = &play->interfaceCtx;
|
||||||
s16 magicDrop = R_MAGIC_BAR_LARGE_Y - R_MAGIC_BAR_SMALL_Y + 2;
|
s16 magicDrop = R_MAGIC_BAR_LARGE_Y - R_MAGIC_BAR_SMALL_Y + 2;
|
||||||
@@ -5397,6 +5437,10 @@ void Interface_Draw(PlayState* play) {
|
|||||||
Interface_DrawLineupTick(play);
|
Interface_DrawLineupTick(play);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(IS_ARCHIPELAGO) {
|
||||||
|
Interface_DrawArchipelagoStatusString(play);
|
||||||
|
}
|
||||||
|
|
||||||
if (fullUi || gSaveContext.magicState > MAGIC_STATE_IDLE) {
|
if (fullUi || gSaveContext.magicState > MAGIC_STATE_IDLE) {
|
||||||
Interface_DrawMagicBar(play);
|
Interface_DrawMagicBar(play);
|
||||||
}
|
}
|
||||||
@@ -6936,6 +6980,41 @@ void Interface_DrawTextCharacter(GraphicsContext* gfx, int16_t x, int16_t y, voi
|
|||||||
CLOSE_DISPS(gfx);
|
CLOSE_DISPS(gfx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Interface_DrawTextCharacter_overlay(GraphicsContext* gfx, int16_t x, int16_t y, void* texture, uint16_t colorR,
|
||||||
|
uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale,
|
||||||
|
uint8_t textShadow) {
|
||||||
|
|
||||||
|
int32_t scale = R_TEXT_CHAR_SCALE * textScale;
|
||||||
|
int32_t sCharTexSize = (scale / 100.0f) * 16.0f;
|
||||||
|
int32_t sCharTexScale = 1024.0f / (scale / 100.0f);
|
||||||
|
|
||||||
|
OPEN_DISPS(gfx);
|
||||||
|
|
||||||
|
gDPPipeSync(OVERLAY_DISP++);
|
||||||
|
|
||||||
|
gDPLoadTextureBlock_4b(OVERLAY_DISP++, texture, G_IM_FMT_I, FONT_CHAR_TEX_WIDTH, FONT_CHAR_TEX_HEIGHT, 0,
|
||||||
|
G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
|
||||||
|
G_TX_NOLOD);
|
||||||
|
|
||||||
|
if (textShadow) {
|
||||||
|
// Draw drop shadow
|
||||||
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, 0, 0, 0, colorA);
|
||||||
|
gSPWideTextureRectangle(OVERLAY_DISP++, (x + R_TEXT_DROP_SHADOW_OFFSET) << 2, (y + R_TEXT_DROP_SHADOW_OFFSET) << 2,
|
||||||
|
(x + R_TEXT_DROP_SHADOW_OFFSET + sCharTexSize) << 2,
|
||||||
|
(y + R_TEXT_DROP_SHADOW_OFFSET + sCharTexSize) << 2, G_TX_RENDERTILE, 0, 0, sCharTexScale,
|
||||||
|
sCharTexScale);
|
||||||
|
}
|
||||||
|
|
||||||
|
gDPPipeSync(OVERLAY_DISP++);
|
||||||
|
|
||||||
|
// Draw normal text
|
||||||
|
gDPSetPrimColor(OVERLAY_DISP++, 0, 0, colorR, colorG, colorB, colorA);
|
||||||
|
gSPWideTextureRectangle(OVERLAY_DISP++, x << 2, y << 2, (x + sCharTexSize) << 2, (y + sCharTexSize) << 2,
|
||||||
|
G_TX_RENDERTILE, 0, 0, sCharTexScale, sCharTexScale);
|
||||||
|
|
||||||
|
CLOSE_DISPS(gfx);
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t Interface_DrawTextLine(GraphicsContext* gfx, char text[], int16_t x, int16_t y, uint16_t colorR,
|
uint16_t Interface_DrawTextLine(GraphicsContext* gfx, char text[], int16_t x, int16_t y, uint16_t colorR,
|
||||||
uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale,
|
uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale,
|
||||||
uint8_t textShadow) {
|
uint8_t textShadow) {
|
||||||
@@ -6966,3 +7045,34 @@ uint16_t Interface_DrawTextLine(GraphicsContext* gfx, char text[], int16_t x, in
|
|||||||
|
|
||||||
return kerningOffset;
|
return kerningOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t Interface_DrawTextLine_overlay(GraphicsContext* gfx, char text[], int16_t x, int16_t y, uint16_t colorR,
|
||||||
|
uint16_t colorG, uint16_t colorB, uint16_t colorA, float textScale,
|
||||||
|
uint8_t textShadow) {
|
||||||
|
|
||||||
|
uint16_t textureIndex;
|
||||||
|
uint16_t kerningOffset = 0;
|
||||||
|
uint16_t lineOffset = 0;
|
||||||
|
void* texture;
|
||||||
|
const char* processedText = Interface_ReplaceSpecialCharacters(text);
|
||||||
|
uint8_t textLength = strlen(processedText);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < textLength; i++) {
|
||||||
|
if (processedText[i] == '\n') {
|
||||||
|
lineOffset += 15 * textScale;
|
||||||
|
kerningOffset = 0;
|
||||||
|
} else {
|
||||||
|
textureIndex = processedText[i] - 32;
|
||||||
|
|
||||||
|
if (textureIndex != 0) {
|
||||||
|
texture = Ship_GetCharFontTexture(processedText[i]);
|
||||||
|
Interface_DrawTextCharacter_overlay(gfx, (int16_t)(x + kerningOffset), (int16_t)(y + lineOffset), texture, colorR, colorG, colorB,
|
||||||
|
colorA, textScale, textShadow);
|
||||||
|
}
|
||||||
|
kerningOffset +=
|
||||||
|
(uint16_t)(Ship_GetCharFontWidth(processedText[i]) * (R_TEXT_CHAR_SCALE / 100.0f) * textScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kerningOffset;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2478,7 +2478,8 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
|
|||||||
&deathCountSplit[2]);
|
&deathCountSplit[2]);
|
||||||
|
|
||||||
// draw death count
|
// draw death count
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) {
|
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT ||
|
||||||
|
Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave) {
|
||||||
for (i = 0, vtxOffset = 0; i < 3; i++, vtxOffset += 4) {
|
for (i = 0, vtxOffset = 0; i < 3; i++, vtxOffset += 4) {
|
||||||
FileChoose_DrawCharacter(this->state.gfxCtx, sp54->fontBuf + deathCountSplit[i] * FONT_CHAR_TEX_SIZE,
|
FileChoose_DrawCharacter(this->state.gfxCtx, sp54->fontBuf + deathCountSplit[i] * FONT_CHAR_TEX_SIZE,
|
||||||
vtxOffset);
|
vtxOffset);
|
||||||
@@ -2504,7 +2505,8 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
|
|||||||
|
|
||||||
i = Save_GetSaveMetaInfo(fileIndex)->healthCapacity / 0x10;
|
i = Save_GetSaveMetaInfo(fileIndex)->healthCapacity / 0x10;
|
||||||
|
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT) {
|
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) == 0 || this->menuMode != FS_MENU_MODE_SELECT ||
|
||||||
|
Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave) {
|
||||||
// draw hearts
|
// draw hearts
|
||||||
for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) {
|
for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) {
|
||||||
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x30, 4, 0);
|
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_8081284C[fileIndex] + vtxOffset] + 0x30, 4, 0);
|
||||||
@@ -2521,7 +2523,8 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
|
|||||||
textAlpha = 255;
|
textAlpha = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT) {
|
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 && this->menuMode == FS_MENU_MODE_SELECT &&
|
||||||
|
Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave == 0) {
|
||||||
DrawMoreInfo(this, fileIndex, textAlpha);
|
DrawMoreInfo(this, fileIndex, textAlpha);
|
||||||
} else {
|
} else {
|
||||||
// draw quest items
|
// draw quest items
|
||||||
@@ -2545,6 +2548,53 @@ void FileChoose_DrawFileInfo(GameState* thisx, s16 fileIndex, s16 isActive) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave) {
|
||||||
|
uint8_t language = (gSaveContext.language == LANGUAGE_JPN) ? LANGUAGE_ENG : gSaveContext.language;
|
||||||
|
|
||||||
|
// Connection status text
|
||||||
|
int statusPos = 61 + Interface_DrawTextLine(this->state.gfxCtx, SohFileSelect_GetArchipelagoSettingText(ASM_STATUS, language),
|
||||||
|
58, 133, 200, 200, 200, textAlpha, 0.8f, true);
|
||||||
|
|
||||||
|
const bool connectedToThisSlot = checkArchipelagoSlotInfo(Save_GetSaveMetaInfo(this->selectedFileIndex)->slotName,
|
||||||
|
Save_GetSaveMetaInfo(this->selectedFileIndex)->archiRoomSeed);
|
||||||
|
|
||||||
|
switch(CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 0)) {
|
||||||
|
case 0: // Not Connected
|
||||||
|
Interface_DrawTextLine(this->state.gfxCtx,
|
||||||
|
SohFileSelect_GetArchipelagoSettingText(ASM_NOT_CONNECTED, language),
|
||||||
|
statusPos, 133, 255, 120, 120, textAlpha, 0.8f, true);
|
||||||
|
break;
|
||||||
|
case 1: // Connecting
|
||||||
|
case 2: // Connection error, retrying
|
||||||
|
case 3: // Connected
|
||||||
|
Interface_DrawTextLine(this->state.gfxCtx,
|
||||||
|
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTING, language),
|
||||||
|
statusPos, 133, 185, 185, 185, textAlpha, 0.8f, true);
|
||||||
|
break;
|
||||||
|
case 4: // Connected + Locations Scouted
|
||||||
|
if(connectedToThisSlot) {
|
||||||
|
Interface_DrawTextLine(this->state.gfxCtx,
|
||||||
|
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTED, language),
|
||||||
|
statusPos, 133, 120, 255, 120, textAlpha, 0.8f, true);
|
||||||
|
} else {
|
||||||
|
Interface_DrawTextLine(this->state.gfxCtx,
|
||||||
|
SohFileSelect_GetArchipelagoSettingText(ASM_CHAR_SELECT_CONNECTED_TO_OTHER_SLOT, language),
|
||||||
|
statusPos, 133, 255, 255, 120, textAlpha, 0.8f, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!connectedToThisSlot) {
|
||||||
|
Interface_DrawTextLine(this->state.gfxCtx, SohFileSelect_GetArchipelagoSettingText(ASM_CHAR_START_TO_CONNECT, language),
|
||||||
|
58, 144, 200, 200, 200, textAlpha, 0.8f, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Interface_DrawTextLine(this->state.gfxCtx,
|
||||||
|
// SohFileSelect_GetArchipelagoSettingText(ASM_CHAR_SELECT_CHANGE_CONNECTION_INFO, language), 95, 220,
|
||||||
|
// 100, 250, 255, textAlpha, 1.0f, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CLOSE_DISPS(this->state.gfxCtx);
|
CLOSE_DISPS(this->state.gfxCtx);
|
||||||
@@ -2944,25 +2994,25 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
|
|||||||
155, 185, 185, 185, textAlpha, 0.8f, true);
|
155, 185, 185, 185, textAlpha, 0.8f, true);
|
||||||
|
|
||||||
// Connection status text
|
// Connection status text
|
||||||
Interface_DrawTextLine(this->state.gfxCtx, SohFileSelect_GetArchipelagoSettingText(ASM_STATUS, language), 70,
|
int statusPos = 75 + Interface_DrawTextLine(this->state.gfxCtx, SohFileSelect_GetArchipelagoSettingText(ASM_STATUS, language), 70,
|
||||||
175, 255, 255, 255, textAlpha, 0.8f, true);
|
175, 255, 255, 255, textAlpha, 0.8f, true);
|
||||||
|
|
||||||
switch (CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 0)) {
|
switch (CVarGetInteger(CVAR_REMOTE_ARCHIPELAGO("ConnectionStatus"), 0)) {
|
||||||
case 0: // Not Connected
|
case 0: // Not Connected
|
||||||
Interface_DrawTextLine(this->state.gfxCtx,
|
Interface_DrawTextLine(this->state.gfxCtx,
|
||||||
SohFileSelect_GetArchipelagoSettingText(ASM_NOT_CONNECTED, language), 110, 175,
|
SohFileSelect_GetArchipelagoSettingText(ASM_NOT_CONNECTED, language), statusPos, 175,
|
||||||
255, 120, 120, textAlpha, 0.8f, true);
|
255, 120, 120, textAlpha, 0.8f, true);
|
||||||
break;
|
break;
|
||||||
case 1: // Connecting
|
case 1: // Connecting
|
||||||
case 2: // Connection error, retrying
|
case 2: // Connection error, retrying
|
||||||
case 3: // Connected
|
case 3: // Connected
|
||||||
Interface_DrawTextLine(this->state.gfxCtx,
|
Interface_DrawTextLine(this->state.gfxCtx,
|
||||||
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTING, language), 110, 175, 185,
|
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTING, language), statusPos, 175, 185,
|
||||||
185, 185, textAlpha, 0.8f, true);
|
185, 185, textAlpha, 0.8f, true);
|
||||||
break;
|
break;
|
||||||
case 4: // Connected + Locations Scouted
|
case 4: // Connected + Locations Scouted
|
||||||
Interface_DrawTextLine(this->state.gfxCtx,
|
Interface_DrawTextLine(this->state.gfxCtx,
|
||||||
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTED, language), 110, 175, 120,
|
SohFileSelect_GetArchipelagoSettingText(ASM_CONNECTED, language), statusPos, 175, 120,
|
||||||
255, 120, textAlpha, 0.8f, true);
|
255, 120, textAlpha, 0.8f, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -3005,7 +3055,7 @@ void FileChoose_DrawWindowContents(GameState* thisx) {
|
|||||||
|
|
||||||
// Draw the small file name box instead when more meta info is enabled
|
// Draw the small file name box instead when more meta info is enabled
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 &&
|
if (CVarGetInteger(CVAR_ENHANCEMENT("FileSelectMoreInfo"), 0) != 0 &&
|
||||||
this->menuMode == FS_MENU_MODE_SELECT) {
|
this->menuMode == FS_MENU_MODE_SELECT && Save_GetSaveMetaInfo(this->selectedFileIndex)->archiSave == 0) {
|
||||||
// Location of file 1 small name box vertices
|
// Location of file 1 small name box vertices
|
||||||
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[68], 4, 0);
|
gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[68], 4, 0);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user