1327 lines
58 KiB
Lua
1327 lines
58 KiB
Lua
-- name: Character Select
|
|
-- description:\\#ffff33\\--- Character Select Coop v1.9.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 can be found on\nCharacter Select's Github:\n\\#6666FF\\Squishy6094/character-select-coop
|
|
-- pausable: false
|
|
|
|
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
|
|
|
|
menu = false
|
|
menuAndTransition = false
|
|
options = false
|
|
currChar = 1
|
|
local currOption = 1
|
|
|
|
local menuCrossFade = 7
|
|
local menuCrossFadeCap = menuCrossFade
|
|
local menuCrossFadeMath = 255 / menuCrossFade
|
|
|
|
local TEX_HEADER = get_texture_info("char-select-text")
|
|
local TEX_OVERRIDE_HEADER = nil
|
|
|
|
---@param texture TextureInfo|nil
|
|
function header_set_texture(texture)
|
|
TEX_OVERRIDE_HEADER = texture
|
|
end
|
|
|
|
local TEXT_PREF_LOAD = "Default"
|
|
|
|
--[[
|
|
Note: Do NOT add characters via the characterTable below,
|
|
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!
|
|
]]
|
|
characterTable = {
|
|
[1] = {
|
|
name = "Default",
|
|
saveName = "Default",
|
|
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,
|
|
offset = 0,
|
|
forceChar = nil, -- Legacy Functionality
|
|
lifeIcon = gTextures.mario_head,
|
|
starIcon = gTextures.star,
|
|
camScale = 1.0
|
|
},
|
|
}
|
|
|
|
gPlayerSyncTable[0].offset = 0
|
|
|
|
characterCaps = {}
|
|
characterCelebrationStar = {}
|
|
characterColorPresets = {}
|
|
|
|
optionTableRef = {
|
|
openInputs = 1,
|
|
notification = 2,
|
|
menuColor = 3,
|
|
anims = 4,
|
|
inputLatency = 5,
|
|
autoPalette = 6,
|
|
localModels = 7,
|
|
localVoices = 8,
|
|
debugInfo = 9,
|
|
resetSaveData = 10
|
|
}
|
|
|
|
optionTable = {
|
|
[optionTableRef.openInputs] = {
|
|
name = "Open Binds",
|
|
toggle = tonumber(mod_storage_load("MenuInput")),
|
|
toggleSaveName = "MenuInput",
|
|
toggleDefault = 1,
|
|
toggleMax = 2,
|
|
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] = {
|
|
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"}
|
|
},
|
|
[optionTableRef.menuColor] = {
|
|
name = "Menu Color",
|
|
toggle = tonumber(mod_storage_load("MenuColor")),
|
|
toggleSaveName = "MenuColor",
|
|
toggleDefault = 0,
|
|
toggleMax = 10,
|
|
toggleNames = {"Auto", "Saved", "Red", "Orange", "Yellow", "Green", "Blue", "Pink", "Purple", "White", "Black"},
|
|
description = {"Toggles the Menu Color"}
|
|
},
|
|
[optionTableRef.anims] = {
|
|
name = "Animations",
|
|
toggle = tonumber(mod_storage_load("Anims")),
|
|
toggleSaveName = "Anims",
|
|
toggleDefault = 1,
|
|
toggleMax = 1,
|
|
toggleNames = {"Off", "On"--[[, "On (30 fps)"]]},
|
|
description = {"Toggles Animations In-Menu,", "Turning these off may", "Save Performance"}
|
|
},
|
|
[optionTableRef.inputLatency] = {
|
|
name = "Scroll Speed",
|
|
toggle = tonumber(mod_storage_load("Latency")),
|
|
toggleSaveName = "Latency",
|
|
toggleDefault = 1,
|
|
toggleMax = 2,
|
|
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")),
|
|
toggleSaveName = "localModels",
|
|
toggleDefault = 1,
|
|
toggleMax = 1,
|
|
description = {"Toggles if Custom Models display", "on your client, practically", "disables Character Select if", "Toggled Off"}
|
|
},
|
|
[optionTableRef.localVoices] = {
|
|
name = "Custom Voices",
|
|
toggle = tonumber(mod_storage_load("localVoices")),
|
|
toggleSaveName = "localVoices",
|
|
toggleDefault = 1,
|
|
toggleMax = 1,
|
|
description = {"Toggle if Custom Voicelines play", "for Characters who support it"}
|
|
},
|
|
[optionTableRef.debugInfo] = {
|
|
name = "Debugging Info",
|
|
toggle = tonumber(mod_storage_load("debuginfo")),
|
|
toggleSaveName = "debuginfo",
|
|
toggleDefault = 0,
|
|
toggleMax = 1,
|
|
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"}
|
|
},
|
|
}
|
|
|
|
local defaultOptionCount = #optionTable
|
|
|
|
local latencyValueTable = {12, 6, 3}
|
|
|
|
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 },
|
|
{ r = 50, g = 50, b = 255 },
|
|
{ r = 251, g = 148, b = 220 },
|
|
{ r = 130, g = 25, b = 130 },
|
|
{ r = 255, g = 255, b = 255 },
|
|
{ r = 50, g = 50, b = 50 }
|
|
}
|
|
|
|
-- Default Player Adjustments
|
|
local defaultNames = {
|
|
[CT_MARIO] = "Mario",
|
|
[CT_LUIGI] = "Luigi",
|
|
[CT_TOAD] = "Toad",
|
|
[CT_WALUIGI] = "Waluigi",
|
|
[CT_WARIO] = "Wario"
|
|
}
|
|
local defaultMenuColors = {
|
|
[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
|
|
}
|
|
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)
|
|
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
|
|
|
|
local prefCharColor = defaultMenuColors[CT_MARIO]
|
|
|
|
local function load_preferred_char()
|
|
local savedChar = mod_storage_load("PrefChar")
|
|
if savedChar == nil or savedChar == "" then
|
|
mod_storage_save("PrefChar", "Default")
|
|
savedChar = "Default"
|
|
end
|
|
if savedChar ~= nil and savedChar ~= "Default" then
|
|
for i = 2, #characterTable do
|
|
if characterTable[i].saveName == savedChar then
|
|
currChar = i
|
|
if optionTable[optionTableRef.localModels].toggle == 1 then
|
|
if optionTable[optionTableRef.notification].toggle > 0 then
|
|
djui_popup_create('Character Select:\nYour Preferred Character\n"' .. string_underscore_to_space(characterTable[i].name) .. '"\nwas applied successfully!', 4)
|
|
end
|
|
end
|
|
break
|
|
end
|
|
end
|
|
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")
|
|
end
|
|
|
|
if #characterTable == 1 then
|
|
if optionTable[optionTableRef.notification].toggle > 0 then
|
|
djui_popup_create("Character Select:\nNo Characters were Found", 2)
|
|
end
|
|
end
|
|
return 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
|
|
end
|
|
|
|
function failsafe_options()
|
|
for i = 1, #optionTable do
|
|
if optionTable[i].toggle == nil or optionTable[i].toggle == "" then
|
|
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
|
|
end
|
|
if optionTable[i].toggleNames == nil then
|
|
optionTable[i].toggleNames = {"Off", "On"}
|
|
end
|
|
end
|
|
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
|
|
|
|
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\nand 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()
|
|
if #characterTable > 1 then
|
|
djui_chat_message_create("Character Select has " .. (#characterTable - 1) .. " character" .. (#characterTable > 2 and "s" or "") .. " available!\nYou can use \\#ffff33\\/char-select \\#ffffff\\to open the menu!")
|
|
else
|
|
djui_chat_message_create("Character Select is active!\nYou can use \\#ffff33\\/char-select \\#ffffff\\to open the menu!")
|
|
end
|
|
end
|
|
|
|
local function menu_is_allowed()
|
|
for _, func in pairs(allowMenu) do
|
|
if not func() then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
-------------------
|
|
-- Model Handler --
|
|
-------------------
|
|
|
|
local stallFrame = 0
|
|
local noLoop = false
|
|
|
|
local CUTSCENE_CS_MENU = 0xFA
|
|
|
|
local ignoredSurfaces = {
|
|
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
|
|
}
|
|
|
|
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,
|
|
[ACT_WARP_DOOR_SPAWN] = true,
|
|
[ACT_PULLING_DOOR] = true,
|
|
[ACT_PUSHING_DOOR] = true,
|
|
[ACT_UNLOCKING_KEY_DOOR] = true,
|
|
[ACT_UNLOCKING_STAR_DOOR] = 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
|
|
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,
|
|
}
|
|
|
|
--- @param m MarioState
|
|
local function mario_update(m)
|
|
if stallFrame == 1 or queueStorageFailsafe then
|
|
failsafe_options()
|
|
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
|
|
stallFrame = stallFrame + 1
|
|
end
|
|
|
|
if m.playerIndex == 0 and stallFrame > 1 then
|
|
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].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[0].modelId = characterTable[currChar].model
|
|
if characterTable[currChar].forceChar ~= nil then
|
|
gNetworkPlayers[0].overrideModelIndex = characterTable[currChar].forceChar
|
|
end
|
|
m.marioObj.hookRender = 1
|
|
else
|
|
gPlayerSyncTable[0].modelId = nil
|
|
gNetworkPlayers[0].overrideModelIndex = characterTable[1].forceChar
|
|
currChar = 1
|
|
end
|
|
|
|
gPlayerSyncTable[0].offset = characterTable[currChar].offset
|
|
--[[
|
|
for i = 0, MAX_PLAYERS-1 do
|
|
local m = gMarioStates[i]
|
|
end
|
|
]]
|
|
|
|
if menuAndTransition then
|
|
camera_freeze()
|
|
hud_hide()
|
|
if _G.PersonalStarCounter then
|
|
_G.PersonalStarCounter.hide_star_counters(true)
|
|
end
|
|
if m.area.camera.cutscene == 0 then
|
|
m.area.camera.cutscene = CUTSCENE_CS_MENU
|
|
end
|
|
local camScale = characterTable[currChar].camScale
|
|
local focusPos = {
|
|
x = m.pos.x,
|
|
y = m.pos.y + 120 * camScale,
|
|
z = m.pos.z,
|
|
}
|
|
vec3f_copy(gLakituState.focus, focusPos)
|
|
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
|
|
|
|
if m.forwardVel == 0 and m.pos.y == m.floorHeight and not ignoredSurfaces[m.floor.type] and m.health > 255 and not menuActBlacklist[m.action] then
|
|
set_mario_action(m, ACT_IDLE, 0)
|
|
set_mario_animation(m, MARIO_ANIM_FIRST_PERSON)
|
|
end
|
|
noLoop = false
|
|
elseif not noLoop then
|
|
camera_unfreeze()
|
|
hud_show()
|
|
if _G.PersonalStarCounter then
|
|
_G.PersonalStarCounter.hide_star_counters(false)
|
|
end
|
|
if m.area.camera.cutscene == CUTSCENE_CS_MENU then
|
|
m.area.camera.cutscene = CUTSCENE_STOP
|
|
end
|
|
noLoop = true
|
|
end
|
|
|
|
--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
|
|
|
|
local offset = gPlayerSyncTable[m.playerIndex].offset
|
|
if offset ~= 0 and offset ~= nil 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) + offset
|
|
end
|
|
end
|
|
end
|
|
|
|
local sCapBhvs = {
|
|
[id_bhvWingCap] = true,
|
|
[id_bhvVanishCap] = true,
|
|
[id_bhvMetalCap] = true
|
|
}
|
|
|
|
--- @param o Object
|
|
--- @param model integer
|
|
local BowserKey = false
|
|
local function on_star_or_key_grab(m, o, type)
|
|
if type == INTERACT_STAR_OR_KEY then
|
|
if get_id_from_behavior(o.behavior) == id_bhvBowserKey then
|
|
BowserKey = true
|
|
else
|
|
BowserKey = false
|
|
end
|
|
end
|
|
end
|
|
|
|
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
|
|
obj_set_model_extended(o, gPlayerSyncTable[i].modelId)
|
|
end
|
|
return
|
|
end
|
|
if obj_has_behavior_id(o, id_bhvCelebrationStar) ~= 0 and o.parentObj ~= nil then
|
|
local i = network_local_index_from_global(o.parentObj.globalPlayerIndex)
|
|
local starModel = characterCelebrationStar[gPlayerSyncTable[i].modelId]
|
|
if gPlayerSyncTable[i].modelId ~= nil and starModel ~= nil and obj_has_model_extended(o, starModel) == 0 and not BowserKey then
|
|
obj_set_model_extended(o, starModel)
|
|
end
|
|
return
|
|
end
|
|
|
|
if sCapBhvs[get_id_from_behavior(o.behavior)] then
|
|
o.globalPlayerIndex = nearest_player_to_object(o.parentObj).globalPlayerIndex
|
|
end
|
|
local i = network_local_index_from_global(o.globalPlayerIndex)
|
|
|
|
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]
|
|
if capModels ~= nil then
|
|
local capModel = E_MODEL_NONE
|
|
if model == c.capModelId then
|
|
capModel = capModels.normal
|
|
elseif model == c.capWingModelId then
|
|
capModel = capModels.wing
|
|
elseif model == c.capMetalModelId then
|
|
capModel = capModels.metal
|
|
elseif model == c.capMetalWingModelId then
|
|
capModel = capModels.metalWing
|
|
end
|
|
if capModel ~= E_MODEL_NONE and capModel ~= E_MODEL_ERROR_MODEL and capModel ~= nil then
|
|
obj_set_model_extended(o, capModel)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
hook_event(HOOK_MARIO_UPDATE, mario_update)
|
|
hook_event(HOOK_ON_INTERACT, on_star_or_key_grab)
|
|
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
|
|
|
|
local inputStallTimerButton = 0
|
|
local inputStallTimerDirectional = 0
|
|
local inputStallToDirectional = 12
|
|
local inputStallToButton = 10
|
|
|
|
--Basic Menu Text
|
|
local TEXT_OPTIONS_HEADER = "Menu Options"
|
|
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 Referencing the original sm64ex DynOS options by PeachyPeach >v<
|
|
TEXT_PAUSE_Z_OPEN = "Z - DynOS"
|
|
TEXT_PAUSE_CURR_CHAR = "Model: "
|
|
end
|
|
|
|
--Debug Text
|
|
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"
|
|
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"
|
|
|
|
menuColor = characterTable[currChar].color
|
|
|
|
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_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_320
|
|
|
|
if menuAndTransition then
|
|
update_menu_color()
|
|
|
|
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
|
|
|
|
-- 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_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
|
|
TEXT_PREF = "Preferred Char:"
|
|
end
|
|
if djui_hud_measure_text(TEXT_PREF_LOAD) / widthScale > 164 then
|
|
TEXT_PREF = "Pref Char:"
|
|
end
|
|
TEXT_PREF = TEXT_PREF .. ' "' .. TEXT_PREF_LOAD .. '"'
|
|
|
|
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)
|
|
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
|
|
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
|
|
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)
|
|
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_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)
|
|
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
|
|
removeLine = removeLine + 1
|
|
end
|
|
end
|
|
local descriptionOffset = (#TEXT_DESCRIPTION_TABLE - removeLine) * 5
|
|
y = y + 5 + descriptionOffset
|
|
end
|
|
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_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, 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 + 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_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_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, 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
|
|
end
|
|
if optionTable[optionTableRef.anims].toggle == 0 then
|
|
buttonScroll = 0
|
|
elseif math_abs(buttonScroll) > 0.1 then
|
|
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 x = buttonX
|
|
if i == 0 then
|
|
if optionTable[optionTableRef.anims].toggle > 0 then
|
|
x = buttonAnimX
|
|
else
|
|
x = buttonX + 10
|
|
end
|
|
end
|
|
local y = (i + 3) * 30 + buttonScroll
|
|
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(characterTable[currChar + i].name, x + 5, y + 5, 0.6)
|
|
end
|
|
end
|
|
|
|
-- 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(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, 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_32), 1 / (TEX_OVERRIDE_HEADER.height*MATH_DIVIDE_32))
|
|
else
|
|
djui_hud_render_texture(TEX_HEADER, widthHalf - 128, 10, 1, 1)
|
|
end
|
|
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
|
|
djui_hud_set_font(FONT_TINY)
|
|
djui_hud_print_text(TEXT_VERSION, 5, 3, 0.5)
|
|
|
|
--Unsupported Res Warning
|
|
if width < 321.2 or width > 575 then
|
|
djui_hud_print_text(TEXT_RATIO_UNSUPPORTED, 5, 39, 0.5)
|
|
end
|
|
|
|
-- 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)
|
|
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
|
|
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_ALIASED)
|
|
djui_hud_set_color(menuColor.r * 0.5 + 127, menuColor.g * 0.5 + 127, menuColor.b * 0.5 + 127, 255)
|
|
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
|
|
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_ALIASED)
|
|
scale = 0.3
|
|
yOffset = yOffset - 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
|
|
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
|
|
else
|
|
djui_hud_set_font(FONT_TINY)
|
|
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 150)
|
|
end
|
|
scale = scale * widthScaleLimited
|
|
djui_hud_print_text(toggleName, widthHalf - djui_hud_measure_text(toggleName) * scale * 0.5, yOffset, scale)
|
|
end
|
|
end
|
|
|
|
-- 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_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
|
|
end
|
|
-- Footer
|
|
djui_hud_set_font(FONT_TINY)
|
|
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
|
|
djui_hud_print_text(TEXT_OPTIONS_SELECT, widthHalf - djui_hud_measure_text(TEXT_OPTIONS_SELECT) * 0.3, height - 20 - optionAnimTimer, 0.6)
|
|
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)
|
|
else
|
|
-- How to open options display
|
|
local widthScaleLimited = minf(widthScale, 1.42)
|
|
djui_hud_set_color(menuColor.r, menuColor.g, menuColor.b, 255)
|
|
djui_hud_render_rect(widthHalf - 50 * widthScale, height - 25 * widthScaleLimited, 100 * widthScale, 26 * widthScaleLimited)
|
|
djui_hud_set_color(0, 0, 0, 255)
|
|
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_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)
|
|
end
|
|
|
|
|
|
-- Anim logic
|
|
if options then
|
|
if optionTable[optionTableRef.anims].toggle > 0 then
|
|
if optionAnimTimer < -1 then
|
|
optionAnimTimer = optionAnimTimer * 0.9
|
|
end
|
|
else
|
|
optionAnimTimer = -1
|
|
end
|
|
else
|
|
if optionTable[optionTableRef.anims].toggle > 0 then
|
|
if optionAnimTimer > optionAnimTimerCap then
|
|
optionAnimTimer = optionAnimTimer * 1.3
|
|
end
|
|
else
|
|
optionAnimTimer = optionAnimTimerCap
|
|
end
|
|
end
|
|
optionAnimTimer = maxf(optionAnimTimer, -200)
|
|
else
|
|
options = false
|
|
optionAnimTimer = optionAnimTimerCap
|
|
end
|
|
|
|
-- 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)
|
|
|
|
-- 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)
|
|
djui_hud_set_font(FONT_USER)
|
|
if optionTable[optionTableRef.openInputs].toggle == 1 then
|
|
currCharY = 27
|
|
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, 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
|
|
width = djui_hud_get_screen_width() - djui_hud_measure_text(TEXT_PAUSE_CURR_CHAR_WITH_NAME)
|
|
local charColor = characterTable[currChar].color
|
|
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)
|
|
djui_hud_set_color(255, 255, 255, 255)
|
|
djui_hud_print_text(TEXT_LOCAL_MODEL_OFF, width - 20, 16 + currCharY, 1)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function before_mario_update(m)
|
|
if m.playerIndex ~= 0 then return end
|
|
if inputStallTimerButton > 0 then inputStallTimerButton = inputStallTimerButton - 1 end
|
|
if inputStallTimerDirectional > 0 then inputStallTimerDirectional = inputStallTimerDirectional - 1 end
|
|
|
|
if menu and inputStallToDirectional ~= latencyValueTable[optionTable[optionTableRef.inputLatency].toggle + 1] then
|
|
inputStallToDirectional = latencyValueTable[optionTable[optionTableRef.inputLatency].toggle + 1]
|
|
end
|
|
|
|
-- Menu Inputs
|
|
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 not menu_is_allowed() then
|
|
menu = false
|
|
return
|
|
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
|
|
|
|
if gNetworkPlayers[0].currActNum == 99 then menu = false end
|
|
if m.action == ACT_INTRO_CUTSCENE then menu = false end
|
|
|
|
if menuAndTransition and not options then
|
|
if menu 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
|
|
inputStallTimerDirectional = inputStallToDirectional
|
|
else
|
|
inputStallTimerDirectional = 3 -- C-Scrolling
|
|
end
|
|
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
|
|
if (m.controller.buttonPressed & U_CBUTTONS) == 0 then
|
|
inputStallTimerDirectional = inputStallToDirectional
|
|
else
|
|
inputStallTimerDirectional = 3 -- C-Scrolling
|
|
end
|
|
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
|
|
|
|
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
|
|
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
|
|
if currChar > #characterTable then currChar = 1 end
|
|
if currChar < 1 then currChar = #characterTable end
|
|
|
|
-- 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
|
|
|
|
nullify_inputs(m)
|
|
if is_game_paused() then
|
|
m.controller.buttonPressed = START_BUTTON
|
|
end
|
|
end
|
|
|
|
if options then
|
|
if inputStallTimerDirectional == 0 then
|
|
if (m.controller.buttonPressed & D_JPAD) ~= 0 then
|
|
currOption = currOption + 1
|
|
inputStallTimerDirectional = inputStallToDirectional
|
|
play_sound(SOUND_MENU_MESSAGE_NEXT_PAGE, cameraToObject)
|
|
end
|
|
if (m.controller.buttonPressed & U_JPAD) ~= 0 then
|
|
currOption = currOption - 1
|
|
inputStallTimerDirectional = inputStallToDirectional
|
|
play_sound(SOUND_MENU_MESSAGE_NEXT_PAGE, cameraToObject)
|
|
end
|
|
if m.controller.stickY < -60 then
|
|
currOption = currOption + 1
|
|
inputStallTimerDirectional = inputStallToDirectional
|
|
play_sound(SOUND_MENU_MESSAGE_NEXT_PAGE, cameraToObject)
|
|
end
|
|
if m.controller.stickY > 60 then
|
|
currOption = currOption - 1
|
|
inputStallTimerDirectional = inputStallToDirectional
|
|
play_sound(SOUND_MENU_MESSAGE_NEXT_PAGE, cameraToObject)
|
|
end
|
|
end
|
|
|
|
if inputStallTimerButton == 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
|
|
mod_storage_save(optionTable[currOption].toggleSaveName, tostring(optionTable[currOption].toggle))
|
|
end
|
|
inputStallTimerButton = inputStallToButton
|
|
play_sound(SOUND_MENU_CHANGE_SELECT, cameraToObject)
|
|
end
|
|
if (m.controller.buttonPressed & B_BUTTON) ~= 0 then
|
|
options = false
|
|
inputStallTimerButton = inputStallToButton
|
|
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)
|
|
|
|
--------------
|
|
-- Commands --
|
|
--------------
|
|
|
|
promptedAreYouSure = false
|
|
|
|
local function chat_command(msg)
|
|
msg = string_lower(msg)
|
|
|
|
-- Open Menu Check
|
|
if msg == "" or msg == "menu" then
|
|
menu = not menu
|
|
return true
|
|
end
|
|
|
|
-- 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
|
|
|
|
-- 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
|
|
currChar = i
|
|
djui_chat_message_create('Character set to "' .. characterTable[i].name .. '" Successfully!')
|
|
return true
|
|
end
|
|
end
|
|
|
|
-- Number Check
|
|
if tonumber(msg) then
|
|
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
|
|
end
|
|
|
|
hook_chat_command("char-select", "- Opens the Character Select Menu", chat_command)
|