fb77ef190c
The "pretend to be in 3rd person view" camera angle never really worked, and using the actual F7 key seems to override this anyway, so let's try setting the default offset to to something more useful maybe.
187 lines
5.0 KiB
Lua
187 lines
5.0 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local minetest, pairs, rawset, type
|
|
= minetest, pairs, rawset, type
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
local vzero = vector.new()
|
|
|
|
local function playerize(param)
|
|
if (not param) or (param == "") then return end
|
|
if type(param) == "string" then
|
|
local player = minetest.get_player_by_name(param)
|
|
if player then return player, param end
|
|
return
|
|
end
|
|
return param, param:get_player_name()
|
|
end
|
|
|
|
local function setprivs(pname, setfunc)
|
|
local privs = minetest.get_player_privs(pname)
|
|
local r = setfunc(privs)
|
|
if r ~= nil then return r end
|
|
minetest.set_player_privs(pname, privs)
|
|
end
|
|
|
|
local watchdata_cache = {}
|
|
local function watchdata_get(player, pname)
|
|
pname = pname or player:get_player_name()
|
|
local c = watchdata_cache[pname]
|
|
if c then return c end
|
|
c = player:get_meta():get_string(modname)
|
|
if (not c) or (c == "") then return end
|
|
c = minetest.deserialize(c)
|
|
watchdata_cache[pname] = c
|
|
return c
|
|
end
|
|
local function watchdata_set(player, pname, data)
|
|
pname = pname or player:get_player_name()
|
|
watchdata_cache[pname] = data
|
|
return player:get_meta():set_string(modname, minetest.serialize(data))
|
|
end
|
|
|
|
local function watch_restore(dtime, wplayer, wname)
|
|
wname = wname or wplayer:get_player_name()
|
|
|
|
local data = watchdata_get(wplayer, wname)
|
|
if not data then return end
|
|
|
|
if data.target then
|
|
return wplayer:set_breath(11)
|
|
end
|
|
|
|
if not data.restore then return end
|
|
|
|
local restore = data.restore
|
|
for k, v in pairs({
|
|
ttl = 1,
|
|
eye1 = {x = 0, y = 0, z = 0},
|
|
eye2 = {x = 0, y = 0, z = 0},
|
|
visual_size = {x = 1, y = 1},
|
|
makes_footstep_sound = true,
|
|
collisionbox = {-0.3, -1, -0.3, 0.3, 1, 0.3},
|
|
interact = false,
|
|
pos = {x = 0, y = 0, z = 0}
|
|
}) do
|
|
restore[k] = restore[k] or v
|
|
end
|
|
restore.ttl = restore.ttl - dtime
|
|
|
|
wplayer:set_detach()
|
|
wplayer:set_eye_offset(restore.eye1, restore.eye2)
|
|
wplayer:set_properties({
|
|
visual_size = restore.visual_size,
|
|
makes_footstep_sound = restore.makes_footstep_sound,
|
|
collisionbox = restore.collisionbox
|
|
})
|
|
setprivs(wname, function(x) x.interact = restore.interact end)
|
|
if restore.inv then
|
|
for k, v in pairs(restore.inv) do
|
|
wplayer:get_inventory():set_list(k, v)
|
|
end
|
|
data.restore.inv = nil
|
|
end
|
|
if vector.distance(wplayer:get_pos(), restore.pos) < 16 then
|
|
wplayer:set_hp(restore.hp or 20)
|
|
end
|
|
wplayer:set_pos(restore.pos)
|
|
|
|
if data.restore.ttl < 0 then data.restore = nil end
|
|
return watchdata_set(wplayer, wname, data)
|
|
end
|
|
|
|
local function watch_damage(wplayer, hp)
|
|
local wname = wplayer:get_player_name()
|
|
|
|
local data = watchdata_get(wplayer, wname)
|
|
if data and data.target then return 0 end
|
|
|
|
return hp
|
|
end
|
|
|
|
local function watch_stop(wparam, tparam)
|
|
local wplayer, wname = playerize(wparam)
|
|
if not wplayer then return false, "watcher not found" end
|
|
|
|
local data = watchdata_get(wplayer, wname)
|
|
if not data then return false, "not watching anybody" end
|
|
|
|
local _, tname = playerize(tparam)
|
|
if tname and tname ~= data.target then
|
|
return false, "not watching specified target"
|
|
end
|
|
|
|
data.restore = data.saved or data.restore
|
|
if data.restore then data.restore.ttl = 0.5 end
|
|
data.saved = nil
|
|
data.target = nil
|
|
watchdata_set(wplayer, wname, data)
|
|
|
|
watch_restore(0, wplayer)
|
|
|
|
return true
|
|
end
|
|
|
|
local function watch_start(wparam, tparam)
|
|
local wplayer, wname = playerize(wparam)
|
|
if not wplayer then return false, "watcher not found" end
|
|
local tplayer, tname = playerize(tparam)
|
|
if not tplayer then return false, "target not found" end
|
|
if wname == tname then return watch_stop(wparam) end
|
|
|
|
local data = watchdata_get(wplayer, wname) or {}
|
|
if data.target == tname then return end
|
|
data.saved = data.saved or data.restore
|
|
if not data.saved then
|
|
local props = wplayer:get_properties()
|
|
local eye1, eye2 = wplayer:get_eye_offset()
|
|
data.saved = {
|
|
pos = wplayer:get_pos(),
|
|
interact = setprivs(wname, function(x) return x.interact or false end),
|
|
visual_size = props.visual_size,
|
|
makes_footstep_sound = props.makes_footstep_sound,
|
|
collisionbox = props.collisionbox,
|
|
eye1 = eye1,
|
|
eye2 = eye2,
|
|
inv = {
|
|
main = wplayer:get_inventory():get_list("main") or {},
|
|
craft = wplayer:get_inventory():get_list("craft") or {}
|
|
},
|
|
hp = wplayer:get_hp()
|
|
}
|
|
for n, l in pairs(data.saved.inv) do
|
|
for k, v in pairs(l) do
|
|
if type(v) == "userdata" then
|
|
l[k] = v:to_string()
|
|
end
|
|
end
|
|
wplayer:get_inventory():set_list(n, {})
|
|
end
|
|
end
|
|
data.saved.ttl = nil
|
|
data.restore = nil
|
|
data.target = tname
|
|
watchdata_set(wplayer, wname, data)
|
|
|
|
wplayer:set_attach(tplayer, "", vector.new(0, 5, 0), vzero)
|
|
wplayer:set_eye_offset(vector.new(0, 5, 0), vzero)
|
|
wplayer:set_properties({
|
|
visual_size = {x = 0, y = 0},
|
|
makes_footstep_sound = false,
|
|
collisionbox = {0}
|
|
})
|
|
wplayer:set_hp(20)
|
|
setprivs(wname, function(x) x.interact = nil end)
|
|
|
|
return true
|
|
end
|
|
|
|
rawset(_G, modname, {
|
|
dataget = watchdata_get,
|
|
dataset = watchdata_set,
|
|
damage = watch_damage,
|
|
restore = watch_restore,
|
|
stop = watch_stop,
|
|
start = watch_start
|
|
})
|