Added the ability to connect to the server and download the item locations
This commit is contained in:
@@ -1,6 +1,15 @@
|
||||

|
||||

|
||||
|
||||
## Fork Overview
|
||||
|
||||
Currently playing around trying to see if we're able to hook the existing Archipelago Ocarina of time randomizer into Ship of Harkinian.
|
||||
You can currently connect to the multiworld server, scout the items.
|
||||
If you have no randomizer genereted (the `Randomizer` folder is empty) and press the `Link up` button, you'll be able to start a randomizer save file
|
||||
with the items populated with the location from the server.
|
||||
|
||||
Sending and recieving is not implemented yet, Multiworld items are currently just recovery hearts
|
||||
|
||||
## Website
|
||||
|
||||
Official Website: https://www.shipofharkinian.com/
|
||||
|
||||
@@ -96,6 +96,10 @@ if (NOT TARGET ZAPDLib)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../ZAPDTR/ZAPD ${CMAKE_BINARY_DIR}/ZAPD)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET APCpp)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../APCpp ${CMAKE_BINARY_DIR}/APCpp)
|
||||
endif()
|
||||
|
||||
set(PROJECT_NAME soh)
|
||||
|
||||
################################################################################
|
||||
@@ -350,6 +354,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets
|
||||
${SDL2-NET-INCLUDE}
|
||||
${BOOST-INCLUDE}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/assets/
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../APCpp
|
||||
.
|
||||
)
|
||||
|
||||
@@ -631,6 +636,9 @@ endif()
|
||||
add_dependencies(${PROJECT_NAME}
|
||||
libultraship
|
||||
)
|
||||
add_dependencies(${PROJECT_NAME}
|
||||
APCpp
|
||||
)
|
||||
if(NOT CMAKE_SYSTEM_NAME MATCHES "NintendoSwitch|CafeOS")
|
||||
add_dependencies(${PROJECT_NAME}
|
||||
ZAPDLib
|
||||
@@ -643,6 +651,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||
"libultraship;"
|
||||
"ZAPDLib;"
|
||||
"APCpp;"
|
||||
"glu32;"
|
||||
"SDL2::SDL2;"
|
||||
"SDL2::SDL2main;"
|
||||
@@ -657,6 +666,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||
"libultraship;"
|
||||
"ZAPDLib;"
|
||||
"APCpp;"
|
||||
"glu32;"
|
||||
"SDL2::SDL2;"
|
||||
"SDL2::SDL2main;"
|
||||
@@ -695,6 +705,7 @@ else()
|
||||
set(ADDITIONAL_LIBRARY_DEPENDENCIES
|
||||
"libultraship;"
|
||||
"ZAPDLib;"
|
||||
"APCpp"
|
||||
SDL2::SDL2
|
||||
"$<$<BOOL:${BUILD_REMOTE_CONTROL}>:SDL2_net::SDL2_net>"
|
||||
${CMAKE_DL_LIBS}
|
||||
|
||||
268
soh/soh/Enhancements/randomizer/archipelago.cpp
Normal file
268
soh/soh/Enhancements/randomizer/archipelago.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
#include "archipelago.h"
|
||||
#include "soh/UIWidgets.hpp"
|
||||
#include "soh/util.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "fixed_string.hpp"
|
||||
|
||||
//extern "C" {
|
||||
// #include "include/z64item.h"
|
||||
// #include "objects/gameplay_keep/gameplay_keep.h"
|
||||
// extern SaveContext gSaveContext;
|
||||
// extern PlayState* gPlayState;
|
||||
//}
|
||||
|
||||
//constexpr const char* requestedSlotData(int i)
|
||||
|
||||
using namespace fixstr; //https://github.com/unterumarmung/fixed_string
|
||||
template<fixed_string key>
|
||||
struct CallbackWrapper {
|
||||
static void SlotCallbackFunc(int id) {
|
||||
ArchipelagoClient::getInstance().add_slot_data(key, id);
|
||||
SPDLOG_TRACE("Recieved Slot data ({}, {})", key, id);
|
||||
}
|
||||
};
|
||||
|
||||
template<fixed_string key>
|
||||
auto SubscribeToSlotData() {
|
||||
AP_RegisterSlotDataIntCallback(std::string(key), CallbackWrapper<key>::SlotCallbackFunc);
|
||||
}
|
||||
|
||||
ArchipelagoClient::ArchipelagoClient() {
|
||||
namespace apc = AP_Client_consts;
|
||||
CVarSetInteger("archipelago_connected", 0);
|
||||
strncpy(server_address, CVarGetString(apc::SETTING_ADDRESS, apc::DEFAULT_SERVER_NAME), apc::MAX_ADDRESS_LENGTH);
|
||||
strncpy(slot_name, CVarGetString(apc::SETTING_NAME, ""), apc::MAX_PLAYER_NAME_LENGHT);
|
||||
}
|
||||
|
||||
ArchipelagoClient& ArchipelagoClient::getInstance() {
|
||||
static ArchipelagoClient Client;
|
||||
return Client;
|
||||
}
|
||||
|
||||
|
||||
void ArchipelagoClient::add_slot_data(std::string_view key, int id) {
|
||||
slot_data.insert(std::pair<std::string_view, int>(key, id));
|
||||
}
|
||||
|
||||
void registerSlotCallbacks() {
|
||||
SubscribeToSlotData<"open_forest">();
|
||||
SubscribeToSlotData<"open_kakoriko">();
|
||||
SubscribeToSlotData<"open_door_of_time">();
|
||||
SubscribeToSlotData<"zora_fountain">();
|
||||
SubscribeToSlotData<"gerudo_fortress">();
|
||||
SubscribeToSlotData<"bridge">();
|
||||
SubscribeToSlotData<"bridge_stones">();
|
||||
SubscribeToSlotData<"bridge_medallions">();
|
||||
SubscribeToSlotData<"bridge_rewards">();
|
||||
SubscribeToSlotData<"bridge_tokens">();
|
||||
SubscribeToSlotData<"bridge_hearts">();
|
||||
SubscribeToSlotData<"shuffle_ganon_bosskey">();
|
||||
SubscribeToSlotData<"ganon_bosskey_medallions">();
|
||||
SubscribeToSlotData<"ganon_bosskey_stones">();
|
||||
SubscribeToSlotData<"ganon_bosskey_rewards">();
|
||||
SubscribeToSlotData<"ganon_bosskey_tokens">();
|
||||
SubscribeToSlotData<"ganon_bosskey_hearts">();
|
||||
SubscribeToSlotData<"trials">();
|
||||
SubscribeToSlotData<"triforce_hunt">();
|
||||
SubscribeToSlotData<"triforce_goal">();
|
||||
SubscribeToSlotData<"extra_triforce_percentage">();
|
||||
SubscribeToSlotData<"shopsanity">();
|
||||
SubscribeToSlotData<"shop_slots">();
|
||||
SubscribeToSlotData<"shopsanity_prices">();
|
||||
SubscribeToSlotData<"tokensanity">();
|
||||
SubscribeToSlotData<"dungeon_shortcuts">();
|
||||
SubscribeToSlotData<"mq_dungeons_mode">();
|
||||
SubscribeToSlotData<"mq_dungeons_count">();
|
||||
SubscribeToSlotData<"shuffle_interior_entrances">();
|
||||
SubscribeToSlotData<"shuffle_grotto_entrances">();
|
||||
SubscribeToSlotData<"shuffle_dungeon_entrances">();
|
||||
SubscribeToSlotData<"shuffle_overworld_entrances">();
|
||||
SubscribeToSlotData<"shuffle_bosses">();
|
||||
SubscribeToSlotData<"key_rings">();
|
||||
SubscribeToSlotData<"enhance_map_compass">();
|
||||
SubscribeToSlotData<"shuffle_mapcompass">();
|
||||
SubscribeToSlotData<"shuffle_smallkeys">();
|
||||
SubscribeToSlotData<"shuffle_hideoutkeys">();
|
||||
SubscribeToSlotData<"shuffle_bosskeys">();
|
||||
SubscribeToSlotData<"logic_rules">();
|
||||
SubscribeToSlotData<"logic_no_night_tokens_without_suns_song">();
|
||||
SubscribeToSlotData<"warp_songs">();
|
||||
SubscribeToSlotData<"shuffle_song_items">();
|
||||
SubscribeToSlotData<"shuffle_medigoron_carpet_salesman">();
|
||||
SubscribeToSlotData<"shuffle_frog_song_rupees">();
|
||||
SubscribeToSlotData<"shuffle_scrubs">();
|
||||
SubscribeToSlotData<"shuffle_child_trade">();
|
||||
SubscribeToSlotData<"shuffle_freestanding_items">();
|
||||
SubscribeToSlotData<"shuffle_pots">();
|
||||
SubscribeToSlotData<"shuffle_crates">();
|
||||
SubscribeToSlotData<"shuffle_cows">();
|
||||
SubscribeToSlotData<"shuffle_beehives">();
|
||||
SubscribeToSlotData<"shuffle_kokiri_sword">();
|
||||
SubscribeToSlotData<"shuffle_ocarinas">();
|
||||
SubscribeToSlotData<"shuffle_gerudo_card">();
|
||||
SubscribeToSlotData<"shuffle_beans">();
|
||||
SubscribeToSlotData<"starting_age">();
|
||||
SubscribeToSlotData<"bombchus_in_logic">();
|
||||
SubscribeToSlotData<"spawn_positions">();
|
||||
SubscribeToSlotData<"owl_drops">();
|
||||
SubscribeToSlotData<"no_epona_race">();
|
||||
SubscribeToSlotData<"skip_some_minigame_phases">();
|
||||
SubscribeToSlotData<"complete_mask_quest">();
|
||||
SubscribeToSlotData<"free_scarecrow">();
|
||||
SubscribeToSlotData<"plant_beans">();
|
||||
SubscribeToSlotData<"chicken_count">();
|
||||
SubscribeToSlotData<"big_poe_count">();
|
||||
SubscribeToSlotData<"fae_torch_count">();
|
||||
SubscribeToSlotData<"blue_fire_arrows">();
|
||||
SubscribeToSlotData<"damage_multiplier">();
|
||||
SubscribeToSlotData<"deadly_bonks">();
|
||||
SubscribeToSlotData<"starting_tod">();
|
||||
SubscribeToSlotData<"junk_ice_traps">();
|
||||
SubscribeToSlotData<"start_with_consumables">();
|
||||
SubscribeToSlotData<"adult_trade_start">();
|
||||
}
|
||||
|
||||
bool ArchipelagoClient::start_client() {
|
||||
switch(AP_GetConnectionStatus()) {
|
||||
case AP_ConnectionStatus::ConnectionRefused:
|
||||
SPDLOG_TRACE("refused");
|
||||
break;
|
||||
case AP_ConnectionStatus::Authenticated:
|
||||
SPDLOG_TRACE("Authenticated");
|
||||
break;
|
||||
case AP_ConnectionStatus::Connected:
|
||||
SPDLOG_TRACE("Connected");
|
||||
break;
|
||||
case AP_ConnectionStatus::Disconnected:
|
||||
SPDLOG_TRACE("Disconnected");
|
||||
break;
|
||||
}
|
||||
|
||||
if(AP_GetConnectionStatus() != AP_ConnectionStatus::Disconnected) {
|
||||
SPDLOG_TRACE("AP already connected, shutting it down");
|
||||
AP_Shutdown();
|
||||
}
|
||||
|
||||
AP_Init(server_address, "Ocarina of Time", slot_name, password);
|
||||
//AP_SetClientConnectedCallback(&ArchipelagoClient::on_connected); // currently broken :(
|
||||
//AP_SetClientCouldntConnectCallback(5, &ArchipelagoClient::on_couldntConnect);
|
||||
AP_SetItemClearCallback(&ArchipelagoClient::on_clear_items);
|
||||
AP_SetItemRecvCallback(&ArchipelagoClient::on_item_recieved);
|
||||
AP_SetLocationCheckedCallback(&ArchipelagoClient::on_location_checked);
|
||||
AP_SetLocationInfoCallback(&ArchipelagoClient::on_location_scouted);
|
||||
registerSlotCallbacks();
|
||||
AP_Start();
|
||||
AP_ConnectionStatus conn_status = AP_GetConnectionStatus();
|
||||
|
||||
//switch(conn_status) {
|
||||
// case AP_ConnectionStatus::Authenticated:
|
||||
// SPDLOG_TRACE("Authenticated");
|
||||
// break;
|
||||
// case AP_ConnectionStatus::Connected:
|
||||
// SPDLOG_TRACE("Connected");
|
||||
// break;
|
||||
// case AP_ConnectionStatus::Disconnected:
|
||||
// SPDLOG_TRACE("Disconnected");
|
||||
// break;
|
||||
//}
|
||||
save_data();
|
||||
return conn_status == AP_ConnectionStatus::Connected;
|
||||
}
|
||||
|
||||
void ArchipelagoClient::start_location_scouts() {
|
||||
AP_SendLocationScouts(AP_GetAllLocations(), false);
|
||||
}
|
||||
|
||||
void ArchipelagoClient::save_data() {
|
||||
CVarSetString(AP_Client_consts::SETTING_ADDRESS, server_address);
|
||||
CVarSetString(AP_Client_consts::SETTING_NAME, slot_name);
|
||||
}
|
||||
|
||||
void ArchipelagoClient::on_connected() {
|
||||
// todo implement me
|
||||
SPDLOG_TRACE("AP Connected!!");
|
||||
}
|
||||
void ArchipelagoClient::on_couldntConnect(AP_ConnectionStatus connection_status) {
|
||||
// todo implement me
|
||||
}
|
||||
|
||||
|
||||
void ArchipelagoClient::on_clear_items() {
|
||||
// todo implement me
|
||||
}
|
||||
|
||||
void ArchipelagoClient::on_item_recieved(int64_t recieved_item_id, bool notify_player) {
|
||||
// todo implement me
|
||||
}
|
||||
|
||||
void ArchipelagoClient::on_location_checked(int64_t location_id) {
|
||||
// todo implement me
|
||||
}
|
||||
|
||||
void ArchipelagoClient::on_location_scouted(std::vector<AP_NetworkItem> network_items) {
|
||||
for(const AP_NetworkItem& item: network_items) {
|
||||
SPDLOG_TRACE("Location scouted: {} for {} in location {}", item.itemName, item.playerName, item.locationName);
|
||||
}
|
||||
getInstance().scouted_items = network_items;
|
||||
}
|
||||
|
||||
char* ArchipelagoClient::get_server_address_buff() {
|
||||
return server_address;
|
||||
}
|
||||
char* ArchipelagoClient::get_slot_name_buff() {
|
||||
return slot_name;
|
||||
}
|
||||
char* ArchipelagoClient::get_password_buff() {
|
||||
return password;
|
||||
}
|
||||
|
||||
const std::map<std::string, int>& ArchipelagoClient::get_slot_data() {
|
||||
return slot_data;
|
||||
}
|
||||
|
||||
const std::vector<AP_NetworkItem>& ArchipelagoClient::get_scouted_items() {
|
||||
return scouted_items;
|
||||
}
|
||||
|
||||
|
||||
void ArchipelagoWindow::ArchipelagoDrawConnectPage() {
|
||||
ArchipelagoClient& AP_client = ArchipelagoClient::getInstance();
|
||||
ImGui::SeparatorText("Connection info");
|
||||
ImGui::InputText("Server Address", AP_client.get_server_address_buff(), AP_Client_consts::MAX_ADDRESS_LENGTH);
|
||||
ImGui::InputText("Slot Name", AP_client.get_slot_name_buff(), AP_Client_consts::MAX_PLAYER_NAME_LENGHT);
|
||||
ImGui::InputText("Password (leave blank for no password)", AP_client.get_password_buff(), AP_Client_consts::MAX_PASSWORD_LENGTH, ImGuiInputTextFlags_Password);
|
||||
|
||||
char connected_text[25] = "Disconnected";
|
||||
if(ImGui::Button("Connect")) {
|
||||
bool success = AP_client.start_client();
|
||||
if(success) {
|
||||
strncpy(connected_text, "Connected!", 25);
|
||||
SPDLOG_TRACE("Connected!!");
|
||||
}
|
||||
else {
|
||||
strncpy(connected_text, "Connection failed!", 25);
|
||||
SPDLOG_TRACE("Connection failed :(");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(connected_text);
|
||||
if(ImGui::Button("scout")) {
|
||||
AP_client.start_location_scouts();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("link up")) {
|
||||
CVarSetInteger("archipelago_connected", 1);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void ArchipelagoWindow::DrawElement() {
|
||||
ArchipelagoDrawConnectPage();
|
||||
UIWidgets::PaddedSeparator();
|
||||
};
|
||||
67
soh/soh/Enhancements/randomizer/archipelago.h
Normal file
67
soh/soh/Enhancements/randomizer/archipelago.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#include "archipelago_settings_window.h"
|
||||
#include "../../../../APCpp/Archipelago.h"
|
||||
|
||||
#include "fixed_string.hpp"
|
||||
|
||||
namespace AP_Client_consts {
|
||||
static constexpr int MAX_ADDRESS_LENGTH = 64;
|
||||
static constexpr int MAX_PLAYER_NAME_LENGHT = 17;
|
||||
static constexpr int MAX_PASSWORD_LENGTH = 32;
|
||||
static constexpr char const* DEFAULT_SERVER_NAME = "archipelago.gg:<port number>";
|
||||
|
||||
static constexpr char const* SETTING_ADDRESS = "AP_server_address";
|
||||
static constexpr char const* SETTING_NAME = "AP_slot_name";
|
||||
};
|
||||
|
||||
class ArchipelagoClient {
|
||||
public:
|
||||
static ArchipelagoClient& getInstance();
|
||||
|
||||
bool start_client();
|
||||
bool stop_client();
|
||||
|
||||
void start_location_scouts();
|
||||
|
||||
// getters
|
||||
char* get_server_address_buff();
|
||||
char* get_slot_name_buff();
|
||||
char* get_password_buff();
|
||||
const std::map<std::string, int>& get_slot_data();
|
||||
const std::vector<AP_NetworkItem>& get_scouted_items();
|
||||
|
||||
void add_slot_data(std::string_view key, int id);
|
||||
|
||||
protected:
|
||||
ArchipelagoClient();
|
||||
|
||||
private:
|
||||
ArchipelagoClient(ArchipelagoClient &) = delete;
|
||||
void operator=(const ArchipelagoClient &) = delete;
|
||||
static std::shared_ptr<ArchipelagoClient> instance;
|
||||
static bool initialized;
|
||||
|
||||
char server_address[AP_Client_consts::MAX_ADDRESS_LENGTH];
|
||||
char slot_name[AP_Client_consts::MAX_PLAYER_NAME_LENGHT];
|
||||
char password[AP_Client_consts::MAX_PLAYER_NAME_LENGHT];
|
||||
|
||||
std::map<std::string, int> slot_data;
|
||||
std::set<int64_t> locations;
|
||||
std::vector<AP_NetworkItem> scouted_items;
|
||||
|
||||
//void registerSlotCallbacks();
|
||||
|
||||
void save_data();
|
||||
|
||||
// callback functions
|
||||
static void on_connected();
|
||||
static void on_couldntConnect(AP_ConnectionStatus connection_status);
|
||||
static void on_clear_items();
|
||||
static void on_item_recieved(int64_t recieved_item_id, bool notify_player);
|
||||
static void on_location_checked(int64_t location_id);
|
||||
static void on_deathlink_recieved() { }; // TODO: implement me
|
||||
static void on_location_scouted(std::vector<AP_NetworkItem> network_items);
|
||||
|
||||
// callbacks
|
||||
|
||||
};
|
||||
|
||||
1781
soh/soh/Enhancements/randomizer/archipelago_mappings.h
Normal file
1781
soh/soh/Enhancements/randomizer/archipelago_mappings.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#ifndef ARCHIPELAGO_H
|
||||
#define ARCHIPELAGO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ARCHIPELAGO_H
|
||||
|
||||
#include <libultraship/libultraship.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
class ArchipelagoClient;
|
||||
|
||||
class ArchipelagoWindow : public Ship::GuiWindow {
|
||||
public:
|
||||
using GuiWindow::GuiWindow;
|
||||
|
||||
void InitElement() override {};
|
||||
void DrawElement() override;
|
||||
void UpdateElement() override{};
|
||||
|
||||
private:
|
||||
//std::shared_ptr<ArchipelagoClient AP_client = nullptr;
|
||||
|
||||
void ArchipelagoDrawConnectPage();
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "macros.h"
|
||||
#include "3drando/hints.hpp"
|
||||
#include "../kaleido.h"
|
||||
#include "archipelago.h"
|
||||
#include "Archipelago.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <spdlog/spdlog.h>
|
||||
@@ -335,6 +337,18 @@ void Context::ParseSpoiler(const char* spoilerFileName) {
|
||||
}
|
||||
}
|
||||
|
||||
void Context::ParseArchipelago() {
|
||||
mSeedGenerated = false;
|
||||
mSpoilerLoaded = false;
|
||||
|
||||
ArchipelagoClient& ap_client = ArchipelagoClient::getInstance();
|
||||
ParseArchipelagoItemsLocations(ap_client.get_scouted_items());
|
||||
|
||||
// lets see if counting AP_loaded as spoiler loaded does the trick
|
||||
mSpoilerLoaded = true;
|
||||
mSeedGenerated = false;
|
||||
}
|
||||
|
||||
void Context::ParseHashIconIndexesJson(nlohmann::json spoilerFileJson) {
|
||||
nlohmann::json hashJson = spoilerFileJson["file_hash"];
|
||||
int index = 0;
|
||||
@@ -367,6 +381,25 @@ void Context::ParseItemLocationsJson(nlohmann::json spoilerFileJson) {
|
||||
}
|
||||
}
|
||||
|
||||
void Context::ParseArchipelagoItemsLocations(std::vector<AP_NetworkItem> scouted_items) {
|
||||
int playerId = AP_GetPlayerID(); // todo change me when the client is developed further
|
||||
for(const AP_NetworkItem& ap_item: scouted_items) {
|
||||
const RandomizerCheck rc = StaticData::APcheckToSoh.find(ap_item.locationName)->second;
|
||||
if(playerId == ap_item.player) {
|
||||
// our item
|
||||
SPDLOG_TRACE("Populated item {} at location {}", ap_item.itemName, ap_item.locationName);
|
||||
const RandomizerGet item = StaticData::APitemToSoh.find(ap_item.itemName)->second;
|
||||
itemLocationTable[rc].SetPlacedItem(item);
|
||||
} else {
|
||||
// other player item
|
||||
itemLocationTable[rc].SetPlacedItem(RG_RECOVERY_HEART); // Ap item doesn't work yet
|
||||
//overrides[rc] = ItemOverride(rc, RG_ZELDAS_LETTER);
|
||||
//std::string getText = ap_item.playerName + "'s " + ap_item.itemName;
|
||||
//overrides[rc].SetTrickName(Text(getText, getText, getText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Context::WriteHintJson(nlohmann::ordered_json& spoilerFileJson){
|
||||
for (Hint hint: hintTable){
|
||||
hint.logHint(spoilerFileJson);
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <map>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
// forward declarations
|
||||
struct AP_NetworkItem;
|
||||
|
||||
/**
|
||||
* @brief Singleton for storing and accessing dynamic Randomizer-related data
|
||||
*
|
||||
@@ -120,6 +123,9 @@ class Context {
|
||||
bool allLocationsReachable = false;
|
||||
RandomizerArea GetAreaFromString(std::string str);
|
||||
|
||||
void ParseArchipelago();
|
||||
void ParseArchipelagoItemsLocations(const std::vector<AP_NetworkItem>);
|
||||
|
||||
/**
|
||||
* @brief Get the hash for the current seed.
|
||||
*
|
||||
|
||||
682
soh/soh/Enhancements/randomizer/fixed_string.hpp
Normal file
682
soh/soh/Enhancements/randomizer/fixed_string.hpp
Normal file
@@ -0,0 +1,682 @@
|
||||
/*
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright (c) 2020 - 2020 Daniil Dudkin.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef FIXED_STRING_HPP
|
||||
#define FIXED_STRING_HPP
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <ostream>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#define FIXSTR_VERSION_MAJOR 0
|
||||
#define FIXSTR_VERSION_MINOR 1
|
||||
#define FIXSTR_VERSION_PATCH 1
|
||||
|
||||
#define FIXSTR_CPP20_CHAR8T_PRESENT __cpp_char8_t
|
||||
#define FIXSTR_CPP20_SPACESHIP_OPERATOR_PRESENT __cpp_lib_three_way_comparison
|
||||
|
||||
#define FIXSTR_CPP20_CONSTEXPR_ALGORITHMS_PRESENT (__cpp_lib_constexpr_algorithms)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FIXSTR_CPP_VERSION _MSVC_LANG
|
||||
#else
|
||||
#define FIXSTR_CPP_VERSION __cplusplus
|
||||
#endif // _MSC_VER
|
||||
|
||||
// Note that when ICC or Clang is in use, FIXSTR_GCC_VERSION might not fully match the actual GCC version on the system.
|
||||
#define FIXSTR_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||
// According to clang documentation, version can be vendor specific
|
||||
#define FIXSTR_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
|
||||
|
||||
#if FIXSTR_GCC_VERSION >= 100'000 && FIXSTR_CPP_VERSION > 201703L
|
||||
#define FIXSTR_CPP20_CNTTP_PRESENT 1
|
||||
#elif __cpp_nontype_template_args >= 201911
|
||||
#define FIXSTR_CPP20_CNTTP_PRESENT 1
|
||||
#elif __cpp_nontype_template_parameter_class >= 201806
|
||||
#define FIXSTR_CPP20_CNTTP_PRESENT 1
|
||||
#else
|
||||
// Other compilers do not support cNTTP just yet
|
||||
#define FIXSTR_CPP20_CNTTP_PRESENT 0
|
||||
#endif // FIXSTR_CPP20_CNTTP_PRESENT
|
||||
|
||||
namespace fixstr
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
constexpr OutputIterator copy(InputIterator first, InputIterator last, OutputIterator d_first)
|
||||
{
|
||||
#if FIXSTR_CPP20_CONSTEXPR_ALGORITHMS_PRESENT
|
||||
return std::copy(first, last, d_first);
|
||||
#else
|
||||
while (first != last)
|
||||
{
|
||||
*d_first++ = *first++;
|
||||
}
|
||||
return d_first;
|
||||
#endif // FIXSTR_CPP20_CONSTEXPR_ALGORITHMS_PRESENT
|
||||
}
|
||||
|
||||
template <typename ForwardIterator, typename T>
|
||||
constexpr void fill(ForwardIterator first, ForwardIterator last, const T& value)
|
||||
{
|
||||
#if FIXSTR_CPP20_CONSTEXPR_ALGORITHMS_PRESENT
|
||||
std::fill(first, last, value);
|
||||
#else
|
||||
for (; first != last; ++first)
|
||||
{
|
||||
*first = value;
|
||||
}
|
||||
#endif // FIXSTR_CPP20_CONSTEXPR_ALGORITHMS_PRESENT
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
|
||||
template <typename TChar, std::size_t N, typename TTraits = std::char_traits<TChar>>
|
||||
struct basic_fixed_string // NOLINT(cppcoreguidelines-special-member-functions)
|
||||
{
|
||||
// exposition only
|
||||
using storage_type = std::array<TChar, N + 1>;
|
||||
storage_type _data{};
|
||||
|
||||
using traits_type = TTraits;
|
||||
using value_type = TChar;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using iterator = typename storage_type::iterator;
|
||||
using const_iterator = typename storage_type::const_iterator;
|
||||
using reverse_iterator = typename storage_type::reverse_iterator;
|
||||
using const_reverse_iterator = typename storage_type::const_reverse_iterator;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using string_view_type = std::basic_string_view<value_type, traits_type>;
|
||||
static constexpr auto npos = string_view_type::npos;
|
||||
|
||||
constexpr basic_fixed_string() noexcept = default;
|
||||
|
||||
constexpr basic_fixed_string(const value_type (&array)[N + 1]) noexcept // NOLINT(google-explicit-constructor)
|
||||
{
|
||||
details::copy(std::begin(array), std::end(array), _data.begin());
|
||||
}
|
||||
|
||||
constexpr basic_fixed_string& operator=(const value_type (&array)[N + 1]) noexcept
|
||||
{
|
||||
details::copy(std::begin(array), std::end(array), _data.begin());
|
||||
return *this;
|
||||
}
|
||||
|
||||
// iterators
|
||||
[[nodiscard]] constexpr iterator begin() noexcept { return _data.begin(); }
|
||||
[[nodiscard]] constexpr const_iterator begin() const noexcept { return _data.begin(); }
|
||||
[[nodiscard]] constexpr iterator end() noexcept { return _data.end() - 1; }
|
||||
[[nodiscard]] constexpr const_iterator end() const noexcept { return _data.end() - 1; }
|
||||
[[nodiscard]] constexpr const_iterator cbegin() const noexcept { return _data.cbegin(); }
|
||||
[[nodiscard]] constexpr const_iterator cend() const noexcept { return _data.cend() - 1; }
|
||||
[[nodiscard]] constexpr reverse_iterator rbegin() noexcept { return _data.rbegin() + 1; }
|
||||
[[nodiscard]] constexpr const_reverse_iterator rbegin() const noexcept { return _data.rbegin() + 1; }
|
||||
[[nodiscard]] constexpr reverse_iterator rend() noexcept { return _data.rend(); }
|
||||
[[nodiscard]] constexpr const_reverse_iterator rend() const noexcept { return _data.rend(); }
|
||||
[[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return _data.crbegin() + 1; }
|
||||
[[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return _data.crend(); }
|
||||
|
||||
private:
|
||||
[[nodiscard]] constexpr static bool static_empty() noexcept { return N == 0; }
|
||||
|
||||
public:
|
||||
// capacity
|
||||
[[nodiscard]] constexpr size_type size() const noexcept { return N; }
|
||||
[[nodiscard]] constexpr size_type length() const noexcept { return N; }
|
||||
[[nodiscard]] constexpr size_type max_size() const noexcept { return N; }
|
||||
[[nodiscard]] constexpr bool empty() const noexcept { return static_empty(); }
|
||||
|
||||
// element access
|
||||
[[nodiscard]] constexpr reference operator[](size_type n) { return _data[n]; }
|
||||
[[nodiscard]] constexpr const_reference operator[](size_type n) const { return _data[n]; }
|
||||
[[nodiscard]] constexpr reference at(size_type n) { return _data.at(n); }
|
||||
[[nodiscard]] constexpr const_reference at(size_type n) const { return _data.at(n); }
|
||||
|
||||
// The lack of C++20 concepts is disappointing
|
||||
// Basically what every `template<...>` line means is `requires (!empty())`
|
||||
template <typename..., bool NonEmpty = !static_empty(), typename = std::enable_if_t<NonEmpty>>
|
||||
[[nodiscard]] constexpr reference front() noexcept
|
||||
{
|
||||
return _data.front();
|
||||
}
|
||||
template <typename..., bool NonEmpty = !static_empty(), typename = std::enable_if_t<NonEmpty>>
|
||||
[[nodiscard]] constexpr const_reference front() const noexcept
|
||||
{
|
||||
return _data.front();
|
||||
}
|
||||
template <typename..., bool NonEmpty = !static_empty(), typename = std::enable_if_t<NonEmpty>>
|
||||
[[nodiscard]] constexpr reference back() noexcept
|
||||
{
|
||||
return _data[size() - 1];
|
||||
}
|
||||
template <typename..., bool NonEmpty = !static_empty(), typename = std::enable_if_t<NonEmpty>>
|
||||
[[nodiscard]] constexpr const_reference back() const noexcept
|
||||
{
|
||||
return _data[size() - 1];
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr pointer data() noexcept { return _data.data(); }
|
||||
[[nodiscard]] constexpr const_pointer data() const noexcept { return _data.data(); }
|
||||
|
||||
[[nodiscard]] constexpr const_pointer c_str() const noexcept { return data(); }
|
||||
|
||||
private:
|
||||
template <size_t M>
|
||||
using same_with_other_size = basic_fixed_string<value_type, M, traits_type>;
|
||||
|
||||
template <size_type pos, size_type count, size_type size>
|
||||
constexpr static size_type calculate_substr_size()
|
||||
{
|
||||
if constexpr (pos >= size)
|
||||
return 0;
|
||||
|
||||
constexpr size_type rcount = std::min(count, size - pos);
|
||||
|
||||
return rcount;
|
||||
}
|
||||
|
||||
template <size_type pos, size_type count>
|
||||
using substr_result_type = same_with_other_size<calculate_substr_size<pos, count, N>()>;
|
||||
|
||||
public:
|
||||
// string operations
|
||||
[[nodiscard]] constexpr operator string_view_type() const noexcept // NOLINT(google-explicit-constructor)
|
||||
{
|
||||
return {data(), N};
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
template <size_type pos = 0, size_type count = npos,
|
||||
typename..., bool IsPosInBounds = pos <= N, typename = std::enable_if_t<IsPosInBounds>>
|
||||
[[nodiscard]] constexpr auto substr() const noexcept
|
||||
-> substr_result_type<pos, count>
|
||||
// clang-format on
|
||||
{
|
||||
substr_result_type<pos, count> result;
|
||||
details::copy(begin() + pos, begin() + pos + result.size(), result.begin());
|
||||
return result;
|
||||
}
|
||||
|
||||
template <size_t M>
|
||||
[[nodiscard]] constexpr size_type find(const same_with_other_size<M>& str, size_type pos = 0) const noexcept
|
||||
{
|
||||
if constexpr (M > N)
|
||||
return npos;
|
||||
return sv().find(str.sv(), pos);
|
||||
}
|
||||
[[nodiscard]] constexpr size_type find(string_view_type sv, size_type pos = 0) const noexcept { return sv().find(sv, pos); }
|
||||
[[nodiscard]] constexpr size_type find(const value_type* s, size_type pos, size_type n) const { return sv().find(s, pos, n); }
|
||||
[[nodiscard]] constexpr size_type find(const value_type* s, size_type pos = 0) const { return sv().find(s, pos); }
|
||||
[[nodiscard]] constexpr size_type find(value_type c, size_type pos = 0) const noexcept { return sv().find(c, pos); }
|
||||
|
||||
template <size_t M>
|
||||
[[nodiscard]] constexpr size_type rfind(const same_with_other_size<M>& str, size_type pos = npos) const noexcept
|
||||
{
|
||||
if constexpr (M > N)
|
||||
return npos;
|
||||
return sv().rfind(str.sv(), pos);
|
||||
}
|
||||
[[nodiscard]] constexpr size_type rfind(string_view_type sv, size_type pos = npos) const noexcept { return sv().rfind(sv, pos); }
|
||||
[[nodiscard]] constexpr size_type rfind(const value_type* s, size_type pos, size_type n) const { return sv().rfind(s, pos, n); }
|
||||
[[nodiscard]] constexpr size_type rfind(const value_type* s, size_type pos = npos) const { return sv().rfind(s, pos); }
|
||||
[[nodiscard]] constexpr size_type rfind(value_type c, size_type pos = npos) const noexcept { return sv().rfind(c, pos); }
|
||||
|
||||
template <size_t M>
|
||||
[[nodiscard]] constexpr size_type find_first_of(const same_with_other_size<M>& str, size_type pos = 0) const noexcept
|
||||
{
|
||||
if constexpr (M > N)
|
||||
return npos;
|
||||
return sv().find_first_of(str.sv(), pos);
|
||||
}
|
||||
[[nodiscard]] constexpr size_type find_first_of(string_view_type sv, size_type pos = 0) const noexcept { return sv().find_first_of(sv, pos); }
|
||||
[[nodiscard]] constexpr size_type find_first_of(const value_type* s, size_type pos, size_type n) const { return sv().find_first_of(s, pos, n); }
|
||||
[[nodiscard]] constexpr size_type find_first_of(const value_type* s, size_type pos = 0) const { return sv().find_first_of(s, pos); }
|
||||
[[nodiscard]] constexpr size_type find_first_of(value_type c, size_type pos = 0) const noexcept { return sv().find_first_of(c, pos); }
|
||||
|
||||
template <size_t M>
|
||||
[[nodiscard]] constexpr size_type find_last_of(const same_with_other_size<M>& str, size_type pos = npos) const noexcept
|
||||
{
|
||||
if constexpr (M > N)
|
||||
return npos;
|
||||
return sv().find_last_of(str.sv(), pos);
|
||||
}
|
||||
[[nodiscard]] constexpr size_type find_last_of(string_view_type sv, size_type pos = npos) const noexcept { return sv().find_last_of(sv, pos); }
|
||||
[[nodiscard]] constexpr size_type find_last_of(const value_type* s, size_type pos, size_type n) const { return sv().find_last_of(s, pos, n); }
|
||||
[[nodiscard]] constexpr size_type find_last_of(const value_type* s, size_type pos = npos) const { return sv().find_last_of(s, pos); }
|
||||
[[nodiscard]] constexpr size_type find_last_of(value_type c, size_type pos = npos) const noexcept { return sv().find_last_of(c, pos); }
|
||||
|
||||
template <size_t M>
|
||||
[[nodiscard]] constexpr size_type find_first_not_of(const same_with_other_size<M>& str, size_type pos = 0) const noexcept
|
||||
{
|
||||
if constexpr (M > N)
|
||||
return npos;
|
||||
return sv().find_first_of(str.sv(), pos);
|
||||
}
|
||||
[[nodiscard]] constexpr size_type find_first_not_of(string_view_type sv, size_type pos = 0) const noexcept { return sv().find_first_not_of(sv, pos); }
|
||||
[[nodiscard]] constexpr size_type find_first_not_of(const value_type* s, size_type pos, size_type n) const { return sv().find_first_not_of(s, pos, n); }
|
||||
[[nodiscard]] constexpr size_type find_first_not_of(const value_type* s, size_type pos = 0) const { return sv().find_first_not_of(s, pos); }
|
||||
[[nodiscard]] constexpr size_type find_first_not_of(value_type c, size_type pos = 0) const noexcept { return sv().find_first_not_of(c, pos); }
|
||||
|
||||
template <size_t M>
|
||||
[[nodiscard]] constexpr size_type find_last_not_of(const same_with_other_size<M>& str, size_type pos = npos) const noexcept
|
||||
{
|
||||
if constexpr (M > N)
|
||||
return npos;
|
||||
return sv().find_last_of(str.sv(), pos);
|
||||
}
|
||||
[[nodiscard]] constexpr size_type find_last_not_of(string_view_type sv, size_type pos = npos) const noexcept { return sv().find_last_not_of(sv, pos); }
|
||||
[[nodiscard]] constexpr size_type find_last_not_of(const value_type* s, size_type pos, size_type n) const { return sv().find_last_not_of(s, pos, n); }
|
||||
[[nodiscard]] constexpr size_type find_last_not_of(const value_type* s, size_type pos = npos) const { return sv().find_last_not_of(s, pos); }
|
||||
[[nodiscard]] constexpr size_type find_last_not_of(value_type c, size_type pos = npos) const noexcept { return sv().find_last_not_of(c, pos); }
|
||||
|
||||
[[nodiscard]] constexpr int compare(string_view_type v) const noexcept { return sv().compare(v); }
|
||||
[[nodiscard]] constexpr int compare(size_type pos1, size_type count1, string_view_type v) const { return sv().compare(pos1, count1, v); }
|
||||
[[nodiscard]] constexpr int compare(size_type pos1, size_type count1, string_view_type v, size_type pos2, size_type count2) const
|
||||
{
|
||||
return sv().compare(pos1, count1, v, pos2, count2);
|
||||
}
|
||||
[[nodiscard]] constexpr int compare(const value_type* s) const { return sv().compare(s); }
|
||||
[[nodiscard]] constexpr int compare(size_type pos1, size_type count1, const value_type* s) const { return sv().compare(pos1, count1, s); }
|
||||
[[nodiscard]] constexpr int compare(size_type pos1, size_type count1, const value_type* s, size_type count2) const
|
||||
{
|
||||
return sv().compare(pos1, count1, s, count2);
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr bool starts_with(string_view_type v) const noexcept { return sv().substr(0, v.size()) == v; }
|
||||
[[nodiscard]] constexpr bool starts_with(char c) const noexcept { return !empty() && traits_type::eq(front(), c); }
|
||||
[[nodiscard]] constexpr bool starts_with(const value_type* s) const noexcept { return starts_with(string_view_type(s)); }
|
||||
|
||||
[[nodiscard]] constexpr bool ends_with(string_view_type sv) const noexcept { return size() >= sv.size() && compare(size() - sv.size(), npos, sv) == 0; }
|
||||
[[nodiscard]] constexpr bool ends_with(value_type c) const noexcept { return !empty() && traits_type::eq(back(), c); }
|
||||
[[nodiscard]] constexpr bool ends_with(const value_type* s) const { return ends_with(string_view_type(s)); }
|
||||
|
||||
[[nodiscard]] constexpr bool contains(string_view_type sv) const noexcept { return find(sv) != npos; }
|
||||
[[nodiscard]] constexpr bool contains(value_type c) const noexcept { return find(c) != npos; }
|
||||
[[nodiscard]] constexpr bool contains(const value_type* s) const { return find(s) != npos; }
|
||||
|
||||
void swap(basic_fixed_string& other) noexcept(std::is_nothrow_swappable_v<storage_type>) { _data.swap(other._data); }
|
||||
|
||||
private:
|
||||
constexpr string_view_type sv() const { return *this; }
|
||||
};
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
void swap(basic_fixed_string<TChar, N, TTraits>& lhs, basic_fixed_string<TChar, N, TTraits>& rhs) noexcept(noexcept(lhs.swap(rhs)))
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t M1, size_t M2>
|
||||
[[nodiscard]] constexpr bool operator==(const basic_fixed_string<TChar, M1, TTraits>& lhs, const basic_fixed_string<TChar, M2, TTraits>& rhs)
|
||||
{
|
||||
if constexpr (M1 != M2)
|
||||
return false;
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) == rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator==(const basic_fixed_string<TChar, N, TTraits>& lhs, std::basic_string_view<TChar, TTraits> rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) == rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator==(std::basic_string_view<TChar, TTraits> lhs, const basic_fixed_string<TChar, N, TTraits>& rhs)
|
||||
{
|
||||
using rhs_type = std::decay_t<decltype(rhs)>;
|
||||
using sv_type = typename rhs_type::string_view_type;
|
||||
return lhs == static_cast<sv_type>(rhs);
|
||||
}
|
||||
|
||||
#if FIXSTR_CPP20_SPACESHIP_OPERATOR_PRESENT
|
||||
|
||||
template <typename TChar, typename TTraits, size_t M1, size_t M2>
|
||||
[[nodiscard]] constexpr auto operator<=>(const basic_fixed_string<TChar, M1, TTraits>& lhs, const basic_fixed_string<TChar, M2, TTraits>& rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) <=> rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr auto operator<=>(const basic_fixed_string<TChar, N, TTraits>& lhs, std::basic_string_view<TChar, TTraits> rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) <=> rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr auto operator<=>(std::basic_string_view<TChar, TTraits> lhs, const basic_fixed_string<TChar, N, TTraits>& rhs)
|
||||
{
|
||||
using rhs_type = std::decay_t<decltype(rhs)>;
|
||||
using sv_type = typename rhs_type::string_view_type;
|
||||
return lhs <=> static_cast<sv_type>(rhs);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename TChar, typename TTraits, size_t M1, size_t M2>
|
||||
[[nodiscard]] constexpr bool operator!=(const basic_fixed_string<TChar, M1, TTraits>& lhs, const basic_fixed_string<TChar, M2, TTraits>& rhs)
|
||||
{
|
||||
if constexpr (M1 != M2)
|
||||
return true;
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) != rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator!=(const basic_fixed_string<TChar, N, TTraits>& lhs, std::basic_string_view<TChar, TTraits> rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) != rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator!=(std::basic_string_view<TChar, TTraits> lhs, const basic_fixed_string<TChar, N, TTraits>& rhs)
|
||||
{
|
||||
using rhs_type = std::decay_t<decltype(rhs)>;
|
||||
using sv_type = typename rhs_type::string_view_type;
|
||||
return lhs != static_cast<sv_type>(rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t M1, size_t M2>
|
||||
[[nodiscard]] constexpr bool operator<(const basic_fixed_string<TChar, M1, TTraits>& lhs, const basic_fixed_string<TChar, M2, TTraits>& rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) < rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator<(const basic_fixed_string<TChar, N, TTraits>& lhs, std::basic_string_view<TChar, TTraits> rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) < rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator<(std::basic_string_view<TChar, TTraits> lhs, const basic_fixed_string<TChar, N, TTraits>& rhs)
|
||||
{
|
||||
using rhs_type = std::decay_t<decltype(rhs)>;
|
||||
using sv_type = typename rhs_type::string_view_type;
|
||||
return lhs < static_cast<sv_type>(rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t M1, size_t M2>
|
||||
[[nodiscard]] constexpr bool operator<=(const basic_fixed_string<TChar, M1, TTraits>& lhs, const basic_fixed_string<TChar, M2, TTraits>& rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) <= rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator<=(const basic_fixed_string<TChar, N, TTraits>& lhs, std::basic_string_view<TChar, TTraits> rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) <= rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator<=(std::basic_string_view<TChar, TTraits> lhs, const basic_fixed_string<TChar, N, TTraits>& rhs)
|
||||
{
|
||||
using rhs_type = std::decay_t<decltype(rhs)>;
|
||||
using sv_type = typename rhs_type::string_view_type;
|
||||
return lhs <= static_cast<sv_type>(rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t M1, size_t M2>
|
||||
[[nodiscard]] constexpr bool operator>(const basic_fixed_string<TChar, M1, TTraits>& lhs, const basic_fixed_string<TChar, M2, TTraits>& rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) > rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator>(const basic_fixed_string<TChar, N, TTraits>& lhs, std::basic_string_view<TChar, TTraits> rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) > rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator>(std::basic_string_view<TChar, TTraits> lhs, const basic_fixed_string<TChar, N, TTraits>& rhs)
|
||||
{
|
||||
using rhs_type = std::decay_t<decltype(rhs)>;
|
||||
using sv_type = typename rhs_type::string_view_type;
|
||||
return lhs > static_cast<sv_type>(rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t M1, size_t M2>
|
||||
[[nodiscard]] constexpr bool operator>=(const basic_fixed_string<TChar, M1, TTraits>& lhs, const basic_fixed_string<TChar, M2, TTraits>& rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) >= rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator>=(const basic_fixed_string<TChar, N, TTraits>& lhs, std::basic_string_view<TChar, TTraits> rhs)
|
||||
{
|
||||
using lhs_type = std::decay_t<decltype(lhs)>;
|
||||
using sv_type = typename lhs_type::string_view_type;
|
||||
return static_cast<sv_type>(lhs) >= rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, typename TTraits, size_t N>
|
||||
[[nodiscard]] constexpr bool operator>=(std::basic_string_view<TChar, TTraits> lhs, const basic_fixed_string<TChar, N, TTraits>& rhs)
|
||||
{
|
||||
using rhs_type = std::decay_t<decltype(rhs)>;
|
||||
using sv_type = typename rhs_type::string_view_type;
|
||||
return lhs >= static_cast<sv_type>(rhs);
|
||||
}
|
||||
|
||||
#endif // FIXSTR_CPP20_SPACESHIP_OPERATOR_PRESENT
|
||||
|
||||
template <typename TChar, size_t N>
|
||||
basic_fixed_string(const TChar (&)[N]) -> basic_fixed_string<TChar, N - 1>;
|
||||
|
||||
// Early GCC versions that support cNTTP were not able to deduce size_t parameter
|
||||
// of basic_fixed_string when fixed_string and other typedef were just type aliases.
|
||||
// That's why the following code is written in this way.
|
||||
template <size_t N>
|
||||
struct fixed_string : basic_fixed_string<char, N>
|
||||
{
|
||||
using basic_fixed_string<char, N>::basic_fixed_string;
|
||||
};
|
||||
template <std::size_t N>
|
||||
fixed_string(const char (&)[N]) -> fixed_string<N - 1>;
|
||||
|
||||
#if FIXSTR_CPP20_CHAR8T_PRESENT
|
||||
template <size_t N>
|
||||
struct fixed_u8string : basic_fixed_string<char8_t, N>
|
||||
{
|
||||
using basic_fixed_string<char8_t, N>::basic_fixed_string;
|
||||
};
|
||||
template <std::size_t N>
|
||||
fixed_u8string(const char8_t (&)[N]) -> fixed_u8string<N - 1>;
|
||||
#endif // FIXSTR_CPP20_CHAR8T_PRESENT
|
||||
|
||||
template <size_t N>
|
||||
struct fixed_u16string : basic_fixed_string<char16_t, N>
|
||||
{
|
||||
using basic_fixed_string<char16_t, N>::basic_fixed_string;
|
||||
};
|
||||
template <std::size_t N>
|
||||
fixed_u16string(const char16_t (&)[N]) -> fixed_u16string<N - 1>;
|
||||
|
||||
template <size_t N>
|
||||
struct fixed_u32string : basic_fixed_string<char32_t, N>
|
||||
{
|
||||
using basic_fixed_string<char32_t, N>::basic_fixed_string;
|
||||
};
|
||||
template <std::size_t N>
|
||||
fixed_u32string(const char32_t (&)[N]) -> fixed_u32string<N - 1>;
|
||||
|
||||
template <size_t N>
|
||||
struct fixed_wstring : basic_fixed_string<wchar_t, N>
|
||||
{
|
||||
using basic_fixed_string<wchar_t, N>::basic_fixed_string;
|
||||
};
|
||||
template <std::size_t N>
|
||||
fixed_wstring(const wchar_t (&)[N]) -> fixed_wstring<N - 1>;
|
||||
|
||||
template <typename TChar, size_t N, size_t M, typename TTraits>
|
||||
constexpr basic_fixed_string<TChar, N + M, TTraits> operator+(const basic_fixed_string<TChar, N, TTraits>& lhs, const basic_fixed_string<TChar, M, TTraits>& rhs)
|
||||
{
|
||||
basic_fixed_string<TChar, N + M, TTraits> result;
|
||||
details::copy(lhs.begin(), lhs.end(), result.begin());
|
||||
details::copy(rhs.begin(), rhs.end(), result.begin() + N);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename TChar, size_t N, size_t M, typename TTraits>
|
||||
constexpr basic_fixed_string<TChar, N - 1 + M, TTraits> operator+(const TChar (&lhs)[N], const basic_fixed_string<TChar, M, TTraits>& rhs)
|
||||
{
|
||||
basic_fixed_string lhs2 = lhs;
|
||||
return lhs2 + rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, size_t N, size_t M, typename TTraits>
|
||||
constexpr basic_fixed_string<TChar, N + M - 1, TTraits> operator+(const basic_fixed_string<TChar, N, TTraits>& lhs, const TChar (&rhs)[M])
|
||||
{
|
||||
basic_fixed_string rhs2 = rhs;
|
||||
return lhs + rhs2;
|
||||
}
|
||||
|
||||
namespace details
|
||||
{
|
||||
template <typename TChar>
|
||||
constexpr basic_fixed_string<TChar, 1> from_char(TChar ch)
|
||||
{
|
||||
basic_fixed_string<TChar, 1> fs;
|
||||
fs[0] = ch;
|
||||
return fs;
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
template <typename TChar, size_t N, typename TTraits>
|
||||
constexpr basic_fixed_string<TChar, N + 1, TTraits> operator+(TChar lhs, const basic_fixed_string<TChar, N, TTraits>& rhs)
|
||||
{
|
||||
return details::from_char(lhs) + rhs;
|
||||
}
|
||||
|
||||
template <typename TChar, size_t N, typename TTraits>
|
||||
constexpr basic_fixed_string<TChar, N + 1, TTraits> operator+(const basic_fixed_string<TChar, N, TTraits>& lhs, TChar rhs)
|
||||
{
|
||||
return lhs + details::from_char(rhs);
|
||||
}
|
||||
|
||||
template <typename TChar, size_t N, typename TTraits>
|
||||
std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const basic_fixed_string<TChar, N, TTraits>& str)
|
||||
{
|
||||
out << str.data();
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace fixstr
|
||||
|
||||
// hash support
|
||||
namespace std
|
||||
{
|
||||
template <size_t N>
|
||||
struct hash<fixstr::fixed_string<N>>
|
||||
{
|
||||
using argument_type = fixstr::fixed_string<N>;
|
||||
size_t operator()(const argument_type& str) const
|
||||
{
|
||||
using sv_t = typename argument_type::string_view_type;
|
||||
return std::hash<sv_t>()(static_cast<sv_t>(str));
|
||||
}
|
||||
};
|
||||
|
||||
#if FIXSTR_CPP20_CHAR8T_PRESENT
|
||||
template <size_t N>
|
||||
struct hash<fixstr::fixed_u8string<N>>
|
||||
{
|
||||
using argument_type = fixstr::fixed_u8string<N>;
|
||||
size_t operator()(const argument_type& str) const
|
||||
{
|
||||
using sv_t = typename argument_type::string_view_type;
|
||||
return std::hash<sv_t>()(static_cast<sv_t>(str));
|
||||
}
|
||||
};
|
||||
#endif // FIXSTR_CPP20_CHAR8T_PRESENT
|
||||
|
||||
template <size_t N>
|
||||
struct hash<fixstr::fixed_u16string<N>>
|
||||
{
|
||||
using argument_type = fixstr::fixed_u16string<N>;
|
||||
size_t operator()(const argument_type& str) const
|
||||
{
|
||||
using sv_t = typename argument_type::string_view_type;
|
||||
return std::hash<sv_t>()(static_cast<sv_t>(str));
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct hash<fixstr::fixed_u32string<N>>
|
||||
{
|
||||
using argument_type = fixstr::fixed_u32string<N>;
|
||||
size_t operator()(const argument_type& str) const
|
||||
{
|
||||
using sv_t = typename argument_type::string_view_type;
|
||||
return std::hash<sv_t>()(static_cast<sv_t>(str));
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct hash<fixstr::fixed_wstring<N>>
|
||||
{
|
||||
using argument_type = fixstr::fixed_wstring<N>;
|
||||
size_t operator()(const argument_type& str) const
|
||||
{
|
||||
using sv_t = typename argument_type::string_view_type;
|
||||
return std::hash<sv_t>()(static_cast<sv_t>(str));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // FIXED_STRING_HPP
|
||||
@@ -392,6 +392,9 @@ void Rando::StaticData::InitItemTable() {
|
||||
itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbessertes Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER);
|
||||
itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Fragment" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER);
|
||||
|
||||
// Archipelago
|
||||
itemTable[RG_ARCHIPELAGO_ITEM] = /* doesn't work :P*/ Item(RG_ARCHIPELAGO_ITEM, Text{"AP Item", "AP Item", "AP_Item"}, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_NONE, RG_ARCHIPELAGO_ITEM, OBJECT_GI_LETTER, GID_LETTER_ZELDA, TEXT_RANDOMIZER_CUSTOM_ITEM, 0, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE);
|
||||
|
||||
// Init itemNameToEnum
|
||||
for (auto& item : itemTable) {
|
||||
// Easiest way to filter out all the empty values from the array, since we still technically want the 0/RG_NONE
|
||||
|
||||
@@ -3392,6 +3392,7 @@ typedef enum {
|
||||
RG_BACK_TOWER_KEY,
|
||||
RG_HYLIA_LAB_KEY,
|
||||
RG_FISHING_HOLE_KEY,
|
||||
RG_ARCHIPELAGO_ITEM,
|
||||
// Logic Only
|
||||
RG_DISTANT_SCARECROW,
|
||||
RG_STICKS,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <unordered_map>
|
||||
#include "static_data.h"
|
||||
#include <spdlog/spdlog.h>
|
||||
#include "archipelago_mappings.h"
|
||||
|
||||
namespace Rando {
|
||||
|
||||
@@ -302,4 +303,34 @@ std::unordered_map<u32, RandomizerHint> StaticData::grottoChestParamsToHint{
|
||||
};
|
||||
|
||||
std::array<HintText, RHT_MAX> StaticData::hintTextTable = {};
|
||||
|
||||
const std::unordered_map<std::string_view, RandomizerGet>generate_APitemToSoh_mapping() {
|
||||
std::unordered_map<std::string_view, RandomizerGet> mapping;
|
||||
for(const auto& pairing : ap_item_mapping_pairs) {
|
||||
mapping[pairing.first] = pairing.second;
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string_view, RandomizerCheck>generate_APcheckToSoh_mapping() {
|
||||
std::unordered_map<std::string_view, RandomizerCheck> mapping;
|
||||
for(const auto& pairing : ap_check_mapping_pairs) {
|
||||
mapping[pairing.first] = pairing.second;
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
const std::unordered_map<RandomizerCheck, std::string_view>generate_SohcheckToAP_mapping() {
|
||||
std::unordered_map<RandomizerCheck, std::string_view> mapping;
|
||||
for(const auto& pairing : ap_check_mapping_pairs) {
|
||||
mapping[pairing.second] = pairing.first;
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string_view, RandomizerGet> StaticData::APitemToSoh = generate_APitemToSoh_mapping();
|
||||
std::unordered_map<std::string_view, RandomizerCheck> StaticData::APcheckToSoh = generate_APcheckToSoh_mapping();
|
||||
std::unordered_map<RandomizerCheck, std::string_view> StaticData::SohCheckToAP = generate_SohcheckToAP_mapping();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -69,6 +69,10 @@ class StaticData {
|
||||
static std::unordered_map<u32, RandomizerHint> grottoChestParamsToHint;
|
||||
static std::array<HintText, RHT_MAX> hintTextTable;
|
||||
|
||||
static std::unordered_map<std::string_view, RandomizerGet> APitemToSoh;
|
||||
static std::unordered_map<std::string_view, RandomizerCheck> APcheckToSoh;
|
||||
static std::unordered_map<RandomizerCheck, std::string_view> SohCheckToAP;
|
||||
|
||||
StaticData();
|
||||
~StaticData();
|
||||
};
|
||||
|
||||
@@ -2468,4 +2468,8 @@ void SoH_ProcessDroppedFiles(std::string filePath) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void parse_archipelago() {
|
||||
OTRGlobals::Instance->gRandoContext->ParseArchipelago();
|
||||
}
|
||||
// #endregion
|
||||
|
||||
@@ -156,6 +156,7 @@ void CheckTracker_OnMessageClose();
|
||||
|
||||
GetItemID RetrieveGetItemIDFromItemID(ItemID itemID);
|
||||
RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID);
|
||||
void parse_archipelago();
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -129,6 +129,7 @@ namespace SohGui {
|
||||
std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||
std::shared_ptr<TimeSplitWindow> mTimeSplitWindow;
|
||||
std::shared_ptr<PlandomizerWindow> mPlandomizerWindow;
|
||||
std::shared_ptr<ArchipelagoWindow> mArchipelagoWindow;
|
||||
std::shared_ptr<RandomizerSettingsWindow> mRandomizerSettingsWindow;
|
||||
std::shared_ptr<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow> mAdvancedResolutionSettingsWindow;
|
||||
std::shared_ptr<SohModalWindow> mModalWindow;
|
||||
@@ -212,6 +213,8 @@ namespace SohGui {
|
||||
gui->AddGuiWindow(mTimeSplitWindow);
|
||||
mPlandomizerWindow = std::make_shared<PlandomizerWindow>(CVAR_WINDOW("PlandomizerWindow"), "Plandomizer Editor", ImVec2(850, 760));
|
||||
gui->AddGuiWindow(mPlandomizerWindow);
|
||||
mArchipelagoWindow = std::make_shared<ArchipelagoWindow>(CVAR_WINDOW("ArchipelagoWindow"), "Archipelago", ImVec2(850, 760));
|
||||
gui->AddGuiWindow(mArchipelagoWindow);
|
||||
mAdvancedResolutionSettingsWindow = std::make_shared<AdvancedResolutionSettings::AdvancedResolutionSettingsWindow>(CVAR_WINDOW("AdvancedResolutionEditor"), "Advanced Resolution Settings", ImVec2(497, 599));
|
||||
gui->AddGuiWindow(mAdvancedResolutionSettingsWindow);
|
||||
mModalWindow = std::make_shared<SohModalWindow>(CVAR_WINDOW("ModalWindow"), "Modal Window");
|
||||
@@ -259,6 +262,7 @@ namespace SohGui {
|
||||
mInputViewerSettings = nullptr;
|
||||
mTimeSplitWindow = nullptr;
|
||||
mPlandomizerWindow = nullptr;
|
||||
mArchipelagoWindow = nullptr;
|
||||
mTimeDisplayWindow = nullptr;
|
||||
mAboutWindow = nullptr;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "Enhancements/randomizer/randomizer_settings_window.h"
|
||||
#include "Enhancements/timesplits/TimeSplits.h"
|
||||
#include "Enhancements/randomizer/Plandomizer.h"
|
||||
#include "Enhancements/randomizer/archipelago.h"
|
||||
#include "AboutWindow.h"
|
||||
#include "SohModals.h"
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "Enhancements/enemyrandomizer.h"
|
||||
#include "Enhancements/timesplits/TimeSplits.h"
|
||||
#include "Enhancements/randomizer/Plandomizer.h"
|
||||
#include "Enhancements/randomizer/archipelago.h"
|
||||
#include "Enhancements/TimeDisplay/TimeDisplay.h"
|
||||
#include "AboutWindow.h"
|
||||
|
||||
@@ -2134,6 +2135,7 @@ void DrawRemoteControlMenu() {
|
||||
|
||||
extern std::shared_ptr<RandomizerSettingsWindow> mRandomizerSettingsWindow;
|
||||
extern std::shared_ptr<PlandomizerWindow> mPlandomizerWindow;
|
||||
extern std::shared_ptr<ArchipelagoWindow> mArchipelagoWindow;
|
||||
extern std::shared_ptr<ItemTrackerWindow> mItemTrackerWindow;
|
||||
extern std::shared_ptr<ItemTrackerSettingsWindow> mItemTrackerSettingsWindow;
|
||||
extern std::shared_ptr<EntranceTrackerWindow> mEntranceTrackerWindow;
|
||||
@@ -2175,6 +2177,14 @@ void DrawRandomizerMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
|
||||
if (mArchipelagoWindow) {
|
||||
if (ImGui::Button(GetWindowButtonText("Archipelago", CVarGetInteger(CVAR_WINDOW("ArchipelagoWindow"), 0)).c_str(), buttonSize)) {
|
||||
mArchipelagoWindow->ToggleVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
|
||||
if (mItemTrackerWindow) {
|
||||
|
||||
@@ -1005,6 +1005,7 @@ void DrawSeedHashSprites(FileChooseContext* this) {
|
||||
u8 generating;
|
||||
int retries = 0;
|
||||
bool fileSelectSpoilerFileLoaded = false;
|
||||
bool fileSelectarchipelagoloaded = false;
|
||||
|
||||
void FileChoose_UpdateRandomizer() {
|
||||
if (CVarGetInteger(CVAR_GENERAL("RandoGenerating"), 0) != 0 && generating == 0) {
|
||||
@@ -1045,6 +1046,13 @@ void FileChoose_UpdateRandomizer() {
|
||||
remove(fileLoc);
|
||||
}
|
||||
}
|
||||
|
||||
if (CVarGetInteger("archipelago_connected", 0) != 0
|
||||
&& !fileSelectarchipelagoloaded) {
|
||||
parse_archipelago();
|
||||
fileSelectarchipelagoloaded = true;
|
||||
Audio_PlayFanfare(NA_BGM_HORSE_GOAL);
|
||||
}
|
||||
}
|
||||
|
||||
static s16 sLastFileChooseButtonIndex;
|
||||
@@ -3711,6 +3719,7 @@ void FileChoose_Init(GameState* thisx) {
|
||||
this->questType[1] = MIN_QUEST;
|
||||
this->questType[2] = MIN_QUEST;
|
||||
fileSelectSpoilerFileLoaded = false;
|
||||
fileSelectarchipelagoloaded = false;
|
||||
CVarSetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0);
|
||||
|
||||
SREG(30) = 1;
|
||||
|
||||
Reference in New Issue
Block a user