Initial commit
commit
5a48c2b232
|
@ -0,0 +1,7 @@
|
|||
globals = {"visible_wielditem"}
|
||||
read_globals = {
|
||||
"minetest",
|
||||
"modlib",
|
||||
"ItemStack",
|
||||
"vector",
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
# Visible Wielditem
|
||||
|
||||
Shows wielded items in-world.
|
||||
|
||||
## Features
|
||||
|
||||
Modern alternative to [`wield3d`](https://github.com/stujones11/wield3d):
|
||||
|
||||
* Relies less on deprecated engine APIs, doesn't aim to support older MT versions
|
||||
* Supports colored items. Works well with [`epidermis`](https://github.com/epidermis).
|
||||
* Supports glow (for environmental lighting use a wielded light mod)
|
||||
* Indicates size of stacks
|
||||
* Provides a proper API for mods to use
|
||||
* Rotates the model instead of the texture
|
||||
|
||||
## License
|
||||
|
||||
Written by [appgurueu](https://github.com/appgurueu) and licensed under the MIT license.
|
||||
|
||||
## API
|
||||
|
||||
All within the `visible_wielditem` global variable.
|
||||
|
||||
### `get_attachment(modelname, itemname)`
|
||||
|
||||
Returns a table with fields `bonename`, `position` (unit: metric/nodes), `rotation` (unit: degrees) and `scale` (number, unit: metric/nodes) based on model attachments and item tweaks.
|
||||
|
||||
### `model_attachments`
|
||||
|
||||
Table. Keys are model media (file) names, values are tables with field `bonename`, `position`, `rotation` and `scale`. The special field `default` is used for default attachment settings based on `character.b3d` if no model attachments are specified for a player model or if the specified attachment settings are incomplete.
|
||||
|
||||
### `item_tweaks`
|
||||
|
||||
Table of tweaks applied based on the item. Subtable entries have strings as keys and tweak tables with fields `position`, `rotation` and `scale` as values. `position`s are added up, `rotation`s are properly composed, `scale` is multiplied.
|
||||
|
||||
#### `types`
|
||||
|
||||
Applies tweaks based on item type. Possible keys are `unknown`, `node`, `tool` and `craftitem`.
|
||||
|
||||
#### `groups`
|
||||
|
||||
Tweaks for a key are applied if the item has an item group with that name.
|
||||
|
||||
#### `names`
|
||||
|
||||
Tweaks for a single item, by full item name.
|
|
@ -0,0 +1,161 @@
|
|||
visible_wielditem = {}
|
||||
|
||||
local entities = {}
|
||||
|
||||
local function create_entity(player)
|
||||
local entity = minetest.add_entity(player:get_pos(), "visible_wielditem:visible_wielditem"):get_luaentity()
|
||||
entity:_set_player(player)
|
||||
entities[player:get_player_name()] = entity
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(create_entity)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local player_name = player:get_player_name()
|
||||
entities[player_name]:remove()
|
||||
entities[player_name] = nil
|
||||
end)
|
||||
|
||||
visible_wielditem.model_attachments = {
|
||||
default = {
|
||||
bonename = "Arm_Right",
|
||||
position = vector.new(0, 0.375, 0),
|
||||
rotation = vector.new(180, 90, 0),
|
||||
scale = 0.25
|
||||
}
|
||||
}
|
||||
|
||||
visible_wielditem.item_tweaks = {
|
||||
types = {
|
||||
unknown = {},
|
||||
node = {
|
||||
position = vector.new(0, 0.2, 0),
|
||||
rotation = vector.new(0, 0, 180)
|
||||
},
|
||||
tool = {
|
||||
position = vector.new(0, 0, 0.3),
|
||||
rotation = vector.new(0, 0, 135)
|
||||
},
|
||||
craft = {
|
||||
position = vector.new(0, 0, 0.3),
|
||||
rotation = vector.new(0, 0, 45),
|
||||
}
|
||||
},
|
||||
groups = {},
|
||||
names = {}
|
||||
}
|
||||
|
||||
local quaternion_from_euler_rot_deg = modlib.quaternion.from_euler_rotation_deg
|
||||
|
||||
local quaternion_to_euler_rot_deg = modlib.quaternion.to_euler_rotation_irrlicht
|
||||
|
||||
-- HACK quaternion multiplication should be fixed in modlib eventually
|
||||
local function quaternion_compose(other, self)
|
||||
local X, Y, Z, W = unpack(self)
|
||||
return modlib.quaternion.normalize{
|
||||
(other[4] * X) + (other[1] * W) + (other[2] * Z) - (other[3] * Y);
|
||||
(other[4] * Y) + (other[2] * W) + (other[3] * X) - (other[1] * Z);
|
||||
(other[4] * Z) + (other[3] * W) + (other[1] * Y) - (other[2] * X);
|
||||
(other[4] * W) - (other[1] * X) - (other[2] * Y) - (other[3] * Z);
|
||||
}
|
||||
end
|
||||
|
||||
function visible_wielditem.get_attachment(modelname, itemname)
|
||||
local model_attachments = visible_wielditem.model_attachments
|
||||
local attachment = modlib.table.copy(model_attachments[modelname] or model_attachments.default)
|
||||
local rotation = quaternion_from_euler_rot_deg(attachment.rotation)
|
||||
local function apply_tweaks(tweaks)
|
||||
tweaks = tweaks or {}
|
||||
if tweaks.position then attachment.position = vector.add(attachment.position, tweaks.position) end
|
||||
if tweaks.rotation then
|
||||
rotation = quaternion_compose(rotation, quaternion_from_euler_rot_deg(tweaks.rotation))
|
||||
end
|
||||
if tweaks.scale then attachment.scale = attachment.scale * tweaks.scale end
|
||||
end
|
||||
local def = minetest.registered_items[itemname]
|
||||
local item_tweaks = visible_wielditem.item_tweaks
|
||||
apply_tweaks(item_tweaks.types[def and def.type or "unknown"])
|
||||
for groupname, rating in pairs(def.groups or {}) do
|
||||
if rating ~= 0 then
|
||||
apply_tweaks(item_tweaks.groups[groupname])
|
||||
end
|
||||
end
|
||||
apply_tweaks(item_tweaks.names[itemname])
|
||||
attachment.rotation = quaternion_to_euler_rot_deg(rotation)
|
||||
return attachment
|
||||
end
|
||||
|
||||
minetest.register_entity("visible_wielditem:visible_wielditem", {
|
||||
initial_properties = {
|
||||
physical = false,
|
||||
collide_with_objects = false,
|
||||
pointable = false,
|
||||
visual = "wielditem" ,
|
||||
wield_item = "",
|
||||
is_visible = false,
|
||||
backface_culling = false,
|
||||
use_texture_alpha = true,
|
||||
glow = 0,
|
||||
static_save = false,
|
||||
shaded = true
|
||||
},
|
||||
on_activate = function(self)
|
||||
local object = self.object
|
||||
object:set_armor_groups{immortal = 1}
|
||||
end,
|
||||
_force_resend = function(self) -- HACK
|
||||
self.object:set_pos(self.object:get_pos())
|
||||
end,
|
||||
_update_attachment = function(self)
|
||||
if not self._item then return end
|
||||
local object = self.object
|
||||
local attachment = visible_wielditem.get_attachment(self._player:get_properties().mesh, self._item:get_name() or "")
|
||||
-- TODO softcode
|
||||
local stack_scale = 1
|
||||
if self._item:get_definition().type ~= "tool" then
|
||||
stack_scale = 0.75 + 0.5 * math.min(1, self._item:get_count() / self._item:get_stack_max())
|
||||
end
|
||||
local vsize = attachment.scale * stack_scale
|
||||
object:set_properties{visual_size = vector.new(vsize, vsize, vsize)}
|
||||
object:set_attach(self._player,
|
||||
attachment.bonename,
|
||||
vector.multiply(vector.offset(attachment.position, 0, vsize / 2, 0), 10),
|
||||
attachment.rotation)
|
||||
self:_force_resend()
|
||||
end,
|
||||
_set_player = function(self, player)
|
||||
self._player = player -- HACK this assumes that PlayerRefs don't change
|
||||
self:_set_item(player:get_wielded_item())
|
||||
self:_update_attachment()
|
||||
end,
|
||||
on_deactivate = function(self)
|
||||
create_entity(self._player)
|
||||
end,
|
||||
_set_item = function(self, item)
|
||||
self._item = item
|
||||
local object = self.object
|
||||
if item:is_empty() then
|
||||
object:set_properties{
|
||||
is_visible = false,
|
||||
wield_item = ""
|
||||
}
|
||||
return
|
||||
end
|
||||
object:set_properties{
|
||||
is_visible = true,
|
||||
wield_item = item:to_string(),
|
||||
glow = item:get_definition().light_source or 0
|
||||
}
|
||||
self:_update_attachment()
|
||||
end,
|
||||
-- TODO on_step: reattach regularly to work around engine bugs?
|
||||
})
|
||||
|
||||
modlib.minetest.register_on_wielditem_change(function(player, _, _, item)
|
||||
local entity = entities[player:get_player_name()]
|
||||
if entity.object:get_pos() then
|
||||
entity:_set_item(item)
|
||||
else -- recreate entity if necessary
|
||||
create_entity(player)
|
||||
end
|
||||
end)
|
Loading…
Reference in New Issue