2022-12-17 18:32:55 +00:00
-- name: Nametags
-- incompatible: nametags
2023-02-21 02:44:24 +00:00
-- description: Nametags\nBy \\#ec7731\\Agent X\\#dcdcdc\\\n\nThis mod adds nametags to sm64ex-coop, this helps to easily identify other players without the player list, nametags can toggled on and off with \\#ffff00\\/nametag-distance 7000\\#dcdcdc\\ and \\#ffff00\\/nametag-distance 0\\#dcdcdc\\ respectively.
2022-12-17 18:32:55 +00:00
2023-04-28 23:54:33 +00:00
local MAX_SCALE = 0.32
2022-12-17 18:32:55 +00:00
gGlobalSyncTable.dist = 7000
2023-02-21 02:44:24 +00:00
2023-04-28 23:54:33 +00:00
local showHealth = true
local showSelfTag = false
2022-12-17 18:32:55 +00:00
2023-04-28 23:54:33 +00:00
local gStateExtras = { }
2023-04-24 23:45:25 +00:00
for i = 0 , ( MAX_PLAYERS - 1 ) do
gStateExtras [ i ] = { }
local e = gStateExtras [ i ]
e.prevPos = { }
e.prevPos . x = 0
e.prevPos . y = 0
e.prevPos . z = 0
e.prevScale = 1
end
2023-04-28 23:54:33 +00:00
-- localize functions to improve performance
local djui_chat_message_create = djui_chat_message_create
local djui_hud_measure_text = djui_hud_measure_text
local djui_hud_print_text_interpolated = djui_hud_print_text_interpolated
local djui_hud_set_color = djui_hud_set_color
local djui_hud_set_font = djui_hud_set_font
local djui_hud_set_resolution = djui_hud_set_resolution
local djui_hud_world_pos_to_screen_pos = djui_hud_world_pos_to_screen_pos
local vec3f_dist = vec3f_dist
local network_player_connected_count = network_player_connected_count
local network_player_palette_to_color = network_player_palette_to_color
local network_is_server = network_is_server
local is_player_active = is_player_active
local clampf = clampf
local hud_render_power_meter_interpolated = hud_render_power_meter_interpolated
local is_game_paused = is_game_paused
local obj_get_first_with_behavior_id = obj_get_first_with_behavior_id
for i in pairs ( gActiveMods ) do
local name = gActiveMods [ i ] . name : lower ( )
if gActiveMods [ i ] . enabled and ( name : find ( " hide " ) or name : find ( " hns " ) or name : find ( " hunt " ) ) then
2023-02-21 02:44:24 +00:00
gGlobalSyncTable.dist = 0
2022-12-17 18:32:55 +00:00
end
end
2023-04-28 23:54:33 +00:00
local function on_or_off ( value )
2023-02-21 02:44:24 +00:00
if value then return " \\ #00ff00 \\ ON " end
return " \\ #ff0000 \\ OFF "
end
2022-12-17 18:32:55 +00:00
--- @param m MarioState
2023-04-28 23:54:33 +00:00
local function active_player ( m )
2022-12-17 18:32:55 +00:00
local np = gNetworkPlayers [ m.playerIndex ]
if m.playerIndex == 0 then
return 1
end
if not np.connected then
return 0
end
if np.currCourseNum ~= gNetworkPlayers [ 0 ] . currCourseNum then
return 0
end
if np.currActNum ~= gNetworkPlayers [ 0 ] . currActNum then
return 0
end
if np.currLevelNum ~= gNetworkPlayers [ 0 ] . currLevelNum then
return 0
end
if np.currAreaIndex ~= gNetworkPlayers [ 0 ] . currAreaIndex then
return 0
end
return is_player_active ( m )
end
2023-04-28 23:54:33 +00:00
local function if_then_else ( cond , if_true , if_false )
2022-12-17 18:32:55 +00:00
if cond then return if_true end
return if_false
end
2023-04-28 23:54:33 +00:00
local function djui_hud_set_adjusted_color ( r , g , b , a )
2022-12-17 18:32:55 +00:00
local multiplier = 1
if is_game_paused ( ) then multiplier = 0.5 end
djui_hud_set_color ( r * multiplier , g * multiplier , b * multiplier , a )
end
2023-04-28 23:54:33 +00:00
local function djui_hud_print_outlined_text_interpolated ( text , prevX , prevY , prevScale , x , y , scale , r , g , b , a , outlineDarkness )
local offset = 1 * ( scale * 2 )
local prevOffset = 1 * ( prevScale * 2 )
2022-12-17 18:32:55 +00:00
-- render outline
2023-02-21 02:44:24 +00:00
djui_hud_set_adjusted_color ( r * outlineDarkness , g * outlineDarkness , b * outlineDarkness , a )
2023-04-28 23:54:33 +00:00
djui_hud_print_text_interpolated ( text , prevX - prevOffset , prevY , prevScale , x - offset , y , scale )
djui_hud_print_text_interpolated ( text , prevX + prevOffset , prevY , prevScale , x + offset , y , scale )
djui_hud_print_text_interpolated ( text , prevX , prevY - prevOffset , prevScale , x , y - offset , scale )
djui_hud_print_text_interpolated ( text , prevX , prevY + prevOffset , prevScale , x , y + offset , scale )
2022-12-17 18:32:55 +00:00
-- render text
djui_hud_set_adjusted_color ( r , g , b , 255 )
2023-04-28 23:54:33 +00:00
djui_hud_print_text_interpolated ( text , prevX , prevY , prevScale , x , y , scale )
2022-12-17 18:32:55 +00:00
djui_hud_set_color ( 255 , 255 , 255 , 255 )
end
2023-04-28 23:54:33 +00:00
local function name_without_hex ( name )
2023-02-21 02:44:24 +00:00
local s = ' '
local inSlash = false
for i = 1 , # name do
local c = name : sub ( i , i )
if c == ' \\ ' then
inSlash = not inSlash
elseif not inSlash then
s = s .. c
2022-12-17 18:32:55 +00:00
end
end
2023-02-21 02:44:24 +00:00
return s
2022-12-17 18:32:55 +00:00
end
2023-05-10 19:42:43 +00:00
local function split ( s )
local result = { }
for match in ( s ) : gmatch ( string.format ( " [^%s]+ " , " " ) ) do
table.insert ( result , match )
end
return result
end
2023-04-28 23:54:33 +00:00
local function on_hud_render ( )
if gGlobalSyncTable.dist == 0 or ( not showSelfTag and network_player_connected_count ( ) == 1 ) or not gNetworkPlayers [ 0 ] . currAreaSyncValid or obj_get_first_with_behavior_id ( id_bhvActSelector ) ~= nil then return end
2022-12-17 18:32:55 +00:00
djui_hud_set_resolution ( RESOLUTION_N64 )
djui_hud_set_font ( FONT_NORMAL )
2023-02-21 02:44:24 +00:00
for i = if_then_else ( showSelfTag , 0 , 1 ) , ( MAX_PLAYERS - 1 ) do
2022-12-17 18:32:55 +00:00
local m = gMarioStates [ i ]
2023-05-10 19:42:43 +00:00
local out = { x = 0 , y = 0 , z = 0 }
local pos = { x = m.marioObj . header.gfx . pos.x , y = m.pos . y + 210 , z = m.marioObj . header.gfx . pos.z }
if djui_hud_world_pos_to_screen_pos ( pos , out ) and m.marioBodyState . updateTorsoTime == gMarioStates [ 0 ] . marioBodyState.updateTorsoTime and active_player ( m ) ~= 0 and m.action ~= ACT_IN_CANNON and ( m.playerIndex ~= 0 or ( m.playerIndex == 0 and m.action ~= ACT_FIRST_PERSON ) ) then
2022-12-17 18:32:55 +00:00
local scale = MAX_SCALE
2023-05-10 19:42:43 +00:00
local dist = vec3f_dist ( gLakituState.pos , m.pos )
2023-04-28 23:54:33 +00:00
if m.playerIndex ~= 0 and dist > 1000 then
2022-12-17 18:32:55 +00:00
scale = 0.5
2023-04-28 23:54:33 +00:00
scale = scale + dist / gGlobalSyncTable.dist
scale = clampf ( 1 - scale , 0 , MAX_SCALE )
2022-12-17 18:32:55 +00:00
end
2023-02-21 02:44:24 +00:00
local name = name_without_hex ( gNetworkPlayers [ i ] . name )
2022-12-17 18:32:55 +00:00
local color = { r = 162 , g = 202 , b = 234 }
network_player_palette_to_color ( gNetworkPlayers [ i ] , SHIRT , color )
2023-02-21 02:44:24 +00:00
local measure = djui_hud_measure_text ( name ) * scale * 0.5
local alpha = if_then_else ( m.action ~= ACT_CROUCHING and m.action ~= ACT_START_CRAWLING and m.action ~= ACT_CRAWLING and m.action ~= ACT_STOP_CRAWLING , 255 , 100 )
2023-04-24 23:45:25 +00:00
local e = gStateExtras [ i ]
2023-04-28 23:54:33 +00:00
djui_hud_print_outlined_text_interpolated ( name , e.prevPos . x - measure , e.prevPos . y , e.prevScale , out.x - measure , out.y , scale , color.r , color.g , color.b , alpha , 0.25 )
2023-02-21 02:44:24 +00:00
2023-04-28 23:54:33 +00:00
if m.playerIndex ~= 0 and showHealth then
2023-02-21 02:44:24 +00:00
djui_hud_set_adjusted_color ( 255 , 255 , 255 , alpha )
local healthScale = 75 * scale
2023-04-24 23:45:25 +00:00
local prevHealthScale = 75 * e.prevScale
hud_render_power_meter_interpolated ( m.health ,
e.prevPos . x - ( prevHealthScale * 0.5 ) , e.prevPos . y - prevHealthScale , prevHealthScale , prevHealthScale ,
out.x - ( healthScale * 0.5 ) , out.y - healthScale , healthScale , healthScale )
2023-02-21 02:44:24 +00:00
end
2023-04-24 23:45:25 +00:00
e.prevPos . x = out.x
e.prevPos . y = out.y
e.prevPos . z = out.z
e.prevScale = scale
2022-12-17 18:32:55 +00:00
end
end
end
2023-05-10 19:42:43 +00:00
local function on_distance_command ( msg )
if not network_is_server ( ) and not network_is_moderator ( ) then
djui_chat_message_create ( " \\ #d86464 \\ You do not have permission to run this command. " )
return true
end
2023-02-21 02:44:24 +00:00
local dist = tonumber ( msg )
if dist ~= nil then
djui_chat_message_create ( " Set nametag distance to " .. msg )
gGlobalSyncTable.dist = dist
return true
2023-05-10 19:42:43 +00:00
else
djui_chat_message_create ( " /nametags \\ #00ffff \\ distance \\ #ffff00 \\ [number] \\ #ffffff \\ \n Sets the distance at which nametags disappear, \n default is \\ #ffff00 \\ 7000 \\ #ffffff \\ , \\ #ffff00 \\ 0 \\ #ffffff \\ turns nametags off " )
return true
2022-12-17 18:32:55 +00:00
end
2023-02-21 02:44:24 +00:00
return false
2022-12-17 18:32:55 +00:00
end
2023-05-10 19:42:43 +00:00
local function on_show_health_command ( msg )
if msg == " ? " then
djui_chat_message_create ( " /nametags \\ #00ffff \\ show-health \\ #ffffff \\ \n Toggles showing health above the nametag, default is \\ #00ff00 \\ ON " )
return true
end
2023-04-28 23:54:33 +00:00
showHealth = not showHealth
djui_chat_message_create ( " Show health status: " .. on_or_off ( showHealth ) )
2022-12-17 18:32:55 +00:00
return true
end
2023-05-10 19:42:43 +00:00
local function on_show_tag_command ( msg )
if msg == " ? " then
djui_chat_message_create ( " /nametags \\ #00ffff \\ show-tag \\ #ffffff \\ \n Toggles your own nametag on or off, default is \\ #ff0000 \\ OFF " )
return true
end
2023-02-21 02:44:24 +00:00
showSelfTag = not showSelfTag
djui_chat_message_create ( " Show my tag status: " .. on_or_off ( showSelfTag ) )
2022-12-17 18:32:55 +00:00
return true
end
2023-05-10 19:42:43 +00:00
local function on_nametags_command ( msg )
local args = split ( msg )
if args [ 1 ] == " distance " then
return on_distance_command ( args [ 2 ] )
elseif args [ 1 ] == " show-health " then
return on_show_health_command ( args [ 2 ] )
elseif args [ 1 ] == " show-tag " then
return on_show_tag_command ( args [ 2 ] )
end
return false
2022-12-17 18:32:55 +00:00
end
2023-05-10 19:42:43 +00:00
hook_event ( HOOK_ON_HUD_RENDER , on_hud_render )
2023-05-16 22:27:04 +00:00
hook_chat_command ( " nametags " , " \\ #00ffff \\ [show-tag|show-health|distance] " , on_nametags_command )