More progress toward custom DynOS levels

This commit is contained in:
MysterD 2022-04-02 15:14:04 -07:00
parent df3618f521
commit 046c595f92
22 changed files with 1017 additions and 582 deletions

View file

@ -2,7 +2,7 @@ import os
usf_types = ['u8', 'u16', 'u32', 'u64', 's8', 's16', 's32', 's64', 'f32']
vec3_types = ['Vec3s', 'Vec3f']
typedef_pointers = ['BehaviorScript', 'ObjectAnimPointer', 'Collision']
typedef_pointers = ['BehaviorScript', 'ObjectAnimPointer', 'Collision', 'LevelScript']
exclude_structs = [
'SPTask',

View file

@ -4171,6 +4171,12 @@ function hud_show()
-- ...
end
--- @param name string
--- @return Pointer_LevelScript
function smlua_level_util_get(name)
-- ...
end
--- @param aDelay integer
--- @return boolean
function warp_exit_level(aDelay)
@ -4507,3 +4513,4 @@ end
--- @class Pointer_number
--- @class Pointer_integer
--- @class Pointer_Collision
--- @class Pointer_LevelScript

File diff suppressed because it is too large Load diff

View file

@ -30,9 +30,14 @@ void dynos_add_actor_custom(const char *modPath, const char* geoName);
const void* dynos_geolayout_get(const char *name);
// -- collisions -- //
void dynos_add_collision_custom(const char *modPath, const char* collisionName);
void dynos_add_collision(const char *modPath, const char* collisionName);
Collision* dynos_collision_get(const char* collisionName);
// -- levels -- //
void dynos_add_level(const char *modPath, const char* levelName);
LevelScript* dynos_level_get(const char* levelName);
#endif
#endif

View file

@ -693,6 +693,9 @@ s16 *DynOS_Level_GetWarp(s32 aLevel, s32 aArea, u8 aWarpId);
s16 *DynOS_Level_GetWarpEntry(s32 aLevel, s32 aArea);
s16 *DynOS_Level_GetWarpDeath(s32 aLevel, s32 aArea);
void DynOS_Lvl_Add(const SysPath &aPackFolder, const char *aLevelName);
LevelScript* DynOS_Lvl_Get(const char* levelName);
//
// Warps
//
@ -709,8 +712,8 @@ const char *DynOS_Warp_GetParamName(s32 aLevel, s32 aIndex);
// Collisions
//
void DynOS_Col_AddCollisionCustom(const SysPath &aPackFolder, const char *aCollisionName);
Collision* DynOS_Col_GetCollision(const char* collisionName);
void DynOS_Col_Add(const SysPath &aPackFolder, const char *aCollisionName);
Collision* DynOS_Col_Get(const char* collisionName);
//
// Bin
@ -729,6 +732,7 @@ void DynOS_Anim_Table_Load(FILE *aFile, GfxData *aGfxData);
DataNode<Collision>* DynOS_Col_Parse(GfxData* aGfxData, DataNode<Collision>* aNode, bool aDisplayPercent);
void DynOS_Col_Write(FILE* aFile, GfxData* aGfxData, DataNode<Collision> *aNode);
DataNode<Collision>* DynOS_Col_Load(FILE *aFile, GfxData *aGfxData);
DataNode<Collision>* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const char *aCollisionName);
void DynOS_Col_Generate(const SysPath &aPackFolder, Array<Pair<u64, String>> _ActorsFolders, GfxData *_GfxData);
@ -745,8 +749,8 @@ void DynOS_Lights_Write(FILE* aFile, GfxData* aGfxData, DataNode<Lights1> *aNode
void DynOS_Lights_Load(FILE *aFile, GfxData *aGfxData);
DataNode<MacroObject>* DynOS_MacroObject_Parse(GfxData* aGfxData, DataNode<MacroObject>* aNode, bool aDisplayPercent);
// TODO: DynOS_MacroObject_Write
// TODO: DynOS_MacroObject_Load
void DynOS_MacroObject_Write(FILE* aFile, GfxData* aGfxData, DataNode<MacroObject> *aNode);
DataNode<MacroObject>* DynOS_MacroObject_Load(FILE *aFile, GfxData *aGfxData);
DataNode<TexData>* DynOS_Tex_Parse(GfxData* aGfxData, DataNode<TexData>* aNode);
void DynOS_Tex_Write(FILE* aFile, GfxData* aGfxData, DataNode<TexData> *aNode);
@ -758,7 +762,7 @@ void DynOS_Vtx_Write(FILE* aFile, GfxData* aGfxData, DataNode<Vtx> *aNode);
void DynOS_Vtx_Load(FILE *aFile, GfxData *aGfxData);
void DynOS_Pointer_Write(FILE* aFile, const void* aPtr, GfxData* aGfxData);
void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue);
void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue, bool isLvl);
void DynOS_GfxDynCmd_Load(FILE *aFile, GfxData *aGfxData);
@ -766,9 +770,10 @@ GfxData *DynOS_Actor_LoadFromBinary(const SysPath &aPackFolder, const char *aAct
void DynOS_Actor_GeneratePack(const SysPath &aPackFolder);
DataNode<LevelScript>* DynOS_Lvl_Parse(GfxData* aGfxData, DataNode<LevelScript>* aNode, bool aDisplayPercent);
// TODO: DynOS_Lvl_Write
// TODO: DynOS_Lvl_Load
GfxData *DynOS_Lvl_LoadFromBinary(const SysPath &aPackFolder, const char *aLevelName);
void DynOS_Lvl_GeneratePack(const SysPath &aPackFolder);
s32 DynOS_Lvl_GetFunctionIndex(const void *aPtr);
void *DynOS_Lvl_GetFunctionPointerFromIndex(s32 aIndex);
#endif
#endif

View file

@ -436,7 +436,7 @@ static bool DynOS_Col_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxD
// Loading //
/////////////
static DataNode<Collision>* LoadCollisionData(FILE *aFile) {
DataNode<Collision>* DynOS_Col_Load(FILE *aFile, GfxData *aGfxData) {
DataNode<Collision> *_Node = New<DataNode<Collision>>();
// Name
@ -449,6 +449,11 @@ static DataNode<Collision>* LoadCollisionData(FILE *aFile) {
_Node->mData[i] = ReadBytes<Collision>(aFile);
}
// Add it
if (aGfxData != NULL) {
aGfxData->mCollisions.Add(_Node);
}
return _Node;
}
@ -460,7 +465,7 @@ DataNode<Collision>* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const
if (_File) {
u8 type = ReadBytes<u8>(_File);
if (type == DATA_TYPE_COLLISION) {
collisionNode = LoadCollisionData(_File);
collisionNode = DynOS_Col_Load(_File, NULL);
}
fclose(_File);
}

View file

@ -398,7 +398,7 @@ void DynOS_Geo_Load(FILE *aFile, GfxData *aGfxData) {
_Node->mData = New<GeoLayout>(_Node->mSize);
for (u32 i = 0; i != _Node->mSize; ++i) {
u32 _Value = ReadBytes<u32>(aFile);
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value);
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, false);
if (_Ptr) {
_Node->mData[i] = (uintptr_t) _Ptr;
} else {

View file

@ -894,7 +894,7 @@ void DynOS_Gfx_Load(FILE *aFile, GfxData *aGfxData) {
for (u32 i = 0; i != _Node->mSize; ++i) {
u32 _WordsW0 = ReadBytes<u32>(aFile);
u32 _WordsW1 = ReadBytes<u32>(aFile);
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _WordsW1);
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _WordsW1, false);
if (_Ptr) {
_Node->mData[i].words.w0 = (uintptr_t) _WordsW0;
_Node->mData[i].words.w1 = (uintptr_t) _Ptr;

View file

@ -33,14 +33,27 @@ return sLvlFunctions;
#define sLvlFunctions __LvlFunctions()
void *DynOS_Lvl_GetFunctionPointerFromName(const String &aName) {
for (const auto &_GeoFunction : sLvlFunctions) {
if (aName == _GeoFunction.first) {
return _GeoFunction.second;
for (const auto &_LvlFunction : sLvlFunctions) {
if (aName == _LvlFunction.first) {
return _LvlFunction.second;
}
};
return NULL;
}
s32 DynOS_Lvl_GetFunctionIndex(const void *aPtr) {
for (const auto &_LvlFunction : sLvlFunctions) {
if (_LvlFunction.second == aPtr) {
return (s32) (&_LvlFunction - sLvlFunctions.begin());
}
}
return -1;
}
void *DynOS_Lvl_GetFunctionPointerFromIndex(s32 aIndex) {
return sLvlFunctions[aIndex].second;
}
/////////////
// Parsing //
/////////////
@ -1478,6 +1491,149 @@ static DataNode<LevelScript> *GetLevelScript(GfxData *aGfxData, const String& aG
return NULL;
}
/////////////
// Writing //
/////////////
static void DynOS_Lvl_Write(FILE* aFile, GfxData* aGfxData, DataNode<LevelScript> *aNode) {
if (!aNode->mData) return;
// Name
WriteBytes<u8>(aFile, DATA_TYPE_LEVEL_SCRIPT);
aNode->mName.Write(aFile);
// Data
WriteBytes<u32>(aFile, aNode->mSize);
for (u32 i = 0; i != aNode->mSize; ++i) {
LevelScript *_Head = &aNode->mData[i];
if (aGfxData->mPointerList.Find((void *) _Head) != -1) {
DynOS_Pointer_Write(aFile, (const void *) (*_Head), aGfxData);
} else {
WriteBytes<u32>(aFile, *((u32 *) _Head));
}
}
}
static bool DynOS_Lvl_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData) {
FILE *_File = fopen(aOutputFilename.c_str(), "wb");
if (!_File) {
PrintError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str());
return false;
}
for (u64 i = 0; i != aGfxData->mLoadIndex; ++i) {
for (auto &_Node : aGfxData->mLights) {
if (_Node->mLoadIndex == i) {
DynOS_Lights_Write(_File, aGfxData, _Node);
}
}
for (auto &_Node : aGfxData->mTextures) {
if (_Node->mLoadIndex == i) {
DynOS_Tex_Write(_File, aGfxData, _Node);
}
}
for (auto &_Node : aGfxData->mVertices) {
if (_Node->mLoadIndex == i) {
DynOS_Vtx_Write(_File, aGfxData, _Node);
}
}
for (auto &_Node : aGfxData->mDisplayLists) {
if (_Node->mLoadIndex == i) {
DynOS_Gfx_Write(_File, aGfxData, _Node);
}
}
for (auto &_Node : aGfxData->mGeoLayouts) {
if (_Node->mLoadIndex == i) {
DynOS_Geo_Write(_File, aGfxData, _Node);
}
}
for (auto &_Node : aGfxData->mCollisions) {
if (_Node->mLoadIndex == i) {
DynOS_Col_Write(_File, aGfxData, _Node);
}
}
for (auto &_Node : aGfxData->mLevelScripts) {
if (_Node->mLoadIndex == i) {
DynOS_Lvl_Write(_File, aGfxData, _Node);
}
}
for (auto &_Node : aGfxData->mMacroObjects) {
if (_Node->mLoadIndex == i) {
DynOS_MacroObject_Write(_File, aGfxData, _Node);
}
}
}
fclose(_File);
return true;
}
/////////////
// Reading //
/////////////
static DataNode<LevelScript>* DynOS_Lvl_Load(FILE *aFile, GfxData *aGfxData) {
DataNode<LevelScript> *_Node = New<DataNode<LevelScript>>();
// Name
_Node->mName.Read(aFile);
// Data
_Node->mSize = ReadBytes<u32>(aFile);
_Node->mData = New<LevelScript>(_Node->mSize);
for (u32 i = 0; i != _Node->mSize; ++i) {
u32 _Value = ReadBytes<u32>(aFile);
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, true);
if (_Ptr) {
_Node->mData[i] = (uintptr_t) _Ptr;
} else {
_Node->mData[i] = (uintptr_t) _Value;
}
}
// Add it
if (aGfxData != NULL) {
aGfxData->mLevelScripts.Add(_Node);
}
return _Node;
}
GfxData *DynOS_Lvl_LoadFromBinary(const SysPath &aPackFolder, const char *aLevelName) {
struct DynosGfxDataCache { SysPath mPackFolder; Array<Pair<const char *, GfxData *>> mGfxData; };
static Array<DynosGfxDataCache *> sDynosGfxDataCache;
// Load data from binary file
GfxData *_GfxData = NULL;
SysPath _Filename = fstring("%s/%s.lvl", aPackFolder.begin(), aLevelName);
FILE *_File = fopen(_Filename.c_str(), "rb");
if (_File) {
_GfxData = New<GfxData>();
for (bool _Done = false; !_Done;) {
switch (ReadBytes<u8>(_File)) {
case DATA_TYPE_LIGHT: DynOS_Lights_Load (_File, _GfxData); break;
case DATA_TYPE_TEXTURE: DynOS_Tex_Load (_File, _GfxData); break;
case DATA_TYPE_VERTEX: DynOS_Vtx_Load (_File, _GfxData); break;
case DATA_TYPE_DISPLAY_LIST: DynOS_Gfx_Load (_File, _GfxData); break;
case DATA_TYPE_GEO_LAYOUT: DynOS_Geo_Load (_File, _GfxData); break;
case DATA_TYPE_ANIMATION: DynOS_Anim_Load (_File, _GfxData); break;
case DATA_TYPE_ANIMATION_TABLE: DynOS_Anim_Table_Load (_File, _GfxData); break;
case DATA_TYPE_GFXDYNCMD: DynOS_GfxDynCmd_Load (_File, _GfxData); break;
case DATA_TYPE_COLLISION: DynOS_Col_Load (_File, _GfxData); break;
case DATA_TYPE_LEVEL_SCRIPT: DynOS_Lvl_Load (_File, _GfxData); break;
case DATA_TYPE_MACRO_OBJECT: DynOS_MacroObject_Load(_File, _GfxData); break;
default: _Done = true; break;
}
}
fclose(_File);
}
return _GfxData;
}
//////////////
// Generate //
//////////////
static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, Array<Pair<u64, String>> _ActorsFolders, GfxData *_GfxData) {
bool generated = false;
for (auto &_LvlNode : _GfxData->mLevelScripts) {
@ -1501,7 +1657,7 @@ static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, Array<Pa
// Write if no error
if (_GfxData->mErrorCount == 0) {
//DynOS_Lvl_WriteBinary(_LvlFilename, _GfxData, _LvlRoot);
DynOS_Lvl_WriteBinary(_LvlFilename, _GfxData);
} else {
Print(" %u error(s): Unable to parse data", _GfxData->mErrorCount);
}
@ -1513,10 +1669,6 @@ static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, Array<Pa
return generated;
}
//////////////
// Generate //
//////////////
void DynOS_Lvl_GeneratePack(const SysPath &aPackFolder) {
Print("---------- Level pack folder: \"%s\" ----------", aPackFolder.c_str());
Array<Pair<u64, String>> _ActorsFolders;

View file

@ -464,3 +464,46 @@ DataNode<MacroObject>* DynOS_MacroObject_Parse(GfxData* aGfxData, DataNode<Macro
}
#pragma GCC diagnostic pop
/////////////
// Writing //
/////////////
void DynOS_MacroObject_Write(FILE* aFile, GfxData* aGfxData, DataNode<MacroObject> *aNode) {
if (!aNode->mData) return;
// Name
WriteBytes<u8>(aFile, DATA_TYPE_MACRO_OBJECT);
aNode->mName.Write(aFile);
// Data
WriteBytes<u32>(aFile, aNode->mSize);
for (u32 i = 0; i != aNode->mSize; ++i) {
WriteBytes<MacroObject>(aFile, aNode->mData[i]);
}
}
/////////////
// Reading //
/////////////
DataNode<MacroObject>* DynOS_MacroObject_Load(FILE *aFile, GfxData *aGfxData) {
DataNode<MacroObject> *_Node = New<DataNode<MacroObject>>();
// Name
_Node->mName.Read(aFile);
// Data
_Node->mSize = ReadBytes<u32>(aFile);
_Node->mData = New<MacroObject>(_Node->mSize);
for (u32 i = 0; i != _Node->mSize; ++i) {
_Node->mData[i] = ReadBytes<MacroObject>(aFile);
}
// Add it
if (aGfxData != NULL) {
aGfxData->mMacroObjects.Add(_Node);
}
return _Node;
}

View file

@ -1,12 +1,13 @@
#include "dynos.cpp.h"
extern "C" {
#include "behavior_table.h"
}
/////////////
// Writing //
/////////////
typedef Pair<String, u32> PointerData;
static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) {
// Lights
for (auto& _Node : aGfxData->mLights) {
if (&_Node->mData->l[0] == aPtr) { // Light *, not Lights1 *
@ -59,6 +60,12 @@ static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) {
}
}
// Behaviors
enum BehaviorId id = get_id_from_vanilla_behavior((const BehaviorScript*) aPtr);
if (id >= 0 && id < id_bhv_max_count) {
return { get_behavior_name_from_id(id), 0 };
}
// Vertices
String _VtxArrayName = "";
uintptr_t _VtxArrayStart = 0;
@ -91,6 +98,14 @@ void DynOS_Pointer_Write(FILE* aFile, const void* aPtr, GfxData* aGfxData) {
return;
}
// Lvl function
s32 _LvlFunctionIndex = DynOS_Lvl_GetFunctionIndex(aPtr);
if (_LvlFunctionIndex != -1) {
WriteBytes<u32>(aFile, FUNCTION_CODE);
WriteBytes<s32>(aFile, _LvlFunctionIndex);
return;
}
// Pointer
PointerData _PtrData = GetDataFromPointer(aPtr, aGfxData);
WriteBytes<u32>(aFile, POINTER_CODE);
@ -166,17 +181,25 @@ static void *GetPointerFromData(GfxData *aGfxData, const String &aPtrName, u32 a
}
}
// Behaviors
enum BehaviorId id = get_id_from_behavior_name(aPtrName.begin());
if (id >= 0 && id < id_bhv_max_count) {
return (void*)get_behavior_from_id(id);
}
// Error
sys_fatal("Pointer not found: %s", aPtrName.begin());
return NULL;
}
void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue) {
void *DynOS_Pointer_Load(FILE *aFile, GfxData *aGfxData, u32 aValue, bool isLvl) {
// FUNC
if (aValue == FUNCTION_CODE) {
s32 _GeoFunctionIndex = ReadBytes<s32>(aFile);
return DynOS_Geo_GetFunctionPointerFromIndex(_GeoFunctionIndex);
s32 _FunctionIndex = ReadBytes<s32>(aFile);
return isLvl
? DynOS_Lvl_GetFunctionPointerFromIndex(_FunctionIndex)
: DynOS_Geo_GetFunctionPointerFromIndex(_FunctionIndex);
}
// PNTR

View file

@ -146,6 +146,8 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) {
} else if (!_DataIgnore) {
_Buffer.Add(*c);
}
} else if (*c == '<' || *c == '>') {
_DataIgnore = !_DataIgnore;
}
// Retrieving data type

View file

@ -89,12 +89,22 @@ const void* dynos_geolayout_get(const char *name) {
// -- collisions -- //
void dynos_add_collision_custom(const char *modPath, const char* collisionName) {
DynOS_Col_AddCollisionCustom(modPath, collisionName);
void dynos_add_collision(const char *modPath, const char* collisionName) {
DynOS_Col_Add(modPath, collisionName);
}
Collision* dynos_collision_get(const char* collisionName) {
return DynOS_Col_GetCollision(collisionName);
return DynOS_Col_Get(collisionName);
}
// -- levels -- //
void dynos_add_level(const char *modPath, const char* levelName) {
DynOS_Lvl_Add(modPath, levelName);
}
LevelScript* dynos_level_get(const char* levelName) {
return DynOS_Lvl_Get(levelName);
}
}

View file

@ -564,14 +564,16 @@ void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory) {
return NULL;
}
// Collisions
////////////////
// Collisions //
////////////////
static Array<Pair<const char*, DataNode<Collision>*>> sDynosCustomCollisions;
static Array<Pair<const char*, DataNode<Collision>*>> sDynosCollisions;
void DynOS_Col_AddCollisionCustom(const SysPath &aPackFolder, const char *aCollisionName) {
void DynOS_Col_Add(const SysPath &aPackFolder, const char *aCollisionName) {
// check for duplicates
for (s32 i = 0; i < sDynosCustomCollisions.Count(); ++i) {
if (!strcmp(sDynosCustomCollisions[i].first, aCollisionName)) {
for (s32 i = 0; i < sDynosCollisions.Count(); ++i) {
if (!strcmp(sDynosCollisions[i].first, aCollisionName)) {
return;
}
}
@ -586,14 +588,52 @@ void DynOS_Col_AddCollisionCustom(const SysPath &aPackFolder, const char *aColli
return;
}
// Add to custom collisions
sDynosCustomCollisions.Add({ collisionName, _Node });
// Add to collisions
sDynosCollisions.Add({ collisionName, _Node });
}
Collision* DynOS_Col_GetCollision(const char* collisionName) {
for (s32 i = 0; i < sDynosCustomCollisions.Count(); ++i) {
if (!strcmp(sDynosCustomCollisions[i].first, collisionName)) {
return sDynosCustomCollisions[i].second->mData;
Collision* DynOS_Col_Get(const char* collisionName) {
for (s32 i = 0; i < sDynosCollisions.Count(); ++i) {
if (!strcmp(sDynosCollisions[i].first, collisionName)) {
return sDynosCollisions[i].second->mData;
}
}
return NULL;
}
////////////
// Levels //
////////////
static Array<Pair<const char*, GfxData*>> sDynosCustomLevelScripts;
void DynOS_Lvl_Add(const SysPath &aPackFolder, const char *aLevelName) {
// check for duplicates
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
if (!strcmp(sDynosCustomLevelScripts[i].first, aLevelName)) {
return;
}
}
u16 levelLen = strlen(aLevelName);
char* levelName = (char*)calloc(1, sizeof(char) * (levelLen + 1));
strcpy(levelName, aLevelName);
GfxData* _Node = DynOS_Lvl_LoadFromBinary(aPackFolder, levelName);
if (!_Node) {
free(levelName);
return;
}
// Add to levels
sDynosCustomLevelScripts.Add({ levelName, _Node });
}
LevelScript* DynOS_Lvl_Get(const char* levelName) {
for (s32 i = 0; i < sDynosCustomLevelScripts.Count(); ++i) {
if (!strcmp(sDynosCustomLevelScripts[i].first, levelName)) {
auto& scripts = sDynosCustomLevelScripts[i].second->mLevelScripts;
return scripts[scripts.Count() - 1]->mData;
}
}
return NULL;

View file

@ -733,6 +733,7 @@
- [get_network_area_timer](#get_network_area_timer)
- [hud_hide](#hud_hide)
- [hud_show](#hud_show)
- [smlua_level_util_get](#smlua_level_util_get)
- [warp_exit_level](#warp_exit_level)
- [warp_restart_level](#warp_restart_level)
- [warp_to_castle](#warp_to_castle)
@ -13775,6 +13776,26 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
<br />
## [smlua_level_util_get](#smlua_level_util_get)
### Lua Example
`local PointerValue = smlua_level_util_get(name)`
### Parameters
| Field | Type |
| ----- | ---- |
| name | `string` |
### Returns
- `Pointer` <`LevelScript`>
### C Prototype
`LevelScript* smlua_level_util_get(const char* name);`
[:arrow_up_small:](#)
<br />
## [warp_exit_level](#warp_exit_level)
### Lua Example

View file

@ -3,8 +3,6 @@
#include "behavior_data.h"
extern const BehaviorScript* gBehaviorTable[];
enum BehaviorId {
id_bhvStarDoor,
id_bhvMrI,
@ -524,6 +522,9 @@ enum BehaviorId {
};
enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior);
enum BehaviorId get_id_from_vanilla_behavior(const BehaviorScript* behavior);
const BehaviorScript* get_behavior_from_id(enum BehaviorId id);
const char* get_behavior_name_from_id(enum BehaviorId id);
enum BehaviorId get_id_from_behavior_name(const char* name);
#endif

View file

@ -375,6 +375,7 @@ static int smlua__get_field(lua_State* L) {
case LVT_BEHAVIORSCRIPT: lua_pushinteger(L, *(s32*)p); break;
case LVT_OBJECTANIMPOINTER: lua_pushinteger(L, *(s32*)p); break;
case LVT_COLLISION: lua_pushinteger(L, *(s32*)p); break;
case LVT_LEVELSCRIPT: lua_pushinteger(L, *(s32*)p); break;
// pointers
case LVT_U8_P:
@ -387,6 +388,7 @@ static int smlua__get_field(lua_State* L) {
case LVT_BEHAVIORSCRIPT_P:
case LVT_OBJECTANIMPOINTER_P:
case LVT_COLLISION_P:
case LVT_LEVELSCRIPT_P:
smlua_push_pointer(L, data->valueType, *(u8**)p);
break;

View file

@ -27,6 +27,8 @@ enum LuaValueType {
LVT_OBJECTANIMPOINTER_P,
LVT_COLLISION,
LVT_COLLISION_P,
LVT_LEVELSCRIPT,
LVT_LEVELSCRIPT_P,
LVT_LUAFUNCTION,
LVT_POINTER,
LVT_MAX,

View file

@ -9266,6 +9266,17 @@ int smlua_func_hud_show(UNUSED lua_State* L) {
return 1;
}
int smlua_func_smlua_level_util_get(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
const char* name = smlua_to_string(L, 1);
if (!gSmLuaConvertSuccess) { return 0; }
smlua_push_pointer(L, LVT_LEVELSCRIPT_P, (void*)smlua_level_util_get(name));
return 1;
}
int smlua_func_warp_exit_level(lua_State* L) {
if(!smlua_functions_valid_param_count(L, 1)) { return 0; }
@ -10709,6 +10720,7 @@ void smlua_bind_functions_autogen(void) {
smlua_bind_function(L, "get_network_area_timer", smlua_func_get_network_area_timer);
smlua_bind_function(L, "hud_hide", smlua_func_hud_hide);
smlua_bind_function(L, "hud_show", smlua_func_hud_show);
smlua_bind_function(L, "smlua_level_util_get", smlua_func_smlua_level_util_get);
smlua_bind_function(L, "warp_exit_level", smlua_func_warp_exit_level);
smlua_bind_function(L, "warp_restart_level", smlua_func_warp_restart_level);
smlua_bind_function(L, "warp_to_castle", smlua_func_warp_to_castle);

View file

@ -54,3 +54,7 @@ f32 get_hand_foot_pos_z(struct MarioState* m, u8 index) {
if (index >= 4) { index = 0; }
return m->marioBodyState->handFootPos[index][2];
}
LevelScript* smlua_level_util_get(const char* name) {
return dynos_level_get(name);
}

View file

@ -17,4 +17,6 @@ f32 get_hand_foot_pos_x(struct MarioState* m, u8 index);
f32 get_hand_foot_pos_y(struct MarioState* m, u8 index);
f32 get_hand_foot_pos_z(struct MarioState* m, u8 index);
LevelScript* smlua_level_util_get(const char* name);
#endif

View file

@ -59,10 +59,39 @@ static void mod_activate_col(struct Mod* mod, struct ModFile* file) {
}
// Add to custom actors
dynos_add_collision_custom(dynosPath, colName);
dynos_add_collision(dynosPath, colName);
LOG_INFO("Activating DynOS col: '%s', '%s'", dynosPath, colName);
}
static void mod_activate_lvl(struct Mod* mod, struct ModFile* file) {
char dynosPath[SYS_MAX_PATH] = { 0 };
if (snprintf(dynosPath, SYS_MAX_PATH - 1, "%s/levels", mod->basePath) < 0) {
LOG_ERROR("Failed to concat dynos path");
return;
}
// copy geo name
char lvlName[64] = { 0 };
if (snprintf(lvlName, 63, "%s", path_basename(file->relativePath)) < 0) {
LOG_ERROR("Truncated lvl name");
return;
}
// remove '.lvl'
char* g = lvlName;
while (*g != '\0') {
if (*g == '.') {
*g = '\0';
break;
}
g++;
}
// Add to levels
dynos_add_level(dynosPath, lvlName);
LOG_INFO("Activating DynOS lvl: '%s', '%s'", dynosPath, lvlName);
}
void mod_activate(struct Mod* mod) {
// activate dynos models
for (int i = 0; i < mod->fileCount; i++) {
@ -73,6 +102,9 @@ void mod_activate(struct Mod* mod) {
if (str_ends_with(file->relativePath, ".col")) {
mod_activate_col(mod, file);
}
if (str_ends_with(file->relativePath, ".lvl")) {
mod_activate_lvl(mod, file);
}
}
}
@ -200,34 +232,69 @@ static bool mod_load_files(struct Mod* mod, char* modName, char* fullPath) {
// open actors directory
struct dirent* dir = NULL;
DIR* d = opendir(actorsPath);
if (!d) {
return true;
}
if (d) {
// iterate mod directory
char path[SYS_MAX_PATH] = { 0 };
char relativePath[SYS_MAX_PATH] = { 0 };
while ((dir = readdir(d)) != NULL) {
// sanity check / fill path[]
if (!directory_sanity_check(dir, actorsPath, path)) { continue; }
if (snprintf(relativePath, SYS_MAX_PATH - 1, "actors/%s", dir->d_name) < 0) {
LOG_ERROR("Could not concat actor path!");
return false;
}
// iterate mod directory
char path[SYS_MAX_PATH] = { 0 };
char relativePath[SYS_MAX_PATH] = { 0 };
while ((dir = readdir(d)) != NULL) {
// sanity check / fill path[]
if (!directory_sanity_check(dir, actorsPath, path)) { continue; }
if (snprintf(relativePath, SYS_MAX_PATH - 1, "actors/%s", dir->d_name) < 0) {
LOG_ERROR("Could not concat actor path!");
return false;
// only consider bin, and col files
if (!str_ends_with(path, ".bin") && !str_ends_with(path, ".col")) {
continue;
}
// allocate file
struct ModFile* file = mod_allocate_file(mod, relativePath);
if (file == NULL) { return false; }
}
// only consider bin and col files
if (!str_ends_with(path, ".bin") && !str_ends_with(path, ".col")) {
continue;
}
// allocate file
struct ModFile* file = mod_allocate_file(mod, relativePath);
if (file == NULL) { return false; }
closedir(d);
}
closedir(d);
}
// deal with levels directory
{
// concat levels directory
char levelsPath[SYS_MAX_PATH] = { 0 };
if (!concat_path(levelsPath, fullPath, "levels")) {
LOG_ERROR("Could not concat directory '%s' + '%s'", fullPath, "levels");
return false;
}
// open levels directory
struct dirent* dir = NULL;
DIR* d = opendir(levelsPath);
if (d) {
// iterate mod directory
char path[SYS_MAX_PATH] = { 0 };
char relativePath[SYS_MAX_PATH] = { 0 };
while ((dir = readdir(d)) != NULL) {
// sanity check / fill path[]
if (!directory_sanity_check(dir, levelsPath, path)) { continue; }
if (snprintf(relativePath, SYS_MAX_PATH - 1, "levels/%s", dir->d_name) < 0) {
LOG_ERROR("Could not concat level path!");
return false;
}
// only consider lvl files
if (!str_ends_with(path, ".lvl")) {
continue;
}
// allocate file
struct ModFile* file = mod_allocate_file(mod, relativePath);
if (file == NULL) { return false; }
}
closedir(d);
}
}
return true;
}