-- name: Shrink Mario -- description: Mario becomes mini-sized if his health drops to 2 bars. Also restricts his moveset (including object grabbing) and makes his voice higher pitched like in some games. local prevhealth = {} local resizetimer = {} local sizechange = {} for i = 0, (MAX_PLAYERS - 1) do prevhealth[i] = 0x880 resizetimer[i] = 0 sizechange[i] = nil end --- @param hookEventType LuaHookedEventType local function create_hook_wrapper(hookEventType) local callbacks = {} hook_event(hookEventType, function(...) for _, func in pairs(callbacks) do func(...) end end) return function(func) table.insert(callbacks, func) end end local hook_mario_update = create_hook_wrapper(HOOK_MARIO_UPDATE) -- Shrink Mario hook_mario_update(function(m) local i = m.playerIndex local health = m.health if health <= 0x300 and prevhealth[i] > 0x300 then resizetimer[i] = 30 sizechange[i] = "small" if m.action ~= ACT_DEATH_EXIT then play_sound(SOUND_MENU_ENTER_PIPE, m.marioObj.header.gfx.cameraToObject) end elseif health > 0x300 and prevhealth[i] <= 0x300 then resizetimer[i] = 30 sizechange[i] = "big" play_sound(SOUND_MENU_EXIT_PIPE, m.marioObj.header.gfx.cameraToObject) end prevhealth[i] = health end) -- Mini Mario Speed local function mario_before_phys_step(m) local hScale = 1.0 local vScale = 1.0 local s = gPlayerSyncTable[m.playerIndex] if not s.minimario then return end if m.action == ACT_WALKING then hScale = hScale * 1.70 end if m.action == ACT_JUMP then if m.marioObj.header.gfx.animInfo.animFrame == 1 then if m.vel.y > 0 then vScale = vScale * 1.50 end end end m.vel.x = m.vel.x * hScale m.vel.y = m.vel.y * vScale m.vel.z = m.vel.z * hScale end hook_event(HOOK_BEFORE_PHYS_STEP, mario_before_phys_step) local function restrictmoves(m, action) local s = gPlayerSyncTable[m.playerIndex] if not s.minimario then return end if action == ACT_WALL_KICK_AIR or action == ACT_CLIMBING_POLE or action == ACT_HOLDING_POLE or action == ACT_GRAB_POLE_SLOW or action == ACT_GRAB_POLE_FAST or action == ACT_TOP_OF_POLE or action == ACT_HOLD_IDLE or action == ACT_RIDING_HOOT or action == ACT_CLIMBING_POLE then return ACT_FORWARD_AIR_KB end if action == ACT_JUMP_KICK or action == ACT_DIVE or action == ACT_SLIDE_KICK or action == ACT_LONG_JUMP or action == ACT_BACKFLIP or action == ACT_GROUND_POUND or action == ACT_SIDE_FLIP then return 1 end if action == ACT_DOUBLE_JUMP_LAND or action == ACT_DOUBLE_JUMP_LAND_STOP or action == ACT_TRIPLE_JUMP_LAND or action == ACT_TRIPLE_JUMP_LAND_STOP then return ACT_SOFT_FORWARD_GROUND_KB end if action == ACT_JUMP_LAND then return ACT_JUMP_LAND_STOP end return mario_stop_riding_and_holding(m) end hook_event(HOOK_BEFORE_SET_MARIO_ACTION, restrictmoves) local function restrictactions(m, o, type, value) local s = gPlayerSyncTable[m.playerIndex] if not s.minimario then return end if (type & INTERACT_TEXT) ~= 0 then return false end if (type & INTERACT_KOOPA_SHELL) ~= 0 then return false end if (type & INTERACT_GRABBABLE) ~= 0 then return false end end hook_event(HOOK_ALLOW_INTERACT, restrictactions) --Pitched voice local get_char_sound = function(m, sound) local character = m.character if sound == CHAR_SOUND_YAH_WAH_HOO then return character.soundYahWahHoo + (math.random(0, 2) << 16) end if sound == CHAR_SOUND_HOOHOO then return character.soundHoohoo end if sound == CHAR_SOUND_YAHOO then return character.soundYahoo end if sound == CHAR_SOUND_UH then return character.soundUh end if sound == CHAR_SOUND_HRMM then return character.soundHrmm end if sound == CHAR_SOUND_WAH2 then return character.soundWah2 end if sound == CHAR_SOUND_WHOA then return character.soundWhoa end if sound == CHAR_SOUND_EEUH then return character.soundEeuh end if sound == CHAR_SOUND_ATTACKED then return character.soundAttacked end if sound == CHAR_SOUND_OOOF then return character.soundOoof end if sound == CHAR_SOUND_OOOF2 then return character.soundOoof2 end if sound == CHAR_SOUND_HERE_WE_GO then return character.soundHereWeGo end if sound == CHAR_SOUND_YAWNING then return character.soundYawning end if sound == CHAR_SOUND_SNORING1 then return character.soundSnoring1 end if sound == CHAR_SOUND_SNORING2 then return character.soundSnoring2 end if sound == CHAR_SOUND_WAAAOOOW then return character.soundWaaaooow end if sound == CHAR_SOUND_HAHA then return character.soundHaha end if sound == CHAR_SOUND_HAHA_2 then return character.soundHaha_2 end if sound == CHAR_SOUND_UH2 then return character.soundUh2 end if sound == CHAR_SOUND_UH2_2 then return character.soundUh2_2 end if sound == CHAR_SOUND_ON_FIRE then return character.soundOnFire end if sound == CHAR_SOUND_DYING then return character.soundDying end if sound == CHAR_SOUND_PANTING_COLD then return character.soundPantingCold end if sound == CHAR_SOUND_PANTING then return character.soundPanting end if sound == CHAR_SOUND_COUGHING1 then return character.soundCoughing1 end if sound == CHAR_SOUND_COUGHING2 then return character.soundCoughing2 end if sound == CHAR_SOUND_COUGHING3 then return character.soundCoughing3 end if sound == CHAR_SOUND_PUNCH_YAH then return character.soundPunchYah end if sound == CHAR_SOUND_PUNCH_HOO then return character.soundPunchHoo end if sound == CHAR_SOUND_MAMA_MIA then return character.soundMamaMia end if sound == CHAR_SOUND_GROUND_POUND_WAH then return character.soundGroundPoundWah end if sound == CHAR_SOUND_DROWNING then return character.soundDrowning end if sound == CHAR_SOUND_PUNCH_WAH then return character.soundPunchWah end if sound == CHAR_SOUND_YAHOO_WAHA_YIPPEE then return character.soundYahooWahaYippee + (math.random(0, 4) << 16) end if sound == CHAR_SOUND_DOH then return character.soundDoh end if sound == CHAR_SOUND_GAME_OVER then return character.soundGameOver end if sound == CHAR_SOUND_HELLO then return character.soundHello end if sound == CHAR_SOUND_PRESS_START_TO_PLAY then return character.soundPressStartToPlay end if sound == CHAR_SOUND_TWIRL_BOUNCE then return character.soundTwirlBounce end if sound == CHAR_SOUND_SNORING3 then return character.soundSnoring3 end if sound == CHAR_SOUND_SO_LONGA_BOWSER then return character.soundSoLongaBowser end if sound == CHAR_SOUND_IMA_TIRED then return character.soundImaTired end if sound == CHAR_SOUND_LETS_A_GO then return character.soundLetsAGo end if sound == CHAR_SOUND_OKEY_DOKEY then return character.soundOkeyDokey end return sound end hook_event(HOOK_CHARACTER_SOUND, function(m, pitchedvoice) if m.flags & MARIO_METAL_CAP ~= 0 then return end local s = gPlayerSyncTable[m.playerIndex] if s.minimario and m.character.type == CT_MARIO then local soundId = get_char_sound(m, pitchedvoice) play_sound_with_freq_scale(soundId, m.marioObj.header.gfx.cameraToObject, m.character.soundFreqScale * 1.35) return 0 elseif s.minimario then local soundId = get_char_sound(m, pitchedvoice) play_sound_with_freq_scale(soundId, m.marioObj.header.gfx.cameraToObject, m.character.soundFreqScale * 1.05) return 0 end end) -- Mini Size hook_mario_update(function(m) local i = m.playerIndex local s = gPlayerSyncTable[i] local scale = m.marioObj.header.gfx.scale if resizetimer[i] > 0 then resizetimer[i] = resizetimer[i] - 1 local scaling = ((resizetimer[i] % 6) < 3) and 1.0 or 0.5 if scale.x > scaling then scale.x = scaling end if scale.y > scaling then scale.y = scaling end if scale.z > scaling then scale.z = scaling end if resizetimer[i] == 0 then if sizechange[i] == "small" then if (m.flags & MARIO_METAL_CAP) == 0 and m.action ~= ACT_DEATH_EXIT then local soundId = get_char_sound(m, CHAR_SOUND_MAMA_MIA) play_sound_with_freq_scale(soundId, m.marioObj.header.gfx.cameraToObject, m.character.soundFreqScale * 1.35) end s.minimario = true elseif sizechange[i] == "big" then s.minimario = false end sizechange[i] = nil end elseif s.minimario then if scale.x > 0.5 then scale.x = 0.5 end if scale.y > 0.5 then scale.y = 0.5 end if scale.z > 0.5 then scale.z = 0.5 end end end)