125 lines
3.9 KiB
Lua
125 lines
3.9 KiB
Lua
|
|
local ns = rgt_cosmetics
|
|
|
|
ns.wearables = {}
|
|
|
|
--[[
|
|
{
|
|
name = "", -- Name of the wearable
|
|
attachments = { -- List of individual attachments managed by this wearable (in case one wearable involves multiple bones)
|
|
mesh = "", -- The wearable's mesh
|
|
textures = {"", ...}, -- The wearable's textures
|
|
bone = ", -- Name of the player bone to attach to
|
|
pos = <vector>, -- Attachment offset
|
|
rot = <vector>, -- Attachment rotation
|
|
}
|
|
}
|
|
--]]
|
|
function ns.register_wearable(def)
|
|
ns.wearables[def.name] = def
|
|
end
|
|
|
|
minetest.register_entity("rgt_cosmetics:wearable", {
|
|
initial_properties = {
|
|
visual = "mesh",
|
|
pointable = false,
|
|
static_save = false
|
|
},
|
|
on_activate = function(e)
|
|
e.object:set_armor_groups{immortal = 1}
|
|
end,
|
|
represent = function(e, form)
|
|
e.form = form
|
|
e.object:set_properties {
|
|
mesh = form.mesh,
|
|
textures = form.textures
|
|
}
|
|
e.object:set_attach(e.owner.object, form.bone, form.pos, form.rot)
|
|
if form.animation then
|
|
e.object:set_animation(form.animation, form.animation.frame_speed or 1, nil, form.animation.loop)
|
|
end
|
|
end,
|
|
on_deactivate = function(e, removed)
|
|
-- Reactivate immediately if we were not explicitly marked for removal.
|
|
-- This is to prevent wearables from being lost to unloading, and to
|
|
-- minimize interference from mods that might try to remove objects
|
|
-- they shouldn't try to remove. Note that we must check get_pos() here
|
|
-- because, since on_leaveplayer is called _after_ mapblock unloading,
|
|
-- the entity may otherwise attempt to reactivate itself when its
|
|
-- owner has left the game (causing a crash).
|
|
if not e._remove and e.owner.object:get_pos() then
|
|
e.owner.wearing[e.form.name][e.index] = ns.apply_wearable_part(e.owner, e.form, e.index)
|
|
end
|
|
end
|
|
})
|
|
|
|
function ns.apply_wearable_part(m, w, i)
|
|
local obj = minetest.add_entity(m.pos, "rgt_cosmetics:wearable")
|
|
local e = obj:get_luaentity()
|
|
e.owner = m
|
|
e.index = i
|
|
e:represent(w)
|
|
return obj
|
|
end
|
|
|
|
function ns.apply_wearable(m, wearable)
|
|
local w = ns.wearables[wearable]
|
|
-- Do nothing if we're already wearing this.
|
|
if not w or m.wearing[w.name] then return end
|
|
local item = {}
|
|
for i, x in ipairs(w.attachments) do
|
|
x.name = w.name
|
|
item[i] = ns.apply_wearable_part(m, x, i)
|
|
end
|
|
m.wearing[w.name] = item
|
|
if w.logical_height_offset then
|
|
m:set_logical_height_offset(m.logical_height_offset +w.logical_height_offset)
|
|
end
|
|
end
|
|
|
|
function ns.remove_wearable(m, wearable)
|
|
if m.wearing[wearable] then
|
|
for _, x in pairs(m.wearing[wearable]) do
|
|
-- Explicitly mark the object for removal.
|
|
x:get_luaentity()._remove = true
|
|
x:remove()
|
|
end
|
|
m.wearing[wearable] = nil
|
|
if ns.wearables[wearable].logical_height_offset then
|
|
m:set_logical_height_offset(m.logical_height_offset -ns.wearables[wearable].logical_height_offset)
|
|
end
|
|
end
|
|
end
|
|
|
|
minetest.register_on_leaveplayer(function(p)
|
|
local m = rgt.players[p:get_player_name()]
|
|
for k in pairs(m.wearing) do
|
|
ns.remove_wearable(m, k)
|
|
end
|
|
end)
|
|
|
|
ns.register_wearable {
|
|
name = "top_hat",
|
|
logical_height_offset = 4.5,
|
|
attachments = {
|
|
{
|
|
mesh = "rgt_top_hat.gltf",
|
|
textures = {"rgt_top_hat.png"},
|
|
bone = "Head",
|
|
pos = vector.new(0, 3.5, 0),
|
|
rot = vector.new(0, 0, 0)
|
|
}
|
|
}
|
|
}
|
|
|
|
minetest.register_chatcommand("wear", {
|
|
func = function(name, args)
|
|
ns.apply_wearable(rgt.players[name], args)
|
|
end
|
|
})
|
|
|
|
minetest.register_chatcommand("unwear", {
|
|
func = function(name, args)
|
|
ns.remove_wearable(rgt.players[name], args)
|
|
end
|
|
})
|