Skip to content

Allow mods to add characters and palettes to the player menu, more#1120

Open
EmeraldLoc wants to merge 20 commits intocoop-deluxe:devfrom
EmeraldLoc:char-selector
Open

Allow mods to add characters and palettes to the player menu, more#1120
EmeraldLoc wants to merge 20 commits intocoop-deluxe:devfrom
EmeraldLoc:char-selector

Conversation

@EmeraldLoc
Copy link
Contributor

@EmeraldLoc EmeraldLoc commented Feb 19, 2026

Characters

Characters can now be added and modified. You can view more details about the functions I'm about to outline in the documentation.

  • Adds character_allocate(const char* name), which takes in a name, and returns a Character and character index.
  • Adds character_get_first_allocated_index(), character_get_first_unallocated_index(), character_get_first_allocated(), and character_get_first_unallocated()
  • Adds get_allocated_character_from_index(int i), which will attempt to get the allocated character at the index, but if it fails, it gets the first allocated character using character_get_first_allocated().
  • Adds get_character(struct MarioState* m), which gets the character that the passed in MarioState is using
  • Adds get_modded_character_anim_string, which gets the current name of the animation used if the animation is modded
  • Adds character_set_name
  • Adds character_set_cap_enemy_gfx_name, for the cap on a enemy head like ukiki
  • Adds character_set_cap_enemy_decal_gfx_name, same above but for decal
  • Adds character_set_hud_head_texture
  • Adds character_add_sound
  • Adds character_remove_sounds
  • Adds character_set_animation
  • Adds character_remove_animation
  • Deprecates CT_MAX in favor of CT_COUNT
  • Syncs MarioState's character
  • Other stuff I probably missed

Palettes

Palettes can now be added to the selector!

  • Adds preset_palette_allocate, which takes in a name, and returns a PresetPalette.
  • Adds preset_palette_set_name, which sets the name of a PresetPalette
  • Adds preset_palette_set_color_of_part, which sets the part of a PresetPalette

Misc Changes

  • Allowed convert_structs.py to use the * symbol to make multiple fields immutable, mutable, invisible, etc.
  • Adds smlua_anim_util_animation_exists
  • Adds smlua_anim_util_animation_exists_using_index
  • Adds smlua_anim_util_get_index_from_name
  • Adds smlua_anim_util_get_name_from_index

And of course, there's a lot more stuff under the hood not documented here. I tried to get it all, but some things may be missing. Any and all suggestions and/or critiques are welcomed.

Tons of testing still needs to be done, and some syncing stuff still needs to be addressed.

@ucuckic
Copy link

ucuckic commented Feb 20, 2026

having an issue where when a player other than oneself attempts to use a character with custom sfx, when those sfx should play the console gets spammed with errors: Tried to load audio file with invalid file type: where the supplied filetype is gibberish characters (and of course, ultimately, the sound does not play)

@EmeraldLoc
Copy link
Contributor Author

Uh oh, that doesn't sound good! What does your implementation look like?

@ucuckic
Copy link

ucuckic commented Feb 20, 2026

local E_MODEL_GARION = smlua_model_util_get_id("garion_geo")

local se_table_garion = {
	[CHAR_SOUND_ATTACKED] = 'GARION1_ara.ogg',
    [CHAR_SOUND_DOH] = {'GARION1_grunt3.ogg', 'GARION1_grunt6.ogg',}, -- Bonk into walls
    [CHAR_SOUND_DYING] = 'GARION1_chikara_ga.ogg',
    [CHAR_SOUND_EEUH] = 'GARION1_fuu2.ogg', -- Slow Get up from ledge
    [CHAR_SOUND_GAME_OVER] = 'GARION1_sayonara.ogg',
    [CHAR_SOUND_GROUND_POUND_WAH] = 'GARION1_oshitsubusu.ogg',
    [CHAR_SOUND_HAHA] = 'GARION1_doudesuka.ogg', -- Landing after backflip
    [CHAR_SOUND_HAHA_2] = 'GARION1_tobimashitane.ogg', -- Landing on Water after a fall
    -- [CHAR_SOUND_HELLO] = '',
    [CHAR_SOUND_HERE_WE_GO] = {'GARION1_subarashii.ogg', 'GARION1_migoto_desu.ogg', }, -- Star Get + Obtaining Power-up
    [CHAR_SOUND_HOOHOO] = 'GARION1_fufu2.ogg', -- 2nd Jump + Dive Attack
    [CHAR_SOUND_HRMM] = 'GARION1_fuu3.ogg', -- Object Pick-up
    [CHAR_SOUND_IMA_TIRED] = 'GARION1_oyaoya.ogg',
    [CHAR_SOUND_LETS_A_GO] = 'GARION1_yarisugirukamoshiremasen.ogg', -- Level Select
    [CHAR_SOUND_MAMA_MIA] = {'GARION1_zannen_deshitane.ogg', 'GARION1_aah_hibiwareru.ogg',}, -- Getting up after thrown out of level
    [CHAR_SOUND_ON_FIRE] = 'GARION1_maa3.ogg', -- 'GARION1_kogeteimasennka.ogg', -- Touch Fire
    [CHAR_SOUND_OOOF] = 'GARION1_grunt9.ogg',
    [CHAR_SOUND_OOOF2] = {'GARION1_maa2.ogg', 'GARION1_aramaa.ogg',}, -- Landing After a Bonk + Thrown out of level
    [CHAR_SOUND_PANTING] = 'GARION1_fuu.ogg', -- Low Health
    [CHAR_SOUND_PANTING_COLD] = 'GARION1_fuu.ogg',
    -- [CHAR_SOUND_PRESS_START_TO_PLAY] = '',
    [CHAR_SOUND_PUNCH_HOO] = 'GARION1_awarena.ogg', -- Kick
    [CHAR_SOUND_PUNCH_WAH] = {'GARION1_iwa_wo.ogg', 'GARION1_tsuchi_wo.ogg'}, --2nd Punch
    [CHAR_SOUND_PUNCH_YAH] = {'GARION1_odokinasai.ogg', 'GARION1_jama_desu.ogg',}, -- 1st Punch
	-- [CHAR_SOUND_SNORING1] = '',
    -- [CHAR_SOUND_SNORING2] = '',
    [CHAR_SOUND_SNORING3] = 'GARION1_tsukareta_toki_ha_oshietekudasai.ogg',
    [CHAR_SOUND_SO_LONGA_BOWSER] = {'GARION1_kagen_ga_muzukashii_desuga.ogg', 'GARION1_sayonara.ogg'}, --Bowser Throw
    [CHAR_SOUND_TWIRL_BOUNCE] = 'GARION1_mairimashou.ogg', -- Boing
    [CHAR_SOUND_UH] = 'GARION1_otto2.ogg', --Drop off of ledge
    [CHAR_SOUND_UH2] = 'GARION1_ei.ogg', -- fast ledge climb
    [CHAR_SOUND_UH2_2] = 'GARION1_mu.ogg', -- Landing after Long Jump
    [CHAR_SOUND_WAAAOOOW] = 'GARION1_ohh.ogg', -- Falling
    [CHAR_SOUND_WAH2] = 'GARION1_ei2.ogg', -- Throw Object
    [CHAR_SOUND_WHOA] = 'GARION1_ara2.ogg', -- Ledge Grab
    [CHAR_SOUND_YAHOO] = 'GARION1_ikimasuyo2.ogg', -- Long Jump
    [CHAR_SOUND_YAHOO_WAHA_YIPPEE] = 'GARION1_aramaa2.ogg', -- 3rd Jump(s)
    [CHAR_SOUND_YAH_WAH_HOO] = {'GARION1_fun.ogg', 'GARION1_ya.ogg', 'GARION1_ya2.ogg'}, -- 1st Jump(s)
    [CHAR_SOUND_YAWNING] = 'GARION1_fuu.ogg',
}


local character = character_allocate("gal")
character.modelId = E_MODEL_GARION

for k, v in pairs(se_table_garion) do
    if type(v) == "string" then
        character_add_sound(character, k, v)
    elseif type(v) == "table" then
        for i = 1, #v do
            if type(v[i]) == "string" then
                character_add_sound(character, k, v[i])
            end
        end
    end
end

i used your example as a base and just repurposed this character i already had for a test

@EmeraldLoc
Copy link
Contributor Author

EmeraldLoc commented Feb 20, 2026

Your implementation looks good. What's being printed to the console? Are you hosting with any other mods?

@EmeraldLoc
Copy link
Contributor Author

I was able to reproduce the issue, and it's quite an annoying one. Will take a bit to fix, but have an idea in mind for doing so.

@EmeraldLoc
Copy link
Contributor Author

Issue should be fixed now

@ucuckic
Copy link

ucuckic commented Feb 21, 2026

the issue is fixed but a new observation: when a character plays custom sounds they dont cancel out the previous character sound when the next one plays (as mario himself typically does) so the previous sound will continue playing and the new sound will play over the previous.

if you fix this, likely you will then run into the classic issue of it being impossible to initialize individual unique miniaudio sounds. consequently, any two people playing the same character will kill eachothers samples when they begin new actions since you cant make unique instances of existing loaded modaudio

@AgentXLP
Copy link
Contributor

It's so peak

@EmeraldLoc
Copy link
Contributor Author

K, this is pretty much feature complete for the most part. Any recommendations, requests, or bug reports are welcomed here still. Did a lot of testing today and everything appears to be working good.

the issue is fixed but a new observation: when a character plays custom sounds they dont cancel out the previous character sound when the next one plays

As you point out later in your comment, yea, this is one hell of a "bug" to fix. I won't be fixing it in this pr unless it doesn't get merged because of it, as it'll require a LOT of work to get it working properly, and a lot of refactoring, so it's kind of outside the scope of this pr (but technically within scope).

@EmeraldLoc EmeraldLoc marked this pull request as ready for review February 28, 2026 00:45
@Squishy6094
Copy link

As of writing I'm on latest commit and I can't seem to get character_set_hud_head_texture nor it's allocated character variable couterpart working, I assume the feature has been implemented but it's just the Mario Icon :/

@AgentXLP
Copy link
Contributor

AgentXLP commented Mar 4, 2026

I don't see Character Select as necessary as it once was anymore with this new PR for a built-in character API.

@Squishy6094
Copy link

Try staying on topic next time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants