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,})
|
player:set_properties({textures = textures,})
|
||||||
end
|
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)
|
function hades_player.player_set_animation(player, anim_name, speed)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
if player_anim[name] == anim_name then
|
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 |