Added a full new custom behavior system (#124)

This commit is contained in:
Prince Frizzy 2022-06-02 15:19:54 -04:00 committed by GitHub
parent a943b8cdde
commit 40e1fa9e58
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 5734 additions and 363 deletions

View file

@ -59,285 +59,7 @@
#include "make_const_nonconst.h"
#include "behavior_data.h"
#include "behavior_table.h"
#define BC_B(a) _SHIFTL(a, 24, 8)
#define BC_BB(a, b) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8))
#define BC_BBBB(a, b, c, d) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 8, 8) | _SHIFTL(d, 0, 8))
#define BC_BBH(a, b, c) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 0, 16))
#define BC_B0H(a, b) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 0, 16))
#define BC_H(a) _SHIFTL(a, 16, 16)
#define BC_HH(a, b) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 0, 16))
#define BC_W(a) ((uintptr_t)(u32)(a))
#define BC_PTR(a) ((uintptr_t)(a))
// Defines the id of the behavior script
#define ID(id) \
BC_B0H(0x39, id)
// Defines the start of the behavior script as well as the object list the object belongs to.
// Has some special behavior for certain objects.
#define BEGIN(objList) \
BC_BB(0x00, objList)
// Delays the behavior script for a certain number of frames.
#define DELAY(num) \
BC_B0H(0x01, num)
// Jumps to a new behavior command and stores the return address in the object's stack.
#define CALL(addr) \
BC_B(0x02), \
BC_PTR(addr)
// Jumps back to the behavior command stored in the object's stack.
#define RETURN() \
BC_B(0x03)
// Jumps to a new behavior script without saving anything.
#define GOTO(addr) \
BC_B(0x04), \
BC_PTR(addr)
// Marks the start of a loop that will repeat a certain number of times.
#define BEGIN_REPEAT(count) \
BC_B0H(0x05, count)
// Marks the end of a repeating loop.
#define END_REPEAT() \
BC_B(0x06)
// Also marks the end of a repeating loop, but continues executing commands following the loop on the same frame.
#define END_REPEAT_CONTINUE() \
BC_B(0x07)
// Marks the beginning of an infinite loop.
#define BEGIN_LOOP() \
BC_B(0x08)
// Marks the end of an infinite loop.
#define END_LOOP() \
BC_B(0x09)
// Exits the behavior script.
// Often used to end behavior scripts that do not contain an infinite loop.
#define BREAK() \
BC_B(0x0A)
// Exits the behavior script, unused.
#define BREAK_UNUSED() \
BC_B(0x0B)
// Executes a native game function.
#define CALL_NATIVE(func) \
BC_B(0x0C), \
BC_PTR(func)
// Adds a float to the specified field.
#define ADD_FLOAT(field, value) \
BC_BBH(0x0D, field, value)
// Sets the specified field to a float.
#define SET_FLOAT(field, value) \
BC_BBH(0x0E, field, value)
// Adds an integer to the specified field.
#define ADD_INT(field, value) \
BC_BBH(0x0F, field, value)
// Sets the specified field to an integer.
#define SET_INT(field, value) \
BC_BBH(0x10, field, value)
// Performs a bitwise OR with the specified field and the given integer.
// Usually used to set an object's flags.
#define OR_INT(field, value) \
BC_BBH(0x11, field, value)
// Performs a bit clear with the specified short. Unused in favor of the 32-bit version.
#define BIT_CLEAR(field, value) \
BC_BBH(0x12, field, value)
// TODO: this one needs a better name / labelling
// Gets a random short, right shifts it the specified amount and adds min to it, then sets the specified field to that value.
#define SET_INT_RAND_RSHIFT(field, min, rshift) \
BC_BBH(0x13, field, min), \
BC_H(rshift)
// Sets the specified field to a random float in the given range.
#define SET_RANDOM_FLOAT(field, min, range) \
BC_BBH(0x14, field, min), \
BC_H(range)
// Sets the specified field to a random integer in the given range.
#define SET_RANDOM_INT(field, min, range) \
BC_BBH(0x15, field, min), \
BC_H(range)
// Adds a random float in the given range to the specified field.
#define ADD_RANDOM_FLOAT(field, min, range) \
BC_BBH(0x16, field, min), \
BC_H(range)
// TODO: better name (unused anyway)
// Gets a random short, right shifts it the specified amount and adds min to it, then adds the value to the specified field. Unused.
#define ADD_INT_RAND_RSHIFT(field, min, rshift) \
BC_BBH(0x17, field, min), \
BC_H(rshift)
// No operation. Unused.
#define CMD_NOP_1(field) \
BC_BB(0x18, field)
// No operation. Unused.
#define CMD_NOP_2(field) \
BC_BB(0x19, field)
// No operation. Unused.
#define CMD_NOP_3(field) \
BC_BB(0x1A, field)
// Sets the current model ID of the object.
#define SET_MODEL(modelID) \
BC_B0H(0x1B, modelID)
// Spawns a child object with the specified model and behavior.
#define SPAWN_CHILD(modelID, behavior) \
BC_B(0x1C), \
BC_W(modelID), \
BC_PTR(behavior)
// Exits the behavior script and despawns the object.
// Often used to end behavior scripts that do not contain an infinite loop.
#define DEACTIVATE() \
BC_B(0x1D)
// Finds the floor triangle directly under the object and moves the object down to it.
#define DROP_TO_FLOOR() \
BC_B(0x1E)
// Sets the destination float field to the sum of the values of the given float fields.
#define SUM_FLOAT(fieldDst, fieldSrc1, fieldSrc2) \
BC_BBBB(0x1F, fieldDst, fieldSrc1, fieldSrc2)
// Sets the destination integer field to the sum of the values of the given integer fields. Unused.
#define SUM_INT(fieldDst, fieldSrc1, fieldSrc2) \
BC_BBBB(0x20, fieldDst, fieldSrc1, fieldSrc2)
// Billboards the current object, making it always face the camera.
#define BILLBOARD() \
BC_B(0x21)
#define CYLBOARD() \
BC_B(0x38)
// Hides the current object.
#define HIDE() \
BC_B(0x22)
// Sets the size of the object's cylindrical hitbox.
#define SET_HITBOX(radius, height) \
BC_B(0x23), \
BC_HH(radius, height)
// No operation. Unused.
#define CMD_NOP_4(field, value) \
BC_BBH(0x24, field, value)
// Delays the behavior script for the number of frames given by the value of the specified field.
#define DELAY_VAR(field) \
BC_BB(0x25, field)
// Unused. Marks the start of a loop that will repeat a certain number of times.
// Uses a u8 as the argument, instead of a s16 like the other version does.
#define BEGIN_REPEAT_UNUSED(count) \
BC_BB(0x26, count)
// Loads the animations for the object. <field> is always set to oAnimations.
#define LOAD_ANIMATIONS(field, anims) \
BC_BB(0x27, field), \
BC_PTR(anims)
// Begins animation and sets the object's current animation index to the specified value.
#define ANIMATE(animIndex) \
BC_BB(0x28, animIndex)
// Spawns a child object with the specified model and behavior, plus a behavior param.
#define SPAWN_CHILD_WITH_PARAM(bhvParam, modelID, behavior) \
BC_B0H(0x29, bhvParam), \
BC_W(modelID), \
BC_PTR(behavior)
// Loads collision data for the object.
#define LOAD_COLLISION_DATA(collisionData) \
BC_B(0x2A), \
BC_PTR(collisionData)
// Sets the size of the object's cylindrical hitbox, and applies a downwards offset.
#define SET_HITBOX_WITH_OFFSET(radius, height, downOffset) \
BC_B(0x2B), \
BC_HH(radius, height), \
BC_H(downOffset)
// Spawns a new object with the specified model and behavior.
#define SPAWN_OBJ(modelID, behavior) \
BC_B(0x2C), \
BC_W(modelID), \
BC_PTR(behavior)
// Sets the home position of the object to its current position.
#define SET_HOME() \
BC_B(0x2D)
// Sets the size of the object's cylindrical hurtbox.
#define SET_HURTBOX(radius, height) \
BC_B(0x2E), \
BC_HH(radius, height)
// Sets the object's interaction type.
#define SET_INTERACT_TYPE(type) \
BC_B(0x2F), \
BC_W(type)
// Sets various parameters that the object uses for calculating physics.
#define SET_OBJ_PHYSICS(wallHitboxRadius, gravity, bounciness, dragStrength, friction, buoyancy, unused1, unused2) \
BC_B(0x30), \
BC_HH(wallHitboxRadius, gravity), \
BC_HH(bounciness, dragStrength), \
BC_HH(friction, buoyancy), \
BC_HH(unused1, unused2)
// Sets the object's interaction subtype. Unused.
#define SET_INTERACT_SUBTYPE(subtype) \
BC_B(0x31), \
BC_W(subtype)
// Sets the object's size to the specified percentage.
#define SCALE(unusedField, percent) \
BC_BBH(0x32, unusedField, percent)
// Performs a bit clear on the object's parent's field with the specified value.
// Used for clearing active particle flags fron Mario's object.
#define PARENT_BIT_CLEAR(field, flags) \
BC_BB(0x33, field), \
BC_W(flags)
// Animates an object using texture animation. <field> is always set to oAnimState.
#define ANIMATE_TEXTURE(field, rate) \
BC_BBH(0x34, field, rate)
// Disables rendering for the object.
#define DISABLE_RENDERING() \
BC_B(0x35)
// Unused. Sets the specified field to an integer. Wastes 4 bytes of space for no reason at all.
#define SET_INT_UNUSED(field, value) \
BC_BB(0x36, field), \
BC_HH(0, value)
// Spawns a water droplet with the given parameters.
#define SPAWN_WATER_DROPLET(dropletParams) \
BC_B(0x37), \
BC_PTR(dropletParams)
#include "behavior_commands.h"
const BehaviorScript bhvStarDoor[] = {

View file

@ -563,7 +563,7 @@ enum BehaviorId get_id_from_vanilla_behavior(const BehaviorScript* behavior) {
}
const BehaviorScript* get_behavior_from_id(enum BehaviorId id) {
const BehaviorScript* behavior = get_lua_behavior_from_id(id, true);
const BehaviorScript* behavior = get_hooked_behavior_from_id(id, true);
if (behavior != NULL) { return behavior; }
if (id < 0 || id >= id_bhv_max_count) {

View file

@ -4,6 +4,7 @@
#include "dynos.h"
#include "types.h"
#include "engine/behavior_script.h"
#include "src/game/moving_texture.h"
void *dynos_swap_cmd(void *cmd);
@ -54,6 +55,12 @@ const char* dynos_level_get_token(u32 index);
Trajectory* dynos_level_get_trajectory(const char* name);
void dynos_level_load_background(void *ptr);
// -- behaviors -- //
void dynos_add_behavior(s32 modIndex, const char *filePath, const char *behaviorName);
s32 dynos_behavior_get_active_mod_index(BehaviorScript *bhvScript);
const char *dynos_behavior_get_token(BehaviorScript *bhvScript, u32 index);
void dynos_behavior_hook_all_custom_behaviors(void);
// -- other -- //
void dynos_mod_shutdown(void);

View file

@ -3,7 +3,11 @@
#ifdef __cplusplus
#include "dynos.h"
#include <string>
extern "C" {
#include "engine/behavior_script.h"
#include "engine/math_util.h"
#include "src/game/moving_texture.h"
}
@ -42,6 +46,7 @@ enum {
DATA_TYPE_AMBIENT_T,
DATA_TYPE_TEXTURE_LIST,
DATA_TYPE_TEXTURE_RAW,
DATA_TYPE_BEHAVIOR_SCRIPT,
DATA_TYPE_UNUSED,
};
@ -190,7 +195,7 @@ private:
// A fixed-size string that doesn't require heap memory allocation
//
#define STRING_SIZE 127
#define STRING_SIZE 256
class String {
public:
inline String() : mCount(0) {
@ -418,6 +423,7 @@ struct GfxData : NoCopy {
DataNodes<Gfx> mDisplayLists;
DataNodes<GeoLayout> mGeoLayouts;
DataNodes<Collision> mCollisions;
DataNodes<BehaviorScript> mBehaviorScripts;
DataNodes<LevelScript> mLevelScripts;
DataNodes<MacroObject> mMacroObjects;
DataNodes<Trajectory> mTrajectories;
@ -548,13 +554,6 @@ void Delete(T *& aPtr) {
aPtr = NULL;
}
template <typename T>
T *CopyBytes(const T *aPtr, u64 aSize) {
T *_Ptr = (T *) calloc(1, aSize);
memcpy(_Ptr, aPtr, aSize);
return _Ptr;
}
template <typename T = void>
Array<String> Split(const char *aBuffer, const String &aDelimiters, const String &aEndCharacters = {}, bool aHandleDoubleQuotedStrings = false) {
Array<String> _Tokens;
@ -585,18 +584,35 @@ Array<String> Split(const char *aBuffer, const String &aDelimiters, const String
return _Tokens;
}
template <typename T>
T *CopyBytes(const T *aPtr, u64 aSize) {
T *_Ptr = (T *) calloc(1, aSize);
memcpy(_Ptr, aPtr, aSize);
return _Ptr;
}
template <typename T>
T ReadBytes(FILE* aFile) {
T _Item = { 0 };
fread(&_Item, sizeof(T), 1, aFile);
// If we're at end of file. Just return the default.
if (feof(aFile)) { return _Item; }
size_t nread = fread(&_Item, sizeof(T), 1, aFile);
// If we failed to read bytes. Print the error.
//if (nread != sizeof(T)) { perror("The following error occured when reading bytes"); }
return _Item;
}
template <typename T>
void WriteBytes(FILE* aFile, const T& aItem) {
fwrite(&aItem, sizeof(T), 1, aFile);
size_t nwrote = fwrite(&aItem, sizeof(T), 1, aFile);
// If we failed to write bytes. Print the error.
//if (nwrote != sizeof(T)) { perror("The following error occured when writing bytes"); }
}
void SkipBytes(FILE *aFile, size_t amount);
template <typename... Args>
void PrintNoNewLine(const char *aFmt, Args... aArgs) {
printf(aFmt, aArgs...);
@ -734,14 +750,17 @@ const char* DynOS_Builtin_Actor_GetNameFromIndex(s32 aIndex);
s32 DynOS_Builtin_Actor_GetCount();
const GeoLayout* DynOS_Builtin_LvlGeo_GetFromName(const char* aDataName);
const char* DynOS_Builtin_LvlGeo_GetFromData(const GeoLayout* aData);
const Collision* DynOS_Builtin_LvlCol_GetFromName(const char* aDataName);
const char* DynOS_Builtin_LvlCol_GetFromData(const Collision* aData);
const Collision* DynOS_Builtin_Col_GetFromName(const char* aDataName);
const char* DynOS_Builtin_Col_GetFromData(const Collision* aData);
const Animation *DynOS_Builtin_Anim_GetFromName(const char *aDataName);
const char * DynOS_Builtin_Anim_GetFromData(const Animation *aData);
const Texture* DynOS_Builtin_Tex_GetFromName(const char* aDataName);
const char* DynOS_Builtin_Tex_GetFromData(const Texture* aData);
const char* DynOS_Builtin_Tex_GetNameFromFileName(const char* aDataName);
const struct BuiltinTexInfo* DynOS_Builtin_Tex_GetInfoFromName(const char* aDataName);
const void* DynOS_Builtin_Func_GetFromName(const char* aDataName);
const void* DynOS_Builtin_Func_GetFromIndex(s32 aIndex);
const char * DynOS_Builtin_Func_GetNameFromIndex(s64 aIndex);
s32 DynOS_Builtin_Func_GetIndexFromData(const void* aData);
//
@ -807,6 +826,18 @@ void DynOS_Lvl_LoadBackground(void *aPtr);
void* DynOS_Lvl_Override(void *aCmd);
void DynOS_Lvl_ModShutdown();
//
// Bhv Manager
//
Array<Pair<const char *, GfxData *>> &DynOS_Bhv_GetArray();
void DynOS_Bhv_Activate(s32 modIndex, const SysPath &aFilename, const char *aBehaviorName);
GfxData *DynOS_Bhv_GetActiveGfx(BehaviorScript *bhvScript);
s32 DynOS_Bhv_GetActiveModIndex(BehaviorScript *bhvScript);
const char *DynOS_Bhv_GetToken(BehaviorScript *bhvScript, u32 index);
void DynOS_Bhv_HookAllCustomBehaviors();
void DynOS_Bhv_ModShutdown();
//
// Col Manager
//
@ -921,5 +952,11 @@ GfxData *DynOS_Lvl_LoadFromBinary(const SysPath &aFilename, const char *aLevelNa
void DynOS_Lvl_GeneratePack(const SysPath &aPackFolder);
s64 DynOS_Lvl_ParseLevelScriptConstants(const String& _Arg, bool* found);
DataNode<BehaviorScript> *DynOS_Bhv_Parse(GfxData *aGfxData, DataNode<BehaviorScript> *aNode, bool aDisplayPercent);
GfxData *DynOS_Bhv_LoadFromBinary(const SysPath &aFilename, const char *aBehaviorName);
void DynOS_Bhv_GeneratePack(const SysPath &aPackFolder);
s64 DynOS_Bhv_ParseBehaviorScriptConstants(const String &_Arg, bool *found);
s64 DynOS_Bhv_ParseBehaviorIntegerScriptConstants(const String &_Arg, bool *found);
#endif
#endif

3739
data/dynos_bin_behavior.cpp Normal file

File diff suppressed because it is too large Load diff

View file

@ -1494,8 +1494,8 @@ static LevelScript ParseLevelScriptSymbolArgInternal(GfxData* aGfxData, DataNode
return (LevelScript)builtinGeo;
}
// Built-in Lvl Cols
auto builtinCol = DynOS_Builtin_LvlCol_GetFromName(_Arg.begin());
// Built-in Cols
auto builtinCol = DynOS_Builtin_Col_GetFromName(_Arg.begin());
if (builtinCol != NULL) {
return (LevelScript)builtinCol;
}

View file

@ -71,7 +71,7 @@ static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) {
return { _Node->mName, 0 };
}
}
// Collisions
for (auto& _Node : aGfxData->mCollisions) {
if (_Node->mData == aPtr) {
@ -132,11 +132,17 @@ static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) {
return { builtinGeo, 0 };
}
// Built-in Lvl Cols
auto builtinCol = DynOS_Builtin_LvlCol_GetFromData((const Collision*)aPtr);
// Built-in Cols
auto builtinCol = DynOS_Builtin_Col_GetFromData((const Collision*)aPtr);
if (builtinCol != NULL) {
return { builtinCol, 0 };
}
// Built-in Animations
auto builtinAnim = DynOS_Builtin_Anim_GetFromData((const Animation *)aPtr);
if (builtinAnim != NULL) {
return { builtinAnim, 0 };
}
// Built-in Script Pointers
auto builtinScriptPtr = DynOS_Builtin_ScriptPtr_GetFromData(aPtr);
@ -177,7 +183,7 @@ static PointerData GetDataFromPointer(const void* aPtr, GfxData* aGfxData) {
}
}
PrintError("Unable to find pointer!");
PrintError("Unable to find pointer %x!", aPtr);
return { "", 0 };
}
@ -320,6 +326,13 @@ static void *GetPointerFromData(GfxData *aGfxData, const String &aPtrName, u32 a
return (void *) (_Node->mData + aPtrData);
}
}
// Behavior scripts
for (auto &_Node : aGfxData->mBehaviorScripts) {
if (_Node->mName == aPtrName) {
return (void *) _Node->mData;
}
}
// Macro objects
for (auto &_Node : aGfxData->mMacroObjects) {
@ -356,7 +369,7 @@ static void *GetPointerFromData(GfxData *aGfxData, const String &aPtrName, u32 a
}
}
// Behaviors
// Lua 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);
@ -374,11 +387,17 @@ static void *GetPointerFromData(GfxData *aGfxData, const String &aPtrName, u32 a
return (void*)builtinGeo;
}
// Built-in Lvl Cols
auto builtinCol = DynOS_Builtin_LvlCol_GetFromName(aPtrName.begin());
// Built-in Cols
auto builtinCol = DynOS_Builtin_Col_GetFromName(aPtrName.begin());
if (builtinCol != NULL) {
return (void*)builtinCol;
}
// Built-in Animations
auto builtinAnim = DynOS_Builtin_Anim_GetFromName(aPtrName.begin());
if (builtinAnim != NULL) {
return (void *)builtinAnim;
}
// Built-in Script Pointers
auto builtinScriptPtr = DynOS_Builtin_ScriptPtr_GetFromName(aPtrName.begin());

View file

@ -214,6 +214,8 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) {
_DataType = DATA_TYPE_MOVTEX;
} else if (_Buffer == "MovtexQuadCollection") {
_DataType = DATA_TYPE_MOVTEXQC;
} else if (_Buffer == "BehaviorScript") {
_DataType = DATA_TYPE_BEHAVIOR_SCRIPT;
} else {
PrintError(" ERROR: Unknown type name: %s", _Buffer.begin());
}
@ -237,22 +239,23 @@ void DynOS_Read_Source(GfxData *aGfxData, const SysPath &aFilename) {
// Adding new data node
else if (_Buffer.Length() != 0) {
switch (_DataType) {
case DATA_TYPE_LIGHT: AppendNewNode(aGfxData, aGfxData->mLights, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_LIGHT_T: AppendNewNode(aGfxData, aGfxData->mLightTs, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_AMBIENT_T: AppendNewNode(aGfxData, aGfxData->mAmbientTs, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_TEXTURE: AppendNewNode(aGfxData, aGfxData->mTextures, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_TEXTURE_LIST: AppendNewNode(aGfxData, aGfxData->mTextureLists, _Buffer, pDataName, pDataTokens); break;
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;
case DATA_TYPE_COLLISION: AppendNewNode(aGfxData, aGfxData->mCollisions, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_LEVEL_SCRIPT: AppendNewNode(aGfxData, aGfxData->mLevelScripts, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_MACRO_OBJECT: AppendNewNode(aGfxData, aGfxData->mMacroObjects, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_TRAJECTORY: AppendNewNode(aGfxData, aGfxData->mTrajectories, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_MOVTEX: AppendNewNode(aGfxData, aGfxData->mMovtexs, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_MOVTEXQC: AppendNewNode(aGfxData, aGfxData->mMovtexQCs, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_ROOMS: AppendNewNode(aGfxData, aGfxData->mRooms, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_UNUSED: pDataTokens = (Array<String> *) 1; break;
case DATA_TYPE_LIGHT: AppendNewNode(aGfxData, aGfxData->mLights, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_LIGHT_T: AppendNewNode(aGfxData, aGfxData->mLightTs, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_AMBIENT_T: AppendNewNode(aGfxData, aGfxData->mAmbientTs, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_TEXTURE: AppendNewNode(aGfxData, aGfxData->mTextures, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_TEXTURE_LIST: AppendNewNode(aGfxData, aGfxData->mTextureLists, _Buffer, pDataName, pDataTokens); break;
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;
case DATA_TYPE_COLLISION: AppendNewNode(aGfxData, aGfxData->mCollisions, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_LEVEL_SCRIPT: AppendNewNode(aGfxData, aGfxData->mLevelScripts, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_MACRO_OBJECT: AppendNewNode(aGfxData, aGfxData->mMacroObjects, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_TRAJECTORY: AppendNewNode(aGfxData, aGfxData->mTrajectories, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_MOVTEX: AppendNewNode(aGfxData, aGfxData->mMovtexs, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_MOVTEXQC: AppendNewNode(aGfxData, aGfxData->mMovtexQCs, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_ROOMS: AppendNewNode(aGfxData, aGfxData->mRooms, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_BEHAVIOR_SCRIPT: AppendNewNode(aGfxData, aGfxData->mBehaviorScripts, _Buffer, pDataName, pDataTokens); break;
case DATA_TYPE_UNUSED: pDataTokens = (Array<String> *) 1; break;
}
_Buffer.Clear();
}

View file

@ -89,6 +89,10 @@ void DynOS_Gfx_Free(GfxData* aGfxData) {
Delete(_Node->mData);
Delete(_Node);
}
for (auto& _Node : aGfxData->mBehaviorScripts) {
Delete(_Node->mData);
Delete(_Node);
}
for (auto& _Node : aGfxData->mLevelScripts) {
Delete(_Node->mData);
Delete(_Node);

View file

@ -160,6 +160,24 @@ void dynos_level_load_background(void *ptr) {
DynOS_Lvl_LoadBackground(ptr);
}
// -- Behaviors -- //
void dynos_add_behavior(s32 modIndex, const char *filePath, const char *behaviorName) {
DynOS_Bhv_Activate(modIndex, filePath, behaviorName);
}
s32 dynos_behavior_get_active_mod_index(BehaviorScript *bhvScript) {
return DynOS_Bhv_GetActiveModIndex(bhvScript);
}
const char *dynos_behavior_get_token(BehaviorScript *bhvScript, u32 index) {
return DynOS_Bhv_GetToken(bhvScript, index);
}
void dynos_behavior_hook_all_custom_behaviors(void) {
DynOS_Bhv_HookAllCustomBehaviors();
}
// -- other -- //
void dynos_mod_shutdown(void) {
DynOS_Mod_Shutdown();

10
data/dynos_file.cpp Normal file
View file

@ -0,0 +1,10 @@
#include "dynos.cpp.h"
void SkipBytes(FILE *aFile, size_t amount) {
// If we're at end of file. There is no more to skip.
if (feof(aFile)) { return; }
int failure = fseek(aFile, amount, SEEK_CUR);
// If we failed to skip bytes. Print the error.
if (failure) { perror("The following error occured when skipping bytes"); }
}

View file

@ -19,6 +19,12 @@ void DynOS_Gfx_GeneratePacks(const char* directory) {
if (fs_sys_dir_exists(_ActorPackFolder.c_str())) {
DynOS_Actor_GeneratePack(_ActorPackFolder);
}
SysPath _BehaviorPackFolder = fstring("%s/%s/data", directory, dir->d_name);
if (fs_sys_dir_exists(_BehaviorPackFolder.c_str())) {
DynOS_Bhv_GeneratePack(_BehaviorPackFolder);
}
SysPath _TexturePackFolder = fstring("%s/%s", directory, dir->d_name);
SysPath _TexturePackOutputFolder = fstring("%s/%s/textures", directory, dir->d_name);
if (fs_sys_dir_exists(_TexturePackFolder.c_str())) {

View file

@ -78,6 +78,7 @@ void DynOS_Mod_Update() {
DynOS_Actor_ModShutdown();
DynOS_Col_ModShutdown();
DynOS_Lvl_ModShutdown();
DynOS_Bhv_ModShutdown();
DynOS_MovtexQC_ModShutdown();
DynOS_Tex_ModShutdown();
}

105
data/dynos_mgr_bhv.cpp Normal file
View file

@ -0,0 +1,105 @@
#include "dynos.cpp.h"
extern "C" {
#include "engine/behavior_script.h"
#include "src/pc/lua/smlua_hooks.h"
}
Array<Pair<const char *, GfxData *>> &DynOS_Bhv_GetArray() {
static Array<Pair<const char *, GfxData *>> sDynosCustomBehaviorScripts;
return sDynosCustomBehaviorScripts;
}
void DynOS_Bhv_Activate(s32 modIndex, const SysPath &aFilename, const char *aBehaviorName) {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
// check for duplicates
for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) {
if (!strcmp(_CustomBehaviorScripts[i].first, aBehaviorName)) {
return;
}
}
u16 behaviorLen = strlen(aBehaviorName);
char *behaviorName = (char *)calloc(1, sizeof(char) * (behaviorLen + 1));
strcpy(behaviorName, aBehaviorName);
GfxData *_Node = DynOS_Bhv_LoadFromBinary(aFilename, behaviorName);
if (!_Node) {
free(behaviorName);
return;
}
// Remember index
_Node->mModIndex = modIndex;
// Add to behaviors
_CustomBehaviorScripts.Add({ behaviorName, _Node });
}
void DynOS_Bhv_ModShutdown() {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
while (_CustomBehaviorScripts.Count() > 0) {
auto &pair = _CustomBehaviorScripts[0];
Delete(pair.second);
free((void *)pair.first);
_CustomBehaviorScripts.Remove(0);
}
}
GfxData *DynOS_Bhv_GetActiveGfx(BehaviorScript *bhvScript) {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) {
auto &gfxData = _CustomBehaviorScripts[i].second;
auto &scripts = gfxData->mBehaviorScripts;
if (bhvScript == scripts[scripts.Count() - 1]->mData) {
return gfxData;
}
}
return NULL;
}
s32 DynOS_Bhv_GetActiveModIndex(BehaviorScript *bhvScript) {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) {
auto &gfxData = _CustomBehaviorScripts[i].second;
auto &scripts = gfxData->mBehaviorScripts;
if (bhvScript == scripts[scripts.Count() - 1]->mData) {
return gfxData->mModIndex;
}
}
return -1;
}
const char *DynOS_Bhv_GetToken(BehaviorScript *bhvScript, u32 index) {
GfxData *gfxData = DynOS_Bhv_GetActiveGfx(bhvScript);
if (gfxData == NULL) {
return NULL;
}
// have to 1-index due to to pointer read code
index = index - 1;
if (index >= gfxData->mLuaTokenList.Count()) {
return NULL;
}
return gfxData->mLuaTokenList[index].begin();
}
void DynOS_Bhv_HookAllCustomBehaviors() {
auto &_CustomBehaviorScripts = DynOS_Bhv_GetArray();
for (s32 i = 0; i < _CustomBehaviorScripts.Count(); ++i) {
auto &scriptName = _CustomBehaviorScripts[i].first;
auto &aGfxData = _CustomBehaviorScripts[i].second;
auto &script = aGfxData->mBehaviorScripts[aGfxData->mBehaviorScripts.Count() - 1]->mData;
// Theres currently no better place but to do this here.
if (hook_behavior(script, scriptName) == 0) {
PrintError(" ERROR: Failed to add custom behavior '%s'!", scriptName);
}
}
}

View file

@ -4,6 +4,7 @@ extern "C" {
#include "levels/scripts.h"
#include "object_fields.h"
#include "engine/level_script.h"
#include "engine/surface_load.h"
#include "game/object_helpers.h"
#include "game/segment2.h"
#include "game/level_geo.h"
@ -13,6 +14,8 @@ extern "C" {
#include "game/geo_misc.h"
#include "game/mario_misc.h"
#include "game/mario_actions_cutscene.h"
#include "game/obj_behaviors.h"
#include "game/obj_behaviors_2.h"
#include "game/screen_transition.h"
#include "game/object_list_processor.h"
#include "game/behavior_actions.h"
@ -81,6 +84,8 @@ extern "C" {
#define define_builtin(_ptr) (const void*)#_ptr, (const void*)_ptr
#define define_animation_builtin(_ptr) (const void*)#_ptr, (const void*)_ptr
#define MGR_FIND_DATA(_DataTable, _Cast) \
size_t _count = sizeof(_DataTable) / (2 * sizeof(_DataTable[0])); \
for (u32 _i = 0; _i < _count; _i++) { \
@ -89,6 +94,21 @@ extern "C" {
} \
} \
return NULL;
#define MGR_FIND_DATA_FROM_TABLES(_DataTable, _DataTable2, _Cast) \
size_t _count = sizeof(_DataTable) / (2 * sizeof(_DataTable[0])); \
for (u32 _i = 0; _i < _count; _i++) { \
if (!strcmp((const char*)_DataTable[_i * 2 + 0], aDataName)) { \
return _Cast _DataTable[_i * 2 + 1]; \
} \
} \
_count = sizeof(_DataTable2) / (2 * sizeof(_DataTable2[0])); \
for (u32 _i = 0; _i < _count; _i++) { \
if (!strcmp((const char*)_DataTable2[_i * 2 + 0], aDataName)) { \
return _Cast _DataTable2[_i * 2 + 1]; \
} \
} \
return NULL;
#define MGR_FIND_NAME(_DataTable) \
size_t _count = sizeof(_DataTable) / (2 * sizeof(_DataTable[0])); \
@ -854,10 +874,11 @@ const char* DynOS_Builtin_LvlGeo_GetFromData(const GeoLayout* aData) {
}
////////////////
// Level Cols //
// Collisions //
////////////////
static const void* sDynosBuiltinLvlCols[] = {
static const void* sDynosBuiltinCols[] = {
// Level Collisions
define_builtin(bbh_seg7_collision_07026B1C),
define_builtin(bbh_seg7_collision_coffin),
define_builtin(bbh_seg7_collision_haunted_bookshelf),
@ -1060,14 +1081,187 @@ static const void* sDynosBuiltinLvlCols[] = {
define_builtin(wf_seg7_collision_trapezoid),
define_builtin(wf_seg7_collision_tumbling_bridge),
define_builtin(wmotr_seg7_collision),
// Actor Collisions
define_builtin(bbh_seg7_collision_coffin),
define_builtin(bbh_seg7_collision_haunted_bookshelf),
define_builtin(bbh_seg7_collision_merry_go_round),
define_builtin(bbh_seg7_collision_mesh_elevator),
define_builtin(bbh_seg7_collision_staircase_step),
define_builtin(bbh_seg7_collision_tilt_floor_platform),
define_builtin(bitdw_seg7_collision_moving_pyramid),
define_builtin(bitfs_seg7_collision_inverted_pyramid),
define_builtin(bitfs_seg7_collision_sinking_cage_platform),
define_builtin(bitfs_seg7_collision_sinking_platform),
define_builtin(bitfs_seg7_collision_squishable_platform),
define_builtin(blue_coin_switch_seg8_collision_08000E98),
define_builtin(bob_seg7_collision_chain_chomp_gate),
define_builtin(bowser_2_seg7_collision_tilting_platform),
define_builtin(breakable_box_seg8_collision_08012D70),
define_builtin(cannon_lid_seg8_collision_08004950),
define_builtin(capswitch_collision_050033D0),
define_builtin(capswitch_collision_05003448),
define_builtin(castle_grounds_seg7_collision_cannon_grill),
define_builtin(castle_grounds_seg7_collision_moat_grills),
define_builtin(checkerboard_platform_seg8_collision_0800D710),
define_builtin(ddd_seg7_collision_bowser_sub_door),
define_builtin(ddd_seg7_collision_submarine),
define_builtin(door_seg3_collision_0301CE78),
define_builtin(dorrie_seg6_collision_0600F644),
define_builtin(dorrie_seg6_collision_0600FBB8),
define_builtin(exclamation_box_outline_seg8_collision_08025F78),
define_builtin(hmc_seg7_collision_controllable_platform),
define_builtin(hmc_seg7_collision_controllable_platform_sub),
define_builtin(hmc_seg7_collision_elevator),
define_builtin(inside_castle_seg7_collision_floor_trap),
define_builtin(inside_castle_seg7_collision_star_door),
define_builtin(inside_castle_seg7_collision_water_level_pillar),
define_builtin(jrb_seg7_collision_floating_box),
define_builtin(jrb_seg7_collision_floating_platform),
define_builtin(jrb_seg7_collision_in_sunken_ship),
define_builtin(jrb_seg7_collision_in_sunken_ship_2),
define_builtin(jrb_seg7_collision_in_sunken_ship_3),
define_builtin(jrb_seg7_collision_pillar_base),
define_builtin(jrb_seg7_collision_rock_solid),
define_builtin(lll_hexagonal_mesh_seg3_collision_0301CECC),
define_builtin(lll_seg7_collision_drawbridge),
define_builtin(lll_seg7_collision_falling_wall),
define_builtin(lll_seg7_collision_floating_block),
define_builtin(lll_seg7_collision_hexagonal_platform),
define_builtin(lll_seg7_collision_inverted_pyramid),
define_builtin(lll_seg7_collision_octagonal_moving_platform),
define_builtin(lll_seg7_collision_pitoune),
define_builtin(lll_seg7_collision_puzzle_piece),
define_builtin(lll_seg7_collision_rotating_fire_bars),
define_builtin(lll_seg7_collision_rotating_platform),
define_builtin(lll_seg7_collision_sinking_pyramids),
define_builtin(lll_seg7_collision_slow_tilting_platform),
define_builtin(lll_seg7_collision_wood_piece),
define_builtin(metal_box_seg8_collision_08024C28),
define_builtin(penguin_seg5_collision_05008B88),
define_builtin(poundable_pole_collision_06002490),
define_builtin(purple_switch_seg8_collision_0800C7A8),
define_builtin(rr_seg7_collision_donut_platform),
define_builtin(rr_seg7_collision_elevator_platform),
define_builtin(rr_seg7_collision_pendulum),
define_builtin(rr_seg7_collision_rotating_platform_with_fire),
define_builtin(sl_seg7_collision_pound_explodes),
define_builtin(sl_seg7_collision_sliding_snow_mound),
define_builtin(springboard_collision_05001A28),
define_builtin(ssl_seg7_collision_0702808C),
define_builtin(ssl_seg7_collision_grindel),
define_builtin(ssl_seg7_collision_pyramid_elevator),
define_builtin(ssl_seg7_collision_pyramid_top),
define_builtin(ssl_seg7_collision_spindel),
define_builtin(ssl_seg7_collision_tox_box),
define_builtin(thi_seg7_collision_top_trap),
define_builtin(thwomp_seg5_collision_0500B7D0),
define_builtin(thwomp_seg5_collision_0500B92C),
define_builtin(ttc_seg7_collision_clock_main_rotation),
define_builtin(ttc_seg7_collision_clock_pendulum),
define_builtin(ttc_seg7_collision_clock_platform),
define_builtin(ttc_seg7_collision_rotating_clock_platform2),
define_builtin(ttc_seg7_collision_sliding_surface),
define_builtin(ttm_seg7_collision_pitoune_2),
define_builtin(ttm_seg7_collision_podium_warp),
define_builtin(ttm_seg7_collision_ukiki_cage),
define_builtin(unknown_seg8_collision_080262F8),
define_builtin(warp_pipe_seg3_collision_03009AC8),
define_builtin(wdw_seg7_collision_arrow_lift),
define_builtin(wdw_seg7_collision_express_elevator_platform),
define_builtin(wdw_seg7_collision_rect_floating_platform),
define_builtin(wdw_seg7_collision_square_floating_platform),
define_builtin(wf_seg7_collision_breakable_wall),
define_builtin(wf_seg7_collision_breakable_wall_2),
define_builtin(wf_seg7_collision_bullet_bill_cannon),
define_builtin(wf_seg7_collision_clocklike_rotation),
define_builtin(wf_seg7_collision_kickable_board),
define_builtin(wf_seg7_collision_large_bomp),
define_builtin(wf_seg7_collision_platform),
define_builtin(wf_seg7_collision_sliding_brick_platform),
define_builtin(wf_seg7_collision_small_bomp),
define_builtin(wf_seg7_collision_tower),
define_builtin(wf_seg7_collision_tower_door),
define_builtin(whomp_seg6_collision_06020A0C),
define_builtin(wooden_signpost_seg3_collision_0302DD80),
};
const Collision* DynOS_Builtin_LvlCol_GetFromName(const char* aDataName) {
MGR_FIND_DATA(sDynosBuiltinLvlCols, (const Collision*));
const Collision* DynOS_Builtin_Col_GetFromName(const char* aDataName) {
MGR_FIND_DATA(sDynosBuiltinCols, (const Collision*));
}
const char* DynOS_Builtin_LvlCol_GetFromData(const Collision* aData) {
MGR_FIND_NAME(sDynosBuiltinLvlCols);
const char* DynOS_Builtin_Col_GetFromData(const Collision* aData) {
MGR_FIND_NAME(sDynosBuiltinCols);
}
////////////////
// Animations //
////////////////
static const void* sDynosBuiltinAnims[] = {
define_builtin(amp_seg8_anims_08004034),
define_builtin(bobomb_seg8_anims_0802396C),
define_builtin(chuckya_seg8_anims_0800C070),
define_builtin(flyguy_seg8_anims_08011A64),
define_builtin(goomba_seg8_anims_0801DA4C),
define_builtin(blue_fish_seg3_anims_0301C2B0),
define_builtin(bowser_key_seg3_anims_list),
define_builtin(butterfly_seg3_anims_030056B0),
define_builtin(door_seg3_anims_030156C0),
define_builtin(heave_ho_seg5_anims_0501534C),
define_builtin(hoot_seg5_anims_05005768),
define_builtin(blargg_seg5_anims_0500616C),
define_builtin(bully_seg5_anims_0500470C),
define_builtin(king_bobomb_seg5_anims_0500FE30),
define_builtin(clam_shell_seg5_anims_05001744),
define_builtin(manta_seg5_anims_05008EB4),
define_builtin(sushi_seg5_anims_0500AE54),
define_builtin(unagi_seg5_anims_05012824),
define_builtin(eyerok_seg5_anims_050116E4),
define_builtin(klepto_seg5_anims_05008CFC),
define_builtin(monty_mole_seg5_anims_05007248),
define_builtin(ukiki_seg5_anims_05015784),
define_builtin(penguin_seg5_anims_05008B74),
define_builtin(snowman_seg5_anims_0500D118),
define_builtin(spindrift_seg5_anims_05002D68),
define_builtin(bookend_seg5_anims_05002540),
define_builtin(chair_seg5_anims_05005784),
define_builtin(mad_piano_seg5_anims_05009B14),
define_builtin(birds_seg5_anims_050009E8),
define_builtin(peach_seg5_anims_0501C41C),
define_builtin(yoshi_seg5_anims_05024100),
define_builtin(lakitu_enemy_seg5_anims_050144D4),
define_builtin(spiny_seg5_anims_05016EAC),
define_builtin(spiny_egg_seg5_anims_050157E4),
define_builtin(wiggler_seg5_anims_0500C874),
define_builtin(wiggler_seg5_anims_0500EC8C),
define_builtin(bowser_seg6_anims_06057690),
define_builtin(bub_seg6_anims_06012354),
define_builtin(cyan_fish_seg6_anims_0600E264),
define_builtin(seaweed_seg6_anims_0600A4D4),
define_builtin(skeeter_seg6_anims_06007DE0),
define_builtin(water_ring_seg6_anims_06013F7C),
define_builtin(chain_chomp_seg6_anims_06025178),
define_builtin(koopa_seg6_anims_06011364),
define_builtin(koopa_flag_seg6_anims_06001028),
define_builtin(piranha_plant_seg6_anims_0601C31C),
define_builtin(whomp_seg6_anims_06020A04),
define_builtin(lakitu_seg6_anims_060058F8),
define_builtin(mips_seg6_anims_06015634),
define_builtin(toad_seg6_anims_0600FB58),
define_builtin(chilly_chief_seg6_anims_06003994),
define_builtin(moneybag_seg6_anims_06005E5C),
define_builtin(dorrie_seg6_anims_0600F638),
define_builtin(scuttlebug_seg6_anims_06015064),
define_builtin(swoop_seg6_anims_060070D0),
};
const Animation *DynOS_Builtin_Anim_GetFromName(const char *aDataName) {
MGR_FIND_DATA(sDynosBuiltinAnims, (const Animation *));
}
const char *DynOS_Builtin_Anim_GetFromData(const Animation *aData) {
MGR_FIND_NAME(sDynosBuiltinAnims);
}
////////////////////
@ -1140,11 +1334,570 @@ static const void* sDynosBuiltinFuncs[] = {
(const void *) "geo_rotate_coin", (const void *) geo_rotate_3d_coin,
define_builtin(geo_offset_klepto_held_object),
define_builtin(geo_switch_peach_eyes),
// coop-specific
// Co-op specific
define_builtin(geo_mario_set_player_colors),
define_builtin(geo_movtex_draw_water_regions_ext),
define_builtin(lvl_init_or_update),
define_builtin(geo_choose_area_ext),
// Behaviors
define_builtin(bhv_cap_switch_loop),
define_builtin(bhv_tiny_star_particles_init),
define_builtin(bhv_grindel_thwomp_loop),
define_builtin(bhv_koopa_shell_underwater_loop),
define_builtin(bhv_door_init),
define_builtin(bhv_door_loop),
define_builtin(bhv_star_door_loop),
define_builtin(bhv_star_door_loop_2),
define_builtin(bhv_mr_i_loop),
define_builtin(bhv_mr_i_body_loop),
define_builtin(bhv_mr_i_particle_loop),
define_builtin(bhv_piranha_particle_loop),
define_builtin(bhv_giant_pole_loop),
define_builtin(bhv_pole_init),
define_builtin(bhv_pole_base_loop),
define_builtin(bhv_thi_huge_island_top_loop),
define_builtin(bhv_thi_tiny_island_top_loop),
define_builtin(bhv_king_bobomb_loop),
define_builtin(bhv_bobomb_anchor_mario_loop),
define_builtin(bhv_beta_chest_bottom_init),
define_builtin(bhv_beta_chest_bottom_loop),
define_builtin(bhv_beta_chest_lid_loop),
define_builtin(bhv_bubble_wave_init),
define_builtin(bhv_bubble_maybe_loop),
define_builtin(bhv_bubble_player_loop),
define_builtin(bhv_water_air_bubble_init),
define_builtin(bhv_water_air_bubble_loop),
define_builtin(bhv_particle_init),
define_builtin(bhv_particle_loop),
define_builtin(bhv_water_waves_init),
define_builtin(bhv_small_bubbles_loop),
define_builtin(bhv_fish_group_loop),
define_builtin(bhv_cannon_base_loop),
define_builtin(bhv_cannon_barrel_loop),
define_builtin(bhv_cannon_base_unused_loop),
define_builtin(bhv_chuckya_loop),
define_builtin(bhv_chuckya_anchor_mario_loop),
define_builtin(bhv_rotating_platform_loop),
define_builtin(bhv_wf_breakable_wall_loop),
define_builtin(bhv_kickable_board_loop),
define_builtin(bhv_tower_door_loop),
define_builtin(bhv_wf_rotating_wooden_platform_init),
define_builtin(bhv_wf_rotating_wooden_platform_loop),
define_builtin(bhv_fading_warp_loop),
define_builtin(bhv_warp_loop),
define_builtin(bhv_white_puff_exploding_loop),
define_builtin(bhv_spawned_star_init),
define_builtin(bhv_spawned_star_loop),
define_builtin(bhv_coin_init),
define_builtin(bhv_coin_loop),
define_builtin(bhv_coin_inside_boo_loop),
define_builtin(bhv_coin_formation_init),
define_builtin(bhv_coin_formation_spawn_loop),
define_builtin(bhv_coin_formation_loop),
define_builtin(bhv_temp_coin_loop),
define_builtin(bhv_coin_sparkles_loop),
define_builtin(bhv_golden_coin_sparkles_loop),
define_builtin(bhv_wall_tiny_star_particle_loop),
define_builtin(bhv_pound_tiny_star_particle_loop),
define_builtin(bhv_pound_tiny_star_particle_init),
define_builtin(bhv_punch_tiny_triangle_loop),
define_builtin(bhv_punch_tiny_triangle_init),
define_builtin(bhv_tumbling_bridge_platform_loop),
define_builtin(bhv_tumbling_bridge_loop),
define_builtin(bhv_elevator_init),
define_builtin(bhv_elevator_loop),
define_builtin(bhv_water_mist_loop),
define_builtin(bhv_water_mist_spawn_loop),
define_builtin(bhv_water_mist_2_loop),
define_builtin(bhv_pound_white_puffs_init),
define_builtin(bhv_ground_sand_init),
define_builtin(bhv_ground_snow_init),
define_builtin(bhv_wind_loop),
define_builtin(bhv_unused_particle_spawn_loop),
define_builtin(bhv_ukiki_cage_star_loop),
define_builtin(bhv_ukiki_cage_loop),
define_builtin(bhv_bitfs_sinking_platform_loop),
define_builtin(bhv_bitfs_sinking_cage_platform_loop),
define_builtin(bhv_ddd_moving_pole_loop),
define_builtin(bhv_platform_normals_init),
define_builtin(bhv_tilting_inverted_pyramid_loop),
define_builtin(bhv_squishable_platform_loop),
define_builtin(bhv_beta_moving_flames_spawn_loop),
define_builtin(bhv_beta_moving_flames_loop),
define_builtin(bhv_rr_rotating_bridge_platform_loop),
define_builtin(bhv_flamethrower_loop),
define_builtin(bhv_flamethrower_flame_loop),
define_builtin(bhv_bouncing_fireball_loop),
define_builtin(bhv_bouncing_fireball_flame_loop),
define_builtin(bhv_bowser_shock_wave_loop),
define_builtin(bhv_flame_mario_loop),
define_builtin(bhv_black_smoke_mario_loop),
define_builtin(bhv_black_smoke_bowser_loop),
define_builtin(bhv_black_smoke_upward_loop),
define_builtin(bhv_beta_fish_splash_spawner_loop),
define_builtin(bhv_spindrift_loop),
define_builtin(bhv_tower_platform_group_init),
define_builtin(bhv_tower_platform_group_loop),
define_builtin(bhv_wf_sliding_tower_platform_loop),
define_builtin(bhv_wf_elevator_tower_platform_loop),
define_builtin(bhv_wf_solid_tower_platform_loop),
define_builtin(bhv_snow_leaf_particle_spawn_init),
define_builtin(bhv_tree_snow_or_leaf_loop),
define_builtin(bhv_piranha_plant_bubble_loop),
define_builtin(bhv_piranha_plant_waking_bubbles_loop),
define_builtin(bhv_purple_switch_loop),
define_builtin(bhv_hidden_object_loop),
define_builtin(bhv_breakable_box_loop),
define_builtin(bhv_pushable_loop),
define_builtin(bhv_init_room),
define_builtin(bhv_small_water_wave_loop),
define_builtin(bhv_yellow_coin_init),
define_builtin(bhv_yellow_coin_loop),
define_builtin(bhv_squarish_path_moving_loop),
define_builtin(bhv_squarish_path_parent_init),
define_builtin(bhv_squarish_path_parent_loop),
define_builtin(bhv_heave_ho_loop),
define_builtin(bhv_heave_ho_throw_mario_loop),
define_builtin(bhv_ccm_touched_star_spawn_loop),
define_builtin(bhv_unused_poundable_platform),
define_builtin(bhv_beta_trampoline_top_loop),
define_builtin(bhv_beta_trampoline_spring_loop),
define_builtin(bhv_jumping_box_loop),
define_builtin(bhv_boo_cage_init),
define_builtin(bhv_boo_cage_loop),
define_builtin(bhv_bowser_key_init),
define_builtin(bhv_bowser_key_loop),
define_builtin(bhv_grand_star_init),
define_builtin(bhv_grand_star_loop),
define_builtin(bhv_beta_boo_key_loop),
define_builtin(bhv_alpha_boo_key_loop),
define_builtin(bhv_bullet_bill_init),
define_builtin(bhv_bullet_bill_loop),
define_builtin(bhv_white_puff_smoke_init),
define_builtin(bhv_bowser_tail_anchor_init),
define_builtin(bhv_bowser_tail_anchor_loop),
define_builtin(bhv_bowser_init),
define_builtin(bhv_bowser_loop),
define_builtin(bhv_bowser_body_anchor_init),
define_builtin(bhv_bowser_body_anchor_loop),
define_builtin(bhv_bowser_flame_spawn_loop),
define_builtin(bhv_tilting_bowser_lava_platform_init),
define_builtin(bhv_falling_bowser_platform_loop),
define_builtin(bhv_blue_bowser_flame_init),
define_builtin(bhv_blue_bowser_flame_loop),
define_builtin(bhv_flame_floating_landing_init),
define_builtin(bhv_flame_floating_landing_loop),
define_builtin(bhv_blue_flames_group_loop),
define_builtin(bhv_flame_bouncing_init),
define_builtin(bhv_flame_bouncing_loop),
define_builtin(bhv_flame_moving_forward_growing_init),
define_builtin(bhv_flame_moving_forward_growing_loop),
define_builtin(bhv_flame_bowser_init),
define_builtin(bhv_flame_bowser_loop),
define_builtin(bhv_flame_large_burning_out_init),
define_builtin(bhv_blue_fish_movement_loop),
define_builtin(bhv_tank_fish_group_loop),
define_builtin(bhv_checkerboard_elevator_group_init),
define_builtin(bhv_checkerboard_elevator_group_loop),
define_builtin(bhv_checkerboard_platform_init),
define_builtin(bhv_checkerboard_platform_loop),
define_builtin(bhv_bowser_key_unlock_door_loop),
define_builtin(bhv_bowser_key_course_exit_loop),
define_builtin(bhv_invisible_objects_under_bridge_init),
define_builtin(bhv_invisible_objects_under_bridge_loop),
define_builtin(bhv_water_level_pillar_init),
define_builtin(bhv_water_level_pillar_loop),
define_builtin(bhv_ddd_warp_loop),
define_builtin(bhv_moat_grills_loop),
define_builtin(bhv_rotating_clock_arm_loop),
define_builtin(bhv_ukiki_init),
define_builtin(bhv_ukiki_loop),
define_builtin(bhv_lll_sinking_rock_block_loop),
define_builtin(bhv_lll_moving_octagonal_mesh_platform_loop),
define_builtin(bhv_lll_rotating_block_fire_bars_loop),
define_builtin(bhv_lll_rotating_hex_flame_loop),
define_builtin(bhv_lll_wood_piece_loop),
define_builtin(bhv_lll_floating_wood_bridge_loop),
define_builtin(bhv_volcano_flames_loop),
define_builtin(bhv_lll_rotating_hexagonal_ring_loop),
define_builtin(bhv_lll_sinking_rectangular_platform_loop),
define_builtin(bhv_lll_sinking_square_platforms_loop),
define_builtin(bhv_koopa_shell_loop),
define_builtin(bhv_koopa_shell_flame_loop),
define_builtin(bhv_tox_box_loop),
define_builtin(bhv_piranha_plant_loop),
define_builtin(bhv_lll_bowser_puzzle_piece_loop),
define_builtin(bhv_lll_bowser_puzzle_loop),
define_builtin(bhv_tuxies_mother_loop),
define_builtin(bhv_small_penguin_loop),
define_builtin(bhv_fish_spawner_loop),
define_builtin(bhv_fish_loop),
define_builtin(bhv_wdw_express_elevator_loop),
define_builtin(bhv_bub_spawner_loop),
define_builtin(bhv_bub_loop),
define_builtin(bhv_exclamation_box_init),
define_builtin(bhv_exclamation_box_loop),
define_builtin(bhv_rotating_exclamation_box_loop),
define_builtin(bhv_sound_spawner_init),
define_builtin(bhv_bowsers_sub_loop),
define_builtin(bhv_sushi_shark_loop),
define_builtin(bhv_sushi_shark_collision_loop),
define_builtin(bhv_jrb_sliding_box_loop),
define_builtin(bhv_ship_part_3_loop),
define_builtin(bhv_sunken_ship_part_loop),
define_builtin(bhv_white_puff_1_loop),
define_builtin(bhv_white_puff_2_loop),
define_builtin(bhv_blue_coin_switch_loop),
define_builtin(bhv_hidden_blue_coin_loop),
define_builtin(bhv_openable_cage_door_loop),
define_builtin(bhv_openable_grill_loop),
define_builtin(bhv_water_level_diamond_loop),
define_builtin(bhv_init_changing_water_level_loop),
define_builtin(bhv_tweester_sand_particle_loop),
define_builtin(bhv_tweester_loop),
define_builtin(bhv_merry_go_round_boo_manager_loop),
define_builtin(bhv_animated_texture_loop),
define_builtin(bhv_boo_in_castle_loop),
define_builtin(bhv_boo_with_cage_init),
define_builtin(bhv_boo_with_cage_loop),
define_builtin(bhv_boo_init),
define_builtin(bhv_big_boo_loop),
define_builtin(bhv_courtyard_boo_triplet_init),
define_builtin(bhv_boo_loop),
define_builtin(bhv_boo_boss_spawned_bridge_loop),
define_builtin(bhv_bbh_tilting_trap_platform_loop),
define_builtin(bhv_haunted_bookshelf_loop),
define_builtin(bhv_merry_go_round_loop),
define_builtin(bhv_play_music_track_when_touched_loop),
define_builtin(bhv_beta_bowser_anchor_loop),
define_builtin(bhv_static_checkered_platform_loop),
define_builtin(bhv_castle_floor_trap_init),
define_builtin(bhv_castle_floor_trap_loop),
define_builtin(bhv_floor_trap_in_castle_loop),
define_builtin(bhv_sparkle_spawn_loop),
define_builtin(bhv_scuttlebug_loop),
define_builtin(bhv_scuttlebug_spawn_loop),
define_builtin(bhv_whomp_loop),
define_builtin(bhv_water_splash_spawn_droplets),
define_builtin(bhv_water_droplet_loop),
define_builtin(bhv_water_droplet_splash_init),
define_builtin(bhv_bubble_splash_init),
define_builtin(bhv_idle_water_wave_loop),
define_builtin(bhv_shallow_water_splash_init),
define_builtin(bhv_wave_trail_shrink),
define_builtin(bhv_strong_wind_particle_loop),
define_builtin(bhv_sl_snowman_wind_loop),
define_builtin(bhv_sl_walking_penguin_loop),
define_builtin(bhv_menu_button_init),
define_builtin(bhv_menu_button_loop),
define_builtin(bhv_menu_button_manager_init),
define_builtin(bhv_menu_button_manager_loop),
define_builtin(bhv_act_selector_star_type_loop),
define_builtin(bhv_act_selector_init),
define_builtin(bhv_act_selector_loop),
define_builtin(bhv_moving_yellow_coin_init),
define_builtin(bhv_moving_yellow_coin_loop),
define_builtin(bhv_moving_blue_coin_init),
define_builtin(bhv_moving_blue_coin_loop),
define_builtin(bhv_blue_coin_sliding_jumping_init),
define_builtin(bhv_blue_coin_sliding_loop),
define_builtin(bhv_blue_coin_jumping_loop),
define_builtin(bhv_seaweed_init),
define_builtin(bhv_seaweed_bundle_init),
define_builtin(bhv_bobomb_init),
define_builtin(bhv_bobomb_loop),
define_builtin(bhv_bobomb_fuse_smoke_init),
define_builtin(bhv_bobomb_buddy_init),
define_builtin(bhv_bobomb_buddy_loop),
define_builtin(bhv_cannon_closed_init),
define_builtin(bhv_cannon_closed_loop),
define_builtin(bhv_whirlpool_init),
define_builtin(bhv_whirlpool_loop),
define_builtin(bhv_jet_stream_loop),
define_builtin(bhv_homing_amp_init),
define_builtin(bhv_homing_amp_loop),
define_builtin(bhv_circling_amp_init),
define_builtin(bhv_circling_amp_loop),
define_builtin(bhv_butterfly_init),
define_builtin(bhv_butterfly_loop),
define_builtin(bhv_hoot_init),
define_builtin(bhv_hoot_loop),
define_builtin(bhv_beta_holdable_object_init),
define_builtin(bhv_beta_holdable_object_loop),
define_builtin(bhv_object_bubble_init),
define_builtin(bhv_object_bubble_loop),
define_builtin(bhv_object_water_wave_init),
define_builtin(bhv_object_water_wave_loop),
define_builtin(bhv_explosion_init),
define_builtin(bhv_explosion_loop),
define_builtin(bhv_bobomb_bully_death_smoke_init),
define_builtin(bhv_bobomb_explosion_bubble_init),
define_builtin(bhv_bobomb_explosion_bubble_loop),
define_builtin(bhv_respawner_loop),
define_builtin(bhv_small_bully_init),
define_builtin(bhv_bully_loop),
define_builtin(bhv_big_bully_init),
define_builtin(bhv_big_bully_with_minions_init),
define_builtin(bhv_big_bully_with_minions_loop),
define_builtin(bhv_jet_stream_ring_spawner_loop),
define_builtin(bhv_jet_stream_water_ring_init),
define_builtin(bhv_jet_stream_water_ring_loop),
define_builtin(bhv_manta_ray_water_ring_init),
define_builtin(bhv_manta_ray_water_ring_loop),
define_builtin(bhv_bowser_bomb_loop),
define_builtin(bhv_bowser_bomb_explosion_loop),
define_builtin(bhv_bowser_bomb_smoke_loop),
define_builtin(bhv_celebration_star_init),
define_builtin(bhv_celebration_star_loop),
define_builtin(bhv_celebration_star_sparkle_loop),
define_builtin(bhv_star_key_collection_puff_spawner_loop),
define_builtin(bhv_lll_drawbridge_spawner_init),
define_builtin(bhv_lll_drawbridge_spawner_loop),
define_builtin(bhv_lll_drawbridge_loop),
define_builtin(bhv_small_bomp_init),
define_builtin(bhv_small_bomp_loop),
define_builtin(bhv_large_bomp_init),
define_builtin(bhv_large_bomp_loop),
define_builtin(bhv_wf_sliding_platform_init),
define_builtin(bhv_wf_sliding_platform_loop),
define_builtin(bhv_moneybag_init),
define_builtin(bhv_moneybag_loop),
define_builtin(bhv_moneybag_hidden_loop),
define_builtin(bhv_bob_pit_bowling_ball_init),
define_builtin(bhv_bob_pit_bowling_ball_loop),
define_builtin(bhv_free_bowling_ball_init),
define_builtin(bhv_free_bowling_ball_loop),
define_builtin(bhv_bowling_ball_init),
define_builtin(bhv_bowling_ball_loop),
define_builtin(bhv_generic_bowling_ball_spawner_init),
define_builtin(bhv_generic_bowling_ball_spawner_loop),
define_builtin(bhv_thi_bowling_ball_spawner_loop),
define_builtin(bhv_rr_cruiser_wing_init),
define_builtin(bhv_rr_cruiser_wing_loop),
define_builtin(bhv_spindel_init),
define_builtin(bhv_spindel_loop),
define_builtin(bhv_ssl_moving_pyramid_wall_init),
define_builtin(bhv_ssl_moving_pyramid_wall_loop),
define_builtin(bhv_pyramid_elevator_init),
define_builtin(bhv_pyramid_elevator_loop),
define_builtin(bhv_pyramid_elevator_trajectory_marker_ball_loop),
define_builtin(bhv_pyramid_top_init),
define_builtin(bhv_pyramid_top_loop),
define_builtin(bhv_pyramid_top_fragment_init),
define_builtin(bhv_pyramid_top_fragment_loop),
define_builtin(bhv_pyramid_pillar_touch_detector_loop),
define_builtin(bhv_waterfall_sound_loop),
define_builtin(bhv_volcano_sound_loop),
define_builtin(bhv_castle_flag_init),
define_builtin(bhv_birds_sound_loop),
define_builtin(bhv_ambient_sounds_init),
define_builtin(bhv_sand_sound_loop),
define_builtin(bhv_castle_cannon_grate_init),
define_builtin(bhv_snowmans_bottom_init),
define_builtin(bhv_snowmans_bottom_loop),
define_builtin(bhv_snowmans_head_init),
define_builtin(bhv_snowmans_head_loop),
define_builtin(bhv_snowmans_body_checkpoint_loop),
define_builtin(bhv_big_boulder_init),
define_builtin(bhv_big_boulder_loop),
define_builtin(bhv_big_boulder_generator_loop),
define_builtin(bhv_wing_cap_init),
define_builtin(bhv_wing_vanish_cap_loop),
define_builtin(bhv_metal_cap_init),
define_builtin(bhv_metal_cap_loop),
define_builtin(bhv_normal_cap_init),
define_builtin(bhv_normal_cap_loop),
define_builtin(bhv_vanish_cap_init),
define_builtin(bhv_collect_star_init),
define_builtin(bhv_collect_star_loop),
define_builtin(bhv_star_spawn_init),
define_builtin(bhv_star_spawn_loop),
define_builtin(bhv_hidden_red_coin_star_init),
define_builtin(bhv_hidden_red_coin_star_loop),
define_builtin(bhv_red_coin_init),
define_builtin(bhv_red_coin_loop),
define_builtin(bhv_bowser_course_red_coin_star_loop),
define_builtin(bhv_hidden_star_init),
define_builtin(bhv_hidden_star_loop),
define_builtin(bhv_hidden_star_trigger_loop),
define_builtin(bhv_ttm_rolling_log_init),
define_builtin(bhv_rolling_log_loop),
define_builtin(bhv_lll_rolling_log_init),
define_builtin(bhv_1up_common_init),
define_builtin(bhv_1up_walking_loop),
define_builtin(bhv_1up_running_away_loop),
define_builtin(bhv_1up_sliding_loop),
define_builtin(bhv_1up_init),
define_builtin(bhv_1up_loop),
define_builtin(bhv_1up_jump_on_approach_loop),
define_builtin(bhv_1up_hidden_loop),
define_builtin(bhv_1up_hidden_trigger_loop),
define_builtin(bhv_1up_hidden_in_pole_loop),
define_builtin(bhv_1up_hidden_in_pole_trigger_loop),
define_builtin(bhv_1up_hidden_in_pole_spawner_loop),
define_builtin(bhv_controllable_platform_init),
define_builtin(bhv_controllable_platform_loop),
define_builtin(bhv_controllable_platform_sub_loop),
define_builtin(bhv_breakable_box_small_init),
define_builtin(bhv_breakable_box_small_loop),
define_builtin(bhv_sliding_snow_mound_loop),
define_builtin(bhv_snow_mound_spawn_loop),
define_builtin(bhv_floating_platform_loop),
define_builtin(bhv_arrow_lift_loop),
define_builtin(bhv_orange_number_init),
define_builtin(bhv_orange_number_loop),
define_builtin(bhv_manta_ray_init),
define_builtin(bhv_manta_ray_loop),
define_builtin(bhv_falling_pillar_init),
define_builtin(bhv_falling_pillar_loop),
define_builtin(bhv_falling_pillar_hitbox_loop),
define_builtin(bhv_jrb_floating_box_loop),
define_builtin(bhv_decorative_pendulum_init),
define_builtin(bhv_decorative_pendulum_loop),
define_builtin(bhv_treasure_chest_ship_init),
define_builtin(bhv_treasure_chest_ship_loop),
define_builtin(bhv_treasure_chest_jrb_init),
define_builtin(bhv_treasure_chest_jrb_loop),
define_builtin(bhv_treasure_chest_init),
define_builtin(bhv_treasure_chest_loop),
define_builtin(bhv_treasure_chest_bottom_init),
define_builtin(bhv_treasure_chest_bottom_loop),
define_builtin(bhv_treasure_chest_top_loop),
define_builtin(bhv_mips_init),
define_builtin(bhv_mips_loop),
define_builtin(bhv_yoshi_init),
define_builtin(bhv_koopa_init),
define_builtin(bhv_koopa_update),
define_builtin(bhv_koopa_race_endpoint_update),
define_builtin(bhv_pokey_update),
define_builtin(bhv_pokey_body_part_update),
define_builtin(bhv_swoop_update),
define_builtin(bhv_fly_guy_update),
define_builtin(bhv_goomba_init),
define_builtin(bhv_goomba_update),
define_builtin(bhv_goomba_triplet_spawner_update),
define_builtin(bhv_chain_chomp_update),
define_builtin(bhv_chain_chomp_chain_part_update),
define_builtin(bhv_wooden_post_update),
define_builtin(bhv_chain_chomp_gate_init),
define_builtin(bhv_chain_chomp_gate_update),
define_builtin(bhv_wiggler_update),
define_builtin(bhv_wiggler_body_part_update),
define_builtin(bhv_enemy_lakitu_update),
define_builtin(bhv_camera_lakitu_init),
define_builtin(bhv_camera_lakitu_update),
define_builtin(bhv_cloud_update),
define_builtin(bhv_cloud_part_update),
define_builtin(bhv_spiny_update),
define_builtin(bhv_monty_mole_init),
define_builtin(bhv_monty_mole_update),
define_builtin(bhv_monty_mole_hole_update),
define_builtin(bhv_monty_mole_rock_update),
define_builtin(bhv_platform_on_track_init),
define_builtin(bhv_platform_on_track_update),
define_builtin(bhv_track_ball_update),
define_builtin(bhv_seesaw_platform_init),
define_builtin(bhv_seesaw_platform_update),
define_builtin(bhv_ferris_wheel_axle_init),
define_builtin(bhv_ferris_wheel_platform_update),
define_builtin(bhv_water_bomb_spawner_update),
define_builtin(bhv_water_bomb_update),
define_builtin(bhv_water_bomb_shadow_update),
define_builtin(bhv_ttc_rotating_solid_init),
define_builtin(bhv_ttc_rotating_solid_update),
define_builtin(bhv_ttc_pendulum_init),
define_builtin(bhv_ttc_pendulum_update),
define_builtin(bhv_ttc_treadmill_init),
define_builtin(bhv_ttc_treadmill_update),
define_builtin(bhv_ttc_moving_bar_init),
define_builtin(bhv_ttc_moving_bar_update),
define_builtin(bhv_ttc_cog_init),
define_builtin(bhv_ttc_cog_update),
define_builtin(bhv_ttc_pit_block_init),
define_builtin(bhv_ttc_pit_block_update),
define_builtin(bhv_ttc_elevator_init),
define_builtin(bhv_ttc_elevator_update),
define_builtin(bhv_ttc_2d_rotator_init),
define_builtin(bhv_ttc_2d_rotator_update),
define_builtin(bhv_ttc_spinner_update),
define_builtin(bhv_mr_blizzard_init),
define_builtin(bhv_mr_blizzard_update),
define_builtin(bhv_mr_blizzard_snowball),
define_builtin(bhv_sliding_plat_2_init),
define_builtin(bhv_sliding_plat_2_loop),
define_builtin(bhv_rotating_octagonal_plat_init),
define_builtin(bhv_rotating_octagonal_plat_loop),
define_builtin(bhv_animates_on_floor_switch_press_init),
define_builtin(bhv_animates_on_floor_switch_press_loop),
define_builtin(bhv_activated_back_and_forth_platform_init),
define_builtin(bhv_activated_back_and_forth_platform_update),
define_builtin(bhv_recovery_heart_loop),
define_builtin(bhv_water_bomb_cannon_loop),
define_builtin(bhv_bubble_cannon_barrel_loop),
define_builtin(bhv_unagi_init),
define_builtin(bhv_unagi_loop),
define_builtin(bhv_unagi_subobject_loop),
define_builtin(bhv_dorrie_update),
define_builtin(bhv_haunted_chair_init),
define_builtin(bhv_haunted_chair_loop),
define_builtin(bhv_mad_piano_update),
define_builtin(bhv_flying_bookend_loop),
define_builtin(bhv_bookend_spawn_loop),
define_builtin(bhv_haunted_bookshelf_manager_loop),
define_builtin(bhv_book_switch_loop),
define_builtin(bhv_fire_piranha_plant_init),
define_builtin(bhv_fire_piranha_plant_update),
define_builtin(bhv_small_piranha_flame_loop),
define_builtin(bhv_fire_spitter_update),
define_builtin(bhv_fly_guy_flame_loop),
define_builtin(bhv_snufit_loop),
define_builtin(bhv_snufit_balls_loop),
define_builtin(bhv_horizontal_grindel_init),
define_builtin(bhv_horizontal_grindel_update),
define_builtin(bhv_eyerok_boss_init),
define_builtin(bhv_eyerok_boss_loop),
define_builtin(bhv_eyerok_hand_loop),
define_builtin(bhv_klepto_init),
define_builtin(bhv_klepto_update),
define_builtin(bhv_bird_update),
define_builtin(bhv_racing_penguin_init),
define_builtin(bhv_racing_penguin_update),
define_builtin(bhv_penguin_race_finish_line_update),
define_builtin(bhv_penguin_race_shortcut_check_update),
define_builtin(bhv_coffin_spawner_loop),
define_builtin(bhv_coffin_loop),
define_builtin(bhv_clam_loop),
define_builtin(bhv_skeeter_update),
define_builtin(bhv_skeeter_wave_update),
define_builtin(bhv_swing_platform_init),
define_builtin(bhv_swing_platform_update),
define_builtin(bhv_donut_platform_spawner_update),
define_builtin(bhv_donut_platform_update),
define_builtin(bhv_ddd_pole_init),
define_builtin(bhv_ddd_pole_update),
define_builtin(bhv_red_coin_star_marker_init),
define_builtin(bhv_triplet_butterfly_update),
define_builtin(bhv_bubba_loop),
define_builtin(bhv_intro_lakitu_loop),
define_builtin(bhv_intro_peach_loop),
define_builtin(bhv_end_birds_1_loop),
define_builtin(bhv_end_birds_2_loop),
define_builtin(bhv_intro_scene_loop),
define_builtin(bhv_dust_smoke_loop),
define_builtin(bhv_yoshi_loop),
define_builtin(bhv_volcano_trap_loop),
// mario_misc.h
define_builtin(bhv_toad_message_init),
define_builtin(bhv_toad_message_loop),
define_builtin(bhv_unlock_door_star_init),
define_builtin(bhv_unlock_door_star_loop),
// Other
define_builtin(load_object_collision_model),
define_builtin(obj_set_secondary_camera_focus),
};
const void* DynOS_Builtin_Func_GetFromName(const char* aDataName) {
@ -1153,8 +1906,14 @@ const void* DynOS_Builtin_Func_GetFromName(const char* aDataName) {
const void* DynOS_Builtin_Func_GetFromIndex(s32 aIndex) {
size_t count = sizeof(sDynosBuiltinFuncs) / (2 * sizeof(sDynosBuiltinFuncs[0]));
if (aIndex < 0 || aIndex >= count) { return NULL; }
return (const void*)sDynosBuiltinFuncs[aIndex * 2 + 1];
if (aIndex >= 0 && aIndex < count) { return (const void*)sDynosBuiltinFuncs[aIndex * 2 + 1]; }
return NULL;
}
const char *DynOS_Builtin_Func_GetNameFromIndex(s64 aIndex) {
size_t count = sizeof(sDynosBuiltinFuncs) / (2 * sizeof(sDynosBuiltinFuncs[0]));
if (aIndex >= 0 && aIndex < count) { return (const char *)sDynosBuiltinFuncs[aIndex * 2 + 0]; }
return NULL;
}
s32 DynOS_Builtin_Func_GetIndexFromData(const void* aData) {
@ -1165,4 +1924,4 @@ s32 DynOS_Builtin_Func_GetIndexFromData(const void* aData) {
}
}
return -1;
}
}

View file

@ -52,7 +52,7 @@ Collision* DynOS_Col_Get(const char* collisionName) {
}
// check builtin collisions
return (Collision*)DynOS_Builtin_LvlCol_GetFromName(collisionName);
return (Collision*)DynOS_Builtin_Col_GetFromName(collisionName);
}
void DynOS_Col_ModShutdown() {

View file

@ -1,4 +1,5 @@
#include "dynos.cpp.h"
extern "C" {
#include "engine/level_script.h"
#include "game/skybox.h"

332
include/behavior_commands.h Normal file
View file

@ -0,0 +1,332 @@
#ifndef BEHAVIOR_COMMANDS_H
#define BEHAVIOR_COMMANDS_H
#define BC_B(a) _SHIFTL(a, 24, 8)
#define BC_BB(a, b) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8))
#define BC_BBBB(a, b, c, d) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 8, 8) | _SHIFTL(d, 0, 8))
#define BC_BBH(a, b, c) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 16, 8) | _SHIFTL(c, 0, 16))
#define BC_B0H(a, b) (_SHIFTL(a, 24, 8) | _SHIFTL(b, 0, 16))
#define BC_H(a) _SHIFTL(a, 16, 16)
#define BC_HH(a, b) (_SHIFTL(a, 16, 16) | _SHIFTL(b, 0, 16))
#define BC_W(a) ((uintptr_t)(u32)(a))
#define BC_PTR(a) ((uintptr_t)(a))
// Defines the start of the behavior script as well as the object list the object belongs to.
// Has some special behavior for certain objects.
#define BEGIN(objList) \
BC_BB(0x00, objList)
// Delays the behavior script for a certain number of frames.
#define DELAY(num) \
BC_B0H(0x01, num)
// Jumps to a new behavior command and stores the return address in the object's stack.
#define CALL(addr) \
BC_B(0x02), \
BC_PTR(addr)
// Jumps back to the behavior command stored in the object's stack.
#define RETURN() \
BC_B(0x03)
// Jumps to a new behavior script without saving anything.
#define GOTO(addr) \
BC_B(0x04), \
BC_PTR(addr)
// Marks the start of a loop that will repeat a certain number of times.
#define BEGIN_REPEAT(count) \
BC_B0H(0x05, count)
// Marks the end of a repeating loop.
#define END_REPEAT() \
BC_B(0x06)
// Also marks the end of a repeating loop, but continues executing commands following the loop on the same frame.
#define END_REPEAT_CONTINUE() \
BC_B(0x07)
// Marks the beginning of an infinite loop.
#define BEGIN_LOOP() \
BC_B(0x08)
// Marks the end of an infinite loop.
#define END_LOOP() \
BC_B(0x09)
// Exits the behavior script.
// Often used to end behavior scripts that do not contain an infinite loop.
#define BREAK() \
BC_B(0x0A)
// Exits the behavior script, unused.
#define BREAK_UNUSED() \
BC_B(0x0B)
// Executes a native game function.
#define CALL_NATIVE(func) \
BC_B(0x0C), \
BC_PTR(func)
// Adds a float to the specified field.
#define ADD_FLOAT(field, value) \
BC_BBH(0x0D, field, value)
// Sets the specified field to a float.
#define SET_FLOAT(field, value) \
BC_BBH(0x0E, field, value)
// Adds an integer to the specified field.
#define ADD_INT(field, value) \
BC_BBH(0x0F, field, value)
// Sets the specified field to an integer.
#define SET_INT(field, value) \
BC_BBH(0x10, field, value)
// Performs a bitwise OR with the specified field and the given integer.
// Usually used to set an object's flags.
#define OR_INT(field, value) \
BC_BBH(0x11, field, value)
// Performs a bit clear with the specified short. Unused in favor of the 32-bit version.
#define BIT_CLEAR(field, value) \
BC_BBH(0x12, field, value)
// TODO: this one needs a better name / labelling
// Gets a random short, right shifts it the specified amount and adds min to it, then sets the specified field to that value.
#define SET_INT_RAND_RSHIFT(field, min, rshift) \
BC_BBH(0x13, field, min), \
BC_H(rshift)
// Sets the specified field to a random float in the given range.
#define SET_RANDOM_FLOAT(field, min, range) \
BC_BBH(0x14, field, min), \
BC_H(range)
// Sets the specified field to a random integer in the given range.
#define SET_RANDOM_INT(field, min, range) \
BC_BBH(0x15, field, min), \
BC_H(range)
// Adds a random float in the given range to the specified field.
#define ADD_RANDOM_FLOAT(field, min, range) \
BC_BBH(0x16, field, min), \
BC_H(range)
// TODO: better name (unused anyway)
// Gets a random short, right shifts it the specified amount and adds min to it, then adds the value to the specified field. Unused.
#define ADD_INT_RAND_RSHIFT(field, min, rshift) \
BC_BBH(0x17, field, min), \
BC_H(rshift)
// No operation. Unused.
#define CMD_NOP_1(field) \
BC_BB(0x18, field)
// No operation. Unused.
#define CMD_NOP_2(field) \
BC_BB(0x19, field)
// No operation. Unused.
#define CMD_NOP_3(field) \
BC_BB(0x1A, field)
// Sets the current model ID of the object.
#define SET_MODEL(modelID) \
BC_B0H(0x1B, modelID)
// Spawns a child object with the specified model and behavior.
#define SPAWN_CHILD(modelID, behavior) \
BC_B(0x1C), \
BC_W(modelID), \
BC_PTR(behavior)
// Exits the behavior script and despawns the object.
// Often used to end behavior scripts that do not contain an infinite loop.
#define DEACTIVATE() \
BC_B(0x1D)
// Finds the floor triangle directly under the object and moves the object down to it.
#define DROP_TO_FLOOR() \
BC_B(0x1E)
// Sets the destination float field to the sum of the values of the given float fields.
#define SUM_FLOAT(fieldDst, fieldSrc1, fieldSrc2) \
BC_BBBB(0x1F, fieldDst, fieldSrc1, fieldSrc2)
// Sets the destination integer field to the sum of the values of the given integer fields. Unused.
#define SUM_INT(fieldDst, fieldSrc1, fieldSrc2) \
BC_BBBB(0x20, fieldDst, fieldSrc1, fieldSrc2)
// Billboards the current object, making it always face the camera.
#define BILLBOARD() \
BC_B(0x21)
#define CYLBOARD() \
BC_B(0x38)
// Hides the current object.
#define HIDE() \
BC_B(0x22)
// Sets the size of the object's cylindrical hitbox.
#define SET_HITBOX(radius, height) \
BC_B(0x23), \
BC_HH(radius, height)
// No operation. Unused.
#define CMD_NOP_4(field, value) \
BC_BBH(0x24, field, value)
// Delays the behavior script for the number of frames given by the value of the specified field.
#define DELAY_VAR(field) \
BC_BB(0x25, field)
// Unused. Marks the start of a loop that will repeat a certain number of times.
// Uses a u8 as the argument, instead of a s16 like the other version does.
#define BEGIN_REPEAT_UNUSED(count) \
BC_BB(0x26, count)
// Loads the animations for the object. <field> is always set to oAnimations.
#define LOAD_ANIMATIONS(field, anims) \
BC_BB(0x27, field), \
BC_PTR(anims)
// Begins animation and sets the object's current animation index to the specified value.
#define ANIMATE(animIndex) \
BC_BB(0x28, animIndex)
// Spawns a child object with the specified model and behavior, plus a behavior param.
#define SPAWN_CHILD_WITH_PARAM(bhvParam, modelID, behavior) \
BC_B0H(0x29, bhvParam), \
BC_W(modelID), \
BC_PTR(behavior)
// Loads collision data for the object.
#define LOAD_COLLISION_DATA(collisionData) \
BC_B(0x2A), \
BC_PTR(collisionData)
// Sets the size of the object's cylindrical hitbox, and applies a downwards offset.
#define SET_HITBOX_WITH_OFFSET(radius, height, downOffset) \
BC_B(0x2B), \
BC_HH(radius, height), \
BC_H(downOffset)
// Spawns a new object with the specified model and behavior.
#define SPAWN_OBJ(modelID, behavior) \
BC_B(0x2C), \
BC_W(modelID), \
BC_PTR(behavior)
// Sets the home position of the object to its current position.
#define SET_HOME() \
BC_B(0x2D)
// Sets the size of the object's cylindrical hurtbox.
#define SET_HURTBOX(radius, height) \
BC_B(0x2E), \
BC_HH(radius, height)
// Sets the object's interaction type.
#define SET_INTERACT_TYPE(type) \
BC_B(0x2F), \
BC_W(type)
// Sets various parameters that the object uses for calculating physics.
#define SET_OBJ_PHYSICS(wallHitboxRadius, gravity, bounciness, dragStrength, friction, buoyancy, unused1, unused2) \
BC_B(0x30), \
BC_HH(wallHitboxRadius, gravity), \
BC_HH(bounciness, dragStrength), \
BC_HH(friction, buoyancy), \
BC_HH(unused1, unused2)
// Sets the object's interaction subtype. Unused.
#define SET_INTERACT_SUBTYPE(subtype) \
BC_B(0x31), \
BC_W(subtype)
// Sets the object's size to the specified percentage.
#define SCALE(unusedField, percent) \
BC_BBH(0x32, unusedField, percent)
// Performs a bit clear on the object's parent's field with the specified value.
// Used for clearing active particle flags fron Mario's object.
#define PARENT_BIT_CLEAR(field, flags) \
BC_BB(0x33, field), \
BC_W(flags)
// Animates an object using texture animation. <field> is always set to oAnimState.
#define ANIMATE_TEXTURE(field, rate) \
BC_BBH(0x34, field, rate)
// Disables rendering for the object.
#define DISABLE_RENDERING() \
BC_B(0x35)
// Unused. Sets the specified field to an integer. Wastes 4 bytes of space for no reason at all.
#define SET_INT_UNUSED(field, value) \
BC_BB(0x36, field), \
BC_HH(0, value)
// Spawns a water droplet with the given parameters.
#define SPAWN_WATER_DROPLET(dropletParams) \
BC_B(0x37), \
BC_PTR(dropletParams)
// coop
// Defines the id of the behavior script
#define ID(id) \
BC_B0H(0x39, id)
// Jumps to a new behavior command and stores the return address in the object's stack.
#define CALL_EXT(addr) \
BC_B(0x3A), \
BC_PTR(addr)
// Jumps to a new behavior script without saving anything.
#define GOTO_EXT(addr) \
BC_B(0x3B), \
BC_PTR(addr)
// Executes a native game function.
#define CALL_NATIVE_EXT(func) \
BC_B(0x3C), \
BC_PTR(func)
// Spawns a child object with the specified model and behavior.
#define SPAWN_CHILD_EXT(modelID, behavior) \
BC_B(0x3D), \
BC_W(modelID), \
BC_PTR(behavior)
// Spawns a child object with the specified model and behavior, plus a behavior param.
#define SPAWN_CHILD_WITH_PARAM_EXT(bhvParam, modelID, behavior) \
BC_B0H(0x3E, bhvParam), \
BC_W(modelID), \
BC_PTR(behavior)
// Spawns a new object with the specified model and behavior.
#define SPAWN_OBJ_EXT(modelID, behavior) \
BC_B(0x3F), \
BC_W(modelID), \
BC_PTR(behavior)
// Loads the animations for the object. <field> is always set to oAnimations.
#define LOAD_ANIMATIONS_EXT(field, anims) \
BC_BB(0x40, field), \
BC_PTR(anims)
// Loads collision data for the object.
#define LOAD_COLLISION_DATA_EXT(collisionData) \
BC_B(0x41), \
BC_PTR(collisionData)
// This is a special case for behaviors hooked from LUA.
#define CALL_LUA_FUNC(func) \
BC_B(0x42), \
BC_W(func)
#endif // BEHAVIOR_COMMANDS_H

View file

@ -312,4 +312,4 @@
CMD_W(arg), \
CMD_PTR(target)
#endif // LEVEL_COMMANDS_H
#endif // LEVEL_COMMANDS_H

View file

@ -3,6 +3,7 @@
#include "sm64.h"
#include "behavior_data.h"
#include "behavior_script.h"
#include "engine/level_script.h"
#include "game/area.h"
#include "game/behavior_actions.h"
#include "game/game_init.h"
@ -14,7 +15,10 @@
#include "graph_node.h"
#include "surface_collision.h"
#include "pc/network/network.h"
#include "pc/mods/mods.h"
#include "pc/lua/smlua.h"
#include "pc/lua/smlua_hooks.h"
#include "pc/lua/smlua_utils.h"
#include "game/rng_position.h"
// Macros for retrieving arguments from behavior scripts.
@ -892,6 +896,295 @@ static s32 bhv_cmd_id(void) {
return BHV_PROC_CONTINUE;
}
// Command 0x3A: Jumps to a new behavior command and stores the return address in the object's behavior stack.
// Usage: CALL_EXT(addr)
static s32 bhv_cmd_call_ext(void) {
gCurBhvCommand++;
BehaviorScript *behavior = (BehaviorScript *)gCurrentObject->behavior;
s32 modIndex = dynos_behavior_get_active_mod_index(behavior);
if (modIndex == -1) {
LOG_ERROR("Could not find behavior script mod index.");
return BHV_PROC_CONTINUE;
}
const char *behStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(0));
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 call address, could not find behavior '%s'", behStr);
return BHV_PROC_CONTINUE;
}
cur_obj_bhv_stack_push(BHV_CMD_GET_ADDR_OF_CMD(1)); // Store address of the next bhv command in the stack.
const BehaviorScript *jumpAddress = (BehaviorScript *)get_behavior_from_id(behId);
gCurBhvCommand = jumpAddress; // Jump to the new address.
return BHV_PROC_CONTINUE;
}
// Command 0x3B: Jumps to a new behavior script without saving anything.
// Usage: GOTO_EXT(addr)
static s32 bhv_cmd_goto_ext(void) {
BehaviorScript *behavior = (BehaviorScript *)gCurrentObject->behavior;
s32 modIndex = dynos_behavior_get_active_mod_index(behavior);
if (modIndex == -1) {
LOG_ERROR("Could not find behavior script mod index.");
return BHV_PROC_CONTINUE;
}
const char *behStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(0));
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 jump to address, could not find behavior '%s'", behStr);
return BHV_PROC_CONTINUE;
}
gCurBhvCommand = (BehaviorScript *)get_behavior_from_id(behId); // Jump directly to address
return BHV_PROC_CONTINUE;
}
// Command 0x3C: Executes a lua function. Function must not take or return any values.
// Usage: CALL_NATIVE_EXT(func)
static s32 bhv_cmd_call_native_ext(void) {
BehaviorScript *behavior = (BehaviorScript *)gCurrentObject->behavior;
s32 modIndex = dynos_behavior_get_active_mod_index(behavior);
if (modIndex == -1) {
LOG_ERROR("Could not find behavior script mod index.");
gCurBhvCommand += 2;
return BHV_PROC_CONTINUE;
}
const char *funcStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(1));
gSmLuaConvertSuccess = true;
LuaFunction funcRef = smlua_get_function_mod_variable(modIndex, funcStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
funcRef = smlua_get_any_function_mod_variable(funcStr);
}
if (!gSmLuaConvertSuccess || funcRef == 0) {
LOG_LUA("Failed to call lua function, could not find lua function '%s'", funcStr);
gCurBhvCommand += 2;
return BHV_PROC_CONTINUE;
}
// Get our mod.
struct Mod *mod = gActiveMods.entries[modIndex];
// Push the callback onto the stack
lua_rawgeti(gLuaState, LUA_REGISTRYINDEX, funcRef);
// Push object
smlua_push_object(gLuaState, LOT_OBJECT, gCurrentObject);
// Call the callback
if (0 != smlua_call_hook(gLuaState, 1, 0, 0, mod)) {
LOG_LUA("Failed to call the function callback: '%s'", funcStr);
}
gCurBhvCommand += 2;
return BHV_PROC_CONTINUE;
}
// Command 0x3D: Spawns a child object with the specified model and behavior.
// Usage: SPAWN_CHILD_EXT(modelID, behavior)
static s32 bhv_cmd_spawn_child_ext(void) {
u32 model = BHV_CMD_GET_U32(1);
BehaviorScript *behavior = (BehaviorScript *)gCurrentObject->behavior;
s32 modIndex = dynos_behavior_get_active_mod_index(behavior);
if (modIndex == -1) {
LOG_ERROR("Could not find behavior script mod index.");
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
const char *behStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(2));
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 spawn custom child, could not find behavior '%s'", behStr);
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
BehaviorScript *childBhvScript = (BehaviorScript *)get_behavior_from_id(behId);
if (childBhvScript == NULL) {
LOG_LUA("Failed to spawn custom child, could not get behavior '%s' from the id %u.", behStr, behId);
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
struct Object *child = spawn_object_at_origin(gCurrentObject, 0, model, childBhvScript);
if (child != NULL) {
obj_copy_pos_and_angle(child, gCurrentObject);
}
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
// Command 0x3E: Spawns a child object with the specified model and behavior, plus a behavior param.
// Usage: SPAWN_CHILD_WITH_PARAM_EXT(bhvParam, modelID, behavior)
static s32 bhv_cmd_spawn_child_with_param_ext(void) {
u32 bhvParam = BHV_CMD_GET_2ND_S16(0);
u32 modelID = BHV_CMD_GET_U32(1);
BehaviorScript *behavior = (BehaviorScript *)gCurrentObject->behavior;
s32 modIndex = dynos_behavior_get_active_mod_index(behavior);
if (modIndex == -1) {
LOG_ERROR("Could not find behavior script mod index.");
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
const char *behStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(2));
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 spawn custom child with params, could not find behavior '%s'", behStr);
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
BehaviorScript *childBhvScript = (BehaviorScript *)get_behavior_from_id(behId);
if (childBhvScript == NULL) {
LOG_LUA("Failed to spawn custom child with params, could not get behavior '%s' from the id %u.", behStr, behId);
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
struct Object *child = spawn_object_at_origin(gCurrentObject, 0, modelID, childBhvScript);
if (child != NULL) {
obj_copy_pos_and_angle(child, gCurrentObject);
child->oBehParams2ndByte = bhvParam;
}
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
// Command 0x3F: Spawns a new object with the specified model and behavior.
// Usage: SPAWN_OBJ_EXT(modelID, behavior)
static s32 bhv_cmd_spawn_obj_ext(void) {
u32 modelID = BHV_CMD_GET_U32(1);
BehaviorScript *behavior = (BehaviorScript *)gCurrentObject->behavior;
s32 modIndex = dynos_behavior_get_active_mod_index(behavior);
if (modIndex == -1) {
LOG_ERROR("Could not find behavior script mod index.");
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
const char *behStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(2));
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 spawn custom object, could not find behavior '%s'", behStr);
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
BehaviorScript *objBhvScript = (BehaviorScript *)get_behavior_from_id(behId);
if (objBhvScript == NULL) {
LOG_LUA("Failed to spawn custom object, could not get behavior '%s' from the id %u.", behStr, behId);
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
struct Object *object = spawn_object_at_origin(gCurrentObject, 0, modelID, objBhvScript);
if (object != NULL) {
obj_copy_pos_and_angle(object, gCurrentObject);
gCurrentObject->prevObj = object;
}
gCurBhvCommand += 3;
return BHV_PROC_CONTINUE;
}
// Command 0x40: Loads the animations for the object. <field> is always set to oAnimations.
// Usage: LOAD_ANIMATIONS_EXT(field, anims)
static s32 bhv_cmd_load_animations_ext(void) {
u8 field = BHV_CMD_GET_2ND_U8(0);
printf("LOAD_ANIMATIONS_EXT is not yet supported! Skipping behavior command.\n");
//BehaviorScript *behavior = (BehaviorScript *)gCurrentObject->behavior;
//const char *animStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(1));
//cur_obj_set_vptr(field, BHV_CMD_GET_VPTR(1));
gCurBhvCommand += 2;
return BHV_PROC_CONTINUE;
}
// Command 0x41: Loads collision data for the object.
// Usage: LOAD_COLLISION_DATA_EXT(collisionData)
static s32 bhv_cmd_load_collision_data_ext(void) {
BehaviorScript *behavior = (BehaviorScript *)gCurrentObject->behavior;
const char *collisionDataStr = dynos_behavior_get_token(behavior, BHV_CMD_GET_U32(1));
Collision *collisionData = dynos_collision_get(collisionDataStr);
if (collisionData == NULL) {
LOG_ERROR("Failed to load custom collision, could not get collision from name '%s'", collisionDataStr);
gCurBhvCommand += 2;
return BHV_PROC_CONTINUE;
}
gCurrentObject->collisionData = collisionData;
gCurBhvCommand += 2;
return BHV_PROC_CONTINUE;
}
void stub_behavior_script_2(void) {
}
@ -954,7 +1247,15 @@ static BhvCommandProc BehaviorCmdTable[] = {
bhv_cmd_set_int_unused, //36
bhv_cmd_spawn_water_droplet, //37
bhv_cmd_cylboard, //38
bhv_cmd_id //39
bhv_cmd_id, //39
bhv_cmd_call_ext, //3A
bhv_cmd_goto_ext, //3B
bhv_cmd_call_native_ext, //3C
bhv_cmd_spawn_child_ext, //3D
bhv_cmd_spawn_child_with_param_ext, //3E
bhv_cmd_spawn_obj_ext, //3F
bhv_cmd_load_animations_ext, //40
bhv_cmd_load_collision_data_ext, //41
};
// Execute the behavior script of the current object, process the object flags, and other miscellaneous code for updating objects.
@ -1000,7 +1301,7 @@ cur_obj_update_begin:;
s16 objFlags = gCurrentObject->oFlags;
f32 distanceFromMario;
BhvCommandProc bhvCmdProc;
BhvCommandProc bhvCmdProc = NULL;
s32 bhvProcResult;
// Calculate the distance from the object to Mario.

View file

@ -887,13 +887,11 @@ static void level_cmd_place_object_ext(void) {
}
gSmLuaConvertSuccess = true;
gSmLuaSuppressErrors = true;
enum BehaviorId behId = smlua_get_mod_variable(modIndex, behStr);
gSmLuaSuppressErrors = false;
enum BehaviorId behId = smlua_get_integer_mod_variable(modIndex, behStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
behId = smlua_get_any_mod_variable(behStr);
behId = smlua_get_any_integer_mod_variable(behStr);
}
if (!gSmLuaConvertSuccess) {
@ -945,12 +943,10 @@ static void level_cmd_place_object_ext2(void) {
}
gSmLuaConvertSuccess = true;
gSmLuaSuppressErrors = true;
enum ModelExtendedId modelId = smlua_get_mod_variable(modIndex, modelStr);
gSmLuaSuppressErrors = false;
enum ModelExtendedId modelId = smlua_get_integer_mod_variable(modIndex, modelStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
modelId = smlua_get_any_mod_variable(modelStr);
modelId = smlua_get_any_integer_mod_variable(modelStr);
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find model '%s'", modelStr);
@ -959,12 +955,10 @@ static void level_cmd_place_object_ext2(void) {
}
gSmLuaConvertSuccess = true;
gSmLuaSuppressErrors = true;
enum BehaviorId behId = smlua_get_mod_variable(modIndex, behStr);
gSmLuaSuppressErrors = false;
enum BehaviorId behId = smlua_get_integer_mod_variable(modIndex, behStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
behId = smlua_get_any_mod_variable(behStr);
behId = smlua_get_any_integer_mod_variable(behStr);
}
if (!gSmLuaConvertSuccess) {

View file

@ -20,4 +20,115 @@ struct Object* obj_spit_fire(s16 relativePosX, s16 relativePosY, s16 relativePos
f32 startSpeed, f32 endSpeed, s16 movePitch);
void obj_set_speed_to_zero(void);
void bhv_koopa_init(void);
void bhv_koopa_update(void);
void bhv_koopa_race_endpoint_update(void);
void bhv_pokey_body_part_update(void);
void bhv_pokey_update(void);
void bhv_swoop_update(void);
void bhv_fly_guy_update(void);
void bhv_goomba_triplet_spawner_update(void);
void bhv_goomba_init(void);
void bhv_goomba_update(void);
void bhv_chain_chomp_chain_part_update(void);
void bhv_chain_chomp_update(void);
void bhv_wooden_post_update(void);
void bhv_chain_chomp_gate_init(void);
void bhv_chain_chomp_gate_update(void);
void bhv_wiggler_body_part_update(void);
void bhv_wiggler_update(void);
void bhv_spiny_update(void);
void bhv_enemy_lakitu_update(void);
void bhv_cloud_update(void);
void bhv_cloud_part_update(void);
void bhv_camera_lakitu_init(void);
void bhv_camera_lakitu_update(void);
void bhv_monty_mole_hole_update(void);
void bhv_monty_mole_init(void);
void bhv_monty_mole_update(void);
void bhv_monty_mole_rock_update(void);
void bhv_platform_on_track_init(void);
void bhv_platform_on_track_update(void);
void bhv_track_ball_update(void);
void bhv_seesaw_platform_init(void);
void bhv_seesaw_platform_update(void);
void bhv_ferris_wheel_axle_init(void);
void bhv_ferris_wheel_platform_update(void);
void bhv_water_bomb_spawner_update(void);
void bhv_water_bomb_update(void);
void bhv_water_bomb_shadow_update(void);
void bhv_ttc_rotating_solid_init(void);
void bhv_ttc_rotating_solid_update(void);
void bhv_ttc_pendulum_init(void);
void bhv_ttc_pendulum_update(void);
void bhv_ttc_treadmill_init(void);
void bhv_ttc_treadmill_update(void);
void bhv_ttc_moving_bar_init(void);
void bhv_ttc_moving_bar_update(void);
void bhv_ttc_cog_init(void);
void bhv_ttc_cog_update(void);
void bhv_ttc_pit_block_init(void);
void bhv_ttc_pit_block_update(void);
void bhv_ttc_elevator_init(void);
void bhv_ttc_elevator_update(void);
void bhv_ttc_2d_rotator_init(void);
void bhv_ttc_2d_rotator_update(void);
void bhv_ttc_spinner_update(void);
void bhv_mr_blizzard_init(void);
void bhv_mr_blizzard_update(void);
void bhv_mr_blizzard_snowball(void);
void bhv_sliding_plat_2_init(void);
void bhv_sliding_plat_2_loop(void);
void bhv_rotating_octagonal_plat_init(void);
void bhv_rotating_octagonal_plat_loop(void);
void bhv_animates_on_floor_switch_press_init(void);
void bhv_animates_on_floor_switch_press_loop(void);
void bhv_activated_back_and_forth_platform_init(void);
void bhv_activated_back_and_forth_platform_update(void);
void bhv_recovery_heart_loop(void);
void bhv_bubble_cannon_barrel_loop(void);
void bhv_water_bomb_cannon_loop(void);
void bhv_unagi_init(void);
void bhv_unagi_loop(void);
void bhv_unagi_subobject_loop(void);
void bhv_dorrie_update(void);
void bhv_haunted_chair_init(void);
void bhv_haunted_chair_loop(void);
void bhv_mad_piano_update(void);
void bhv_flying_bookend_loop(void);
void bhv_bookend_spawn_loop(void);
void bhv_haunted_bookshelf_manager_loop(void);
void bhv_book_switch_loop(void);
void bhv_fire_piranha_plant_init(void);
void bhv_fire_piranha_plant_update(void);
void bhv_fire_spitter_update(void);
void bhv_small_piranha_flame_loop(void);
void bhv_fly_guy_flame_loop(void);
void bhv_snufit_loop(void);
void bhv_snufit_balls_loop(void);
void bhv_horizontal_grindel_init(void);
void bhv_horizontal_grindel_update(void);
void bhv_eyerok_boss_init(void);
void bhv_eyerok_boss_loop(void);
void bhv_eyerok_hand_loop(void);
void bhv_klepto_init(void);
void bhv_klepto_update(void);
void bhv_bird_update(void);
void bhv_racing_penguin_init(void);
void bhv_racing_penguin_update(void);
void bhv_coffin_spawner_loop(void);
void bhv_coffin_loop(void);
void bhv_clam_loop(void);
void bhv_skeeter_update(void);
void bhv_skeeter_wave_update(void);
void bhv_swing_platform_init(void);
void bhv_swing_platform_update(void);
void bhv_donut_platform_spawner_update(void);
void bhv_donut_platform_update(void);
void bhv_ddd_pole_init(void);
void bhv_ddd_pole_update(void);
void bhv_red_coin_star_marker_init(void);
void bhv_triplet_butterfly_update(void);
void bhv_bubba_loop(void);
#endif // OBJ_BEHAVIORS_2_H

View file

@ -354,6 +354,7 @@ static void snap_object_to_floor(struct Object *obj) {
struct Object *create_object(const BehaviorScript *bhvScript) {
if (!bhvScript) { return NULL; }
s32 objListIndex = OBJ_LIST_DEFAULT;
bool luaBehavior = is_behavior_hooked_from_lua(bhvScript);
const BehaviorScript *behavior = smlua_override_behavior(bhvScript);
// If the first behavior script command is "begin <object list>", then
@ -371,7 +372,7 @@ struct Object *create_object(const BehaviorScript *bhvScript) {
struct Object *obj = allocate_object(objList);
if (obj == NULL) { return NULL; }
obj->curBhvCommand = bhvScript;
obj->curBhvCommand = luaBehavior ? bhvScript : behavior;
obj->behavior = behavior;
if (objListIndex == OBJ_LIST_UNIMPORTANT) {

View file

@ -1,4 +1,5 @@
#include "smlua.h"
#include "behavior_commands.h"
#include "pc/mods/mod.h"
#include "src/game/object_list_processor.h"
#include "pc/djui/djui_chat_message.h"
@ -84,7 +85,7 @@ struct LuaHookedEvent {
static struct LuaHookedEvent sHookedEvents[HOOK_MAX] = { 0 };
static int smlua_call_hook(lua_State* L, int nargs, int nresults, int errfunc, struct Mod* activeMod) {
int smlua_call_hook(lua_State* L, int nargs, int nresults, int errfunc, struct Mod* activeMod) {
struct Mod* prev = gLuaActiveMod;
gLuaActiveMod = activeMod;
gLuaLastHookMod = activeMod;
@ -617,11 +618,13 @@ u32 smlua_get_action_interaction_type(struct MarioState* m) {
struct LuaHookedBehavior {
u32 behaviorId;
u32 overrideId;
BehaviorScript behavior[2];
u32 originalId;
BehaviorScript *behavior;
const BehaviorScript* originalBehavior;
int initReference;
int loopReference;
bool replace;
bool luaBehavior;
struct Mod* mod;
};
@ -641,19 +644,20 @@ enum BehaviorId smlua_get_original_behavior_id(const BehaviorScript* behavior) {
return id;
}
const BehaviorScript* smlua_override_behavior(const BehaviorScript* behavior) {
lua_State* L = gLuaState;
const BehaviorScript* smlua_override_behavior(const BehaviorScript *behavior) {
lua_State *L = gLuaState;
if (L == NULL) { return behavior; }
enum BehaviorId id = get_id_from_behavior(behavior);
const BehaviorScript* luaBehavior = get_lua_behavior_from_id(id, false);
if (luaBehavior != NULL) { return luaBehavior; }
const BehaviorScript *hookedBehavior = get_hooked_behavior_from_id(id, false);
if (hookedBehavior != NULL) { return hookedBehavior; }
return behavior + *sBehaviorOffset;
}
const BehaviorScript* get_lua_behavior_from_id(enum BehaviorId id, bool returnOriginal) {
lua_State* L = gLuaState;
if (L == NULL) { return false; }
const BehaviorScript* get_hooked_behavior_from_id(enum BehaviorId id, bool returnOriginal) {
lua_State *L = gLuaState;
if (L == NULL) { return NULL; }
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &sHookedBehaviors[i];
if (hooked->behaviorId != id && hooked->overrideId != id) { continue; }
@ -663,6 +667,56 @@ const BehaviorScript* get_lua_behavior_from_id(enum BehaviorId id, bool returnOr
return NULL;
}
bool is_behavior_hooked_from_lua(const BehaviorScript *behavior) {
lua_State *L = gLuaState;
if (L == NULL) { return false; }
enum BehaviorId id = get_id_from_behavior(behavior);
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior *hooked = &sHookedBehaviors[i];
if (hooked->behaviorId != id && hooked->overrideId != id) { continue; }
return hooked->luaBehavior;
}
return false;
}
int hook_behavior(BehaviorScript *bhvScript, const char *bhvName) {
if (sHookedBehaviorsCount >= MAX_HOOKED_BEHAVIORS) {
LOG_ERROR("Hooked behaviors exceeded maximum references!");
return 0;
}
u32 originalBehaviorId = get_id_from_behavior(bhvScript);
u8 newBehavior = originalBehaviorId >= id_bhv_max_count;
struct LuaHookedBehavior *hooked = &sHookedBehaviors[sHookedBehaviorsCount];
u16 customBehaviorId = (sHookedBehaviorsCount & 0xFFFF) | LUA_BEHAVIOR_FLAG;
hooked->behavior = bhvScript;
hooked->behavior[1] = (BehaviorScript)BC_B0H(0x39, customBehaviorId); // This is ID(customBehaviorId)
hooked->behaviorId = customBehaviorId;
hooked->overrideId = newBehavior ? customBehaviorId : originalBehaviorId;
hooked->originalId = originalBehaviorId;
hooked->originalBehavior = newBehavior ? bhvScript : get_behavior_from_id(originalBehaviorId);
hooked->initReference = 0;
hooked->loopReference = 0;
hooked->replace = true;
hooked->luaBehavior = false;
hooked->mod = gLuaActiveMod;
sHookedBehaviorsCount++;
// We want to push the behavior into the global LUA state. So mods can access it.
// It's also used for some things that would normally access a LUA behavior instead.
lua_State* L = gLuaState;
if (L != NULL) {
lua_pushinteger(L, customBehaviorId);
lua_setglobal(L, bhvName);
}
return 1;
}
int smlua_hook_behavior(lua_State* L) {
if (L == NULL) { return 0; }
if (!smlua_functions_valid_param_count(L, 5)) { return 0; }
@ -729,14 +783,18 @@ int smlua_hook_behavior(lua_State* L) {
struct LuaHookedBehavior* hooked = &sHookedBehaviors[sHookedBehaviorsCount];
u16 customBehaviorId = (sHookedBehaviorsCount & 0xFFFF) | LUA_BEHAVIOR_FLAG;
hooked->behavior = calloc(3, sizeof(BehaviorScript));
hooked->behavior[0] = (BehaviorScript)BC_BB(0x00, objectList); // This is BEGIN(objectList)
hooked->behavior[1] = (BehaviorScript)BC_B0H(0x39, customBehaviorId); // This is ID(customBehaviorId)
hooked->behavior[2] = 0;
hooked->behaviorId = customBehaviorId;
hooked->overrideId = noOverrideId ? customBehaviorId : overrideBehaviorId;
hooked->behavior[0] = (((unsigned int) (((unsigned int)(0x00) & ((0x01 << (8)) - 1)) << (24))) | ((unsigned int) (((unsigned int)(objectList) & ((0x01 << (8)) - 1)) << (16)))); // gross. this is BEGIN(objectList)
hooked->behavior[1] = (((unsigned int) (((unsigned int)(0x39) & ((0x01 << (8)) - 1)) << (24))) | ((unsigned int) (((unsigned int)(customBehaviorId) & ((0x01 << (16)) - 1)) << (0)))); // gross. this is ID(customBehaviorId)
hooked->originalId = customBehaviorId; // For LUA behaviors. The only behavior id they have IS their custom one.
hooked->originalBehavior = originalBehavior ? originalBehavior : hooked->behavior;
hooked->initReference = initReference;
hooked->loopReference = loopReference;
hooked->replace = replaceBehavior;
hooked->luaBehavior = true;
hooked->mod = gLuaActiveMod;
sHookedBehaviorsCount++;
@ -758,13 +816,19 @@ bool smlua_call_behavior_hook(const BehaviorScript** behavior, struct Object* ob
continue;
}
// figure out whether to run before or after
// Figure out whether to run before or after
if (before && !hooked->replace) {
return false;
}
if (!before && hooked->replace) {
return false;
}
// This behavior doesn't call it's LUA functions in this manner. It actually uses the normal behavior
// system.
if (!hooked->luaBehavior) {
return false;
}
// retrieve and remember first run
bool firstRun = (object->curBhvCommand == hooked->originalBehavior) || (object->curBhvCommand == hooked->behavior);
@ -1010,13 +1074,28 @@ void smlua_clear_hooks(void) {
for (int i = 0; i < sHookedBehaviorsCount; i++) {
struct LuaHookedBehavior* hooked = &sHookedBehaviors[i];
// If this is NULL. We can't do anything with it.
if (hooked->behavior != NULL) {
// If it's a LUA made behavior, The behavior is allocated so reset and free it.
// Otherwise it's a DynOS behavior and it needs to have it's original id put back where it belongs.
if (hooked->luaBehavior) {
// Just free the allocated behavior.
free(hooked->behavior);
} else {
hooked->behavior[1] = (BehaviorScript)BC_B0H(0x39, hooked->originalId); // This is ID(hooked->originalId)
}
}
// Reset the variables.
hooked->behaviorId = 0;
hooked->behavior[0] = 0;
hooked->behavior[1] = 0;
hooked->overrideId = 0;
hooked->originalId = 0;
hooked->behavior = NULL;
hooked->originalBehavior = NULL;
hooked->initReference = 0;
hooked->loopReference = 0;
hooked->replace = false;
hooked->luaBehavior = false;
hooked->mod = NULL;
}
sHookedBehaviorsCount = 0;

View file

@ -4,6 +4,9 @@
#include <stdbool.h>
#include "include/behavior_table.h"
#include "smlua.h"
#include "pc/mods/mod.h"
// forward declare
struct Camera;
@ -63,6 +66,8 @@ static const char* LuaHookedEventTypeName[] = {
extern u32 gLuaMarioActionIndex;
int hook_behavior(BehaviorScript *bhvScript, const char *bhvName);
void smlua_call_event_hooks(enum LuaHookedEventType hookType);
void smlua_call_event_hooks_bool_param(enum LuaHookedEventType hookType, bool value);
void smlua_call_event_hooks_bool_param_ret_bool(enum LuaHookedEventType hookType, bool value, bool* returnValue);
@ -79,9 +84,11 @@ void smlua_call_event_hooks_value_param(enum LuaHookedEventType hookType, int mo
enum BehaviorId smlua_get_original_behavior_id(const BehaviorScript* behavior);
const BehaviorScript* smlua_override_behavior(const BehaviorScript* behavior);
const BehaviorScript* get_lua_behavior_from_id(enum BehaviorId id, bool returnOriginal);
const BehaviorScript* get_hooked_behavior_from_id(enum BehaviorId id, bool returnOriginal);
bool is_behavior_hooked_from_lua(const BehaviorScript *behavior);
bool smlua_call_behavior_hook(const BehaviorScript** behavior, struct Object* object, bool before);
int smlua_call_hook(lua_State* L, int nargs, int nresults, int errfunc, struct Mod* activeMod);
bool smlua_call_action_hook(struct MarioState* m, s32* returnValue);
u32 smlua_get_action_interaction_type(struct MarioState* m);

View file

@ -496,9 +496,21 @@ lua_Number smlua_get_number_field(int index, char* name) {
return val;
}
LuaFunction smlua_get_function_field(int index, char *name) {
if (lua_type(gLuaState, index) != LUA_TTABLE) {
LOG_LUA_LINE("smlua_get_function_field received improper type '%d'", lua_type(gLuaState, index));
gSmLuaConvertSuccess = false;
return 0;
}
lua_getfield(gLuaState, index, name);
LuaFunction val = smlua_to_lua_function(gLuaState, -1);
lua_pop(gLuaState, 1);
return val;
}
///////////////////////////////////////////////////////////////////////////////////////////
s64 smlua_get_mod_variable(u16 modIndex, const char* variable) {
s64 smlua_get_integer_mod_variable(u16 modIndex, const char* variable) {
lua_State* L = gLuaState;
// figure out entry
@ -507,18 +519,22 @@ s64 smlua_get_mod_variable(u16 modIndex, const char* variable) {
LOG_ERROR("Could not find mod list entry for modIndex: %u", modIndex);
return 0;
}
u8 prevSuppress = gSmLuaSuppressErrors;
int prevTop = lua_gettop(L);
lua_getglobal(L, "_G"); // get global table
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // get the file's "global" table
gSmLuaSuppressErrors = true;
s64 value = smlua_get_integer_field(-1, (char*)variable);
lua_settop(L, prevTop);
// return variable
gSmLuaSuppressErrors = prevSuppress;
return value;
}
s64 smlua_get_any_mod_variable(const char* variable) {
s64 smlua_get_any_integer_mod_variable(const char* variable) {
lua_State* L = gLuaState;
u8 prevSuppress = gSmLuaSuppressErrors;
@ -545,6 +561,57 @@ s64 smlua_get_any_mod_variable(const char* variable) {
return value;
}
LuaFunction smlua_get_function_mod_variable(u16 modIndex, const char *variable) {
lua_State *L = gLuaState;
// figure out entry
struct Mod *mod = gActiveMods.entries[modIndex];
if (mod == NULL) {
LOG_ERROR("Could not find mod list entry for modIndex: %u", modIndex);
return 0;
}
u8 prevSuppress = gSmLuaSuppressErrors;
int prevTop = lua_gettop(L);
lua_getglobal(L, "_G"); // get global table
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // get the file's "global" table
gSmLuaSuppressErrors = true;
LuaFunction value = smlua_get_function_field(-1, (char *)variable);
lua_settop(L, prevTop);
// return variable
gSmLuaSuppressErrors = prevSuppress;
return value;
}
LuaFunction smlua_get_any_function_mod_variable(const char *variable) {
lua_State *L = gLuaState;
u8 prevSuppress = gSmLuaSuppressErrors;
LuaFunction value = 0;
for (s32 i = 0; i < gActiveMods.entryCount; i++) {
// figure out entry
struct Mod *mod = gActiveMods.entries[i];
int prevTop = lua_gettop(L);
lua_getglobal(L, "_G"); // get global table
lua_getfield(L, LUA_REGISTRYINDEX, mod->relativePath); // get the file's "global" table
gSmLuaSuppressErrors = true;
value = smlua_get_function_field(-1, (char *)variable);
lua_settop(L, prevTop);
if (gSmLuaConvertSuccess) {
gSmLuaSuppressErrors = prevSuppress;
return value;
}
}
// return variable
gSmLuaSuppressErrors = prevSuppress;
return value;
}
///////////////////////////////////////////////////////////////////////////////////////////
char* smlua_lnt_to_str(struct LSTNetworkType* lnt) {

View file

@ -37,11 +37,14 @@ void smlua_push_lnt(struct LSTNetworkType* lnt);
lua_Integer smlua_get_integer_field(int index, char* name);
lua_Number smlua_get_number_field(int index, char* name);
LuaFunction smlua_get_function_field(int index, char *name);
char* smlua_lnt_to_str(struct LSTNetworkType* lnt);
s64 smlua_get_mod_variable(u16 modIndex, const char* variable) ;
s64 smlua_get_any_mod_variable(const char* variable) ;
s64 smlua_get_integer_mod_variable(u16 modIndex, const char* variable);
s64 smlua_get_any_integer_mod_variable(const char* variable);
LuaFunction smlua_get_function_mod_variable(u16 modIndex, const char *variable);
LuaFunction smlua_get_any_function_mod_variable(const char *variable);
void smlua_logline(void);
void smlua_dump_stack(void);

View file

@ -32,6 +32,7 @@
struct GlobalObjectAnimations gGlobalObjectAnimations = {
.amp_seg8_anims_08004034 = (struct Animation**) amp_seg8_anims_08004034,
.birds_seg5_anims_050009E8 = (struct Animation**) birds_seg5_anims_050009E8,
.blargg_seg5_anims_0500616C = (struct Animation**) blargg_seg5_anims_0500616C,
.blue_fish_seg3_anims_0301C2B0 = (struct Animation**) blue_fish_seg3_anims_0301C2B0,
.bobomb_seg8_anims_0802396C = (struct Animation**) bobomb_seg8_anims_0802396C,
.bookend_seg5_anims_05002540 = (struct Animation**) bookend_seg5_anims_05002540,
@ -46,6 +47,7 @@ struct GlobalObjectAnimations gGlobalObjectAnimations = {
.chilly_chief_seg6_anims_06003994 = (struct Animation**) chilly_chief_seg6_anims_06003994,
.chuckya_seg8_anims_0800C070 = (struct Animation**) chuckya_seg8_anims_0800C070,
.clam_shell_seg5_anims_05001744 = (struct Animation**) clam_shell_seg5_anims_05001744,
.cyan_fish_seg6_anims_0600E264 = (struct Animation**) cyan_fish_seg6_anims_0600E264,
.door_seg3_anims_030156C0 = (struct Animation**) door_seg3_anims_030156C0,
.dorrie_seg6_anims_0600F638 = (struct Animation**) dorrie_seg6_anims_0600F638,
.eyerok_seg5_anims_050116E4 = (struct Animation**) eyerok_seg5_anims_050116E4,
@ -73,6 +75,7 @@ struct GlobalObjectAnimations gGlobalObjectAnimations = {
.snowman_seg5_anims_0500D118 = (struct Animation**) snowman_seg5_anims_0500D118,
.spindrift_seg5_anims_05002D68 = (struct Animation**) spindrift_seg5_anims_05002D68,
.spiny_seg5_anims_05016EAC = (struct Animation**) spiny_seg5_anims_05016EAC,
.spiny_egg_seg5_anims_050157E4 = (struct Animation**) spiny_egg_seg5_anims_050157E4,
.sushi_seg5_anims_0500AE54 = (struct Animation**) sushi_seg5_anims_0500AE54,
.swoop_seg6_anims_060070D0 = (struct Animation**) swoop_seg6_anims_060070D0,
.toad_seg6_anims_0600FB58 = (struct Animation**) toad_seg6_anims_0600FB58,

View file

@ -6,6 +6,7 @@ typedef struct Animation* ObjectAnimPointer;
struct GlobalObjectAnimations {
ObjectAnimPointer* amp_seg8_anims_08004034;
ObjectAnimPointer* birds_seg5_anims_050009E8;
ObjectAnimPointer* blargg_seg5_anims_0500616C;
ObjectAnimPointer* blue_fish_seg3_anims_0301C2B0;
ObjectAnimPointer* bobomb_seg8_anims_0802396C;
ObjectAnimPointer* bookend_seg5_anims_05002540;
@ -20,6 +21,7 @@ struct GlobalObjectAnimations {
ObjectAnimPointer* chilly_chief_seg6_anims_06003994;
ObjectAnimPointer* chuckya_seg8_anims_0800C070;
ObjectAnimPointer* clam_shell_seg5_anims_05001744;
ObjectAnimPointer* cyan_fish_seg6_anims_0600E264;
ObjectAnimPointer* door_seg3_anims_030156C0;
ObjectAnimPointer* dorrie_seg6_anims_0600F638;
ObjectAnimPointer* eyerok_seg5_anims_050116E4;
@ -47,6 +49,7 @@ struct GlobalObjectAnimations {
ObjectAnimPointer* snowman_seg5_anims_0500D118;
ObjectAnimPointer* spindrift_seg5_anims_05002D68;
ObjectAnimPointer* spiny_seg5_anims_05016EAC;
ObjectAnimPointer* spiny_egg_seg5_anims_050157E4;
ObjectAnimPointer* sushi_seg5_anims_0500AE54;
ObjectAnimPointer* swoop_seg6_anims_060070D0;
ObjectAnimPointer* toad_seg6_anims_0600FB58;

View file

@ -78,6 +78,7 @@ struct GlobalObjectCollisionData gGlobalObjectCollisionData = {
.ddd_seg7_collision_submarine = (Collision*) ddd_seg7_collision_submarine,
.door_seg3_collision_0301CE78 = (Collision*) door_seg3_collision_0301CE78,
.dorrie_seg6_collision_0600F644 = (Collision*) dorrie_seg6_collision_0600F644,
.dorrie_seg6_collision_0600FBB8 = (Collision*) dorrie_seg6_collision_0600FBB8,
.exclamation_box_outline_seg8_collision_08025F78 = (Collision*) exclamation_box_outline_seg8_collision_08025F78,
.hmc_seg7_collision_controllable_platform = (Collision*) hmc_seg7_collision_controllable_platform,
.hmc_seg7_collision_controllable_platform_sub = (Collision*) hmc_seg7_collision_controllable_platform_sub,
@ -134,6 +135,7 @@ struct GlobalObjectCollisionData gGlobalObjectCollisionData = {
.ttm_seg7_collision_pitoune_2 = (Collision*) ttm_seg7_collision_pitoune_2,
.ttm_seg7_collision_podium_warp = (Collision*) ttm_seg7_collision_podium_warp,
.ttm_seg7_collision_ukiki_cage = (Collision*) ttm_seg7_collision_ukiki_cage,
.unknown_seg8_collision_080262F8 = (Collision*) unknown_seg8_collision_080262F8,
.warp_pipe_seg3_collision_03009AC8 = (Collision*) warp_pipe_seg3_collision_03009AC8,
.wdw_seg7_collision_arrow_lift = (Collision*) wdw_seg7_collision_arrow_lift,
.wdw_seg7_collision_express_elevator_platform = (Collision*) wdw_seg7_collision_express_elevator_platform,

View file

@ -32,6 +32,7 @@ struct GlobalObjectCollisionData {
Collision* ddd_seg7_collision_submarine;
Collision* door_seg3_collision_0301CE78;
Collision* dorrie_seg6_collision_0600F644;
Collision* dorrie_seg6_collision_0600FBB8;
Collision* exclamation_box_outline_seg8_collision_08025F78;
Collision* hmc_seg7_collision_controllable_platform;
Collision* hmc_seg7_collision_controllable_platform_sub;
@ -88,6 +89,7 @@ struct GlobalObjectCollisionData {
Collision* ttm_seg7_collision_pitoune_2;
Collision* ttm_seg7_collision_podium_warp;
Collision* ttm_seg7_collision_ukiki_cage;
Collision* unknown_seg8_collision_080262F8;
Collision* warp_pipe_seg3_collision_03009AC8;
Collision* wdw_seg7_collision_arrow_lift;
Collision* wdw_seg7_collision_express_elevator_platform;

View file

@ -99,6 +99,29 @@ static void mod_activate_lvl(struct Mod* mod, struct ModFile* file) {
dynos_add_level(mod->index, file->cachedPath, lvlName);
}
static void mod_activate_bhv(struct Mod *mod, struct ModFile *file) {
// copy bhv name
char bhvName[64] = { 0 };
if (snprintf(bhvName, 63, "%s", path_basename(file->relativePath)) < 0) {
LOG_ERROR("Truncated bhv name");
return;
}
// remove '.bhv'
char *g = bhvName;
while (*g != '\0') {
if (*g == '.') {
*g = '\0';
break;
}
g++;
}
// Add to levels
LOG_INFO("Activating DynOS bhv: '%s', '%s'", file->cachedPath, bhvName);
dynos_add_behavior(mod->index, file->cachedPath, bhvName);
}
void mod_activate(struct Mod* mod) {
// activate dynos models
for (int i = 0; i < mod->fileCount; i++) {
@ -113,6 +136,9 @@ void mod_activate(struct Mod* mod) {
if (str_ends_with(file->relativePath, ".lvl")) {
mod_activate_lvl(mod, file);
}
if (str_ends_with(file->relativePath, ".bhv")) {
mod_activate_bhv(mod, file);
}
if (str_ends_with(file->relativePath, ".tex")) {
mod_activate_tex(file);
}
@ -273,6 +299,12 @@ static bool mod_load_files(struct Mod* mod, char* modName, char* fullPath) {
const char* fileTypes[] = { ".bin", ".col", NULL };
if (!mod_load_files_dir(mod, fullPath, "actors", fileTypes)) { return false; }
}
// deal with behaviors directory
{
const char* fileTypes[] = { ".bhv", NULL };
if (!mod_load_files_dir(mod, fullPath, "data", fileTypes)) { return false; }
}
// deal with textures directory
{

View file

@ -121,6 +121,8 @@ bool network_init(enum NetworkType inNetworkType) {
mods_activate(&gLocalMods);
smlua_init();
dynos_behavior_hook_all_custom_behaviors();
network_player_connected(NPT_LOCAL, 0, configPlayerModel, configPlayerPalette, configPlayerName);
extern u8* gOverrideEeprom;

View file

@ -236,6 +236,7 @@ void network_receive_join(struct Packet* p) {
mods_activate(&gRemoteMods);
djui_panel_modlist_create(NULL);
smlua_init();
dynos_behavior_hook_all_custom_behaviors();
network_send_network_players_request();
network_send_lua_sync_table_request();