diff --git a/mods/playeranim/.gitrepo b/mods/playeranim/.gitrepo new file mode 100644 index 0000000..73b87d8 --- /dev/null +++ b/mods/playeranim/.gitrepo @@ -0,0 +1,11 @@ +; DO NOT EDIT (unless you know what you are doing) +; +; This subdirectory is a git "subrepo", and this file is maintained by the +; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme +; +[subrepo] + remote = https://github.com/minetest-mods/playeranim.git + branch = master + commit = 0ca8e5a3aad630657d17ba801eede61cb1ff7065 + parent = 2f40301c2d455e5bcda3aa9e24a951b39fe3a4df + cmdver = 0.3.1 diff --git a/mods/playeranim/depends.txt b/mods/playeranim/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/mods/playeranim/depends.txt @@ -0,0 +1 @@ +default diff --git a/mods/playeranim/description.txt b/mods/playeranim/description.txt new file mode 100644 index 0000000..0c1198d --- /dev/null +++ b/mods/playeranim/description.txt @@ -0,0 +1 @@ +Adds animations to the players' head and right arm. \ No newline at end of file diff --git a/mods/playeranim/init.lua b/mods/playeranim/init.lua new file mode 100644 index 0000000..8eeaeaa --- /dev/null +++ b/mods/playeranim/init.lua @@ -0,0 +1,331 @@ +-- Version of player model. +-- default_character_v1: +-- minetest_game before 25 nov 2016 +-- 3d_armor before 27 nov 2016 (overrides model from minetest_game) +-- 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 = { + default_character_v1 = true, + default_character_v2 = true, +} + +local player_model_version = minetest.setting_get("player_model_version") +if not player_model_version or player_model_version == "" then + player_model_version = "default_character_v2" +elseif not valid_player_model_versions[player_model_version] then + error("Invalid value for player_model_version in minetest.conf: " .. player_model_version) +end + +-- Localize to avoid table lookups +local vector_new = vector.new +local math_pi = math.pi +local math_sin = math.sin +local table_remove = table.remove +local get_animation = default.player_get_animation + +-- Animation alias +local STAND = 1 +local WALK = 2 +local MINE = 3 +local WALK_MINE = 4 +local SIT = 5 +local LAY = 6 + +-- 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" + +local bone_positions = { + default_character_v1 = { + [BODY] = vector_new(0, -3.5, 0), + [HEAD] = vector_new(0, 6.75, 0), + [CAPE] = vector_new(0, 6.75, 1.1), + [LARM] = vector_new(2, 6.75, 0), + [RARM] = vector_new(-2, 6.75, 0), + [LLEG] = vector_new(-1, 0, 0), + [RLEG] = vector_new(1, 0, 0) + }, + default_character_v2 = { + [BODY] = vector_new(0, -3.5, 0), + [HEAD] = vector_new(0, 6.75, 0), + [CAPE] = vector_new(0, 6.75, 1.2), + [LARM] = vector_new(3, 5.75, 0), + [RARM] = vector_new(-3, 5.75, 0), + [LLEG] = vector_new(1, 0, 0), + [RLEG] = vector_new(-1, 0, 0) + } +} + +local bone_rotations = { + default_character_v1 = { + [BODY] = vector_new(0, 0, 0), + [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) + } +} + +local bone_rotation = bone_rotations[player_model_version] +local bone_position = bone_positions[player_model_version] +if not bone_rotation or not bone_position then + 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 + +local step = 0 + +local look_pitch = {} +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 + +local function set_animation_speed(player, sneak) + local speed = sneak and 0.75 or 2 + + if animation_speed[player] ~= speed then + animation_speed[player] = speed + end +end + +local previous_animation = {} + +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 + + player_count = position +end + +minetest.register_on_joinplayer(function(player) + bone_rotation_cache[player] = {} + previous_yaw[player] = {} + + player_list[player] = true + update_players() +end) + +minetest.register_on_leaveplayer(function(player) + bone_rotation_cache[player] = nil + + look_pitch[player] = nil + animation_speed[player] = nil + + previous_yaw[player] = nil + previous_animation[player] = nil + + player_list[player] = nil + update_players() +end) + +minetest.register_globalstep(function(dtime) + if player_count == 0 then return end + + 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) diff --git a/mods/playeranim/license.md b/mods/playeranim/license.md new file mode 100644 index 0000000..539d1d7 --- /dev/null +++ b/mods/playeranim/license.md @@ -0,0 +1,23 @@ +Copyright (c) 2013-2014, Diego Martínez +Copyright (c) 2016, Rui +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/mods/playeranim/mod.conf b/mods/playeranim/mod.conf new file mode 100644 index 0000000..0df8814 --- /dev/null +++ b/mods/playeranim/mod.conf @@ -0,0 +1 @@ +name = playeranim diff --git a/mods/playeranim/readme.md b/mods/playeranim/readme.md new file mode 100644 index 0000000..395d687 --- /dev/null +++ b/mods/playeranim/readme.md @@ -0,0 +1,23 @@ +# 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. diff --git a/mods/playeranim/screenshot.png b/mods/playeranim/screenshot.png new file mode 100644 index 0000000..57aeefe Binary files /dev/null and b/mods/playeranim/screenshot.png differ diff --git a/mods/playeranim/settingtypes.txt b/mods/playeranim/settingtypes.txt new file mode 100644 index 0000000..19912bb --- /dev/null +++ b/mods/playeranim/settingtypes.txt @@ -0,0 +1,14 @@ +# 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: +# . -- default_character_v1; used in: +# . -- minetest_game before 25 nov 2016 +# . -- 3d_armor before 27 nov 2016 (overrides model from minetest_game) +# . -- default_character_v2; used in: +# . -- minetest_game after 25 nov 2016 +# . -- 3d_armor after 27 nov 2016 (overrides model from minetest_game) +player_model_version (Version of player model) enum default_character_v2 default_character_v1,default_character_v2 +