red_glazed_terracotta/mods/rgt_cosmetics/wearables.lua
2025-10-11 00:03:51 -04:00

118 lines
3.5 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
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
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",
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
})