Add customizable skins support (WIP)
|
@ -0,0 +1,9 @@
|
|||
Mesh hand mod for Hades Revisited
|
||||
|
||||
This mod uses a better-looking mesh for the wieldhand and applies the player skin color to it.
|
||||
|
||||
== Credits ==
|
||||
Based on 3D Hand [newhand] mod by jordan4ibanez.
|
||||
https://forum.minetest.net/viewtopic.php?t=16435
|
||||
|
||||
License: CC0
|
|
@ -0,0 +1,41 @@
|
|||
hades_meshhand = {}
|
||||
|
||||
local handdef = minetest.registered_items[""]
|
||||
|
||||
-- This is a fake node that should never be placed in the world
|
||||
minetest.register_node("hades_meshhand:hand", {
|
||||
description = "",
|
||||
tiles = {"hades_skins_skin_base.png"},
|
||||
use_texture_alpha = "opaque",
|
||||
visual_scale = 1,
|
||||
wield_scale = {x=1,y=1,z=1},
|
||||
paramtype = "light",
|
||||
drawtype = "mesh",
|
||||
mesh = "hades_meshhand.b3d",
|
||||
-- Prevent construction
|
||||
node_placement_prediction = "",
|
||||
on_construct = function(pos)
|
||||
minetest.log("error", "[hades_meshhand] Trying to construct hades_meshhand:hand at "..minetest.pos_to_string(pos))
|
||||
minetest.remove_node(pos)
|
||||
end,
|
||||
drop = "",
|
||||
on_drop = function()
|
||||
return ""
|
||||
end,
|
||||
-- Allow to get rid of the node if it somehow ended up in world
|
||||
buildable_to = true,
|
||||
groups = { dig_immediate = 3, not_in_creative_inventory = 1 },
|
||||
range = handdef.range,
|
||||
})
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
player:get_inventory():set_size("hand", 1)
|
||||
end)
|
||||
|
||||
function hades_meshhand.set_skin_color(player, colorstring)
|
||||
local hand = ItemStack("hades_meshhand:hand")
|
||||
local handmeta = hand:get_meta()
|
||||
handmeta:set_string("color", colorstring)
|
||||
player:get_inventory():set_stack("hand", 1, hand)
|
||||
end
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
name = hades_meshhand
|
||||
author = jordan4ibanez
|
||||
description = Applies the player skin texture to the hand.
|
|
@ -77,6 +77,12 @@ function hades_player.player_set_textures(player, textures)
|
|||
player:set_properties({textures = textures,})
|
||||
end
|
||||
|
||||
function hades_player.player_get_textures(player)
|
||||
local name = player:get_player_name()
|
||||
local props = player:get_properties()
|
||||
return props.textures
|
||||
end
|
||||
|
||||
function hades_player.player_set_animation(player, anim_name, speed)
|
||||
local name = player:get_player_name()
|
||||
if player_anim[name] == anim_name then
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
License and credits:
|
||||
|
||||
The overall license of the media is CC BY-SA 3.0.
|
||||
|
||||
In the list below, there's a list of all authors and indivudual file licenses.
|
||||
Note: Files marked with an asterisk were modified from the original.
|
||||
|
||||
Wuzzy (CC0 1.0):
|
||||
- hades_skins_eyes_base.png
|
||||
- hades_skins_eyes_pupils.png
|
||||
- hades_skins_mouth.png
|
||||
- hades_skins_pupils.png
|
||||
- hades_skins_pants_shorts.png
|
||||
- hades_skins_pants_hotpants.png
|
||||
- hades_skins_shirt_top.png
|
||||
- hades_skins_shirt_tanktop.png
|
||||
- hades_skins_accessoire_head_flowers.png
|
||||
|
||||
Kosanaya (CC BY-SA 3.0):
|
||||
* hades_skins_accessoire_head_bikutoria.png (original skin: Bikutoria_by_Kosanaya.png)
|
||||
|
||||
Minetestian (CC BY-SA 3.0):
|
||||
* hades_skins_shirt_minetestian.png (original skin: Minetestian_by_Minetestian.png)
|
||||
|
||||
nelly (CC BY-SA 3.0):
|
||||
* hades_skins_hair_emma.png (original skin: Emma_by_nelly.png)
|
||||
|
||||
QoiOui (CC BY-SA 3.0):
|
||||
* hades_skins_hair_quioui.png (original skin: QoiOui_by_QoiOui.png)
|
||||
|
||||
Geopbyte (CC BY-SA 3.0):
|
||||
* character.png (original skin: Geopbyte_by_Geopbyte.png)
|
||||
* hades_skins_belt_simple.png (original skin: Geopbyte_by_Geopbyte.png)
|
||||
* hades_skins_hair_simple.png (original skin: Geopbyte_by_Geopbyte.png)
|
||||
* hades_skins_pants_simple.png (original skin: Geopbyte_by_Geopbyte.png)
|
||||
* hades_skins_shirt_simple.png (original skin: Geopbyte_by_Geopbyte.png)
|
||||
* hades_skins_shoes_simple.png (original skin: Geopbyte_by_Geopbyte.png)
|
||||
* hades_skins_skin_base.png (original skin: Geopbyte_by_Geopbyte.png)
|
||||
|
||||
|
|
@ -0,0 +1,195 @@
|
|||
local S = minetest.get_translator("hades_skins")
|
||||
local F = minetest.formspec_escape
|
||||
|
||||
hades_skins = {}
|
||||
|
||||
local editor_color_states = {}
|
||||
local editor_cloth_states = {}
|
||||
|
||||
local get_color = function(r, g, b)
|
||||
if not r then
|
||||
r = math.random(0,255)
|
||||
end
|
||||
if not g then
|
||||
g = math.random(0,255)
|
||||
end
|
||||
if not b then
|
||||
b = math.random(0,255)
|
||||
end
|
||||
local cstr = string.format("#%.2X%.2X%.2X", r, g, b)
|
||||
return cstr
|
||||
end
|
||||
|
||||
local styles = {
|
||||
hair = { "simple", "emma", "quioui" },
|
||||
accessoire_head = { "blank", "bikutoria", "headband", "flowers" },
|
||||
shirt = { "simple", "tanktop", "top", "minetestian"},
|
||||
belt = { "blank", "simple" },
|
||||
pants = { "simple", "shorts", "hotpants" },
|
||||
shoes = { "simple" },
|
||||
skin = { "base" },
|
||||
eyes = { "pupils" },
|
||||
}
|
||||
|
||||
local styles_sorted = {
|
||||
"skin", "accessoire_head", "hair", "eyes", "shirt", "belt", "pants", "shoes"
|
||||
}
|
||||
|
||||
function hades_skins.get_random_textures_and_colors()
|
||||
local color = {}
|
||||
local base = {}
|
||||
local tex = {}
|
||||
for k, v in pairs(styles) do
|
||||
color[k] = get_color()
|
||||
base[k] = v[math.random(1, #v)]
|
||||
end
|
||||
color.skin = get_color()
|
||||
color.eyes = get_color()
|
||||
return { colors = color, bases = base }
|
||||
end
|
||||
|
||||
function hades_skins.build_texture(base, color)
|
||||
local tex = {}
|
||||
for k, v in pairs(styles) do
|
||||
if base[k] ~= "blank" then
|
||||
tex[k] = "^(hades_skins_"..k.."_"..base[k]..".png"
|
||||
tex[k] = tex[k] .. "^[multiply:"..color[k]..")"
|
||||
else
|
||||
tex[k] = ""
|
||||
end
|
||||
end
|
||||
|
||||
if not color.skin then
|
||||
color.skin = get_color()
|
||||
end
|
||||
if not color.eyes then
|
||||
color.eyes = get_color()
|
||||
end
|
||||
|
||||
local eyes = "^(hades_skins_eyes_base.png"
|
||||
.. "^(hades_skins_eyes_pupils.png^[multiply:"..color.eyes.."))"
|
||||
|
||||
local skin = "((hades_skins_skin_base.png^hades_skins_mouth.png)^[multiply:"..color.skin..")"
|
||||
|
||||
local texture = skin
|
||||
.. eyes
|
||||
.. tex.pants
|
||||
.. tex.shoes
|
||||
.. tex.shirt
|
||||
.. tex.belt
|
||||
.. tex.hair
|
||||
.. tex.accessoire_head
|
||||
return { textures = { texture }, colors = color }
|
||||
end
|
||||
|
||||
function hades_skins.editor_state_to_textures(player)
|
||||
local name = player:get_player_name()
|
||||
local bases = {}
|
||||
local colors = {}
|
||||
for k,v in pairs(editor_cloth_states[name]) do
|
||||
bases[k] = styles[k][v]
|
||||
end
|
||||
for k,v in pairs(editor_color_states[name]) do
|
||||
colors[k] = string.format("#%.6X", v)
|
||||
end
|
||||
return hades_skins.build_texture(bases, colors)
|
||||
end
|
||||
|
||||
function hades_skins.player_set_textures(player, textures, skin_color)
|
||||
hades_player.player_set_textures(player, textures)
|
||||
-- Set meshhand
|
||||
hades_meshhand.set_skin_color(player, skin_color)
|
||||
end
|
||||
|
||||
function hades_skins.player_set_random_textures(player)
|
||||
local texcol = hades_skins.get_random_textures_and_colors()
|
||||
local out = hades_skins.build_texture(texcol.bases, texcol.colors)
|
||||
hades_skins.player_set_textures(player, out.textures, out.colors.skin)
|
||||
end
|
||||
|
||||
function hades_skins.show_skin_editor(player, texture)
|
||||
if not texture then
|
||||
texture = hades_player.player_get_textures(player)
|
||||
if not texture then
|
||||
return
|
||||
end
|
||||
texture = texture[1]
|
||||
end
|
||||
local formspec = [[
|
||||
formspec_version[4]
|
||||
size[12,11]
|
||||
box[0.4,0.4;4.2,8.2;#FFFFFF4F]
|
||||
box[0.5,0.5;4,8;#000000FF]
|
||||
model[0.5,0.5;4,8;playerpreview;character.b3d;]]..texture..[[;0,180;false;true;0,79]
|
||||
button[5.15,9.75;1,0.8;random;]]..F(S("Random"))..[[]
|
||||
button[6.15,9.75;1,0.8;reset;]]..F(S("Reset"))..[[]
|
||||
button_exit[7.55,9.75;2,0.8;cancel;]]..F(S("Cancel"))..[[]
|
||||
button_exit[9.55,9.75;2,0.8;submit;]]..F(S("OK"))..[[]
|
||||
]]
|
||||
local name = player:get_player_name()
|
||||
local y = 0.5
|
||||
for i=1, #styles_sorted do
|
||||
local s = styles_sorted[i]
|
||||
local id = editor_cloth_states[name][s]
|
||||
local choice = styles[s][id]
|
||||
formspec = formspec .. "button[5.15,"..y..";1,0.8;"..s.."_prev;<]"
|
||||
formspec = formspec .. "button[6.15,"..y..";3,0.8;"..s..";"..F(S("@1: @2", s, choice)).."]"
|
||||
formspec = formspec .. "button[9.15,"..y..";1,0.8;"..s.."_next;>]"
|
||||
formspec = formspec .. "button[10.55,"..y..";1,0.8;"..s.."_color;"..F(S("Color")).."]"
|
||||
y = y + 0.9
|
||||
end
|
||||
|
||||
minetest.show_formspec(player:get_player_name(), "hades_skins:skin_editor", formspec)
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
editor_color_states[name] = {}
|
||||
editor_cloth_states[name] = {}
|
||||
for k,_ in pairs(styles) do
|
||||
editor_cloth_states[name][k] = 1
|
||||
editor_color_states[name][k] = math.random(0, 0xFFFFFF)
|
||||
end
|
||||
end)
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
editor_color_states[name] = nil
|
||||
editor_cloth_states[name] = nil
|
||||
end)
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if formname ~= "hades_skins:skin_editor" then
|
||||
return
|
||||
end
|
||||
local name = player:get_player_name()
|
||||
local update_skin = function(player)
|
||||
local out = hades_skins.editor_state_to_textures(player)
|
||||
hades_skins.player_set_textures(player, out.textures, out.colors.skin)
|
||||
hades_skins.show_skin_editor(player)
|
||||
end
|
||||
for stylename,_ in pairs(styles) do
|
||||
if fields[stylename] or fields[stylename.."_next"] then
|
||||
editor_cloth_states[name][stylename] = editor_cloth_states[name][stylename] + 1
|
||||
if editor_cloth_states[name][stylename] > #styles[stylename] then
|
||||
editor_cloth_states[name][stylename] = 1
|
||||
end
|
||||
update_skin(player)
|
||||
return
|
||||
elseif fields[stylename.."_prev"] then
|
||||
editor_cloth_states[name][stylename] = editor_cloth_states[name][stylename] - 1
|
||||
if editor_cloth_states[name][stylename] < 1 then
|
||||
editor_cloth_states[name][stylename] = #styles[stylename]
|
||||
end
|
||||
update_skin(player)
|
||||
return
|
||||
elseif fields[stylename.."_color"] then
|
||||
editor_color_states[name][stylename] = math.random(0, 0xFFFFFF)
|
||||
update_skin(player)
|
||||
return
|
||||
end
|
||||
end
|
||||
if fields.random then
|
||||
hades_skins.player_set_random_textures(player)
|
||||
hades_skins.show_skin_editor(player)
|
||||
end
|
||||
end)
|
|
@ -0,0 +1,2 @@
|
|||
name = hades_skins
|
||||
depends = hades_player, hades_meshhand
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 315 B |
After Width: | Height: | Size: 202 B |
After Width: | Height: | Size: 910 B |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 156 B |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 356 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 669 B |