mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-17 12:57:01 +02:00
Merge pull request #262 from Kalmarv/pr/tod-v3
Time of day: the new one loads only after the old one has unloaded
This commit is contained in:
2 files changed
+36
-3
No files matched your search
@@ -169,6 +169,29 @@ inline WorldLayerMapSelection select_world_layer_map(
|
||||
return result;
|
||||
}
|
||||
|
||||
// A TOD_<n>_<name> layer (or a lighting tier's <tier>_TOD_<n>_<name>): one time of day among its siblings.
|
||||
inline bool world_layer_time_of_day(std::size_t slot) {
|
||||
const auto& bundle = world_layer_nodes()[slot].bundle;
|
||||
auto leaf = bundle.substr(bundle.find_last_of('/') + 1);
|
||||
for (auto& c : leaf) if (c >= 'A' && c <= 'Z') c = static_cast<char>(c + ('a' - 'A'));
|
||||
const auto mid = leaf.find("_tod_");
|
||||
const auto at = leaf.starts_with("tod_") ? 4 : mid == std::string::npos ? leaf.size() : mid + 5;
|
||||
return at < leaf.size() && leaf[at] >= '1' && leaf[at] <= '9';
|
||||
}
|
||||
|
||||
// A sibling time of day that is to be off but not fully unloaded yet, which `slot` must wait for;
|
||||
// world_layer_nodes().size() when there is none.
|
||||
template <class FullyOff>
|
||||
std::size_t world_layer_old_time_of_day(std::size_t slot, const std::vector<std::optional<bool>>& desired, FullyOff&& fully_off) {
|
||||
const auto& nodes = world_layer_nodes();
|
||||
if (!world_layer_time_of_day(slot)) return nodes.size();
|
||||
for (std::size_t at = 0; at < nodes.size(); ++at)
|
||||
if (at != slot && nodes[at].parent == nodes[slot].parent && nodes[at].map == nodes[slot].map &&
|
||||
desired[at] == false && world_layer_time_of_day(at) && !fully_off(at))
|
||||
return at;
|
||||
return nodes.size();
|
||||
}
|
||||
|
||||
inline bool world_layer_supported(
|
||||
std::size_t choice,
|
||||
const std::vector<bool>& present) noexcept {
|
||||
|
||||
@@ -171,8 +171,9 @@ bool ensure_seasonal_state(std::uintptr_t entity, bool wanted, std::uint64_t now
|
||||
}
|
||||
if (reached(wanted)) return true;
|
||||
// An engine-initiated auto-load is still in flight. Wait for it rather than
|
||||
// claiming success from a non-null request handle or repeatedly reloading.
|
||||
if (wanted && state.requested) { status = "Loading..."; return false; }
|
||||
// claiming success from a non-null request handle, repeatedly reloading, or
|
||||
// unloading it midway (the engine ignores that unload and finishes the load).
|
||||
if (state.requested && !state.loaded) { status = "Loading..."; return false; }
|
||||
node.pending = wanted; node.requested_at = now;
|
||||
const auto slot = node.slot;
|
||||
SeasonalEvent event{local_runtime().base + addr::world_layers::subworld_event_vtable, wanted ? 0xd27bc17eu : 0x21f3f677u};
|
||||
@@ -309,6 +310,10 @@ void update_world_layers(std::uintptr_t manager, std::uint64_t now) {
|
||||
std::vector<bool> done(targets.size()), inactive(targets.size());
|
||||
std::vector<std::string> status(targets.size(), "Waiting for layer");
|
||||
bool issued{};
|
||||
const auto fully_off = [&](std::size_t at) {
|
||||
SeasonalState live;
|
||||
return !targets[at] || (seasonal_state(r.nodes.at(targets[at]), live) && !live.requested && !live.loaded);
|
||||
};
|
||||
for (unsigned slot = 0; slot < targets.size(); ++slot) {
|
||||
if (world_layer_nodes()[slot].map != map) continue;
|
||||
const auto parent = world_parent(static_cast<int>(slot));
|
||||
@@ -323,7 +328,12 @@ void update_world_layers(std::uintptr_t manager, std::uint64_t now) {
|
||||
if (!targets[slot]) continue;
|
||||
SeasonalState state;
|
||||
if (!seasonal_state(r.nodes.at(targets[slot]), state)) continue;
|
||||
if (!desired[slot]) {
|
||||
// Two times of day loaded at once can overflow the engine's light tables: the old one goes first.
|
||||
const auto old = desired[slot] == true && !state.requested ? world_layer_old_time_of_day(slot, desired, fully_off) : targets.size();
|
||||
if (old < targets.size()) {
|
||||
status[slot] = "Waiting for the old time of day";
|
||||
(void)ensure_seasonal_state(targets[old], false, now, issued, status[old]);
|
||||
} else if (!desired[slot]) {
|
||||
done[slot] = state.requested == state.loaded;
|
||||
inactive[slot] = done[slot] && !state.loaded;
|
||||
status[slot] = done[slot] ? "Default" : "Loading...";
|
||||
|
||||
Reference in new issue
Block a user