mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-02-22 05:21:05 +00:00
Add custom collisions to DynOS/Lua
This commit is contained in:
parent
0bb48cb6e7
commit
d74f5cfe61
14 changed files with 520 additions and 32 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<Vtx> mVertices;
|
||||
DataNodes<Gfx> mDisplayLists;
|
||||
DataNodes<GeoLayout> mGeoLayouts;
|
||||
#ifdef COOP
|
||||
DataNodes<Collision> mCollisions;
|
||||
#endif
|
||||
|
||||
// Animation data
|
||||
Array<AnimBuffer<s16> *> mAnimValues;
|
||||
|
|
@ -645,6 +651,10 @@ Array<String> 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<Collision>* _Node);
|
||||
DataNode<Collision>* 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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -315,3 +315,40 @@ GfxData *DynOS_Gfx_LoadFromBinary(const SysPath &aPackFolder, const char *aActor
|
|||
}
|
||||
return _GfxData;
|
||||
}
|
||||
|
||||
#ifdef COOP
|
||||
|
||||
//
|
||||
// Load collision from binary
|
||||
//
|
||||
|
||||
static DataNode<Collision>* LoadCollisionData(FILE *aFile) {
|
||||
DataNode<Collision> *_Node = New<DataNode<Collision>>();
|
||||
|
||||
// Name
|
||||
_Node->mName.Read(aFile);
|
||||
|
||||
// Data
|
||||
_Node->mSize = ReadBytes<u32>(aFile);
|
||||
_Node->mData = New<Collision>(_Node->mSize);
|
||||
for (u32 i = 0; i != _Node->mSize; ++i) {
|
||||
_Node->mData[i] = ReadBytes<Collision>(aFile);
|
||||
}
|
||||
|
||||
return _Node;
|
||||
}
|
||||
|
||||
DataNode<Collision>* DynOS_Col_LoadFromBinary(const SysPath &aPackFolder, const char *aCollisionName) {
|
||||
// Load data from binary file
|
||||
DataNode<Collision>* 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
|
||||
|
|
|
|||
|
|
@ -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<String> *) 1; break;
|
||||
}
|
||||
_Buffer.Clear();
|
||||
|
|
@ -1595,6 +1608,208 @@ static DataNode<GeoLayout>* ParseGeoLayoutData(GfxData* aGfxData, DataNode<GeoLa
|
|||
return aNode;
|
||||
}
|
||||
|
||||
#ifdef COOP
|
||||
//
|
||||
// Collision files
|
||||
//
|
||||
|
||||
#define col_constant(x) if (_Arg == #x) { return (s16) (x); }
|
||||
static s16 ParseColSymbolArg(GfxData* aGfxData, DataNode<Collision>* 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<Collision>* aNode, Collision*& aHead, u64& aTokenIndex, Array<u64>& 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<Collision>* ParseCollisionData(GfxData* aGfxData, DataNode<Collision>* aNode, bool aDisplayPercent) {
|
||||
if (aNode->mData) return aNode;
|
||||
|
||||
// Collision data
|
||||
aNode->mData = New<Collision>(aNode->mTokens.Count() * COLLISION_SIZE_PER_TOKEN);
|
||||
Collision* _Head = aNode->mData;
|
||||
Array<u64> _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<Pair<u64, String>> &aActorsFolders, u64
|
|||
}
|
||||
|
||||
#ifdef COOP
|
||||
|
||||
static DataNode<Collision> *GetCollision(GfxData *aGfxData, const String& aGeoRoot) {
|
||||
for (DataNode<Collision> *_Node : aGfxData->mCollisions) {
|
||||
if (_Node->mName == aGeoRoot) {
|
||||
return _Node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool DynOS_Gfx_GeneratePack_Internal(const SysPath &aPackFolder, Array<Pair<u64, String>> _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, Array<Pa
|
|||
ClearGfxDataNodes(_GfxData->mVertices);
|
||||
ClearGfxDataNodes(_GfxData->mDisplayLists);
|
||||
ClearGfxDataNodes(_GfxData->mGeoLayouts);
|
||||
ClearGfxDataNodes(_GfxData->mCollisions);
|
||||
generated = true;
|
||||
}
|
||||
}
|
||||
return generated;
|
||||
}
|
||||
|
||||
static bool DynOS_Gfx_GeneratePack_Collisions(const SysPath &aPackFolder, Array<Pair<u64, String>> _ActorsFolders, GfxData *_GfxData) {
|
||||
bool generated = false;
|
||||
for (auto &_ColNode : _GfxData->mCollisions) {
|
||||
String _ColRootName = _ColNode->mName;
|
||||
DataNode<Collision> *_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
|
||||
|
|
|
|||
|
|
@ -239,6 +239,27 @@ static void WriteAnimationTable(FILE* aFile, GfxData* aGfxData) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef COOP
|
||||
|
||||
//
|
||||
// Collisions
|
||||
//
|
||||
|
||||
static void WriteCollisionData(FILE* aFile, GfxData* aGfxData, DataNode<Collision> *aNode) {
|
||||
if (!aNode->mData) return;
|
||||
|
||||
// Name
|
||||
aNode->mName.Write(aFile);
|
||||
|
||||
// Data
|
||||
WriteBytes<u32>(aFile, aNode->mSize);
|
||||
for (u32 i = 0; i != aNode->mSize; ++i) {
|
||||
WriteBytes<Collision>(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<Collision>* _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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -593,3 +593,42 @@ void *DynOS_Geo_GetGraphNode(const void *aGeoLayout, bool aKeepInMemory) {
|
|||
free(_Pool);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef COOP
|
||||
|
||||
// Collisions
|
||||
|
||||
static Array<Pair<const char*, DataNode<Collision>*>> 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<Collision>* _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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
<br />
|
||||
|
||||
|
|
@ -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
|
|||
|
||||
<br />
|
||||
|
||||
## [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:](#)
|
||||
|
||||
<br />
|
||||
|
||||
---
|
||||
# functions from smlua_misc_utils.h
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#include <ultra64.h>
|
||||
#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_
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue