mirror of
https://github.com/minetest/minetest.git
synced 2024-08-18 20:44:16 +02:00
New physics overrides (#11465)
This commit is contained in:
parent
2479d51cc6
commit
8ebaf753d3
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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!
|
||||
|
Loading…
Reference in New Issue
Block a user