mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-09-10 03:01:56 -04:00
235 lines
6.8 KiB
C++
235 lines
6.8 KiB
C++
#ifndef DUSK_RANDOMIZER_CONTEXT_HPP
|
|
#define DUSK_RANDOMIZER_CONTEXT_HPP
|
|
|
|
#include <dolphin/types.h>
|
|
|
|
#include <array>
|
|
#include <list>
|
|
#include <iomanip>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <unordered_map>
|
|
#include <unordered_set>
|
|
|
|
#include "dusk/randomizer/generator/randomizer.hpp"
|
|
|
|
/*
|
|
* Class holding all the information necessary for playing
|
|
* the current randomizer seed
|
|
*/
|
|
class RandomizerContext {
|
|
public:
|
|
static constexpr size_t ACTR_CRC_SIZE = 32;
|
|
static constexpr size_t TGSC_CRC_SIZE = 35; // 3 extra bytes for scale x, y, z
|
|
static constexpr size_t OBJ_DELETE_SIZE = 1;
|
|
static constexpr u8 ROOM_STAGE = 0xFF;
|
|
|
|
RandomizerContext() = default;
|
|
|
|
bool mCreatingSave{false};
|
|
u32 mSeedID{0};
|
|
std::string mHash{""};
|
|
|
|
// Maps enum of necessary setting to enum of value
|
|
std::unordered_map<int, int> mSettings{};
|
|
|
|
std::list<u16> mStartEventFlags{};
|
|
std::unordered_map<u8, std::list<u8>> mStartRegionFlags{};
|
|
std::list<u8> mStartingInventory{};
|
|
std::unordered_map<u16, u8> mTreasureChestOverrides{};
|
|
std::unordered_map<u16, u8> mPoeOverrides{};
|
|
std::unordered_map<u16, u8> mFreestandingItemOverrides{};
|
|
std::unordered_map<u8, u8> mBugRewardOverrides{};
|
|
std::unordered_map<u16, u8> mSkyCharacterOverrides{};
|
|
std::unordered_map<u16, u8> mGoldenWolfOverrides{};
|
|
std::unordered_map<u16, u8> mShopOverrides{};
|
|
std::unordered_map<u32, u8> mFlowItemMessageOverrides{};
|
|
std::unordered_map<std::string, int> mItemLocations{};
|
|
u8 mStartHour{0};
|
|
u8 mMapBits{};
|
|
|
|
std::unordered_map<u32, std::unordered_map<u32, std::vector<u8>>> mObjectPatches{};
|
|
std::unordered_map<u32, std::list<std::vector<u8>>> mObjectAdditions{};
|
|
// std::unordered_map<u32, std::unordered_set<u32>> mTgscDeletions{};
|
|
std::unordered_map<u32, u64> mFlowPatches{};
|
|
|
|
// struct TextOverride {
|
|
// std::array<u8, 16> mAttributes{};
|
|
// std::string mText{};
|
|
// };
|
|
std::unordered_map<u32, std::string> mTextOverrides{};
|
|
|
|
std::optional<std::string> WriteToFile();
|
|
std::optional<std::string> LoadFromHash(const std::string& hash);
|
|
std::string GetSeedDataPath() const;
|
|
|
|
enum Settings {
|
|
HYRULE_BARRIER_REQUIREMENTS,
|
|
HYRULE_BARRIER_FUSED_SHADOWS,
|
|
HYRULE_BARRIER_MIRROR_SHARDS,
|
|
HYRULE_BARRIER_POE_SOULS,
|
|
HYRULE_BARRIER_HEARTS,
|
|
HYRULE_BARRIER_DUNGEONS,
|
|
HYRULE_BIG_KEY_REQUIREMENTS,
|
|
HYRULE_BIG_KEY_FUSED_SHADOWS,
|
|
HYRULE_BIG_KEY_MIRROR_SHARDS,
|
|
HYRULE_BIG_KEY_POE_SOULS,
|
|
HYRULE_BIG_KEY_HEARTS,
|
|
HYRULE_BIG_KEY_DUNGEONS,
|
|
PALACE_OF_TWILIGHT_REQUIREMENTS,
|
|
TEMPLE_OF_TIME_SWORD_REQUIREMENT,
|
|
SKIP_MINOR_CUTSCENES,
|
|
SKIP_MAJOR_CUTSCENES,
|
|
};
|
|
|
|
enum Options {
|
|
ON,
|
|
OFF,
|
|
NONE,
|
|
VANILLA,
|
|
OPEN,
|
|
FUSED_SHADOWS,
|
|
MIRROR_SHARDS,
|
|
POE_SOULS,
|
|
HEARTS,
|
|
DUNGEONS,
|
|
WOODEN_SWORD,
|
|
ORDON_SWORD,
|
|
MASTER_SWORD,
|
|
LIGHT_SWORD,
|
|
};
|
|
|
|
static int SettingToEnum(const std::string& settingName);
|
|
|
|
static int OptionToEnum(const std::string& optionName);
|
|
};
|
|
|
|
/*
|
|
* Class holding seed-agnostic dynamic information about current randomizer play.
|
|
* This gets reset when reseting to the title screen.
|
|
*/
|
|
class RandomizerState {
|
|
public:
|
|
enum TimeChange {
|
|
NO_CHANGE = 0,
|
|
CHANGE_TO_NIGHT,
|
|
CHANGE_TO_DAY,
|
|
};
|
|
|
|
enum EventItemStatus {
|
|
QUEUE_EMPTY,
|
|
ITEM_IN_QUEUE,
|
|
CLEAR_QUEUE,
|
|
};
|
|
|
|
static constexpr u8 EVENT_ITEM_QUEUE_SIZE = 10;
|
|
|
|
RandomizerState() {mInitialized = false;}
|
|
|
|
int _create();
|
|
int _delete();
|
|
int execute();
|
|
int draw();
|
|
void addItemToEventQueue(u8 item);
|
|
void initGiveItemToPlayer();
|
|
//void handleBonkDamage();
|
|
void handleTimeOfDayChange();
|
|
void handleTimeSpeed();
|
|
void offLoad();
|
|
|
|
void handlePoeItem(u8 bitSw);
|
|
|
|
u8 getGiveItemToPlayerStatus() const { return mEventItemStatus;}
|
|
u8 getTimeChange() const { return mTimeChange; }
|
|
bool getRoomReloadingState() const { return mRoomReloadingState; }
|
|
bool getHasPendingToDChange() const { return mHasPendingToDChange; }
|
|
|
|
void setGiveItemToPlayerStatus(u8 status) { mEventItemStatus = status;}
|
|
void setHasPendingToDChange(bool hasPending) { mHasPendingToDChange = hasPending; }
|
|
void setTimeChange(u8 newTimeChange) { mTimeChange = newTimeChange; }
|
|
void setRoomReloadingState(bool newState) { mRoomReloadingState = newState; }
|
|
|
|
bool mInitialized{false};
|
|
u8 mEventItemStatus{};
|
|
bool mHasPendingToDChange{false};
|
|
u8 mTimeChange{};
|
|
u8 mEventItemQueue[EVENT_ITEM_QUEUE_SIZE];
|
|
bool mRoomReloadingState{false};
|
|
|
|
// Used to store an item id for a flow message override so that we can give the item
|
|
// once the textbox is closed instead of when the message appears. This lines up
|
|
// more naturally with the timing of when the game normally gives items and affects
|
|
// things like the sound of the rupee counter going up.
|
|
u8 mFlowMessageItemId{0};
|
|
|
|
int foolishItemCount{0};
|
|
};
|
|
|
|
extern randomizer::Randomizer g_RandomizerGenerator;
|
|
|
|
extern RandomizerState g_randomizerState;
|
|
|
|
RandomizerContext& randomizer_GetContext();
|
|
|
|
bool randomizer_IsActive();
|
|
|
|
int randomizer_getItemAtLocation(const std::string& locationName);
|
|
|
|
bool randomizer_checkTempleOfTimeRequirement();
|
|
|
|
u8 randomizer_getRandomFoolishItemModelID();
|
|
|
|
/**
|
|
* Helper function to convert raw bytes of a container to a hex string
|
|
*/
|
|
template <typename T>
|
|
std::string ContainerToHexString(const T& container, bool includePrefix = true) {
|
|
std::ostringstream oss;
|
|
|
|
if (includePrefix) {
|
|
oss << "0x";
|
|
}
|
|
|
|
// Get the raw byte pointer to the start of the data
|
|
const auto* rawBytes = reinterpret_cast<const u8*>(container.data());
|
|
|
|
// Calculate total byte size (number of elements * size of each element)
|
|
size_t totalBytes = container.size() * sizeof(typename T::value_type);
|
|
|
|
oss << std::hex << std::setfill('0') << std::uppercase;
|
|
|
|
for (size_t i = 0; i < totalBytes; ++i) {
|
|
// static_cast to not u8 is necessary so oss treats it as a number, not a char
|
|
oss << std::setw(2) << static_cast<u16>(rawBytes[i]);
|
|
}
|
|
|
|
return oss.str();
|
|
}
|
|
|
|
/**
|
|
* Helper function to convert hex string to raw bytes
|
|
*/
|
|
std::vector<u8> HexToBytes(std::string hex);
|
|
|
|
/*
|
|
* Gets the current stage id, room no, and layer no in the format for a key in mActorPatches
|
|
*/
|
|
u32 getActorPatchesCurrentStageKey(u8 roomNo);
|
|
|
|
class stage_actor_data_class;
|
|
/*
|
|
* Gets the CRC32 hash of an actors name, parameters, position, and angle
|
|
*/
|
|
u32 getStageObjCRC32(u8* data, size_t size);
|
|
|
|
void GenerateAndWriteSeed(std::string& generationStatusMsg);
|
|
|
|
void LoadRandomizerConfig();
|
|
|
|
randomizer::seedgen::config::Config& GetRandomizerConfig();
|
|
|
|
std::string GetRandomizerConfigPath();
|
|
|
|
#endif //DUSK_RANDOMIZER_CONTEXT_HPP
|