-
Notifications
You must be signed in to change notification settings - Fork 580
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
161 additions
and
103 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,132 +1,190 @@ | ||
-- Minetest 0.4 mod: player | ||
-- See README.txt for licensing and other information. | ||
|
||
-- | ||
-- Start of configuration area: | ||
-- | ||
--[[ | ||
-- Player animation speed | ||
animation_speed = 30 | ||
API | ||
--- | ||
default.player_register_model(name, def) | ||
^ Register a new model to be used by players. | ||
^ <name> is the model filename such as "character.x", "foo.b3d", etc. | ||
^ See Model Definition below for format of <def>. | ||
default.registered_player_models[name] | ||
^ See Model Definition below for format. | ||
default.player_set_model(player, model_name) | ||
^ <player> is a PlayerRef. | ||
^ <model_name> is a model registered with player_register_model. | ||
default.player_set_animation(player, anim_name [, speed]) | ||
^ <player> is a PlayerRef. | ||
^ <anim_name> is the name of the animation. | ||
^ <speed> is in frames per second. If nil, default from the model is used | ||
default.player_set_textures(player, textures) | ||
^ <player> is a PlayerRef. | ||
^ <textures> is an array of textures | ||
^ If <textures> is nil, the default textures from the model def are used | ||
default.player_get_animation(player) | ||
^ <player> is a PlayerRef. | ||
^ Returns a table containing fields "model", "textures" and "animation". | ||
^ Any of the fields of the returned table may be nil. | ||
Model Definition | ||
---------------- | ||
model_def = { | ||
animation_speed = 30, -- Default animation speed, in FPS. | ||
textures = {"character.png", }, -- Default array of textures. | ||
visual_size = {x=1, y=1,}, -- Used to scale the model. | ||
animations = { | ||
-- <anim_name> = { x=<start_frame>, y=<end_frame>, }, | ||
foo = { x= 0, y=19, }, | ||
bar = { x=20, y=39, }, | ||
-- ... | ||
}, | ||
} | ||
]] | ||
|
||
-- Player animation blending | ||
-- Note: This is currently broken due to a bug in Irrlicht, leave at 0 | ||
animation_blend = 0 | ||
local animation_blend = 0 | ||
|
||
-- Default player appearance | ||
default_model = "character.x" | ||
default_textures = {"character.png", } | ||
|
||
-- Frame ranges for each player model | ||
function player_get_animations(model) | ||
if model == "character.x" then | ||
return { | ||
stand_START = 0, | ||
stand_END = 79, | ||
sit_START = 81, | ||
sit_END = 160, | ||
lay_START = 162, | ||
lay_END = 166, | ||
walk_START = 168, | ||
walk_END = 187, | ||
mine_START = 189, | ||
mine_END = 198, | ||
walk_mine_START = 200, | ||
walk_mine_END = 219 | ||
} | ||
end | ||
default.registered_player_models = { } | ||
|
||
-- Local for speed. | ||
local models = default.registered_player_models | ||
|
||
function default.player_register_model(name, def) | ||
models[name] = def | ||
end | ||
|
||
-- | ||
-- End of configuration area. | ||
-- | ||
-- Default player appearance | ||
default.player_register_model("character.x", { | ||
animation_speed = 30, | ||
textures = {"character.png", }, | ||
animations = { | ||
-- Standard animations. | ||
stand = { x= 0, y= 79, }, | ||
lay = { x=162, y=166, }, | ||
walk = { x=168, y=187, }, | ||
mine = { x=189, y=198, }, | ||
walk_mine = { x=200, y=219, }, | ||
-- Extra animations (not currently used by the game). | ||
sit = { x= 81, y=160, }, | ||
}, | ||
}) | ||
|
||
-- Player stats and animations | ||
local player_model = {} | ||
local player_textures = {} | ||
local player_anim = {} | ||
local player_sneak = {} | ||
local ANIM_STAND = 1 | ||
local ANIM_SIT = 2 | ||
local ANIM_LAY = 3 | ||
local ANIM_WALK = 4 | ||
local ANIM_WALK_MINE = 5 | ||
local ANIM_MINE = 6 | ||
|
||
-- Called when a player's appearance needs to be updated | ||
function player_update_visuals(pl) | ||
local name = pl:get_player_name() | ||
|
||
player_model[name] = default_model | ||
player_anim[name] = 0 -- Animation will be set further below immediately | ||
player_sneak[name] = false | ||
prop = { | ||
mesh = default_model, | ||
textures = default_textures, | ||
visual = "mesh", | ||
visual_size = {x=1, y=1}, | ||
function default.player_get_animation(player) | ||
local name = player:get_player_name() | ||
return { | ||
model = player_model[name], | ||
textures = player_textures[name], | ||
animation = player_anim[name], | ||
} | ||
pl:set_properties(prop) | ||
end | ||
|
||
-- Called when a player's appearance needs to be updated | ||
function default.player_set_model(player, model_name) | ||
local name = player:get_player_name() | ||
local model = models[model_name] | ||
if model then | ||
if player_model[name] == model_name then | ||
return | ||
end | ||
player:set_properties({ | ||
mesh = model_name, | ||
textures = player_textures[name] or model.textures, | ||
visual = "mesh", | ||
visual_size = model.visual_size or {x=1, y=1}, | ||
}) | ||
default.player_set_animation(player, "stand") | ||
else | ||
player:set_properties({ | ||
textures = { "player.png", "player_back.png", }, | ||
visual = "upright_sprite", | ||
}) | ||
end | ||
player_model[name] = model_name | ||
end | ||
|
||
function default.player_set_textures(player, textures) | ||
local name = player:get_player_name() | ||
player_textures[name] = textures | ||
player:set_properties({textures = textures,}) | ||
end | ||
|
||
function default.player_set_animation(player, anim_name, speed) | ||
local name = player:get_player_name() | ||
if player_anim[name] == anim_name then | ||
return | ||
end | ||
local model = player_model[name] and models[player_model[name]] | ||
if not (model and model.animations[anim_name]) then | ||
return | ||
end | ||
local anim = model.animations[anim_name] | ||
player_anim[name] = anim_name | ||
player:set_animation(anim, speed or model.animation_speed, animation_blend) | ||
end | ||
|
||
-- Update appearance when the player joins | ||
minetest.register_on_joinplayer(player_update_visuals) | ||
minetest.register_on_joinplayer(function(player) | ||
default.player_set_model(player, "character.x") | ||
end) | ||
|
||
-- Localize for better performance. | ||
local player_set_animation = default.player_set_animation | ||
|
||
-- Check each player and apply animations | ||
function player_step(dtime) | ||
for _, pl in pairs(minetest.get_connected_players()) do | ||
local name = pl:get_player_name() | ||
local anim = player_get_animations(player_model[name]) | ||
local controls = pl:get_player_control() | ||
local walking = false | ||
local animation_speed_mod = animation_speed | ||
|
||
-- Determine if the player is walking | ||
if controls.up or controls.down or controls.left or controls.right then | ||
walking = true | ||
end | ||
minetest.register_globalstep(function(dtime) | ||
for _, player in pairs(minetest.get_connected_players()) do | ||
local name = player:get_player_name() | ||
local model_name = player_model[name] | ||
local model = model_name and models[model_name] | ||
if model then | ||
local controls = player:get_player_control() | ||
local walking = false | ||
local animation_speed_mod = model.animation_speed or 30 | ||
|
||
-- Determine if the player is sneaking, and reduce animation speed if so | ||
if controls.sneak and pl:get_hp() ~= 0 and (walking or controls.LMB) then | ||
animation_speed_mod = animation_speed_mod / 2 | ||
-- Refresh player animation below if sneak state changed | ||
if not player_sneak[name] then | ||
player_anim[name] = 0 | ||
player_sneak[name] = true | ||
end | ||
else | ||
-- Refresh player animation below if sneak state changed | ||
if player_sneak[name] then | ||
player_anim[name] = 0 | ||
player_sneak[name] = false | ||
-- Determine if the player is walking | ||
if controls.up or controls.down or controls.left or controls.right then | ||
walking = true | ||
end | ||
end | ||
|
||
-- Apply animations based on what the player is doing | ||
if pl:get_hp() == 0 then | ||
if player_anim[name] ~= ANIM_LAY then | ||
pl:set_animation({x=anim.lay_START, y=anim.lay_END}, animation_speed_mod, animation_blend) | ||
player_anim[name] = ANIM_LAY | ||
end | ||
elseif walking and controls.LMB then | ||
if player_anim[name] ~= ANIM_WALK_MINE then | ||
pl:set_animation({x=anim.walk_mine_START, y=anim.walk_mine_END}, animation_speed_mod, animation_blend) | ||
player_anim[name] = ANIM_WALK_MINE | ||
-- Determine if the player is sneaking, and reduce animation speed if so | ||
if controls.sneak then | ||
animation_speed_mod = animation_speed_mod / 2 | ||
end | ||
elseif walking then | ||
if player_anim[name] ~= ANIM_WALK then | ||
pl:set_animation({x=anim.walk_START, y=anim.walk_END}, animation_speed_mod, animation_blend) | ||
player_anim[name] = ANIM_WALK | ||
end | ||
elseif controls.LMB then | ||
if player_anim[name] ~= ANIM_MINE then | ||
pl:set_animation({x=anim.mine_START, y=anim.mine_END}, animation_speed_mod, animation_blend) | ||
player_anim[name] = ANIM_MINE | ||
|
||
-- Apply animations based on what the player is doing | ||
if player:get_hp() == 0 then | ||
player_set_animation(player, "lay") | ||
elseif walking then | ||
if player_sneak[name] ~= controls.sneak then | ||
player_anim[name] = nil | ||
player_sneak[name] = controls.sneak | ||
end | ||
if controls.LMB then | ||
player_set_animation(player, "walk_mine", animation_speed_mod) | ||
else | ||
player_set_animation(player, "walk", animation_speed_mod) | ||
end | ||
elseif controls.LMB then | ||
player_set_animation(player, "mine") | ||
else | ||
player_set_animation(player, "stand", animation_speed_mod) | ||
end | ||
elseif player_anim[name] ~= ANIM_STAND then | ||
pl:set_animation({x=anim.stand_START, y=anim.stand_END}, animation_speed_mod, animation_blend) | ||
player_anim[name] = ANIM_STAND | ||
end | ||
end | ||
end | ||
minetest.register_globalstep(player_step) | ||
|
||
-- END | ||
end) |