2023-12-16 18:25:28 +00:00
-- name: Character Select
2024-02-20 21:52:50 +00:00
-- description:\\#ffff33\\--- Character Select Coop v1.6.1 ---\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
2023-12-16 18:25:28 +00:00
2023-12-23 16:40:20 +00:00
local menu = false
menuAndTransition = false
2023-12-16 18:25:28 +00:00
options = false
currChar = 1
local currOption = 1
2024-02-20 21:10:45 +00:00
local menuCrossFade = 7
2023-12-23 16:40:20 +00:00
local menuCrossFadeCap = menuCrossFade
local menuCrossFadeMath = 255 / menuCrossFade
2023-12-16 18:25:28 +00:00
local TEX_HEADER = get_texture_info ( " char-select-text " )
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
API to add characters , this ensures your pack is easy
to use for anyone and low on file space !
] ]
characterTable = {
[ 1 ] = {
name = " Default " ,
2024-02-20 21:10:45 +00:00
saveName = " Default " ,
2023-12-16 18:25:28 +00:00
description = { " The vanilla cast for sm64ex-coop! " , " " , " These Characters are swappable " , " via the default Options Menu " } ,
credit = " Nintendo / Coop Team " ,
color = { r = 255 , g = 50 , b = 50 } ,
model = nil ,
forceChar = nil ,
lifeIcon = gTextures.mario_head ,
2024-02-20 21:10:45 +00:00
camScale = 1.0
2023-12-16 18:25:28 +00:00
} ,
}
2024-02-20 21:10:45 +00:00
characterCaps = { }
optionTableRef = {
2023-12-16 18:25:28 +00:00
openInputs = 1 ,
2024-02-20 21:10:45 +00:00
notification = 2 ,
menuColor = 3 ,
anims = 4 ,
inputLatency = 5 ,
localModels = 6 ,
localVoices = 7 ,
debugInfo = 8 ,
resetSaveData = 9 ,
2023-12-16 18:25:28 +00:00
}
optionTable = {
[ optionTableRef.openInputs ] = {
name = " Open Binds " ,
toggle = tonumber ( mod_storage_load ( " MenuInput " ) ) ,
toggleSaveName = " MenuInput " ,
toggleDefault = 0 ,
toggleMax = 2 ,
toggleNames = { " None " , ommActive and " D-pad Down + R " or " D-pad Down " , " Z (Pause Menu) " } ,
2024-02-20 21:10:45 +00:00
description = { " Sets a Bind to Open the Menu " , " rather than using the command. " }
} ,
[ optionTableRef.notification ] = {
name = " Notifications " ,
toggle = tonumber ( mod_storage_load ( " notifs " ) ) ,
toggleSaveName = " notifs " ,
toggleDefault = 1 ,
toggleMax = 2 ,
toggleNames = { " Off " , " On " , " Pop-ups Only " } ,
description = { " Toggles wheather Pop-ups and " , " Chat Messages display " }
2023-12-16 18:25:28 +00:00
} ,
[ optionTableRef.menuColor ] = {
name = " Menu Color " ,
toggle = tonumber ( mod_storage_load ( " MenuColor " ) ) ,
toggleSaveName = " MenuColor " ,
toggleDefault = 0 ,
2024-02-20 21:10:45 +00:00
toggleMax = 10 ,
toggleNames = { " Auto " , " Saved " , " Red " , " Orange " , " Yellow " , " Green " , " Blue " , " Pink " , " Purple " , " White " , " Black " } ,
description = { " Toggles the Menu Color " }
2023-12-16 18:25:28 +00:00
} ,
[ optionTableRef.anims ] = {
name = " Animations " ,
toggle = tonumber ( mod_storage_load ( " Anims " ) ) ,
toggleSaveName = " Anims " ,
toggleDefault = 1 ,
toggleMax = 1 ,
2024-02-20 21:10:45 +00:00
description = { " Toggles Animations In-Menu, " , " Turning these off may " , " Save Performance " }
2023-12-16 18:25:28 +00:00
} ,
[ optionTableRef.inputLatency ] = {
name = " Scroll Speed " ,
toggle = tonumber ( mod_storage_load ( " Latency " ) ) ,
toggleSaveName = " Latency " ,
toggleDefault = 1 ,
toggleMax = 2 ,
toggleNames = { " Slow " , " Normal " , " Fast " } ,
2024-02-20 21:10:45 +00:00
description = { " Sets how fast you scroll " , " throughout the Menu " }
2023-12-16 18:25:28 +00:00
} ,
[ optionTableRef.localModels ] = {
name = " Locally Display Models " ,
toggle = tonumber ( mod_storage_load ( " localModels " ) ) ,
toggleSaveName = " localModels " ,
toggleDefault = 1 ,
toggleMax = 1 ,
2024-02-20 21:10:45 +00:00
description = { " Toggles if Custom Models display " , " on your client, practically " , " disables Character Select if " , " Toggled Off " }
2023-12-16 18:25:28 +00:00
} ,
2024-02-20 21:10:45 +00:00
[ optionTableRef.localVoices ] = {
name = " Custom Voices " ,
toggle = tonumber ( mod_storage_load ( " localVoices " ) ) ,
toggleSaveName = " localVoices " ,
toggleDefault = 1 ,
2023-12-16 18:25:28 +00:00
toggleMax = 1 ,
2024-02-20 21:10:45 +00:00
description = { " Toggle if Custom Voicelines play " , " for Characters who support it " }
2023-12-16 18:25:28 +00:00
} ,
2023-12-18 22:01:33 +00:00
[ optionTableRef.debugInfo ] = {
name = " Debugging Info " ,
toggle = tonumber ( mod_storage_load ( " debuginfo " ) ) ,
toggleSaveName = " debuginfo " ,
toggleDefault = 0 ,
toggleMax = 1 ,
2024-02-20 21:10:45 +00:00
description = { " Replaces the Character " , " Description with Character " , " Debugging Information " }
} ,
[ optionTableRef.resetSaveData ] = {
name = " Reset Save Data " ,
toggle = 0 ,
toggleDefault = 0 ,
toggleMax = 1 ,
toggleNames = { " " , " " } ,
description = { " Resets Character Select's " , " Save Data " }
2023-12-18 22:01:33 +00:00
} ,
2023-12-16 18:25:28 +00:00
}
2024-02-20 21:10:45 +00:00
local optionTableCount = # optionTable
2023-12-16 18:25:28 +00:00
2024-02-20 21:10:45 +00:00
local latencyValueTable = { 12 , 6 , 3 }
2023-12-16 18:25:28 +00:00
2023-12-23 16:40:20 +00:00
local menuColorTable = {
{ r = 255 , g = 50 , b = 50 } ,
{ r = 255 , g = 100 , b = 50 } ,
{ r = 255 , g = 255 , b = 50 } ,
{ r = 50 , g = 255 , b = 50 } ,
2024-02-20 21:10:45 +00:00
{ r = 50 , g = 50 , b = 255 } ,
2023-12-23 16:40:20 +00:00
{ r = 251 , g = 148 , b = 220 } ,
{ r = 130 , g = 25 , b = 130 } ,
{ r = 255 , g = 255 , b = 255 } ,
{ r = 50 , g = 50 , b = 50 } ,
}
2024-02-20 21:10:45 +00:00
-- Default Player Adjustments
local defaultNames = {
[ CT_MARIO ] = " Mario " ,
[ CT_LUIGI ] = " Luigi " ,
[ CT_TOAD ] = " Toad " ,
[ CT_WALUIGI ] = " Waluigi " ,
[ CT_WARIO ] = " Wario " ,
}
local defaultPlayerColors = {
[ CT_MARIO ] = menuColorTable [ 1 ] ,
[ CT_LUIGI ] = menuColorTable [ 4 ] ,
[ CT_TOAD ] = menuColorTable [ 5 ] ,
[ CT_WALUIGI ] = menuColorTable [ 7 ] ,
[ CT_WARIO ] = menuColorTable [ 3 ] ,
}
local defaultForceChar = {
[ CT_MARIO ] = " CT_MARIO " ,
[ CT_LUIGI ] = " CT_LUIGI " ,
[ CT_TOAD ] = " CT_TOAD " ,
[ CT_WALUIGI ] = " CT_WALUIGI " ,
[ CT_WARIO ] = " CT_WARIO " ,
}
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 defaultCamScales = {
[ CT_MARIO ] = 1 ,
[ CT_LUIGI ] = 1 ,
[ CT_TOAD ] = 0.8 ,
[ CT_WALUIGI ] = 1.1 ,
[ CT_WARIO ] = 1 ,
}
-- "localize functions to improve performance" 🔥🔥🔥
local camera_freeze , camera_unfreeze , network_local_index_from_global , obj_set_model_extended , hud_hide , hud_show , djui_chat_message_create ,
djui_hud_set_resolution , djui_hud_set_font , djui_hud_set_color , djui_hud_get_screen_width , djui_hud_render_rect , djui_hud_print_text ,
djui_hud_render_texture , math_max , math_min , math_sin , math_random , math_abs , math_ceil , play_sound , mod_storage_save , mod_storage_load , string_lower =
camera_freeze , camera_unfreeze , network_local_index_from_global , obj_set_model_extended , hud_hide , hud_show , djui_chat_message_create ,
djui_hud_set_resolution , djui_hud_set_font , djui_hud_set_color , djui_hud_get_screen_width , djui_hud_render_rect , djui_hud_print_text ,
djui_hud_render_texture , math.max , math.min , math.sin , math.random , math.abs , math.ceil , play_sound , mod_storage_save , mod_storage_load , string.lower
2023-12-16 18:25:28 +00:00
---@param m MarioState
local function nullify_inputs ( m )
local c = m.controller
_G.charSelect . controller = {
buttonDown = c.buttonDown ,
buttonPressed = c.buttonPressed & ~ _G.charSelect . controller.buttonDown ,
extStickX = c.extStickX ,
extStickY = c.extStickY ,
rawStickX = c.rawStickX ,
rawStickY = c.rawStickY ,
stickMag = c.stickMag ,
stickX = c.stickX ,
stickY = c.stickY
}
c.buttonDown = 0
c.buttonPressed = 0
c.extStickX = 0
c.extStickY = 0
c.rawStickX = 0
c.rawStickY = 0
c.stickMag = 0
c.stickX = 0
c.stickY = 0
end
2024-02-20 21:10:45 +00:00
local prefCharColor = defaultPlayerColors [ CT_MARIO ]
2023-12-16 18:25:28 +00:00
local function load_preferred_char ( )
2024-02-20 21:10:45 +00:00
local savedChar = mod_storage_load ( " PrefChar " )
if savedChar ~= nil and savedChar ~= " Default " then
2023-12-16 18:25:28 +00:00
for i = 2 , # characterTable do
2024-02-20 21:10:45 +00:00
if characterTable [ i ] . saveName == savedChar then
2023-12-16 18:25:28 +00:00
currChar = i
2023-12-18 22:01:33 +00:00
if optionTable [ optionTableRef.localModels ] . toggle == 1 then
2024-02-20 21:10:45 +00:00
if optionTable [ optionTableRef.notification ] . toggle > 0 then
djui_popup_create ( ' Character Select: \n Your Preferred Character \n " ' .. string_underscore_to_space ( characterTable [ i ] . name ) .. ' " \n was applied successfully! ' , 4 )
end
2023-12-18 22:01:33 +00:00
end
2023-12-16 18:25:28 +00:00
break
end
end
2024-02-20 21:10:45 +00:00
elseif savedChar == nil then
2023-12-16 18:25:28 +00:00
mod_storage_save ( " PrefChar " , " Default " )
2024-02-20 21:10:45 +00:00
savedChar = " Default "
end
local savedCharColors = mod_storage_load ( " PrefCharColor " )
if savedCharColors ~= nil and savedCharColors ~= " " then
local savedCharColorsTable = string_split ( string_underscore_to_space ( savedCharColors ) )
prefCharColor = {
r = tonumber ( savedCharColorsTable [ 1 ] ) ,
g = tonumber ( savedCharColorsTable [ 2 ] ) ,
b = tonumber ( savedCharColorsTable [ 3 ] )
}
else
mod_storage_save ( " PrefCharColor " , " 255_50_50 " )
2023-12-16 18:25:28 +00:00
end
2024-02-20 21:10:45 +00:00
2023-12-16 18:25:28 +00:00
if # characterTable == 1 then
2024-02-20 21:10:45 +00:00
if optionTable [ optionTableRef.notification ] . toggle > 0 then
djui_popup_create ( " Character Select: \n No Characters were Found " , 2 )
end
2023-12-16 18:25:28 +00:00
end
2024-02-20 21:10:45 +00:00
TEXT_PREF_LOAD = savedChar
end
local function mod_storage_save_pref_char ( charTable )
mod_storage_save ( " PrefChar " , charTable.saveName )
mod_storage_save ( " PrefCharColor " , tostring ( charTable.color . r ) .. " _ " .. tostring ( charTable.color . g ) .. " _ " .. tostring ( charTable.color . b ) )
TEXT_PREF_LOAD = charTable.saveName
prefCharColor = charTable.color
2023-12-16 18:25:28 +00:00
end
local function failsafe_options ( )
for i = 1 , # optionTable do
2024-02-20 21:10:45 +00:00
if optionTable [ i ] . toggle == nil or optionTable [ i ] . toggle == " " then
2023-12-16 18:25:28 +00:00
optionTable [ i ] . toggle = optionTable [ i ] . toggleDefault
if optionTable [ i ] . toggleSaveName ~= nil then
mod_storage_save ( optionTable [ i ] . toggleSaveName , tostring ( optionTable [ i ] . toggle ) )
end
end
if optionTable [ i ] . toggleNames == nil then
optionTable [ i ] . toggleNames = { " Off " , " On " }
end
end
2024-02-20 21:10:45 +00:00
if optionTable [ optionTableRef.openInputs ] . toggle > 0 and ommActive then
2023-12-16 18:25:28 +00:00
djui_popup_create ( ' Character Select: \n Your Open bind has changed to: \n D-pad Down + R \n Due to OMM Rebirth being active! ' , 4 )
end
end
2024-02-20 21:10:45 +00:00
local promptedAreYouSure = false
local function reset_options ( wasChatTriggered )
if not promptedAreYouSure then
djui_chat_message_create ( " \\ #ffdcdc \\ Are you sure you want to reset your Save Data for Character Select, including your Preferred Character \n and Settings? \n " .. ( wasChatTriggered and " Type \\ #ff3333 \\ /char-select reset \\ #ffdcdc \\ to confirm. " or " Press the \\ #ff3333 \\ " .. optionTable [ optionTableRef.resetSaveData ] . name .. " \\ #ffdcdc \\ Option again to confirm. " ) )
promptedAreYouSure = true
else
djui_chat_message_create ( " \\ #ff3333 \\ Character Select Save Data Reset! " )
djui_chat_message_create ( " Note: If your issue has not been resolved, you may need to manually delete your save data via the directory below: \n \\ #dcdcFF \\ sm64ex-coop/sav/character-select-coop.sav " )
for i = 1 , # optionTable do
optionTable [ i ] . toggle = optionTable [ i ] . toggleDefault
if optionTable [ i ] . toggleSaveName ~= nil then
mod_storage_save ( optionTable [ i ] . toggleSaveName , tostring ( optionTable [ i ] . toggle ) )
end
if optionTable [ i ] . toggleNames == nil then
optionTable [ i ] . toggleNames = { " Off " , " On " }
end
end
mod_storage_save_pref_char ( characterTable [ 1 ] )
promptedAreYouSure = false
end
end
local function boot_note ( )
2023-12-23 16:40:20 +00:00
if # characterTable > 1 then
2024-02-20 21:10:45 +00:00
djui_chat_message_create ( " Character Select has " .. ( # characterTable - 1 ) .. " character " .. ( # characterTable > 2 and " s " or " " ) .. " available! \n You can use \\ #ffff33 \\ /char-select \\ #ffffff \\ to open the menu! " )
2023-12-16 18:25:28 +00:00
else
2024-02-20 21:10:45 +00:00
djui_chat_message_create ( " Character Select is active! \n You can use \\ #ffff33 \\ /char-select \\ #ffffff \\ to open the menu! " )
end
if not client_is_coop_dx then
djui_chat_message_create ( " \\ #FFAAAA \\ Note: Although not required, we highly reccomend \n using SM64CoopDX when playing Character Select! \n \\ #6666FF \\ https://sm64coopdx.com " )
2023-12-16 18:25:28 +00:00
end
end
-------------------
-- Model Handler --
-------------------
local stallFrame = 0
local noLoop = false
2024-02-20 21:10:45 +00:00
local CUTSCENE_CS_MENU = 0xFA
2023-12-16 18:25:28 +00:00
-- Respecfully, GO FUCK YOURSELVES. I hate EVERY SINGLE ONE OF YOU. Your lives are NOTHING. You serve ZERO PURPOSE. You should kill yourselves, NOW!
local ignored_surfaces = {
SURFACE_BURNING , SURFACE_QUICKSAND , SURFACE_INSTANT_QUICKSAND , SURFACE_INSTANT_MOVING_QUICKSAND , SURFACE_DEEP_MOVING_QUICKSAND , SURFACE_INSTANT_QUICKSAND , SURFACE_DEEP_QUICKSAND , SURFACE_SHALLOW_MOVING_QUICKSAND ,
SURFACE_SHALLOW_QUICKSAND , SURFACE_WARP , SURFACE_LOOK_UP_WARP , SURFACE_WOBBLING_WARP , SURFACE_INSTANT_WARP_1B , SURFACE_INSTANT_WARP_1C , SURFACE_INSTANT_WARP_1D , SURFACE_INSTANT_WARP_1E
}
-- Yes, floral gave me permission to use this table full of USELESS PIECES OF SHITS
2024-02-20 21:10:45 +00:00
local menuActBlacklist = {
-- Star Acts
[ ACT_FALL_AFTER_STAR_GRAB ] = true ,
[ ACT_STAR_DANCE_EXIT ] = true ,
[ ACT_STAR_DANCE_NO_EXIT ] = true ,
[ ACT_STAR_DANCE_WATER ] = true ,
-- Key Acts
[ ACT_UNLOCKING_KEY_DOOR ] = true ,
[ ACT_UNLOCKING_STAR_DOOR ] = true ,
-- Cutscene Acts
[ ACT_INTRO_CUTSCENE ] = true ,
[ ACT_CREDITS_CUTSCENE ] = true ,
-- Dialog Acts
[ ACT_READING_NPC_DIALOG ] = true ,
[ ACT_WAITING_FOR_DIALOG ] = true ,
[ ACT_EXIT_LAND_SAVE_DIALOG ] = true ,
[ ACT_READING_AUTOMATIC_DIALOG ] = true ,
}
local faceAngle = 0
2023-12-16 18:25:28 +00:00
--- @param m MarioState
local function mario_update ( m )
if stallFrame == 1 then
failsafe_options ( )
2024-02-20 21:10:45 +00:00
load_preferred_char ( )
if optionTable [ optionTableRef.notification ] . toggle == 1 then
boot_note ( )
end
2023-12-16 18:25:28 +00:00
end
if stallFrame < 2 then
stallFrame = stallFrame + 1
end
if m.playerIndex == 0 and stallFrame > 1 then
2023-12-19 00:17:19 +00:00
local modelIndex = gNetworkPlayers [ m.playerIndex ] . modelIndex
characterTable [ 1 ] . forceChar = modelIndex
2024-02-20 21:10:45 +00:00
characterTable [ 1 ] . name = defaultNames [ modelIndex ]
2023-12-16 18:25:28 +00:00
if currChar == 1 then
2023-12-19 00:17:19 +00:00
characterTable [ 1 ] . color = defaultPlayerColors [ modelIndex ]
characterTable [ 1 ] . lifeIcon = defaultIcons [ modelIndex ]
2024-02-20 21:10:45 +00:00
characterTable [ 1 ] . camScale = defaultCamScales [ modelIndex ]
2023-12-16 18:25:28 +00:00
end
if optionTable [ optionTableRef.localModels ] . toggle > 0 then
2023-12-19 00:17:19 +00:00
gPlayerSyncTable [ m.playerIndex ] . modelId = characterTable [ currChar ] . model
2023-12-16 18:25:28 +00:00
if characterTable [ currChar ] . forceChar ~= nil then
gNetworkPlayers [ m.playerIndex ] . overrideModelIndex = characterTable [ currChar ] . forceChar
end
else
2023-12-19 00:17:19 +00:00
gPlayerSyncTable [ m.playerIndex ] . modelId = nil
2023-12-16 18:25:28 +00:00
gNetworkPlayers [ m.playerIndex ] . overrideModelIndex = characterTable [ 1 ] . forceChar
end
2023-12-23 16:40:20 +00:00
if menuAndTransition then
2023-12-16 18:25:28 +00:00
for _ , func in pairs ( allowMenu ) do
if not func ( ) then
menu = false
return
end
end
camera_freeze ( )
hud_hide ( )
if _G.PersonalStarCounter then
_G.PersonalStarCounter . hide_star_counters ( true )
end
2024-02-20 21:10:45 +00:00
if m.area . camera.cutscene == 0 then
m.area . camera.cutscene = CUTSCENE_CS_MENU
end
local camScale = characterTable [ currChar ] . camScale
2023-12-16 18:25:28 +00:00
local focusPos = {
x = m.pos . x ,
2024-02-20 21:10:45 +00:00
y = m.pos . y + 120 * camScale ,
2023-12-16 18:25:28 +00:00
z = m.pos . z ,
}
vec3f_copy ( gLakituState.focus , focusPos )
2024-02-20 21:10:45 +00:00
gLakituState.pos . x = m.pos . x + sins ( faceAngle ) * 500 * camScale
gLakituState.pos . y = m.pos . y + 100 * camScale
gLakituState.pos . z = m.pos . z + coss ( faceAngle ) * 500 * camScale
2023-12-16 18:25:28 +00:00
2024-02-20 21:10:45 +00:00
if m.forwardVel == 0 and m.pos . y == m.floorHeight and not ignored_surfaces [ m.floor . type ] and m.health > 255 and not menuActBlacklist [ m.action ] then
2023-12-16 18:25:28 +00:00
set_mario_action ( m , ACT_IDLE , 0 )
2024-02-20 21:10:45 +00:00
set_mario_animation ( m , MARIO_ANIM_FIRST_PERSON )
2023-12-16 18:25:28 +00:00
end
noLoop = false
elseif not noLoop then
camera_unfreeze ( )
hud_show ( )
if _G.PersonalStarCounter then
_G.PersonalStarCounter . hide_star_counters ( false )
end
2024-02-20 21:10:45 +00:00
if m.area . camera.cutscene == CUTSCENE_CS_MENU then
m.area . camera.cutscene = CUTSCENE_STOP
end
2023-12-16 18:25:28 +00:00
noLoop = true
end
end
2024-02-20 21:10:45 +00:00
--Reset Save Data Check
if optionTable [ optionTableRef.resetSaveData ] . toggle > 0 then
reset_options ( false )
optionTable [ optionTableRef.resetSaveData ] . toggle = 0
2023-12-16 18:25:28 +00:00
end
end
function set_model ( o , model )
2024-02-20 21:10:45 +00:00
local i = network_local_index_from_global ( o.globalPlayerIndex )
2023-12-16 18:25:28 +00:00
if obj_has_behavior_id ( o , id_bhvMario ) ~= 0 then
if gPlayerSyncTable [ i ] . modelId ~= nil and obj_has_model_extended ( o , gPlayerSyncTable [ i ] . modelId ) == 0 then
obj_set_model_extended ( o , gPlayerSyncTable [ i ] . modelId )
2024-02-20 21:10:45 +00:00
return end
2023-12-16 18:25:28 +00:00
end
2024-02-20 21:10:45 +00:00
local c = gMarioStates [ i ] . character
if model == c.capModelId or
model == c.capWingModelId or
model == c.capMetalModelId or
model == c.capMetalWingModelId then
local capModels = characterCaps [ gPlayerSyncTable [ i ] . modelId ]
2023-12-16 18:25:28 +00:00
local capModel = nil
if capModels ~= nil then
2024-02-20 21:10:45 +00:00
if model == c.capModelId then
2023-12-16 18:25:28 +00:00
capModel = capModels.normal
2024-02-20 21:10:45 +00:00
elseif model == c.capWingModelId then
2023-12-16 18:25:28 +00:00
capModel = capModels.wing
2024-02-20 21:10:45 +00:00
elseif model == c.capMetalModelId then
2023-12-16 18:25:28 +00:00
capModel = capModels.metal
2024-02-20 21:10:45 +00:00
elseif model == c.capMetalWingModelId then
2023-12-16 18:25:28 +00:00
capModel = capModels.metalWing
end
if capModel ~= nil and obj_has_model_extended ( o , capModel ) == 0 then
obj_set_model_extended ( o , capModel )
2024-02-20 21:10:45 +00:00
return end
2023-12-16 18:25:28 +00:00
end
end
end
hook_event ( HOOK_MARIO_UPDATE , mario_update )
hook_event ( HOOK_OBJECT_SET_MODEL , set_model )
------------------
-- Menu Handler --
------------------
local buttonAnimTimer = 0
local buttonScroll = 0
local buttonScrollCap = 30
local optionAnimTimer = - 200
local optionAnimTimerCap = optionAnimTimer
2024-02-20 21:10:45 +00:00
local inputStallTimerButton = 0
local inputStallTimerDirectional = 0
local inputStallToDirectional = 12
local inputStallToButton = 10
2023-12-16 18:25:28 +00:00
2024-02-20 21:10:45 +00:00
-- Font Consistency between sm64ex-coop and sm64coopdx
local FONT_CS_NORMAL = client_is_coop_dx and FONT_ALIASED or FONT_NORMAL
2023-12-18 22:01:33 +00:00
2023-12-23 16:40:20 +00:00
--Basic Menu Text
2023-12-16 18:25:28 +00:00
local TEXT_OPTIONS_HEADER = " Menu Options "
2024-02-20 21:10:45 +00:00
local TEXT_VERSION = " Version: " .. modVersion .. ( client_is_coop_dx and " | sm64coopdx " or " | sm64ex-coop " )
2023-12-16 18:25:28 +00:00
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_PAUSE_Z_OPEN = " Z Button - Character Select "
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
TEXT_PAUSE_CURR_CHAR = " Model: "
end
2023-12-23 16:40:20 +00:00
--Debug Text
local TEXT_DEBUGGING = " Character Debug "
local TEXT_DESCRIPTION_SHORT = " Description: "
local TEXT_LIFE_ICON = " Life Icon: "
local TEXT_FORCED_CHAR = " Forced: "
local TEXT_TABLE_POS = " Table Position: "
--Options Text
2023-12-16 18:25:28 +00:00
local TEXT_OPTIONS_OPEN = " Press START to open Options "
local TEXT_MENU_CLOSE = " Press B to Exit Menu "
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
2024-02-20 21:10:45 +00:00
local MATH_DIVIDE_THREE_HUNDRED_TWENTY = 1 / 320
2023-12-16 18:25:28 +00:00
local function on_hud_render ( )
djui_hud_set_resolution ( RESOLUTION_N64 )
2023-12-18 22:01:33 +00:00
djui_hud_set_font ( FONT_CS_NORMAL )
2023-12-16 18:25:28 +00:00
local width = djui_hud_get_screen_width ( ) + 1.4
local height = 240
local widthHalf = width * 0.5
local heightHalf = height * 0.5
2024-02-20 21:10:45 +00:00
local widthScale = math_max ( width , 321.4 ) * MATH_DIVIDE_THREE_HUNDRED_TWENTY
2023-12-16 18:25:28 +00:00
2023-12-23 16:40:20 +00:00
if menuAndTransition then
2024-02-20 21:10:45 +00:00
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
2023-12-16 18:25:28 +00:00
else
menuColor = characterTable [ currChar ] . color
end
if optionTable [ optionTableRef.localModels ] . toggle == 0 then
djui_hud_set_color ( 0 , 0 , 0 , 200 )
djui_hud_render_rect ( 0 , 0 , width , height )
djui_hud_set_color ( 255 , 255 , 255 , 255 )
djui_hud_print_text ( TEXT_LOCAL_MODEL_OFF , widthHalf - djui_hud_measure_text ( TEXT_LOCAL_MODEL_OFF ) * 0.15 * widthScale , heightHalf , 0.3 * widthScale )
djui_hud_print_text ( TEXT_LOCAL_MODEL_OFF_OPTIONS , widthHalf - djui_hud_measure_text ( TEXT_LOCAL_MODEL_OFF_OPTIONS ) * 0.1 * widthScale , heightHalf + 10 * widthScale , 0.2 * widthScale )
end
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 )
djui_hud_set_color ( 0 , 0 , 0 , 255 )
djui_hud_render_rect ( width - x + 2 , 2 , x - 4 , height - 4 )
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
2023-12-18 22:01:33 +00:00
djui_hud_set_font ( FONT_CS_NORMAL )
2023-12-23 16:40:20 +00:00
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
2024-02-20 21:10:45 +00:00
local TEXT_PREF = " Preferred Character: "
if djui_hud_measure_text ( string_underscore_to_space ( TEXT_PREF_LOAD ) ) / widthScale > 110 then
TEXT_PREF = " Preferred Char: "
end
if djui_hud_measure_text ( string_underscore_to_space ( TEXT_PREF_LOAD ) ) / widthScale > 164 then
TEXT_PREF = " Pref Char: "
end
TEXT_PREF = TEXT_PREF .. ' " ' .. string_underscore_to_space ( TEXT_PREF_LOAD ) .. ' " '
2023-12-16 18:25:28 +00:00
2023-12-18 22:01:33 +00:00
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 )
2024-02-20 21:10:45 +00:00
djui_hud_print_text ( TEXT_CREDIT , width - textX - djui_hud_measure_text ( TEXT_CREDIT ) * 0.3 , 74 , 0.6 )
2023-12-18 22:01:33 +00:00
djui_hud_set_font ( FONT_CS_NORMAL )
djui_hud_print_text ( TEXT_DESCRIPTION , width - textX - djui_hud_measure_text ( TEXT_DESCRIPTION ) * 0.2 , 85 , 0.4 )
2023-12-23 16:40:20 +00:00
if widthScale < 1.65 then
for i = 1 , # TEXT_DESCRIPTION_TABLE do
djui_hud_print_text ( TEXT_DESCRIPTION_TABLE [ i ] , width - textX - djui_hud_measure_text ( TEXT_DESCRIPTION_TABLE [ i ] ) * 0.15 , 90 + i * 9 , 0.3 )
end
else
for i = 1 , math_ceil ( # TEXT_DESCRIPTION_TABLE * 0.5 ) do
local TablePos = ( i * 2 ) - 1
if TEXT_DESCRIPTION_TABLE [ TablePos ] and TEXT_DESCRIPTION_TABLE [ TablePos + 1 ] then
local TEXT_STRING = TEXT_DESCRIPTION_TABLE [ TablePos ] .. " " .. TEXT_DESCRIPTION_TABLE [ TablePos + 1 ]
djui_hud_print_text ( TEXT_STRING , width - textX - djui_hud_measure_text ( TEXT_STRING ) * 0.15 , 90 + i * 9 , 0.3 )
elseif TEXT_DESCRIPTION_TABLE [ TablePos ] then
local TEXT_STRING = TEXT_DESCRIPTION_TABLE [ TablePos ]
djui_hud_print_text ( TEXT_STRING , width - textX - djui_hud_measure_text ( TEXT_STRING ) * 0.15 , 90 + i * 9 , 0.3 )
end
end
2023-12-18 22:01:33 +00:00
end
2023-12-23 16:40:20 +00:00
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 )
else -- Debugging Info
local TEXT_NAME = " Name: " .. character.name
2024-02-20 21:10:45 +00:00
local TEXT_SAVE_NAME = " Save Name: " .. character.saveName
2023-12-23 16:40:20 +00:00
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
2024-02-20 21:10:45 +00:00
local TEXT_ICON_DEFAULT = " ? "
local TEXT_SCALE = " Camera Scale: " .. character.camScale
2023-12-23 16:40:20 +00:00
local TEXT_PREF = " Preferred: " .. TEXT_PREF_LOAD
2024-02-20 21:10:45 +00:00
local TEXT_PREF_COLOR = " Pref Color: R- " .. prefCharColor.r .. " , G- " .. prefCharColor.g .. " , B- " .. prefCharColor.b
2023-12-18 22:01:33 +00:00
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 )
2024-02-20 21:10:45 +00:00
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 )
2023-12-23 16:40:20 +00:00
local removeLine = 0
2023-12-18 22:01:33 +00:00
for i = 1 , # TEXT_DESCRIPTION_TABLE do
2023-12-23 16:40:20 +00:00
if TEXT_DESCRIPTION_TABLE [ i ] ~= " " then
2024-02-20 21:10:45 +00:00
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
else
TEXT_DESCRIPTION_LINE = " " .. TEXT_DESCRIPTION_LINE
end
djui_hud_set_font ( FONT_TINY )
djui_hud_print_text ( TEXT_DESCRIPTION_LINE , width - x + 5 , 101 + ( i - removeLine ) * 7 , 0.5 )
2023-12-23 16:40:20 +00:00
else
removeLine = removeLine + 1
end
2023-12-18 22:01:33 +00:00
end
2023-12-23 16:40:20 +00:00
local descriptionOffset = ( # TEXT_DESCRIPTION_TABLE - removeLine ) * 7
2024-02-20 21:10:45 +00:00
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 ( 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 ) )
else
djui_hud_print_text ( TEXT_LIFE_ICON .. " (?x?) " , width - x + 8 , 118 + descriptionOffset , 0.6 )
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_set_font ( FONT_TINY )
end
2023-12-23 16:40:20 +00:00
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
2024-02-20 21:10:45 +00:00
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_PREF , width - x + 8 , height - 27 , 0.6 )
djui_hud_print_text ( TEXT_PREF_COLOR , width - x + 8 , height - 18 , 0.6 )
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 )
if optionTable [ optionTableRef.anims ] . toggle > 0 then
buttonAnimTimer = buttonAnimTimer + 1
end
if optionTable [ optionTableRef.anims ] . toggle == 0 then
buttonScroll = 0
elseif math_abs ( buttonScroll ) > 0.1 then
buttonScroll = buttonScroll * 0.03 * inputStallToDirectional
end
local buttonColor = { }
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
if i == 0 then
if optionTable [ optionTableRef.anims ] . toggle > 0 then
buttonX = buttonX + math_sin ( buttonAnimTimer * 0.05 ) * 2.5 + 5
else
buttonX = 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_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 )
end
2023-12-16 18:25:28 +00:00
end
2024-02-20 21:10:45 +00:00
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
djui_hud_render_rect ( 0 , height - 2 , x , 2 )
-- Scroll Bar
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_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 )
2023-12-16 18:25:28 +00:00
--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_set_color ( menuColor.r * 0.5 + 127 , menuColor.g * 0.5 + 127 , menuColor.b * 0.5 + 127 , 255 )
djui_hud_render_texture ( TEX_HEADER , widthHalf - 128 , 10 , 1 , 1 )
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
djui_hud_set_font ( FONT_TINY )
2023-12-18 22:01:33 +00:00
djui_hud_print_text ( TEXT_VERSION , 5 , 3 , 0.5 )
2023-12-16 18:25:28 +00:00
--Unsupported Res Warning
if width < 321.2 or width > 575 then
djui_hud_print_text ( TEXT_RATIO_UNSUPPORTED , 5 , 39 , 0.5 )
end
--Options display
if options or optionAnimTimer > optionAnimTimerCap then
djui_hud_set_color ( menuColor.r * 0.25 , menuColor.g * 0.25 , menuColor.b * 0.25 , 205 + math_max ( - 200 , optionAnimTimer ) )
djui_hud_render_rect ( 0 , 0 , width , height )
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
djui_hud_render_rect ( width * 0.5 - 50 * widthScale , math.min ( 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 , math.min ( 55 - optionAnimTimer + 2 , height - 25 * widthScale + 2 ) , 100 * widthScale - 4 , 196 )
2023-12-18 22:01:33 +00:00
djui_hud_set_font ( FONT_CS_NORMAL )
2023-12-16 18:25:28 +00:00
djui_hud_set_color ( menuColor.r * 0.5 + 127 , menuColor.g * 0.5 + 127 , menuColor.b * 0.5 + 127 , 255 )
2023-12-23 16:40:20 +00:00
djui_hud_print_text ( TEXT_OPTIONS_HEADER , widthHalf - djui_hud_measure_text ( TEXT_OPTIONS_HEADER ) * 0.3 * math_min ( widthScale , 1.5 ) , 65 + optionAnimTimer * - 1 , 0.6 * math_min ( widthScale , 1.5 ) )
2023-12-16 18:25:28 +00:00
2024-02-20 21:10:45 +00:00
local widthScaleLimited = math_min ( widthScale , 1.5 )
-- Up Arrow
if currOption > 3 then
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
djui_hud_set_rotation ( 0x2000 , 0.5 , 0.5 )
djui_hud_render_rect ( widthHalf - 3 * widthScaleLimited , 95 - optionAnimTimer , 5 * widthScaleLimited , 5 * widthScaleLimited )
djui_hud_set_color ( 0 , 0 , 0 , 255 )
djui_hud_set_rotation ( 0x0000 , 0.5 , 0.5 )
djui_hud_render_rect ( widthHalf - 4 * widthScaleLimited , 95 - optionAnimTimer + 2 * widthScaleLimited , 8 * widthScaleLimited , 10 )
end
-- Down Arrow
if currOption < optionTableCount - 2 then
local yOffset = 90 - optionAnimTimer + 45 * widthScaleLimited
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
djui_hud_set_rotation ( 0x2000 , 0.5 , 0.5 )
djui_hud_render_rect ( widthHalf - 3 * widthScaleLimited , yOffset + 10 , 5 * widthScaleLimited , 5 * widthScaleLimited )
djui_hud_set_color ( 0 , 0 , 0 , 255 )
djui_hud_set_rotation ( 0x0000 , 0.5 , 0.5 )
djui_hud_render_rect ( widthHalf - 4 * widthScaleLimited , yOffset + 10 - 2 * widthScaleLimited , 8 * widthScaleLimited , 5 * widthScaleLimited )
end
-- Options
for i = currOption - 2 , currOption + 2 do
if not ( i < 1 or i > optionTableCount ) then
local toggleName = optionTable [ i ] . name
local scale = 0.5
local yOffset = 100 - optionAnimTimer + ( i - currOption + 2 ) * 9 * widthScaleLimited
if i == currOption then
djui_hud_set_font ( FONT_CS_NORMAL )
scale = 0.3
yOffset = yOffset - 1
if optionTable [ i ] . toggleNames [ optionTable [ i ] . toggle + 1 ] ~= " " then
toggleName = toggleName .. " - " .. optionTable [ i ] . toggleNames [ optionTable [ i ] . toggle + 1 ]
else
toggleName = toggleName
end
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
2023-12-16 18:25:28 +00:00
else
2024-02-20 21:10:45 +00:00
djui_hud_set_font ( FONT_TINY )
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 150 )
2023-12-16 18:25:28 +00:00
end
2024-02-20 21:10:45 +00:00
scale = scale * widthScaleLimited
djui_hud_print_text ( toggleName , widthHalf - djui_hud_measure_text ( toggleName ) * scale * 0.5 , yOffset , scale )
2023-12-16 18:25:28 +00:00
end
end
2024-02-20 21:10:45 +00:00
-- Description
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 )
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
end
-- Footer
2023-12-16 18:25:28 +00:00
djui_hud_set_font ( FONT_TINY )
2024-02-20 21:10:45 +00:00
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
2023-12-16 18:25:28 +00:00
djui_hud_print_text ( TEXT_OPTIONS_SELECT , widthHalf - djui_hud_measure_text ( TEXT_OPTIONS_SELECT ) * 0.3 , height - 20 - optionAnimTimer , 0.6 )
2024-02-20 21:10:45 +00:00
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
djui_hud_render_rect ( width * 0.5 - 50 * widthScale , height - 2 , 100 * widthScale , 2 )
2023-12-16 18:25:28 +00:00
else
-- How to open options display
2024-02-20 21:10:45 +00:00
local widthScaleLimited = math_min ( widthScale , 1.42 )
2023-12-16 18:25:28 +00:00
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
2024-02-20 21:10:45 +00:00
djui_hud_render_rect ( widthHalf - 50 * widthScale , height - 25 * widthScaleLimited , 100 * widthScale , 26 * widthScaleLimited )
2023-12-16 18:25:28 +00:00
djui_hud_set_color ( 0 , 0 , 0 , 255 )
2024-02-20 21:10:45 +00:00
djui_hud_render_rect ( widthHalf - 50 * widthScale + 2 , height - 25 * widthScaleLimited + 2 , 100 * widthScale - 4 , 22 * widthScaleLimited )
2023-12-16 18:25:28 +00:00
djui_hud_set_color ( menuColor.r , menuColor.g , menuColor.b , 255 )
2024-02-20 21:10:45 +00:00
djui_hud_render_rect ( widthHalf - 50 * widthScale , height - 2 , 100 * widthScale , 2 )
2023-12-18 22:01:33 +00:00
djui_hud_set_font ( FONT_CS_NORMAL )
2024-02-20 21:10:45 +00:00
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 )
2023-12-16 18:25:28 +00:00
djui_hud_set_font ( FONT_TINY )
2024-02-20 21:10:45 +00:00
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 )
2023-12-16 18:25:28 +00:00
end
2024-02-20 21:10:45 +00:00
2023-12-16 18:25:28 +00:00
-- Anim logic
if options then
if optionTable [ optionTableRef.anims ] . toggle > 0 then
if optionAnimTimer < - 1 then
optionAnimTimer = optionAnimTimer / 1.1
end
else
optionAnimTimer = - 1
end
else
if optionTable [ optionTableRef.anims ] . toggle > 0 then
if optionAnimTimer > optionAnimTimerCap then
2024-02-20 21:10:45 +00:00
optionAnimTimer = optionAnimTimer * 1.3
2023-12-16 18:25:28 +00:00
end
else
optionAnimTimer = optionAnimTimerCap
end
end
optionAnimTimer = math_max ( optionAnimTimer , - 200 )
else
options = false
optionAnimTimer = optionAnimTimerCap
end
2023-12-23 16:40:20 +00:00
-- Cross fade
if optionTable [ optionTableRef.anims ] . toggle == 1 then
if menu and menuCrossFade > - menuCrossFadeCap then
menuCrossFade = menuCrossFade - 1
if menuCrossFade == 0 then menuCrossFade = menuCrossFade - 1 end
end
if not menu and menuCrossFade < menuCrossFadeCap then
menuCrossFade = menuCrossFade + 1
if menuCrossFade == 0 then menuCrossFade = menuCrossFade + 1 end
end
if menuCrossFade < 0 then
menuAndTransition = true
else
menuAndTransition = false
end
else
if menu then
menuCrossFade = - menuCrossFadeCap
else
menuCrossFade = menuCrossFadeCap
end
menuAndTransition = menu
end
djui_hud_set_resolution ( RESOLUTION_N64 )
djui_hud_set_color ( 0 , 0 , 0 , ( math_abs ( menuCrossFade ) ) * - menuCrossFadeMath )
djui_hud_render_rect ( 0 , 0 , width , height )
2023-12-16 18:25:28 +00:00
-- Info / Z Open Bind on Pause Menu
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 )
2023-12-23 16:40:20 +00:00
djui_hud_set_font ( FONT_NORMAL )
2023-12-16 18:25:28 +00:00
if optionTable [ optionTableRef.openInputs ] . toggle == 2 then
currCharY = 27
local width = djui_hud_get_screen_width ( ) - djui_hud_measure_text ( TEXT_PAUSE_Z_OPEN )
2024-02-20 21:10:45 +00:00
if not client_is_coop_dx then -- Done to match DX not having dropshadow on the "R Button - Options" thingy
2023-12-18 22:01:33 +00:00
djui_hud_set_color ( 0 , 0 , 0 , 255 )
djui_hud_print_text ( TEXT_PAUSE_Z_OPEN , width - 19 , 17 , 1 )
end
2023-12-16 18:25:28 +00:00
djui_hud_set_color ( 255 , 255 , 255 , 255 )
djui_hud_print_text ( TEXT_PAUSE_Z_OPEN , width - 20 , 16 , 1 )
end
if optionTable [ optionTableRef.localModels ] . toggle == 1 then
local charName = string_underscore_to_space ( characterTable [ currChar ] . name )
local TEXT_PAUSE_CURR_CHAR_WITH_NAME = TEXT_PAUSE_CURR_CHAR .. charName
local width = djui_hud_get_screen_width ( ) - djui_hud_measure_text ( TEXT_PAUSE_CURR_CHAR_WITH_NAME )
local charColor = characterTable [ currChar ] . color
2024-02-20 21:10:45 +00:00
if not client_is_coop_dx then
2023-12-18 22:01:33 +00:00
djui_hud_set_color ( 0 , 0 , 0 , 255 )
djui_hud_print_text ( TEXT_PAUSE_CURR_CHAR_WITH_NAME , width - 19 , 17 + currCharY , 1 )
end
2023-12-16 18:25:28 +00:00
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
local width = djui_hud_get_screen_width ( ) - djui_hud_measure_text ( TEXT_LOCAL_MODEL_OFF )
2024-02-20 21:10:45 +00:00
if not client_is_coop_dx then
2023-12-18 22:01:33 +00:00
djui_hud_set_color ( 0 , 0 , 0 , 255 )
djui_hud_print_text ( TEXT_LOCAL_MODEL_OFF , width - 19 , 17 + currCharY , 1 )
end
2023-12-16 18:25:28 +00:00
djui_hud_set_color ( 255 , 255 , 255 , 255 )
djui_hud_print_text ( TEXT_LOCAL_MODEL_OFF , width - 20 , 16 + currCharY , 1 )
end
end
end
-- Custom life icon rendering (Thanks LuigiGamer)
function on_life_counter_render ( )
if obj_get_first_with_behavior_id ( id_bhvActSelector ) ~= nil then return end
djui_hud_set_font ( FONT_HUD )
djui_hud_set_resolution ( RESOLUTION_N64 )
djui_hud_set_color ( 255 , 255 , 255 , 255 ) ;
local x = 22
local y = 15
if gNetworkPlayers [ 0 ] . currActNum == 99 then return end
2024-02-20 21:10:45 +00:00
if gMarioStates [ 0 ] . action == ACT_INTRO_CUTSCENE then return end
2023-12-16 18:25:28 +00:00
if not hud_is_hidden ( ) then
local icon = characterTable [ currChar ] . lifeIcon
2024-02-20 21:10:45 +00:00
if icon == nil then
djui_hud_print_text ( " ? " , x , y , 1 )
else
djui_hud_render_texture ( icon , x , y , 1 / ( icon.width / 16 ) , 1 / ( icon.height / 16 ) )
end
2023-12-16 18:25:28 +00:00
djui_hud_print_text ( " @ " , x + 16 , y , 1 )
djui_hud_print_text ( tostring ( gMarioStates [ 0 ] . numLives ) , x + 32 , y , 1 )
hud_set_value ( HUD_DISPLAY_FLAGS , hud_get_value ( HUD_DISPLAY_FLAGS ) &~ HUD_DISPLAY_FLAG_LIVES ) -- Hides the lives counter
else
hud_set_value ( HUD_DISPLAY_FLAGS , hud_get_value ( HUD_DISPLAY_FLAGS ) | HUD_DISPLAY_FLAG_LIVES ) -- Shows the lives counter, use this when you're no longer using a custom character
end
end
local function before_mario_update ( m )
if m.playerIndex ~= 0 then return end
2024-02-20 21:10:45 +00:00
if inputStallTimerButton > 0 then inputStallTimerButton = inputStallTimerButton - 1 end
if inputStallTimerDirectional > 0 then inputStallTimerDirectional = inputStallTimerDirectional - 1 end
2023-12-16 18:25:28 +00:00
2024-02-20 21:10:45 +00:00
if menu and inputStallToDirectional ~= latencyValueTable [ optionTable [ optionTableRef.inputLatency ] . toggle + 1 ] then
inputStallToDirectional = latencyValueTable [ optionTable [ optionTableRef.inputLatency ] . toggle + 1 ]
2023-12-16 18:25:28 +00:00
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
menu = true
end
2024-02-20 21:10:45 +00:00
inputStallTimerDirectional = inputStallToDirectional
2023-12-16 18:25:28 +00:00
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
end
local cameraToObject = gMarioStates [ 0 ] . marioObj.header . gfx.cameraToObject
-- C-up Failsafe (Camera Softlocks)
if m.action == ACT_FIRST_PERSON or ( m.prevAction == ACT_FIRST_PERSON and is_game_paused ( ) ) then
menu = false
elseif m.prevAction == ACT_FIRST_PERSON and not is_game_paused ( ) then
m.prevAction = ACT_WALKING
end
2024-02-20 21:10:45 +00:00
if gNetworkPlayers [ 0 ] . currActNum == 99 then menu = false end
if m.action == ACT_INTRO_CUTSCENE then menu = false end
2023-12-16 18:25:28 +00:00
2023-12-23 16:40:20 +00:00
if menuAndTransition and not options then
2024-02-20 21:10:45 +00:00
if menu then
if inputStallTimerDirectional == 0 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
inputStallTimerDirectional = inputStallToDirectional
else
inputStallTimerDirectional = 3 -- C-Scrolling
end
buttonScroll = buttonScrollCap
play_sound ( SOUND_MENU_MESSAGE_NEXT_PAGE , cameraToObject )
end
if ( m.controller . buttonPressed & U_JPAD ) ~= 0 or ( m.controller . buttonPressed & U_CBUTTONS ) ~= 0 or m.controller . stickY > 60 then
currChar = currChar - 1
if ( m.controller . buttonPressed & U_CBUTTONS ) == 0 then
inputStallTimerDirectional = inputStallToDirectional
else
inputStallTimerDirectional = 3 -- C-Scrolling
end
buttonScroll = - buttonScrollCap
play_sound ( SOUND_MENU_MESSAGE_NEXT_PAGE , cameraToObject )
2023-12-16 18:25:28 +00:00
end
end
2024-02-20 21:10:45 +00:00
if inputStallTimerButton == 0 then
if ( m.controller . buttonPressed & A_BUTTON ) ~= 0 then
if characterTable [ currChar ] ~= nil then
mod_storage_save_pref_char ( characterTable [ currChar ] )
inputStallTimerButton = inputStallToButton
play_sound ( SOUND_MENU_CLICK_FILE_SELECT , cameraToObject )
else
play_sound ( SOUND_MENU_CAMERA_BUZZ , cameraToObject )
end
end
if ( m.controller . buttonPressed & B_BUTTON ) ~= 0 then
menu = false
end
if ( m.controller . buttonPressed & START_BUTTON ) ~= 0 then
options = true
end
2023-12-16 18:25:28 +00:00
end
end
2024-02-20 21:10:45 +00:00
-- Wraping Menu
2023-12-16 18:25:28 +00:00
if currChar > # characterTable then currChar = 1 end
if currChar < 1 then currChar = # characterTable end
2024-02-20 21:10:45 +00:00
-- Handles Camera Posistioning
faceAngle = m.faceAngle . y
if m.controller . buttonPressed & R_CBUTTONS ~= 0 then faceAngle = faceAngle + 0x1000 end
if m.controller . buttonPressed & L_CBUTTONS ~= 0 then faceAngle = faceAngle - 0x1000 end
2023-12-16 18:25:28 +00:00
nullify_inputs ( m )
if is_game_paused ( ) then
m.controller . buttonPressed = START_BUTTON
end
end
if options then
2024-02-20 21:10:45 +00:00
if inputStallTimerDirectional == 0 then
2023-12-16 18:25:28 +00:00
if ( m.controller . buttonPressed & D_JPAD ) ~= 0 then
currOption = currOption + 1
2024-02-20 21:10:45 +00:00
inputStallTimerDirectional = inputStallToDirectional
2023-12-16 18:25:28 +00:00
play_sound ( SOUND_MENU_MESSAGE_NEXT_PAGE , cameraToObject )
end
if ( m.controller . buttonPressed & U_JPAD ) ~= 0 then
currOption = currOption - 1
2024-02-20 21:10:45 +00:00
inputStallTimerDirectional = inputStallToDirectional
2023-12-16 18:25:28 +00:00
play_sound ( SOUND_MENU_MESSAGE_NEXT_PAGE , cameraToObject )
end
if m.controller . stickY < - 60 then
currOption = currOption + 1
2024-02-20 21:10:45 +00:00
inputStallTimerDirectional = inputStallToDirectional
2023-12-16 18:25:28 +00:00
play_sound ( SOUND_MENU_MESSAGE_NEXT_PAGE , cameraToObject )
end
if m.controller . stickY > 60 then
currOption = currOption - 1
2024-02-20 21:10:45 +00:00
inputStallTimerDirectional = inputStallToDirectional
2023-12-16 18:25:28 +00:00
play_sound ( SOUND_MENU_MESSAGE_NEXT_PAGE , cameraToObject )
end
2024-02-20 21:10:45 +00:00
end
if inputStallTimerButton == 0 then
2023-12-16 18:25:28 +00:00
if ( m.controller . buttonPressed & A_BUTTON ) ~= 0 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
mod_storage_save ( optionTable [ currOption ] . toggleSaveName , tostring ( optionTable [ currOption ] . toggle ) )
end
2024-02-20 21:10:45 +00:00
inputStallTimerButton = inputStallToButton
2023-12-16 18:25:28 +00:00
play_sound ( SOUND_MENU_CHANGE_SELECT , cameraToObject )
end
if ( m.controller . buttonPressed & B_BUTTON ) ~= 0 then
options = false
2024-02-20 21:10:45 +00:00
inputStallTimerButton = inputStallToButton
2023-12-16 18:25:28 +00:00
end
end
if currOption > # optionTable then currOption = 1 end
if currOption < 1 then currOption = # optionTable end
nullify_inputs ( m )
end
end
hook_event ( HOOK_BEFORE_MARIO_UPDATE , before_mario_update )
hook_event ( HOOK_ON_HUD_RENDER , on_hud_render )
hook_event ( HOOK_ON_HUD_RENDER_BEHIND , on_life_counter_render )
--------------
-- Commands --
--------------
2024-02-20 21:10:45 +00:00
local promptedAreYouSure = false
2023-12-16 18:25:28 +00:00
local function chat_command ( msg )
2024-02-20 21:10:45 +00:00
msg = string_lower ( msg )
-- Open Menu Check
if msg == " " or msg == " menu " then
2023-12-16 18:25:28 +00:00
menu = not menu
return true
end
2024-02-20 21:10:45 +00:00
-- Help Prompt Check
if msg == " ? " or msg == " help " then
djui_chat_message_create ( " Character Select's Avalible Commands: " ..
" \n \\ #ffff33 \\ /char-select help \\ #ffffff \\ - Returns Avalible Commands " ..
" \n \\ #ffff33 \\ /char-select menu \\ #ffffff \\ - Opens the Menu " ..
" \n \\ #ffff33 \\ /char-select [name/num] \\ #ffffff \\ - Switches to Character " ..
" \n \\ #ff3333 \\ /char-select reset \\ #ffffff \\ - Resets your Save Data " )
return true
end
-- Reset Save Data Check
if msg == " reset " or ( msg == " confirm " and promptedAreYouSure ) then
reset_options ( true )
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
currChar = i
djui_chat_message_create ( characterTable [ i ] . saveName )
djui_chat_message_create ( ' Character set to " ' .. characterTable [ i ] . name .. ' " Successfully! ' )
return true
end
end
-- Number Check
if tonumber ( msg ) then
local msg = tonumber ( msg )
if msg > 0 and msg <= # characterTable then
currChar = msg
djui_chat_message_create ( ' Character set to " ' .. characterTable [ msg ] . name .. ' " Successfully! ' )
return true
end
end
djui_chat_message_create ( " Character Not Found " )
return true
2023-12-16 18:25:28 +00:00
end
hook_chat_command ( " char-select " , " - Opens the Character Select Menu " , chat_command )