diff --git a/README.md b/README.md index 3cc0be09e..5846a9783 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,7 @@ Some can be changed in the key config dialog in the settings tab. | + | Increase view range | | - | Decrease view range | | K | Enable/disable fly mode (needs fly privilege) | +| L | Enable/disable pitch fly mode | | J | Enable/disable fast mode (needs fast privilege) | | H | Enable/disable noclip mode (needs noclip privilege) | | E | Move fast in fast mode | diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 950de5d1c..3effd694a 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -72,6 +72,9 @@ enable_build_where_you_stand (Build inside player) bool false # This requires the "fly" privilege on the server. free_move (Flying) bool false +# If enabled together with fly mode, makes move directions relative to the player's pitch. +pitch_fly (Pitch fly mode) bool false + # Fast movement (via the "special" key). # This requires the "fast" privilege on the server. fast_move (Fast movement) bool false @@ -208,6 +211,10 @@ keymap_rangeselect (Range select key) key KEY_KEY_R # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 keymap_freemove (Fly key) key KEY_KEY_K +# Key for toggling pitch fly mode. +# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 +keymap_pitchfly (Pitch fly key) key KEY_KEY_L + # Key for toggling fast mode. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 keymap_fastmove (Fast key) key KEY_KEY_J diff --git a/minetest.conf.example b/minetest.conf.example index ccb57520c..173b85c70 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -26,6 +26,10 @@ # type: bool # free_move = false +# If enabled together with fly mode, makes move directions relative to the player's pitch. +# type: bool +# pitch_fly = false + # Fast movement (via the "special" key). # This requires the "fast" privilege on the server. # type: bool @@ -194,6 +198,11 @@ # type: key # keymap_freemove = KEY_KEY_K +# Key for toggling pitch fly mode. +# See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 +# type: key +# keymap_pitchfly = KEY_KEY_L + # Key for toggling fast mode. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 # type: key diff --git a/src/client/game.cpp b/src/client/game.cpp index 6cf6723e9..418b412fa 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -701,6 +701,7 @@ protected: void openConsole(float scale, const wchar_t *line=NULL); void toggleFreeMove(); void toggleFreeMoveAlt(); + void togglePitchFly(); void toggleFast(); void toggleNoClip(); void toggleCinematic(); @@ -1896,6 +1897,8 @@ void Game::processKeyInput() toggleFreeMove(); } else if (wasKeyDown(KeyType::JUMP)) { toggleFreeMoveAlt(); + } else if (wasKeyDown(KeyType::PITCHFLY)) { + togglePitchFly(); } else if (wasKeyDown(KeyType::FASTMOVE)) { toggleFast(); } else if (wasKeyDown(KeyType::NOCLIP)) { @@ -2107,6 +2110,19 @@ void Game::toggleFreeMoveAlt() } +void Game::togglePitchFly() +{ + bool pitch_fly = !g_settings->getBool("pitch_fly"); + g_settings->set("pitch_fly", bool_to_cstr(pitch_fly)); + + if (pitch_fly) { + m_game_ui->showTranslatedStatusText("Pitch fly mode enabled"); + } else { + m_game_ui->showTranslatedStatusText("Pitch fly mode disabled"); + } +} + + void Game::toggleFast() { bool fast_move = !g_settings->getBool("fast_move"); diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index e465c018a..29c68cf01 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -47,6 +47,7 @@ void KeyCache::populate() key[KeyType::CONSOLE] = getKeySetting("keymap_console"); key[KeyType::MINIMAP] = getKeySetting("keymap_minimap"); key[KeyType::FREEMOVE] = getKeySetting("keymap_freemove"); + key[KeyType::PITCHFLY] = getKeySetting("keymap_pitchfly"); key[KeyType::FASTMOVE] = getKeySetting("keymap_fastmove"); key[KeyType::NOCLIP] = getKeySetting("keymap_noclip"); key[KeyType::HOTBAR_PREV] = getKeySetting("keymap_hotbar_previous"); diff --git a/src/client/keys.h b/src/client/keys.h index e7ef5f456..15e46293c 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -47,6 +47,7 @@ public: CONSOLE, MINIMAP, FREEMOVE, + PITCHFLY, FASTMOVE, NOCLIP, HOTBAR_PREV, diff --git a/src/client/localplayer.cpp b/src/client/localplayer.cpp index 1c65d3b4d..c15c90931 100644 --- a/src/client/localplayer.cpp +++ b/src/client/localplayer.cpp @@ -481,9 +481,9 @@ void LocalPlayer::applyControl(float dtime, Environment *env) PlayerSettings &player_settings = getPlayerSettings(); - v3f move_direction = v3f(0,0,1); - move_direction.rotateXZBy(getYaw()); - + // All vectors are relative to the player's yaw, + // (and pitch if pitch fly mode enabled), + // and will be rotated at the end v3f speedH = v3f(0,0,0); // Horizontal (X, Z) v3f speedV = v3f(0,0,0); // Vertical (Y) @@ -492,6 +492,7 @@ void LocalPlayer::applyControl(float dtime, Environment *env) bool free_move = fly_allowed && player_settings.free_move; bool fast_move = fast_allowed && player_settings.fast_move; + bool pitch_fly = free_move && player_settings.pitch_fly; // When aux1_descends is enabled the fast key is used to go down, so fast isn't possible bool fast_climb = fast_move && control.aux1 && !player_settings.aux1_descends; bool continuous_forward = player_settings.continuous_forward; @@ -582,31 +583,31 @@ void LocalPlayer::applyControl(float dtime, Environment *env) } if (continuous_forward) - speedH += move_direction; + speedH += v3f(0,0,1); if (control.up) { if (continuous_forward) { if (fast_move) superspeed = true; } else { - speedH += move_direction; + speedH += v3f(0,0,1); } } if (control.down) { - speedH -= move_direction; + speedH -= v3f(0,0,1); } if (!control.up && !control.down) { - speedH -= move_direction * + speedH -= v3f(0,0,1) * (control.forw_move_joystick_axis / 32767.f); } if (control.left) { - speedH += move_direction.crossProduct(v3f(0,1,0)); + speedH += v3f(-1,0,0); } if (control.right) { - speedH += move_direction.crossProduct(v3f(0,-1,0)); + speedH += v3f(1,0,0); } if (!control.left && !control.right) { - speedH -= move_direction.crossProduct(v3f(0,1,0)) * + speedH += v3f(1,0,0) * (control.sidew_move_joystick_axis / 32767.f); } if(control.jump) @@ -685,10 +686,9 @@ void LocalPlayer::applyControl(float dtime, Environment *env) slip_factor = getSlipFactor(env, speedH); // Accelerate to target speed with maximum increment - accelerateHorizontal(speedH * physics_override_speed, - incH * physics_override_speed * slip_factor); - accelerateVertical(speedV * physics_override_speed, - incV * physics_override_speed); + accelerate((speedH + speedV) * physics_override_speed, + incH * physics_override_speed * slip_factor, incV * physics_override_speed, + pitch_fly); } v3s16 LocalPlayer::getStandingNodePos() @@ -725,38 +725,46 @@ v3f LocalPlayer::getEyeOffset() const return v3f(0, BS * eye_height, 0); } -// Horizontal acceleration (X and Z), Y direction is ignored -void LocalPlayer::accelerateHorizontal(const v3f &target_speed, - const f32 max_increase) +// 3D acceleration +void LocalPlayer::accelerate(const v3f &target_speed, const f32 max_increase_H, + const f32 max_increase_V, const bool use_pitch) { - if (max_increase == 0) - return; + const f32 yaw = getYaw(); + const f32 pitch = getPitch(); + v3f flat_speed = m_speed; + // Rotate speed vector by -yaw and -pitch to make it relative to the player's yaw and pitch + flat_speed.rotateXZBy(-yaw); + if (use_pitch) + flat_speed.rotateYZBy(-pitch); - v3f d_wanted = target_speed - m_speed; - d_wanted.Y = 0.0f; - f32 dl = d_wanted.getLength(); - if (dl > max_increase) - dl = max_increase; + v3f d_wanted = target_speed - flat_speed; + v3f d = v3f(0,0,0); - v3f d = d_wanted.normalize() * dl; + // Then compare the horizontal and vertical components with the wanted speed + if (max_increase_H > 0) { + v3f d_wanted_H = d_wanted * v3f(1,0,1); + if (d_wanted_H.getLength() > max_increase_H) + d += d_wanted_H.normalize() * max_increase_H; + else + d += d_wanted_H; + } - m_speed.X += d.X; - m_speed.Z += d.Z; -} + if (max_increase_V > 0) { + f32 d_wanted_V = d_wanted.Y; + if (d_wanted_V > max_increase_V) + d.Y += max_increase_V; + else if (d_wanted_V < -max_increase_V) + d.Y -= max_increase_V; + else + d.Y += d_wanted_V; + } -// Vertical acceleration (Y), X and Z directions are ignored -void LocalPlayer::accelerateVertical(const v3f &target_speed, const f32 max_increase) -{ - if (max_increase == 0) - return; + // Finally rotate it again + if (use_pitch) + d.rotateYZBy(pitch); + d.rotateXZBy(yaw); - f32 d_wanted = target_speed.Y - m_speed.Y; - if (d_wanted > max_increase) - d_wanted = max_increase; - else if (d_wanted < -max_increase) - d_wanted = -max_increase; - - m_speed.Y += d_wanted; + m_speed += d; } // Temporary option for old move code diff --git a/src/client/localplayer.h b/src/client/localplayer.h index 7148bc4de..28404aa01 100644 --- a/src/client/localplayer.h +++ b/src/client/localplayer.h @@ -149,8 +149,8 @@ public: bool getAutojump() const { return m_autojump; } private: - void accelerateHorizontal(const v3f &target_speed, const f32 max_increase); - void accelerateVertical(const v3f &target_speed, const f32 max_increase); + void accelerate(const v3f &target_speed, const f32 max_increase_H, + const f32 max_increase_V, const bool use_pitch); bool updateSneakNode(Map *map, const v3f &position, const v3f &sneak_max); float getSlipFactor(Environment *env, const v3f &speedH); void handleAutojump(f32 dtime, Environment *env, diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index e12ad0b3b..095ebc841 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -43,6 +43,7 @@ void set_default_settings(Settings *settings) settings->setDefault("meshgen_block_cache_size", "20"); settings->setDefault("enable_vbo", "true"); settings->setDefault("free_move", "false"); + settings->setDefault("pitch_fly", "false"); settings->setDefault("fast_move", "false"); settings->setDefault("noclip", "false"); settings->setDefault("screenshot_path", "."); @@ -80,6 +81,7 @@ void set_default_settings(Settings *settings) settings->setDefault("keymap_console", "KEY_F10"); settings->setDefault("keymap_rangeselect", "KEY_KEY_R"); settings->setDefault("keymap_freemove", "KEY_KEY_K"); + settings->setDefault("keymap_pitchfly", "KEY_KEY_L"); settings->setDefault("keymap_fastmove", "KEY_KEY_J"); settings->setDefault("keymap_noclip", "KEY_KEY_H"); settings->setDefault("keymap_hotbar_next", "KEY_KEY_N"); diff --git a/src/player.cpp b/src/player.cpp index 4b104a71b..f00eb0829 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -139,6 +139,7 @@ void Player::clearHud() void PlayerSettings::readGlobalSettings() { free_move = g_settings->getBool("free_move"); + pitch_fly = g_settings->getBool("pitch_fly"); fast_move = g_settings->getBool("fast_move"); continuous_forward = g_settings->getBool("continuous_forward"); always_fly_fast = g_settings->getBool("always_fly_fast"); diff --git a/src/player.h b/src/player.h index 674491546..9af6e5cac 100644 --- a/src/player.h +++ b/src/player.h @@ -87,6 +87,7 @@ struct PlayerControl struct PlayerSettings { bool free_move = false; + bool pitch_fly = false; bool fast_move = false; bool continuous_forward = false; bool always_fly_fast = false; @@ -94,8 +95,8 @@ struct PlayerSettings bool noclip = false; bool autojump = false; - const std::string setting_names[7] = { - "free_move", "fast_move", "continuous_forward", "always_fly_fast", + const std::string setting_names[8] = { + "free_move", "pitch_fly", "fast_move", "continuous_forward", "always_fly_fast", "aux1_descends", "noclip", "autojump" }; void readGlobalSettings();