sm64coopdx/src/pc/lua/smlua_functions.c

844 lines
32 KiB
C

#include "smlua.h"
#include "smlua_cobject.h"
#include "game/level_update.h"
#include "game/area.h"
#include "game/mario.h"
#include "game/mario_step.h"
#include "game/mario_actions_stationary.h"
#include "audio/external.h"
#include "object_fields.h"
#include "engine/math_util.h"
#include "engine/level_script.h"
#include "pc/djui/djui_hud_utils.h"
#include "include/level_misc_macros.h"
#include "include/macro_presets.h"
#include "utils/smlua_anim_utils.h"
bool smlua_functions_valid_param_count(lua_State* L, int expected) {
int top = lua_gettop(L);
if (top != expected) {
LOG_LUA_LINE("Improper param count: Expected %u, Received %u", expected, top);
return false;
}
return true;
}
bool smlua_functions_valid_param_range(lua_State* L, int min, int max) {
int top = lua_gettop(L);
if (top < min || top > max) {
LOG_LUA_LINE("Improper param count: Expected (%u - %u), Received %u", min, max, top);
return false;
}
return true;
}
//////////
// misc //
//////////
int smlua_func_sins(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 1)) { return 0; }
s16 x = smlua_to_number(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
lua_pushnumber(L, sins(x));
return 1;
}
int smlua_func_coss(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 1)) { return 0; }
s16 x = smlua_to_number(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
lua_pushnumber(L, coss(x));
return 1;
}
int smlua_func_atan2s(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
f32 y = smlua_to_number(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
f32 x = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
lua_pushinteger(L, atan2s(y, x));
return 1;
}
int smlua_func_init_mario_after_warp(lua_State* L) {
if (network_player_connected_count() >= 2) {
LOG_LUA_LINE("This function can only be used in single-player");
return 0;
}
if(!smlua_functions_valid_param_count(L, 0)) { return 0; }
extern void init_mario_after_warp(void);
init_mario_after_warp();
return 1;
}
int smlua_func_initiate_warp(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 4)) { return 0; }
s16 destLevel = smlua_to_number(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
s16 destArea = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
s16 destWarpNode = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 3"); return 0; }
s32 arg3 = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 4"); return 0; }
extern void initiate_warp(s16 destLevel, s16 destArea, s16 destWarpNode, s32 arg3);
initiate_warp(destLevel, destArea, destWarpNode, arg3);
return 1;
}
int smlua_func_reset_level(lua_State* L) {
if (network_player_connected_count() >= 2) {
LOG_LUA_LINE("This function can only be used in single-player");
return 0;
}
if(!smlua_functions_valid_param_count(L, 0)) { return 0; }
gChangeLevel = gCurrLevelNum;
return 1;
}
int smlua_func_network_init_object(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 3)) { return 0; }
struct Object* obj = smlua_to_cobject(L, 1, LOT_OBJECT);
if (!gSmLuaConvertSuccess || obj == NULL) { LOG_LUA("Failed to convert parameter 1"); return 0; }
bool standardSync = smlua_to_boolean(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
if (lua_type(L, 3) != LUA_TNIL && lua_type(L, 3) != LUA_TTABLE) {
LOG_LUA_LINE("network_init_object() called with an invalid type for param 3: %u", lua_type(L, 3));
return 0;
}
struct SyncObject* so = sync_object_init(obj, standardSync ? 4000.0f : SYNC_DISTANCE_ONLY_EVENTS);
if (so == NULL) {
LOG_LUA_LINE("Failed to allocate sync object.");
return 0;
}
if (lua_type(L, 3) == LUA_TTABLE) {
lua_pushnil(L); // first key
while (lua_next(L, 3) != 0) {
// uses 'key' (at index -2) and 'value' (at index -1)
if (lua_type(L, -1) != LUA_TSTRING) {
LOG_LUA_LINE("Invalid type passed to network_init_object(): %u", lua_type(L, -1));
lua_pop(L, 1); // pop value
continue;
}
const char* fieldIdentifier = smlua_to_string(L, -1);
if (!gSmLuaConvertSuccess) {
LOG_LUA_LINE("Invalid field passed to network_init_object()");
lua_pop(L, 1); // pop value
continue;
}
struct LuaObjectField* data = smlua_get_object_field(LOT_OBJECT, fieldIdentifier);
if (data == NULL) {
data = smlua_get_custom_field(L, LOT_OBJECT, lua_gettop(L));
}
u8 lvtSize = 0;
if ((data->valueType == LVT_U32) || (data->valueType == LVT_S32) || (data->valueType == LVT_F32)) { lvtSize = 32; }
if ((data->valueType == LVT_U16) || (data->valueType == LVT_S16)) { lvtSize = 16; }
if ((data->valueType == LVT_U8) || (data->valueType == LVT_S8)) { lvtSize = 8; }
if (data == NULL || lvtSize == 0) {
LOG_LUA_LINE("Invalid field passed to network_init_object(): %s", fieldIdentifier);
lua_pop(L, 1); // pop value
continue;
}
u8* field = ((u8*)(intptr_t)obj) + data->valueOffset;
sync_object_init_field_with_size(obj, field, lvtSize);
lua_pop(L, 1); // pop value
}
lua_pop(L, 1); // pop key
}
return 1;
}
int smlua_func_network_send_object(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
struct Object* obj = smlua_to_cobject(L, 1, LOT_OBJECT);
if (!gSmLuaConvertSuccess || obj == NULL) { LOG_LUA("Failed to convert parameter 1"); return 0; }
bool reliable = smlua_to_boolean(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
struct SyncObject* so = sync_object_get(obj->oSyncID);
if (!so || so->o != obj) {
LOG_LUA_LINE("Failed to retrieve sync object.");
return 0;
}
network_send_object_reliability(obj, reliable);
return 1;
}
int smlua_func_network_send(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
network_send_lua_custom(true);
return 1;
}
int smlua_func_network_send_to(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 3)) { return 0; }
network_send_lua_custom(false);
return 1;
}
//////////////
// Textures //
//////////////
int smlua_func_get_texture_info(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 1)) { return 0; }
if (lua_type(L, -1) != LUA_TSTRING) {
LOG_LUA_LINE("Invalid type passed to get_texture_info(): %u", lua_type(L, -1));
lua_pop(L, 1); // pop value
return 0;
}
struct TextureInfo texInfo = { 0 };
const char* textureName = smlua_to_string(L, -1);
if (!dynos_texture_get(textureName, &texInfo)) {
LOG_LUA_LINE("Could not find texture info for '%s'", textureName);
return 0;
}
lua_newtable(L);
lua_pushstring(L, "texture");
smlua_push_pointer(L, LVT_U8_P, texInfo.texture);
lua_settable(L, -3);
lua_pushstring(L, "bitSize");
lua_pushinteger(L, texInfo.bitSize);
lua_settable(L, -3);
lua_pushstring(L, "width");
lua_pushinteger(L, texInfo.width);
lua_settable(L, -3);
lua_pushstring(L, "height");
lua_pushinteger(L, texInfo.height);
lua_settable(L, -3);
lua_pushstring(L, "name");
lua_pushstring(L, texInfo.name);
lua_settable(L, -3);
return 1;
}
int smlua_func_djui_hud_render_texture(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 5)) { return 0; }
struct TextureInfo tmpTexInfo = { 0 };
struct TextureInfo* texInfo = &tmpTexInfo;
if (smlua_is_cobject(L, 1, LOT_TEXTUREINFO)) {
texInfo = (struct TextureInfo*)smlua_to_cobject(L, 1, LOT_TEXTUREINFO);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
} else {
int top = lua_gettop(L);
lua_pushvalue(L, 1);
lua_pushstring(L, "texture");
lua_gettable(L, top+1);
tmpTexInfo.texture = smlua_to_cpointer(L, lua_gettop(L), LVT_U8_P);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'texture' field"); return 0; }
tmpTexInfo.bitSize = smlua_get_integer_field(top+1, "bitSize");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'bitSize' field"); return 0; }
tmpTexInfo.width = smlua_get_integer_field(top+1, "width");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'width' field"); return 0; }
tmpTexInfo.height = smlua_get_integer_field(top+1, "height");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'height' field"); return 0; }
tmpTexInfo.name = smlua_get_string_field(top+1, "name");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'name' field"); return 0; }
lua_settop(L, top);
}
f32 x = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
f32 y = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 3"); return 0; }
f32 scaleW = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 4"); return 0; }
f32 scaleH = smlua_to_number(L, 5);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 5"); return 0; }
djui_hud_render_texture_raw(texInfo->texture, texInfo->bitSize, texInfo->width, texInfo->height, x, y, scaleW, scaleH);
return 1;
}
int smlua_func_djui_hud_render_texture_tile(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 9)) { return 0; }
struct TextureInfo tmpTexInfo = { 0 };
struct TextureInfo* texInfo = &tmpTexInfo;
if (smlua_is_cobject(L, 1, LOT_TEXTUREINFO)) {
texInfo = (struct TextureInfo*)smlua_to_cobject(L, 1, LOT_TEXTUREINFO);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
} else {
int top = lua_gettop(L);
lua_pushvalue(L, 1);
lua_pushstring(L, "texture");
lua_gettable(L, top+1);
tmpTexInfo.texture = smlua_to_cpointer(L, lua_gettop(L), LVT_U8_P);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'texture' field"); return 0; }
tmpTexInfo.bitSize = smlua_get_integer_field(top+1, "bitSize");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'bitSize' field"); return 0; }
tmpTexInfo.width = smlua_get_integer_field(top+1, "width");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'width' field"); return 0; }
tmpTexInfo.height = smlua_get_integer_field(top+1, "height");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'height' field"); return 0; }
tmpTexInfo.name = smlua_get_string_field(top+1, "name");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'name' field"); return 0; }
lua_settop(L, top);
}
f32 x = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
f32 y = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 3"); return 0; }
f32 scaleW = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 4"); return 0; }
f32 scaleH = smlua_to_number(L, 5);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 5"); return 0; }
f32 tileX = smlua_to_number(L, 6);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 6"); return 0; }
f32 tileY = smlua_to_number(L, 7);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 7"); return 0; }
f32 tileW = smlua_to_number(L, 8);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 8"); return 0; }
f32 tileH = smlua_to_number(L, 9);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 9"); return 0; }
djui_hud_render_texture_tile_raw(texInfo->texture, texInfo->bitSize, texInfo->width, texInfo->height, x, y, scaleW, scaleH, tileX, tileY, tileW, tileH);
return 1;
}
int smlua_func_djui_hud_render_texture_interpolated(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 9)) { return 0; }
struct TextureInfo tmpTexInfo = { 0 };
struct TextureInfo* texInfo = &tmpTexInfo;
if (smlua_is_cobject(L, 1, LOT_TEXTUREINFO)) {
texInfo = (struct TextureInfo*)smlua_to_cobject(L, 1, LOT_TEXTUREINFO);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
} else {
int top = lua_gettop(L);
lua_pushvalue(L, 1);
lua_pushstring(L, "texture");
lua_gettable(L, top+1);
tmpTexInfo.texture = smlua_to_cpointer(L, lua_gettop(L), LVT_U8_P);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'texture' field"); return 0; }
tmpTexInfo.bitSize = smlua_get_integer_field(top+1, "bitSize");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'bitSize' field"); return 0; }
tmpTexInfo.width = smlua_get_integer_field(top+1, "width");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'width' field"); return 0; }
tmpTexInfo.height = smlua_get_integer_field(top+1, "height");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'height' field"); return 0; }
tmpTexInfo.name = smlua_get_string_field(top+1, "name");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'name' field"); return 0; }
lua_settop(L, top);
}
f32 prevX = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
f32 prevY = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 3"); return 0; }
f32 prevScaleW = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 4"); return 0; }
f32 prevScaleH = smlua_to_number(L, 5);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 5"); return 0; }
f32 x = smlua_to_number(L, 6);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 6"); return 0; }
f32 y = smlua_to_number(L, 7);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 7"); return 0; }
f32 scaleW = smlua_to_number(L, 8);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 8"); return 0; }
f32 scaleH = smlua_to_number(L, 9);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 9"); return 0; }
djui_hud_render_texture_interpolated(texInfo, prevX, prevY, prevScaleW, prevScaleH, x, y, scaleW, scaleH);
return 1;
}
int smlua_func_djui_hud_render_texture_tile_interpolated(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 13)) { return 0; }
struct TextureInfo tmpTexInfo = { 0 };
struct TextureInfo* texInfo = &tmpTexInfo;
if (smlua_is_cobject(L, 1, LOT_TEXTUREINFO)) {
texInfo = (struct TextureInfo*)smlua_to_cobject(L, 1, LOT_TEXTUREINFO);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
} else {
int top = lua_gettop(L);
lua_pushvalue(L, 1);
lua_pushstring(L, "texture");
lua_gettable(L, top+1);
tmpTexInfo.texture = smlua_to_cpointer(L, lua_gettop(L), LVT_U8_P);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'texture' field"); return 0; }
tmpTexInfo.bitSize = smlua_get_integer_field(top+1, "bitSize");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'bitSize' field"); return 0; }
tmpTexInfo.width = smlua_get_integer_field(top+1, "width");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'width' field"); return 0; }
tmpTexInfo.height = smlua_get_integer_field(top+1, "height");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'height' field"); return 0; }
tmpTexInfo.name = smlua_get_string_field(top+1, "name");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1's 'name' field"); return 0; }
lua_settop(L, top);
}
f32 prevX = smlua_to_number(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
f32 prevY = smlua_to_number(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 3"); return 0; }
f32 prevScaleW = smlua_to_number(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 4"); return 0; }
f32 prevScaleH = smlua_to_number(L, 5);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 5"); return 0; }
f32 x = smlua_to_number(L, 6);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 6"); return 0; }
f32 y = smlua_to_number(L, 7);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 7"); return 0; }
f32 scaleW = smlua_to_number(L, 8);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 8"); return 0; }
f32 scaleH = smlua_to_number(L, 9);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 9"); return 0; }
f32 tileX = smlua_to_number(L, 10);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 10"); return 0; }
f32 tileY = smlua_to_number(L, 11);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 11"); return 0; }
f32 tileW = smlua_to_number(L, 12);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 12"); return 0; }
f32 tileH = smlua_to_number(L, 13);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 13"); return 0; }
djui_hud_render_texture_tile_interpolated(texInfo, prevX, prevY, prevScaleW, prevScaleH, x, y, scaleW, scaleH, tileX, tileY, tileW, tileH);
return 1;
}
int smlua_func_texture_override_set(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 2)) { return 0; }
const char* textureName = smlua_to_string(L, 1);
struct TextureInfo tmpOverrideTexInfo = { 0 };
struct TextureInfo* overrideTexInfo = &tmpOverrideTexInfo;
if (smlua_is_cobject(L, 2, LOT_TEXTUREINFO)) {
overrideTexInfo = (struct TextureInfo*)smlua_to_cobject(L, 2, LOT_TEXTUREINFO);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
} else {
int top = lua_gettop(L);
lua_pushvalue(L, 2);
lua_pushstring(L, "texture");
lua_gettable(L, top+1);
tmpOverrideTexInfo.texture = smlua_to_cpointer(L, lua_gettop(L), LVT_U8_P);
lua_pop(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2's 'texture' field"); return 0; }
tmpOverrideTexInfo.bitSize = smlua_get_integer_field(top+1, "bitSize");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2's 'bitSize' field"); return 0; }
tmpOverrideTexInfo.width = smlua_get_integer_field(top+1, "width");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2's 'width' field"); return 0; }
tmpOverrideTexInfo.height = smlua_get_integer_field(top+1, "height");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2's 'height' field"); return 0; }
tmpOverrideTexInfo.name = smlua_get_string_field(top+1, "name");
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2's 'name' field"); return 0; }
lua_settop(L, top);
}
dynos_texture_override_set(textureName, overrideTexInfo);
return 1;
}
int smlua_func_texture_override_reset(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 1)) { return 0; }
const char* textureName = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
dynos_texture_override_reset(textureName);
return 1;
}
////////////////////////////////
// level script preprocessing //
////////////////////////////////
struct LuaLevelScriptParse {
int reference;
struct Mod* mod;
};
struct LuaLevelScriptParse sLevelScriptParse = { 0 };
s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
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: {
if (gLevelScriptModIndex != -1) {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 20));
if (bhvStr) {
gSmLuaConvertSuccess = true;
bhvId = (u32) smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
bhvId = (u32) smlua_get_any_integer_mod_variable(bhvStr);
}
if (gSmLuaConvertSuccess) {
bhvArgs = (u32) dynos_level_cmd_get(cmd, 16);
pBhvId = &bhvId;
pBhvArgs = &bhvArgs;
}
}
}
} break;
// OBJECT_WITH_ACTS_EXT2
case 0x40: {
if (gLevelScriptModIndex != -1) {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 24));
if (bhvStr) {
gSmLuaConvertSuccess = true;
bhvId = (u32) smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
bhvId = (u32) smlua_get_any_integer_mod_variable(bhvStr);
}
if (gSmLuaConvertSuccess) {
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);
// Push 'areaIndex'
if (pAreaIndex) {
lua_pushinteger(L, *pAreaIndex);
} else {
lua_pushnil(L);
}
// Push 'bhvData'
if (pBhvId && pBhvArgs) {
lua_newtable(L);
lua_pushstring(L, "behavior");
lua_pushinteger(L, *pBhvId);
lua_settable(L, -3);
lua_pushstring(L, "behaviorArg");
lua_pushinteger(L, *pBhvArgs);
lua_settable(L, -3);
} else {
lua_pushnil(L);
}
// Push 'macroBhvIds' and 'macroBhvArgs'
if (pMacroData) {
lua_newtable(L);
s32 macroBhvIdsIdx = lua_gettop(gLuaState);
lua_newtable(L);
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 = (pMacroData[4] & 0xFF00) | (presetParams & 0x00FF);
s32 bhvParams = ((objParams & 0x00FF) << 16) | (objParams & 0xFF00);
lua_pushinteger(L, i);
lua_pushinteger(L, get_id_from_behavior(MacroObjectPresets[presetId].behavior));
lua_settable(L, macroBhvIdsIdx);
lua_pushinteger(L, i);
lua_pushinteger(L, bhvParams);
lua_settable(L, macroBhvArgsIdx);
}
} else {
lua_pushnil(L);
lua_pushnil(L);
}
// call the callback
if (0 != smlua_call_hook(L, 4, 0, 0, preprocess->mod)) {
LOG_LUA("Failed to call the callback behaviors: %u", type);
return 0;
}
return 0;
}
void smlua_func_level_script_parse(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 2)) { return; }
lua_Integer levelNum = smlua_to_integer(L, 1);
if (!gSmLuaConvertSuccess) {
LOG_LUA_LINE("Invalid level script name");
return;
}
struct LuaLevelScriptParse* preprocess = &sLevelScriptParse;
preprocess->reference = LUA_NOREF;
lua_pushvalue(L, 2);
int ref = luaL_ref(L, LUA_REGISTRYINDEX);
if (ref == -1) {
LOG_LUA_LINE("Level Script Parse: %lld tried to parse using undefined function", levelNum);
return;
}
preprocess->reference = ref;
preprocess->mod = gLuaActiveMod;
void *script = dynos_level_get_script(levelNum);
if (script == NULL) {
LOG_LUA("Failed to find script: %lld", levelNum);
return;
}
s32 modIndex = dynos_level_get_mod_index(levelNum);
// Back up current values
LevelScript *currLevelScript = gLevelScriptActive;
s32 currModIndex = gLevelScriptModIndex;
// Parse script
gLevelScriptActive = (LevelScript *) script;
gLevelScriptModIndex = modIndex;
dynos_level_parse_script(script, smlua_func_level_script_parse_callback);
// Restore current values
gLevelScriptActive = currLevelScript;
gLevelScriptModIndex = currModIndex;
}
///////////////////////
// custom animations //
///////////////////////
static u16 *smlua_to_u16_list(lua_State* L, int index, u32* length) {
// Get number of values
*length = lua_rawlen(L, index);
if (!*length) { LOG_LUA("smlua_to_u16_list: Table must not be empty"); return NULL; }
u16 *values = calloc(*length, sizeof(u16));
// Retrieve values
lua_pushnil(L);
s32 top = lua_gettop(L);
while (lua_next(L, index) != 0) {
int indexKey = lua_gettop(L) - 1;
int indexValue = lua_gettop(L) - 0;
s32 key = smlua_to_integer(L, indexKey);
if (!gSmLuaConvertSuccess) {
LOG_LUA("smlua_to_u16_list: Failed to convert table key");
free(values);
return 0;
}
u16 value = smlua_to_integer(L, indexValue);
if (!gSmLuaConvertSuccess) {
LOG_LUA("smlua_to_u16_list: Failed to convert table value");
free(values);
return 0;
}
values[key - 1] = value;
lua_settop(L, top);
}
lua_settop(L, top);
return values;
}
int smlua_func_smlua_anim_util_register_animation(lua_State* L) {
if (!smlua_functions_valid_param_count(L, 8)) { return 0; }
const char *name = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "name"); return 0; }
s16 flags = smlua_to_integer(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "flags"); return 0; }
s16 animYTransDivisor = smlua_to_integer(L, 3);
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "animYTransDivisor"); return 0; }
s16 startFrame = smlua_to_integer(L, 4);
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "startFrame"); return 0; }
s16 loopStart = smlua_to_integer(L, 5);
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "loopStart"); return 0; }
s16 loopEnd = smlua_to_integer(L, 6);
if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "loopEnd"); return 0; }
u32 valuesLength = 0;
u16 *values = (u16 *) smlua_to_u16_list(L, 7, &valuesLength);
if (!values) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "values"); return 0; }
u32 indexLength = 0;
u16 *index = (u16 *) smlua_to_u16_list(L, 8, &indexLength);
if (!index) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "index"); free(values); return 0; }
smlua_anim_util_register_animation(name, flags, animYTransDivisor, startFrame, loopStart, loopEnd, values, valuesLength, index, indexLength);
return 1;
}
/////////////
// console //
/////////////
int smlua_func_log_to_console(lua_State* L) {
if (!smlua_functions_valid_param_range(L, 1, 2)) { return 0; }
int paramCount = lua_gettop(L);
const char* message = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 1"); return 0; }
enum ConsoleMessageLevel level = CONSOLE_MESSAGE_INFO;
if (paramCount >= 2) {
level = smlua_to_integer(L, 2);
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter 2"); return 0; }
}
djui_console_message_create(message, level);
return 1;
}
//////////
// bind //
//////////
void smlua_bind_functions(void) {
lua_State* L = gLuaState;
// misc
smlua_bind_function(L, "sins", smlua_func_sins);
smlua_bind_function(L, "coss", smlua_func_coss);
smlua_bind_function(L, "atan2s", smlua_func_atan2s);
smlua_bind_function(L, "init_mario_after_warp", smlua_func_init_mario_after_warp);
smlua_bind_function(L, "initiate_warp", smlua_func_initiate_warp);
smlua_bind_function(L, "network_init_object", smlua_func_network_init_object);
smlua_bind_function(L, "network_send_object", smlua_func_network_send_object);
smlua_bind_function(L, "reset_level", smlua_func_reset_level);
smlua_bind_function(L, "network_send", smlua_func_network_send);
smlua_bind_function(L, "network_send_to", smlua_func_network_send_to);
smlua_bind_function(L, "get_texture_info", smlua_func_get_texture_info);
smlua_bind_function(L, "djui_hud_render_texture", smlua_func_djui_hud_render_texture);
smlua_bind_function(L, "djui_hud_render_texture_tile", smlua_func_djui_hud_render_texture_tile);
smlua_bind_function(L, "djui_hud_render_texture_interpolated", smlua_func_djui_hud_render_texture_interpolated);
smlua_bind_function(L, "djui_hud_render_texture_tile_interpolated", smlua_func_djui_hud_render_texture_tile_interpolated);
smlua_bind_function(L, "texture_override_set", smlua_func_texture_override_set);
smlua_bind_function(L, "texture_override_reset", smlua_func_texture_override_reset);
smlua_bind_function(L, "level_script_parse", smlua_func_level_script_parse);
smlua_bind_function(L, "smlua_anim_util_register_animation", smlua_func_smlua_anim_util_register_animation);
smlua_bind_function(L, "log_to_console", smlua_func_log_to_console);
}