1
0
mirror of https://github.com/minetest/minetest.git synced 2024-11-13 22:10:28 +01:00

New physics overrides (#11465)

This commit is contained in:
Wuzzy 2023-09-15 20:10:08 +02:00 committed by GitHub
parent 2479d51cc6
commit 8ebaf753d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 148 additions and 22 deletions

View File

@ -7693,16 +7693,44 @@ child will follow movement and rotation of that bone.
* 9 - zoom
* Returns `0` (no bits set) if the object is not a player.
* `set_physics_override(override_table)`
* Overrides the physics attributes of the player
* `override_table` is a table with the following fields:
* `speed`: multiplier to default walking speed value (default: `1`)
* `speed`: multiplier to default movement speed and acceleration values (default: `1`)
* `jump`: multiplier to default jump value (default: `1`)
* `gravity`: multiplier to default gravity value (default: `1`)
* `speed_climb`: multiplier to default climb speed value (default: `1`)
* Note: The actual climb speed is the product of `speed` and `speed_climb`
* `speed_crouch`: multiplier to default sneak speed value (default: `1`)
* Note: The actual sneak speed is the product of `speed` and `speed_crouch`
* `liquid_fluidity`: multiplier to liquid movement resistance value
(for nodes with `liquid_move_physics`); the higher this value, the lower the
resistance to movement. At `math.huge`, the resistance is zero and you can
move through any liquid like air. (default: `1`)
* Warning: Values below 1 are currently unsupported.
* `liquid_fluidity_smooth`: multiplier to default maximum liquid resistance value
(for nodes with `liquid_move_physics`); controls deceleration when entering
node at high speed. At higher values you come to a halt more quickly
(default: `1`)
* `liquid_sink`: multiplier to default liquid sinking speed value;
(for nodes with `liquid_move_physics`) (default: `1`)
* `acceleration_default`: multiplier to horizontal and vertical acceleration
on ground or when climbing (default: `1`)
* Note: The actual acceleration is the product of `speed` and `acceleration_default`
* `acceleration_air`: multiplier to acceleration
when jumping or falling (default: `1`)
* Note: The actual acceleration is the product of `speed` and `acceleration_air`
* `sneak`: whether player can sneak (default: `true`)
* `sneak_glitch`: whether player can use the new move code replications
of the old sneak side-effects: sneak ladders and 2 node sneak jump
(default: `false`)
* `new_move`: use new move/sneak code. When `false` the exact old code
is used for the specific old sneak behavior (default: `true`)
* Note: All numeric fields above modify a corresponding `movement_*` setting.
* For games, we recommend for simpler code to first modify the `movement_*`
settings (e.g. via the game's `minetest.conf`) to set a global base value
for all players and only use `set_physics_override` when you need to change
from the base value on a per-player basis
* `get_physics_override()`: returns the table given to `set_physics_override`
* `hud_add(hud definition)`: add a HUD element described by HUD def, returns ID
number on success

View File

@ -208,7 +208,7 @@ void ClientEnvironment::step(float dtime)
!lplayer->swimming_vertical &&
!lplayer->swimming_pitch)
// HACK the factor 2 for gravity is arbitrary and should be removed eventually
lplayer->gravity = 2 * lplayer->movement_liquid_sink;
lplayer->gravity = 2 * lplayer->movement_liquid_sink * lplayer->physics_override.liquid_sink;
// Movement resistance
if (lplayer->move_resistance > 0) {
@ -218,20 +218,22 @@ void ClientEnvironment::step(float dtime)
// between 0 and 1. Should match the scale at which liquid_viscosity
// increase affects other liquid attributes.
static const f32 resistance_factor = 0.3f;
float fluidity = lplayer->movement_liquid_fluidity;
fluidity *= MYMAX(1.0f, lplayer->physics_override.liquid_fluidity);
fluidity = MYMAX(0.001f, fluidity); // prevent division by 0
float fluidity_smooth = lplayer->movement_liquid_fluidity_smooth;
fluidity_smooth *= lplayer->physics_override.liquid_fluidity_smooth;
fluidity_smooth = MYMAX(0.0f, fluidity_smooth);
v3f d_wanted;
bool in_liquid_stable = lplayer->in_liquid_stable || lplayer->in_liquid;
if (in_liquid_stable) {
d_wanted = -speed / lplayer->movement_liquid_fluidity;
} else {
if (in_liquid_stable)
d_wanted = -speed / fluidity;
else
d_wanted = -speed / BS;
}
f32 dl = d_wanted.getLength();
if (in_liquid_stable) {
if (dl > lplayer->movement_liquid_fluidity_smooth)
dl = lplayer->movement_liquid_fluidity_smooth;
}
if (in_liquid_stable)
dl = MYMIN(dl, fluidity_smooth);
dl *= (lplayer->move_resistance * resistance_factor) +
(1 - resistance_factor);
v3f d = d_wanted.normalize() * (dl * dtime_part * 100.0f);

View File

@ -1775,6 +1775,23 @@ void GenericCAO::processMessage(const std::string &data)
bool sneak_glitch = !readU8(is);
bool new_move = !readU8(is);
float override_speed_climb = readF32(is);
float override_speed_crouch = readF32(is);
float override_liquid_fluidity = readF32(is);
float override_liquid_fluidity_smooth = readF32(is);
float override_liquid_sink = readF32(is);
float override_acceleration_default = readF32(is);
float override_acceleration_air = readF32(is);
// fallback for new overrides (since 5.8.0)
if (is.eof()) {
override_speed_climb = 1.0f;
override_speed_crouch = 1.0f;
override_liquid_fluidity = 1.0f;
override_liquid_fluidity_smooth = 1.0f;
override_liquid_sink = 1.0f;
override_acceleration_default = 1.0f;
override_acceleration_air = 1.0f;
}
if (m_is_local_player) {
auto &phys = m_env->getLocalPlayer()->physics_override;
@ -1784,6 +1801,13 @@ void GenericCAO::processMessage(const std::string &data)
phys.sneak = sneak;
phys.sneak_glitch = sneak_glitch;
phys.new_move = new_move;
phys.speed_climb = override_speed_climb;
phys.speed_crouch = override_speed_crouch;
phys.liquid_fluidity = override_liquid_fluidity;
phys.liquid_fluidity_smooth = override_liquid_fluidity_smooth;
phys.liquid_sink = override_liquid_sink;
phys.acceleration_default = override_acceleration_default;
phys.acceleration_air = override_acceleration_air;
}
} else if (cmd == AO_CMD_SET_ANIMATION) {
// TODO: change frames send as v2s32 value

View File

@ -557,7 +557,7 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
speedV.Y = -movement_speed_walk;
swimming_vertical = true;
} else if (is_climbing && !m_disable_descend) {
speedV.Y = -movement_speed_climb;
speedV.Y = -movement_speed_climb * physics_override.speed_climb;
} else {
// If not free movement but fast is allowed, aux1 is
// "Turbo button"
@ -595,7 +595,7 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
if (fast_climb)
speedV.Y = -movement_speed_fast;
else
speedV.Y = -movement_speed_climb;
speedV.Y = -movement_speed_climb * physics_override.speed_climb;
}
}
}
@ -647,7 +647,7 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
if (fast_climb)
speedV.Y = movement_speed_fast;
else
speedV.Y = movement_speed_climb;
speedV.Y = movement_speed_climb * physics_override.speed_climb;
}
}
@ -656,7 +656,7 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
((in_liquid || in_liquid_stable) && fast_climb))
speedH = speedH.normalize() * movement_speed_fast;
else if (control.sneak && !free_move && !in_liquid && !in_liquid_stable)
speedH = speedH.normalize() * movement_speed_crouch;
speedH = speedH.normalize() * movement_speed_crouch * physics_override.speed_crouch;
else
speedH = speedH.normalize() * movement_speed_walk;
@ -671,13 +671,13 @@ void LocalPlayer::applyControl(float dtime, Environment *env)
if (superspeed || (fast_move && control.aux1))
incH = movement_acceleration_fast * BS * dtime;
else
incH = movement_acceleration_air * BS * dtime;
incH = movement_acceleration_air * physics_override.acceleration_air * BS * dtime;
incV = 0.0f; // No vertical acceleration in air
} else if (superspeed || (is_climbing && fast_climb) ||
((in_liquid || in_liquid_stable) && fast_climb)) {
incH = incV = movement_acceleration_fast * BS * dtime;
} else {
incH = incV = movement_acceleration_default * BS * dtime;
incH = incV = movement_acceleration_default * physics_override.acceleration_default * BS * dtime;
}
float slip_factor = 1.0f;

View File

@ -106,6 +106,14 @@ struct PlayerPhysicsOverride
bool sneak_glitch = false;
// "Temporary" option for old move code
bool new_move = true;
float speed_climb = 1.f;
float speed_crouch = 1.f;
float liquid_fluidity = 1.f;
float liquid_fluidity_smooth = 1.f;
float liquid_sink = 1.f;
float acceleration_default = 1.f;
float acceleration_air = 1.f;
};
struct PlayerSettings

View File

@ -177,6 +177,27 @@ int LuaLocalPlayer::l_get_physics_override(lua_State *L)
lua_pushboolean(L, phys.new_move);
lua_setfield(L, -2, "new_move");
lua_pushnumber(L, phys.speed_climb);
lua_setfield(L, -2, "speed_climb");
lua_pushnumber(L, phys.speed_crouch);
lua_setfield(L, -2, "speed_crouch");
lua_pushnumber(L, phys.liquid_fluidity);
lua_setfield(L, -2, "liquid_fluidity");
lua_pushnumber(L, phys.liquid_fluidity_smooth);
lua_setfield(L, -2, "liquid_fluidity_smooth");
lua_pushnumber(L, phys.liquid_sink);
lua_setfield(L, -2, "liquid_sink");
lua_pushnumber(L, phys.acceleration_default);
lua_setfield(L, -2, "acceleration_default");
lua_pushnumber(L, phys.acceleration_air);
lua_setfield(L, -2, "acceleration_air");
return 1;
}

View File

@ -1435,6 +1435,13 @@ int ObjectRef::l_set_physics_override(lua_State *L)
modified |= getboolfield(L, 2, "sneak", phys.sneak);
modified |= getboolfield(L, 2, "sneak_glitch", phys.sneak_glitch);
modified |= getboolfield(L, 2, "new_move", phys.new_move);
modified |= getfloatfield(L, 2, "speed_climb", phys.speed_climb);
modified |= getfloatfield(L, 2, "speed_crouch", phys.speed_crouch);
modified |= getfloatfield(L, 2, "liquid_fluidity", phys.liquid_fluidity);
modified |= getfloatfield(L, 2, "liquid_fluidity_smooth", phys.liquid_fluidity_smooth);
modified |= getfloatfield(L, 2, "liquid_sink", phys.liquid_sink);
modified |= getfloatfield(L, 2, "acceleration_default", phys.acceleration_default);
modified |= getfloatfield(L, 2, "acceleration_air", phys.acceleration_air);
if (modified)
playersao->m_physics_override_sent = false;
} else {
@ -1481,6 +1488,20 @@ int ObjectRef::l_get_physics_override(lua_State *L)
lua_setfield(L, -2, "sneak_glitch");
lua_pushboolean(L, phys.new_move);
lua_setfield(L, -2, "new_move");
lua_pushnumber(L, phys.speed_climb);
lua_setfield(L, -2, "speed_climb");
lua_pushnumber(L, phys.speed_crouch);
lua_setfield(L, -2, "speed_crouch");
lua_pushnumber(L, phys.liquid_fluidity);
lua_setfield(L, -2, "liquid_fluidity");
lua_pushnumber(L, phys.liquid_fluidity_smooth);
lua_setfield(L, -2, "liquid_fluidity_smooth");
lua_pushnumber(L, phys.liquid_sink);
lua_setfield(L, -2, "liquid_sink");
lua_pushnumber(L, phys.acceleration_default);
lua_setfield(L, -2, "acceleration_default");
lua_pushnumber(L, phys.acceleration_air);
lua_setfield(L, -2, "acceleration_air");
return 1;
}

View File

@ -325,6 +325,14 @@ std::string PlayerSAO::generateUpdatePhysicsOverrideCommand() const
writeU8(os, !phys.sneak);
writeU8(os, !phys.sneak_glitch);
writeU8(os, !phys.new_move);
// new physics overrides since 5.8.0
writeF32(os, phys.speed_climb);
writeF32(os, phys.speed_crouch);
writeF32(os, phys.liquid_fluidity);
writeF32(os, phys.liquid_fluidity_smooth);
writeF32(os, phys.liquid_sink);
writeF32(os, phys.acceleration_default);
writeF32(os, phys.acceleration_air);
return os.str();
}
@ -609,17 +617,31 @@ bool PlayerSAO::checkMovementCheat()
float player_max_walk = 0; // horizontal movement
float player_max_jump = 0; // vertical upwards movement
if (m_privs.count("fast") != 0)
player_max_walk = m_player->movement_speed_fast; // Fast speed
else
player_max_walk = m_player->movement_speed_walk; // Normal speed
player_max_walk *= m_player->physics_override.speed;
float speed_walk = m_player->movement_speed_walk * m_player->physics_override.speed;
float speed_fast = m_player->movement_speed_fast;
float speed_crouch = m_player->movement_speed_crouch * m_player->physics_override.speed_crouch;
// Get permissible max. speed
if (m_privs.count("fast") != 0) {
// Fast priv: Get the highest speed of fast, walk or crouch
// (it is not forbidden the 'fast' speed is
// not actually the fastest)
player_max_walk = MYMAX(speed_crouch, speed_fast);
player_max_walk = MYMAX(player_max_walk, speed_walk);
} else {
// Get the highest speed of walk or crouch
// (it is not forbidden the 'walk' speed is
// lower than the crouch speed)
player_max_walk = MYMAX(speed_crouch, speed_walk);
}
player_max_walk = MYMAX(player_max_walk, override_max_H);
player_max_jump = m_player->movement_speed_jump * m_player->physics_override.jump;
// FIXME: Bouncy nodes cause practically unbound increase in Y speed,
// until this can be verified correctly, tolerate higher jumping speeds
player_max_jump *= 2.0;
player_max_jump = MYMAX(player_max_jump, m_player->movement_speed_climb * m_player->physics_override.speed_climb);
player_max_jump = MYMAX(player_max_jump, override_max_V);
// Don't divide by zero!