diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 551c6c8ed..9660bfcdd 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -4075,6 +4075,12 @@ function get_water_surface_pseudo_floor() -- ... end +--- @param name string +--- @return Pointer_Collision +function smlua_collision_util_get(name) + -- ... +end + --- @param actFlags integer --- @return integer function allocate_mario_action(actFlags) @@ -4452,3 +4458,4 @@ end --- @class Pointer_BehaviorScript --- @class Pointer_number --- @class Pointer_integer +--- @class Pointer_Collision diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 94bc6c34e..0445dcb9f 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -26,6 +26,9 @@ enum { DATA_TYPE_ANIMATION, DATA_TYPE_ANIMATION_TABLE, DATA_TYPE_GFXDYNCMD, +#ifdef COOP + DATA_TYPE_COLLISION, +#endif DATA_TYPE_UNUSED, }; @@ -420,6 +423,9 @@ struct GfxData : NoCopy { DataNodes mVertices; DataNodes mDisplayLists; DataNodes mGeoLayouts; +#ifdef COOP + DataNodes mCollisions; +#endif // Animation data Array *> mAnimValues; @@ -645,6 +651,10 @@ Array DynOS_Gfx_Init(); void DynOS_Gfx_Update(); void DynOS_Gfx_SwapAnimations(void *aPtr); bool DynOS_Gfx_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData); +#ifdef COOP +bool DynOS_Col_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData, DataNode* _Node); +DataNode* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const char *aCollisionName); +#endif GfxData *DynOS_Gfx_LoadFromBinary(const SysPath &aPackFolder, const char *aActorName); void DynOS_Gfx_Free(GfxData *aGfxData); void DynOS_Gfx_GeneratePack(const SysPath &aPackFolder); @@ -678,6 +688,11 @@ void *DynOS_Geo_GetFunctionPointerFromIndex(s32 aIndex); s32 DynOS_Geo_GetFunctionIndex(const void *aPtr); void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory); +#ifdef COOP +void DynOS_Col_AddCollisionCustom(const SysPath &aPackFolder, const char *aCollisionName); +Collision* DynOS_Col_GetCollision(const char* collisionName); +#endif + // // Levels // diff --git a/data/dynos_coop.c.h b/data/dynos_coop.c.h index 2b2d02469..fa5aad25e 100644 --- a/data/dynos_coop.c.h +++ b/data/dynos_coop.c.h @@ -3,6 +3,8 @@ #define DYNOS_COOP_C_H #ifndef __cplusplus +#include "types.h" + bool dynos_warp_to_level(s32 aLevel, s32 aArea, s32 aAct); bool dynos_warp_restart_level(void); bool dynos_warp_exit_level(s32 aDelay); @@ -18,6 +20,9 @@ void dynos_generate_packs(const char* directory); void dynos_add_actor_custom(const char *modPath, const char* geoName); const void* dynos_geolayout_get(const char *name); +void dynos_add_collision_custom(const char *modPath, const char* collisionName); +Collision* dynos_collision_get(const char* collisionName); + #endif #endif #endif diff --git a/data/dynos_coop_c.cpp b/data/dynos_coop_c.cpp index 6909153e0..2a2af5f7d 100644 --- a/data/dynos_coop_c.cpp +++ b/data/dynos_coop_c.cpp @@ -65,5 +65,13 @@ const void* dynos_geolayout_get(const char *name) { return DynOS_Geo_GetActorLayoutFromName(name); } +void dynos_add_collision_custom(const char *modPath, const char* collisionName) { + DynOS_Col_AddCollisionCustom(modPath, collisionName); +} + +Collision* dynos_collision_get(const char* collisionName) { + return DynOS_Col_GetCollision(collisionName); +} + } #endif diff --git a/data/dynos_gfx_load.cpp b/data/dynos_gfx_load.cpp index 97d90bd10..616860666 100644 --- a/data/dynos_gfx_load.cpp +++ b/data/dynos_gfx_load.cpp @@ -315,3 +315,40 @@ GfxData *DynOS_Gfx_LoadFromBinary(const SysPath &aPackFolder, const char *aActor } return _GfxData; } + +#ifdef COOP + +// +// Load collision from binary +// + +static DataNode* LoadCollisionData(FILE *aFile) { + DataNode *_Node = New>(); + + // Name + _Node->mName.Read(aFile); + + // Data + _Node->mSize = ReadBytes(aFile); + _Node->mData = New(_Node->mSize); + for (u32 i = 0; i != _Node->mSize; ++i) { + _Node->mData[i] = ReadBytes(aFile); + } + + return _Node; +} + +DataNode* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const char *aCollisionName) { + // Load data from binary file + DataNode* collisionNode = NULL; + SysPath _Filename = fstring("%s/%s.col", aPackFolder.begin(), aCollisionName); + FILE *_File = fopen(_Filename.c_str(), "rb"); + if (_File) { + collisionNode = LoadCollisionData(_File); + fclose(_File); + } + + return collisionNode; +} + +#endif diff --git a/data/dynos_gfx_read.cpp b/data/dynos_gfx_read.cpp index c5ae7eec0..ab040b052 100644 --- a/data/dynos_gfx_read.cpp +++ b/data/dynos_gfx_read.cpp @@ -1,5 +1,8 @@ #include "dynos.cpp.h" extern "C" { +#ifdef COOP +#include "include/surface_terrains.h" +#endif #include "geo_commands.h" #define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb/stb_image_write.h" @@ -15,6 +18,9 @@ extern "C" { #define LAYER_TRANSPARENT_INTER 7 #define DISPLAY_LIST_SIZE_PER_TOKEN 4 #define GEO_LAYOUT_SIZE_PER_TOKEN 4 +#ifdef COOP +#define COLLISION_SIZE_PER_TOKEN 4 +#endif #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnarrowing" @@ -199,6 +205,10 @@ static void ScanModelFile(GfxData *aGfxData, const SysPath &aFilename) { _DataType = DATA_TYPE_DISPLAY_LIST; } else if (_Buffer == "GeoLayout") { _DataType = DATA_TYPE_GEO_LAYOUT; +#ifdef COOP + } else if (_Buffer == "Collision") { + _DataType = DATA_TYPE_COLLISION; +#endif } else { PrintError(" ERROR: Unknown type name: %s", _Buffer.begin()); } @@ -222,6 +232,9 @@ static void ScanModelFile(GfxData *aGfxData, const SysPath &aFilename) { case DATA_TYPE_VERTEX: AppendNewNode(aGfxData, aGfxData->mVertices, _Buffer, pDataName, pDataTokens); break; case DATA_TYPE_DISPLAY_LIST: AppendNewNode(aGfxData, aGfxData->mDisplayLists, _Buffer, pDataName, pDataTokens); break; case DATA_TYPE_GEO_LAYOUT: AppendNewNode(aGfxData, aGfxData->mGeoLayouts, _Buffer, pDataName, pDataTokens); break; +#ifdef COOP + case DATA_TYPE_COLLISION: AppendNewNode(aGfxData, aGfxData->mCollisions, _Buffer, pDataName, pDataTokens); break; +#endif case DATA_TYPE_UNUSED: pDataTokens = (Array *) 1; break; } _Buffer.Clear(); @@ -1595,6 +1608,208 @@ static DataNode* ParseGeoLayoutData(GfxData* aGfxData, DataNode* aNode, u64& aTokenIndex) { + const String& _Arg = aNode->mTokens[aTokenIndex++]; + + // Surface constants + col_constant(SURFACE_DEFAULT); + col_constant(SURFACE_BURNING); + col_constant(SURFACE_0004); + col_constant(SURFACE_HANGABLE); + col_constant(SURFACE_SLOW); + col_constant(SURFACE_DEATH_PLANE); + col_constant(SURFACE_CLOSE_CAMERA); + col_constant(SURFACE_WATER); + col_constant(SURFACE_FLOWING_WATER); + col_constant(SURFACE_INTANGIBLE); + col_constant(SURFACE_VERY_SLIPPERY); + col_constant(SURFACE_SLIPPERY); + col_constant(SURFACE_NOT_SLIPPERY); + col_constant(SURFACE_TTM_VINES); + col_constant(SURFACE_MGR_MUSIC); + col_constant(SURFACE_INSTANT_WARP_1B); + col_constant(SURFACE_INSTANT_WARP_1C); + col_constant(SURFACE_INSTANT_WARP_1D); + col_constant(SURFACE_INSTANT_WARP_1E); + col_constant(SURFACE_SHALLOW_QUICKSAND); + col_constant(SURFACE_DEEP_QUICKSAND); + col_constant(SURFACE_INSTANT_QUICKSAND); + col_constant(SURFACE_DEEP_MOVING_QUICKSAND); + col_constant(SURFACE_SHALLOW_MOVING_QUICKSAND); + col_constant(SURFACE_QUICKSAND); + col_constant(SURFACE_MOVING_QUICKSAND); + col_constant(SURFACE_WALL_MISC); + col_constant(SURFACE_NOISE_DEFAULT); + col_constant(SURFACE_NOISE_SLIPPERY); + col_constant(SURFACE_HORIZONTAL_WIND); + col_constant(SURFACE_INSTANT_MOVING_QUICKSAND); + col_constant(SURFACE_ICE); + col_constant(SURFACE_LOOK_UP_WARP); + col_constant(SURFACE_HARD); + col_constant(SURFACE_WARP); + col_constant(SURFACE_TIMER_START); + col_constant(SURFACE_TIMER_END); + col_constant(SURFACE_HARD_SLIPPERY); + col_constant(SURFACE_HARD_VERY_SLIPPERY); + col_constant(SURFACE_HARD_NOT_SLIPPERY); + col_constant(SURFACE_VERTICAL_WIND); + col_constant(SURFACE_BOSS_FIGHT_CAMERA); + col_constant(SURFACE_CAMERA_FREE_ROAM); + col_constant(SURFACE_THI3_WALLKICK); + col_constant(SURFACE_CAMERA_8_DIR); + col_constant(SURFACE_CAMERA_MIDDLE); + col_constant(SURFACE_CAMERA_ROTATE_RIGHT); + col_constant(SURFACE_CAMERA_ROTATE_LEFT); + col_constant(SURFACE_CAMERA_BOUNDARY); + col_constant(SURFACE_NOISE_VERY_SLIPPERY_73); + col_constant(SURFACE_NOISE_VERY_SLIPPERY_74); + col_constant(SURFACE_NOISE_VERY_SLIPPERY); + col_constant(SURFACE_NO_CAM_COLLISION); + col_constant(SURFACE_NO_CAM_COLLISION_77); + col_constant(SURFACE_NO_CAM_COL_VERY_SLIPPERY); + col_constant(SURFACE_NO_CAM_COL_SLIPPERY); + col_constant(SURFACE_SWITCH); + col_constant(SURFACE_VANISH_CAP_WALLS); + col_constant(SURFACE_TRAPDOOR); + + // Surface class constants + col_constant(SURFACE_CLASS_DEFAULT); + col_constant(SURFACE_CLASS_VERY_SLIPPERY); + col_constant(SURFACE_CLASS_SLIPPERY); + col_constant(SURFACE_CLASS_NOT_SLIPPERY); + + // Surface flag constants + col_constant(SURFACE_FLAG_DYNAMIC); + col_constant(SURFACE_FLAG_NO_CAM_COLLISION); + col_constant(SURFACE_FLAG_X_PROJECTION); + + // Other constants + col_constant(NULL); + + // Integers + s32 x; + if ((_Arg[1] == 'x' && sscanf(_Arg.begin(), "%x", &x) == 1) || (sscanf(_Arg.begin(), "%d", &x) == 1)) { + return (s16) x; + } + + // Unknown + PrintError(" ERROR: Unknown col arg: %s", _Arg.begin()); + return 0; +} + +#define col_symbol_0(symb) \ + if (_Symbol == #symb) { \ + Collision _Cl[] = { symb() }; \ + memcpy(aHead, _Cl, sizeof(_Cl)); \ + aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \ + return; \ + } + +#define col_symbol_1(symb, n) \ + if (_Symbol == #symb) { \ + s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + if (n != 0) { aGfxData->mPointerList.Add(aHead + n); } \ + Collision _Cl[] = { symb(_Arg0) }; \ + memcpy(aHead, _Cl, sizeof(_Cl)); \ + aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \ + return; \ + } + +#define col_symbol_2(symb, n) \ + if (_Symbol == #symb) { \ + s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + if (n != 0) { aGfxData->mPointerList.Add(aHead + n); } \ + Collision _Cl[] = { symb(_Arg0, _Arg1) }; \ + memcpy(aHead, _Cl, sizeof(_Cl)); \ + aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \ + return; \ + } + +#define col_symbol_3(symb, n) \ + if (_Symbol == #symb) { \ + s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg2 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + if (n != 0) { aGfxData->mPointerList.Add(aHead + n); } \ + Collision _Cl[] = { symb(_Arg0, _Arg1, _Arg2) }; \ + memcpy(aHead, _Cl, sizeof(_Cl)); \ + aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \ + return; \ + } + +#define col_symbol_4(symb, n) \ + if (_Symbol == #symb) { \ + s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg2 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg3 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + if (n != 0) { aGfxData->mPointerList.Add(aHead + n); } \ + Collision _Cl[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3) }; \ + memcpy(aHead, _Cl, sizeof(_Cl)); \ + aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \ + return; \ + } + +#define col_symbol_6(symb, n) \ + if (_Symbol == #symb) { \ + s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg2 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg3 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg4 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + s16 _Arg5 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \ + if (n != 0) { aGfxData->mPointerList.Add(aHead + n); } \ + Collision _Cl[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4, _Arg5) }; \ + memcpy(aHead, _Cl, sizeof(_Cl)); \ + aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \ + return; \ + } + +static void ParseCollisionSymbol(GfxData* aGfxData, DataNode* aNode, Collision*& aHead, u64& aTokenIndex, Array& aSwitchNodes) { + const String& _Symbol = aNode->mTokens[aTokenIndex++]; + + col_symbol_0(COL_INIT); + col_symbol_1(COL_VERTEX_INIT, 0); + col_symbol_3(COL_VERTEX, 0); + col_symbol_2(COL_TRI_INIT, 0); + col_symbol_3(COL_TRI, 0); + col_symbol_4(COL_TRI_SPECIAL, 0); + col_symbol_0(COL_TRI_STOP); + col_symbol_0(COL_END); + col_symbol_1(COL_SPECIAL_INIT, 0); + col_symbol_1(COL_WATER_BOX_INIT, 0); + col_symbol_6(COL_WATER_BOX, 0); + + // Unknown + PrintError(" ERROR: Unknown col symbol: %s", _Symbol.begin()); +} + +static DataNode* ParseCollisionData(GfxData* aGfxData, DataNode* aNode, bool aDisplayPercent) { + if (aNode->mData) return aNode; + + // Collision data + aNode->mData = New(aNode->mTokens.Count() * COLLISION_SIZE_PER_TOKEN); + Collision* _Head = aNode->mData; + Array _SwitchNodes; + for (u64 _TokenIndex = 0; _TokenIndex < aNode->mTokens.Count();) { // Don't increment _TokenIndex here! + ParseCollisionSymbol(aGfxData, aNode, _Head, _TokenIndex, _SwitchNodes); + if (aDisplayPercent && aGfxData->mErrorCount == 0) { PrintNoNewLine("%3d%%\b\b\b\b", (s32) (_TokenIndex * 100) / aNode->mTokens.Count()); } + } + if (aDisplayPercent && aGfxData->mErrorCount == 0) { Print("100%%"); } + aNode->mSize = (u32)(_Head - aNode->mData); + aNode->mLoadIndex = aGfxData->mLoadIndex++; + return aNode; +} + +#endif + // // Animation files // @@ -1783,6 +1998,16 @@ static String GetActorFolder(const Array> &aActorsFolders, u64 } #ifdef COOP + +static DataNode *GetCollision(GfxData *aGfxData, const String& aGeoRoot) { + for (DataNode *_Node : aGfxData->mCollisions) { + if (_Node->mName == aGeoRoot) { + return _Node; + } + } + return NULL; +} + static bool DynOS_Gfx_GeneratePack_Internal(const SysPath &aPackFolder, Array> _ActorsFolders, GfxData *_GfxData, bool onlyConsiderActors) { bool generated = false; for (auto &_GeoNode : _GfxData->mGeoLayouts) { @@ -1853,11 +2078,48 @@ static bool DynOS_Gfx_GeneratePack_Internal(const SysPath &aPackFolder, ArraymVertices); ClearGfxDataNodes(_GfxData->mDisplayLists); ClearGfxDataNodes(_GfxData->mGeoLayouts); + ClearGfxDataNodes(_GfxData->mCollisions); generated = true; } } return generated; } + +static bool DynOS_Gfx_GeneratePack_Collisions(const SysPath &aPackFolder, Array> _ActorsFolders, GfxData *_GfxData) { + bool generated = false; + for (auto &_ColNode : _GfxData->mCollisions) { + String _ColRootName = _ColNode->mName; + DataNode *_ColRoot = GetCollision(_GfxData, _ColRootName); + if (_ColRoot != NULL) { + + // If there is an existing binary file for this collision, skip and go to the next actor + SysPath _ColFilename = fstring("%s/%s.col", aPackFolder.c_str(), _ColRootName.begin()); + if (fs_sys_file_exists(_ColFilename.c_str())) { + continue; + } + + // Init + _GfxData->mErrorCount = 0; + _GfxData->mLoadIndex = 0; + + // Parse data + PrintNoNewLine("%s.col: Model identifier: %X - Processing... ", _ColRootName.begin(), _GfxData->mModelIdentifier); + ParseCollisionData(_GfxData, _ColRoot, true); + + // Write if no error + if (_GfxData->mErrorCount == 0) { + DynOS_Col_WriteBinary(_ColFilename, _GfxData, _ColRoot); + } else { + Print(" %u error(s): Unable to parse data", _GfxData->mErrorCount); + } + // Clear data pointers + ClearGfxDataNodes(_GfxData->mCollisions); + generated = true; + } + } + return generated; +} + #endif void DynOS_Gfx_GeneratePack(const SysPath &aPackFolder) { @@ -1882,6 +2144,9 @@ void DynOS_Gfx_GeneratePack(const SysPath &aPackFolder) { _GfxData->mModelIdentifier = 0; ScanModelFile(_GfxData, fstring("%s/model.inc.c", _Folder.c_str())); ScanModelFile(_GfxData, fstring("%s/geo.inc.c", _Folder.c_str())); +#ifdef COOP + ScanModelFile(_GfxData, fstring("%s/collision.inc.c", _Folder.c_str())); +#endif if (_GfxData->mModelIdentifier != 0) { _ActorsFolders.Add({ _GfxData->mModelIdentifier, String(_PackEnt->d_name) }); } @@ -1892,6 +2157,7 @@ void DynOS_Gfx_GeneratePack(const SysPath &aPackFolder) { // Generate a binary file for each actor found in the GfxData #ifdef COOP + DynOS_Gfx_GeneratePack_Collisions(aPackFolder, _ActorsFolders, _GfxData); bool foundActor = DynOS_Gfx_GeneratePack_Internal(aPackFolder, _ActorsFolders, _GfxData, true); if (!foundActor) { DynOS_Gfx_GeneratePack_Internal(aPackFolder, _ActorsFolders, _GfxData, false); } #else diff --git a/data/dynos_gfx_write.cpp b/data/dynos_gfx_write.cpp index 07ddc2531..52d0cebc6 100644 --- a/data/dynos_gfx_write.cpp +++ b/data/dynos_gfx_write.cpp @@ -239,6 +239,27 @@ static void WriteAnimationTable(FILE* aFile, GfxData* aGfxData) { } } +#ifdef COOP + +// +// Collisions +// + +static void WriteCollisionData(FILE* aFile, GfxData* aGfxData, DataNode *aNode) { + if (!aNode->mData) return; + + // Name + aNode->mName.Write(aFile); + + // Data + WriteBytes(aFile, aNode->mSize); + for (u32 i = 0; i != aNode->mSize; ++i) { + WriteBytes(aFile, aNode->mData[i]); + } +} + +#endif + // // Write // @@ -283,6 +304,23 @@ bool DynOS_Gfx_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData) { return true; } +#ifdef COOP + +bool DynOS_Col_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData, DataNode* _Node) { + FILE *_File = fopen(aOutputFilename.c_str(), "wb"); + if (!_File) { + PrintError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str()); + return false; + } + + WriteCollisionData(_File, aGfxData, _Node); + + fclose(_File); + return true; +} + +#endif + // // Free // diff --git a/data/dynos_misc.cpp b/data/dynos_misc.cpp index 583f86a5f..252c94280 100644 --- a/data/dynos_misc.cpp +++ b/data/dynos_misc.cpp @@ -593,3 +593,42 @@ void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory) { free(_Pool); return NULL; } + +#ifdef COOP + +// Collisions + +static Array*>> sDynosCustomCollisions; + +void DynOS_Col_AddCollisionCustom(const SysPath &aPackFolder, const char *aCollisionName) { + // check for duplicates + for (s32 i = 0; i < sDynosCustomCollisions.Count(); ++i) { + if (!strcmp(sDynosCustomCollisions[i].first, aCollisionName)) { + return; + } + } + + u16 collisionLen = strlen(aCollisionName); + char* collisionName = (char*)calloc(1, sizeof(char) * (collisionLen + 1)); + strcpy(collisionName, aCollisionName); + + DataNode* _Node = DynOS_Col_LoadFromBinary(aPackFolder, collisionName); + if (!_Node) { + free(collisionName); + return; + } + + // Add to custom collisions + sDynosCustomCollisions.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; + } + } + return NULL; +} + +#endif diff --git a/docs/lua/functions.md b/docs/lua/functions.md index a8c66d809..fc59ca4f5 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -713,6 +713,7 @@ - smlua_collision_utils.h - [collision_find_surface_on_ray](#collision_find_surface_on_ray) - [get_water_surface_pseudo_floor](#get_water_surface_pseudo_floor) + - [smlua_collision_util_get](#smlua_collision_util_get)
@@ -3752,7 +3753,7 @@ The `reliable` field will ensure that the packet arrives, but should be used spa - `string` ### C Prototype -`const char* get_level_name(s16 courseNum, s16 levelNum, s16 areaIndex);` +`const char *get_level_name(s16 courseNum, s16 levelNum, s16 areaIndex);` [:arrow_up_small:](#) @@ -13445,6 +13446,26 @@ The `reliable` field will ensure that the packet arrives, but should be used spa
+## [smlua_collision_util_get](#smlua_collision_util_get) + +### Lua Example +`local PointerValue = smlua_collision_util_get(name)` + +### Parameters +| Field | Type | +| ----- | ---- | +| name | `string` | + +### Returns +- `Pointer` <`Collision`> + +### C Prototype +`Collision* smlua_collision_util_get(const char* name);` + +[:arrow_up_small:](#) + +
+ --- # functions from smlua_misc_utils.h diff --git a/include/types.h b/include/types.h index 9a0a3bebf..f077e9bb7 100644 --- a/include/types.h +++ b/include/types.h @@ -7,7 +7,6 @@ #include #include "macros.h" #include "data/dynos.c.h" -#include "data/dynos_coop.c.h" #include "pc/network/version.h" // Certain functions are marked as having return values, but do not @@ -406,5 +405,6 @@ struct TextureInfo #define COOP_OBJ_FLAG_NON_SYNC (1 << 2) #include "src/game/characters.h" +#include "data/dynos_coop.c.h" #endif // _SM64_TYPES_H_ diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index d498b3355..5e268201a 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -9096,6 +9096,17 @@ int smlua_func_get_water_surface_pseudo_floor(UNUSED lua_State* L) { return 1; } +int smlua_func_smlua_collision_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_COLLISION_P, (void*)smlua_collision_util_get(name)); + + return 1; +} + //////////////////////// // smlua_misc_utils.h // //////////////////////// @@ -10603,6 +10614,7 @@ void smlua_bind_functions_autogen(void) { // smlua_collision_utils.h smlua_bind_function(L, "collision_find_surface_on_ray", smlua_func_collision_find_surface_on_ray); smlua_bind_function(L, "get_water_surface_pseudo_floor", smlua_func_get_water_surface_pseudo_floor); + smlua_bind_function(L, "smlua_collision_util_get", smlua_func_smlua_collision_util_get); // smlua_misc_utils.h smlua_bind_function(L, "allocate_mario_action", smlua_func_allocate_mario_action); diff --git a/src/pc/lua/utils/smlua_collision_utils.c b/src/pc/lua/utils/smlua_collision_utils.c index f1c5ef719..01818efd7 100644 --- a/src/pc/lua/utils/smlua_collision_utils.c +++ b/src/pc/lua/utils/smlua_collision_utils.c @@ -165,3 +165,7 @@ struct RayIntersectionInfo* collision_find_surface_on_ray(f32 startX, f32 startY struct Surface* get_water_surface_pseudo_floor(void) { return &gWaterSurfacePseudoFloor; } + +Collision* smlua_collision_util_get(const char* name) { + return dynos_collision_get(name); +} diff --git a/src/pc/lua/utils/smlua_collision_utils.h b/src/pc/lua/utils/smlua_collision_utils.h index 6ac1f61be..f3da975bb 100644 --- a/src/pc/lua/utils/smlua_collision_utils.h +++ b/src/pc/lua/utils/smlua_collision_utils.h @@ -114,4 +114,6 @@ struct RayIntersectionInfo* collision_find_surface_on_ray(f32 startX, f32 startY struct Surface* get_water_surface_pseudo_floor(void); +Collision* smlua_collision_util_get(const char* name); + #endif diff --git a/src/pc/mods/mod.c b/src/pc/mods/mod.c index 79b37b297..5482cfe2c 100644 --- a/src/pc/mods/mod.c +++ b/src/pc/mods/mod.c @@ -5,40 +5,74 @@ #include "pc/utils/misc.h" #include "pc/debuglog.h" +static void mod_activate_bin(struct Mod* mod, struct ModFile* file) { + char dynosPath[SYS_MAX_PATH] = { 0 }; + if (snprintf(dynosPath, SYS_MAX_PATH - 1, "%s/actors", mod->basePath) < 0) { + LOG_ERROR("Failed to concat dynos path"); + return; + } + + // copy geo name + char geoName[64] = { 0 }; + if (snprintf(geoName, 63, "%s", path_basename(file->relativePath)) < 0) { + LOG_ERROR("Truncated geo name"); + return; + } + + // remove '.bin' + char* g = geoName; + while (*g != '\0') { + if (*g == '.') { + *g = '\0'; + break; + } + g++; + } + + // Add to custom actors + dynos_add_actor_custom(dynosPath, geoName); + LOG_INFO("Activating DynOS bin: '%s', '%s'", dynosPath, geoName); +} + +static void mod_activate_col(struct Mod* mod, struct ModFile* file) { + char dynosPath[SYS_MAX_PATH] = { 0 }; + if (snprintf(dynosPath, SYS_MAX_PATH - 1, "%s/actors", mod->basePath) < 0) { + LOG_ERROR("Failed to concat dynos path"); + return; + } + + // copy geo name + char colName[64] = { 0 }; + if (snprintf(colName, 63, "%s", path_basename(file->relativePath)) < 0) { + LOG_ERROR("Truncated col name"); + return; + } + + // remove '.col' + char* g = colName; + while (*g != '\0') { + if (*g == '.') { + *g = '\0'; + break; + } + g++; + } + + // Add to custom actors + dynos_add_collision_custom(dynosPath, colName); + LOG_INFO("Activating DynOS col: '%s', '%s'", dynosPath, colName); +} + void mod_activate(struct Mod* mod) { // activate dynos models for (int i = 0; i < mod->fileCount; i++) { struct ModFile* file = &mod->files[i]; - if (!str_ends_with(file->relativePath, ".bin")) { - continue; + if (str_ends_with(file->relativePath, ".bin")) { + mod_activate_bin(mod, file); } - - char dynosPath[SYS_MAX_PATH] = { 0 }; - if (snprintf(dynosPath, SYS_MAX_PATH - 1, "%s/actors", mod->basePath) < 0) { - LOG_ERROR("Failed to concat dynos path"); - continue; + if (str_ends_with(file->relativePath, ".col")) { + mod_activate_col(mod, file); } - - // copy geo name - char geoName[64] = { 0 }; - if (snprintf(geoName, 63, "%s", path_basename(file->relativePath)) < 0) { - LOG_ERROR("Truncated geo name"); - continue; - } - - // remove '.bin' - char* g = geoName; - while (*g != '\0') { - if (*g == '.') { - *g = '\0'; - break; - } - g++; - } - - // Add to custom actors - dynos_add_actor_custom(dynosPath, geoName); - LOG_INFO("Activating DynOS: '%s', '%s'", dynosPath, geoName); } } @@ -181,8 +215,8 @@ static bool mod_load_files(struct Mod* mod, char* modName, char* fullPath) { return false; } - // only consider bin files - if (!str_ends_with(path, ".bin")) { + // only consider bin and col files + if (!str_ends_with(path, ".bin") && !str_ends_with(path, ".col")) { continue; }