206 lines
5.6 KiB
Lua
206 lines
5.6 KiB
Lua
|
|
--[[
|
|
|
|
Copyright (C) 2016 - Auke Kok <sofar@foo-projects.org>
|
|
|
|
"emote" is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU Lesser General Public License as
|
|
published by the Free Software Foundation; either version 2.1
|
|
of the license, or (at your option) any later version.
|
|
|
|
]]--
|
|
|
|
local S = minetest.get_translator("emote")
|
|
local N = function(s) return s end
|
|
|
|
emote = {}
|
|
|
|
local emotes = {
|
|
stand = {{x = 0, y = 79}, 30, 0, true, N("@1 stands up."), N("stand up")},
|
|
sit = {{x = 81, y = 160}, 30, 0, true, N("@1 sits."), N("sit")},
|
|
lay = {{x = 162, y = 166}, 30, 0, true, N("@1 lies down."), N("lie down")},
|
|
sleep = {{x = 162, y = 166}, 30, 0, true, N("@1 falls asleep."), N("sleep")}, -- alias for lay
|
|
wave = {{x = 192, y = 196}, 15, 0, false, N("@1 waves."), N("wave")},
|
|
point = {{x = 196, y = 196}, 30, 0, true, N("@1 points."), N("point")},
|
|
freeze = {{x = 205, y = 205}, 30, 0, true, N("@1 freezes."), N("freeze")},
|
|
}
|
|
|
|
local emoting = {}
|
|
local attached = {}
|
|
|
|
-- helper functions
|
|
local function facedir_to_look_horizontal(dir)
|
|
if dir == 0 then
|
|
return 0
|
|
elseif dir == 1 then
|
|
return math.pi * 3/2
|
|
elseif dir == 2 then
|
|
return math.pi
|
|
elseif dir == 3 then
|
|
return math.pi / 2
|
|
else
|
|
return nil
|
|
end
|
|
end
|
|
|
|
local function vector_rotate_xz(vec, angle)
|
|
local a = angle - (math.pi * 3/2)
|
|
return {
|
|
x = (vec.z * math.sin(a)) - (vec.x * math.cos(a)),
|
|
y = vec.y,
|
|
z = (vec.z * math.cos(a)) - (vec.x * math.sin(a))
|
|
}
|
|
end
|
|
|
|
-- entity for locked emotes (attached to nodes, etc)
|
|
local attacher = {
|
|
description = S("Attachment entity for emotes"),
|
|
physical = false,
|
|
visual = "upright_sprite",
|
|
visual_size = {x = 1/16, y = 1/16},
|
|
spritediv = {x = 1/16, y = 1/16},
|
|
collisionbox = {-1/16, -1/16, -1/16, 1/16, 1/16, 1/16},
|
|
textures = {"itb_blank.png"},
|
|
init = function(self, player)
|
|
self.player = player
|
|
end,
|
|
}
|
|
|
|
function attacher:on_step(dtime)
|
|
if not self.player then
|
|
self.object:remove()
|
|
return
|
|
end
|
|
|
|
local ctrl = self.player:get_player_control()
|
|
if ctrl.jump then
|
|
self:detach()
|
|
return
|
|
end
|
|
end
|
|
|
|
function attacher:detach()
|
|
attached[self.player] = nil
|
|
self.player:set_detach()
|
|
self.player:set_animation(unpack(emotes["stand"]))
|
|
self.object:remove()
|
|
end
|
|
|
|
minetest.register_entity("emote:attacher", attacher)
|
|
|
|
-- API functions
|
|
|
|
function emote.start(player, emotestring)
|
|
emote.stop(player)
|
|
if emotes[emotestring] then
|
|
player:set_animation(unpack(emotes[emotestring]))
|
|
emoting[player] = emotestring
|
|
local e = emotes[emotestring]
|
|
if e[5] then
|
|
minetest.chat_send_all("* " .. S(e[5], player:get_player_name()))
|
|
end
|
|
if not e[4] then
|
|
local len = (e[1].y - e[1].x) / e[2]
|
|
minetest.after(len, emote.stop, player)
|
|
end
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
function emote.stop(player)
|
|
if emoting[player] then
|
|
emoting[player] = nil
|
|
player:set_animation(unpack(emotes["stand"]))
|
|
end
|
|
end
|
|
|
|
function emote.list()
|
|
local r = {}
|
|
for k, _ in pairs(emotes) do
|
|
table.insert(r, k)
|
|
end
|
|
return r
|
|
end
|
|
|
|
function emote.attach_to_node(player, pos, locked)
|
|
local node = minetest.get_node(pos)
|
|
if node.name == "ignore" then
|
|
return false
|
|
end
|
|
|
|
if attached[player] then
|
|
return
|
|
end
|
|
|
|
local def = minetest.registered_nodes[node.name].emote or {}
|
|
|
|
local emotedef = {
|
|
eye_offset = def.eye_offset or {x = 0, y = 1/2, z = 0},
|
|
player_offset = def.player_offset or {x = 0, y = 0, z = 0},
|
|
look_horizontal_offset = def.look_horizontal_offset or 0,
|
|
emotestring = def.emotestring or "sit",
|
|
}
|
|
|
|
if locked then
|
|
player:set_animation(unpack(emotes[emotedef.emotestring]))
|
|
local offset = vector_rotate_xz(emotedef.player_offset,facedir_to_look_horizontal(node.param2))
|
|
local object = minetest.add_entity(vector.add(pos, offset), "emote:attacher")
|
|
object:get_luaentity():init(player)
|
|
local rotation = facedir_to_look_horizontal(node.param2) + emotedef.look_horizontal_offset
|
|
object:setyaw(rotation)
|
|
player:set_attach(object, "", emotedef.eye_offset, minetest.facedir_to_dir(node.param2))
|
|
player:set_look_horizontal(rotation)
|
|
-- this is highly unreliable!
|
|
minetest.after(0, function()
|
|
player:set_animation(unpack(emotes[emotedef.emotestring]))
|
|
end)
|
|
attached[player] = object
|
|
else
|
|
player:set_pos(vector.add(pos, vector_rotate_xz(emotedef.player_offset, facedir_to_look_horizontal(node.param2))))
|
|
player:set_eye_offset(emotedef.eye_offset, {x = 0, y = 0, z = 0})
|
|
player:set_look_horizontal(facedir_to_look_horizontal(node.param2) + emotedef.look_horizontal_offset)
|
|
player:set_animation(unpack(emotes[emotedef.emotestring]))
|
|
player:set_physics_override(0, 0, 0)
|
|
end
|
|
end
|
|
|
|
function emote.attach_to_entity(player, emotestring, obj)
|
|
-- not implemented yet.
|
|
end
|
|
|
|
function emote.detach(player)
|
|
if attached[player] then
|
|
attached[player]:detach()
|
|
end
|
|
-- check if attached?
|
|
player:set_eye_offset(vector.new(), vector.new())
|
|
player:set_physics_override(1, 1, 1)
|
|
player:set_animation(unpack(emotes["stand"]))
|
|
end
|
|
|
|
for k, _ in pairs(emotes) do
|
|
minetest.register_chatcommand(k, {
|
|
params = k .. " emote",
|
|
description = S("Makes your character perform the \"@1\" emote", S(emotes[k][6])),
|
|
func = function(name, param)
|
|
local player = minetest.get_player_by_name(name)
|
|
emote.start(player, k)
|
|
end,
|
|
})
|
|
end
|
|
|
|
--[[
|
|
-- testing tool - punch any node to test attachment code
|
|
minetest.register_craftitem("emote:sleep", {
|
|
description = "use me on a bed bottom",
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
-- the delay here is weird, but the client receives a mouse-up event
|
|
-- after the punch and switches back to "stand" animation, undoing
|
|
-- the animation change we're doing.
|
|
minetest.after(0.5, emote.attach_to_node, user, pointed_thing.under)
|
|
end
|
|
})
|
|
]]--
|