Update Character Select to v1.9

This commit is contained in:
Agent X 2024-06-30 20:09:46 -04:00
parent 2a6d17c4cc
commit 360fd9fb8e
6 changed files with 825 additions and 259 deletions

View file

@ -1,5 +1,10 @@
MOD_VERSION = "1.7"
IS_COOPDX = get_coop_compatibility_enabled ~= nil
if VERSION_NUMBER < 37 then
djui_popup_create("\n\\#FFAAAA\\Character Select requires\n CoopDX v1 or higher use!\n\nYou can find CoopDX here:\n\\#6666FF\\https://sm64coopdx.com", 5)
incompatibleClient = true
return 0
end
MOD_VERSION = "1.9"
ommActive = false
for i in pairs(gActiveMods) do
@ -102,4 +107,18 @@ end
allowMenu = {}
renderInMenuTable = {}
renderInMenuTable = {
front = {},
back = {},
}
queueStorageFailsafe = false
charBeingSet = false
stopPalettes = false
for i in pairs(gActiveMods) do
if (gActiveMods[i].incompatible ~= nil and gActiveMods[i].incompatible:find("gamemode")) and not (gActiveMods[i].name:find("Personal Star Counter EX+")) then
stopPalettes = true
end
end

View file

@ -1,10 +1,12 @@
-- name: Character Select
-- description:\\#ffff33\\---- Character Select Coop v1.7 ----\n\n\\#dcdcdc\\A Library / API made to make adding and using Custom Characters as simple as possible!\nUse\\#ffff33\\ /char-select\\#dcdcdc\\ to get started!\n\nCreated by:\\#008800\\ Squishy6094\n\\#dcdcdc\\Concepts by:\\#4496f5\\ AngelicMiracles\n\n\\#AAAAFF\\Updates and Packs can be found on\nCharacter Select's Github:\n\\#6666FF\\Squishy6094/character-select-coop
-- description:\\#ffff33\\---- Character Select Coop v1.9 ----\n\n\\#dcdcdc\\A Library / API made to make adding and using Custom Characters as simple as possible!\nUse\\#ffff33\\ /char-select\\#dcdcdc\\ to get started!\n\nCreated by:\\#008800\\ Squishy6094\n\\#dcdcdc\\Concepts by:\\#4496f5\\ AngelicMiracles\n\n\\#AAAAFF\\Updates can be found on\nCharacter Select's Github:\n\\#6666FF\\Squishy6094/character-select-coop
if incompatibleClient then return 0 end
-- localize functions to improve performance
local mod_storage_load,tonumber,djui_popup_create,mod_storage_save,tostring,djui_chat_message_create,camera_freeze,hud_hide,vec3f_copy,set_mario_action,set_mario_animation,camera_unfreeze,hud_show,obj_has_behavior_id,network_local_index_from_global,obj_has_model_extended,obj_set_model_extended,get_id_from_behavior,nearest_player_to_object,math_random,djui_hud_set_resolution,djui_hud_set_font,djui_hud_get_screen_width,maxf,djui_hud_set_color,djui_hud_render_rect,djui_hud_measure_text,djui_hud_print_text,math_ceil,math_abs,math_sin,min,math_min,minf,djui_hud_set_rotation,djui_hud_is_pause_menu_created,is_game_paused,hud_is_hidden,obj_get_first_with_behavior_id,hud_get_value,hud_set_value,play_sound,string_lower = mod_storage_load,tonumber,djui_popup_create,mod_storage_save,tostring,djui_chat_message_create,camera_freeze,hud_hide,vec3f_copy,set_mario_action,set_mario_animation,camera_unfreeze,hud_show,obj_has_behavior_id,network_local_index_from_global,obj_has_model_extended,obj_set_model_extended,get_id_from_behavior,nearest_player_to_object,math.random,djui_hud_set_resolution,djui_hud_set_font,djui_hud_get_screen_width,maxf,djui_hud_set_color,djui_hud_render_rect,djui_hud_measure_text,djui_hud_print_text,math.ceil,math.abs,math.sin,min,math.min,minf,djui_hud_set_rotation,djui_hud_is_pause_menu_created,is_game_paused,hud_is_hidden,obj_get_first_with_behavior_id,hud_get_value,hud_set_value,play_sound,string.lower
local menu = false
menu = false
menuAndTransition = false
options = false
currChar = 1
@ -26,7 +28,7 @@ local TEXT_PREF_LOAD = "Default"
--[[
Note: Do NOT add characters via the characterTable below,
We highly reccomend you create your own mod and use the
We highly recommend you create your own mod and use the
API to add characters, this ensures your pack is easy
to use for anyone and low on file space!
]]
@ -34,11 +36,12 @@ characterTable = {
[1] = {
name = "Default",
saveName = "Default",
description = {"The vanilla cast for sm64ex-coop!", "", "These Characters are swappable", "via the default Options Menu"},
description = {"The vanilla cast for sm64coopdx!", "", "These Characters are swappable", "via the default Options Menu"},
credit = "Nintendo / Coop Team",
color = {r = 255, g = 50, b = 50},
model = nil,
forceChar = nil,
offset = 0,
forceChar = nil, -- Legacy Functionality
lifeIcon = gTextures.mario_head,
starIcon = gTextures.star,
camScale = 1.0
@ -47,6 +50,7 @@ characterTable = {
characterCaps = {}
characterCelebrationStar = {}
characterColorPresets = {}
optionTableRef = {
openInputs = 1,
@ -54,10 +58,11 @@ optionTableRef = {
menuColor = 3,
anims = 4,
inputLatency = 5,
localModels = 6,
localVoices = 7,
debugInfo = 8,
resetSaveData = 9
autoPalette = 6,
localModels = 7,
localVoices = 8,
debugInfo = 9,
resetSaveData = 10
}
optionTable = {
@ -65,9 +70,9 @@ optionTable = {
name = "Open Binds",
toggle = tonumber(mod_storage_load("MenuInput")),
toggleSaveName = "MenuInput",
toggleDefault = 0,
toggleDefault = 1,
toggleMax = 2,
toggleNames = {"None", ommActive and "D-pad Down + R" or "D-pad Down", "Z (Pause Menu)"},
toggleNames = {"None", "Z (Pause Menu)", ommActive and "D-pad Down + R" or "D-pad Down"},
description = {"Sets a Bind to Open the Menu", "rather than using the command."}
},
[optionTableRef.notification] = {
@ -106,6 +111,14 @@ optionTable = {
toggleNames = {"Slow", "Normal", "Fast"},
description = {"Sets how fast you scroll", "throughout the Menu"}
},
[optionTableRef.autoPalette] = {
name = "Auto-Apply Palette",
toggle = tonumber(mod_storage_load("autoPalette")),
toggleSaveName = "autoPalette",
toggleDefault = 1,
toggleMax = 1,
description = {"If On, Automatically", "sets your palette to the", "Character's Preset if avalible"}
},
[optionTableRef.localModels] = {
name = "Locally Display Models",
toggle = tonumber(mod_storage_load("localModels")),
@ -140,7 +153,7 @@ optionTable = {
},
}
local optionTableCount = #optionTable
local defaultOptionCount = #optionTable
local latencyValueTable = {12, 6, 3}
@ -164,7 +177,7 @@ local defaultNames = {
[CT_WALUIGI] = "Waluigi",
[CT_WARIO] = "Wario"
}
local defaultPlayerColors = {
local defaultMenuColors = {
[CT_MARIO] = menuColorTable[1],
[CT_LUIGI] = menuColorTable[4],
[CT_TOAD] = menuColorTable[5],
@ -192,6 +205,13 @@ local defaultCamScales = {
[CT_WALUIGI] = 1.1,
[CT_WARIO] = 1
}
local defaultModels = {
[CT_MARIO] = E_MODEL_MARIO,
[CT_LUIGI] = E_MODEL_LUIGI,
[CT_TOAD] = E_MODEL_TOAD_PLAYER,
[CT_WALUIGI] = E_MODEL_WALUIGI,
[CT_WARIO] = E_MODEL_WARIO
}
---@param m MarioState
local function nullify_inputs(m)
@ -218,7 +238,7 @@ local function nullify_inputs(m)
c.stickY = 0
end
local prefCharColor = defaultPlayerColors[CT_MARIO]
local prefCharColor = defaultMenuColors[CT_MARIO]
local function load_preferred_char()
local savedChar = mod_storage_load("PrefChar")
@ -267,10 +287,14 @@ local function mod_storage_save_pref_char(charTable)
prefCharColor = charTable.color
end
local function failsafe_options()
function failsafe_options()
for i = 1, #optionTable do
if optionTable[i].toggle == nil or optionTable[i].toggle == "" then
optionTable[i].toggle = optionTable[i].toggleDefault
local load = optionTable[i].toggleSaveName and mod_storage_load(optionTable[i].toggleSaveName) or nil
if load == "" then
load = nil
end
optionTable[i].toggle = load and tonumber(load) or optionTable[i].toggleDefault
if optionTable[i].toggleSaveName ~= nil then
mod_storage_save(optionTable[i].toggleSaveName, tostring(optionTable[i].toggle))
end
@ -279,7 +303,7 @@ local function failsafe_options()
optionTable[i].toggleNames = {"Off", "On"}
end
end
if optionTable[optionTableRef.openInputs].toggle > 0 and ommActive then
if optionTable[optionTableRef.openInputs].toggle == 2 and ommActive then
djui_popup_create('Character Select:\nYour Open bind has changed to:\nD-pad Down + R\nDue to OMM Rebirth being active!', 4)
end
end
@ -313,10 +337,15 @@ local function boot_note()
else
djui_chat_message_create("Character Select is active!\nYou can use \\#ffff33\\/char-select \\#ffffff\\to open the menu!")
end
end
if not IS_COOPDX then
djui_chat_message_create("\\#FFAAAA\\Note: Although not required, we highly reccomend\nusing SM64CoopDX when playing Character Select!\n\\#6666FF\\https://sm64coopdx.com")
local function menu_is_allowed()
for _, func in pairs(allowMenu) do
if not func() then
return false
end
end
return true
end
-------------------
@ -361,12 +390,15 @@ local faceAngle = 0
--- @param m MarioState
local function mario_update(m)
if stallFrame == 1 then
if stallFrame == 1 or queueStorageFailsafe then
failsafe_options()
TEXT_PREF_LOAD = load_preferred_char()
if optionTable[optionTableRef.notification].toggle == 1 then
boot_note()
if not queueStorageFailsafe then
TEXT_PREF_LOAD = load_preferred_char()
if optionTable[optionTableRef.notification].toggle == 1 then
boot_note()
end
end
queueStorageFailsafe = false
end
if stallFrame < 2 then
@ -374,31 +406,30 @@ local function mario_update(m)
end
if m.playerIndex == 0 and stallFrame > 1 then
local modelIndex = gNetworkPlayers[m.playerIndex].modelIndex
local modelIndex = gNetworkPlayers[0].modelIndex
characterTable[1].forceChar = modelIndex
characterTable[1].name = defaultNames[modelIndex]
characterTable[1].color = defaultMenuColors[modelIndex]
if currChar == 1 then
characterTable[1].color = defaultPlayerColors[modelIndex]
characterTable[1].lifeIcon = defaultIcons[modelIndex]
characterTable[1].camScale = defaultCamScales[modelIndex]
gNetworkPlayers[0].overrideModelIndex = modelIndex
else
gNetworkPlayers[0].overrideModelIndex = CT_MARIO
end
if optionTable[optionTableRef.localModels].toggle > 0 then
gPlayerSyncTable[m.playerIndex].modelId = characterTable[currChar].model
gPlayerSyncTable[0].modelId = characterTable[currChar].model
if characterTable[currChar].forceChar ~= nil then
gNetworkPlayers[m.playerIndex].overrideModelIndex = characterTable[currChar].forceChar
gNetworkPlayers[0].overrideModelIndex = characterTable[currChar].forceChar
end
m.marioObj.hookRender = 1
else
gPlayerSyncTable[m.playerIndex].modelId = nil
gNetworkPlayers[m.playerIndex].overrideModelIndex = characterTable[1].forceChar
gPlayerSyncTable[0].modelId = nil
gNetworkPlayers[0].overrideModelIndex = characterTable[1].forceChar
currChar = 1
end
if menuAndTransition then
for _, func in pairs(allowMenu) do
if not func() then
menu = false
return
end
end
camera_freeze()
hud_hide()
if _G.PersonalStarCounter then
@ -434,12 +465,41 @@ local function mario_update(m)
end
noLoop = true
end
end
--Reset Save Data Check
if optionTable[optionTableRef.resetSaveData].toggle > 0 then
reset_options(false)
optionTable[optionTableRef.resetSaveData].toggle = 0
--Reset Save Data Check
if optionTable[optionTableRef.resetSaveData].toggle > 0 then
reset_options(false)
optionTable[optionTableRef.resetSaveData].toggle = 0
end
charBeingSet = false
for i = 1, #optionTable do
optionTable[i].optionBeingSet = false
end
end
end
local altOffsetActs = {
[ACT_CROUCH_SLIDE] = true,
[ACT_READING_AUTOMATIC_DIALOG] = true,
[ACT_DEATH_EXIT_LAND] = true,
[ACT_SLIDE_KICK] = false,
[ACT_SLIDE_KICK_SLIDE] = false,
[ACT_GROUND_POUND] = true,
}
-- Vertical Offsets
local function on_object_render(obj)
if get_id_from_behavior(obj.behavior) ~= id_bhvMario then
return
end
for i=0, MAX_PLAYERS-1 do
local m = gMarioStates[i]
if characterTable[currChar].offset ~= 0 then
if altOffsetActs[m.action] ~= false then
m.marioObj.header.gfx.pos.y = (altOffsetActs[m.action] and m.pos.y or m.marioObj.header.gfx.pos.y) + characterTable[currChar].offset
end
end
end
end
@ -452,6 +512,7 @@ local sCapBhvs = {
--- @param o Object
--- @param model integer
function set_model(o, model)
if optionTable[optionTableRef.localModels].toggle == 0 then return end
if obj_has_behavior_id(o, id_bhvMario) ~= 0 then
local i = network_local_index_from_global(o.globalPlayerIndex)
if gPlayerSyncTable[i].modelId ~= nil and obj_has_model_extended(o, gPlayerSyncTable[i].modelId) == 0 then
@ -490,7 +551,7 @@ function set_model(o, model)
elseif model == c.capMetalWingModelId then
capModel = capModels.metalWing
end
if capModel ~= E_MODEL_NONE then
if capModel ~= E_MODEL_NONE and capModel ~= E_MODEL_ERROR_MODEL and capModel ~= nil then
obj_set_model_extended(o, capModel)
end
end
@ -499,6 +560,7 @@ end
hook_event(HOOK_MARIO_UPDATE, mario_update)
hook_event(HOOK_OBJECT_SET_MODEL, set_model)
hook_event(HOOK_ON_OBJECT_RENDER, on_object_render)
------------------
-- Menu Handler --
@ -516,19 +578,20 @@ local inputStallTimerDirectional = 0
local inputStallToDirectional = 12
local inputStallToButton = 10
-- Font Consistency between sm64ex-coop and sm64coopdx
local FONT_CS_NORMAL = IS_COOPDX and FONT_ALIASED or FONT_NORMAL
--Basic Menu Text
local TEXT_OPTIONS_HEADER = "Menu Options"
local TEXT_VERSION = "Version: " .. MOD_VERSION .. (IS_COOPDX and " | sm64coopdx" or " | sm64ex-coop")
local TEXT_OPTIONS_HEADER_API = "API Options"
local TEXT_VERSION = "Version: " .. MOD_VERSION .. " | sm64coopdx"
local TEXT_RATIO_UNSUPPORTED = "Your Current Aspect-Ratio isn't Supported!"
local TEXT_DESCRIPTION = "Character Description:"
local TEXT_PREF_SAVE = "Press A to Set as Preferred Character"
local TEXT_PREF_SAVE_AND_PALETTE = "A - Set Preference | Y - Toggle Palette"
local TEXT_PAUSE_Z_OPEN = "Z Button - Character Select"
local TEXT_PAUSE_UNAVALIBLE = "Character Select is Unavalible"
local TEXT_PAUSE_CURR_CHAR = "Current Character: "
if math_random(100) == 64 then -- Easter Egg if you get lucky loading the mod >v<
TEXT_PAUSE_Z_OPEN = "Z - DynOS" -- Referencing the original sm64ex DynOS options
if math_random(100) == 64 then
-- Easter Egg if you get lucky loading the mod Referencing the original sm64ex DynOS options by PeachyPeach >v<
TEXT_PAUSE_Z_OPEN = "Z - DynOS"
TEXT_PAUSE_CURR_CHAR = "Model: "
end
@ -536,8 +599,11 @@ end
local TEXT_DEBUGGING = "Character Debug"
local TEXT_DESCRIPTION_SHORT = "Description:"
local TEXT_LIFE_ICON = "Life Icon:"
local TEXT_STAR_ICON = "Star Icon:"
local TEXT_FORCED_CHAR = "Forced: "
local TEXT_OFFSET = "Offset: "
local TEXT_TABLE_POS = "Table Position: "
local TEXT_PALETTE = "Palette: "
--Options Text
local TEXT_OPTIONS_OPEN = "Press START to open Options"
@ -546,30 +612,38 @@ local TEXT_OPTIONS_SELECT = "A - Select | B - Exit "
local TEXT_LOCAL_MODEL_OFF = "Locally Display Models is Off"
local TEXT_LOCAL_MODEL_OFF_OPTIONS = "You can turn it back on in the Options Menu"
local menuColor = characterTable[currChar].color
menuColor = characterTable[currChar].color
local MATH_DIVIDE_THREE_HUNDRED_TWENTY = 1/320
local MATH_DIVIDE_THIRTY_TWO = 1/32
local MATH_DIVIDE_320 = 1/320
local MATH_DIVIDE_32 = 1/32
local MATH_DIVIDE_30 = 1/30
local MATH_DIVIDE_16 = 1/16
function update_menu_color()
if optionTable[optionTableRef.menuColor].toggle > 1 then
menuColor = menuColorTable[optionTable[optionTableRef.menuColor].toggle - 1]
elseif optionTable[optionTableRef.menuColor].toggle == 1 then
optionTable[optionTableRef.menuColor].toggleNames[2] = string_underscore_to_space(TEXT_PREF_LOAD) .. " (Pref)"
menuColor = prefCharColor
else
menuColor = characterTable[currChar].color
end
return menuColor
end
local function on_hud_render()
local FONT_USER = djui_menu_get_font()
djui_hud_set_resolution(RESOLUTION_N64)
djui_hud_set_font(FONT_CS_NORMAL)
djui_hud_set_font(FONT_ALIASED)
local width = djui_hud_get_screen_width() + 1.4
local height = 240
local widthHalf = width * 0.5
local heightHalf = height * 0.5
local widthScale = maxf(width, 321.4) * MATH_DIVIDE_THREE_HUNDRED_TWENTY
local widthScale = maxf(width, 321.4) * MATH_DIVIDE_320
if menuAndTransition then
if optionTable[optionTableRef.menuColor].toggle > 1 then
menuColor = menuColorTable[optionTable[optionTableRef.menuColor].toggle - 1]
elseif optionTable[optionTableRef.menuColor].toggle == 1 then
optionTable[optionTableRef.menuColor].toggleNames[2] = string_underscore_to_space(TEXT_PREF_LOAD) .. " (Pref)"
menuColor = prefCharColor
else
menuColor = characterTable[currChar].color
end
update_menu_color()
if optionTable[optionTableRef.localModels].toggle == 0 then
djui_hud_set_color(0, 0, 0, 200)
@ -581,18 +655,37 @@ local function on_hud_render()
local x = 135 * widthScale * 0.8
--Character Description
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_render_rect(width - x, 0, x, height)
-- Render All Black Squares Behind Below API
-- Description
djui_hud_set_color(0, 0, 0, 255)
djui_hud_render_rect(width - x + 2, 2, x - 4, height - 4)
-- Buttons
djui_hud_set_color(0, 0, 0, 255)
djui_hud_render_rect(2, 2, x - 4, height - 4)
-- Header
djui_hud_set_color(0, 0, 0, 255)
djui_hud_render_rect(2, 2, width - 4, 46)
-- API Rendering (Below Text)
if #renderInMenuTable.back > 0 then
for i = 1, #renderInMenuTable.back do
renderInMenuTable.back[i]()
end
end
--Character Description
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_set_font(FONT_CS_NORMAL)
djui_hud_render_rect(width - x, 50, 2, height - 50)
djui_hud_render_rect(width - x, height - 2, x, 2)
djui_hud_render_rect(width - 2, 50, 2, height - 50)
djui_hud_set_font(FONT_ALIASED)
local character = characterTable[currChar]
if optionTable[optionTableRef.debugInfo].toggle == 0 then -- Actual Description
local TEXT_NAME = string_underscore_to_space(character.name)
local TEXT_CREDIT = "Credit: " .. character.credit
local TEXT_DESCRIPTION_TABLE = character.description
local TEXT_PRESET = "Preset Character Palette: "..(gPlayerSyncTable[0].presetPalette and "On" or "Off")
local TEXT_PREF = "Preferred Character:"
local TEXT_PREF_LOAD = string_underscore_to_space(TEXT_PREF_LOAD)
if djui_hud_measure_text(TEXT_PREF_LOAD) / widthScale > 110 then
@ -606,8 +699,10 @@ local function on_hud_render()
local textX = x * 0.5
djui_hud_print_text(TEXT_NAME, width - textX - djui_hud_measure_text(TEXT_NAME) * 0.3, 55, 0.6)
djui_hud_set_font(FONT_TINY)
djui_hud_print_text(TEXT_CREDIT, width - textX - djui_hud_measure_text(TEXT_CREDIT) * 0.3, 74, 0.6)
djui_hud_set_font(FONT_CS_NORMAL)
local creditScale = 0.6
creditScale = math.min(creditScale, 100/djui_hud_measure_text(TEXT_CREDIT))
djui_hud_print_text(TEXT_CREDIT, width - textX - djui_hud_measure_text(TEXT_CREDIT) * creditScale *0.5, 74, creditScale)
djui_hud_set_font(FONT_ALIASED)
djui_hud_print_text(TEXT_DESCRIPTION, width - textX - djui_hud_measure_text(TEXT_DESCRIPTION) * 0.2, 85, 0.4)
if widthScale < 1.65 then
for i = 1, #TEXT_DESCRIPTION_TABLE do
@ -626,72 +721,117 @@ local function on_hud_render()
end
end
local modelId = gPlayerSyncTable[0].modelId and gPlayerSyncTable[0].modelId or defaultModels[gMarioStates[0].character.type]
djui_hud_print_text(TEXT_PREF, width - textX - djui_hud_measure_text(TEXT_PREF) * 0.15, height - 22, 0.3)
djui_hud_set_font(FONT_TINY)
djui_hud_print_text(TEXT_PREF_SAVE, width - textX - djui_hud_measure_text(TEXT_PREF_SAVE) * 0.25, height - 13, 0.5)
if characterColorPresets[modelId] and not stopPalettes then
djui_hud_print_text(TEXT_PRESET, width - textX - djui_hud_measure_text(TEXT_PRESET) * 0.15, height - 31, 0.3)
djui_hud_set_font(FONT_TINY)
djui_hud_print_text(TEXT_PREF_SAVE_AND_PALETTE, width - textX - djui_hud_measure_text(TEXT_PREF_SAVE_AND_PALETTE) * 0.25, height - 13, 0.5)
else
djui_hud_set_font(FONT_TINY)
djui_hud_print_text(TEXT_PREF_SAVE, width - textX - djui_hud_measure_text(TEXT_PREF_SAVE) * 0.25, height - 13, 0.5)
end
else -- Debugging Info
local TEXT_NAME = "Name: " .. character.name
local TEXT_SAVE_NAME = "Save Name: " .. character.saveName
local TEXT_CREDIT = "Credit: " .. character.credit
local TEXT_DESCRIPTION_TABLE = character.description
local TEXT_COLOR = "Color: R-" .. character.color.r ..", G-" ..character.color.g ..", B-"..character.color.b
local TEX_ICON = character.lifeIcon
local TEX_LIFE_ICON = character.lifeIcon
local TEX_STAR_ICON = character.starIcon
local TEXT_ICON_DEFAULT = "?"
local TEXT_SCALE = "Camera Scale: " .. character.camScale
local TEXT_PRESET = "Preset Palette: "..(gPlayerSyncTable[0].presetPalette and "On" or "Off")
local TEXT_PREF = "Preferred: " .. TEXT_PREF_LOAD
local TEXT_PREF_COLOR = "Pref Color: R-" .. prefCharColor.r .. ", G-" .. prefCharColor.g .. ", B-" .. prefCharColor.b
local textX = x * 0.5
djui_hud_print_text(TEXT_DEBUGGING, width - textX - djui_hud_measure_text(TEXT_DEBUGGING) * 0.3, 55, 0.6)
djui_hud_set_font(FONT_TINY)
djui_hud_print_text(TEXT_NAME, width - x + 8, 72, 0.6)
djui_hud_print_text(TEXT_SAVE_NAME, width - x + 8, 81, 0.6)
djui_hud_print_text(TEXT_CREDIT, width - x + 8, 90, 0.6)
djui_hud_print_text(TEXT_DESCRIPTION_SHORT, width - x + 8, 99, 0.6)
local removeLine = 0
for i = 1, #TEXT_DESCRIPTION_TABLE do
if TEXT_DESCRIPTION_TABLE[i] ~= "" then
djui_hud_set_font(FONT_CS_NORMAL)
local TEXT_DESCRIPTION_LINE = TEXT_DESCRIPTION_TABLE[i]
if (djui_hud_measure_text(TEXT_DESCRIPTION_TABLE[i]) * 0.3 > 100) then
TEXT_DESCRIPTION_LINE = "(!) " .. TEXT_DESCRIPTION_LINE
local y = 72
djui_hud_print_text(TEXT_NAME, width - x + 8, y, 0.5)
y = y + 7
djui_hud_print_text(TEXT_SAVE_NAME, width - x + 8, y, 0.5)
y = y + 7
djui_hud_print_text(TEXT_CREDIT, width - x + 8, y, 0.5)
y = y + 7
if TEXT_DESCRIPTION_TABLE[1] ~= "No description has been provided" then
djui_hud_print_text(TEXT_DESCRIPTION_SHORT, width - x + 8, y, 0.5)
y = y + 2
local removeLine = 0
for i = 1, #TEXT_DESCRIPTION_TABLE do
if TEXT_DESCRIPTION_TABLE[i] ~= "" then
djui_hud_set_font(FONT_ALIASED)
local TEXT_DESCRIPTION_LINE = TEXT_DESCRIPTION_TABLE[i]
if (djui_hud_measure_text(TEXT_DESCRIPTION_TABLE[i]) * 0.3 > 100) then
TEXT_DESCRIPTION_LINE = "(!) " .. TEXT_DESCRIPTION_LINE
else
TEXT_DESCRIPTION_LINE = " " .. TEXT_DESCRIPTION_LINE
end
djui_hud_set_font(FONT_TINY)
djui_hud_print_text(TEXT_DESCRIPTION_LINE, width - x + 5, y + (i-removeLine) * 5, 0.4)
else
TEXT_DESCRIPTION_LINE = " " .. TEXT_DESCRIPTION_LINE
removeLine = removeLine + 1
end
djui_hud_set_font(FONT_TINY)
djui_hud_print_text(TEXT_DESCRIPTION_LINE, width - x + 5, 101 + (i-removeLine) * 7, 0.5)
else
removeLine = removeLine + 1
end
local descriptionOffset = (#TEXT_DESCRIPTION_TABLE - removeLine) * 5
y = y + 5 + descriptionOffset
end
local descriptionOffset = (#TEXT_DESCRIPTION_TABLE - removeLine) * 7
djui_hud_print_text(TEXT_COLOR, width - x + 8, 109 + descriptionOffset, 0.6)
if TEX_ICON ~= nil then
djui_hud_print_text(TEXT_LIFE_ICON .. " (" .. TEX_ICON.width .. "x" .. TEX_ICON.height .. ")", width - x + 8, 118 + descriptionOffset, 0.6)
djui_hud_set_color(character.color.r, character.color.g, character.color.b, 255)
djui_hud_print_text(TEXT_COLOR, width - x + 8, y, 0.5)
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
y = y + 7
if TEX_LIFE_ICON ~= nil then
djui_hud_print_text(TEXT_LIFE_ICON .. " (" .. TEX_LIFE_ICON.width .. "x" .. TEX_LIFE_ICON.height .. ")", width - x + 8, y, 0.5)
djui_hud_set_color(255, 255, 255, 255)
djui_hud_render_texture(TEX_ICON, width - x + 38, 119 + descriptionOffset, 0.5 / (TEX_ICON.width / 16), 0.5 / (TEX_ICON.height / 16))
djui_hud_render_texture(TEX_LIFE_ICON, width - x + 33, y + 1, 0.4 / (TEX_LIFE_ICON.width * MATH_DIVIDE_16), 0.4 / (TEX_LIFE_ICON.height * MATH_DIVIDE_16))
else
djui_hud_print_text(TEXT_LIFE_ICON .. " (?x?)", width - x + 8, 118 + descriptionOffset, 0.6)
djui_hud_print_text(TEXT_LIFE_ICON .. " (?x?)", width - x + 8, y, 0.5)
djui_hud_set_font(FONT_HUD)
djui_hud_set_color(255, 255, 255, 255)
djui_hud_print_text(TEXT_ICON_DEFAULT, width - x + 38, 119 + descriptionOffset, 0.5)
djui_hud_print_text(TEXT_ICON_DEFAULT, width - x + 33, y + 1, 0.5)
djui_hud_set_font(FONT_TINY)
end
y = y + 7
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_print_text(TEXT_FORCED_CHAR .. defaultForceChar[character.forceChar], width - x + 8, 127 + descriptionOffset, 0.6)
djui_hud_print_text(TEXT_TABLE_POS .. currChar, width - x + 8, 136 + descriptionOffset, 0.6)
djui_hud_print_text(TEXT_SCALE, width - x + 8, 145 + descriptionOffset, 0.6)
djui_hud_print_text(TEXT_STAR_ICON .. " (" .. TEX_STAR_ICON.width .. "x" .. TEX_STAR_ICON.height .. ")", width - x + 8, y, 0.5)
djui_hud_set_color(255, 255, 255, 255)
djui_hud_render_texture(TEX_STAR_ICON, width - x + 35, y + 1, 0.4 / (TEX_STAR_ICON.width * MATH_DIVIDE_16), 0.4 / (TEX_STAR_ICON.height * MATH_DIVIDE_16))
y = y + 7
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_print_text(TEXT_FORCED_CHAR .. defaultForceChar[character.forceChar], width - x + 8, y, 0.5)
y = y + 7
djui_hud_print_text(TEXT_OFFSET .. character.offset, width - x + 8, y, 0.5)
y = y + 7
djui_hud_print_text(TEXT_TABLE_POS .. currChar, width - x + 8, y, 0.5)
y = y + 7
djui_hud_print_text(TEXT_SCALE, width - x + 8, y, 0.5)
local modelId = gPlayerSyncTable[0].modelId and gPlayerSyncTable[0].modelId or defaultModels[gMarioStates[0].character.type]
if characterColorPresets[modelId] ~= nil then
y = y + 7
djui_hud_print_text(TEXT_PALETTE, width - x + 8, y, 0.5)
local x = x - djui_hud_measure_text(TEXT_PALETTE)*0.5
for i = 0, #characterColorPresets[modelId] do
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_render_rect(width - x + 6.5 + (6.5 * i), y + 1.5, 6, 6)
djui_hud_set_color(characterColorPresets[modelId][i].r, characterColorPresets[modelId][i].g, characterColorPresets[modelId][i].g, 255)
djui_hud_render_rect(width - x + 7 + (6.5 * i), y + 2, 5, 5)
end
end
djui_hud_print_text(TEXT_PREF, width - x + 8, height - 27, 0.6)
djui_hud_print_text(TEXT_PREF_COLOR, width - x + 8, height - 18, 0.6)
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_print_text(TEXT_PRESET, width - x + 8, height - 29, 0.5)
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_print_text(TEXT_PREF, width - x + 8, height - 22, 0.5)
djui_hud_set_color(prefCharColor.r, prefCharColor.g, prefCharColor.b, 255)
djui_hud_print_text(TEXT_PREF_COLOR, width - x + 8, height - 15, 0.5)
end
--Character Buttons
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_render_rect(0, 0, x, height)
djui_hud_set_color(0, 0, 0, 255)
djui_hud_render_rect(2, 2, x - 4, height - 4)
djui_hud_render_rect(0, 50, 2, height - 50)
djui_hud_render_rect(x - 2, 50, 2, height - 50)
djui_hud_render_rect(0, height - 2, x, 2)
if optionTable[optionTableRef.anims].toggle > 0 then
buttonAnimTimer = buttonAnimTimer + 1
@ -699,53 +839,59 @@ local function on_hud_render()
if optionTable[optionTableRef.anims].toggle == 0 then
buttonScroll = 0
elseif math_abs(buttonScroll) > 0.1 then
buttonScroll = buttonScroll * 0.03 * inputStallToDirectional
buttonScroll = buttonScroll * 0.05 * inputStallToDirectional
end
local buttonColor = {}
local buttonX = 20 * widthScale
local buttonAnimX = buttonX + math_sin(buttonAnimTimer * 0.05) * 2.5 + 5
for i = -1, 4 do
if characterTable[i + currChar] ~= nil then
buttonColor = characterTable[i + currChar].color
djui_hud_set_color(buttonColor.r, buttonColor.g, buttonColor.b, 255)
local buttonX = 20 * widthScale
local x = buttonX
if i == 0 then
if optionTable[optionTableRef.anims].toggle > 0 then
buttonX = buttonX + math_sin(buttonAnimTimer * 0.05) * 2.5 + 5
x = buttonAnimX
else
buttonX = buttonX + 10
x = buttonX + 10
end
end
local y = (i + 3) * 30 + buttonScroll
djui_hud_render_rect(buttonX, y, 70, 20)
djui_hud_set_color(0, 0, 0, 255)
djui_hud_render_rect(buttonX + 1, y + 1, 68, 18)
djui_hud_render_rect(x, y, 1, 20)
djui_hud_render_rect(x, y, 70, 1)
djui_hud_render_rect(x + 69, y, 1, 20)
djui_hud_render_rect(x, y + 19, 70, 1)
djui_hud_set_color(0, 0, 0, 200)
djui_hud_render_rect(x + 1, y + 1, 68, 18)
djui_hud_set_font(FONT_TINY)
djui_hud_set_color(buttonColor.r, buttonColor.g, buttonColor.b, 255)
djui_hud_print_text(string_underscore_to_space(characterTable[currChar + i].name), buttonX + 5, y + 5, 0.6)
djui_hud_print_text(characterTable[currChar + i].name, x + 5, y + 5, 0.6)
end
end
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_render_rect(0, height-2, x, 2)
-- Scroll Bar
local MATH_DIVIDE_CHARACTERS = 1/#characterTable
local MATH_7_WIDTHSCALE = 7 * widthScale
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_render_rect(7 * widthScale, 55, 7, 170)
djui_hud_set_color(0, 0, 0, 255)
djui_hud_render_rect(7 * widthScale + 1, 56, 5, 168)
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_render_rect(7 * widthScale + 2, 57 + 166 * ((currChar - 1) / #characterTable) - (buttonScroll * 0.03333333333) * (166 / #characterTable), 3, 166 / #characterTable)
djui_hud_render_rect(MATH_7_WIDTHSCALE, 55, 1, 170)
djui_hud_render_rect(MATH_7_WIDTHSCALE, 55, 7, 1)
djui_hud_render_rect(MATH_7_WIDTHSCALE + 6, 55, 1, 170)
djui_hud_render_rect(MATH_7_WIDTHSCALE, 224, 7, 1)
djui_hud_render_rect(MATH_7_WIDTHSCALE + 2, 57 + 166 * ((currChar - 1) * MATH_DIVIDE_CHARACTERS) - (buttonScroll * MATH_DIVIDE_30) * (166 * MATH_DIVIDE_CHARACTERS), 3, 166 * MATH_DIVIDE_CHARACTERS)
djui_hud_set_font(FONT_TINY)
local TEXT_CHAR_COUNT = currChar .. "/" .. #characterTable
djui_hud_print_text(TEXT_CHAR_COUNT, (11 - djui_hud_measure_text(TEXT_CHAR_COUNT) * 0.2) * widthScale, height - 12, 0.4)
--Character Select Header
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_render_rect(0, 0, width, 50)
djui_hud_set_color(0, 0, 0, 255)
djui_hud_render_rect(2, 2, width - 4, 46)
djui_hud_render_rect(0, 0, width, 2)
djui_hud_render_rect(0, 0, 2, 50)
djui_hud_render_rect(0, 48, width, 2)
djui_hud_render_rect(width - 2, 0, 2, 50)
djui_hud_set_color(menuColor.r * 0.5 + 127, menuColor.g * 0.5 + 127, menuColor.b * 0.5 + 127, 255)
if TEX_OVERRIDE_HEADER then -- Render Override Header
djui_hud_render_texture(TEX_OVERRIDE_HEADER, widthHalf - 128, 10, 1/(TEX_OVERRIDE_HEADER.height*MATH_DIVIDE_THIRTY_TWO), 1/(TEX_OVERRIDE_HEADER.height*MATH_DIVIDE_THIRTY_TWO))
djui_hud_render_texture(TEX_OVERRIDE_HEADER, widthHalf - 128, 10, 1 / (TEX_OVERRIDE_HEADER.height*MATH_DIVIDE_32), 1 / (TEX_OVERRIDE_HEADER.height*MATH_DIVIDE_32))
else
djui_hud_render_texture(TEX_HEADER, widthHalf - 128, 10, 1, 1)
end
@ -758,14 +904,15 @@ local function on_hud_render()
djui_hud_print_text(TEXT_RATIO_UNSUPPORTED, 5, 39, 0.5)
end
-- API Rendering
if #renderInMenuTable > 0 then
for i = 1, #renderInMenuTable do
renderInMenuTable[i]()
-- API Rendering (Above Text)
if #renderInMenuTable.front > 0 then
for i = 1, #renderInMenuTable.front do
renderInMenuTable.front[i]()
end
end
--Options display
local optionTableCount = #optionTable
if options or optionAnimTimer > optionAnimTimerCap then
djui_hud_set_color(menuColor.r * 0.25, menuColor.g * 0.25, menuColor.b * 0.25, 205 + maxf(-200, optionAnimTimer))
djui_hud_render_rect(0, 0, width, height)
@ -773,9 +920,13 @@ local function on_hud_render()
djui_hud_render_rect(width * 0.5 - 50 * widthScale, minf(55 - optionAnimTimer, height - 25 * widthScale), 100 * widthScale, 200)
djui_hud_set_color(0, 0, 0, 255)
djui_hud_render_rect(width * 0.5 - 50 * widthScale + 2, minf(55 - optionAnimTimer + 2, height - 25 * widthScale + 2), 100 * widthScale - 4, 196)
djui_hud_set_font(FONT_CS_NORMAL)
djui_hud_set_font(FONT_ALIASED)
djui_hud_set_color(menuColor.r * 0.5 + 127, menuColor.g * 0.5 + 127, menuColor.b * 0.5 + 127, 255)
djui_hud_print_text(TEXT_OPTIONS_HEADER, widthHalf - djui_hud_measure_text(TEXT_OPTIONS_HEADER) * 0.3 * minf(widthScale, 1.5), 65 + optionAnimTimer * -1, 0.6 * minf(widthScale, 1.5))
local text = TEXT_OPTIONS_HEADER
if currOption > defaultOptionCount then
text = TEXT_OPTIONS_HEADER_API
end
djui_hud_print_text(text, widthHalf - djui_hud_measure_text(text) * 0.3 * minf(widthScale, 1.5), 65 + optionAnimTimer * -1, 0.6 * minf(widthScale, 1.5))
local widthScaleLimited = minf(widthScale, 1.5)
-- Up Arrow
@ -806,11 +957,13 @@ local function on_hud_render()
local scale = 0.5
local yOffset = 100 - optionAnimTimer + (i - currOption + 2) * 9 * widthScaleLimited
if i == currOption then
djui_hud_set_font(FONT_CS_NORMAL)
djui_hud_set_font(FONT_ALIASED)
scale = 0.3
yOffset = yOffset - 1
if optionTable[i].toggleNames[optionTable[i].toggle + 1] ~= "" then
toggleName = toggleName .. " - " .. optionTable[i].toggleNames[optionTable[i].toggle + 1]
local currToggleName = optionTable[i].toggleNames[optionTable[i].toggle + 1]
currToggleName = currToggleName and currToggleName or "???"
if currToggleName ~= "" then
toggleName = toggleName .. " - " .. currToggleName
else
toggleName = toggleName
end
@ -828,7 +981,7 @@ local function on_hud_render()
if optionTable[currOption].description ~= nil then
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
for i = 1, #optionTable[currOption].description do
djui_hud_set_font(FONT_CS_NORMAL)
djui_hud_set_font(FONT_ALIASED)
local line = optionTable[currOption].description[i]
djui_hud_print_text(line, widthHalf - djui_hud_measure_text(line) * 0.15, 180 - optionAnimTimer + 15 * widthScaleLimited + 8 * i - 8 * #optionTable[currOption].description, 0.3)
end
@ -848,7 +1001,7 @@ local function on_hud_render()
djui_hud_render_rect(widthHalf - 50 * widthScale + 2, height - 25 * widthScaleLimited + 2, 100 * widthScale - 4, 22 * widthScaleLimited)
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
djui_hud_render_rect(widthHalf - 50 * widthScale, height - 2, 100 * widthScale, 2)
djui_hud_set_font(FONT_CS_NORMAL)
djui_hud_set_font(FONT_ALIASED)
djui_hud_print_text(TEXT_OPTIONS_OPEN, widthHalf - djui_hud_measure_text(TEXT_OPTIONS_OPEN) * 0.175 * widthScaleLimited, height - 23 * widthScaleLimited + optionAnimTimer + 202, 0.35 * widthScaleLimited)
djui_hud_set_font(FONT_TINY)
djui_hud_print_text(TEXT_MENU_CLOSE, widthHalf - djui_hud_measure_text(TEXT_MENU_CLOSE) * 0.25 * widthScaleLimited, height - 13 * widthScaleLimited + optionAnimTimer + 202, 0.5 * widthScaleLimited)
@ -859,7 +1012,7 @@ local function on_hud_render()
if options then
if optionTable[optionTableRef.anims].toggle > 0 then
if optionAnimTimer < -1 then
optionAnimTimer = optionAnimTimer / 1.1
optionAnimTimer = optionAnimTimer * 0.9
end
else
optionAnimTimer = -1
@ -910,16 +1063,13 @@ local function on_hud_render()
if is_game_paused() and not djui_hud_is_pause_menu_created() and gMarioStates[0].action ~= ACT_EXIT_LAND_SAVE_DIALOG then
local currCharY = 0
djui_hud_set_resolution(RESOLUTION_DJUI)
djui_hud_set_font(FONT_NORMAL)
if optionTable[optionTableRef.openInputs].toggle == 2 then
djui_hud_set_font(FONT_USER)
if optionTable[optionTableRef.openInputs].toggle == 1 then
currCharY = 27
width = djui_hud_get_screen_width() - djui_hud_measure_text(TEXT_PAUSE_Z_OPEN)
if not IS_COOPDX then -- Done to match DX not having dropshadow on the "R Button - Options" thingy
djui_hud_set_color(0, 0, 0, 255)
djui_hud_print_text(TEXT_PAUSE_Z_OPEN, width - 19, 17, 1)
end
local text = menu_is_allowed() and TEXT_PAUSE_Z_OPEN or TEXT_PAUSE_UNAVALIBLE
width = djui_hud_get_screen_width() - djui_hud_measure_text(text)
djui_hud_set_color(255, 255, 255, 255)
djui_hud_print_text(TEXT_PAUSE_Z_OPEN, width - 20, 16, 1)
djui_hud_print_text(text, width - 20, 16, 1)
end
if optionTable[optionTableRef.localModels].toggle == 1 then
@ -927,20 +1077,12 @@ local function on_hud_render()
local TEXT_PAUSE_CURR_CHAR_WITH_NAME = TEXT_PAUSE_CURR_CHAR .. charName
width = djui_hud_get_screen_width() - djui_hud_measure_text(TEXT_PAUSE_CURR_CHAR_WITH_NAME)
local charColor = characterTable[currChar].color
if not IS_COOPDX then
djui_hud_set_color(0, 0, 0, 255)
djui_hud_print_text(TEXT_PAUSE_CURR_CHAR_WITH_NAME, width - 19, 17 + currCharY, 1)
end
djui_hud_set_color(255, 255, 255, 255)
djui_hud_print_text(TEXT_PAUSE_CURR_CHAR, width - 20, 16 + currCharY, 1)
djui_hud_set_color(charColor.r, charColor.g, charColor.b, 255)
djui_hud_print_text(charName, djui_hud_get_screen_width() - djui_hud_measure_text(charName) - 20, 16 + currCharY, 1)
else
width = djui_hud_get_screen_width() - djui_hud_measure_text(TEXT_LOCAL_MODEL_OFF)
if not IS_COOPDX then
djui_hud_set_color(0, 0, 0, 255)
djui_hud_print_text(TEXT_LOCAL_MODEL_OFF, width - 19, 17 + currCharY, 1)
end
djui_hud_set_color(255, 255, 255, 255)
djui_hud_print_text(TEXT_LOCAL_MODEL_OFF, width - 20, 16 + currCharY, 1)
end
@ -957,18 +1099,19 @@ local function before_mario_update(m)
end
-- Menu Inputs
if not menu and (m.controller.buttonDown & D_JPAD) ~= 0 and m.action ~= ACT_EXIT_LAND_SAVE_DIALOG and optionTable[optionTableRef.openInputs].toggle == 1 then
if ommActive then
if (m.controller.buttonDown & R_TRIG) ~= 0 then
menu = true
end
else
if is_game_paused() and m.action ~= ACT_EXIT_LAND_SAVE_DIALOG and (m.controller.buttonPressed & Z_TRIG) ~= 0 and optionTable[optionTableRef.openInputs].toggle == 1 then
menu = true
end
if not menu and (m.controller.buttonDown & D_JPAD) ~= 0 and m.action ~= ACT_EXIT_LAND_SAVE_DIALOG and optionTable[optionTableRef.openInputs].toggle == 2 then
if (m.controller.buttonDown & R_TRIG) ~= 0 or not ommActive then
menu = true
end
inputStallTimerDirectional = inputStallToDirectional
end
if is_game_paused() and m.action ~= ACT_EXIT_LAND_SAVE_DIALOG and (m.controller.buttonPressed & Z_TRIG) ~= 0 and optionTable[optionTableRef.openInputs].toggle == 2 then
menu = true
if not menu_is_allowed() then
menu = false
return
end
local cameraToObject = gMarioStates[0].marioObj.header.gfx.cameraToObject
@ -985,7 +1128,7 @@ local function before_mario_update(m)
if menuAndTransition and not options then
if menu then
if inputStallTimerDirectional == 0 then
if inputStallTimerDirectional == 0 and optionTable[optionTableRef.localModels].toggle ~= 0 and not charBeingSet then
if (m.controller.buttonPressed & D_JPAD) ~= 0 or (m.controller.buttonPressed & D_CBUTTONS) ~= 0 or m.controller.stickY < -60 then
currChar = currChar + 1
if (m.controller.buttonPressed & D_CBUTTONS) == 0 then
@ -993,8 +1136,13 @@ local function before_mario_update(m)
else
inputStallTimerDirectional = 3 -- C-Scrolling
end
buttonScroll = buttonScrollCap
if currChar > #characterTable then
buttonScroll = -buttonScrollCap * #characterTable
else
buttonScroll = buttonScrollCap
end
play_sound(SOUND_MENU_MESSAGE_NEXT_PAGE, cameraToObject)
gPlayerSyncTable[0].presetPalette = false
end
if (m.controller.buttonPressed & U_JPAD) ~= 0 or (m.controller.buttonPressed & U_CBUTTONS) ~= 0 or m.controller.stickY > 60 then
currChar = currChar - 1
@ -1003,8 +1151,13 @@ local function before_mario_update(m)
else
inputStallTimerDirectional = 3 -- C-Scrolling
end
buttonScroll = -buttonScrollCap
if currChar < 1 then
buttonScroll = buttonScrollCap * (#characterTable - 1)
else
buttonScroll = -buttonScrollCap
end
play_sound(SOUND_MENU_MESSAGE_NEXT_PAGE, cameraToObject)
gPlayerSyncTable[0].presetPalette = false
end
end
@ -1024,6 +1177,17 @@ local function before_mario_update(m)
if (m.controller.buttonPressed & START_BUTTON) ~= 0 then
options = true
end
local modelId = gPlayerSyncTable[0].modelId and gPlayerSyncTable[0].modelId or defaultModels[m.character.type]
if (m.controller.buttonPressed & Y_BUTTON) ~= 0 then
if characterColorPresets[modelId] and optionTable[optionTableRef.localModels].toggle > 0 and not stopPalettes then
play_sound(SOUND_MENU_CLICK_FILE_SELECT, cameraToObject)
gPlayerSyncTable[0].presetPalette = not gPlayerSyncTable[0].presetPalette
inputStallTimerButton = inputStallToButton
else
play_sound(SOUND_MENU_CAMERA_BUZZ, cameraToObject)
inputStallTimerButton = inputStallToButton
end
end
end
end
-- Wraping Menu
@ -1066,7 +1230,7 @@ local function before_mario_update(m)
end
if inputStallTimerButton == 0 then
if (m.controller.buttonPressed & A_BUTTON) ~= 0 then
if (m.controller.buttonPressed & A_BUTTON) ~= 0 and not optionTable[currOption].optionBeingSet then
optionTable[currOption].toggle = optionTable[currOption].toggle + 1
if optionTable[currOption].toggle > optionTable[currOption].toggleMax then optionTable[currOption].toggle = 0 end
if optionTable[currOption].toggleSaveName ~= nil then
@ -1120,6 +1284,12 @@ local function chat_command(msg)
return true
end
-- Stop Character checks if API disallows it
if not menu_is_allowed() or charBeingSet then
djui_chat_message_create("Character Cannot be Changed")
return true
end
-- Name Check
for i = 1, #characterTable do
if msg == string_lower(characterTable[i].name) or msg == string_underscore_to_space(string_lower(characterTable[i].saveName)) then

View file

@ -2,17 +2,83 @@
-- Custom HUD Rendering by Agent X and xLuigiGamerx --
------------------------------------------------------
if incompatibleClient then return 0 end
local defaultIcons = {
[CT_MARIO] = gTextures.mario_head,
[CT_LUIGI] = gTextures.luigi_head,
[CT_TOAD] = gTextures.toad_head,
[CT_WALUIGI] = gTextures.waluigi_head,
[CT_WARIO] = gTextures.wario_head
}
local MATH_DIVIDE_16 = 1/16
-- Localize Functions to improve performence
local texture_override_set,texture_override_reset,djui_hud_print_text,djui_hud_render_texture,tostring,hud_set_value,hud_get_value,hud_get_flash,djui_hud_get_screen_width,djui_hud_render_rect,math_ceil = texture_override_set,texture_override_reset,djui_hud_print_text,djui_hud_render_texture,tostring,hud_set_value,hud_get_value,hud_get_flash,djui_hud_get_screen_width,djui_hud_render_rect,math.ceil
--- @param localIndex integer
--- @return TextureInfo|nil
--- This assumes multiple characters will not have the same model
--- This assumes multiple characters will not have the same model,
--- Icons can only be seen by users who have the character avalible to them.
--- This function can return nil. if this is the case, render `djui_hud_print_text("?", x, y, 1)`
function life_icon_from_local_index(localIndex)
for i = 1, #characterTable do
if i == 1 and characterTable[i].model == gPlayerSyncTable[localIndex].modelId then
return defaultIcons[gMarioStates[localIndex].character.type]
end
if characterTable[i].model == gPlayerSyncTable[localIndex].modelId then
return characterTable[i].lifeIcon
end
end
end
--- @param localIndex integer
--- @return TextureInfo
--- This assumes multiple characters will not have the same model,
--- Icons can only be seen by users who have the character avalible to them
function star_icon_from_local_index(localIndex)
for i = 1, #characterTable do
if characterTable[i].model == gPlayerSyncTable[localIndex].modelId then
return characterTable[i].starIcon
end
end
return gTextures.star
end
local pieTextureNames = {
"one_segments",
"two_segments",
"three_segments",
"four_segments",
"five_segments",
"six_segments",
"seven_segments",
"full",
}
local function render_hud_health()
local textureTable = characterTable[currChar].healthTexture
if textureTable then -- sets health HUD to custom textures
if textureTable.label.left and textureTable.label.right then -- if left and right label textures exist. BOTH have to exist to be set!
texture_override_set("texture_power_meter_left_side", textureTable.label.left)
texture_override_set("texture_power_meter_right_side", textureTable.label.right)
end
for i = 1, 8 do
texture_override_set("texture_power_meter_" .. pieTextureNames[i], textureTable.pie[i])
end
else -- resets the health HUD
texture_override_reset("texture_power_meter_left_side")
texture_override_reset("texture_power_meter_right_side")
for i = 1, 8 do
texture_override_reset("texture_power_meter_" .. pieTextureNames[i])
end
end
end
local function render_hud_mario_lives()
hud_set_value(HUD_DISPLAY_FLAGS, hud_get_value(HUD_DISPLAY_FLAGS) & ~HUD_DISPLAY_FLAG_LIVES)
@ -23,7 +89,7 @@ local function render_hud_mario_lives()
if lifeIcon == nil then
djui_hud_print_text("?", x, y, 1)
else
djui_hud_render_texture(lifeIcon, x, y, 1 / (lifeIcon.width * 0.0625), 1 / (lifeIcon.height * 0.0625)) -- 0.0625 is 1/16
djui_hud_render_texture(lifeIcon, x, y, 1 / (lifeIcon.width * MATH_DIVIDE_16), 1 / (lifeIcon.height * MATH_DIVIDE_16))
end
djui_hud_print_text("@", x + 16, y, 1)
djui_hud_print_text(tostring(hud_get_value(HUD_DISPLAY_LIVES)):gsub("-", "M"), x + 32, y, 1)
@ -32,10 +98,7 @@ end
local function render_hud_stars()
hud_set_value(HUD_DISPLAY_FLAGS, hud_get_value(HUD_DISPLAY_FLAGS) & ~HUD_DISPLAY_FLAG_STAR_COUNT)
-- the flashing when you exit a painting, uses sm64coopdx exclusive functionality
-- v0.1.5
--[[
if IS_COOPDX then
if IS_COOPDX and hud_get_flash ~= nil then
-- prevent star count from flashing outside of castle
if gNetworkPlayers[0].currCourseNum ~= COURSE_NONE then hud_set_flash(0) end
@ -43,17 +106,19 @@ local function render_hud_stars()
return
end
end
]]
local x = djui_hud_get_screen_width() - 78
local y = 15 -- SCREEN_HEIGHT - 209 - 16
local x = math_ceil(djui_hud_get_screen_width() - 76)
if x % 2 ~= 0 then
x = x - 1
end
local y = math_ceil(240 - 209 - 16)
local starIcon = characterTable[currChar].starIcon and characterTable[currChar].starIcon or gTextures.star
local showX = 0
local hudDisplayStars = hud_get_value(HUD_DISPLAY_STARS)
if hudDisplayStars < 100 then showX = 1 end
djui_hud_render_texture(starIcon, x, y, 1 / (starIcon.width * 0.0625), 1 / (starIcon.height * 0.0625)) -- 0.0625 is 1/16
djui_hud_render_texture(starIcon, x, y, 1 / (starIcon.width*MATH_DIVIDE_16), 1 / (starIcon.height*MATH_DIVIDE_16))
if showX == 1 then
djui_hud_print_text("@", x + 16, y, 1)
end
@ -79,7 +144,7 @@ local function render_hud_camera_status()
if lifeIcon == nil then
djui_hud_print_text("?", x + 16, y, 1)
else
djui_hud_render_texture(lifeIcon, x + 16, y, 1 / (lifeIcon.width * 0.0625), 1 / (lifeIcon.height * 0.0625)) -- 0.0625 is 1/16
djui_hud_render_texture(lifeIcon, x + 16, y, 1 / (lifeIcon.width * MATH_DIVIDE_16), 1 / (lifeIcon.height * MATH_DIVIDE_16))
end
end,
[CAM_STATUS_LAKITU] = function()
@ -103,20 +168,21 @@ end
local function render_act_select_hud()
local course = gNetworkPlayers[0].currCourseNum
if gServerSettings.enablePlayersInLevelDisplay == 0 or course == 0 or obj_get_first_with_behavior_id(id_bhvActSelector) == nil then return end
local stars = save_file_get_star_flags(get_current_save_file_num() - 1, course - 1)
local maxStar = 0
local wasLastActBeat = true -- True by default to account for 0 stars collected not needing an offset
for i = 5, 0, -1 do
if stars & 2 ^ i ~= 0 then
maxStar = i
wasLastActBeat = stars & 2^(i-1) ~= 0
break
end
end
for a = 1, maxStar + 1 do
local x = (38 - maxStar * 17 + a * 34) + djui_hud_get_screen_width() * 0.5 - 75
for j = 0, MAX_PLAYERS - 1 do
local x = (139 - (maxStar - (wasLastActBeat and 1 or 0) - (maxStar < 5 and 0 or 1) - (maxStar < 1 and 1 or 0)) * 17 + (a - (wasLastActBeat and 1 or 0)) * 34) + (djui_hud_get_screen_width()/2) - 176
for j = 1, MAX_PLAYERS - 1 do -- 0 is not needed due to the due to the fact that you are never supposed to see yourself in the act
local np = gNetworkPlayers[j]
if np and np.connected and np.currCourseNum == course and np.currActNum == a then
djui_hud_render_rect(x - 4, 17, 16, 16)
@ -124,8 +190,9 @@ local function render_act_select_hud()
if displayHead == nil then
djui_hud_print_text("?", x - 4, 17, 1)
else
djui_hud_render_texture(displayHead, x - 4, 17, 1 / (displayHead.width * 0.0625), 1 / (displayHead.height * 0.0625)) -- 0.0625 is 1/16
djui_hud_render_texture(displayHead, x - 4, 17, 1 / (displayHead.width/16), 1 / (displayHead.height * MATH_DIVIDE_16))
end
break
end
end
end
@ -136,17 +203,26 @@ local function on_hud_render_behind()
djui_hud_set_font(FONT_HUD)
djui_hud_set_color(255, 255, 255, 255)
if obj_get_first_with_behavior_id(id_bhvActSelector) ~= nil then
render_act_select_hud()
return
elseif gNetworkPlayers[0].currActNum == 99 or gMarioStates[0].action == ACT_INTRO_CUTSCENE or hud_is_hidden() then
if gNetworkPlayers[0].currActNum == 99 or gMarioStates[0].action == ACT_INTRO_CUTSCENE or hud_is_hidden() or obj_get_first_with_behavior_id(id_bhvActSelector) ~= nil then
return
end
render_hud_mario_lives()
render_hud_stars()
render_hud_camera_status()
render_hud_health()
end
local function on_hud_render()
djui_hud_set_resolution(RESOLUTION_N64)
djui_hud_set_font(FONT_HUD)
djui_hud_set_color(255, 255, 255, 255)
if obj_get_first_with_behavior_id(id_bhvActSelector) ~= nil then
render_act_select_hud()
end
end
hook_event(HOOK_ON_HUD_RENDER_BEHIND, on_hud_render_behind)
hook_event(HOOK_ON_HUD_RENDER_BEHIND, on_hud_render_behind)
hook_event(HOOK_ON_HUD_RENDER, on_hud_render)

View file

@ -1,3 +1,6 @@
if incompatibleClient then return 0 end
--- @class CharacterTable
--- @field public name string
--- @field public saveName string
@ -8,15 +11,20 @@
--- @field public forceChar CharacterType
--- @field public lifeIcon TextureInfo
--- @field public camScale integer
--- @field public offset integer
-- localize functions to improve performance
local smlua_model_util_get_id,table_insert,djui_hud_measure_text,type = smlua_model_util_get_id,table.insert,djui_hud_measure_text,type
local smlua_model_util_get_id,table_insert,type,djui_hud_measure_text,tonumber = smlua_model_util_get_id,table.insert,type,djui_hud_measure_text,tonumber
local characterVoices = {}
local saveNameTable = {}
local E_MODEL_ARMATURE = smlua_model_util_get_id("armature_geo")
---------
-- API --
---------
local function split_text_into_lines(text)
local words = {}
for word in text:gmatch("%S+") do
@ -39,33 +47,44 @@ local function split_text_into_lines(text)
return lines
end
---------
-- API --
---------
local TYPE_INTEGER = "number"
local TYPE_STRING = "string"
local TYPE_TABLE = "table"
local TYPE_FUNCTION = "function"
---@param name string|nil Underscores turn into Spaces
---@param description table|string|nil {"string"}
---@param credit string|nil
---@param color Color|nil {r, g, b}
---@param color Color|string|nil {r, g, b}
---@param modelInfo ModelExtendedId|integer|nil Use smlua_model_util_get_id()
---@param forceChar CharacterType|nil CT_MARIO, CT_LUIGI, CT_TOAD, CT_WALUIGI, CT_WARIO
---@param lifeIcon TextureInfo|nil Use get_texture_info()
---@param camScale integer|nil Zooms the camera based on a multiplier (Default 1.0)
---@param offset integer|nil Visually offsets the character
---@return integer
local function character_add(name, description, credit, color, modelInfo, forceChar, lifeIcon, camScale)
if type(description) == "string" then
local function character_add(name, description, credit, color, modelInfo, forceChar, lifeIcon, camScale, offset)
if type(description) == TYPE_STRING then
description = split_text_into_lines(description)
end
if type(color) == TYPE_STRING then
color = {r = tonumber(color:sub(1,2), 16), g = tonumber(color:sub(3,4), 16), b = tonumber(color:sub(5,6), 16) }
end
if type(offset) ~= TYPE_INTEGER then
offset = (forceChar == CT_WALUIGI and 25 or 0)
end
table_insert(characterTable, {
name = name and name or "Untitled",
saveName = name and string_space_to_underscore(name) or "Untitled",
description = description and description or {"No description has been provided"},
credit = credit and credit or "Unknown",
color = color and color or {r = 255, g = 255, b = 255},
model = modelInfo and modelInfo or E_MODEL_ARMATURE,
name = type(name) == TYPE_STRING and name or "Untitled",
saveName = type(name) == TYPE_STRING and string_space_to_underscore(name) or "Untitled",
description = type(description) == TYPE_TABLE and description or {"No description has been provided"},
credit = type(credit) == TYPE_STRING and credit or "Unknown",
color = type(color) == TYPE_TABLE and color or {r = 255, g = 255, b = 255},
model = (modelInfo and modelInfo ~= E_MODEL_ERROR_MODEL) and modelInfo or E_MODEL_ARMATURE,
forceChar = forceChar and forceChar or CT_MARIO,
lifeIcon = lifeIcon and lifeIcon or nil,
camScale = camScale and camScale or 1
offset = offset and offset or 0,
lifeIcon = type(lifeIcon) == TYPE_TABLE and lifeIcon or nil,
starIcon = gTextures.star,
camScale = type(camScale) == TYPE_INTEGER and camScale or 1,
healthTexture = nil,
})
saveNameTable[#characterTable] = characterTable[#characterTable].saveName
return #characterTable
@ -77,36 +96,56 @@ end
---@param credit string|nil
---@param color Color|nil {r, g, b}
---@param modelInfo ModelExtendedId|integer|nil Use smlua_model_util_get_id()
---@param forceChar CharacterType|nil CT_MARIO, CT_LUIGI, CT_TOAD, CT_WALUIGI, CT_WARIO
---@param forceChar integer|CharacterType|nil CT_MARIO, CT_LUIGI, CT_TOAD, CT_WALUIGI, CT_WARIO
---@param lifeIcon TextureInfo|nil Use get_texture_info()
---@param camScale integer|nil Zooms the camera based on a multiplier (Default 1.0)
local function character_edit(charNum, name, description, credit, color, modelInfo, forceChar, lifeIcon, camScale)
if type(description) == "string" then
---@param offset integer|nil Visually offsets the character
local function character_edit(charNum, name, description, credit, color, modelInfo, forceChar, lifeIcon, camScale, offset)
if tonumber(charNum) == nil or charNum > #characterTable or charNum < 0 then return end
if type(description) == TYPE_STRING then
description = split_text_into_lines(description)
end
if type(color) == TYPE_STRING then
color = {r = tonumber(color:sub(1,2), 16), g = tonumber(color:sub(3,4), 16), b = tonumber(color:sub(5,6), 16) }
end
if type(offset) ~= TYPE_INTEGER then
offset = (forceChar == CT_WALUIGI and 25 or 0)
end
local tableCache = characterTable[charNum]
characterTable[charNum] = characterTable[charNum] and {
name = name and name or characterTable[charNum].name,
name = type(name) == TYPE_STRING and name or tableCache.name,
saveName = saveNameTable[charNum],
description = description and description or characterTable[charNum].description,
credit = credit and credit or characterTable[charNum].credit,
color = color and color or characterTable[charNum].color,
model = modelInfo and modelInfo or characterTable[charNum].model,
forceChar = forceChar and forceChar or characterTable[charNum].forceChar,
lifeIcon = lifeIcon and lifeIcon or characterTable[charNum].lifeIcon,
camScale = camScale and camScale or 1
description = type(description) == TYPE_TABLE and description or tableCache.description,
credit = type(credit) == TYPE_STRING and credit or tableCache.credit,
color = type(color) == TYPE_TABLE and color or tableCache.color,
model = (modelInfo and modelInfo ~= E_MODEL_ERROR_MODEL) and modelInfo or tableCache.model,
forceChar = type(forceChar) == TYPE_INTEGER and forceChar or tableCache.forceChar,
offset = type(offset) == TYPE_INTEGER and offset or tableCache.offset,
lifeIcon = type(lifeIcon) == TYPE_TABLE and lifeIcon or tableCache.lifeIcon,
starIcon = tableCache.starIcon, -- Done to prevent it getting lost in the sauce
camScale = type(camScale) == TYPE_INTEGER and camScale or tableCache.camScale,
healthTexture = tableCache.healthTexture,
} or nil
end
---@param modelInfo ModelExtendedId|integer
---@param clips table
local function character_add_voice(modelInfo, clips)
characterVoices[modelInfo] = clips
characterVoices[modelInfo] = type(clips) == TYPE_TABLE and clips or nil
end
---@param modelInfo ModelExtendedId|integer
---@param caps table
local function character_add_caps(modelInfo, caps)
characterCaps[modelInfo] = caps
characterCaps[modelInfo] = type(caps) == TYPE_TABLE and caps or nil
end
---@param charNum integer
---@param healthTexture table|nil
local function character_add_health_meter(charNum, healthTexture)
if type(charNum) ~= TYPE_INTEGER or charNum == nil then return end
characterTable[charNum].healthTexture = type(healthTexture) == TYPE_TABLE and healthTexture or nil
return false
end
---@param modelInfo ModelExtendedId|integer
@ -116,24 +155,56 @@ local function character_add_celebration_star(modelInfo, starModel, starIcon)
characterCelebrationStar[modelInfo] = starModel
for i = 2, #characterTable do
if characterTable[i].model == modelInfo then
characterTable[i].starIcon = starIcon and starIcon or gTextures.star
characterTable[i].starIcon = type(starIcon) == TYPE_TABLE and starIcon or gTextures.star
return
end
end
return false
end
---@param modelInfo ModelExtendedId|integer
---@param paletteTable table
local function character_add_palette_preset(modelInfo, paletteTable)
local paletteTableOut = {}
local defaultColors = characterColorPresets[E_MODEL_MARIO]
for i = 0, 7 do
local color = paletteTable[i]
paletteTableOut[i] = {r = 0, g = 0, b = 0}
if type(color) == TYPE_STRING then
paletteTableOut[i].r = tonumber(color:sub(1,2), 16) and tonumber(color:sub(1,2), 16) or defaultColors[i].r
paletteTableOut[i].g = tonumber(color:sub(3,4), 16) and tonumber(color:sub(3,4), 16) or defaultColors[i].g
paletteTableOut[i].b = tonumber(color:sub(5,6), 16) and tonumber(color:sub(5,6), 16) or defaultColors[i].b
end
if type(color) == TYPE_TABLE then
paletteTableOut[i].r = (type(color) == TYPE_TABLE and color.r ~= nil) and color.r or defaultColors[i].r
paletteTableOut[i].g = (type(color) == TYPE_TABLE and color.g ~= nil) and color.g or defaultColors[i].g
paletteTableOut[i].b = (type(color) == TYPE_TABLE and color.b ~= nil) and color.b or defaultColors[i].b
end
end
characterColorPresets[modelInfo] = paletteTableOut
end
---@param tablePos integer|nil
---@return CharacterTable
local function character_get_current_table()
return characterTable[currChar]
local function character_get_current_table(tablePos)
tablePos = tablePos and tablePos or currChar
return characterTable[tablePos]
end
local function character_get_current_number()
return currChar
end
---@param charNum integer|nil
local function character_set_current_number(charNum)
if type(charNum) ~= TYPE_INTEGER or characterTable[charNum] == nil then return end
currChar = charNum
charBeingSet = true
end
---@param name string
local function character_get_number_from_string(name)
if type(name) ~= TYPE_STRING then return nil end
for i = 2, #characterTable do
if characterTable[i].name == name or characterTable[i].name == string_space_to_underscore(name) then
return i
@ -147,26 +218,54 @@ local function character_get_voice(m)
return characterVoices[gPlayerSyncTable[m.playerIndex].modelId]
end
---@return string
local function version_get()
return MOD_VERSION
end
---@return boolean
local function is_menu_open()
return menuAndTransition
end
---@param bool boolean|nil Sets if the menu is open
local function set_menu_open(bool)
if bool == nil then bool = true end
menu = bool
end
---@return table
local function get_menu_color()
return update_menu_color()
end
---@param func function
local function hook_allow_menu_open(func)
if type(func) ~= TYPE_FUNCTION then return end
table_insert(allowMenu, func)
end
local function hook_render_in_menu(func)
table_insert(renderInMenuTable, func)
---@param func function
local function hook_render_in_menu(func, underText)
if type(func) ~= TYPE_FUNCTION then return end
if underText then
table_insert(renderInMenuTable.back, func)
else
table_insert(renderInMenuTable.front, func)
end
end
---@return boolean
local function is_options_open()
return options
end
---@param bool boolean
local function restrict_palettes(bool)
if bool == nil then bool = true end
stopPalettes = bool
end
local controller = {
buttonDown = 0,
buttonPressed = 0,
@ -179,31 +278,89 @@ local controller = {
stickY = 0
}
---@param name string
---@param toggleDefault number|nil Defaults to 0
---@param toggleMax number|nil Defaults to 1
---@param toggleNames table|nil Table of Strings {"Off", "On"}
---@param description table|nil Table of Strings {"This toggle allows your", "character to feel everything."}
---@param save boolean|nil Defaults to true
---@return number
local function add_option(name, toggleDefault, toggleMax, toggleNames, description, save)
if save == nil then save = true end
local saveName = string_space_to_underscore(name)
table_insert(optionTable, {
name = type(name) == TYPE_STRING and name or "Unknown Toggle",
toggle = nil, -- Set as nil for Failsafe to Catch
toggleSaveName = save and saveName or nil,
toggleDefault = type(toggleDefault) == TYPE_INTEGER and toggleDefault or 0,
toggleMax = type(toggleMax) == TYPE_INTEGER and toggleMax or 1,
toggleNames = type(toggleNames) == TYPE_TABLE and toggleNames or {"Off", "On"},
description = type(description) == TYPE_TABLE and description or {""},
})
queueStorageFailsafe = true -- Used variable trigger to not save/load in the external mod
return #optionTable
end
---@param tableNum integer
local function get_status(tableNum)
---@return table|nil
local function get_option(tableNum)
if type(tableNum) ~= TYPE_INTEGER then return nil end
return optionTable[tableNum]
end
---@param tableNum integer
---@return number|nil
local function get_options_status(tableNum)
if type(tableNum) ~= TYPE_INTEGER then return nil end
return optionTable[tableNum].toggle
end
---@param tableNum integer
---@param toggle integer
local function set_options_status(tableNum, toggle)
local currOption = optionTable[tableNum]
if currOption == nil or type(toggle) ~= TYPE_INTEGER or toggle > currOption.toggleMax or toggle < 1 then return end
optionTable[tableNum].toggle = toggle
optionTable[tableNum].optionBeingSet = true
end
_G.charSelectExists = true
_G.charSelect = {
-- Character Functions --
character_add = character_add,
character_edit = character_edit,
character_add_voice = character_add_voice,
character_add_caps = character_add_caps,
character_add_celebration_star = character_add_celebration_star,
character_add_health_meter = character_add_health_meter,
character_add_palette_preset = character_add_palette_preset,
character_get_current_table = character_get_current_table,
character_get_current_number = character_get_current_number,
character_get_current_model_number --[[Depreiciated Function Name, Not recommended for use]] = character_get_current_number,
character_get_current_model_number = character_get_current_number, -- Outdated function name, Not recommended for use
character_set_current_number = character_set_current_number,
character_get_number_from_string = character_get_number_from_string,
character_get_voice = character_get_voice,
character_get_life_icon = life_icon_from_local_index,
character_get_life_icon = life_icon_from_local_index, -- Function located in n-hud.lua
character_get_star_icon = star_icon_from_local_index, -- Function located in n-hud.lua
-- Menu Functions --
header_set_texture = header_set_texture, -- Function located in main.lua
version_get = version_get,
is_menu_open = is_menu_open,
set_menu_open = set_menu_open,
is_options_open = is_options_open,
get_status = get_status,
get_menu_color = get_menu_color,
add_option = add_option,
get_option = get_option,
get_options_status = get_options_status,
set_options_status = set_options_status,
restrict_palettes = restrict_palettes,
-- Tables --
optionTableRef = optionTableRef,
controller = controller,
-- Custom Hooks --
hook_allow_menu_open = hook_allow_menu_open,
hook_render_in_menu = hook_render_in_menu,
}

View file

@ -0,0 +1,138 @@
if incompatibleClient then return 0 end
characterColorPresets = {
[E_MODEL_MARIO] = {
[PANTS] = {r = 0x00, g = 0x00, b = 0xff},
[SHIRT] = {r = 0xff, g = 0x00, b = 0x00},
[GLOVES] = {r = 0xff, g = 0xff, b = 0xff},
[SHOES] = {r = 0x72, g = 0x1c, b = 0x0e},
[HAIR] = {r = 0x73, g = 0x06, b = 0x00},
[SKIN] = {r = 0xfe, g = 0xc1, b = 0x79},
[CAP] = {r = 0xff, g = 0x00, b = 0x00},
[EMBLEM] = {r = 0xff, g = 0x00, b = 0x00},
},
[E_MODEL_LUIGI] = {
[PANTS] = {r = 0x00, g = 0x00, b = 0xff},
[SHIRT] = {r = 0x00, g = 0xff, b = 0x00},
[GLOVES] = {r = 0xff, g = 0xff, b = 0xff},
[SHOES] = {r = 0x72, g = 0x1c, b = 0x0e},
[HAIR] = {r = 0x73, g = 0x06, b = 0x00},
[SKIN] = {r = 0xfe, g = 0xc1, b = 0x79},
[CAP] = {r = 0x00, g = 0xff, b = 0x00},
[EMBLEM] = {r = 0x00, g = 0xff, b = 0x00},
},
[E_MODEL_TOAD_PLAYER] = {
[PANTS] = {r = 0xff, g = 0xff, b = 0xff},
[SHIRT] = {r = 0x4c, g = 0x2c, b = 0xd3},
[GLOVES] = {r = 0xff, g = 0xff, b = 0xff},
[SHOES] = {r = 0x68, g = 0x40, b = 0x1b},
[HAIR] = {r = 0x73, g = 0x06, b = 0x00},
[SKIN] = {r = 0xfe, g = 0xd5, b = 0xa1},
[CAP] = {r = 0xff, g = 0x00, b = 0x00},
[EMBLEM] = {r = 0xff, g = 0x00, b = 0x00},
},
[E_MODEL_WALUIGI] = {
[PANTS] = {r = 0x16, g = 0x16, b = 0x27},
[SHIRT] = {r = 0x61, g = 0x26, b = 0xb0},
[GLOVES] = {r = 0xff, g = 0xff, b = 0xff},
[SHOES] = {r = 0xfe, g = 0x76, b = 0x00},
[HAIR] = {r = 0x73, g = 0x53, b = 0x00},
[SKIN] = {r = 0xfe, g = 0xc1, b = 0x79},
[CAP] = {r = 0x61, g = 0x26, b = 0xb0},
[EMBLEM] = {r = 0x4c, g = 0x2c, b = 0xd3},
},
[E_MODEL_WARIO] = {
[PANTS] = {r = 0x7f, g = 0x20, b = 0x7a},
[SHIRT] = {r = 0xe3, g = 0xa9, b = 0x01},
[GLOVES] = {r = 0xff, g = 0xff, b = 0xff},
[SHOES] = {r = 0x0e, g = 0x72, b = 0x1c},
[HAIR] = {r = 0x73, g = 0x53, b = 0x00},
[SKIN] = {r = 0xfe, g = 0xc1, b = 0x79},
[CAP] = {r = 0xe3, g = 0xa9, b = 0x01},
[EMBLEM] = {r = 0x61, g = 0x26, b = 0xb0},
},
}
local defaultModels = {
[CT_MARIO] = E_MODEL_MARIO,
[CT_LUIGI] = E_MODEL_LUIGI,
[CT_TOAD] = E_MODEL_TOAD_PLAYER,
[CT_WALUIGI] = E_MODEL_WALUIGI,
[CT_WARIO] = E_MODEL_WARIO
}
local paletteLoop = #characterColorPresets[E_MODEL_MARIO]
local network_player_set_override_palette_color = network_player_set_override_palette_color
local function network_player_set_full_override_palette(networkPlayer, colorTable)
for i = 0, paletteLoop do
network_player_set_override_palette_color(networkPlayer, i, colorTable[i])
end
end
local prevChar = currChar
local stallTimer = 5
local prevPresetPalette = {}
local prevModel = {}
local function mario_update(m)
local np = gNetworkPlayers[m.playerIndex]
local p = gPlayerSyncTable[m.playerIndex]
if m.playerIndex == 0 and not p.isUpdating then
p.isUpdating = true
for i = 1, MAX_PLAYERS - 1 do
prevPresetPalette[i] = gPlayerSyncTable[i].presetPalette
prevModel[i] = gPlayerSyncTable[i].modelId and gPlayerSyncTable[i].modelId or defaultModels[gMarioStates[i].character.type]
end
end
if np.connected then
local modelId = p.modelId and p.modelId or defaultModels[m.character.type]
if p.presetPalette == nil or characterColorPresets[modelId] == nil then
if p.presetPalette == nil then
prevPresetPalette[m.playerIndex] = false
end
p.presetPalette = false
end
if (prevPresetPalette[m.playerIndex] ~= p.presetPalette or prevModel[m.playerIndex] ~= modelId) then
if not p.presetPalette or not characterColorPresets[modelId] then
network_player_reset_override_palette(np)
end
end
prevPresetPalette[m.playerIndex] = p.presetPalette
prevModel[m.playerIndex] = modelId
if p.presetPalette and characterColorPresets[modelId] and not stopPalettes then
network_player_set_full_override_palette(np, characterColorPresets[modelId])
end
else
if p.isUpdating then
p.isUpdating = false
end
end
if m.playerIndex == 0 then
if (menuAndTransition or prevChar ~= currChar) and stallTimer == 0 then
local modelId = p.modelId and p.modelId or defaultModels[m.character.type]
if optionTable[optionTableRef.autoPalette].toggle > 0 and optionTable[optionTableRef.localModels].toggle > 0 and (currChar ~= 1 and prevChar ~= currChar and not p.presetPalette) and characterColorPresets[modelId] and not stopPalettes then
p.presetPalette = true
end
if optionTable[optionTableRef.localModels].toggle == 0 then
p.presetPalette = false
end
prevChar = currChar
end
if stallTimer > 0 then
stallTimer = stallTimer - 1
end
end
end
hook_event(HOOK_MARIO_UPDATE, mario_update)

View file

@ -1,13 +1,11 @@
for i = 0, MAX_PLAYERS -1, 1 do
gPlayerSyncTable[i].customVoice = 0
end
local voicecount = 0
if incompatibleClient then return 0 end
local voiceTimeout = false
local SLEEP_TALK_SNORES = 8
gCustomVoiceSamples = {}
gCustomVoiceSamplesBackup = {}
gCustomVoiceStream = nil
-- localize functions to improve performance
@ -16,19 +14,8 @@ local audio_sample_stop,audio_sample_destroy,type,math_random,audio_stream_stop,
--- @param m MarioState
function stop_custom_character_sound(m, sound)
local voice_sample = gCustomVoiceSamples[m.playerIndex]
if voice_sample == false and gCustomVoiceSamplesBackup[m.playerIndex].loaded then
audio_sample_stop(gCustomVoiceSamplesBackup[m.playerIndex])
audio_sample_destroy(gCustomVoiceSamplesBackup[m.playerIndex])
voicecount = voicecount - 1
gCustomVoiceSamplesBackup[m.playerIndex] = nil
return
end
if voice_sample == nil or type(voice_sample) == "boolean" then
return
end
if not voice_sample.loaded then
gCustomVoiceSamplesBackup[m.playerIndex] = true
return
if voice_sample == nil or not voice_sample.loaded or voice_sample.isStream then
return nil
end
audio_sample_stop(voice_sample)
@ -36,14 +23,17 @@ function stop_custom_character_sound(m, sound)
return voice_sample
end
audio_sample_destroy(voice_sample)
voicecount = voicecount - 1
gCustomVoiceSamples[m.playerIndex] = nil -- prevent this from pointing to another sample or possibly garbage data
return nil
end
--- @param m MarioState
function play_custom_character_sound(m, voice)
if voiceTimeout then return 0 end
local sound
if type(voice) == "table" then
sound = voice[math.random(#voice)]
sound = voice[math_random(#voice)]
else
sound = voice
end
@ -66,23 +56,29 @@ function play_custom_character_sound(m, voice)
else
if voice_sample == nil then
voice_sample = audio_sample_load(sound)
while not voice_sample.loaded do end
voicecount = voicecount + 1
local lagTimer = 0
repeat
lagTimer = lagTimer + 1
if lagTimer > 500 then
voiceTimeout = true
if optionTable[optionTableRef.notification].toggle == 1 then
djui_chat_message_create("\\#FFAAAA\\Note: Custom Character Voices are unavalible due to\ninability to load audio, This is most likely because\nyour client does not support custom audio functionality.")
elseif optionTable[optionTableRef.notification].toggle == 2 then
djui_popup_create('Character Select:\nCustom Character Voices\nare unavalible due to\ninability to load audio!', 4)
end
break
end
until voice_sample.loaded
end
audio_sample_play(voice_sample, m.pos, 1)
if gCustomVoiceSamplesBackup[m.playerIndex] ~= nil and not(gCustomVoiceSamples[m.playerIndex] == false) then
gCustomVoiceSamplesBackup[m.playerIndex] = voice_sample
else
gCustomVoiceSamples[m.playerIndex] = voice_sample
end
gCustomVoiceSamples[m.playerIndex] = voice_sample
end
return 0
end
--- @param m MarioState
local function custom_character_sound(m, characterSound)
if is_game_paused() or optionTable[optionTableRef.localVoices].toggle == 0 then return end
if is_game_paused() or voiceTimeout or optionTable[optionTableRef.localVoices].toggle == 0 then return 0 end
if characterSound == CHAR_SOUND_SNORING3 then return 0 end
if characterSound == CHAR_SOUND_HAHA and m.hurtCounter > 0 then return 0 end
@ -99,16 +95,10 @@ local SLEEP_TALK_END = SLEEP_TALK_START + SLEEP_TALK_SNORES
--- @param m MarioState
local function custom_character_snore(m)
if is_game_paused() or optionTable[optionTableRef.localVoices].toggle == 0 then return end
if gCustomVoiceSamplesBackup[m.playerIndex] ~= nil and not (gCustomVoiceSamples[m.playerIndex] == false) then
if gCustomVoiceSamples[m.playerIndex].loaded then
audio_sample_destroy(gCustomVoiceSamples[m.playerIndex])
voicecount = voicecount - 1
gCustomVoiceSamples[m.playerIndex] = false
end
end
if is_game_paused() or voiceTimeout or optionTable[optionTableRef.localVoices].toggle == 0 then return end
local SNORE3_TABLE = _G.charSelect.character_get_voice(m)[CHAR_SOUND_SNORING3]
if m.action ~= ACT_SLEEPING then
if m.isSnoring > 0 then
stop_custom_character_sound(m)
@ -147,8 +137,24 @@ local function custom_character_snore(m)
end
end
function stop_all_character_sounds()
if gCustomVoiceStream then
audio_stream_stop(gCustomVoiceStream)
audio_stream_destroy(gCustomVoiceStream)
gCustomVoiceStream = nil
end
for i = 0, MAX_PLAYERS-1 do
stop_custom_character_sound(gMarioStates[i])
end
end
hook_event(HOOK_ON_WARP, stop_all_character_sounds)
hook_event(HOOK_UPDATE, function ()
if is_game_paused() then
stop_all_character_sounds()
end
end)
_G.charSelect.voice = {
sound = custom_character_sound,
snore = custom_character_snore,
}
gPlayerSyncTable[0].customVoice = true