Merge branch 'coop' into coopnet

This commit is contained in:
MysterD 2023-04-14 10:53:58 -07:00
commit 6c7e7778d1
69 changed files with 563 additions and 290 deletions

View file

@ -11522,7 +11522,7 @@ MAX_LOCAL_VERSION_LENGTH = 12
MAX_VERSION_LENGTH = 10
--- @type integer
MINOR_VERSION_NUMBER = 0
MINOR_VERSION_NUMBER = 1
--- @type integer
PATCH_VERSION_NUMBER = 0

View file

@ -222,8 +222,12 @@ function djui_hud_render_texture_tile_interpolated(texInfo, prevX, prevY, prevSc
end
--- @param levelNum number
--- @param func fun(areaNum:number, bhv:table)
--- @param func fun(areaIndex:number, bhvData:table, macroBhvIds:table, macroBhvArgs:table)
--- @return nil
--- When `func` is called, arguments are filled depending on the level command:
--- - `AREA` command: only `areaIndex` is filled. It's a number.
--- - `OBJECT` command: only `bhvData` is filled. `bhvData` is a table with two fields: `behavior` and `behaviorArg`.
--- - `MACRO` command: only `macroBhvIds` and `macroBhvArgs` are filled. `macrobhvIds` is a list of behavior ids. `macroBhvArgs` is a list of behavior params. Both lists have the same size and start at index 0.
function level_script_parse(levelNum, func)
-- ...
end

View file

@ -2,47 +2,47 @@
CONNECTED = "@ se ha conectado"
DISCONNECTED = "@ se ha desconectado"
LEFT_THIS_LEVEL = "@ ha salido del nivel"
ENTERED_THIS_LEVEL = "@ ha entrado al nivel"
ENTERED = "@ se ha unido\n#"
SERVER_CLOSED = "\\#ffa0a0\\Desconectado:\\#dcdcdc\\ servidor cerrado"
ENTERED_THIS_LEVEL = "@ se ha unido a tu nivel"
ENTERED = "@ ha entrado a \n#"
SERVER_CLOSED = "\\#ffa0a0\\Desconectado:\\#dcdcdc\\ El servidor ha sido cerrado."
DISCORD_ERROR = "Discord ha lanzado un error.\nPara solucionarlo, intenta: \n1. Cerrar el juego.\n2. Reiniciar Discord.\n3. Iniciar el juego."
DISCORD_DETECT = "\\#ffa0a0\\Error:\\#c8c8c8\\ No se ha podido detectar Discord.\n\\#a0a0a0\\Prueba a cerrar el juego, reiniciar Discord, e iniciar el juego otra vez."
DISCONNECT_FULL = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ La partida está llena."
DISCONNECT_KICK = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ Has sido expulsado del servidor."
DISCONNECT_BAN = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ Has sido vetado del servidor."
DISCONNECT_REJOIN = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ Uniendose de nuevo..."
DISCONNECT_CLOSED = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ El anfitrión ha cerrado la conexion."
DISCONNECT_BIG_MOD = "El servidor tenía un mod demasiado pesado.\nSaliendo."
DIED = "@ ha muerto"
DEBUG_FLY = "@ está en estado de vuelo libre debug"
IMPORT_MOD_SUCCESS = "\\#a0ffa0\\Mod \n\\#c8c8c8\\'@'\n\\#a0ffa0\\Importado"
IMPORT_DYNOS_SUCCESS = "\\#a0ffa0\\DynOS pack \n\\#c8c8c8\\'@'\n\\#a0ffa0\\Importado"
IMPORT_FAIL = "\\#ffa0a0\\Fallo al importar \\#c8c8c8\\\n'@'"
IMPORT_FAIL_INGAME = "\\#ffa0a0\\No se puede importar mientras se está en juego"
DISCONNECT_FULL = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ La partida está llena"
DISCONNECT_KICK = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ has sido\nexpulsado del servidor"
DISCONNECT_BAN = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ has sido\nbaneado del servidor"
DISCONNECT_REJOIN = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ Uniéndose de nuevo..."
DISCONNECT_CLOSED = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ El alfitrión ha cerrado el servidor"
DISCONNECT_BIG_MOD = "\\#ffa0a0\\Desconectado:\\#c8c8c8\\ El servidor tenía\nun mod demasiado pesado"
DIED = "@ ha muerto."
DEBUG_FLY = "@ Está en estado de vuelo libre debug."
IMPORT_MOD_SUCCESS = "El mod \\#c8c8c8\\'@'\\#a0ffa0\\\nha sido importado con éxito."
IMPORT_DYNOS_SUCCESS = "El pack de DynOS \\#c8c8c8\\'@'\\#a0ffa0\\\nha sido importado con éxito."
IMPORT_FAIL = "\n\\#ffa0a0\\Error al importar archivo. \\#c8c8c8\\\n'@'"
IMPORT_FAIL_INGAME = "\\#ffa0a0\\No se pueden importar archivos\nen medio de una partida."
[CHAT]
KICKING = Expulsando a '@'!"
BANNING = Vetando a '@'!"
SERVER_ONLY = "Solo el servidor puede usar este comando."
PERM_BANNING = Vetando permanentemente a '@'!"
ADD_MODERATOR = Añadiendo a '@' como Moderador!"
KICKING = '@' ha sido expulsado!"
BANNING = '@' ha sido baneado!"
SERVER_ONLY = "Solo el anfitrión puede usar este comando."
PERM_BANNING = '@' ha sido baneado permanentemente!"
ADD_MODERATOR = '@' ahora es un moderador!"
PLAYERS = "Jugadores"
NO_PERMS = "No tienes permiso para usar este comando."
PLAYER_NOT_FOUND = "No se ha podido encontrar al jugador."
SELF_KICK = "No te puedes expulsar a tí mismo."
SELF_BAN = "No te puedes vetar a tí mismo."
SELF_MOD = "No te puedes hacerte moderador a tí mismo."
KICK_CONFIRM = "¿Seguro que quieres expulsar a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para expusar."
BAN_CONFIRM = "¿Seguro que quieres vetar a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para vetar."
PERM_BAN_CONFIRM = "¿Seguro que quieres vetar permanentemente a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para vetar."
MOD_CONFIRM = "¿Seguro que quieres convertir a '@' en moderador?\Escribe '\\#a0ffa0\\/confirm\\#fff982\\'."
PLAYERS_DESC = "/players - Mostrar lista de todos los jugadores y sus IDs"
KICK_DESC = "/kick [NAME|ID] - Expulsar al jugador de la partida actual"
BAN_DESC = "/ban [NAME|ID] - Vetar al jugador de la partida actual"
PERM_BAN_DESC = "/permban [NAME|ID] - Vetar al jugador de todas tus partidas"
MOD_DESC = "/moderator [NAME|ID] - Permitir a este jugador usar comandos como /kick, /ban o /permban de cualquier juego que alojes"
UNRECOGNIZED = "Comando de chat desconocido."
MOD_GRANTED = "\\#fff982\\Ahora eres un Moderador."
SELF_BAN = "No te puedes banear a tí mismo."
SELF_MOD = "No puedes hacerte moderador a tí mismo."
KICK_CONFIRM = "¿Seguro que quieres expulsar a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para expulsar."
BAN_CONFIRM = "¿Seguro que quieres banear a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para banear."
PERM_BAN_CONFIRM = "¿Seguro que quieres banear permanentemente a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para banear."
MOD_CONFIRM = "¿Seguro que quieres hacer moderador a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\'."
PLAYERS_DESC = "/players - Muestra la lista de todos los jugadores y sus IDs."
KICK_DESC = "/kick [NAME|ID] - Expulsa al jugador de la partida actual."
BAN_DESC = "/ban [NAME|ID] - Banea al jugador de la partida actual."
PERM_BAN_DESC = "/permban [NAME|ID] - Banea al jugador de todas tus partidas."
MOD_DESC = "/moderator [NAME|ID] - Permite a un jugador usar comandos como /kick, /ban o /permban de cualquier partida que crees."
UNRECOGNIZED = "Comando desconocido."
MOD_GRANTED = "\\#fff982\\Ahora eres un moderador."
[MENU]
BACK = "Volver"
@ -52,37 +52,37 @@ YES = "Sí"
[CAMERA]
CAMERA = "CÁMARA"
FREE_CAMERA = "Cámara Libre"
ANALOG_CAMERA = "Cámara Analógica"
MOUSE_LOOK = "Moviemiento con Ratón"
FREE_CAMERA = "Cámara libre"
ANALOG_CAMERA = "Cámara analógica"
MOUSE_LOOK = "Movimiento con mouse"
INVERT_X = "Invertir eje X"
INVERT_Y = "Invertir eje Y"
X_SENSITIVITY = "Sensibilidad Eje X"
Y_SENSITIVITY = "Sensibilidad Eje Y"
AGGRESSION = "Agresíon"
PAN_LEVEL = "Nivel Seguimiento"
X_SENSITIVITY = "Sensibilidad eje X"
Y_SENSITIVITY = "Sensibilidad eje Y"
AGGRESSION = "Agresn"
PAN_LEVEL = "Nivel de seguimiento"
DECELERATION = "Deceleración"
[CHEATS]
CHEATS = "TRUCOS"
MOON_JUMP = "Salto Lunar"
MOON_JUMP = "Salto lunar"
GOD_MODE = "Modo Dios"
INFINITE_LIVES = "Vidas Ilimitadas"
SUPER_SPEED = "Super Velocidad"
RESPONSIVE_CONTROLS = "Controles Responsivos"
RAPID_FIRE = "Pulsación Rápida (A)"
BLJ_ANYWHERE = "BLJ en cualquier parte"
ALWAYS_TRIPLE_JUMP = "Siempre hacer Triple Salto"
INFINITE_LIVES = "Vidas infinitas"
SUPER_SPEED = "Super velocidad"
RESPONSIVE_CONTROLS = "Controles responsivos"
RAPID_FIRE = "Pulsación rápida (A)"
BLJ_ANYWHERE = "BLJ donde sea"
ALWAYS_TRIPLE_JUMP = "Siempre hacer triple salto"
[CONTROLS]
CONTROLS = "CONTROLES"
N64_BINDS = "Asignaciones N64"
EXTRA_BINDS = "Asignaciones Extra"
N64_BINDS = "Botones N64"
EXTRA_BINDS = "Botones Extra"
BACKGROUND_GAMEPAD = "Mando en segundo plano"
GAMEPAD = "Mando"
DEADZONE = "Zona muerta"
RUMBLE_STRENGTH = "Fuerza de Vibración"
RUMBLE_STRENGTH = "Fuerza de vibración"
CHAT = "Chat"
PLAYERS = "Jugadores"
@ -111,12 +111,12 @@ C_RIGHT = "C Derecha"
[DISPLAY]
DISPLAY = "PANTALLA"
FULLSCREEN = "Pantalla completa"
PRELOAD_TEXTURES = "Precargar Texturas"
VSYNC = "Sincronización Vertical"
PRELOAD_TEXTURES = "Precargar texturas"
VSYNC = "Sincronización vertical"
UNCAPPED_FRAMERATE = "FPS sin límite"
FRAME_LIMIT = "Límite de FPS"
FAST = "Rápido"
ACCURATE = "Preciso"
FAST = "Rápida"
ACCURATE = "Precisa"
INTERPOLATION = "Interpolación"
NEAREST = "Más cercano"
LINEAR = "Lineal"
@ -128,33 +128,33 @@ D1P5X = "1.5x"
D3X = "3x"
D10X = "10x"
D100X = "100x"
DRAW_DISTANCE = "Distancia de Dibujado"
DYNOS_PACKS = "Packs DynOS"
DRAW_DISTANCE = "Distancia de dibujado"
DYNOS_PACKS = "Packs de DynOS"
[DYNOS]
DYNOS = "DYNOS"
[HOST_MESSAGE]
INFO_TITLE = "INFO"
WARN_DISCORD = "Invita a amigos haciendo click derecho en su nombre en Discord y seleccionando\n'\\#d0d0ff\\Invitar a unirse\\#c8c8c8\\'.\n\nPuedes invitar en canales de un servidor también presionando el\nbotón \\#d0d0ff\\+\\#c8c8c8\\ al lado del cuadro de texto del chat.\n\nEl estado de Actividad Actual \\#ffa0a0\\debe estar\\#c8c8c8\\ activado en tus \najustes de Discord.\n\nEstár invisible \\#ffa0a0\\te prevendrá\\#c8c8c8\\ de crear invitaciones."
WARN_DISCORD2 = "\\#ffa0a0\\Error:\\#c8c8c8\\ No se ha detectado a Discord.\n\n\\#a0a0a0\\Prueba a cerrar el juego,\nreiniciar Discord,\ny abrir el juego de nuevo."
WARN_SOCKET = "Las conexiones directas \\#ffa0a0\\requieren\\#c8c8c8\\ que abras los puertos en tu rúter.\n\nAbre el puerto '\\#d0d0ff\\%d\\#c8c8c8\\' con protocolo UDP."
HOST = "Alojar"
WARN_DISCORD = "Invita a amigos haciendo click derecho en su nombre en Discord y seleccionando\n'\\#d0d0ff\\Invitar a unirse\\#c8c8c8\\'.\n\nPuedes invitar en canales de un servidor también presionando el botón \\#d0d0ff\\+\\#c8c8c8\\ al lado del cuadro de texto del chat.\n\nEl estado de Actividad Actual \\#ffa0a0\\debe estar\\#c8c8c8\\ activado en tus ajustes de Discord.\n\nEstar invisible \\#ffa0a0\\te prevendrá\\#c8c8c8\\ de crear invitaciones."
WARN_DISCORD2 = "\\#ffa0a0\\Error:\\#c8c8c8\\ No se ha detectado Discord.\n\n\\#a0a0a0\\Prueba a cerrar el juego,\nreiniciar Discord,\ny abrir el juego de nuevo."
WARN_SOCKET = "Las conexiones directas \\#ffa0a0\\requieren\\#c8c8c8\\ que abras los puertos en tu router.\n\nAbre el puerto '\\#d0d0ff\\%d\\#c8c8c8\\' con protocolo UDP."
HOST = "Crear"
[HOST_MODS]
ROMHACKS = "ROMHACKS"
MODS = "MODS"
[HOST_SAVE]
SAVE_TITLE = "GUARDAR"
SAVE_TITLE = "RANURAS DE\nGUARDADO"
ERASE_TITLE = "BORRAR"
CONFIRM = "¿Seguro que quieres borrar esta partida?"
ERASE = "Borrar"
[HOST_SETTINGS]
SETTINGS = "AJUSTES"
NONSOLID = "Intangible"
SOLID = "Tangible"
NONSOLID = "No Sólida"
SOLID = "Sólida"
FRIENDLY_FIRE = "Fuego Amigo"
PLAYER_INTERACTION = "Interacción entre jugadores"
WEAK = "Poca"
@ -163,7 +163,7 @@ TOO_MUCH = "Demasiada"
KNOCKBACK_STRENGTH = "Fuerza de retroceso"
LEAVE_LEVEL = "Salir del nivel"
STAY_IN_LEVEL = "Seguir en el nivel"
NONSTOP = "Siguiente misión"
NONSTOP = "Sin parar"
ON_STAR_COLLECTION = "Al conseguir una estrella"
SKIP_INTRO_CUTSCENE = "Saltar cinemática de introducción"
SHARE_LIVES = "Compartir vidas"
@ -172,33 +172,33 @@ BUBBLE_ON_DEATH = "Burbuja al morir"
AMOUNT_OF_PLAYERS = "Número de jugadores"
[HOST]
SERVER_TITLE = "SERVIDOR"
HOST_TITLE = "ALOJAR"
SERVER_TITLE = "PARTIDA"
HOST_TITLE = "CREAR"
DISCORD = "Discord"
COOPNET = "CoopNet"
DIRECT_CONNECTION = "Conexión Directa"
NETWORK_SYSTEM = "Modo de conexión"
PORT = "Puerto"
SAVE_SLOT = "Ranura de Guardado"
SAVE_SLOT = "Ranuras"
SETTINGS = "Ajustes"
MODS = "Mods"
ROMHACKS = "Rom-Hacks"
APPLY = "Aplicar"
HOST = "Alojar"
HOST = "Crear"
[JOIN_MESSAGE]
JOINING = "UNIENDOSE"
JOINING = "UNIÉNDOSE"
[JOIN]
JOIN_TITLE = "UNIRSE"
JOIN_DISCORD = "Para unirte a un lobby en \\#d0d0ff\\Discord\\#c8c8c8\\:\n\nManten el juego abierto y acepta la invitación.\n\nSi la invitación dice que la partida ha terminado, haz click en el nombre de la persona que te invitó para refrescarla."
JOIN_SOCKET = "Introduce la IP y el puerto de \\#d0d0ff\\conexión directa\\#c8c8c8\\:"
JOIN_DISCORD = "Para unirte a un lobby en \\#d0d0ff\\Discord\\#c8c8c8\\:\n\nMantén el juego abierto y acepta la invitación.\n\nSi la invitación dice que la partida ha terminado, haz click en el nombre de la persona que te invitó para\nrefrescarla."
JOIN_SOCKET = "Introduce la IP y el puerto de la \\#d0d0ff\\conexión directa\\#c8c8c8\\:"
JOIN = "Unirse"
[MAIN]
QUIT_TITLE = "SALIR"
QUIT_CONFIRM = "¿Seguro que quieres salir?"
HOST = "Alojar"
HOST = "Crear"
JOIN = "Unirse"
OPTIONS = "Opciones"
QUIT = "Salir"
@ -206,9 +206,9 @@ QUIT = "Salir"
[MENU_OPTIONS]
MAIN_MENU = "MENÚ PRINCIPAL"
LEVEL = "Nivel"
USE_STAGE_MUSIC = "Usar Música del Nivel"
RANDOM_STAGE = "Nivel Aleatório"
PLAY_VANILLA_DEMOS = "Reproducir Demostraciones Vanilla"
USE_STAGE_MUSIC = "Usar música del nivel"
RANDOM_STAGE = "Nivel aleatorio"
PLAY_VANILLA_DEMOS = "Demos originales"
[MISC]
DEBUG_TITLE = "DEPURACIÓN"
@ -217,10 +217,10 @@ LUA_PROFILER = "Perfilador de Lua"
DEBUG_PRINT = "Mensajes de Depuración"
DEBUG_INFO = "Información de Depuración"
DEBUG_ERRORS = "Errores de Depuración"
MISC_TITLE = "MISCELÁNEO"
PAUSE_IN_SINGLEPLAYER = "Pausa en Modo de Un jugador"
DISABLE_POPUPS = "Deshabilitar Mensajes Emergentes"
MENU_OPTIONS = "Opciones del Menú"
MISC_TITLE = "OTROS"
PAUSE_IN_SINGLEPLAYER = "Pausa en modo de un jugador"
DISABLE_POPUPS = "Deshabilitar mensajes emergentes"
MENU_OPTIONS = "Opciones del menú"
DEBUG = "Depuración"
LANGUAGE = "Idioma"
@ -234,26 +234,26 @@ CAMERA = "Cámara"
CONTROLS = "Controles"
DISPLAY = "Pantalla"
SOUND = "Sonido"
MISC = "Misceláneo"
MISC = "Otros"
[PAUSE]
QUIT_TITLE = "SALIR"
QUIT_HOST = "¿Seguro que quieres dejar de alojar?"
QUIT_HOST = "¿Seguro que quieres finalizar la partida?"
QUIT_CLIENT = "¿Seguro que te quieres desconectar?"
PAUSE_TITLE = "PAUSA"
PLAYER = "Jugador"
DYNOS_PACKS = "Packs DynOS"
DYNOS_PACKS = "Packs de DynOS"
OPTIONS = "Opciones"
CHEATS = "Trucos"
SERVER_SETTINGS = "Ajustes del Servidor"
SERVER_SETTINGS = "Ajustes de la partida"
RESUME = "Continuar"
STOP_HOSTING = "Dejar de Alojar"
STOP_HOSTING = "Finalizar partida"
DISCONNECT = "Desconectarse"
[PLAYER]
PLAYER_TITLE = "JUGADOR"
OVERALLS = "Tirantes"
SHIRT = "Camisa"
OVERALLS = "Overoles"
SHIRT = "Camiseta"
GLOVES = "Guantes"
SHOES = "Zapatos"
HAIR = "Pelo"
@ -268,7 +268,7 @@ BLUE = "Azul"
PLAYER = "Jugador"
NAME = "Nombre"
MODEL = "Modelo"
PALETTE_PRESET = "Perfil de Paleta"
PALETTE_PRESET = "Paletas predeterminadas"
EDIT_PALETTE = "Editar Paleta"
[PALETTE]
@ -304,20 +304,20 @@ RASPBERRY = "Frambuesa"
BUBBLEGUM = "Chicle"
ICE_MARIO = "Mario de Hielo"
ICE_LUIGI = "Luigi de Hielo"
CUSTOM = "Personalizado"
CUSTOM = "Personalizada"
[PLAYER_LIST]
PLAYERS = "JUGADORES"
NAME = "nombre"
LOCATION = "localización"
ACT = "recorrido"
ACT = "acto"
[SOUND]
SOUND = "SONIDO"
MASTER_VOLUME = "Volumen Maestro"
MUSIC_VOLUME = "Volumen Música"
SFX_VOLUME = "Volumen Efectos de Sonido"
ENV_VOLUME = "Volumen Entorno"
MASTER_VOLUME = "Volumen General"
MUSIC_VOLUME = "Volumen de Música"
SFX_VOLUME = "Volumen de Efectos de Sonido"
ENV_VOLUME = "Volumen de Entorno"
[LANGUAGE]
LANGUAGE = "IDIOMA"

View file

@ -28,6 +28,14 @@ for i = 0, (MAX_PLAYERS - 1) do
s.rank = 0
end
local sKnockbackActions = {
ACT_SOFT_FORWARD_GROUND_KB, ACT_FORWARD_GROUND_KB, ACT_HARD_FORWARD_GROUND_KB,
ACT_FORWARD_AIR_KB, ACT_FORWARD_AIR_KB, ACT_HARD_FORWARD_AIR_KB,
ACT_FORWARD_WATER_KB, ACT_FORWARD_WATER_KB, ACT_FORWARD_WATER_KB,
ACT_SOFT_BACKWARD_GROUND_KB, ACT_BACKWARD_GROUND_KB, ACT_HARD_BACKWARD_GROUND_KB,
ACT_BACKWARD_AIR_KB, ACT_BACKWARD_AIR_KB, ACT_HARD_BACKWARD_AIR_KB,
ACT_BACKWARD_WATER_KB, ACT_BACKWARD_WATER_KB, ACT_BACKWARD_WATER_KB
}
------------
-- hammer --
------------
@ -361,6 +369,27 @@ function mario_update(m)
local s = gPlayerSyncTable[m.playerIndex]
local np = gNetworkPlayers[m.playerIndex]
-- increase knockback animations
local animInfo = nil
if m.marioObj ~= nil then
animInfo = m.marioObj.header.gfx.animInfo
end
for i, value in ipairs(sKnockbackActions) do
if m.action == value then
local frame = animInfo.animFrame
local loopEnd = frame
if animInfo.curAnim ~= nil then
loopEnd = animInfo.curAnim.loopEnd
end
if frame < loopEnd - 2 then
frame = frame + 1
end
animInfo.animFrame = frame
end
end
-- clear invincibilities
m.invincTimer = 0
if m.knockbackTimer > 5 then

View file

@ -1163,7 +1163,7 @@ function act_walking(m)
end
function act_hold_walking(m)
if m.heldObj.behavior == bhvJumpingBox then
if m.heldObj ~= nil and m.heldObj.behavior == bhvJumpingBox then
return set_mario_action(m, ACT_CRAZY_BOX_BOUNCE, 0)
end

View file

@ -2195,27 +2195,46 @@ possibility.\
Good luck and\
frustration resistance.")
-- smlua_text_utils_dialog_replace(DIALOG_063,1,5,30,200, "It's really a shame but\
-- this level was way too\
-- big for the level importer\
-- so I had to split it\
-- into two parts.\
-- That means I CAN'T place\
-- red coins in the whole\
-- level. Sad, isn't it?\
-- I know that you would\
-- enjoy collecting 30\
-- red coins, right?\
-- Well then, instead,\
-- the red coins are all\
-- beyond the cannon.\
-- And since they are so\
-- close together\
-- I won't tell you how\
-- many there are.\
-- \
-- (Well, honestly, I forgot\
-- how many I placed.)")
smlua_text_utils_dialog_replace(DIALOG_063,1,5,30,200, "It's really a shame but\
this level was way too\
big for the level importer\
so I had to split it\
into two parts.\
That means I CAN'T place\
Nah! Just kidding!\
You're no longer playing\
a Nintendo 64 rom-hack.\
It's the pc port we're\
talking about!\
That means I CAN place\
red coins in the whole\
level. Sad, isn't it?\
level. Great, isn't it?\
I know that you would\
enjoy collecting 30\
red coins, right?\
Well then, instead,\
the red coins are all\
beyond the cannon.\
And since they are so\
close together\
I won't tell you how\
many there are.\
\
(Well, honestly, I forgot\
how many I placed.)")
red coins. So, after 9\
years, it's finally\
possible. Have fun!")
smlua_text_utils_dialog_replace(DIALOG_064,1,5,30,200, "You should already know\
the concept of this\

View file

@ -161,6 +161,8 @@ u32 get_mario_spawn_type(struct Object *o) {
}
struct ObjectWarpNode *area_get_warp_node(u8 id) {
if (!gCurrentArea || !gCurrentArea->warpNodes) { return NULL; }
struct ObjectWarpNode *node = NULL;
for (node = gCurrentArea->warpNodes; node != NULL; node = node->next) {

View file

@ -170,5 +170,5 @@ static void (*sBetaBooKeyActions[])(void) = { beta_boo_key_inside_boo_loop, beta
* Update function for bhvBetaBooKey.
*/
void bhv_beta_boo_key_loop(void) {
cur_obj_call_action_function(sBetaBooKeyActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBetaBooKeyActions);
}

View file

@ -555,7 +555,7 @@ void bhv_boo_loop(void) {
//PARTIAL_UPDATE
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sBooActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBooActions);
cur_obj_move_standard(78);
boo_approach_target_opacity_and_update_scale();
@ -793,7 +793,7 @@ void bhv_big_boo_loop(void) {
o->oGraphYOffset = o->oBooBaseScale * 60.0f;
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sBooGivingStarActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBooGivingStarActions);
cur_obj_move_standard(78);
boo_approach_target_opacity_and_update_scale();
@ -870,7 +870,7 @@ void bhv_boo_with_cage_loop(void) {
//PARTIAL_UPDATE
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sBooWithCageActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBooWithCageActions);
cur_obj_move_standard(78);
boo_approach_target_opacity_and_update_scale();

View file

@ -59,7 +59,7 @@ void bhv_bowser_tail_anchor_init(void) {
}
void bhv_bowser_tail_anchor_loop(void) {
cur_obj_call_action_function(sBowserTailAnchorActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBowserTailAnchorActions);
o->oParentRelativePosX = 90.0f;
if (o->parentObj->oAction == 4)
o->parentObj->oIntangibleTimer = -1;
@ -1204,7 +1204,7 @@ void bowser_free_update(void) {
o->oBowserUnk10E = 0;
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sBowserActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBowserActions);
cur_obj_move_standard(-78);
if (bowser_check_fallen_off_stage())
o->oAction = 2; // bowser go home?
@ -1657,7 +1657,7 @@ void bhv_falling_bowser_platform_loop(void) {
}
}
cur_obj_call_action_function(sFallingBowserPlatformActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sFallingBowserPlatformActions);
}
void bowser_flame_despawn(void) {

View file

@ -275,7 +275,7 @@ void (*sBowserPuzzlePieceActions[])(void) = {
void bhv_lll_bowser_puzzle_piece_loop(void) {
bhv_lll_bowser_puzzle_piece_update();
cur_obj_call_action_function(sBowserPuzzlePieceActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBowserPuzzlePieceActions);
o->oPosX = o->oBowserPuzzlePieceOffsetX + o->oHomeX;
o->oPosY = o->oBowserPuzzlePieceOffsetY + o->oHomeY;

View file

@ -28,7 +28,7 @@ void (*sBirdChirpChirpActions[])(void) = { bub_spawner_act_0, bub_spawner_act_1,
bub_spawner_act_2, bub_spawner_act_3 };
void bhv_bub_spawner_loop(void) {
cur_obj_call_action_function(sBirdChirpChirpActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBirdChirpChirpActions);
}
void bub_move_vertically(s32 a0) {
@ -136,7 +136,7 @@ void bhv_bub_loop(void) {
}
o->oWallHitboxRadius = 30.0f;
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sCheepCheepActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sCheepCheepActions);
cur_obj_move_using_fvel_and_gravity();
if (o->parentObj->oAction == 2)
obj_mark_for_deletion(o);

View file

@ -86,7 +86,7 @@ void (*sBulletBillActions[])(void) = { bullet_bill_act_0, bullet_bill_act_1, bul
bullet_bill_act_3, bullet_bill_act_4 };
void bhv_bullet_bill_loop(void) {
cur_obj_call_action_function(sBulletBillActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sBulletBillActions);
if (cur_obj_check_interacted())
o->oAction = 4;
}

View file

@ -237,7 +237,7 @@ void bhv_cannon_base_loop(void) {
cur_obj_push_mario_away_from_cylinder(220, 300);
}
cur_obj_call_action_function(sOpenedCannonActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sOpenedCannonActions);
if (o->oCannonUnkF8)
o->oCannonUnkF8++;
o->oInteractStatus = 0;

View file

@ -65,5 +65,5 @@ void bhv_cap_switch_loop(void) {
sync_object_init_field(o, &capSwitchForcePress);
}
cur_obj_call_action_function(sCapSwitchActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sCapSwitchActions);
}

View file

@ -193,7 +193,7 @@ void (*sChuckyaActions[])(void) = { chuckya_act_0, chuckya_act_1, chuckya_act_2,
void chuckya_move(void) {
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sChuckyaActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sChuckyaActions);
cur_obj_move_standard(-30);
if (o->oInteractStatus & INT_STATUS_GRABBED_MARIO) {
o->oAction = 1;

View file

@ -255,7 +255,7 @@ void coin_inside_boo_act_0(void) {
void (*sCoinInsideBooActions[])(void) = { coin_inside_boo_act_0, coin_inside_boo_act_1 };
void bhv_coin_inside_boo_loop(void) {
cur_obj_call_action_function(sCoinInsideBooActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sCoinInsideBooActions);
}
void bhv_coin_sparkles_loop(void) {

View file

@ -154,7 +154,7 @@ struct SpawnParticlesInfo D_8032F3FC = { 0, 5, MODEL_WHITE_PARTICLE_DL, 0,
2.0f, 2.0f };
void bhv_elevator_loop(void) {
cur_obj_call_action_function(sElevatorActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sElevatorActions);
// allow bubbled players to pass through
if (gMarioStates[0].action == ACT_BUBBLED) {

View file

@ -214,5 +214,5 @@ void bhv_exclamation_box_init(void) {
void bhv_exclamation_box_loop(void) {
cur_obj_scale(2.0f);
cur_obj_call_action_function(sExclamationBoxActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sExclamationBoxActions);
}

View file

@ -73,7 +73,7 @@ static void (*sFishSpawnerActions[])(void) = {
};
void bhv_fish_spawner_loop(void) {
cur_obj_call_action_function(sFishSpawnerActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sFishSpawnerActions);
}
/**
@ -276,7 +276,7 @@ void bhv_fish_loop(void)
}
// Call fish action methods and apply physics engine.
cur_obj_call_action_function(sFishActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sFishActions);
cur_obj_move_using_fvel_and_gravity();
// If the parent object has action set to two, then delete the fish object.

View file

@ -99,7 +99,7 @@ void (*sHeaveHoActions[])(void) = { heave_ho_act_0, heave_ho_act_1, heave_ho_act
void heave_ho_move(void) {
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sHeaveHoActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sHeaveHoActions);
cur_obj_move_standard(-78);
if (o->oMoveFlags & OBJ_MOVE_MASK_IN_WATER)
o->oGraphYOffset = -15.0f;

View file

@ -41,7 +41,7 @@ void jumping_box_free_update(void) {
obj_set_hitbox(o, &sJumpingBoxHitbox);
cur_obj_update_floor_and_walls();
cur_obj_move_standard(78);
cur_obj_call_action_function(sJumpingBoxActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sJumpingBoxActions);
}
void bhv_jumping_box_loop(void) {

View file

@ -365,7 +365,7 @@ void king_bobomb_move(void) {
cur_obj_move_standard(-78);
else
cur_obj_move_using_fvel_and_gravity();
cur_obj_call_action_function(sKingBobombActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sKingBobombActions);
exec_anim_sound_state(sKingBobombSoundStates);
s32 distanceToPlayer = dist_between_objects(o, gMarioStates[0].marioObj);
if (distanceToPlayer < 5000.0f * draw_distance_scalar())

View file

@ -60,7 +60,7 @@ void bhv_lll_rotating_block_fire_bars_loop(void) {
sync_object_init(o, 4000.0f);
sync_object_init_field(o, &o->oAngleVelYaw);
}
cur_obj_call_action_function(sRotatingCwFireBarsActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sRotatingCwFireBarsActions);
if (o->oBehParams2ndByte == 0)
load_object_collision_model();
}

View file

@ -33,7 +33,7 @@ void mr_i_piranha_particle_act_1(void) {
void (*sMrIParticleActions[])(void) = { mr_i_piranha_particle_act_0, mr_i_piranha_particle_act_1 };
void bhv_mr_i_particle_loop(void) {
cur_obj_call_action_function(sMrIParticleActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sMrIParticleActions);
}
void spawn_mr_i_particle(void) {
@ -283,7 +283,7 @@ void bhv_mr_i_loop(void) {
s32 distanceToPlayer = player ? dist_between_objects(o, player) : 10000;
obj_set_hitbox(o, &sMrIHitbox);
cur_obj_call_action_function(sMrIActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sMrIActions);
if (o->oAction != 3) {
if (distanceToPlayer > 3000.0f || o->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM) {
o->oAction = 0;

View file

@ -369,7 +369,7 @@ void bhv_piranha_plant_loop(void) {
cur_obj_set_hitbox_radius_and_height(150.0f, 100.0f);
cur_obj_set_hurtbox_radius_and_height(150.0f, 100.0f);
cur_obj_call_action_function(TablePiranhaPlantActions);
CUR_OBJ_CALL_ACTION_FUNCTION(TablePiranhaPlantActions);
// In WF, hide all Piranha Plants once high enough up.
if (gCurrLevelNum == LEVEL_WF) {
struct Object* player = gMarioStates[0].marioObj;

View file

@ -63,5 +63,5 @@ void bhv_grindel_thwomp_loop(void) {
sync_object_init_field(o, &o->oTimer);
sync_object_init_field(o, &o->oVelY);
}
cur_obj_call_action_function(sGrindelThwompActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sGrindelThwompActions);
}

View file

@ -85,6 +85,6 @@ void bhv_tox_box_loop(void) {
sync_object_init_field(o, &o->oToxBoxMovementStep);
}
}
cur_obj_call_action_function(sToxBoxActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sToxBoxActions);
load_object_collision_model();
}

View file

@ -164,5 +164,5 @@ void bhv_tumbling_bridge_loop(void) {
}
}
cur_obj_call_action_function(sTumblingBridgeActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sTumblingBridgeActions);
}

View file

@ -160,7 +160,7 @@ void bhv_tuxies_mother_loop(void) {
}
o->activeFlags |= ACTIVE_FLAG_UNK10;
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sTuxiesMotherActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sTuxiesMotherActions);
cur_obj_move_standard(-78);
play_penguin_walking_sound(PENGUIN_WALK_BIG);
o->oInteractStatus = 0;
@ -289,7 +289,7 @@ void small_penguin_free_actions(void) {
cur_obj_become_tangible();
cur_obj_enable_rendering();
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sSmallPenguinActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sSmallPenguinActions);
cur_obj_move_standard(-78);
play_penguin_walking_sound(PENGUIN_WALK_BABY);
}

View file

@ -149,7 +149,7 @@ void bhv_tweester_loop(void) {
}
obj_set_hitbox(o, &sTweesterHitbox);
cur_obj_call_action_function(sTweesterActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sTweesterActions);
o->oInteractStatus = 0;
}

View file

@ -504,7 +504,7 @@ void ukiki_free_loop(void) {
s32 steepSlopeAngleDegrees;
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sUkikiActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sUkikiActions);
if (o->oAction == UKIKI_ACT_GO_TO_CAGE || o->oAction == UKIKI_ACT_RETURN_HOME) {
steepSlopeAngleDegrees = -88;

View file

@ -103,5 +103,5 @@ void (*sUkikiCageActions[])(void) = {
* Main behavior loop for the cage. Only calls the relevant action.
*/
void bhv_ukiki_cage_loop(void) {
cur_obj_call_action_function(sUkikiCageActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sUkikiCageActions);
}

View file

@ -284,7 +284,7 @@ void bhv_whomp_loop(void) {
}
cur_obj_update_floor_and_walls();
cur_obj_call_action_function(sWhompActions);
CUR_OBJ_CALL_ACTION_FUNCTION(sWhompActions);
cur_obj_move_standard(-20);
if (o->oAction != 9) {
// o->oBehParams2ndByte here seems to be a flag

View file

@ -3297,11 +3297,6 @@ void soft_reset_camera(struct Camera* c) {
* Reset all the camera variables to their arcane defaults
*/
void reset_camera(struct Camera *c) {
UNUSED s32 unused = 0;
UNUSED u8 unused1[16];
UNUSED struct LinearTransitionPoint *start = &sModeInfo.transitionStart;
UNUSED struct LinearTransitionPoint *end = &sModeInfo.transitionEnd;
gCamera = c;
gCameraMovementFlags = 0;
s2ndRotateFlags = 0;
@ -3315,7 +3310,6 @@ void reset_camera(struct Camera *c) {
unused8032CFCC = 0;
gSecondCameraFocus = NULL;
sCButtonsPressed = 0;
vec3f_copy(sModeTransition.marioPos, sMarioCamState->pos);
sModeTransition.framesLeft = 0;
unused8032CFCC = -1;
unused8032CFC8 = -1;
@ -3340,11 +3334,19 @@ void reset_camera(struct Camera *c) {
sCSideButtonYaw = 0;
s8DirModeBaseYaw = 0;
s8DirModeYawOffset = 0;
if (c) {
c->doorStatus = DOOR_DEFAULT;
}
if (sMarioCamState) {
vec3f_copy(sModeTransition.marioPos, sMarioCamState->pos);
sMarioCamState->headRotation[0] = 0;
sMarioCamState->headRotation[1] = 0;
sMarioCamState->cameraEvent = 0;
sMarioCamState->usedObj = NULL;
}
gLakituState.shakeMagnitude[0] = 0;
gLakituState.shakeMagnitude[1] = 0;
gLakituState.shakeMagnitude[2] = 0;
@ -3355,12 +3357,14 @@ void reset_camera(struct Camera *c) {
gLakituState.unusedVec1[1] = 0.f;
gLakituState.unusedVec1[2] = 0.f;
gLakituState.lastFrameAction = 0;
set_fov_function(CAM_FOV_DEFAULT);
sFOVState.fov = 45.f;
sFOVState.fovOffset = 0.f;
sFOVState.unusedIsSleeping = 0;
sFOVState.shakeAmplitude = 0.f;
sFOVState.shakePhase = 0;
sObjectCutscene = 0;
gRecentCutscene = 0;
unused8033B30C = 0;

View file

@ -59,7 +59,7 @@ enum InteractionFlag {
(INT_SLIDE_KICK | INT_FAST_ATTACK_OR_SHELL)
u8 sDelayInvincTimer;
s16 sInvulnerable;
s16 gInteractionInvulnerable;
u32 interact_coin(struct MarioState *, u32, struct Object *);
u32 interact_water_ring(struct MarioState *, u32, struct Object *);
u32 interact_star_or_key(struct MarioState *, u32, struct Object *);
@ -824,7 +824,7 @@ u32 take_damage_from_interact_object(struct MarioState *m) {
u32 take_damage_and_knock_back(struct MarioState *m, struct Object *o) {
u32 damage;
if (!sInvulnerable && !(m->flags & MARIO_VANISH_CAP)
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)
&& !(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
o->oInteractStatus = INT_STATUS_INTERACTED | INT_STATUS_ATTACKED_MARIO;
m->interactObj = o;
@ -1309,7 +1309,7 @@ static u8 resolve_player_collision(struct MarioState* m, struct MarioState* m2)
velY = fmax(fmin(55.0f, 15.0f + fabs(m->vel[1])), 35.0f);
} else if (m->action == ACT_DOUBLE_JUMP) {
mario_stop_riding_and_holding(m);
set_mario_action(m, (m->specialTripleJump && m->playerIndex == 0) ? ACT_SPECIAL_TRIPLE_JUMP : ACT_TRIPLE_JUMP, 0);
set_mario_action(m, (m->specialTripleJump && m->playerIndex == 0) ? ACT_SPECIAL_TRIPLE_JUMP : m->flags & MARIO_WING_CAP ? ACT_FLYING_TRIPLE_JUMP : ACT_TRIPLE_JUMP, 0);
velY = fmax(fmin(60.0f, 20.0f + fabs(m->vel[1])), 40.0f);
} else {
mario_stop_riding_and_holding(m);
@ -1353,6 +1353,8 @@ u8 player_is_sliding(struct MarioState* m) {
}
u8 passes_pvp_interaction_checks(struct MarioState* attacker, struct MarioState* victim) {
if (!attacker || !victim) { return false; }
// attacked
u8 isInCutscene = ((attacker->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE) || ((victim->action & ACT_GROUP_MASK) == ACT_GROUP_CUTSCENE);
isInCutscene = isInCutscene || (attacker->action == ACT_IN_CANNON) || (victim->action == ACT_IN_CANNON);
@ -1587,7 +1589,7 @@ u32 interact_strong_wind(struct MarioState *m, UNUSED u32 interactType, struct O
u32 interact_flame(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
u32 burningAction = ACT_BURNING_JUMP;
if (!sInvulnerable && !(m->flags & MARIO_METAL_CAP) && !(m->flags & MARIO_VANISH_CAP)
if (!gInteractionInvulnerable && !(m->flags & MARIO_METAL_CAP) && !(m->flags & MARIO_VANISH_CAP)
&& !(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
queue_rumble_data_mario(m, 5, 80);
@ -1614,7 +1616,7 @@ u32 interact_flame(struct MarioState *m, UNUSED u32 interactType, struct Object
}
u32 interact_snufit_bullet(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!sInvulnerable && !(m->flags & MARIO_VANISH_CAP)) {
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)) {
if (m->flags & MARIO_METAL_CAP) {
o->oInteractStatus = INT_STATUS_INTERACTED | INT_STATUS_WAS_ATTACKED;
play_sound(SOUND_ACTION_UNKNOWN458, m->marioObj->header.gfx.cameraToObject);
@ -1679,7 +1681,7 @@ u32 interact_bully(struct MarioState *m, UNUSED u32 interactType, struct Object
return TRUE;
}
else if (!sInvulnerable && !(m->flags & MARIO_VANISH_CAP)
else if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)
&& !(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
o->oInteractStatus = INT_STATUS_INTERACTED;
m->invincTimer = 2;
@ -1699,7 +1701,7 @@ u32 interact_bully(struct MarioState *m, UNUSED u32 interactType, struct Object
}
u32 interact_shock(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (!sInvulnerable && !(m->flags & MARIO_VANISH_CAP)
if (!gInteractionInvulnerable && !(m->flags & MARIO_VANISH_CAP)
&& !(o->oInteractionSubtype & INT_SUBTYPE_DELAY_INVINCIBILITY)) {
u32 actionArg = (m->action & (ACT_FLAG_AIR | ACT_FLAG_ON_POLE | ACT_FLAG_HANGING)) == 0;
@ -1916,7 +1918,7 @@ u32 interact_koopa_shell(struct MarioState *m, UNUSED u32 interactType, struct O
u32 check_object_grab_mario(struct MarioState *m, UNUSED u32 interactType, struct Object *o) {
if (m != &gMarioStates[0]) { return false; }
if ((!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !sInvulnerable)
if ((!(m->action & (ACT_FLAG_AIR | ACT_FLAG_INVULNERABLE | ACT_FLAG_ATTACKING)) || !gInteractionInvulnerable)
&& (o->oInteractionSubtype & INT_SUBTYPE_GRABS_MARIO)) {
if (object_facing_mario(m, o, 0x2AAA)) {
mario_stop_riding_and_holding(m);
@ -2222,7 +2224,7 @@ void check_kick_or_punch_wall(struct MarioState *m) {
void mario_process_interactions(struct MarioState *m) {
sDelayInvincTimer = FALSE;
sInvulnerable = (m->action & ACT_FLAG_INVULNERABLE) || m->invincTimer != 0;
gInteractionInvulnerable = (m->action & ACT_FLAG_INVULNERABLE) || m->invincTimer != 0;
if (!(m->action & ACT_FLAG_INTANGIBLE) && m->collidedObjInteractTypes != 0 && is_player_active(m)) {
s32 i;

View file

@ -98,6 +98,7 @@ enum InteractionType {
#define INT_STATUS_STOP_RIDING (1 << 22) /* 0x00400000 */
#define INT_STATUS_TOUCHED_BOB_OMB (1 << 23) /* 0x00800000 */
extern s16 gInteractionInvulnerable;
extern u8 gPssSlideStarted;
s16 mario_obj_angle_to_object(struct MarioState *m, struct Object *o);

View file

@ -176,7 +176,11 @@ void set_anim_to_frame(struct MarioState *m, s16 animFrame) {
s32 is_anim_past_frame(struct MarioState *m, s16 animFrame) {
s32 isPastFrame;
s32 acceleratedFrame = animFrame << 0x10;
if (!m || !m->marioObj) { return TRUE; }
struct AnimInfo *animInfo = &m->marioObj->header.gfx.animInfo;
if (!animInfo->curAnim) { return TRUE; }
struct Animation *curAnim = animInfo->curAnim;
if (animInfo->animAccel) {

View file

@ -2282,6 +2282,8 @@ s32 cur_obj_follow_path(UNUSED s32 unusedArg) {
f32 objToNextXZ;
f32 objToNextX, objToNextY, objToNextZ;
if (o == NULL) { return PATH_NONE; }
if (o->oPathedPrevWaypointFlags == 0) {
o->oPathedPrevWaypoint = o->oPathedStartWaypoint;
o->oPathedPrevWaypointFlags = WAYPOINT_FLAGS_INITIALIZED;
@ -2295,12 +2297,15 @@ s32 cur_obj_follow_path(UNUSED s32 unusedArg) {
struct Waypoint* tmpWaypoint = (lastWaypoint + 1);
if (tmpWaypoint == NULL) { tmpWaypoint = lastWaypoint; }
if (tmpWaypoint->flags != WAYPOINT_FLAGS_END) {
if (tmpWaypoint && tmpWaypoint->flags != WAYPOINT_FLAGS_END) {
targetWaypoint = tmpWaypoint;
} else {
targetWaypoint = startWaypoint;
}
if (lastWaypoint == NULL) { return PATH_NONE; }
if (targetWaypoint == NULL) { return PATH_NONE; }
o->oPathedPrevWaypointFlags = lastWaypoint->flags | WAYPOINT_FLAGS_INITIALIZED;
prevToNextX = targetWaypoint->pos[0] - lastWaypoint->pos[0];
@ -2320,7 +2325,7 @@ s32 cur_obj_follow_path(UNUSED s32 unusedArg) {
o->oPathedPrevWaypoint = targetWaypoint;
struct Waypoint* tmpWaypoint2 = (targetWaypoint + 1);
if (tmpWaypoint2 == NULL) { tmpWaypoint2 = targetWaypoint; }
if (tmpWaypoint2->flags == WAYPOINT_FLAGS_END) {
if (tmpWaypoint2 && tmpWaypoint2->flags == WAYPOINT_FLAGS_END) {
return PATH_REACHED_END;
} else {
return PATH_REACHED_WAYPOINT;
@ -2658,8 +2663,11 @@ s32 cur_obj_move_up_and_down(s32 a0) {
return FALSE;
}
void cur_obj_call_action_function(void (*actionFunctions[])(void)) {
void cur_obj_call_action_function(void (*actionFunctions[])(void), uint32_t actionFunctionsLength) {
if (!actionFunctions) { return; }
if ((uint32_t)o->oAction >= actionFunctionsLength) { return; }
void (*actionFunction)(void) = actionFunctions[o->oAction];
if (!actionFunction) { return; }
actionFunction();
}

View file

@ -256,6 +256,8 @@ struct GraphNode_802A45E4 {
/*0x22*/ s16 unk22;
};
#define CUR_OBJ_CALL_ACTION_FUNCTION(_action_func) cur_obj_call_action_function(_action_func, (sizeof(_action_func) / sizeof(&_action_func[0])))
void obj_set_hitbox(struct Object *obj, struct ObjectHitbox *hitbox);
s32 signum_positive(s32 x);
f32 absf(f32 x);
@ -273,7 +275,7 @@ void cur_obj_scale_over_time(s32 a0, s32 a1, f32 sp10, f32 sp14);
void cur_obj_set_pos_to_home_with_debug(void);
s32 cur_obj_is_mario_on_platform(void);
s32 cur_obj_move_up_and_down(s32 a0);
void cur_obj_call_action_function(void (*actionFunctions[])(void));
void cur_obj_call_action_function(void (*actionFunctions[])(void), uint32_t actionFunctionsLength);
void spawn_base_star_with_no_lvl_exit(void);
s32 bit_shift_left(s32 a0);
s32 cur_obj_mario_far_away(void);

View file

@ -337,6 +337,7 @@ void bhv_mario_update(void) {
update_character_anim_offset(gMarioState);
// reset mario state to the local player
gInteractionInvulnerable = false;
gMarioState = &gMarioStates[0];
}

View file

@ -1554,7 +1554,7 @@ void geo_process_node_and_siblings(struct GraphNode *firstNode) {
}
}
} else {
if (curGraphNode->type == GRAPH_NODE_TYPE_OBJECT) {
if (curGraphNode && curGraphNode->type == GRAPH_NODE_TYPE_OBJECT) {
((struct GraphNodeObject *) curGraphNode)->throwMatrix = NULL;
}
}

View file

@ -98,6 +98,7 @@ void djui_render(void) {
gDjuiHudUtilsZ = 0;
create_dl_ortho_matrix();
djui_gfx_displaylist_begin();
smlua_call_event_hooks(HOOK_ON_HUD_RENDER);
@ -119,4 +120,5 @@ void djui_render(void) {
djui_cursor_update();
djui_interactable_update();
djui_gfx_displaylist_end();
}

View file

@ -4,8 +4,14 @@
#define G_TEXOVERRIDE_DJUI 0xe0
#define G_DJUI_SIMPLE_VERT 0x11
#define G_DJUI_SIMPLE_TRI2 0x12
#define G_TEXADDR_DJUI 0x13
#define G_EXECUTE_DJUI 0xdd
#define gsSPTextureAddrDjui(c) \
{{ \
(_SHIFTL(G_TEXADDR_DJUI,24,8)|_SHIFTL(~(u32)(c),0,24)),(u32)(0) \
}}
#define gSetClippingDjui(pkt, cmd, x1, y1, x2, y2) \
{ \
Gfx *_g = (Gfx *)(pkt); \

View file

@ -6,6 +6,25 @@
#include "src/pc/pc_main.h"
#include "src/pc/gfx/gfx_window_manager_api.h"
#include "gfx_dimensions.h"
#include "djui_gfx.h"
const Gfx dl_djui_display_list_begin[] = {
gsSPTextureAddrDjui(1),
gsSPEndDisplayList(),
};
const Gfx dl_djui_display_list_end[] = {
gsSPTextureAddrDjui(0),
gsSPEndDisplayList(),
};
void djui_gfx_displaylist_begin(void) {
gSPDisplayList(gDisplayListHead++, dl_djui_display_list_begin);
}
void djui_gfx_displaylist_end(void) {
gSPDisplayList(gDisplayListHead++, dl_djui_display_list_end);
}
static const Vtx vertex_djui_simple_rect[] = {
{{{ 0, -1, 0}, 0, { 0, 0 }, { 0xff, 0xff, 0xff, 0xff }}},

View file

@ -9,6 +9,9 @@ extern const Gfx dl_djui_simple_rect[];
extern const Gfx dl_djui_img_begin[];
extern const Gfx dl_djui_img_end[];
void djui_gfx_displaylist_begin(void);
void djui_gfx_displaylist_end(void);
f32 djui_gfx_get_scale(void);
void djui_gfx_render_texture(const u8* texture, u32 w, u32 h, u32 bitSize);

View file

@ -91,6 +91,7 @@ struct InterpHud {
f32 scaleH;
f32 width;
f32 height;
enum HudUtilsResolution resolution;
};
static struct InterpHud sInterpHuds[MAX_INTERP_HUD] = { 0 };
static u16 sInterpHudCount = 0;
@ -102,12 +103,14 @@ void patch_djui_hud_before(void) {
void patch_djui_hud(f32 delta) {
f32 savedZ = gDjuiHudUtilsZ;
Gfx* savedHeadPos = gDisplayListHead;
enum HudUtilsResolution savedResolution = sResolution;
for (u16 i = 0; i < sInterpHudCount; i++) {
struct InterpHud* interp = &sInterpHuds[i];
f32 x = delta_interpolate_f32(interp->prevX, interp->x, delta);
f32 y = delta_interpolate_f32(interp->prevY, interp->y, delta);
f32 scaleW = delta_interpolate_f32(interp->prevScaleW, interp->scaleW, delta);
f32 scaleH = delta_interpolate_f32(interp->prevScaleH, interp->scaleH, delta);
sResolution = interp->resolution;
gDjuiHudUtilsZ = interp->z;
gDisplayListHead = interp->headPos;
@ -125,6 +128,7 @@ void patch_djui_hud(f32 delta) {
djui_hud_size_translate(&translatedH);
create_dl_scale_matrix(DJUI_MTX_NOPUSH, interp->width * translatedW, interp->height * translatedH, 1.0f);
}
sResolution = savedResolution;
gDisplayListHead = savedHeadPos;
gDjuiHudUtilsZ = savedZ;
}
@ -326,6 +330,7 @@ void djui_hud_render_texture_interpolated(struct TextureInfo* texInfo, f32 prevX
interp->width = texInfo->width;
interp->height = texInfo->height;
interp->z = savedZ;
interp->resolution = sResolution;
}
void djui_hud_render_texture_tile_interpolated(struct TextureInfo* texInfo, f32 prevX, f32 prevY, f32 prevScaleW, f32 prevScaleH, f32 x, f32 y, f32 scaleW, f32 scaleH, u32 tileX, u32 tileY, u32 tileW, u32 tileH) {

View file

@ -8,16 +8,11 @@
// events //
////////////
static void djui_paginated_prev(struct DjuiBase* base) {
struct DjuiPaginated* paginated = (struct DjuiPaginated*)base->parent;
paginated->startIndex -= paginated->showCount;
if (paginated->startIndex < 0) { paginated->startIndex = 0; }
}
static void djui_paginated_next(struct DjuiBase* base) {
struct DjuiPaginated* paginated = (struct DjuiPaginated*)base->parent;
paginated->startIndex += paginated->showCount;
static struct DjuiButton* sPrevButton = NULL;
static struct DjuiButton* sNextButton = NULL;
static struct DjuiText* sPageNumText = NULL;
static s32 djui_paginated_get_count(struct DjuiPaginated* paginated) {
s32 count = 0;
struct DjuiBaseChild* dbc = paginated->layout->base.child;
while (dbc != NULL) {
@ -25,6 +20,35 @@ static void djui_paginated_next(struct DjuiBase* base) {
dbc = dbc->next;
}
return count;
}
static void djui_paginated_prev(struct DjuiBase* base) {
struct DjuiPaginated* paginated = (struct DjuiPaginated*)base->parent;
paginated->startIndex -= paginated->showCount;
djui_base_set_enabled(&sPrevButton->base, (paginated->startIndex > 0));
djui_base_set_enabled(&sNextButton->base, true);
char pageNumString[32] = { 0 };
snprintf(pageNumString, 32, "%d/%d", paginated->startIndex / paginated->showCount + 1, djui_paginated_get_count(paginated) / paginated->showCount + 1);
djui_text_set_text(sPageNumText, pageNumString);
if (paginated->startIndex < 0) { paginated->startIndex = 0; }
}
static void djui_paginated_next(struct DjuiBase* base) {
struct DjuiPaginated* paginated = (struct DjuiPaginated*)base->parent;
paginated->startIndex += paginated->showCount;
s32 count = djui_paginated_get_count(paginated);
djui_base_set_enabled(&sNextButton->base, (paginated->startIndex < count - 8));
djui_base_set_enabled(&sPrevButton->base, true);
char pageNumString[32] = { 0 };
snprintf(pageNumString, 32, "%d/%d", paginated->startIndex / paginated->showCount + 1, count / paginated->showCount + 1);
djui_text_set_text(sPageNumText, pageNumString);
if (paginated->startIndex >= count) { paginated->startIndex -= paginated->showCount; }
}
@ -57,6 +81,10 @@ void djui_paginated_calculate_height(struct DjuiPaginated* paginated) {
}
djui_base_set_size(&paginated->base, paginated->base.width.value, height);
char pageNumString[32] = { 0 };
snprintf(pageNumString, 32, "%d/%d", paginated->startIndex / paginated->showCount + 1, count / paginated->showCount + 1);
djui_text_set_text(sPageNumText, pageNumString);
}
bool djui_paginated_render(struct DjuiBase* base) {
@ -112,22 +140,23 @@ struct DjuiPaginated* djui_paginated_create(struct DjuiBase* parent, u32 showCou
paginated->layout = layout;
}
{
struct DjuiButton* button = djui_button_create(&paginated->base, "<", DJUI_BUTTON_STYLE_NORMAL, djui_paginated_prev);
djui_base_set_alignment(&button->base, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
djui_base_set_size_type(&button->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button->base, 128, 32);
paginated->prevButton = button;
}
sPrevButton = djui_button_create(&paginated->base, "<", DJUI_BUTTON_STYLE_NORMAL, djui_paginated_prev);
djui_base_set_alignment(&sPrevButton->base, DJUI_HALIGN_LEFT, DJUI_VALIGN_BOTTOM);
djui_base_set_size_type(&sPrevButton->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&sPrevButton->base, 128, 32);
djui_base_set_enabled(&sPrevButton->base, false);
paginated->prevButton = sPrevButton;
{
struct DjuiButton* button = djui_button_create(&paginated->base, ">", DJUI_BUTTON_STYLE_NORMAL, djui_paginated_next);
djui_base_set_alignment(&button->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_BOTTOM);
djui_base_set_size_type(&button->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&button->base, 128, 32);
djui_interactable_hook_click(&button->base, djui_paginated_next);
paginated->nextButton = button;
}
sPageNumText = djui_text_create(&paginated->base, "");
djui_base_set_color(&sPageNumText->base, 200, 200, 200, 255);
djui_base_set_alignment(&sPageNumText->base, DJUI_HALIGN_CENTER, DJUI_VALIGN_BOTTOM);
sPageNumText->base.y.value -= 30;
sNextButton = djui_button_create(&paginated->base, ">", DJUI_BUTTON_STYLE_NORMAL, djui_paginated_next);
djui_base_set_alignment(&sNextButton->base, DJUI_HALIGN_RIGHT, DJUI_VALIGN_BOTTOM);
djui_base_set_size_type(&sNextButton->base, DJUI_SVT_ABSOLUTE, DJUI_SVT_ABSOLUTE);
djui_base_set_size(&sNextButton->base, 128, 32);
paginated->nextButton = sNextButton;
return paginated;
}

View file

@ -189,6 +189,18 @@ static const uint8_t missing_texture[MISSING_W * MISSING_H * 4] = {
0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
};
static bool sOnlyTextureChangeOnAddrChange = false;
static void gfx_update_loaded_texture(uint8_t tile_number, uint32_t size_bytes, const uint8_t* addr) {
if (!sOnlyTextureChangeOnAddrChange) {
rdp.textures_changed[tile_number] = true;
} else if (!rdp.textures_changed[tile_number]) {
rdp.textures_changed[tile_number] = rdp.loaded_texture[tile_number].addr != addr;
}
rdp.loaded_texture[tile_number].size_bytes = size_bytes;
rdp.loaded_texture[tile_number].addr = addr;
}
//////////////////////////////////
// forward declaration for djui //
//////////////////////////////////
@ -210,15 +222,9 @@ static unsigned long get_time(void) {
static void gfx_flush(void) {
if (buf_vbo_len > 0) {
/*int num = buf_vbo_num_tris;
unsigned long t0 = get_time();*/
gfx_rapi->draw_triangles(buf_vbo, buf_vbo_len, buf_vbo_num_tris);
buf_vbo_len = 0;
buf_vbo_num_tris = 0;
/*unsigned long t1 = get_time();
if (t1 - t0 > 1000) {
printf("f: %d %d\n", num, (int)(t1 - t0));
}*/
}
}
@ -1241,9 +1247,12 @@ static void gfx_dp_set_tile(uint8_t fmt, uint32_t siz, uint32_t line, uint32_t t
rdp.texture_tile.cms = cms;
rdp.texture_tile.cmt = cmt;
rdp.texture_tile.line_size_bytes = line * 8;
if (!sOnlyTextureChangeOnAddrChange) {
// I don't know if we ever need to set these...
rdp.textures_changed[0] = true;
rdp.textures_changed[1] = true;
}
}
if (tile == G_TX_LOADTILE) {
rdp.texture_to_load.tile_number = tmem / 256;
@ -1256,9 +1265,12 @@ static void gfx_dp_set_tile_size(uint8_t tile, uint16_t uls, uint16_t ult, uint1
rdp.texture_tile.ult = ult;
rdp.texture_tile.lrs = lrs;
rdp.texture_tile.lrt = lrt;
if (!sOnlyTextureChangeOnAddrChange) {
// I don't know if we ever need to set these...
rdp.textures_changed[0] = true;
rdp.textures_changed[1] = true;
}
}
}
static void gfx_dp_load_tlut(uint8_t tile, UNUSED uint32_t high_index) {
@ -1290,9 +1302,7 @@ static void gfx_dp_load_block(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t
break;
}
uint32_t size_bytes = (lrs + 1) << word_size_shift;
rdp.loaded_texture[rdp.texture_to_load.tile_number].size_bytes = size_bytes;
rdp.loaded_texture[rdp.texture_to_load.tile_number].addr = rdp.texture_to_load.addr;
rdp.textures_changed[rdp.texture_to_load.tile_number] = true;
gfx_update_loaded_texture(rdp.texture_to_load.tile_number, size_bytes, rdp.texture_to_load.addr);
}
static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t lrs, uint32_t lrt) {
@ -1318,15 +1328,11 @@ static void gfx_dp_load_tile(uint8_t tile, uint32_t uls, uint32_t ult, uint32_t
}
uint32_t size_bytes = (((lrs >> G_TEXTURE_IMAGE_FRAC) + 1) * ((lrt >> G_TEXTURE_IMAGE_FRAC) + 1)) << word_size_shift;
rdp.loaded_texture[rdp.texture_to_load.tile_number].size_bytes = size_bytes;
rdp.loaded_texture[rdp.texture_to_load.tile_number].addr = rdp.texture_to_load.addr;
gfx_update_loaded_texture(rdp.texture_to_load.tile_number, size_bytes, rdp.texture_to_load.addr);
rdp.texture_tile.uls = uls;
rdp.texture_tile.ult = ult;
rdp.texture_tile.lrs = lrs;
rdp.texture_tile.lrt = lrt;
rdp.textures_changed[rdp.texture_to_load.tile_number] = true;
}
static uint8_t color_comb_component(uint32_t v) {
@ -1977,10 +1983,7 @@ static void OPTIMIZE_O3 djui_gfx_dp_execute_override(void) {
uint32_t wordSizeShift = (sDjuiOverrideB == 32) ? 2 : 1;
uint32_t lrs = (sDjuiOverrideW * sDjuiOverrideH) - 1;
uint32_t sizeBytes = (lrs + 1) << wordSizeShift;
rdp.loaded_texture[rdp.texture_to_load.tile_number].size_bytes = sizeBytes;
rdp.textures_changed[rdp.texture_to_load.tile_number] = rdp.loaded_texture[rdp.texture_to_load.tile_number].addr != rdp.texture_to_load.addr;
rdp.loaded_texture[rdp.texture_to_load.tile_number].addr = rdp.texture_to_load.addr;
//rdp.textures_changed[rdp.texture_to_load.tile_number] = true;
gfx_update_loaded_texture(rdp.texture_to_load.tile_number, sizeBytes, rdp.texture_to_load.addr);
// gsDPSetTile
uint32_t line = (((sDjuiOverrideW * 2) + 7) >> 3);
@ -2135,6 +2138,9 @@ void OPTIMIZE_O3 djui_gfx_run_dl(Gfx* cmd) {
djui_gfx_sp_simple_tri1(C0(16, 8) / 2, C0(8, 8) / 2, C0(0, 8) / 2);
djui_gfx_sp_simple_tri1(C1(16, 8) / 2, C1(8, 8) / 2, C1(0, 8) / 2);
break;
case G_TEXADDR_DJUI:
sOnlyTextureChangeOnAddrChange = !(C0(0, 24) & 0x01);
break;
case G_EXECUTE_DJUI:
djui_gfx_dp_execute_djui(cmd->words.w1);
break;

View file

@ -4016,7 +4016,7 @@ char gSmluaConstants[] = ""
"COOP_OBJ_FLAG_INITIALIZED = (1 << 3)\n"
"VERSION_TEXT = 'beta'\n"
"VERSION_NUMBER = 33\n"
"MINOR_VERSION_NUMBER = 0\n"
"MINOR_VERSION_NUMBER = 1\n"
"PATCH_VERSION_NUMBER = 0\n"
"MAX_VERSION_LENGTH = 10\n"
"MAX_LOCAL_VERSION_LENGTH = 12\n"

View file

@ -473,66 +473,104 @@ struct LuaLevelScriptParse {
struct LuaLevelScriptParse sLevelScriptParse = { 0 };
s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
if (type != 0x24 && type != 0x39 && type != 0x1F) {
return 0;
u32 areaIndex, bhvId, bhvArgs;
u32 *pAreaIndex = NULL, *pBhvId = NULL, *pBhvArgs = NULL;
MacroObject *pMacroData = NULL;
// Gather arguments
switch (type) {
// AREA
case 0x1F: {
areaIndex = (u8) dynos_level_cmd_get(cmd, 2);
pAreaIndex = &areaIndex;
} break;
// OBJECT_WITH_ACTS
case 0x24: {
const BehaviorScript *bhv = (const BehaviorScript *) dynos_level_cmd_get(cmd, 20);
if (bhv) {
bhvId = (u32) get_id_from_behavior(bhv);
bhvArgs = (u32) dynos_level_cmd_get(cmd, 16);
pBhvId = &bhvId;
pBhvArgs = &bhvArgs;
}
} break;
// OBJECT_WITH_ACTS_EXT
case 0x3F: {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 20));
if (bhvStr) {
bhvId = (u32) smlua_get_any_integer_mod_variable(bhvStr);
bhvArgs = (u32) dynos_level_cmd_get(cmd, 16);
pBhvId = &bhvId;
pBhvArgs = &bhvArgs;
}
} break;
// OBJECT_WITH_ACTS_EXT2
case 0x40: {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 24));
if (bhvStr) {
bhvId = (u32) smlua_get_any_integer_mod_variable(bhvStr);
bhvArgs = (u32) dynos_level_cmd_get(cmd, 16);
pBhvId = &bhvId;
pBhvArgs = &bhvArgs;
}
} break;
// MACRO_OBJECTS
case 0x39: {
pMacroData = (MacroObject *) dynos_level_cmd_get(cmd, 4);
} break;
// None of the above
default: return 0;
}
// Retrieve Lua state
lua_State* L = gLuaState;
if (L == NULL) { return 0; }
struct LuaLevelScriptParse* preprocess = &sLevelScriptParse;
lua_rawgeti(L, LUA_REGISTRYINDEX, preprocess->reference);
if (type == 0x1F) {
u8 area = (u8) dynos_level_cmd_get(cmd, 2);
lua_pushinteger(L, area);
// Push 'areaIndex'
if (pAreaIndex) {
lua_pushinteger(L, *pAreaIndex);
} else {
lua_pushnil(L);
}
if (type == 0x24) {
const BehaviorScript *bhv = (const BehaviorScript *) dynos_level_cmd_get(cmd, 20);
u32 behaviorArg = (u32) dynos_level_cmd_get(cmd, 16);
// Push 'bhvData'
if (pBhvId && pBhvArgs) {
lua_newtable(L);
lua_pushstring(L, "behavior");
lua_pushinteger(L, get_id_from_behavior(bhv));
lua_pushinteger(L, *pBhvId);
lua_settable(L, -3);
lua_pushstring(L, "behaviorArg");
lua_pushinteger(L, behaviorArg);
lua_pushinteger(L, *pBhvArgs);
lua_settable(L, -3);
} else {
lua_pushnil(L);
}
if (type == 0x39) {
MacroObject *data = (MacroObject *) dynos_level_cmd_get(cmd, 4);
int i = 0;
s32 len = 0;
// Push 'macroBhvIds' and 'macroBhvArgs'
if (pMacroData) {
lua_newtable(L);
int t = lua_gettop(gLuaState);
s32 macroBhvIdsIdx = lua_gettop(gLuaState);
lua_newtable(L);
int args = lua_gettop(gLuaState);
while (data[len++] != MACRO_OBJECT_END()) {
s32 presetId = (s32) ((data[len - 1] & 0x1FF) - 0x1F);
const BehaviorScript *bhv = (const BehaviorScript *) MacroObjectPresets[presetId].behavior;
s32 macroBhvArgsIdx = lua_gettop(gLuaState);
for (s32 i = 0; *pMacroData != MACRO_OBJECT_END(); pMacroData += 5, i++) {
s32 presetId = (s32) ((pMacroData[0] & 0x1FF) - 0x1F);
s32 presetParams = MacroObjectPresets[presetId].param;
s32 objParams = (data[4] & 0xFF00) + (presetParams & 0x00FF);
u32 behaviorArg = ((objParams & 0x00FF) << 16) + (objParams & 0xFF00);
s32 objParams = (pMacroData[4] & 0xFF00) | (presetParams & 0x00FF);
s32 bhvParams = ((objParams & 0x00FF) << 16) | (objParams & 0xFF00);
lua_pushinteger(L, i);
lua_pushinteger(L, get_id_from_behavior(bhv));
lua_settable(L, t);
lua_pushinteger(L, get_id_from_behavior(MacroObjectPresets[presetId].behavior));
lua_settable(L, macroBhvIdsIdx);
lua_pushinteger(L, i);
lua_pushinteger(L, behaviorArg);
lua_settable(L, args);
i++;
len += 4;
lua_pushinteger(L, bhvParams);
lua_settable(L, macroBhvArgsIdx);
}
} else {
lua_pushnil(L);

View file

@ -271,8 +271,12 @@ static bool smlua_sync_table_send_field(u8 toLocalIndex, int stackIndex, bool al
// send over the network
if (!gLuaInitializingScript) {
if (sUnwoundLntsCount < 2) {
LOG_ERROR("Sent sync table field packet with an invalid key count: %u", sUnwoundLntsCount);
} else {
network_send_lua_sync_table(toLocalIndex, seq, modRemoteIndex, sUnwoundLntsCount, sUnwoundLnts, &lntValue);
}
}
///////////////
@ -311,6 +315,12 @@ void smlua_set_sync_table_field_from_network(u64 seq, u16 modRemoteIndex, u16 ln
return;
}
// sanity check key count
if (lntKeyCount < 2) {
LOG_ERROR("Received sync table field packet with an invalid key count: %u", lntKeyCount);
return;
}
lua_getglobal(L, "_G"); // get global table
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // get the file's "global" table
lua_remove(L, -2); // remove global table

View file

@ -152,6 +152,9 @@ void mod_activate(struct Mod* mod) {
}
void mod_clear(struct Mod* mod) {
if (!mod) { return; }
if (mod->files) {
for (int j = 0; j < mod->fileCount; j++) {
struct ModFile* file = &mod->files[j];
if (file->fp != NULL) {
@ -163,6 +166,7 @@ void mod_clear(struct Mod* mod) {
file->cachedPath = NULL;
}
}
}
if (mod->name != NULL) {
free(mod->name);
@ -437,15 +441,10 @@ bool mod_load(struct Mods* mods, char* basePath, char* modName) {
valid = true;
} else if (is_directory(fullPath)) {
char tmpPath[SYS_MAX_PATH] = { 0 };
char path1[SYS_MAX_PATH] = { 0 };
char path2[SYS_MAX_PATH] = { 0 };
if (!concat_path(tmpPath, fullPath, "main.lua")) {
LOG_ERROR("Failed to concat path '%s' + '%s'", fullPath, "main.lua");
return true;
}
if ((concat_path(path1, fullPath, "c-update.lua") && path_exists(path1)) || (concat_path(path2, fullPath, "m-update.lua") && path_exists(path2))) {
return true;
}
valid = path_exists(tmpPath);
}
@ -513,13 +512,11 @@ bool mod_load(struct Mods* mods, char* basePath, char* modName) {
// print
LOG_INFO(" %s", mod->name);
if (isDirectory) {
for (int i = 0; i < mod->fileCount; i++) {
struct ModFile* file = &mod->files[i];
mod_cache_add(mod, file, true);
LOG_INFO(" - %s", file->relativePath);
}
}
return true;
}

View file

@ -56,6 +56,7 @@ static bool mod_import_lua(char* src) {
static bool mod_import_zip(char* path, bool* isLua, bool* isDynos) {
LOG_INFO("Importing zip mod: %s", path);
char luaPath[SYS_MAX_PATH] = { 0 };
mz_zip_archive zip_archive = { 0 };
mz_bool status = mz_zip_reader_init_file(&zip_archive, path, 0);
if (!status) {
@ -75,6 +76,7 @@ static bool mod_import_zip(char* path, bool* isLua, bool* isDynos) {
}
if (str_ends_with(file_stat.m_filename, ".lua")) {
path_get_folder(file_stat.m_filename, luaPath);
*isLua = true;
break;
} else if (str_ends_with(file_stat.m_filename, ".tex")) {
@ -99,12 +101,32 @@ static bool mod_import_zip(char* path, bool* isLua, bool* isDynos) {
snprintf(dstDirectory, SYS_MAX_PATH, "%s", (char*)fs_get_write_path(DYNOS_PACKS_FOLDER));
} else {
LOG_ERROR("Could not figure out what type of mod this is");
mz_zip_reader_end(&zip_archive);
return false;
}
// create mod/dynos path if it doesn't exist
if (!fs_sys_dir_exists(dstDirectory)) {
fs_sys_mkdir(dstDirectory);
}
// erase and create lua path
if (*isLua && strlen(luaPath) > 0) {
if (!concat_path(dst, dstDirectory, luaPath)) {
LOG_ERROR("Failed to concat path for base lua directory");
mz_zip_reader_end(&zip_archive);
return false;
}
if (fs_sys_dir_exists(dst)) {
mods_delete_folder(dst);
}
if (!fs_sys_mkdir(dst)) {
LOG_ERROR("Failed to mkdir for base lua directory");
mz_zip_reader_end(&zip_archive);
return false;
}
}
// Extract the archive
for (int i = 0; i < (int)mz_zip_reader_get_num_files(&zip_archive); i++) {
mz_zip_archive_file_stat file_stat;
@ -159,6 +181,8 @@ static bool mod_import_zip(char* path, bool* isLua, bool* isDynos) {
FILE* fout = fopen(dst, "wb");
if (fout == NULL) {
LOG_ERROR("Failed to open dst path for zip mod import");
mz_free((void*)p);
mz_zip_reader_end(&zip_archive);
return false;
}

View file

@ -132,6 +132,16 @@ void discord_activity_update(bool hosting) {
LOGFILE_INFO(LFT_DISCORD, "truncating details");
}
if (!app.activities) {
LOGFILE_INFO(LFT_DISCORD, "no activities");
return;
}
if (!app.activities->update_activity) {
LOGFILE_INFO(LFT_DISCORD, "no update_activity");
return;
}
app.activities->update_activity(app.activities, &gCurActivity, NULL, on_activity_update_callback);
LOGFILE_INFO(LFT_DISCORD, "set activity");
}

View file

@ -6,7 +6,7 @@
#include "behavior_table.h"
#include "model_ids.h"
#define MAX_LOCAL_STATE_HISTORY 20
#define MAX_LOCAL_STATE_HISTORY 30
struct StateHistory {
struct MarioState m;
struct Object marioObj;
@ -40,16 +40,16 @@ void lag_compensation_store(void) {
}
struct MarioState* lag_compensation_get_local_state(struct NetworkPlayer* otherNp) {
if (!otherNp) { return NULL; }
if (gNetworkType == NT_NONE) { return NULL; }
if (!sLocalStateHistoryReady) { return NULL; }
if (!otherNp) { return &gMarioStates[0]; }
if (gNetworkType == NT_NONE) { return &gMarioStates[0]; }
if (!sLocalStateHistoryReady) { return &gMarioStates[0]; }
s32 pingToTicks = (otherNp->ping / 1000.0f) * 30;
if (pingToTicks > (MAX_LOCAL_STATE_HISTORY-1)) {
pingToTicks = (MAX_LOCAL_STATE_HISTORY-1);
}
//LOG_INFO("Ping: %s :: %u :: %d", otherNp->name, otherNp->ping, pingToTicks);
if (pingToTicks == 0) { return NULL; }
if (pingToTicks == 0) { return &gMarioStates[0]; }
s32 index = (s32)sLocalStateHistoryIndex - pingToTicks;
while (index < 0) { index += MAX_LOCAL_STATE_HISTORY; }

View file

@ -52,8 +52,8 @@ void packet_process(struct Packet* p) {
case PACKET_JOIN: network_receive_join(p); break;
case PACKET_CHAT: network_receive_chat(p); break;
case PACKET_KICK: network_receive_kick(p); break;
case PACKET_COMMAND: network_recieve_chat_command(p); break;
case PACKET_MODERATOR: network_recieve_moderator(p); break;
case PACKET_COMMAND: network_receive_chat_command(p); break;
case PACKET_MODERATOR: network_receive_moderator(p); break;
case PACKET_KEEP_ALIVE: network_receive_keep_alive(p); break;
case PACKET_LEAVING: network_receive_leaving(p); break;
case PACKET_SAVE_FILE: network_receive_save_file(p); break;

View file

@ -234,11 +234,11 @@ void network_receive_kick(struct Packet* p);
// packet_command_mod.c
void network_send_chat_command(u8 localIndex, enum ChatConfirmCommand CCC);
void network_recieve_chat_command(struct Packet* p);
void network_receive_chat_command(struct Packet* p);
// packet_moderator.c
void network_send_moderator(u8 localIndex);
void network_recieve_moderator(struct Packet* p);
void network_receive_moderator(struct Packet* p);
// packet_keep_alive.c
void network_send_keep_alive(u8 localIndex);

View file

@ -138,7 +138,7 @@ void network_receive_area(struct Packet* p) {
LOG_INFO("rx area");
if (p == NULL) {
LOG_ERROR("rx area: the packet was NULL, failed to recieve the area.");
LOG_ERROR("rx area: the packet was NULL, failed to receive the area.");
return;
}

View file

@ -18,7 +18,7 @@ void network_send_chat_command(u8 globalIndex, enum ChatConfirmCommand ccc) {
}
}
void network_recieve_chat_command(struct Packet *p) {
void network_receive_chat_command(struct Packet *p) {
if (!moderator_list_contains(gNetworkSystem->get_id_str(p->localIndex))) {
return;
}
@ -59,7 +59,7 @@ void network_send_moderator(u8 localIndex) {
network_send_to(localIndex, &p);
}
void network_recieve_moderator(struct Packet *p) {
void network_receive_moderator(struct Packet *p) {
if ((gIsModerator) || (network_player_any_connected() && gNetworkPlayers[p->localIndex].type != NPT_SERVER)) {
return;
}

View file

@ -332,6 +332,11 @@ static void open_mod_file(struct Mod* mod, struct ModFile* file) {
}
void network_receive_download(struct Packet* p) {
if (!p) {
LOG_ERROR("Received null packet");
return;
}
SOFT_ASSERT(gNetworkType == NT_CLIENT);
if (p->localIndex != UNKNOWN_LOCAL_INDEX) {
if (gNetworkPlayerServer == NULL || gNetworkPlayerServer->localIndex != p->localIndex) {
@ -343,9 +348,13 @@ void network_receive_download(struct Packet* p) {
// read the chunk
u64 receiveOffset = 0;
u64 chunkLength = 0;
u8 chunk[CHUNK_SIZE] = { 0 };
u8 chunk[CHUNK_SIZE+1] = { 0 };
packet_read(p, &receiveOffset, sizeof(u64));
packet_read(p, &chunkLength, sizeof(u64));
if (chunkLength > CHUNK_SIZE) {
LOG_ERROR("Received improper chunk length");
return;
}
packet_read(p, &chunk, sizeof(u8) * chunkLength);
// mark the offset group as received
@ -379,6 +388,10 @@ after_group:;
u64 fileStartOffset = 0;
for (u64 modIndex = 0; modIndex < gRemoteMods.entryCount; modIndex++) {
struct Mod* mod = gRemoteMods.entries[modIndex];
if (!mod) {
LOG_ERROR("Null mod");
continue;
}
// skip past mods to get to the right offset
if ((fileStartOffset + mod->size) < receiveOffset) {
@ -386,6 +399,11 @@ after_group:;
continue;
}
if (mod->fileCount > 0 && !mod->files) {
LOG_ERROR("Null mod files");
continue;
}
for (u64 fileIndex = 0; fileIndex < mod->fileCount; fileIndex++) {
struct ModFile* modFile = &mod->files[fileIndex];

View file

@ -11,6 +11,11 @@ void network_send_lua_custom(bool broadcast) {
u16 zero = 0;
s32 paramIndex = 1;
if (!L) {
LOG_ERROR("Sent lua custom packet when lua is dead");
return;
}
// figure out mod index
if (gLuaActiveMod == NULL) {
LOG_LUA_LINE("Could not figure out the current active mod!");
@ -99,6 +104,11 @@ void network_receive_lua_custom(struct Packet* p) {
packet_read(p, &modIndex, sizeof(u16));
packet_read(p, &keyCount, sizeof(u8));
if (!L) {
LOG_ERROR("Received lua custom packet when lua is dead");
return;
}
lua_newtable(L);
s32 tableIndex = lua_gettop(L);
for(u16 i = 0; i < keyCount; i++) {

View file

@ -36,6 +36,7 @@ void network_send_lua_sync_table(u8 toLocalIndex, u64 seq, u16 modRemoteIndex, u
//LOG_INFO(" %s", smlua_lnt_to_str(&lntKeys[i]));
}
//LOG_INFO(" -> %s", smlua_lnt_to_str(lntValue));
//LOG_INFO(" count %u", lntKeyCount);
if (!packet_write_lnt(&p, lntValue)) { return; }
@ -66,6 +67,7 @@ void network_receive_lua_sync_table(struct Packet* p) {
//LOG_INFO(" %s", smlua_lnt_to_str(&lntKeys[i]));
}
//LOG_INFO(" -> %s", smlua_lnt_to_str(&lntValue));
//LOG_INFO(" count %u", lntKeyCount);
if (!packet_read_lnt(p, &lntValue)) { goto cleanup; }

View file

@ -28,7 +28,10 @@ void network_send_mod_list_request(void) {
}
void network_receive_mod_list_request(UNUSED struct Packet* p) {
SOFT_ASSERT(gNetworkType == NT_SERVER);
if (gNetworkType != NT_SERVER) {
LOG_ERROR("Network type should be server!");
return;
}
LOG_INFO("received mod list request");
network_send_mod_list();

View file

@ -59,6 +59,11 @@ void network_send_spawn_objects_to(u8 sendToLocalIndex, struct Object* objects[]
return;
}
if (objectCount == 0) {
LOG_ERROR("Tried to send 0 objects");
return;
}
SOFT_ASSERT(objectCount < MAX_SPAWN_OBJECTS_PER_PACKET);
// prevent sending spawn objects during credits
if (gCurrActStarNum == 99) {
@ -74,6 +79,11 @@ void network_send_spawn_objects_to(u8 sendToLocalIndex, struct Object* objects[]
for (u8 i = 0; i < objectCount; i++) {
struct Object* o = objects[i];
if (!o) {
LOG_ERROR("Tried to send null object");
return;
}
u32 model = models[i];
u32 parentId = generate_parent_id(objects, i, true);
u32 behaviorId = get_id_from_behavior(o->behavior);
@ -96,11 +106,15 @@ void network_send_spawn_objects_to(u8 sendToLocalIndex, struct Object* objects[]
if (sendToLocalIndex == PACKET_DESTINATION_BROADCAST) {
network_send(&p);
if (objects[0] && objects[0]->behavior) {
LOG_INFO("tx spawn objects (BROADCAST) | %u", get_id_from_behavior(objects[0]->behavior));
}
} else {
network_send_to(sendToLocalIndex, &p);
if (objects[0] && objects[0]->behavior) {
LOG_INFO("tx spawn objects to %d | %u", gNetworkPlayers[sendToLocalIndex].globalIndex, get_id_from_behavior(objects[0]->behavior));
}
}
}
void network_receive_spawn_objects(struct Packet* p) {

View file

@ -3,7 +3,7 @@
#define VERSION_TEXT "beta"
#define VERSION_NUMBER 33
#define MINOR_VERSION_NUMBER 0
#define MINOR_VERSION_NUMBER 1
#define PATCH_VERSION_NUMBER 0
#define MAX_VERSION_LENGTH 10

View file

@ -14,6 +14,7 @@ u64 osClockRate = 62500000;
s32 osPiStartDma(UNUSED OSIoMesg *mb, UNUSED s32 priority, UNUSED s32 direction,
uintptr_t devAddr, void *vAddr, size_t nbytes,
UNUSED OSMesgQueue *mq) {
if (!vAddr || !devAddr) { return 0; }
memcpy(vAddr, (const void *) devAddr, nbytes);
return 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB