add 3d quiver

This commit is contained in:
Juraj Vajda 2022-10-27 15:38:51 -04:00
parent b84c0409e8
commit cf759edfec
14 changed files with 189 additions and 20 deletions

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
.DS_Store .DS_Store
docs/build docs/build
*.blend1
*.blend2

View File

@ -63,5 +63,8 @@ read_globals = {
"default", "default",
"i3", "i3",
"unified_inventory", "unified_inventory",
"player_api" "player_api",
"u_skins",
"wardrobe",
"3d_armor"
} }

106
api.lua
View File

@ -32,6 +32,9 @@ XBows = {
player_monoids = minetest.get_modpath('player_monoids'), player_monoids = minetest.get_modpath('player_monoids'),
i3 = minetest.get_modpath('i3'), i3 = minetest.get_modpath('i3'),
unified_inventory = minetest.get_modpath('unified_inventory'), unified_inventory = minetest.get_modpath('unified_inventory'),
u_skins = minetest.get_modpath('u_skins'),
wardrobe = minetest.get_modpath('wardrobe'),
_3d_armor = minetest.get_modpath('3d_armor'),
registered_bows = {}, registered_bows = {},
registered_arrows = {}, registered_arrows = {},
registered_quivers = {}, registered_quivers = {},
@ -2157,3 +2160,106 @@ function XBowsQuiver.ui_register_page(self)
tooltip = 'X Bows', tooltip = 'X Bows',
}) })
end end
function XBows.show_3d_quiver(self, player)
local p_name = player:get_player_name()
local player_textures
if self._3d_armor then
minetest.after(0.1, function()
player_textures = {
armor.textures[p_name].skin,
armor.textures[p_name].armor,
armor.textures[p_name].wielditem,
'x_bows_quiver_mesh.png'
}
if player_textures then
player_api.set_textures(player, player_textures)
end
end)
return
elseif self.u_skins then
local u_skin_texture = u_skins.u_skins[p_name]
player_textures = {
u_skin_texture .. '.png',
'x_bows_quiver_mesh.png'
}
elseif self.wardrobe and wardrobe.playerSkins and wardrobe.playerSkins[p_name] then
player_textures = {
wardrobe.playerSkins[p_name],
'x_bows_quiver_mesh.png'
}
else
local textures = player_api.get_textures(player)
---cleanup
for index, value in ipairs(textures) do
if value == 'x_bows_quiver_empty_mesh.png' or value == 'x_bows_quiver_mesh.png' then
table.remove(textures, index)
end
end
table.insert(textures, 'x_bows_quiver_mesh.png')
player_textures = textures
end
if player_textures then
player_api.set_textures(player, player_textures)
end
end
function XBows.hide_3d_quiver(self, player)
local p_name = player:get_player_name()
local player_textures
if self._3d_armor then
minetest.after(0.1, function()
player_textures = {
armor.textures[p_name].skin,
armor.textures[p_name].armor,
armor.textures[p_name].wielditem,
'x_bows_quiver_empty_mesh.png'
}
if player_textures then
player_api.set_textures(player, player_textures)
end
end)
return
elseif self.u_skins then
local u_skin_texture = u_skins.u_skins[p_name]
player_textures = {
u_skin_texture .. '.png',
'x_bows_quiver_empty_mesh.png'
}
elseif self.wardrobe and wardrobe.playerSkins and wardrobe.playerSkins[p_name] then
player_textures = {
wardrobe.playerSkins[p_name],
'x_bows_quiver_empty_mesh.png'
}
else
local textures = player_api.get_textures(player)
---cleanup
for index, value in ipairs(textures) do
if value == 'x_bows_quiver_mesh.png' or value == 'x_bows_quiver_empty_mesh.png' then
table.remove(textures, index)
end
end
table.insert(textures, 'x_bows_quiver_empty_mesh.png')
player_textures = textures
end
if player_textures then
player_api.set_textures(player, player_textures)
end
end

View File

@ -6,6 +6,8 @@ ItemStack = ItemStack--[[@as ItemStack]]
vector = vector--[[@as Vector]] vector = vector--[[@as Vector]]
default = default--[[@as MtgDefault]] default = default--[[@as MtgDefault]]
sfinv = sfinv--[[@as Sfinv]] sfinv = sfinv--[[@as Sfinv]]
unified_inventory = unified_inventory--[[@as UnifiedInventory]]
player_api = player_api--[[@as MtgPlayerApi]]
math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 9))--[[@as number]]) math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 9))--[[@as number]])
@ -20,7 +22,6 @@ dofile(path .. '/arrow.lua')
dofile(path .. '/items.lua') dofile(path .. '/items.lua')
dofile(path .. '/quiver.lua') dofile(path .. '/quiver.lua')
if XBows.i3 then if XBows.i3 then
XBowsQuiver:i3_register_page() XBowsQuiver:i3_register_page()
elseif XBows.unified_inventory then elseif XBows.unified_inventory then
@ -33,34 +34,48 @@ minetest.register_on_joinplayer(function(player)
local inv_quiver = player:get_inventory()--[[@as InvRef]] local inv_quiver = player:get_inventory()--[[@as InvRef]]
local inv_arrow = player:get_inventory()--[[@as InvRef]] local inv_arrow = player:get_inventory()--[[@as InvRef]]
if XBows._3d_armor then
player_api.set_model(player, 'x_bows_3d_armor_character.b3d')
else
player_api.set_model(player, 'x_bows_character.b3d')
end
inv_quiver:set_size('x_bows:quiver_inv', 1 * 1) inv_quiver:set_size('x_bows:quiver_inv', 1 * 1)
inv_arrow:set_size('x_bows:arrow_inv', 1 * 1) inv_arrow:set_size('x_bows:arrow_inv', 1 * 1)
local quiver = player:get_inventory():get_stack('x_bows:quiver_inv', 1) local quiver_stack = player:get_inventory():get_stack('x_bows:quiver_inv', 1)
if quiver and not quiver:is_empty() then if quiver_stack and not quiver_stack:is_empty() then
local st_meta = quiver:get_meta() local st_meta = quiver_stack:get_meta()
local quiver_id = st_meta:get_string('quiver_id') local quiver_id = st_meta:get_string('quiver_id')
---create detached inventory
XBowsQuiver:get_or_create_detached_inv( XBowsQuiver:get_or_create_detached_inv(
quiver_id, quiver_id,
player:get_player_name(), player:get_player_name(),
st_meta:get_string('quiver_items') st_meta:get_string('quiver_items')
) )
---set model textures
XBows:show_3d_quiver(player)
else
---set model textures
XBows:hide_3d_quiver(player)
end end
player_api.set_model(player, 'x_bows_character.b3d') XBows:reset_charged_bow(player, true)
XBowsQuiver:close_quiver(player)
player_api.set_textures(player, {
'character.png',
'x_bows_quiver_mesh.png'
})
end) end)
---player api local model_name = 'x_bows_character.b3d'
player_api.register_model('x_bows_character.b3d', { if XBows._3d_armor then
---3d armor
model_name = 'x_bows_3d_armor_character.b3d'
end
player_api.register_model(model_name, {
animation_speed = 30, animation_speed = 30,
textures = {"character.png"}, textures = {'character.png'},
animations = { animations = {
-- Standard animations. -- Standard animations.
stand = {x = 0, y = 79}, stand = {x = 0, y = 79},
@ -206,7 +221,11 @@ minetest.register_on_player_inventory_action(function(player, action, inventory,
sfinv.set_player_inventory_formspec(player) sfinv.set_player_inventory_formspec(player)
end end
---set player visual
XBows:show_3d_quiver(player)
elseif action == 'move' and inventory_info.from_list == 'x_bows:quiver_inv' then elseif action == 'move' and inventory_info.from_list == 'x_bows:quiver_inv' then
local stack = inventory:get_stack(inventory_info.from_list, inventory_info.from_index)
if XBows.i3 then if XBows.i3 then
i3.set_fs(player) i3.set_fs(player)
elseif XBows.unified_inventory then elseif XBows.unified_inventory then
@ -214,6 +233,11 @@ minetest.register_on_player_inventory_action(function(player, action, inventory,
else else
sfinv.set_player_inventory_formspec(player) sfinv.set_player_inventory_formspec(player)
end end
---set player visual
if stack:is_empty() then
XBows:hide_3d_quiver(player)
end
elseif action == 'put' and inventory_info.listname == 'x_bows:quiver_inv' then elseif action == 'put' and inventory_info.listname == 'x_bows:quiver_inv' then
if XBows.i3 then if XBows.i3 then
i3.set_fs(player) i3.set_fs(player)
@ -236,11 +260,6 @@ end)
---backwards compatibility ---backwards compatibility
minetest.register_alias('x_bows:arrow_diamond_tipped_poison', 'x_bows:arrow_diamond') minetest.register_alias('x_bows:arrow_diamond_tipped_poison', 'x_bows:arrow_diamond')
minetest.register_on_joinplayer(function(player)
XBows:reset_charged_bow(player, true)
XBowsQuiver:close_quiver(player)
end)
-- sneak, fov adjustments when bow is charged -- sneak, fov adjustments when bow is charged
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
bow_charged_timer = bow_charged_timer + dtime bow_charged_timer = bow_charged_timer + dtime

View File

@ -1,6 +1,6 @@
name = x_bows name = x_bows
description = Adds bow and arrows to Minetest. description = Adds bow and arrows to Minetest.
depends = depends =
optional_depends = default, farming, 3d_armor, mesecons, playerphysics, player_monoids, wool, i3, unified_inventory optional_depends = default, farming, 3d_armor, mesecons, playerphysics, player_monoids, wool, i3, unified_inventory, simple_skins, u_skins, wardrobe
supported_games = minetest_game supported_games = minetest_game
min_minetest_version = 5.4 min_minetest_version = 5.4

Binary file not shown.

Binary file not shown.

BIN
models/x_bows_arrow.blend Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

View File

@ -0,0 +1,32 @@
---The player API can register player models and update the player's appearance.
---@class MtgPlayerApi
---@field globalstep fun(dtime: number, ...): nil The function called by the globalstep that controls player animations. You can override this to replace the globalstep with your own implementation. Receives all args that minetest.register_globalstep() passes
---@field register_model fun(name: string, def: MtgPlayerApiModelDef): nil Register a new model to be used by players, `name`: model filename such as "character.x", "foo.b3d", etc., `def`: see [#Model definition] Saved to player_api.registered_models
---@field registered_models string[] Get a model's definition, `name`: model filename See [#Model definition]
---@field set_model fun(player: ObjectRef, model_name: string): nil Change a player's model, `player`: PlayerRef, `model_name`: model registered with `player_api.register_model`
---@field set_animation fun(player: ObjectRef, anim_name: string, speed: number): nil Applies an animation to a player if speed or anim_name differ from the currently playing animation, `player`: PlayerRef, `anim_name`: name of the animation, `speed`: keyframes per second. If nil, the default from the model def is used
---@field set_textures fun(player: ObjectRef, textures: string[]): nil Sets player textures `player`: PlayerRef, `textures`: array of textures. If nil, the default from the model def is used
---@field set_texture fun(player: ObjectRef, index: number, texture: string): nil Sets one of the player textures, `player`: PlayerRef, `index`: Index into array of all textures, `texture`: the texture string
---@field get_textures fun(player: ObjectRef): string[] Returns player textures table
---@field get_animation fun(player: ObjectRef): {["model"]: string | nil, ["textures"]: string[] | nil, ["animation"]: table | nil} Returns a table containing fields `model`, `textures` and `animation`. Any of the fields of the returned table may be nil, `player`: PlayerRef
---@field player_attached table<string, boolean> A table that maps a player name to a boolean. If the value for a given player is set to true, the default player animations (walking, digging, ...) will no longer be updated, and knockback from damage is prevented for that player. Example of usage: A mod sets a player's value to true when attached to a vehicle.
---Model Definition
---@class MtgPlayerApiModelDef
---@field animation_speed number Default: 30, animation speed, in keyframes per second
---@field textures string[] Default `{"character.png"}`, array of textures
---@field animations table<string, MtgPlayerApiAnimationDef>
---@field visual_size {["x"]: number, ["y"]: number}
---@field collisionbox number[]
---@field stepheight number
---@field eye_height number
---Model Animation definition
---@class MtgPlayerApiAnimationDef
---@field x number start frame
---@field y number end frame
---@field collisionbox number[] | nil
---@field eye_height number | nil model eye height
---@field override_local boolean | nil suspend client side animations while this one is active (optional)

View File

@ -0,0 +1,7 @@
---Base class Unified Inventory
---@class UnifiedInventory
---@field set_inventory_formspec fun(player: ObjectRef, formspecname: string): nil
---@field register_button fun(name: string, def: table): nil
---@field single_slot fun(x: number, y: number): nil
---@field register_page fun(name: string, def: table): nil
---@field style_full table