Skip to content

Commit

Permalink
Speedometer (#16)
Browse files Browse the repository at this point in the history
* speedometer

* bump version
  • Loading branch information
Pistonight authored Sep 8, 2024
1 parent 3dcdd4a commit 7eacc09
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ tasks:
package:
desc: Package the build for release
vars:
VERSION: "SS2.1"
VERSION: "SS2.2"
MOD_DIR: "target/package/mods/The Legend of Zelda - Breath of the Wild/Save State/contents/01007EF00011E000"
cmds:
- megaton -p none
Expand Down
57 changes: 51 additions & 6 deletions src/core/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <toolkit/tcp.hpp>

#include "core/controller.hpp"
#include "core/time.hpp"

namespace botw::savs {

Expand Down Expand Up @@ -67,9 +68,7 @@ bool Controller::has_held_keys_for(Key keys, u32 seconds) {
} else {
m_hold_counter++;
}
// 1 tick = 3 frames
// 1s = 30 frames = 10 ticks
u32 ticks = seconds * 10;
u32 ticks = time::secs_to_ticks(seconds);
if (m_hold_counter >= ticks) {
m_hold_counter = 0;
return true;
Expand Down Expand Up @@ -193,6 +192,10 @@ Command Controller::update_setting_mode() {
m_mode = Mode::SettingStateOption;
m_menu_current_option = 0;
break;
default:
m_mode = Mode::SettingOtherFunction;
m_menu_current_option = 0;
break;
}
refresh_menu();
return Command::None;
Expand Down Expand Up @@ -302,6 +305,39 @@ Command Controller::update_setting_mode() {
return Command::SaveOption;
}
break;
case Mode::SettingOtherFunction:
if (is_only_holding(Key::B)) {
m_mode = Mode::SettingHome;
m_menu_current_option = 2;
refresh_menu();
return Command::None;
}
if (is_only_holding(Key::X)) {
m_menu_showing_explain_message = true;
m_tick_since_last_menu_input = 0;
switch (m_menu_current_option) {
// clang-format off
case 0:// ----------------------------------MAX
msg::widget::print("Speedometer\n\n"
"When enabled, display the speed\n"
"every tick.");
break;
}
// clang-format on
}
if (is_only_holding(Key::A)) {
bool value;
switch (m_menu_current_option) {
case 0:
value = !m_config->m_speedometer;
msg::info::printf("Speedometer: %s", get_enabled_text(value));
m_config->m_speedometer = value;
break;
}
refresh_menu();
return Command::SaveOption;
}
break;
}

return Command::None;
Expand Down Expand Up @@ -335,14 +371,13 @@ void Controller::refresh_menu() {
m_menu_showing_explain_message = false;
m_tick_since_last_menu_input = 0;
switch (m_mode) {
case Mode::Active:
return;
case Mode::SettingHome:
m_menu_title.copy("Save State Settings");
m_menu_subtitle.copy("What do you want to do?");
m_menu_options_count = 2;
m_menu_options_count = 3;
m_menu_options[0].copy("Change Key Binding");
m_menu_options[1].copy("Change State Options");
m_menu_options[2].copy("Other Functions");
break;
case Mode::SettingKeyBinding:
if (is_configuring_key()) {
Expand Down Expand Up @@ -372,6 +407,16 @@ void Controller::refresh_menu() {
m_menu_options[2].appendf(
"[%s] Inventory", get_toggle_text(m_config->m_enable_inventory));
break;
case Mode::SettingOtherFunction:
m_menu_title.copy("Other Functions");
m_menu_subtitle.copy("[A] Toggle; [X] Explain");
m_menu_options_count = 1;
m_menu_options[0].clear();
m_menu_options[0].appendf("[%s] Speedometer",
get_toggle_text(m_config->m_speedometer));
break;
default:
return;
}
if (m_menu_current_option >= m_menu_options_count) {
m_menu_current_option = 0;
Expand Down
2 changes: 2 additions & 0 deletions src/core/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class Controller {
SettingHome,
SettingKeyBinding,
SettingStateOption,
SettingOtherFunction,
};

bool initialize();
Expand All @@ -136,6 +137,7 @@ class Controller {
void load_key_bindings(io::DataReader& reader);

Mode get_mode() const { return m_mode; }
bool is_in_settings() const { return m_mode != Mode::Active; }

public:
StateConfig* m_config = nullptr;
Expand Down
7 changes: 6 additions & 1 deletion src/core/state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,20 @@ void StateConfig::save_config(io::DataWriter& w) const {
bool unused = false;
w.write_bool(_named(unused));
w.write_bool(_named(m_enable_inventory));
w.write_bool(_named(m_speedometer));
}

void StateConfig::read_config(io::DataReader& r) {
void StateConfig::read_config(io::DataReader& r, u32 version) {
r.read_bool(&m_show_restore_message);
r.read_bool(&m_enable_timers);
// was overworld durability in v5
bool unused;
r.read_bool(&unused);
r.read_bool(&m_enable_inventory);

if (version >= Version::v7) {
r.read_bool(&m_speedometer);
}
}

void State::read_from_game(Reporter& r, const StateConfig& config) {
Expand Down
4 changes: 3 additions & 1 deletion src/core/state.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ enum class StateFileResult {
class StateConfig {
public:
void save_config(io::DataWriter& w) const;
void read_config(io::DataReader& r);
void read_config(io::DataReader& r, u32 version);
// show info message when restoring
bool m_show_restore_message = true;
// enable TOD, bloodmoon, ability, master sword, potion, and climate damage
Expand All @@ -28,6 +28,8 @@ class StateConfig {
// enable restoring inventory state, including full pmdm and num offset
// slots
bool m_enable_inventory = false;
// enable displaying the speed on every tick
bool m_speedometer = false;
};

class State {
Expand Down
19 changes: 19 additions & 0 deletions src/core/time.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <exl/types.h>

namespace botw::savs::time {

inline float ticks_to_secs_f32(u32 ticks) {
// 1 tick = 3 frames
// 1s = 30 frames = 10 ticks
return ticks / 10.0F;
}

inline u32 secs_to_ticks(u32 secs) {
// 1 tick = 3 frames
// 1s = 30 frames = 10 ticks
return secs * 10;
}

} // namespace botw::savs::time
3 changes: 2 additions & 1 deletion src/core/version.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ enum Version {
vLegacy = 4, // no longer supported
v5 = 5,
v6 = 6,
vLatest = v6
v7 = 7,
vLatest = v7
};
}
57 changes: 51 additions & 6 deletions src/core/worker.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <Game/UI/uiPauseMenuDataMgr.h>
#include <KingSystem/ActorSystem/actActorSystem.h>
#include <KingSystem/ActorSystem/actBaseProcMgr.h>
#include <cstdlib>
#include <nn/os.h>
Expand All @@ -11,6 +12,7 @@
#include <toolkit/tcp.hpp>

#include "core/reporter.hpp"
#include "core/time.hpp"
#include "core/version.hpp"
#include "core/worker.hpp"
#include "impl/raw_ptr.hpp"
Expand Down Expand Up @@ -54,6 +56,7 @@ void start_worker_thread() {

void Worker::do_work() {
welcome();
tick_update();
Command command = m_controller.update();
switch (command) {
case Command::Save:
Expand Down Expand Up @@ -124,7 +127,7 @@ void Worker::load_options() {
}

StateConfig temp_config;
temp_config.read_config(reader);
temp_config.read_config(reader, version);
if (reader.is_successful()) {
m_config = temp_config;
}
Expand Down Expand Up @@ -238,11 +241,53 @@ void Worker::execute_restore_file() {
}

bool Worker::show_active_mode_message() const {
return msg::widget::printf("\
Settings exited.\n\
You can use the save state now\n\
Hold All Triggers + Dpad Down\n\
to open Settings again");
// clang-format off
// ----------------------------------MAX
return msg::widget::print("Settings exited\n\n"
"You can use the save state now\n"
"Hold All Triggers + Dpad Down\n"
"to open Settings again");
// clang-format on
}

void Worker::tick_update() {
if (m_controller.is_in_settings()) {
return;
}
if (!m_showed_welcome) {
// only update after showing welcome message
// since we are reusing variables
return;
}
if (m_config.m_speedometer) {
// for some reason, ActorSystem::getPlayerPos() doesn't work
float new_pos[3];
if (!raw_ptr::havok_position().get_array(new_pos, 3)) {
tcp::sendf("failed to get player pos\n");
return;
}
// we can't use nn::time because the resolution is 1s
f32 secs = time::ticks_to_secs_f32(1);
f32 dx = new_pos[0] - m_player_pos[0];
f32 dy = new_pos[1] - m_player_pos[1];
f32 dz = new_pos[2] - m_player_pos[2];
m_player_pos[0] = new_pos[0];
m_player_pos[1] = new_pos[1];
m_player_pos[2] = new_pos[2];
bool pos_diff =
std::abs(dx) > 0.1 || std::abs(dz) > 0.1 || std::abs(dy) > 0.1;
if (!pos_diff) {
tcp::sendf("pos diff too small\n");
return;
}
tcp::sendf("pos: %.2f %.2f %.2f, d: %.2f %.2f %.2f\n", new_pos[0],
new_pos[1], new_pos[2], dx, dy, dz);
f32 xsq_zsq = dx * dx + dz * dz;
f32 horizontal_speed = std::sqrt(xsq_zsq) / secs;
f32 true_speed = std::sqrt(dy * dy + xsq_zsq) / secs;
msg::info::printf("HS: %.2f m/s | TS: %.2f m/s", horizontal_speed,
true_speed);
}
}

void Worker::welcome() {
Expand Down
2 changes: 2 additions & 0 deletions src/core/worker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class Worker {
bool m_showed_welcome = false;
float m_player_pos[3]{0, 0, 0};
u32 m_pos_diff_ticks = 0;
u64 m_last_timestamp = 0;

State m_memory_state;
State m_last_restored_file;
Expand All @@ -56,6 +57,7 @@ class Worker {

StateConfig m_config;

void tick_update();
bool show_active_mode_message() const;
void welcome();
};
Expand Down

0 comments on commit 7eacc09

Please sign in to comment.