added improved skin selection depending on model/mesh

This commit is contained in:
Sokomine 2022-07-19 21:02:48 +02:00
parent 4953f23737
commit 0a52637271
3 changed files with 255 additions and 13 deletions

View File

@ -18,10 +18,37 @@ yl_speak_up.enable_staff_based_editing = true
yl_speak_up.enable_yl_mobs = true
-- Do the NPCs talk right after they spawned?
yl_speak_up.talk_after_spawn = true
-- diffrent NPC may use diffrent models
-- IMPORTANT: If you want to support an NPC with a diffrent model, provide
-- an entry in this array! Else setting its skin will fail horribly.
-- TODO: provide function for preview image
yl_speak_up.mesh_data = {}
yl_speak_up.mesh_data["error"] = {
texture_index = 1,
-- TODO: actually handle that and call the right formspec
can_show_wielded_items = false,
}
-- this model is used by mobs_npc
yl_speak_up.mesh_data["mobs_character.b3d"] = {
-- the first texture is the skin
texture_index = 1,
-- there is no support for capes or wielded items
can_show_wielded_items = false,
}
yl_speak_up.mesh_data["skinsdb_3d_armor_character_5.b3d"] = {
-- the second texture is the skin
texture_index = 2,
-- they can wear and show capes and wield items
can_show_wielded_items = true,
}
-- TODO: provide skin texture list for the diffrent NPC (self.name)
-- some properties from external NPC can be edited and changed (they have the self. prefix),
-- and it is possible to react to property changes with handlers;
-- key: name of the property (i.e. self.order);

View File

@ -7,18 +7,21 @@
-- helper function for yl_speak_up.show_fs_decorated
yl_speak_up.calculate_portrait = function(pname, n_id)
local tex = yl_speak_up.speak_to[pname].textures
local head = ""
if(tex and tex[2]) then
return head .. "[combine:8x8:-8,-8=" .. tex[2] .. ":-40,-8=" .. tex[2]
end
if(tex and tex[1]) then
return head .. "[combine:8x8:-8,-8=" .. tex[1] .. ":-40,-8=" .. tex[1]
end
return head
local mesh = yl_speak_up.get_mesh(pname)
-- which texture from the textures list are we talking about?
-- this depends on the model!
if(not(mesh)
or not(yl_speak_up.mesh_data[mesh])
or not(yl_speak_up.mesh_data[mesh].texture_index)) then
return ""
end
local texture_index = yl_speak_up.mesh_data[mesh].texture_index
local tex = yl_speak_up.speak_to[pname].textures
if(not(tex) or not(tex[texture_index])) then
return ""
end
return "[combine:8x8:-8,-8=" .. tex[texture_index] .. ":-40,-8=" .. tex[texture_index]
end

View File

@ -2,6 +2,24 @@
-- Fashion
-- ###
-- some meshes use more than one texture, and which texture is the main skin
-- texture can only be derived from the name of the mesh
yl_speak_up.get_mesh = function(pname)
if(not(pname)) then
return "error"
end
local obj = yl_speak_up.speak_to[pname].obj
if(not(obj)) then
return "error"
end
local entity = obj:get_luaentity()
if(not(entity)) then
return "error"
end
return entity.mesh
end
local function cape2texture(t)
return "yl_speak_up_mask_cape.png^[combine:32x64:56,20=" .. t
end
@ -172,7 +190,8 @@ local function create_preview(main_skin)
return skin
end
yl_speak_up.get_fs_fashion = function(pname)
-- TODO: link that somehow for NPC that support it
yl_speak_up.get_fs_fashion_extended = function(pname)
local textures = yl_speak_up.speak_to[pname].textures
local maintable, mainlist, mainindex = get_npc_skins(textures[2])
@ -260,11 +279,103 @@ yl_speak_up.fashion_wield_give_items_back = function(player, pname)
end
-- normal skins for NPC - without wielded items or capes etc.
yl_speak_up.input_fashion = function(player, formname, fields)
if formname ~= "yl_speak_up:fashion" then
return
end
local pname = player:get_player_name()
local n_id = yl_speak_up.speak_to[pname].n_id
-- is the player editing this npc? if not: abort
if(not(yl_speak_up.edit_mode[pname])
or (yl_speak_up.edit_mode[pname] ~= n_id)) then
return ""
end
-- catch ESC as well
if(not(fields) or (fields.quit or fields.button_cancel or fields.button_exit)) then
yl_speak_up.show_fs(player, "talk", {n_id = yl_speak_up.speak_to[pname].n_id,
d_id = yl_speak_up.speak_to[pname].d_id})
return
end
-- TODO: get that list from somewhere
local skins = {"mobs_npc.png", "mobs_npc2.png", "mobs_npc3.png", "mobs_npc4.png",
"mobs_npc_baby.png"}
local mesh = yl_speak_up.get_mesh(pname)
-- which texture from the textures list are we talking about?
-- this depends on the model!
local texture_index = yl_speak_up.mesh_data[mesh].texture_index
local textures = yl_speak_up.speak_to[pname].textures
local skin = (textures[texture_index] or "")
local skin_index = table.indexof(skins, skin)
if(skin_index == -1) then
skin_index = 1
end
local new_skin = skin
-- swithc back to the stored old skin
if(fields.button_old_skin) then
local old_texture = yl_speak_up.speak_to[pname].old_texture
if(old_texture) then
new_skin = old_texture
end
-- store the new skin
elseif(fields.button_store_new_skin) then
yl_speak_up.speak_to[pname].old_texture = skin
-- show previous skin
elseif(fields.button_prev_skin) then
if(skin_index > 1) then
new_skin = skins[skin_index - 1]
else
new_skin = skins[#skins]
end
-- show next skin
elseif(fields.button_next_skin) then
if(skin_index < #skins) then
new_skin = skins[skin_index + 1]
else
new_skin = skins[1]
end
-- set directly via list
elseif(fields.set_skin_normal) then
local new_index = table.indexof(skins, fields.set_skin_normal)
if(new_index ~= -1) then
new_skin = skins[new_index]
end
end
-- if there is a new skin to consider
if(textures[texture_index] ~= new_skin) then
textures[texture_index] = new_skin
-- actually make sure that the NPC updates its texture
local obj = yl_speak_up.speak_to[pname].obj
if(obj) then
obj:set_properties({ textures = textures })
end
-- scrolling through the diffrent skins updates the skin; avoid spam in the log
-- yl_speak_up.log_change(pname, n_id,
-- "(fashion) skin changed to "..tostring(new_skin)..".")
end
if(fields.button_old_skin or fields.button_store_new_skin) then
yl_speak_up.speak_to[pname].old_texture = nil
yl_speak_up.show_fs(player, "talk", {n_id = yl_speak_up.speak_to[pname].n_id,
d_id = yl_speak_up.speak_to[pname].d_id})
return
end
yl_speak_up.show_fs(player, "fashion")
end
-- TODO: make use of this somehow
yl_speak_up.input_fashion_extended = function(player, formname, fields)
if formname ~= "yl_speak_up:fashion" then
return
end
local pname = player:get_player_name()
local textures = yl_speak_up.speak_to[pname].textures
@ -283,6 +394,12 @@ yl_speak_up.input_fashion = function(player, formname, fields)
d_id = yl_speak_up.speak_to[pname].d_id})
return
-- normal skins for NPC - without wielded items or capes etc.
-- TODO add a back button to get back to the normal formspec
elseif(true) then
yl_speak_up.input_fashion_normal(player, formname, fields)
return
elseif(fields.button_wield_left
or fields.button_wield_right) then
local trade_inv = minetest.get_inventory({type="detached", name="yl_speak_up_player_"..pname})
@ -393,3 +510,98 @@ yl_speak_up.get_wield_texture = function(item)
end
return "3d_armor_trans.png"
end
-- this only sets the *skin*, depending on the mesh of the NPC;
-- capes and wielded items are supported by an extended formspec for those
-- NPC that can handle them
yl_speak_up.get_fs_fashion = function(pname)
-- TODO: get that list from somewhere (it may depend on the model...)
local skins = {"mobs_npc.png", "mobs_npc2.png", "mobs_npc3.png", "mobs_npc4.png",
"mobs_npc_baby.png"}
local mesh = yl_speak_up.get_mesh(pname)
-- which texture from the textures list are we talking about?
-- this depends on the model!
local texture_index = yl_speak_up.mesh_data[mesh].texture_index
local textures = yl_speak_up.speak_to[pname].textures
local skin = (textures[texture_index] or "")
-- store the old texture so that we can go back to it
local old_texture = yl_speak_up.speak_to[pname].old_texture
if(not(old_texture)) then
yl_speak_up.speak_to[pname].old_texture = skin
old_texture = skin
end
local button_cancel = "Cancel"
-- is this player editing this particular NPC? then rename the button
if( yl_speak_up.edit_mode[pname]
and yl_speak_up.edit_mode[pname] == yl_speak_up.speak_to[pname].n_id) then
button_cancel = "Back"
end
local skin_list = table.concat(skins, ",")
local skin_index = table.indexof(skins, skin)
if(skin_index == -1) then
skin_index = ""
end
-- TODO: the preview depends on the model as well
local preview =
"image[4.5,1.8;3,3;[combine:8x9:-8,-9="..skin..":-40,-9="..skin.."]".. -- head, beard
"image[4.5,4.12;3,4.5;[combine:8x12:-20,-20="..skin.."]".. -- body
"image[4.5,8.02;1.5,4.5;[combine:4x12:-4,-20="..skin.."]".. -- left leg
"image[5.73,8.02;1.5,4.5;[combine:4x12:-4,-20="..skin.."^[transformFX]".. -- right leg
"image[3.15,4.12;1.5,4.5;[combine:4x12:-44,-20="..skin.."]".. -- left hand
"image[7.35,4.12;1.5,4.5;[combine:4x12:-44,-20="..skin.."^[transformFX]".. -- right hand
"image[10.5,1.8;3,3;[combine:8x8:-24,-8="..skin.."]".. -- back head
"image[10.5,4.12;3,4.5;[combine:8x12:-32,-20="..skin.."]".. -- body back
"image[10.5,8.02;1.5,4.5;[combine:4x12:-12,-20="..skin.."]".. -- left leg back
"image[11.73,8.02;1.5,4.5;[combine:4x12:-12,-20="..skin.."^[transformFX]".. -- right leg back
"image[9.3,4.12;1.5,4.5;[combine:4x12:-52,-20="..skin.."]".. -- left hand back
"image[12.95,4.12;1.5,4.5;[combine:4x12:-52,-20="..skin.."^[transformFX]" -- right hand back
local formspec = {
"container[0.5,4.0]",
"dropdown[0.75,14.1;16.25,1.5;set_skin_normal;",
skin_list or "",
";",
tostring(skin_index) or "",
"]",
"label[0.75,13.6;The name of this skin is:]",
"button[0.75,0.75;1.2,12;button_prev_skin;<]",
"button[15.75,0.75;1.2,12;button_next_skin;>]",
"tooltip[button_prev_skin;Select previous skin in list.]",
"tooltip[button_next_skin;Select next skin in list.]",
"tooltip[set_skin_normal;Select a skin from the list.]",
preview,
-- we add a special button for setting the skin in the player answer/reply window
"container_end[]",
}
local left_window = table.concat(formspec, "")
formspec = {}
local h = -0.8
local button_text = "This shall be your new skin. Wear it proudly!"
if(skin == old_texture) then
button_text = "This is your old skin. It is fine. Keep it!"
end
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"button_store_new_skin",
"The NPC will wear the currently selected skin.",
button_text,
true, nil, nil, nil)
h = yl_speak_up.add_edit_button_fs_talkdialog(formspec, h,
"button_old_skin",
"The NPC will wear the skin he wore before you started changing it.",
"On a second throught - Keep your old skin. It was fine.",
(skin ~= old_texture), nil, nil, nil)
return yl_speak_up.show_fs_decorated(pname, true, h,
"",
left_window,
table.concat(formspec, ""),
nil,
h)
end