mirror of
https://github.com/minetest-mods/playeranim.git
synced 2024-10-31 23:40:28 +01:00
Bump version to 0.4.16 (#16)
This commit is contained in:
parent
0cccb537a2
commit
05a794fe9d
|
@ -1,5 +1,5 @@
|
||||||
Copyright (c) 2013-2014, Diego Martínez
|
Copyright (c) 2013-2014, Diego Martínez
|
||||||
Copyright (c) 2016, Rui
|
Copyright (c) 2016-2018, Rui
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
47
README.md
Normal file
47
README.md
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# playeranim
|
||||||
|
|
||||||
|
Makes the head, and the right arm when you're mining, face the way you're facing, similar to Minecraft. Compatible with [3d_armor](https://github.com/stujones11/minetest-3d_armor). This is an ugly hack. Forked from [Kaeza's animplus mod](https://github.com/kaeza/minetest-animplus).
|
||||||
|
|
||||||
|
The head only turns up and down relative to the body, except it turns slightly to the right/left when you strafe right/left. When you turn the body turns with the head.
|
||||||
|
Works in both singleplayer and multiplayer.
|
||||||
|
|
||||||
|
Created by [Rui](https://github.com/Rui-Minetest), this document was written by [sloantothebone](https://github.com/sloantothebone).
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### 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)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
Configure `playeranim.body_rotation_delay`.
|
||||||
|
It's the number of frame delay of sideways body rotation.
|
||||||
|
The default value is `7`.
|
||||||
|
|
||||||
|
### Lengthways body rotation in sneaking
|
||||||
|
|
||||||
|
Configure `playeranim.body_x_rotation_sneak`.
|
||||||
|
It's the degrees of the body's X-axis rotation in sneaking.
|
||||||
|
The default value is `6.0`.
|
||||||
|
|
||||||
|
### The speed of an animation
|
||||||
|
|
||||||
|
Configure `playeranim.animation_speed`.
|
||||||
|
It's the number of stepping per seconds.
|
||||||
|
The default value is `2.4`.
|
||||||
|
|
||||||
|
### The speed of an animation in sneaking
|
||||||
|
|
||||||
|
Configure `playeranim.animation_speed_sneak`.
|
||||||
|
It's the number of stepping per seconds in sneaking.
|
||||||
|
The default value is `0.8`.
|
|
@ -1 +1,2 @@
|
||||||
default
|
default?
|
||||||
|
player_api?
|
||||||
|
|
563
init.lua
563
init.lua
|
@ -1,30 +1,126 @@
|
||||||
-- Version of player model.
|
local ANIMATION_SPEED = tonumber(minetest.settings:get("playeranim.animation_speed")) or 2.4
|
||||||
-- default_character_v1:
|
local ANIMATION_SPEED_SNEAK = tonumber(minetest.settings:get("playeranim.animation_speed_sneak")) or 0.8
|
||||||
-- minetest_game before 25 nov 2016
|
local BODY_ROTATION_DELAY = math.max(math.floor(tonumber(minetest.settings:get("playeranim.body_rotation_delay")) or 7), 1)
|
||||||
-- 3d_armor before 27 nov 2016 (overrides model from minetest_game)
|
local BODY_X_ROTATION_SNEAK = tonumber(minetest.settings:get("playeranim.body_x_rotation_sneak")) or 6.0
|
||||||
-- default_character_v2:
|
|
||||||
-- minetest_game after 25 nov 2016
|
|
||||||
-- 3d_armor after 27 nov 2016 (overrides model from minetest_game)
|
|
||||||
|
|
||||||
local valid_player_model_versions = {
|
local BONE_POSITION, BONE_ROTATION = (function()
|
||||||
default_character_v1 = true,
|
local modname = minetest.get_current_modname()
|
||||||
default_character_v2 = true,
|
local modpath = minetest.get_modpath(modname)
|
||||||
default_character_v3 = true,
|
return dofile(modpath .. "/model.lua")
|
||||||
}
|
end)()
|
||||||
|
|
||||||
local player_model_version = minetest.settings:get("player_model_version")
|
local get_animation = player_api and player_api.get_animation or default.player_get_animation
|
||||||
if not player_model_version or player_model_version == "" then
|
if not get_animation then
|
||||||
player_model_version = "default_character_v2"
|
error("player_api.get_animation or default.player_get_animation is not found")
|
||||||
elseif not valid_player_model_versions[player_model_version] then
|
|
||||||
error("Invalid value for player_model_version in minetest.conf: " .. player_model_version)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Localize to avoid table lookups
|
local function get_animation_speed(player)
|
||||||
local vector_new = vector.new
|
if player:get_player_control().sneak then
|
||||||
local math_pi = math.pi
|
return ANIMATION_SPEED_SNEAK
|
||||||
local math_sin = math.sin
|
end
|
||||||
local table_remove = table.remove
|
return ANIMATION_SPEED
|
||||||
local get_animation = default.player_get_animation
|
end
|
||||||
|
|
||||||
|
local math_deg = math.deg
|
||||||
|
local function get_pitch_deg(player)
|
||||||
|
return math_deg(player:get_look_vertical())
|
||||||
|
end
|
||||||
|
|
||||||
|
local players_animation_data = setmetatable({}, {
|
||||||
|
__index = {
|
||||||
|
init_player = function(self, player)
|
||||||
|
self[player] = {
|
||||||
|
time = 0,
|
||||||
|
yaw_history = {},
|
||||||
|
bone_rotations = {},
|
||||||
|
bone_positions = {},
|
||||||
|
previous_animation = 0,
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- time
|
||||||
|
get_time = function(self, player)
|
||||||
|
return self[player].time
|
||||||
|
end,
|
||||||
|
|
||||||
|
increment_time = function(self, player, dtime)
|
||||||
|
self[player].time = self:get_time(player) + dtime
|
||||||
|
end,
|
||||||
|
|
||||||
|
reset_time = function(self, player)
|
||||||
|
self[player].time = 0
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- yaw_history
|
||||||
|
get_yaw_history = function(self, player)
|
||||||
|
return self[player].yaw_history -- Return mutable reference
|
||||||
|
end,
|
||||||
|
|
||||||
|
add_yaw_to_history = function(self, player)
|
||||||
|
local yaw = player:get_look_horizontal()
|
||||||
|
local history = self:get_yaw_history(player)
|
||||||
|
history[#history + 1] = yaw
|
||||||
|
end,
|
||||||
|
|
||||||
|
clear_yaw_history = function(self, player)
|
||||||
|
if #self[player].yaw_history > 0 then
|
||||||
|
self[player].yaw_history = {}
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- bone_rotations
|
||||||
|
get_bone_rotation = function(self, player, bone)
|
||||||
|
return self[player].bone_rotations[bone]
|
||||||
|
end,
|
||||||
|
|
||||||
|
set_bone_rotation = function(self, player, bone, rotation)
|
||||||
|
self[player].bone_rotations[bone] = rotation
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- bone_positions
|
||||||
|
get_bone_position = function(self, player, bone)
|
||||||
|
return self[player].bone_positions[bone]
|
||||||
|
end,
|
||||||
|
|
||||||
|
set_bone_position = function(self, player, bone, position)
|
||||||
|
self[player].bone_positions[bone] = position
|
||||||
|
end,
|
||||||
|
|
||||||
|
-- previous_animation
|
||||||
|
get_previous_animation = function(self, player)
|
||||||
|
return self[player].previous_animation
|
||||||
|
end,
|
||||||
|
|
||||||
|
set_previous_animation = function(self, player, animation)
|
||||||
|
self[player].previous_animation = animation
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
players_animation_data:init_player(player)
|
||||||
|
end)
|
||||||
|
|
||||||
|
local vector_add, vector_equals = vector.add, vector.equals
|
||||||
|
local function rotate_bone(player, bone, rotation, position_optional)
|
||||||
|
local previous_rotation = players_animation_data:get_bone_rotation(player, bone)
|
||||||
|
local rotation = vector_add(rotation, BONE_ROTATION[bone])
|
||||||
|
|
||||||
|
local previous_position = players_animation_data:get_bone_position(player, bone)
|
||||||
|
local position = BONE_POSITION[bone]
|
||||||
|
if position_optional then
|
||||||
|
position = vector_add(position, position_optional)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not previous_rotation
|
||||||
|
or not previous_position
|
||||||
|
or not vector_equals(rotation, previous_rotation)
|
||||||
|
or not vector_equals(position, previous_position) then
|
||||||
|
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
|
||||||
|
|
||||||
-- Animation alias
|
-- Animation alias
|
||||||
local STAND = 1
|
local STAND = 1
|
||||||
|
@ -43,308 +139,163 @@ local RARM = "Arm_Right"
|
||||||
local LLEG = "Leg_Left"
|
local LLEG = "Leg_Left"
|
||||||
local RLEG = "Leg_Right"
|
local RLEG = "Leg_Right"
|
||||||
|
|
||||||
local bone_positions = {
|
local math_sin, math_cos, math_pi = math.sin, math.cos, math.pi
|
||||||
default_character_v1 = {
|
local ANIMATIONS = {
|
||||||
[BODY] = vector_new(0, -3.5, 0),
|
[STAND] = function(player, _time)
|
||||||
[HEAD] = vector_new(0, 6.75, 0),
|
rotate_bone(player, BODY, {x = 0, y = 0, z = 0})
|
||||||
[CAPE] = vector_new(0, 6.75, 1.1),
|
rotate_bone(player, CAPE, {x = 0, y = 0, z = 0})
|
||||||
[LARM] = vector_new(2, 6.75, 0),
|
rotate_bone(player, LARM, {x = 0, y = 0, z = 0})
|
||||||
[RARM] = vector_new(-2, 6.75, 0),
|
rotate_bone(player, RARM, {x = 0, y = 0, z = 0})
|
||||||
[LLEG] = vector_new(-1, 0, 0),
|
rotate_bone(player, LLEG, {x = 0, y = 0, z = 0})
|
||||||
[RLEG] = vector_new(1, 0, 0)
|
rotate_bone(player, RLEG, {x = 0, y = 0, z = 0})
|
||||||
},
|
end,
|
||||||
default_character_v2 = {
|
|
||||||
[BODY] = vector_new(0, -3.5, 0),
|
[LAY] = function(player, _time)
|
||||||
[HEAD] = vector_new(0, 6.75, 0),
|
rotate_bone(player, HEAD, {x = 0, y = 0, z = 0})
|
||||||
[CAPE] = vector_new(0, 6.75, 1.2),
|
rotate_bone(player, CAPE, {x = 0, y = 0, z = 0})
|
||||||
[LARM] = vector_new(3, 5.75, 0),
|
rotate_bone(player, LARM, {x = 0, y = 0, z = 0})
|
||||||
[RARM] = vector_new(-3, 5.75, 0),
|
rotate_bone(player, RARM, {x = 0, y = 0, z = 0})
|
||||||
[LLEG] = vector_new(1, 0, 0),
|
rotate_bone(player, LLEG, {x = 0, y = 0, z = 0})
|
||||||
[RLEG] = vector_new(-1, 0, 0)
|
rotate_bone(player, RLEG, {x = 0, y = 0, z = 0})
|
||||||
},
|
rotate_bone(player, BODY, BONE_ROTATION.body_lay, BONE_POSITION.body_lay)
|
||||||
default_character_v3 = {
|
end,
|
||||||
[BODY] = vector_new(0, 6.75, 0),
|
|
||||||
[HEAD] = vector_new(0, 6.75, 0),
|
[SIT] = function(player, _time)
|
||||||
[CAPE] = vector_new(0, 6.75, 1.2),
|
rotate_bone(player, LARM, {x = 0, y = 0, z = 0})
|
||||||
[LARM] = vector_new(3, 5.75, 0),
|
rotate_bone(player, RARM, {x = 0, y = 0, z = 0})
|
||||||
[RARM] = vector_new(-3, 5.75, 0),
|
rotate_bone(player, LLEG, {x = 90, y = 0, z = 0})
|
||||||
[LLEG] = vector_new(1, 0, 0),
|
rotate_bone(player, RLEG, {x = 90, y = 0, z = 0})
|
||||||
[RLEG] = vector_new(-1, 0, 0)
|
rotate_bone(player, BODY, BONE_ROTATION.body_sit, BONE_POSITION.body_sit)
|
||||||
}
|
end,
|
||||||
|
|
||||||
|
[WALK] = function(player, time)
|
||||||
|
local speed = get_animation_speed(player)
|
||||||
|
local sin = math_sin(time * speed * math_pi)
|
||||||
|
|
||||||
|
rotate_bone(player, CAPE, {x = -35 * sin - 35, y = 0, z = 0})
|
||||||
|
rotate_bone(player, LARM, {x = -55 * sin, y = 0, z = 0})
|
||||||
|
rotate_bone(player, RARM, {x = 55 * sin, y = 0, z = 0})
|
||||||
|
rotate_bone(player, LLEG, {x = 55 * sin, y = 0, z = 0})
|
||||||
|
rotate_bone(player, RLEG, {x = -55 * sin, y = 0, z = 0})
|
||||||
|
end,
|
||||||
|
|
||||||
|
[MINE] = function(player, time)
|
||||||
|
local speed = get_animation_speed(player)
|
||||||
|
|
||||||
|
local cape_sin = math_sin(time * speed * math_pi)
|
||||||
|
local rarm_sin = math_sin(2 * time * speed * math_pi)
|
||||||
|
local rarm_cos = -math_cos(2 * time * speed * math_pi)
|
||||||
|
local pitch = 90 - get_pitch_deg(player)
|
||||||
|
|
||||||
|
rotate_bone(player, CAPE, {x = -5 * cape_sin - 5, y = 0, z = 0})
|
||||||
|
rotate_bone(player, LARM, {x = 0, y = 0, z = 0})
|
||||||
|
rotate_bone(player, RARM, {x = 10 * rarm_sin + pitch, y = 10 * rarm_cos, z = 0})
|
||||||
|
rotate_bone(player, LLEG, {x = 0, y = 0, z = 0})
|
||||||
|
rotate_bone(player, RLEG, {x = 0, y = 0, z = 0})
|
||||||
|
end,
|
||||||
|
|
||||||
|
[WALK_MINE] = function(player, time)
|
||||||
|
local speed = get_animation_speed(player)
|
||||||
|
|
||||||
|
local sin = math_sin(time * speed * math_pi)
|
||||||
|
local rarm_sin = math_sin(2 * time * speed * math_pi)
|
||||||
|
local rarm_cos = -math_cos(2 * time * speed * math_pi)
|
||||||
|
local pitch = 90 - get_pitch_deg(player)
|
||||||
|
|
||||||
|
rotate_bone(player, CAPE, {x = -35 * sin - 35, y = 0, z = 0})
|
||||||
|
rotate_bone(player, LARM, {x = -55 * sin, y = 0, z = 0})
|
||||||
|
rotate_bone(player, RARM, {x = 10 * rarm_sin + pitch, y = 10 * rarm_cos, z = 0})
|
||||||
|
rotate_bone(player, LLEG, {x = 55 * sin, y = 0, z = 0})
|
||||||
|
rotate_bone(player, RLEG, {x = -55 * sin, y = 0, z = 0})
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
local bone_rotations = {
|
local function set_animation(player, animation, force_animate)
|
||||||
default_character_v1 = {
|
local animation_changed
|
||||||
[BODY] = vector_new(0, 0, 0),
|
= (players_animation_data:get_previous_animation(player) ~= animation)
|
||||||
[HEAD] = vector_new(0, 0, 0),
|
|
||||||
[CAPE] = vector_new(180, 0, 0),
|
|
||||||
[LARM] = vector_new(180, 0, 9),
|
|
||||||
[RARM] = vector_new(180, 0, -9),
|
|
||||||
[LLEG] = vector_new(0, 0, 0),
|
|
||||||
[RLEG] = vector_new(0, 0, 0)
|
|
||||||
},
|
|
||||||
default_character_v2 = {
|
|
||||||
[BODY] = vector_new(0, 0, 0),
|
|
||||||
[HEAD] = vector_new(0, 0, 0),
|
|
||||||
[CAPE] = vector_new(0, 0, 0),
|
|
||||||
[LARM] = vector_new(0, 0, 0),
|
|
||||||
[RARM] = vector_new(0, 0, 0),
|
|
||||||
[LLEG] = vector_new(0, 0, 0),
|
|
||||||
[RLEG] = vector_new(0, 0, 0)
|
|
||||||
},
|
|
||||||
default_character_v3 = {
|
|
||||||
[BODY] = vector_new(0, 0, 0),
|
|
||||||
[HEAD] = vector_new(0, 0, 0),
|
|
||||||
[CAPE] = vector_new(0, 0, 0),
|
|
||||||
[LARM] = vector_new(0, 0, 0),
|
|
||||||
[RARM] = vector_new(0, 0, 0),
|
|
||||||
[LLEG] = vector_new(0, 0, 0),
|
|
||||||
[RLEG] = vector_new(0, 0, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
local bone_rotation = bone_rotations[player_model_version]
|
if force_animate or animation_changed then
|
||||||
local bone_position = bone_positions[player_model_version]
|
players_animation_data:set_previous_animation(player, animation)
|
||||||
if not bone_rotation or not bone_position then
|
ANIMATIONS[animation](player, players_animation_data:get_time(player))
|
||||||
error("Internal error: invalid player_model_version: " .. player_model_version)
|
|
||||||
end
|
|
||||||
|
|
||||||
local bone_rotation_cache = {}
|
|
||||||
|
|
||||||
local function rotate(player, bone, x, y, z)
|
|
||||||
local default_rotation = bone_rotation[bone]
|
|
||||||
local rotation = {
|
|
||||||
x = (x or 0) + default_rotation.x,
|
|
||||||
y = (y or 0) + default_rotation.y,
|
|
||||||
z = (z or 0) + default_rotation.z
|
|
||||||
}
|
|
||||||
|
|
||||||
local player_cache = bone_rotation_cache[player]
|
|
||||||
local rotation_cache = player_cache[bone]
|
|
||||||
|
|
||||||
if not rotation_cache
|
|
||||||
or rotation.x ~= rotation_cache.x
|
|
||||||
or rotation.y ~= rotation_cache.y
|
|
||||||
or rotation.z ~= rotation_cache.z then
|
|
||||||
player_cache[bone] = rotation
|
|
||||||
player:set_bone_position(bone, bone_position[bone], rotation)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local step = 0
|
local function rotate_head(player)
|
||||||
|
local head_x_rotation = -get_pitch_deg(player)
|
||||||
local look_pitch = {}
|
rotate_bone(player, HEAD, {x = head_x_rotation, y = 0, z = 0})
|
||||||
local animation_speed = {}
|
|
||||||
|
|
||||||
local animations = {
|
|
||||||
[STAND] = function(player)
|
|
||||||
rotate(player, BODY)
|
|
||||||
rotate(player, CAPE)
|
|
||||||
rotate(player, LARM)
|
|
||||||
rotate(player, RARM)
|
|
||||||
rotate(player, LLEG)
|
|
||||||
rotate(player, RLEG)
|
|
||||||
end,
|
|
||||||
|
|
||||||
[WALK] = function(player)
|
|
||||||
local swing = math_sin(step * 4 * animation_speed[player])
|
|
||||||
|
|
||||||
rotate(player, CAPE, swing * -30 - 35)
|
|
||||||
rotate(player, LARM, swing * -40)
|
|
||||||
rotate(player, RARM, swing * 40)
|
|
||||||
rotate(player, LLEG, swing * 40)
|
|
||||||
rotate(player, RLEG, swing * -40)
|
|
||||||
end,
|
|
||||||
|
|
||||||
[MINE] = function(player)
|
|
||||||
local pitch = look_pitch[player]
|
|
||||||
local speed = animation_speed[player]
|
|
||||||
|
|
||||||
local swing = math_sin(step * 4 * speed)
|
|
||||||
local hand_swing = math_sin(step * 8 * speed)
|
|
||||||
|
|
||||||
rotate(player, CAPE, swing * -5 - 10)
|
|
||||||
rotate(player, LARM)
|
|
||||||
rotate(player, RARM, hand_swing * 20 + 80 + pitch, hand_swing * 5 - 3, 10)
|
|
||||||
rotate(player, LLEG)
|
|
||||||
rotate(player, RLEG)
|
|
||||||
end,
|
|
||||||
|
|
||||||
[WALK_MINE] = function(player)
|
|
||||||
local pitch = look_pitch[player]
|
|
||||||
local speed = animation_speed[player]
|
|
||||||
|
|
||||||
local swing = math_sin(step * 4 * speed)
|
|
||||||
local hand_swing = math_sin(step * 8 * speed)
|
|
||||||
|
|
||||||
rotate(player, CAPE, swing * -30 - 35)
|
|
||||||
rotate(player, LARM, swing * -40)
|
|
||||||
rotate(player, RARM, hand_swing * 20 + 80 + pitch, hand_swing * 5 - 3, 10)
|
|
||||||
rotate(player, LLEG, swing * 40)
|
|
||||||
rotate(player, RLEG, swing * -40)
|
|
||||||
end,
|
|
||||||
|
|
||||||
[SIT] = function(player)
|
|
||||||
local body_position = vector_new(bone_position[BODY])
|
|
||||||
body_position.y = body_position.y - 6
|
|
||||||
|
|
||||||
player:set_bone_position(BODY, body_position, {x = 0, y = 0, z = 0})
|
|
||||||
|
|
||||||
rotate(player, LARM)
|
|
||||||
rotate(player, RARM)
|
|
||||||
rotate(player, LLEG, 90)
|
|
||||||
rotate(player, RLEG, 90)
|
|
||||||
end,
|
|
||||||
|
|
||||||
[LAY] = function(player)
|
|
||||||
rotate(player, HEAD)
|
|
||||||
rotate(player, CAPE)
|
|
||||||
rotate(player, LARM)
|
|
||||||
rotate(player, RARM)
|
|
||||||
rotate(player, LLEG)
|
|
||||||
rotate(player, RLEG)
|
|
||||||
|
|
||||||
local body_position = {x = 0, y = -9, z = 0}
|
|
||||||
local body_rotation = {x = 270, y = 0, z = 0}
|
|
||||||
|
|
||||||
player:set_bone_position(BODY, body_position, body_rotation)
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local function update_look_pitch(player)
|
|
||||||
local pitch = -player:get_look_vertical() * 180 / math_pi
|
|
||||||
|
|
||||||
if look_pitch[player] ~= pitch then
|
|
||||||
look_pitch[player] = pitch
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function set_animation_speed(player, sneak)
|
local table_remove, math_deg = table.remove, math.deg
|
||||||
local speed = sneak and 0.75 or 2
|
local function rotate_body_and_head(player)
|
||||||
|
local body_x_rotation = (function()
|
||||||
|
local sneak = player:get_player_control().sneak
|
||||||
|
return sneak and BODY_X_ROTATION_SNEAK or 0
|
||||||
|
end)()
|
||||||
|
|
||||||
if animation_speed[player] ~= speed then
|
local body_y_rotation = (function()
|
||||||
animation_speed[player] = speed
|
local yaw_history = players_animation_data:get_yaw_history(player)
|
||||||
end
|
if #yaw_history > BODY_ROTATION_DELAY then
|
||||||
end
|
local body_yaw = table_remove(yaw_history, 1)
|
||||||
|
local player_yaw = player:get_look_horizontal()
|
||||||
local previous_animation = {}
|
return math_deg(player_yaw - body_yaw)
|
||||||
|
|
||||||
local function set_animation(player, anim)
|
|
||||||
if (anim == WALK or anim == MINE or anim == WALK_MINE)
|
|
||||||
or (previous_animation[player] ~= anim) then
|
|
||||||
previous_animation[player] = anim
|
|
||||||
animations[anim](player)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local previous_yaw = {}
|
|
||||||
|
|
||||||
local function body_moving(player, sneak, no_rotate_body)
|
|
||||||
local yaw = player:get_look_horizontal()
|
|
||||||
|
|
||||||
local player_previous_yaw = previous_yaw[player]
|
|
||||||
local index = #player_previous_yaw + 1
|
|
||||||
player_previous_yaw[index] = yaw
|
|
||||||
|
|
||||||
local next_yaw = yaw
|
|
||||||
if index > 7 then
|
|
||||||
next_yaw = player_previous_yaw[1]
|
|
||||||
table_remove(player_previous_yaw, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
local x, y = 0, 0
|
|
||||||
if not no_rotate_body then
|
|
||||||
x = sneak and 5 or 0
|
|
||||||
y = (yaw - next_yaw) * 180 / math_pi
|
|
||||||
end
|
|
||||||
|
|
||||||
rotate(player, BODY, x, y)
|
|
||||||
rotate(player, HEAD, look_pitch[player], -y)
|
|
||||||
end
|
|
||||||
|
|
||||||
local players = {}
|
|
||||||
local player_list = {}
|
|
||||||
local player_count = 0
|
|
||||||
|
|
||||||
local function update_players()
|
|
||||||
players = {}
|
|
||||||
|
|
||||||
local position = 0
|
|
||||||
|
|
||||||
for player, joined in pairs(player_list) do
|
|
||||||
if joined and player:is_player_connected() then
|
|
||||||
position = position + 1
|
|
||||||
players[position] = player
|
|
||||||
end
|
end
|
||||||
end
|
return 0
|
||||||
|
end)()
|
||||||
|
|
||||||
player_count = position
|
rotate_bone(player, BODY, {x = body_x_rotation, y = body_y_rotation, z = 0})
|
||||||
|
|
||||||
|
local head_x_rotation = -get_pitch_deg(player)
|
||||||
|
rotate_bone(player, HEAD, {x = head_x_rotation, y = -body_y_rotation, z = 0})
|
||||||
end
|
end
|
||||||
|
|
||||||
minetest.register_on_joinplayer(function(player)
|
|
||||||
bone_rotation_cache[player] = {}
|
|
||||||
previous_yaw[player] = {}
|
|
||||||
|
|
||||||
player_list[player] = true
|
local function animate_player(player, dtime)
|
||||||
update_players()
|
local animation = get_animation(player).animation
|
||||||
end)
|
|
||||||
|
|
||||||
minetest.register_on_leaveplayer(function(player)
|
-- Yaw history
|
||||||
bone_rotation_cache[player] = nil
|
if animation == "lay" or animation == "sit" then
|
||||||
|
players_animation_data:clear_yaw_history(player)
|
||||||
|
else
|
||||||
|
players_animation_data:add_yaw_to_history(player)
|
||||||
|
end
|
||||||
|
|
||||||
look_pitch[player] = nil
|
-- Increment animation time
|
||||||
animation_speed[player] = nil
|
if animation == "walk"
|
||||||
|
or animation == "mine"
|
||||||
|
or animation == "walk_mine" then
|
||||||
|
players_animation_data:increment_time(player, dtime)
|
||||||
|
else
|
||||||
|
players_animation_data:reset_time(player)
|
||||||
|
end
|
||||||
|
|
||||||
previous_yaw[player] = nil
|
-- Set animation
|
||||||
previous_animation[player] = nil
|
if animation == "stand" then
|
||||||
|
set_animation(player, STAND)
|
||||||
|
elseif animation == "lay" then
|
||||||
|
set_animation(player, LAY)
|
||||||
|
elseif animation == "sit" then
|
||||||
|
set_animation(player, SIT)
|
||||||
|
elseif animation == "walk" then
|
||||||
|
set_animation(player, WALK, true)
|
||||||
|
elseif animation == "mine" then
|
||||||
|
set_animation(player, MINE, true)
|
||||||
|
elseif animation == "walk_mine" then
|
||||||
|
set_animation(player, WALK_MINE, true)
|
||||||
|
end
|
||||||
|
|
||||||
player_list[player] = nil
|
-- Rotate body and head
|
||||||
update_players()
|
if animation == "lay" then
|
||||||
end)
|
-- Do nothing
|
||||||
|
elseif animation == "sit" then
|
||||||
|
rotate_head(player)
|
||||||
|
else
|
||||||
|
rotate_body_and_head(player)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local minetest_get_connected_players = minetest.get_connected_players
|
||||||
minetest.register_globalstep(function(dtime)
|
minetest.register_globalstep(function(dtime)
|
||||||
if player_count == 0 then return end
|
for _, player in ipairs(minetest_get_connected_players()) do
|
||||||
|
animate_player(player, dtime)
|
||||||
step = step + dtime
|
|
||||||
if step >= 3600 then
|
|
||||||
step = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
for i = 1, player_count do
|
|
||||||
local player = players[i]
|
|
||||||
local animation = get_animation(player).animation
|
|
||||||
|
|
||||||
if animation == "lay" then
|
|
||||||
set_animation(player, LAY)
|
|
||||||
|
|
||||||
if #previous_yaw[player] ~= 0 then
|
|
||||||
previous_yaw[player] = {}
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local controls = player:get_player_control()
|
|
||||||
local sneak = controls.sneak
|
|
||||||
|
|
||||||
update_look_pitch(player)
|
|
||||||
|
|
||||||
if animation == "walk" then
|
|
||||||
set_animation_speed(player, sneak)
|
|
||||||
set_animation(player, WALK)
|
|
||||||
body_moving(player, sneak)
|
|
||||||
elseif animation == "mine" then
|
|
||||||
set_animation_speed(player, sneak)
|
|
||||||
set_animation(player, MINE)
|
|
||||||
body_moving(player, sneak)
|
|
||||||
elseif animation == "walk_mine" then
|
|
||||||
set_animation_speed(player, sneak)
|
|
||||||
set_animation(player, WALK_MINE)
|
|
||||||
body_moving(player, sneak)
|
|
||||||
elseif animation == "sit" then
|
|
||||||
set_animation(player, SIT)
|
|
||||||
body_moving(player, sneak, true)
|
|
||||||
else
|
|
||||||
set_animation(player, STAND)
|
|
||||||
body_moving(player, sneak)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
99
model.lua
Normal file
99
model.lua
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
-- Bone alias
|
||||||
|
local BODY = "Body"
|
||||||
|
local HEAD = "Head"
|
||||||
|
local CAPE = "Cape"
|
||||||
|
local LARM = "Arm_Left"
|
||||||
|
local RARM = "Arm_Right"
|
||||||
|
local LLEG = "Leg_Left"
|
||||||
|
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 = {
|
||||||
|
MTG_4_Jun_2017 = {
|
||||||
|
[BODY] = {x = 0, y = -3.5, z = 0},
|
||||||
|
[HEAD] = {x = 0, y = 6.5, z = 0},
|
||||||
|
[CAPE] = {x = 0, y = 6.5, z = 1.2},
|
||||||
|
[LARM] = {x = 3, y = 5.5, z = 0},
|
||||||
|
[RARM] = {x = -3, y = 5.5, z = 0},
|
||||||
|
[LLEG] = {x = 1, y = 0, z = 0},
|
||||||
|
[RLEG] = {x = -1, y = 0, z = 0},
|
||||||
|
|
||||||
|
body_sit = {x = 0, y = -5.5, z = 0},
|
||||||
|
body_lay = {x = 0, y = -5.5, z = 0},
|
||||||
|
},
|
||||||
|
MTG_4_Nov_2017 = {
|
||||||
|
[BODY] = {x = 0, y = 6.25, z = 0},
|
||||||
|
[HEAD] = {x = 0, y = 6.5, z = 0},
|
||||||
|
[CAPE] = {x = 0, y = 6.5, z = 1.2},
|
||||||
|
[LARM] = {x = 3, y = 5.5, z = 0},
|
||||||
|
[RARM] = {x = -3, y = 5.5, z = 0},
|
||||||
|
[LLEG] = {x = 1, y = 0, z = 0},
|
||||||
|
[RLEG] = {x = -1, y = 0, z = 0},
|
||||||
|
|
||||||
|
body_sit = {x = 0, y = -5, z = 0},
|
||||||
|
body_lay = {x = 0, y = -5, z = 0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local BONE_ROTATIONS = {
|
||||||
|
MTG_4_Jun_2017 = {
|
||||||
|
[BODY] = {x = 0, y = 0, z = 0},
|
||||||
|
[HEAD] = {x = 0, y = 0, z = 0},
|
||||||
|
[CAPE] = {x = 0, y = 0, z = 0},
|
||||||
|
[LARM] = {x = 0, y = 0, z = 0},
|
||||||
|
[RARM] = {x = 0, y = 0, z = 0},
|
||||||
|
[LLEG] = {x = 0, y = 0, z = 0},
|
||||||
|
[RLEG] = {x = 0, y = 0, z = 0},
|
||||||
|
|
||||||
|
body_sit = {x = 0, y = 0, z = 0},
|
||||||
|
body_lay = {x = 270, y = 0, z = 0},
|
||||||
|
},
|
||||||
|
MTG_4_Nov_2017 = {
|
||||||
|
[BODY] = {x = 0, y = 0, z = 0},
|
||||||
|
[HEAD] = {x = 0, y = 0, z = 0},
|
||||||
|
[CAPE] = {x = 0, y = 0, z = 0},
|
||||||
|
[LARM] = {x = 0, y = 0, z = 0},
|
||||||
|
[RARM] = {x = 0, y = 0, z = 0},
|
||||||
|
[LLEG] = {x = 0, y = 0, z = 0},
|
||||||
|
[RLEG] = {x = 0, y = 0, z = 0},
|
||||||
|
|
||||||
|
body_sit = {x = 0, y = 0, z = 0},
|
||||||
|
body_lay = {x = 270, y = 0, z = 0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
local PLAYER_MODEL_VERSION = (function()
|
||||||
|
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
|
||||||
|
error("The model version '" .. version .. "' is no longer suppported")
|
||||||
|
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
|
||||||
|
error("Internal error: invalid player_model_version: " .. PLAYER_MODEL_VERSION)
|
||||||
|
end
|
||||||
|
|
||||||
|
return BONE_POSITION, BONE_ROTATION
|
23
readme.md
23
readme.md
|
@ -1,23 +0,0 @@
|
||||||
# playeranim
|
|
||||||
Makes the head, and the right arm when you’re mining, face the way you’re facing, similar to Minecraft. Compatible with 3d_armor. Forked from the animplus mod, which was an ugly hack.
|
|
||||||
|
|
||||||
The head only turns up and down relative to the body, except it turns slightly to the right/left when you strafe right/left. When you turn the body turns with the head.
|
|
||||||
|
|
||||||
Works in multiplayer, I tested it on a local server.
|
|
||||||
|
|
||||||
Configuration
|
|
||||||
-------------
|
|
||||||
|
|
||||||
This mod supports 2 versions of the player model:
|
|
||||||
- The old version: v1 (before nov. 2016)
|
|
||||||
- The new version: v2 (after nov. 2016)
|
|
||||||
(see also init.lua)
|
|
||||||
|
|
||||||
As there is no automatic way to determine which version is used, this must be manually configured in `init.lua`.
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
Created by Rui914, this document was written by sloantothebone.
|
|
|
@ -1,17 +1,18 @@
|
||||||
# Version of player model.
|
# Version of player model.
|
||||||
# Some fixes and improvements were made to the default player model (character.b3d)
|
|
||||||
# end of november 2016. These changes affect the way body parts are attached and
|
|
||||||
# positioned. For correct results, the version of the player model must be known.
|
|
||||||
#
|
#
|
||||||
# Player models known / supported by this mod:
|
# Player models supported by this mod:
|
||||||
# . -- default_character_v1; used in:
|
# . -- `MTG_4_Jun_2017` (minetest_game after 4 Jun 2017, 0.4.16)
|
||||||
# . -- minetest_game before 25 nov 2016
|
# . -- `MTG_4_Nov_2017` (minetest_game after 4 Nov 2017, 0.5.0)
|
||||||
# . -- 3d_armor before 27 nov 2016 (overrides model from minetest_game)
|
playeranim.model_version (Version of player model) enum MTG_4_Jun_2017 MTG_4_Jun_2017,MTG_4_Nov_2017
|
||||||
# . -- default_character_v2; used in:
|
|
||||||
# . -- minetest_game after 25 nov 2016
|
|
||||||
# . -- 3d_armor after 27 nov 2016 (overrides model from minetest_game)
|
|
||||||
# . -- default_character_v3; used in:
|
|
||||||
# . -- minetest_game after 22 jul 2017
|
|
||||||
# . -- 3d_armor after ???????????????? (overrides model from minetest_game)
|
|
||||||
player_model_version (Version of player model) enum default_character_v2 default_character_v1,default_character_v2,default_character_v3
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# The degrees of the body's X-axis rotation in sneaking.
|
||||||
|
playeranim.body_x_rotation_sneak (Lengthways body rotation in sneaking) float 6.0
|
||||||
|
|
||||||
|
# The number of stepping per seconds.
|
||||||
|
playeranim.animation_speed (The speed of an animation) float 2.4
|
||||||
|
|
||||||
|
# The number of stepping per seconds in sneaking.
|
||||||
|
playeranim.animation_speed_sneak (The speed of an animation in sneaking) float 0.8
|
||||||
|
|
Loading…
Reference in New Issue
Block a user