6 Commits

Author SHA1 Message Date
cabc79de36 Work around wrong character bone rotations on Luanti 5.11+ (#6) 2025-02-21 09:21:21 +01:00
f763ce648e Limit angle between head and body (#5)
Fixes head turning more than 90 degrees during minor lag, which appears unnatural.
2024-02-24 11:47:14 +01:00
e0acae8ed8 Workaround for Minetest #12189 2022-04-10 12:53:25 +02:00
9dab03f544 Clear up all animations of all registered models (#1)
Disable animations for all registered models, not only for "character.b3d".
Increases compatibility to other mods
2020-09-25 19:38:44 +02:00
ae45fe4cca Fix compatibility with (upcoming) Minetest 5.3.0
But note that since bone animation was fixed in 5.3,
there is no reason to use this mod anymore.
2020-06-18 16:30:34 +02:00
41f23cf799 Autodetect the player model version, remove playeranim.model_version 2019-12-20 19:58:47 +01:00
4 changed files with 73 additions and 56 deletions

View File

@ -12,15 +12,8 @@ Created by [Rui](https://github.com/Rui-Minetest), this document was written by
### Version of player model ### Version of player model
Player models supported by this mod: Player models supported by this mod:
- `MTG_4_Jun_2017` (minetest_game after 4 Jun 2017, 0.4.16) - minetest_game after 4 Jun 2017, Minetest 0.4.16
- `MTG_4_Nov_2017` (minetest_game after 4 Nov 2017, 0.5.0) - minetest_game after 4 Nov 2017, Minetest 0.5.0-dev
As there is no automatic way to determine which version is used, this must be configured with advanced settings menu, or by manually editing `playeranim.model_version` entry in minetest.conf.
The default value is `MTG_4_Jun_2017`.
Symptoms of having configured the incorrect player model:
- In rest, arms are raised up, and are either detached from the body, or are too close to the body
- Cape (if visible) points upward
### The delay of sideways body rotation ### The delay of sideways body rotation

View File

@ -1,3 +1,8 @@
if not minetest.settings then
error("Mod playeranim requires Minetest 0.4.16 or newer")
end
local ANIMATION_SPEED = tonumber(minetest.settings:get("playeranim.animation_speed")) or 2.4 local ANIMATION_SPEED = tonumber(minetest.settings:get("playeranim.animation_speed")) or 2.4
local ANIMATION_SPEED_SNEAK = tonumber(minetest.settings:get("playeranim.animation_speed_sneak")) or 0.8 local ANIMATION_SPEED_SNEAK = tonumber(minetest.settings:get("playeranim.animation_speed_sneak")) or 0.8
local BODY_ROTATION_DELAY = math.max(math.floor(tonumber(minetest.settings:get("playeranim.body_rotation_delay")) or 7), 1) local BODY_ROTATION_DELAY = math.max(math.floor(tonumber(minetest.settings:get("playeranim.body_rotation_delay")) or 7), 1)
@ -9,11 +14,30 @@ local BONE_POSITION, BONE_ROTATION = (function()
return dofile(modpath .. "/model.lua") return dofile(modpath .. "/model.lua")
end)() end)()
local get_animation = player_api and player_api.get_animation or default.player_get_animation local get_animation = minetest.global_exists("player_api")
and player_api.get_animation or default.player_get_animation
if not get_animation then if not get_animation then
error("player_api.get_animation or default.player_get_animation is not found") error("player_api.get_animation or default.player_get_animation is not found")
end end
-- stop player_api from messing stuff up (since 5.3)
if minetest.global_exists("player_api") then
minetest.register_on_mods_loaded(function()
for _, model in pairs(player_api.registered_models) do
if model.animations then
for _, animation in pairs(model.animations) do
animation.x = 0
animation.y = 0
end
end
end
end)
minetest.register_on_joinplayer(function(player)
player:set_local_animation(nil, nil, nil, nil, 0)
end)
end
local function get_animation_speed(player) local function get_animation_speed(player)
if player:get_player_control().sneak then if player:get_player_control().sneak then
return ANIMATION_SPEED_SNEAK return ANIMATION_SPEED_SNEAK
@ -101,6 +125,17 @@ minetest.register_on_joinplayer(function(player)
players_animation_data:init_player(player) players_animation_data:init_player(player)
end) end)
-- HACK work around https://github.com/luanti-org/luanti/issues/15692
-- Scales corresponding to default perfect 180° rotations in the character b3d model
local bone_workaround_scales = {
Body = vector.new(-1, 1, -1),
Arm_Left = vector.new(1, -1, -1),
Arm_Right = vector.new(1, -1, -1),
Leg_Left = vector.new(1, -1, -1),
Leg_Right = vector.new(1, -1, -1),
Cape = vector.new(1, -1, -1),
}
local vector_add, vector_equals = vector.add, vector.equals local vector_add, vector_equals = vector.add, vector.equals
local function rotate_bone(player, bone, rotation, position_optional) local function rotate_bone(player, bone, rotation, position_optional)
local previous_rotation = players_animation_data:get_bone_rotation(player, bone) local previous_rotation = players_animation_data:get_bone_rotation(player, bone)
@ -116,9 +151,17 @@ local function rotate_bone(player, bone, rotation, position_optional)
or not previous_position or not previous_position
or not vector_equals(rotation, previous_rotation) or not vector_equals(rotation, previous_rotation)
or not vector_equals(position, previous_position) then or not vector_equals(position, previous_position) then
player:set_bone_position(bone, position, rotation) if player.set_bone_override then -- Luanti 5.9+
players_animation_data:set_bone_rotation(player, bone, rotation) player:set_bone_override(bone, {
players_animation_data:set_bone_position(player, bone, position) position = {vec = position, absolute = true},
rotation = {vec = rotation:apply(math.rad), absolute = true},
scale = {vec = bone_workaround_scales[bone], absolute = true},
})
else
player:set_bone_position(bone, position, rotation)
players_animation_data:set_bone_rotation(player, bone, rotation)
players_animation_data:set_bone_position(player, bone, position)
end
end end
end end
@ -237,7 +280,14 @@ local function rotate_body_and_head(player)
if #yaw_history > BODY_ROTATION_DELAY then if #yaw_history > BODY_ROTATION_DELAY then
local body_yaw = table_remove(yaw_history, 1) local body_yaw = table_remove(yaw_history, 1)
local player_yaw = player:get_look_horizontal() local player_yaw = player:get_look_horizontal()
return math_deg(player_yaw - body_yaw) -- Get the difference and normalize it to [-180,180) range.
-- This will give the shortest rotation between head and body angles.
local angle = ((player_yaw - body_yaw + 3.0*math_pi) % (2.0*math_pi)) - math_pi
-- Arbitrary limit of the head turn angle
local limit = math_pi*0.3 -- value from 0 to pi, less than 0.45*pi looks good
-- Clamp the value to the limit
angle = math.max(math.min(angle, limit), -limit)
return math_deg(angle)
end end
return 0 return 0
end)() end)()
@ -250,7 +300,15 @@ end
local function animate_player(player, dtime) local function animate_player(player, dtime)
local animation = get_animation(player).animation local data = get_animation(player)
if not data then
-- Minetest Engine workaround for 5.6.0-dev and older
-- minetest.register_globalstep may call to this function before the player is
-- initialized by minetest.register_on_joinplayer in player_api
return
end
local animation = data.animation
-- Yaw history -- Yaw history
if animation == "lay" or animation == "sit" then if animation == "lay" or animation == "sit" then

View File

@ -7,22 +7,8 @@ local RARM = "Arm_Right"
local LLEG = "Leg_Left" local LLEG = "Leg_Left"
local RLEG = "Leg_Right" local RLEG = "Leg_Right"
-- Version of player model
local DEFAULT_PLAYER_MODEL_VERSION = "MTG_4_Jun_2017"
local VALID_PLAYER_MODEL_VERSIONS = {
MTG_4_Jun_2017 = true,
MTG_4_Nov_2017 = true,
}
local LEGACY_PLAYER_MODEL_VERSIONS = {
default_character_v1 = true,
default_character_v2 = true,
default_character_v3 = true,
}
local BONE_POSITIONS = { local BONE_POSITIONS = {
MTG_4_Jun_2017 = { MTG_0_4_x = {
[BODY] = {x = 0, y = -3.5, z = 0}, [BODY] = {x = 0, y = -3.5, z = 0},
[HEAD] = {x = 0, y = 6.5, z = 0}, [HEAD] = {x = 0, y = 6.5, z = 0},
[CAPE] = {x = 0, y = 6.5, z = 1.2}, [CAPE] = {x = 0, y = 6.5, z = 1.2},
@ -34,7 +20,7 @@ local BONE_POSITIONS = {
body_sit = {x = 0, y = -5.5, z = 0}, body_sit = {x = 0, y = -5.5, z = 0},
body_lay = {x = 0, y = -5.5, z = 0}, body_lay = {x = 0, y = -5.5, z = 0},
}, },
MTG_4_Nov_2017 = { MTG_5_0_x = {
[BODY] = {x = 0, y = 6.25, z = 0}, [BODY] = {x = 0, y = 6.25, z = 0},
[HEAD] = {x = 0, y = 6.5, z = 0}, [HEAD] = {x = 0, y = 6.5, z = 0},
[CAPE] = {x = 0, y = 6.5, z = 1.2}, [CAPE] = {x = 0, y = 6.5, z = 1.2},
@ -49,7 +35,7 @@ local BONE_POSITIONS = {
} }
local BONE_ROTATIONS = { local BONE_ROTATIONS = {
MTG_4_Jun_2017 = { MTG_0_4_x = {
[BODY] = {x = 0, y = 0, z = 0}, [BODY] = {x = 0, y = 0, z = 0},
[HEAD] = {x = 0, y = 0, z = 0}, [HEAD] = {x = 0, y = 0, z = 0},
[CAPE] = {x = 0, y = 0, z = 0}, [CAPE] = {x = 0, y = 0, z = 0},
@ -61,7 +47,7 @@ local BONE_ROTATIONS = {
body_sit = {x = 0, y = 0, z = 0}, body_sit = {x = 0, y = 0, z = 0},
body_lay = {x = 270, y = 0, z = 0}, body_lay = {x = 270, y = 0, z = 0},
}, },
MTG_4_Nov_2017 = { MTG_5_0_x = {
[BODY] = {x = 0, y = 0, z = 0}, [BODY] = {x = 0, y = 0, z = 0},
[HEAD] = {x = 0, y = 0, z = 0}, [HEAD] = {x = 0, y = 0, z = 0},
[CAPE] = {x = 0, y = 0, z = 0}, [CAPE] = {x = 0, y = 0, z = 0},
@ -75,23 +61,10 @@ local BONE_ROTATIONS = {
}, },
} }
local PLAYER_MODEL_VERSION = (function() local model = minetest.global_exists("player_api") and "MTG_5_0_x" or "MTG_0_4_x"
local version = minetest.settings:get("playeranim.model_version")
if version == nil or version == "" then
version = DEFAULT_PLAYER_MODEL_VERSION
end
if LEGACY_PLAYER_MODEL_VERSIONS[version] then local BONE_POSITION = BONE_POSITIONS[model]
error("The model version '" .. version .. "' is no longer suppported") local BONE_ROTATION = BONE_ROTATIONS[model]
elseif not VALID_PLAYER_MODEL_VERSIONS[version] then
error("Invalid value for playeranim.model_version in minetest.conf: " .. version)
end
return version
end)()
local BONE_POSITION = BONE_POSITIONS[PLAYER_MODEL_VERSION]
local BONE_ROTATION = BONE_ROTATIONS[PLAYER_MODEL_VERSION]
if not BONE_POSITION or not BONE_ROTATION then if not BONE_POSITION or not BONE_ROTATION then
error("Internal error: invalid player_model_version: " .. PLAYER_MODEL_VERSION) error("Internal error: invalid player_model_version: " .. PLAYER_MODEL_VERSION)
end end

View File

@ -1,10 +1,3 @@
# Version of player model.
#
# Player models supported by this mod:
# . -- `MTG_4_Jun_2017` (minetest_game after 4 Jun 2017, 0.4.16)
# . -- `MTG_4_Nov_2017` (minetest_game after 4 Nov 2017, 0.5.0)
playeranim.model_version (Version of player model) enum MTG_4_Jun_2017 MTG_4_Jun_2017,MTG_4_Nov_2017
# The number of frame delay of sideways body rotation. (between 1 and 20). # The number of frame delay of sideways body rotation. (between 1 and 20).
playeranim.body_rotation_delay (The delay of sideways body rotation) int 7 1 20 playeranim.body_rotation_delay (The delay of sideways body rotation) int 7 1 20