2270f84336
Colorize player clothes based on a hash of player name. This should make it easier to distinguish players from each other even when you can't see their names, by remembering clothing colors. Unfortunately there's no good way currently to prevent some ugly color combinations, which may risk incentivizing players to mess with their name until they get a combination they like, creating a bunch of junk accounts. Making colors never clash (i.e. always matching or complementary hues) would reduce the variation in colorations, causing more player color collisions. Finding a way to ensure colors are "pretty" but still having enough variation to give each player name a unique color scheme would be ideal. Also there's room for more variations, e.g. adding some stripes, patterns, emblems, etc. that can be colorized separately, ideally something visible from every angle.
126 lines
4.3 KiB
Lua
126 lines
4.3 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local math, minetest, nodecore, pairs, string, table, tonumber
|
|
= math, minetest, nodecore, pairs, string, table, tonumber
|
|
local math_ceil, math_floor, math_pi, math_sin, string_format,
|
|
string_sub, table_concat
|
|
= math.ceil, math.floor, math.pi, math.sin, string.format,
|
|
string.sub, table.concat
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
local function addcolor(layers, id, value)
|
|
local theta = tonumber(value, 16) / 32768 * math_pi
|
|
local r = math_sin(theta + math_pi * 0/3) * 127 + 128
|
|
local g = math_sin(theta + math_pi * 2/3) * 127 + 128
|
|
local b = math_sin(theta + math_pi * 4/3) * 127 + 128
|
|
layers[#layers + 1] = string_format("(%s_color%d.png^[multiply:#%02x%02x%02x)",
|
|
modname, id, math_ceil(r), math_ceil(g), math_ceil(b))
|
|
end
|
|
|
|
nodecore.player_skin = nodecore.player_skin or function(player)
|
|
local skin = player:get_meta():get_string("custom_skin") or ""
|
|
if skin ~= "" then return skin end
|
|
|
|
local layers = {modname .. "_base.png"}
|
|
|
|
local name = player:get_player_name()
|
|
if name ~= "singleplayer" then
|
|
local hash = minetest.sha1(name)
|
|
addcolor(layers, 1, string_sub(hash, 1, 4))
|
|
addcolor(layers, 2, string_sub(hash, 5, 8))
|
|
addcolor(layers, 3, string_sub(hash, 9, 12))
|
|
end
|
|
|
|
local privs = minetest.get_player_privs(player:get_player_name())
|
|
if not privs.interact then
|
|
layers[#layers + 1] = modname .. "_no_interact.png"
|
|
layers[#layers + 1] = "[makealpha:254,0,253"
|
|
end
|
|
if not privs.shout then
|
|
layers[#layers + 1] = modname .. "_no_shout.png"
|
|
end
|
|
|
|
return table_concat(layers, "^"), layers
|
|
end
|
|
|
|
nodecore.player_anim_data = nodecore.player_anim_data or {
|
|
stand = {x = 0, y = 0},
|
|
sit = {x = 1, y = 1},
|
|
lay = {x = 2, y = 2},
|
|
walk = {x = 3, y = 27},
|
|
walk_mine = {x = 28, y = 52},
|
|
mine = {x = 53, y = 77},
|
|
swim_mine = {x = 78, y = 108, speed = 0.6},
|
|
swim_up = {x = 109, y = 133, speed = 0.6},
|
|
swim_down = {x = 134, y = 158, speed = 0.6},
|
|
wave = {x = 159, y = 171, speed = 0.8}
|
|
}
|
|
for k, v in pairs(nodecore.player_anim_data) do
|
|
v.name = k
|
|
v.speed = 30 * (v.speed or 1)
|
|
end
|
|
|
|
local function walkspeed(player, anim)
|
|
if not anim.speed then return anim end
|
|
local phys = player:get_physics_override()
|
|
local speed = math_floor(phys.speed * 10) / 10
|
|
if speed == 1 then return anim end
|
|
local t = {}
|
|
for k, v in pairs(anim) do
|
|
t[k] = (k == "speed") and (speed * v) or v
|
|
end
|
|
return t
|
|
end
|
|
|
|
nodecore.player_anim = nodecore.player_anim or function(player, data)
|
|
local hp = player:get_hp()
|
|
if hp <= 0 then
|
|
return nodecore.player_anim_data.lay
|
|
end
|
|
|
|
local ctl = player:get_player_control()
|
|
local walk = (ctl.up or ctl.down) and not (ctl.up and ctl.down)
|
|
or (ctl.right or ctl.left) and not (ctl.right and ctl.left)
|
|
local mine = ctl.LMB or ctl.RMB
|
|
if data then
|
|
if mine then data.animcontrol_mine_exp = nodecore.gametime + 0.25 end
|
|
mine = mine or data.animcontrol_mine_exp and data.animcontrol_mine_exp >= nodecore.gametime
|
|
end
|
|
local aux = ctl.aux1
|
|
if data then
|
|
if aux then data.animcontrol_aux_exp = nodecore.gametime + 1 end
|
|
aux = aux or data.animcontrol_aux_exp and data.animcontrol_aux_exp >= nodecore.gametime
|
|
end
|
|
|
|
if not nodecore.player_swimming(player) then
|
|
if walk and mine then return walkspeed(player, nodecore.player_anim_data.walk_mine) end
|
|
if walk then return walkspeed(player, nodecore.player_anim_data.walk) end
|
|
if mine then return nodecore.player_anim_data.mine end
|
|
if aux then return nodecore.player_anim_data.wave end
|
|
return nodecore.player_anim_data.stand
|
|
end
|
|
|
|
if mine then return walkspeed(player, nodecore.player_anim_data.swim_mine) end
|
|
if not (walk or ctl.jump or ctl.sneak or (ctl.left or ctl.right)
|
|
and not (ctl.left and ctl.right)) then
|
|
local t = {}
|
|
for k, v in pairs(nodecore.player_anim_data.swim_up) do
|
|
t[k] = (k == "speed") and (0.1 * v) or v
|
|
end
|
|
return t
|
|
end
|
|
local v = player:get_player_velocity()
|
|
if v and v.y >= -0.5 then return walkspeed(player, nodecore.player_anim_data.swim_up) end
|
|
return walkspeed(player, nodecore.player_anim_data.swim_down)
|
|
end
|
|
|
|
nodecore.player_visuals_base = nodecore.player_visuals_base or function(player)
|
|
local mesh = player:get_meta():get_string("custom_mesh") or ""
|
|
return {
|
|
visual = "mesh",
|
|
visual_size = {x = 0.9, y = 0.9, z = 0.9},
|
|
mesh = mesh and mesh ~= "" and mesh or modname .. ".b3d"
|
|
}
|
|
end
|