Add lua params support to level macros (allocate dialog pt. 2) (#905)
Some checks are pending
Build coop / build-linux (push) Waiting to run
Build coop / build-steamos (push) Waiting to run
Build coop / build-windows-opengl (push) Waiting to run
Build coop / build-windows-directx (push) Waiting to run
Build coop / build-macos-arm (push) Waiting to run
Build coop / build-macos-intel (push) Waiting to run

* all OBJECT fields are now Lua variables

* add lua variable support to SHOW_DIALOG

* fix object_with_acts

* minor tweak

* Peachy review

---------

Co-authored-by: PeachyPeachSM64 <72323920+PeachyPeachSM64@users.noreply.github.com>
This commit is contained in:
Beckowl 2025-09-13 15:36:28 -03:00 committed by GitHub
parent 6524e709a3
commit 1c71449ed2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 270 additions and 201 deletions

View file

@ -558,6 +558,8 @@ const struct BehaviorTableEntry gBehaviorTable[id_bhv_max_count] = {
enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior) {
if (behavior == NULL) { return id_bhv_max_count; }
if ((behavior[0] >> 24) != 0x00) { return id_bhv_max_count; } // check for BEGIN
if ((behavior[1] >> 24) != 0x39) { return id_bhv_max_count; } // check for ID
return (enum BehaviorId)(behavior[1] & 0xFFFF);
}

View file

@ -641,6 +641,15 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelSc
return; \
}
static LevelScript ParseLevelScriptObjectSymbolArgInternal(GfxData* aGfxData, DataNode<LevelScript>* aNode, u64& aTokenIndex, u32 *luaParams, u32 luaParamFlag) {
bool foundParam = true;
LevelScript value = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundParam);
if (!foundParam) {
*luaParams |= luaParamFlag;
}
return value;
}
static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNode, LevelScript*& aHead, u64& aTokenIndex, Array<u64>& aSwitchNodes) {
const String& _Symbol = aNode->mTokens[aTokenIndex++];
@ -711,7 +720,6 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
lvl_symbol_0(CMD2D);
lvl_symbol_1(TERRAIN, 1);
lvl_symbol_1(ROOMS, 1);
lvl_symbol_2(SHOW_DIALOG, 0, 0);
lvl_symbol_1(TERRAIN_TYPE, 0);
lvl_symbol_0(NOP);
@ -733,75 +741,75 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
lvl_symbol_0(ADV_DEMO);
lvl_symbol_0(CLEAR_DEMO_PTR);
// object
if (_Symbol == "OBJECT") {
// dialog
if (_Symbol == "SHOW_DIALOG") {
u64 topTokenIndex = aTokenIndex;
u32 luaParams = 0;
LevelScript index = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, SHOW_DIALOG_EXT_LUA_INDEX);
LevelScript dialogId = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, SHOW_DIALOG_EXT_LUA_DIALOG);
bool foundModel = true;
bool foundBeh = true;
LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel);
LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh);
if (luaParams != 0) {
LevelScript finalIndex = (luaParams & SHOW_DIALOG_EXT_LUA_INDEX) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 1, aNode->mTokens[topTokenIndex + 0]) : index;
LevelScript finalDialogId = (luaParams & SHOW_DIALOG_EXT_LUA_DIALOG) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 2, aNode->mTokens[topTokenIndex + 1]) : dialogId;
if (foundModel && foundBeh) {
aGfxData->mPointerList.Add(aHead + 5);
LevelScript _Ls[] = { OBJECT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else if (foundModel) {
u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 8]);
LevelScript _Ls[] = { OBJECT_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex) };
LevelScript _Ls[] = { SHOW_DIALOG_EXT(luaParams, finalIndex, finalDialogId) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else {
u32 modelIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 0]);
u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 8]);
LevelScript _Ls[] = { OBJECT_EXT2(modelIndex, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex) };
LevelScript _Ls[] = { SHOW_DIALOG(index, dialogId) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
return;
}
// object with acts
if (_Symbol == "OBJECT_WITH_ACTS") {
// object
if (_Symbol == "OBJECT" || _Symbol == "OBJECT_WITH_ACTS") {
u64 topTokenIndex = aTokenIndex;
bool foundModel = true;
bool foundBeh = true;
LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel);
LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh);
LevelScript acts = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
u32 luaParams = 0;
LevelScript model = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_MODEL);
LevelScript posX = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_X);
LevelScript posY = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_Y);
LevelScript posZ = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_Z);
LevelScript angleX = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_X);
LevelScript angleY = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_Y);
LevelScript angleZ = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_Z);
LevelScript behParam = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_BEH_PARAMS);
LevelScript beh = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_BEHAVIOR);
LevelScript acts = (_Symbol == "OBJECT_WITH_ACTS") ? ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ACTS) : 0x1F;
if (foundModel && foundBeh) {
// At least one parameter is a Lua variable, use OBJECT_EXT_LUA_PARAMS
if (luaParams != 0) {
// Remember behavior pointer if it's not a Lua param
if (!(luaParams & OBJECT_EXT_LUA_BEHAVIOR)) {
aGfxData->mPointerList.Add(aHead + 9);
}
LevelScript finalModel = (luaParams & OBJECT_EXT_LUA_MODEL) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 1, aNode->mTokens[topTokenIndex + 0]) : model;
LevelScript finalPosX = (luaParams & OBJECT_EXT_LUA_POS_X) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 2, aNode->mTokens[topTokenIndex + 1]) : posX;
LevelScript finalPosY = (luaParams & OBJECT_EXT_LUA_POS_Y) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 3, aNode->mTokens[topTokenIndex + 2]) : posY;
LevelScript finalPosZ = (luaParams & OBJECT_EXT_LUA_POS_Z) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 4, aNode->mTokens[topTokenIndex + 3]) : posZ;
LevelScript finalAngleX = (luaParams & OBJECT_EXT_LUA_ANGLE_X) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 4]) : angleX;
LevelScript finalAngleY = (luaParams & OBJECT_EXT_LUA_ANGLE_Y) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 5]) : angleY;
LevelScript finalAngleZ = (luaParams & OBJECT_EXT_LUA_ANGLE_Z) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 7, aNode->mTokens[topTokenIndex + 6]) : angleZ;
LevelScript finalBehParam = (luaParams & OBJECT_EXT_LUA_BEH_PARAMS) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 8, aNode->mTokens[topTokenIndex + 7]) : behParam;
LevelScript finalBeh = (luaParams & OBJECT_EXT_LUA_BEHAVIOR) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 9, aNode->mTokens[topTokenIndex + 8]) : beh;
LevelScript finalActs = (luaParams & OBJECT_EXT_LUA_ACTS) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 10, aNode->mTokens[topTokenIndex + 9]) : acts;
LevelScript _Ls[] = { OBJECT_EXT_LUA_PARAMS(luaParams, finalModel, finalPosX, finalPosY, finalPosZ, finalAngleX, finalAngleY, finalAngleZ, finalBehParam, finalBeh, finalActs) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
// No Lua parameter, use OBJECT_WITH_ACTS
else {
aGfxData->mPointerList.Add(aHead + 5);
LevelScript _Ls[] = { OBJECT_WITH_ACTS(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else if (foundModel) {
u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 8]);
LevelScript _Ls[] = { OBJECT_WITH_ACTS_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex, acts) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else {
u32 modelIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 0]);
u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 8]);
LevelScript _Ls[] = { OBJECT_WITH_ACTS_EXT2(modelIndex, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex, acts) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
return;
}
@ -1063,12 +1071,12 @@ static DataNode<LevelScript>* DynOS_Lvl_Load(BinFile *aFile, GfxData *aGfxData)
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, FUNCTION_LVL, &_Node->mFlags);
if (_Ptr) {
if (!requirePointer) {
if (!requirePointer && _Value != LUA_VAR_CODE) {
PrintError("Didn't expect a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value);
}
_Node->mData[i] = (uintptr_t) _Ptr;
} else {
if (requirePointer) {
if (requirePointer && _Value != LUA_VAR_CODE) {
PrintError("Expected a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value);
_Node->mData[i] = 0;
} else {

View file

@ -134,6 +134,8 @@ static void LvlCmd_Init() {
ADD_COMMAND(OBJECT_EXT2(POINTER, 0, 0, 0, 0, 0, 0, 0, POINTER));
ADD_COMMAND(LOAD_MODEL_FROM_GEO_EXT(0, POINTER));
ADD_COMMAND(JUMP_AREA_EXT(0, 0, POINTER));
ADD_COMMAND(OBJECT_EXT_LUA_PARAMS(0, 0, 0, 0, 0, 0, 0, 0, 0, POINTER, 0));
ADD_COMMAND(SHOW_DIALOG_EXT(0, 0, 0))
}
void DynOS_Lvl_Validate_Begin() {

View file

@ -30,6 +30,34 @@
#define WHIRLPOOL_COND_BOWSER2_BEATEN 2
#define WHIRLPOOL_COND_AT_LEAST_SECOND_STAR 3
#define OBJECT_EXT_LUA_MODEL (1 << 0)
#define OBJECT_EXT_LUA_POS_X (1 << 1)
#define OBJECT_EXT_LUA_POS_Y (1 << 2)
#define OBJECT_EXT_LUA_POS_Z (1 << 3)
#define OBJECT_EXT_LUA_ANGLE_X (1 << 4)
#define OBJECT_EXT_LUA_ANGLE_Y (1 << 5)
#define OBJECT_EXT_LUA_ANGLE_Z (1 << 6)
#define OBJECT_EXT_LUA_BEH_PARAMS (1 << 7)
#define OBJECT_EXT_LUA_BEHAVIOR (1 << 8)
#define OBJECT_EXT_LUA_ACTS (1 << 9)
#define OBJECT_EXT_LUA_MODEL_OFFSET(type) (type == 0x3F ? 3 : (type == 0x40 ? 20 : 4))
#define OBJECT_EXT_LUA_POS_X_OFFSET(type) (type == 0x3F ? 4 : (type == 0x40 ? 4 : 8))
#define OBJECT_EXT_LUA_POS_Y_OFFSET(type) (type == 0x3F ? 6 : (type == 0x40 ? 6 : 12))
#define OBJECT_EXT_LUA_POS_Z_OFFSET(type) (type == 0x3F ? 8 : (type == 0x40 ? 8 : 16))
#define OBJECT_EXT_LUA_ANGLE_X_OFFSET(type) (type == 0x3F ? 10 : (type == 0x40 ? 10 : 20))
#define OBJECT_EXT_LUA_ANGLE_Y_OFFSET(type) (type == 0x3F ? 12 : (type == 0x40 ? 12 : 24))
#define OBJECT_EXT_LUA_ANGLE_Z_OFFSET(type) (type == 0x3F ? 14 : (type == 0x40 ? 14 : 28))
#define OBJECT_EXT_LUA_BEH_PARAMS_OFFSET(type) (type == 0x3F ? 16 : (type == 0x40 ? 16 : 32))
#define OBJECT_EXT_LUA_BEHAVIOR_OFFSET(type) (type == 0x3F ? 20 : (type == 0x40 ? 24 : 36))
#define OBJECT_EXT_LUA_ACTS_OFFSET(type) (type == 0x3F ? 2 : (type == 0x40 ? 2 : 40))
#define SHOW_DIALOG_EXT_LUA_INDEX (1 << 0)
#define SHOW_DIALOG_EXT_LUA_DIALOG (1 << 1)
#define SHOW_DIALOG_EXT_LUA_INDEX_OFFSET(type) (4)
#define SHOW_DIALOG_EXT_LUA_DIALOG_OFFSET(type) (8)
// Head defines
#define REGULAR_FACE 0x0002
#define DIZZY_FACE 0x0003
@ -324,6 +352,30 @@
CMD_W(arg), \
CMD_PTR(target)
// This command is used when parameters are Lua variables.
// The flags parameter describes which parameter is a Lua variable.
// See OBJECT_EXT_LUA flags at the top of this file.
#define OBJECT_EXT_LUA_PARAMS(flags, model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) \
CMD_BBH(0x43, 0x2C, flags), \
CMD_PTR(model), \
CMD_PTR(posX), \
CMD_PTR(posY), \
CMD_PTR(posZ), \
CMD_PTR(angleX), \
CMD_PTR(angleY), \
CMD_PTR(angleZ), \
CMD_PTR(behParam), \
CMD_PTR(beh), \
CMD_PTR(acts)
// This command is used when parameters are Lua variables.
// The flags parameter describes which parameter is a Lua variable.
// See SHOW_DIALOG_EXT flags at the top of this file.
#define SHOW_DIALOG_EXT(flags, index, dialogId) \
CMD_BBBB(0x44, 0x0C, flags, 0x00), \
CMD_PTR(index), \
CMD_PTR(dialogId)
// README //
// README //
// README //

View file

@ -18,6 +18,7 @@
#include "goddard/renderer.h"
#include "geo_layout.h"
#include "graph_node.h"
#include "level_commands.h"
#include "level_script.h"
#include "level_misc_macros.h"
#include "macro_presets.h"
@ -918,124 +919,94 @@ static void level_cmd_cleardemoptr(void)
sCurrentCmd = CMD_NEXT;
}
//
// coop
static void level_cmd_place_object_ext(void) {
u8 val7 = 1 << (gCurrActNum - 1);
struct SpawnInfo *spawnInfo;
//
u16 modIndex = gLevelScriptModIndex;
const char* behStr = dynos_level_get_token(CMD_GET(u32, 20));
static bool find_lua_param(uintptr_t *param, u32 offset, u32 luaParams, u32 luaParamFlag, const char *paramType) {
*param = CMD_GET(uintptr_t, offset);
if (luaParams & luaParamFlag) {
if (gLevelScriptModIndex == -1) {
LOG_ERROR("Could not find level script mod index");
return false;
}
if (gLevelScriptModIndex == -1) {
LOG_ERROR("Could not find level script mod index");
sCurrentCmd = CMD_NEXT;
return;
}
gSmLuaConvertSuccess = true;
enum BehaviorId behId = smlua_get_integer_mod_variable(modIndex, behStr);
if (!gSmLuaConvertSuccess) {
const char *paramStr = dynos_level_get_token(*param);
gSmLuaConvertSuccess = true;
behId = smlua_get_any_integer_mod_variable(behStr);
*param = smlua_get_integer_mod_variable(gLevelScriptModIndex, paramStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
*param = smlua_get_any_integer_mod_variable(paramStr);
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to execute level command, could not find parameter '%s'", paramStr);
return false;
}
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr);
sCurrentCmd = CMD_NEXT;
return;
}
if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
u16 model = CMD_GET(u8, 3);
spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo));
spawnInfo->startPos[0] = CMD_GET(s16, 4);
spawnInfo->startPos[1] = CMD_GET(s16, 6);
spawnInfo->startPos[2] = CMD_GET(s16, 8);
spawnInfo->startAngle[0] = CMD_GET(s16, 10) * 0x8000 / 180;
spawnInfo->startAngle[1] = CMD_GET(s16, 12) * 0x8000 / 180;
spawnInfo->startAngle[2] = CMD_GET(s16, 14) * 0x8000 / 180;
spawnInfo->areaIndex = sCurrAreaIndex;
spawnInfo->activeAreaIndex = sCurrAreaIndex;
spawnInfo->behaviorArg = CMD_GET(u32, 16);
spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId);
spawnInfo->unk18 = dynos_model_get_geo(model);
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next
? spawnInfo->next->syncID + 10
: 10;
gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo;
area_check_red_coin_or_secret(spawnInfo->behaviorScript, false);
}
sCurrentCmd = CMD_NEXT;
return true;
}
static void level_cmd_place_object_ext2(void) {
#define get_lua_param(name, type, flag) \
uintptr_t name##Param; \
if (!find_lua_param(&name##Param, flag##_OFFSET(cmdType), luaParams, flag, #name)) { \
sCurrentCmd = CMD_NEXT; \
return; \
} \
type name = (type) name##Param;
static void level_cmd_place_object_ext_lua_params(void) {
u8 val7 = 1 << (gCurrActNum - 1);
struct SpawnInfo *spawnInfo;
u16 modIndex = gLevelScriptModIndex;
const char* modelStr = dynos_level_get_token(CMD_GET(u32, 20));
const char* behStr = dynos_level_get_token(CMD_GET(u32, 24));
u8 cmdType = sCurrentCmd->type;
u16 luaParams = (
cmdType == 0x3F ? OBJECT_EXT_LUA_BEHAVIOR : (
cmdType == 0x40 ? OBJECT_EXT_LUA_BEHAVIOR | OBJECT_EXT_LUA_MODEL : (
CMD_GET(u16, 2)
)));
if (gLevelScriptModIndex == -1) {
LOG_ERROR("Could not find level script mod index");
sCurrentCmd = CMD_NEXT;
return;
}
get_lua_param(acts, u8, OBJECT_EXT_LUA_ACTS);
gSmLuaConvertSuccess = true;
enum ModelExtendedId modelId = smlua_get_integer_mod_variable(modIndex, modelStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
modelId = smlua_get_any_integer_mod_variable(modelStr);
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find model '%s'", modelStr);
sCurrentCmd = CMD_NEXT;
return;
}
gSmLuaConvertSuccess = true;
enum BehaviorId behId = smlua_get_integer_mod_variable(modIndex, behStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
behId = smlua_get_any_integer_mod_variable(behStr);
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr);
sCurrentCmd = CMD_NEXT;
return;
}
if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (acts & val7) || acts == 0x1F)) {
spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo));
spawnInfo->startPos[0] = CMD_GET(s16, 4);
spawnInfo->startPos[1] = CMD_GET(s16, 6);
spawnInfo->startPos[2] = CMD_GET(s16, 8);
get_lua_param(modelId, u32, OBJECT_EXT_LUA_MODEL);
get_lua_param(posX, s16, OBJECT_EXT_LUA_POS_X);
get_lua_param(posY, s16, OBJECT_EXT_LUA_POS_Y);
get_lua_param(posZ, s16, OBJECT_EXT_LUA_POS_Z);
get_lua_param(angleX, s16, OBJECT_EXT_LUA_ANGLE_X);
get_lua_param(angleY, s16, OBJECT_EXT_LUA_ANGLE_Y);
get_lua_param(angleZ, s16, OBJECT_EXT_LUA_ANGLE_Z);
get_lua_param(behParam, u32, OBJECT_EXT_LUA_BEH_PARAMS);
get_lua_param(behavior, uintptr_t, OBJECT_EXT_LUA_BEHAVIOR);
spawnInfo->startAngle[0] = CMD_GET(s16, 10) * 0x8000 / 180;
spawnInfo->startAngle[1] = CMD_GET(s16, 12) * 0x8000 / 180;
spawnInfo->startAngle[2] = CMD_GET(s16, 14) * 0x8000 / 180;
spawnInfo->startPos[0] = posX;
spawnInfo->startPos[1] = posY;
spawnInfo->startPos[2] = posZ;
spawnInfo->startAngle[0] = (angleX * 0x8000) / 180;
spawnInfo->startAngle[1] = (angleY * 0x8000) / 180;
spawnInfo->startAngle[2] = (angleZ * 0x8000) / 180;
spawnInfo->areaIndex = sCurrAreaIndex;
spawnInfo->activeAreaIndex = sCurrAreaIndex;
spawnInfo->behaviorArg = CMD_GET(u32, 16);
spawnInfo->behaviorArg = behParam;
if (luaParams & OBJECT_EXT_LUA_MODEL) {
u16 slot = smlua_model_util_load((enum ModelExtendedId) modelId);
spawnInfo->unk18 = dynos_model_get_geo(slot);
} else {
spawnInfo->unk18 = dynos_model_get_geo(modelId);
}
if (luaParams & OBJECT_EXT_LUA_BEHAVIOR) {
spawnInfo->behaviorScript = (BehaviorScript *) get_behavior_from_id((enum BehaviorId) behavior);
} else {
spawnInfo->behaviorScript = (BehaviorScript *) behavior;
}
spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId);
u16 slot = smlua_model_util_load(modelId);
spawnInfo->unk18 = dynos_model_get_geo(slot);
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next
@ -1064,6 +1035,21 @@ static void level_cmd_jump_area_ext(void) {
}
}
static void level_cmd_show_dialog_ext(void) {
if (sCurrAreaIndex != -1 && !gDjuiInMainMenu) {
u8 luaParams = CMD_GET(u8, 2);
get_lua_param(index, u8, SHOW_DIALOG_EXT_LUA_INDEX);
get_lua_param(dialogId, s32, SHOW_DIALOG_EXT_LUA_DIALOG);
if (index < 2) {
gAreas[sCurrAreaIndex].dialog[index] = dialogId;
}
}
sCurrentCmd = CMD_NEXT;
}
static void (*LevelScriptJumpTable[])(void) = {
/*00*/ level_cmd_load_and_execute,
/*01*/ level_cmd_exit_and_execute,
@ -1130,10 +1116,12 @@ static void (*LevelScriptJumpTable[])(void) = {
/*3E*/ level_cmd_cleardemoptr,
// coop
/*3F*/ level_cmd_place_object_ext,
/*40*/ level_cmd_place_object_ext2,
/*3F*/ level_cmd_place_object_ext_lua_params,
/*40*/ level_cmd_place_object_ext_lua_params,
/*41*/ level_cmd_load_model_from_geo_ext,
/*42*/ level_cmd_jump_area_ext,
/*43*/ level_cmd_place_object_ext_lua_params,
/*44*/ level_cmd_show_dialog_ext
};
struct LevelCommand *level_script_execute(struct LevelCommand *cmd) {

View file

@ -79,9 +79,9 @@ struct Area
/*0x24*/ struct Camera *camera;
/*0x28*/ struct UnusedArea28 *unused28; // Filled by level script 0x3A, but is unused.
/*0x2C*/ struct Whirlpool *whirlpools[2];
/*0x34*/ u8 dialog[2]; // Level start dialog number (set by level script cmd 0x30)
/*0x36*/ u16 musicParam;
/*0x38*/ u16 musicParam2;
/*0x34*/ s32 dialog[2]; // Level start dialog number (set by level script cmd 0x30 and 0x44)
/*0x3C*/ u16 musicParam;
/*0x40*/ u16 musicParam2;
/*????*/ u32 localAreaTimer;
/*????*/ u8 *macroObjectsAltered;
/*????*/ u8 numRedCoins;

View file

@ -10,6 +10,7 @@
#include "game/mario_actions_stationary.h"
#include "audio/external.h"
#include "object_fields.h"
#include "level_commands.h"
#include "engine/math_util.h"
#include "engine/level_script.h"
#include "pc/djui/djui_hud_utils.h"
@ -492,6 +493,30 @@ struct LuaLevelScriptParse {
struct LuaLevelScriptParse sLevelScriptParse = { 0 };
static bool smlua_func_level_find_lua_param(u64 *param, void *cmd, u32 offset, u32 luaParams, u32 luaParamFlag) {
*param = dynos_level_cmd_get(cmd, offset);
if (luaParams & luaParamFlag) {
const char *paramStr = dynos_level_get_token(*param);
gSmLuaConvertSuccess = true;
*param = smlua_get_integer_mod_variable(gLevelScriptModIndex, paramStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
*param = smlua_get_any_integer_mod_variable(paramStr);
}
if (!gSmLuaConvertSuccess) {
return false;
}
}
return true;
}
#define smlua_func_level_get_lua_param(name, ptype, flag) \
u64 name##Param; \
if (!smlua_func_level_find_lua_param(&name##Param, cmd, flag##_OFFSET(type), luaParams, flag)) { \
break; \
} \
ptype name = (ptype) name##Param;
s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
u32 areaIndex, bhvId, bhvArgs, bhvModelId;
s16 bhvPosX, bhvPosY, bhvPosZ;
@ -513,7 +538,7 @@ s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
const BehaviorScript *bhvPtr = (const BehaviorScript *) dynos_level_cmd_get(cmd, 20);
if (bhvPtr) {
bhvId = get_id_from_behavior(bhvPtr);
if (bhvId == id_bhv1Up) {
if (bhvId == id_bhv_max_count) {
bhvId = get_id_from_vanilla_behavior(bhvPtr); // for behaviors with no id in the script (e.g. bhvInstantActiveWarp)
}
bhvArgs = dynos_level_cmd_get(cmd, 16);
@ -529,54 +554,46 @@ s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) {
} break;
// OBJECT_EXT, 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 = smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
bhvId = smlua_get_any_integer_mod_variable(bhvStr);
}
if (gSmLuaConvertSuccess) {
bhvArgs = dynos_level_cmd_get(cmd, 16);
bhvModelId = dynos_level_cmd_get(cmd, 3);
bhvPosX = dynos_level_cmd_get(cmd, 4);
bhvPosY = dynos_level_cmd_get(cmd, 6);
bhvPosZ = dynos_level_cmd_get(cmd, 8);
bhvPitch = (dynos_level_cmd_get(cmd, 10) * 0x8000) / 180;
bhvYaw = (dynos_level_cmd_get(cmd, 12) * 0x8000) / 180;
bhvRoll = (dynos_level_cmd_get(cmd, 14) * 0x8000) / 180;
bhv = true;
}
}
}
} break;
// OBJECT_EXT2, OBJECT_WITH_ACTS_EXT2
case 0x40: {
// OBJECT_EXT_LUA_PARAMS
case 0x3F:
case 0x40:
case 0x43: {
if (gLevelScriptModIndex != -1) {
const char *bhvStr = dynos_level_get_token(dynos_level_cmd_get(cmd, 24));
if (bhvStr) {
gSmLuaConvertSuccess = true;
bhvId = smlua_get_integer_mod_variable(gLevelScriptModIndex, bhvStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
bhvId = smlua_get_any_integer_mod_variable(bhvStr);
}
if (gSmLuaConvertSuccess) {
bhvArgs = dynos_level_cmd_get(cmd, 16);
bhvModelId = dynos_level_cmd_get(cmd, 3);
bhvPosX = dynos_level_cmd_get(cmd, 4);
bhvPosY = dynos_level_cmd_get(cmd, 6);
bhvPosZ = dynos_level_cmd_get(cmd, 8);
bhvPitch = (dynos_level_cmd_get(cmd, 10) * 0x8000) / 180;
bhvYaw = (dynos_level_cmd_get(cmd, 12) * 0x8000) / 180;
bhvRoll = (dynos_level_cmd_get(cmd, 14) * 0x8000) / 180;
bhv = true;
u16 luaParams = (
type == 0x3F ? OBJECT_EXT_LUA_BEHAVIOR : (
type == 0x40 ? OBJECT_EXT_LUA_BEHAVIOR | OBJECT_EXT_LUA_MODEL : (
dynos_level_cmd_get(cmd, 2)
)));
smlua_func_level_get_lua_param(modelId, u32, OBJECT_EXT_LUA_MODEL);
smlua_func_level_get_lua_param(posX, s16, OBJECT_EXT_LUA_POS_X);
smlua_func_level_get_lua_param(posY, s16, OBJECT_EXT_LUA_POS_Y);
smlua_func_level_get_lua_param(posZ, s16, OBJECT_EXT_LUA_POS_Z);
smlua_func_level_get_lua_param(angleX, s16, OBJECT_EXT_LUA_ANGLE_X);
smlua_func_level_get_lua_param(angleY, s16, OBJECT_EXT_LUA_ANGLE_Y);
smlua_func_level_get_lua_param(angleZ, s16, OBJECT_EXT_LUA_ANGLE_Z);
smlua_func_level_get_lua_param(behParam, u32, OBJECT_EXT_LUA_BEH_PARAMS);
smlua_func_level_get_lua_param(behavior, uintptr_t, OBJECT_EXT_LUA_BEHAVIOR);
bhvArgs = behParam;
bhvModelId = modelId;
bhvPosX = posX;
bhvPosY = posY;
bhvPosZ = posZ;
bhvPitch = angleX;
bhvYaw = angleY;
bhvRoll = angleZ;
if (luaParams & OBJECT_EXT_LUA_BEHAVIOR) {
bhvId = (u32) behavior;
} else {
bhvId = get_id_from_behavior((const BehaviorScript *) behavior);
if (bhvId == id_bhv_max_count) {
bhvId = get_id_from_vanilla_behavior((const BehaviorScript *) behavior);
}
}
bhv = true;
}
} break;