mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2026-05-10 19:01:46 +00:00
Merge branch 'dev' into screen-shader-effects
This commit is contained in:
commit
840db50ed0
21 changed files with 311 additions and 141 deletions
|
|
@ -17,3 +17,6 @@ sm64coopdx is moddable via Lua, similar to Roblox and Garry's Mod's Lua APIs. To
|
|||
|
||||
## Wiki
|
||||
The wiki is made using GitHub's wiki feature, you can go to the wiki tab or click [here](https://github.com/coop-deluxe/sm64coopdx/wiki).
|
||||
|
||||
## Community
|
||||
We have an official Discord server open to the public [here](https://discord.gg/TJVKHS4).
|
||||
|
|
|
|||
|
|
@ -8271,7 +8271,9 @@ HOOK_ON_FIND_WATER_LEVEL = 63 --- @type LuaHookedEventType
|
|||
HOOK_ON_FIND_POISON_GAS_LEVEL = 64 --- @type LuaHookedEventType
|
||||
HOOK_ON_FIND_SURFACE_ON_RAY = 65 --- @type LuaHookedEventType
|
||||
HOOK_ON_DYNOS_PACK_TOGGLED = 66 --- @type LuaHookedEventType
|
||||
HOOK_MAX = 67 --- @type LuaHookedEventType
|
||||
HOOK_BEFORE_PLAY_MODE_UPDATE = 67 --- @type LuaHookedEventType
|
||||
HOOK_ON_PLAY_MODE_UPDATE = 68 --- @type LuaHookedEventType
|
||||
HOOK_MAX = 69 --- @type LuaHookedEventType
|
||||
|
||||
--- @alias LuaHookedEventType
|
||||
--- | `HOOK_UPDATE`
|
||||
|
|
@ -8341,6 +8343,8 @@ HOOK_MAX = 67 --- @type LuaHookedEventType
|
|||
--- | `HOOK_ON_FIND_POISON_GAS_LEVEL`
|
||||
--- | `HOOK_ON_FIND_SURFACE_ON_RAY`
|
||||
--- | `HOOK_ON_DYNOS_PACK_TOGGLED`
|
||||
--- | `HOOK_BEFORE_PLAY_MODE_UPDATE`
|
||||
--- | `HOOK_ON_PLAY_MODE_UPDATE`
|
||||
--- | `HOOK_MAX`
|
||||
|
||||
--- @type integer
|
||||
|
|
@ -11241,6 +11245,9 @@ ANIM_FLAG_7 = (1 << 7)
|
|||
--- @type integer
|
||||
ANIM_FLAG_BONE_TRANS = (1 << 8)
|
||||
|
||||
--- @type integer
|
||||
ANIM_FLAG_BONE_SCALE = (1 << 9)
|
||||
|
||||
--- @type integer
|
||||
OBJECT_MAX_BHV_STACK = 16
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,25 @@
|
|||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <unordered_map>
|
||||
#include "dynos.cpp.h"
|
||||
|
||||
extern "C" {
|
||||
#include "object_fields.h"
|
||||
#include "game/level_update.h"
|
||||
#include "game/object_list_processor.h"
|
||||
#include "pc/configfile.h"
|
||||
#include "pc/lua/smlua_hooks.h"
|
||||
#include "pc/mods/mod_fs.h"
|
||||
}
|
||||
|
||||
static ObjectList sObjectListsToOverride[] = {
|
||||
OBJ_LIST_PLAYER,
|
||||
OBJ_LIST_DESTRUCTIVE,
|
||||
OBJ_LIST_GENACTOR,
|
||||
OBJ_LIST_PUSHABLE,
|
||||
OBJ_LIST_LEVEL,
|
||||
OBJ_LIST_DEFAULT,
|
||||
OBJ_LIST_SURFACE,
|
||||
OBJ_LIST_POLELIKE,
|
||||
OBJ_LIST_UNIMPORTANT
|
||||
};
|
||||
|
||||
// Static maps/arrays
|
||||
static std::map<const void*, ActorGfx>& DynosValidActors() {
|
||||
static std::map<const void*, ActorGfx> sDynosValidActors;
|
||||
|
|
@ -25,13 +33,11 @@ static std::vector<std::pair<std::string, void *>> &DynosCustomActors() {
|
|||
|
||||
static std::map<struct GraphNode *, struct GraphNode *> sModifiedGraphNodes;
|
||||
|
||||
// TODO: the cleanup/refactor didn't really go as planned.
|
||||
// clean up the actor management code more
|
||||
|
||||
std::map<const void *, ActorGfx> &DynOS_Actor_GetValidActors() {
|
||||
return DynosValidActors();
|
||||
}
|
||||
|
||||
// Only used for mods with custom actors.
|
||||
bool DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFilename, const char *aActorName) {
|
||||
const void* georef = DynOS_Builtin_Actor_GetFromName(aActorName);
|
||||
|
||||
|
|
@ -51,17 +57,14 @@ bool DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFil
|
|||
return false;
|
||||
}
|
||||
|
||||
// Alloc and init the actors gfx list
|
||||
// Load the graph node
|
||||
u32 id = 0;
|
||||
ActorGfx actorGfx = { };
|
||||
actorGfx.mGfxData = _GfxData;
|
||||
actorGfx.mPackIndex = MOD_PACK_INDEX;
|
||||
actorGfx.mGraphNode = (GraphNode *) DynOS_Model_LoadGeo(&id, MODEL_POOL_SESSION, geoLayout, true);
|
||||
if (!actorGfx.mGraphNode) {
|
||||
GraphNode *graphNode = (GraphNode *) DynOS_Model_LoadGeo(&id, MODEL_POOL_SESSION, geoLayout, true);
|
||||
if (!graphNode) {
|
||||
PrintError(" ERROR: Couldn't load graph node for \"%s\"", actorName.c_str());
|
||||
return false;
|
||||
}
|
||||
actorGfx.mGraphNode->georef = georef;
|
||||
graphNode->georef = georef;
|
||||
|
||||
// Add to custom actors
|
||||
if (georef == NULL) {
|
||||
|
|
@ -69,6 +72,13 @@ bool DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFil
|
|||
georef = geoLayout;
|
||||
}
|
||||
|
||||
// Alloc and init the actors gfx list
|
||||
ActorGfx actorGfx = {
|
||||
.mGfxData = _GfxData,
|
||||
.mGraphNode = graphNode,
|
||||
.mPackIndex = MOD_PACK_INDEX,
|
||||
};
|
||||
|
||||
// Add to list
|
||||
DynOS_Actor_Valid(georef, actorGfx);
|
||||
return true;
|
||||
|
|
@ -121,44 +131,28 @@ const void *DynOS_Actor_GetLayoutFromName(const char *aActorName) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool DynOS_Actor_GetModIndexAndTokenFromGfxData(const GfxData *aGfxData, u32 aTokenIndex, s32 *outModIndex, s32 *outModFileIndex, const char **outToken) {
|
||||
if (aGfxData) {
|
||||
if (outModIndex) { *outModIndex = aGfxData->mModIndex; }
|
||||
if (outModFileIndex) { *outModFileIndex = aGfxData->mModFileIndex; }
|
||||
if (outToken) {
|
||||
if (!aTokenIndex || aTokenIndex > aGfxData->mLuaTokenList.Count()) {
|
||||
return false;
|
||||
}
|
||||
*outToken = aGfxData->mLuaTokenList[aTokenIndex - 1].begin(); // token index is 1-indexed
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DynOS_Actor_GetModIndexAndToken(const GraphNode *aGraphNode, u32 aTokenIndex, s32 *outModIndex, s32 *outModFileIndex, const char **outToken) {
|
||||
ActorGfx *_ActorGfx = DynOS_Actor_GetActorGfx(aGraphNode);
|
||||
if (_ActorGfx) {
|
||||
GfxData *_GfxData = _ActorGfx->mGfxData;
|
||||
if (_GfxData) {
|
||||
if (outModIndex) {
|
||||
*outModIndex = _GfxData->mModIndex;
|
||||
}
|
||||
if (outModFileIndex) {
|
||||
*outModFileIndex = _GfxData->mModFileIndex;
|
||||
}
|
||||
if (outToken) {
|
||||
if (!aTokenIndex || aTokenIndex > _GfxData->mLuaTokenList.Count()) {
|
||||
return false;
|
||||
}
|
||||
*outToken = _GfxData->mLuaTokenList[aTokenIndex - 1].begin(); // token index is 1-indexed
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return DynOS_Actor_GetModIndexAndTokenFromGfxData(_ActorGfx->mGfxData, aTokenIndex, outModIndex, outModFileIndex, outToken);
|
||||
} else { // try the active level
|
||||
GfxData *_GfxData = DynOS_Lvl_GetActiveGfx();
|
||||
if (_GfxData) {
|
||||
if (outModIndex) {
|
||||
*outModIndex = _GfxData->mModIndex;
|
||||
}
|
||||
if (outModFileIndex) {
|
||||
*outModFileIndex = _GfxData->mModFileIndex;
|
||||
}
|
||||
if (outToken) {
|
||||
if (!aTokenIndex || aTokenIndex > _GfxData->mLuaTokenList.Count()) {
|
||||
return false;
|
||||
}
|
||||
*outToken = _GfxData->mLuaTokenList[aTokenIndex - 1].begin(); // token index is 1-indexed
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return DynOS_Actor_GetModIndexAndTokenFromGfxData(DynOS_Lvl_GetActiveGfx(), aTokenIndex, outModIndex, outModFileIndex, outToken);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ActorGfx* DynOS_Actor_GetActorGfx(const GraphNode* aGraphNode) {
|
||||
|
|
@ -214,13 +208,15 @@ void DynOS_Actor_Override(struct Object* obj, void** aSharedChild) {
|
|||
if (it == _ValidActors.end()) { return; }
|
||||
|
||||
// Check if the behavior uses a character specific model
|
||||
if (obj && (obj->behavior == bhvMario ||
|
||||
obj->behavior == smlua_override_behavior(bhvNormalCap) ||
|
||||
obj->behavior == smlua_override_behavior(bhvWingCap) ||
|
||||
obj->behavior == smlua_override_behavior(bhvMetalCap) ||
|
||||
obj->behavior == smlua_override_behavior(bhvVanishCap))) {
|
||||
if (obj && (
|
||||
obj->behavior == smlua_override_behavior(bhvMario) ||
|
||||
obj->behavior == smlua_override_behavior(bhvNormalCap) ||
|
||||
obj->behavior == smlua_override_behavior(bhvWingCap) ||
|
||||
obj->behavior == smlua_override_behavior(bhvMetalCap) ||
|
||||
obj->behavior == smlua_override_behavior(bhvVanishCap)
|
||||
)) {
|
||||
struct NetworkPlayer* np = network_player_from_global_index(obj->globalPlayerIndex);
|
||||
if (np && np->localIndex > 0 && configDynosLocalPlayerModelOnly && it->second.mPackIndex != MOD_PACK_INDEX) {
|
||||
if (np != NULL && np->localIndex > 0 && configDynosLocalPlayerModelOnly && it->second.mPackIndex != MOD_PACK_INDEX) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -228,10 +224,12 @@ void DynOS_Actor_Override(struct Object* obj, void** aSharedChild) {
|
|||
*aSharedChild = (void*)it->second.mGraphNode;
|
||||
}
|
||||
|
||||
// Used for both DynOS packs and actors from mods, only overrides existing actors
|
||||
void DynOS_Actor_Override_All(void) {
|
||||
if (!gObjectLists) { return; }
|
||||
|
||||
// Loop through all object lists
|
||||
for (s32 list : { OBJ_LIST_PLAYER, OBJ_LIST_DESTRUCTIVE, OBJ_LIST_GENACTOR, OBJ_LIST_PUSHABLE, OBJ_LIST_LEVEL, OBJ_LIST_DEFAULT, OBJ_LIST_SURFACE, OBJ_LIST_POLELIKE, OBJ_LIST_UNIMPORTANT }) {
|
||||
for (ObjectList list : sObjectListsToOverride) {
|
||||
struct Object *_Head = (struct Object *) &gObjectLists[list];
|
||||
for (struct Object *_Object = (struct Object *) _Head->header.next; _Object != _Head; _Object = (struct Object *) _Object->header.next) {
|
||||
if (_Object->activeFlags && _Object->header.gfx.sharedChild != NULL) {
|
||||
|
|
|
|||
|
|
@ -45,8 +45,16 @@ static s32 RetrieveCurrentAnimationIndex(struct Object *aObject) {
|
|||
void DynOS_Anim_Swap(void *aPtr) {
|
||||
if (!aPtr) { return; }
|
||||
|
||||
static Animation *pDefaultAnimation = NULL;
|
||||
static Animation sGfxDataAnimation;
|
||||
// Must support nested calls (held objects render inside other object render)
|
||||
// and interleaving objects without corrupting swap state.
|
||||
struct AnimSwapFrame {
|
||||
struct Object *obj;
|
||||
Animation *defaultAnim;
|
||||
Animation gfxDataAnim;
|
||||
};
|
||||
|
||||
static AnimSwapFrame sAnimSwapFrames[32] = { 0 };
|
||||
static s32 sCurrAnimSwapIndex = 0;
|
||||
|
||||
// Does the object have a model?
|
||||
struct Object *_Object = (struct Object *) aPtr;
|
||||
|
|
@ -54,9 +62,20 @@ void DynOS_Anim_Swap(void *aPtr) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Determine if this call is the "swap" phase or "restore" phase.
|
||||
// The engine calls DynOS_Anim_Swap twice around geo_set_animation_globals.
|
||||
const bool restoring = (sCurrAnimSwapIndex > 0 && sAnimSwapFrames[sCurrAnimSwapIndex - 1].obj == _Object);
|
||||
|
||||
// Swap the current animation with the one from the Gfx data
|
||||
if (!pDefaultAnimation) {
|
||||
pDefaultAnimation = _Object->header.gfx.animInfo.curAnim;
|
||||
if (!restoring) {
|
||||
if (sCurrAnimSwapIndex >= (s32) ARRAY_COUNT(sAnimSwapFrames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AnimSwapFrame *frame = &sAnimSwapFrames[sCurrAnimSwapIndex];
|
||||
frame->obj = _Object;
|
||||
frame->defaultAnim = _Object->header.gfx.animInfo.curAnim;
|
||||
sCurrAnimSwapIndex++;
|
||||
|
||||
// ActorGfx data
|
||||
ActorGfx* _ActorGfx = DynOS_Actor_GetActorGfx(_Object->header.gfx.sharedChild);
|
||||
|
|
@ -100,23 +119,26 @@ void DynOS_Anim_Swap(void *aPtr) {
|
|||
// Animation data
|
||||
const AnimData *_AnimData = (const AnimData *) _GfxData->mAnimationTable[_AnimIndex].second;
|
||||
if (_AnimData) {
|
||||
sGfxDataAnimation.flags = _AnimData->mFlags;
|
||||
sGfxDataAnimation.animYTransDivisor = _AnimData->mUnk02;
|
||||
sGfxDataAnimation.startFrame = _AnimData->mUnk04;
|
||||
sGfxDataAnimation.loopStart = _AnimData->mUnk06;
|
||||
sGfxDataAnimation.loopEnd = _AnimData->mUnk08;
|
||||
sGfxDataAnimation.unusedBoneCount = _AnimData->mUnk0A.second;
|
||||
sGfxDataAnimation.values = (u16*)_AnimData->mValues.second.begin();
|
||||
sGfxDataAnimation.index = (u16*)_AnimData->mIndex.second.begin();
|
||||
sGfxDataAnimation.valuesLength = _AnimData->mValues.second.Count();
|
||||
sGfxDataAnimation.indexLength = _AnimData->mIndex.second.Count();
|
||||
sGfxDataAnimation.length = _AnimData->mLength;
|
||||
_Object->header.gfx.animInfo.curAnim = &sGfxDataAnimation;
|
||||
frame->gfxDataAnim.flags = _AnimData->mFlags;
|
||||
frame->gfxDataAnim.animYTransDivisor = _AnimData->mUnk02;
|
||||
frame->gfxDataAnim.startFrame = _AnimData->mUnk04;
|
||||
frame->gfxDataAnim.loopStart = _AnimData->mUnk06;
|
||||
frame->gfxDataAnim.loopEnd = _AnimData->mUnk08;
|
||||
frame->gfxDataAnim.unusedBoneCount = _AnimData->mUnk0A.second;
|
||||
frame->gfxDataAnim.values = (u16*) _AnimData->mValues.second.begin();
|
||||
frame->gfxDataAnim.index = (u16*) _AnimData->mIndex.second.begin();
|
||||
frame->gfxDataAnim.valuesLength = _AnimData->mValues.second.Count();
|
||||
frame->gfxDataAnim.indexLength = _AnimData->mIndex.second.Count();
|
||||
frame->gfxDataAnim.length = _AnimData->mLength;
|
||||
_Object->header.gfx.animInfo.curAnim = &frame->gfxDataAnim;
|
||||
}
|
||||
|
||||
// Restore the default animation
|
||||
} else {
|
||||
_Object->header.gfx.animInfo.curAnim = pDefaultAnimation;
|
||||
pDefaultAnimation = NULL;
|
||||
sCurrAnimSwapIndex--;
|
||||
AnimSwapFrame *frame = &sAnimSwapFrames[sCurrAnimSwapIndex];
|
||||
_Object->header.gfx.animInfo.curAnim = frame->defaultAnim;
|
||||
frame->obj = NULL;
|
||||
frame->defaultAnim = NULL;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3590,7 +3590,9 @@
|
|||
| HOOK_ON_FIND_POISON_GAS_LEVEL | 64 |
|
||||
| HOOK_ON_FIND_SURFACE_ON_RAY | 65 |
|
||||
| HOOK_ON_DYNOS_PACK_TOGGLED | 66 |
|
||||
| HOOK_MAX | 67 |
|
||||
| HOOK_BEFORE_PLAY_MODE_UPDATE | 67 |
|
||||
| HOOK_ON_PLAY_MODE_UPDATE | 68 |
|
||||
| HOOK_MAX | 69 |
|
||||
- MAX_HOOKED_BEHAVIORS
|
||||
|
||||
[:arrow_up_small:](#)
|
||||
|
|
@ -4751,6 +4753,7 @@
|
|||
- ANIM_FLAG_6
|
||||
- ANIM_FLAG_7
|
||||
- ANIM_FLAG_BONE_TRANS
|
||||
- ANIM_FLAG_BONE_SCALE
|
||||
- OBJECT_MAX_BHV_STACK
|
||||
- OBJECT_NUM_REGULAR_FIELDS
|
||||
- OBJECT_NUM_CUSTOM_FIELDS
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
|
|||
| HOOK_ON_GEO_PROCESS | Called when a GeoLayout is processed **Note:** You must set the `hookProcess` field of the graph node to a non-zero value | [GraphNode](../structs.md#GraphNode) graphNode, `integer` matStackIndex |
|
||||
| HOOK_BEFORE_GEO_PROCESS | Called before a GeoLayout is processed **Note:** You must set the `hookProcess` field of the graph node to a non-zero value | [GraphNode](../structs.md#GraphNode) graphNode, `integer` matStackIndex |
|
||||
| HOOK_ON_GEO_PROCESS_CHILDREN | Called when the children of a GeoLayout node is processed **Note:** You must set the `hookProcess` field of the parent graph node to a non-zero value | [GraphNode](../structs.md#GraphNode) graphNode, `integer` matStackIndex |
|
||||
| HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS | Called before running Mario's geometry input logic, return `false` to not run it. | [MarioState](../structs.md) m |
|
||||
| HOOK_MARIO_OVERRIDE_GEOMETRY_INPUTS | Called before running Mario's geometry input logic, return `false` to not run it. | [MarioState](../structs.md) m |
|
||||
| HOOK_ON_INTERACTIONS | Called when the Mario interactions are processed | [MarioState](../structs.md#MarioState) mario |
|
||||
| HOOK_ALLOW_FORCE_WATER_ACTION | Called when executing a non-water action while under the water's surface, or vice versa. Return `false` to prevent the player from being forced out of the action at the water's surface | [MarioState](../structs.md#MarioState) mario, `boolean` isInWaterAction |
|
||||
| HOOK_BEFORE_WARP | Called before the local player warps. Return a table with `destLevel`, `destArea`, `destWarpNode`, to override the warp | `integer` destLevel, `integer` destArea, `integer` destWarpNode, `integer` arg |
|
||||
|
|
@ -158,6 +158,8 @@ The lua functions sent to `hook_event()` will be automatically called by SM64 wh
|
|||
| HOOK_ON_FIND_POISON_GAS_LEVEL | Called after poison gas level detection completes. Return a number to override the gas level | `number` x, `number` z, `number` gasLevel |
|
||||
| HOOK_ON_FIND_SURFACE_ON_RAY | Called after ray-surface intersection completes. Return `surface` to override the hit surface, or `surface, hitPos` to override both | `Vec3f` orig, `Vec3f` dir, [Surface](../structs.md#Surface) hitSurface, `Vec3f` hitPos |
|
||||
| HOOK_ON_DYNOS_PACK_TOGGLED | Called after a DynOS pack is toggled | `string` dynosPackName, `boolean` enabled |
|
||||
| HOOK_BEFORE_PLAY_MODE_UPDATE | Called before the play mode is ran. Return a number to override the play mode to be ran. | `number` playMode |
|
||||
| HOOK_ON_PLAY_MODE_UPDATE | Called after the play mode is ran. Return a number to override the change level. | `number` playMode |
|
||||
|
||||
### Parameters
|
||||
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ struct VblankHandler
|
|||
#define ANIM_FLAG_6 (1 << 6) // 0x40
|
||||
#define ANIM_FLAG_7 (1 << 7) // 0x80
|
||||
#define ANIM_FLAG_BONE_TRANS (1 << 8)
|
||||
#define ANIM_FLAG_BONE_SCALE (1 << 9)
|
||||
|
||||
struct Animation {
|
||||
// TODO: Optimize this later if possible.
|
||||
|
|
|
|||
|
|
@ -448,13 +448,15 @@ void play_transition_after_delay(s16 transType, s16 time, u8 red, u8 green, u8 b
|
|||
|
||||
void render_game(void) {
|
||||
dynos_update_gfx();
|
||||
if (gCurrentArea != NULL && !gWarpTransition.pauseRendering) {
|
||||
geo_process_root(gCurrentArea->root, gViewportOverride, gViewportClip, gFBSetColor);
|
||||
if (gCurrentArea != NULL) {
|
||||
if (!gWarpTransition.pauseRendering) {
|
||||
geo_process_root(gCurrentArea->root, gViewportOverride, gViewportClip, gFBSetColor);
|
||||
|
||||
gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gViewportFullscreen));
|
||||
gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gViewportFullscreen));
|
||||
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT - BORDER_HEIGHT);
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT - BORDER_HEIGHT);
|
||||
}
|
||||
|
||||
if (!gDjuiDisabled) {
|
||||
djui_reset_hud_params();
|
||||
|
|
@ -466,41 +468,45 @@ void render_game(void) {
|
|||
smlua_call_event_hooks(HOOK_ON_HUD_RENDER_BEHIND, djui_reset_hud_params);
|
||||
djui_gfx_displaylist_end();
|
||||
}
|
||||
render_hud();
|
||||
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
render_text_labels();
|
||||
do_cutscene_handler();
|
||||
if (!gDjuiInMainMenu) {
|
||||
print_displaying_credits_entry();
|
||||
}
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT - BORDER_HEIGHT);
|
||||
gPauseScreenMode = render_menus_and_dialogs();
|
||||
if (!gWarpTransition.pauseRendering) {
|
||||
render_hud();
|
||||
|
||||
if (gPauseScreenMode != 0) {
|
||||
gSaveOptSelectIndex = gPauseScreenMode;
|
||||
}
|
||||
|
||||
if (gViewportClip != NULL) {
|
||||
make_viewport_clip_rect(gViewportClip);
|
||||
} else
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
render_text_labels();
|
||||
do_cutscene_handler();
|
||||
if (!gDjuiInMainMenu) {
|
||||
print_displaying_credits_entry();
|
||||
}
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT - BORDER_HEIGHT);
|
||||
gPauseScreenMode = render_menus_and_dialogs();
|
||||
|
||||
if (gWarpTransition.isActive) {
|
||||
if (gWarpTransDelay == 0) {
|
||||
gWarpTransition.isActive = !render_screen_transition(0, gWarpTransition.type, gWarpTransition.time,
|
||||
&gWarpTransition.data);
|
||||
if (!gWarpTransition.isActive) {
|
||||
if (gWarpTransition.type & 1) {
|
||||
gWarpTransition.pauseRendering = TRUE;
|
||||
} else {
|
||||
set_warp_transition_rgb(0, 0, 0);
|
||||
}
|
||||
}
|
||||
if (gPauseScreenMode != 0) {
|
||||
gSaveOptSelectIndex = gPauseScreenMode;
|
||||
}
|
||||
|
||||
if (gViewportClip != NULL) {
|
||||
make_viewport_clip_rect(gViewportClip);
|
||||
} else {
|
||||
gWarpTransDelay--;
|
||||
gDPSetScissor(gDisplayListHead++, G_SC_NON_INTERLACE, 0, BORDER_HEIGHT, SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT - BORDER_HEIGHT);
|
||||
}
|
||||
|
||||
if (gWarpTransition.isActive) {
|
||||
if (gWarpTransDelay == 0) {
|
||||
gWarpTransition.isActive = !render_screen_transition(0, gWarpTransition.type, gWarpTransition.time,
|
||||
&gWarpTransition.data);
|
||||
if (!gWarpTransition.isActive) {
|
||||
if (gWarpTransition.type & 1) {
|
||||
gWarpTransition.pauseRendering = TRUE;
|
||||
} else {
|
||||
set_warp_transition_rgb(0, 0, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gWarpTransDelay--;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ void bhv_bbh_tilting_trap_platform_loop(void) {
|
|||
u8 playersTouched = 0;
|
||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj == NULL) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
x += gMarioStates[i].marioObj->oPosX;
|
||||
y += gMarioStates[i].marioObj->oPosY;
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ void controllable_platform_tilt_from_mario(void) {
|
|||
f32 z = 0;
|
||||
|
||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (gMarioStates[i].marioObj == NULL) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o || gMarioStates[i].marioObj->platform == cur_obj_nearest_object_with_behavior(bhvControllablePlatformSub)) {
|
||||
x += gMarioStates[i].pos[0];
|
||||
z += gMarioStates[i].pos[2];
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ void dorrie_act_raise_head(void) {
|
|||
|
||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj == NULL) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform != o) { continue; }
|
||||
s32 dist = dist_between_objects(o, gMarioStates[0].marioObj);
|
||||
if (dist <= 780.0f) { continue; }
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ void floating_platform_act_0(void) {
|
|||
u8 playersTouched = 0;
|
||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj == NULL) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
x += gMarioStates[i].marioObj->oPosX;
|
||||
z += gMarioStates[i].marioObj->oPosZ;
|
||||
|
|
|
|||
|
|
@ -291,6 +291,7 @@ static void platform_on_track_rock_ski_lift(void) {
|
|||
struct Object* player = NULL;
|
||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj == NULL) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform != o) { continue; }
|
||||
player = gMarioStates[i].marioObj;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ void bhv_seesaw_platform_update(void) {
|
|||
u8 playersTouched = 0;
|
||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj == NULL) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform == o) {
|
||||
x += gMarioStates[i].marioObj->oPosX;
|
||||
y += gMarioStates[i].marioObj->oPosY;
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ void bhv_tilting_inverted_pyramid_loop(void) {
|
|||
u8 playersTouched = 0;
|
||||
for (s32 i = 0; i < MAX_PLAYERS; i++) {
|
||||
if (!is_player_active(&gMarioStates[i])) { continue; }
|
||||
if (gMarioStates[i].marioObj == NULL) { continue; }
|
||||
if (gMarioStates[i].marioObj->platform != o) { continue; }
|
||||
x += gMarioStates[i].marioObj->oPosX;
|
||||
y += gMarioStates[i].marioObj->oPosY;
|
||||
|
|
@ -135,7 +136,7 @@ void bhv_tilting_inverted_pyramid_loop(void) {
|
|||
o->oTiltingPyramidMarioOnPlatform = FALSE;
|
||||
}
|
||||
|
||||
// Approach the normals by 0.01f towards the new goal, then create a transform matrix and orient the object.
|
||||
// Approach the normals by 0.01f towards the new goal, then create a transform matrix and orient the object.
|
||||
// Outside of the other conditionals since it needs to tilt regardless of whether Mario is on.
|
||||
o->oTiltingPyramidNormalX = approach_by_increment(dx, o->oTiltingPyramidNormalX, 0.01f);
|
||||
o->oTiltingPyramidNormalY = approach_by_increment(dy, o->oTiltingPyramidNormalY, 0.01f);
|
||||
|
|
|
|||
|
|
@ -1503,6 +1503,44 @@ UNUSED static s32 play_mode_unused(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
s32 update_current_play_mode() {
|
||||
s32 changeLevel = 0;
|
||||
|
||||
s16 hookPlaymode = sCurrPlayMode;
|
||||
if (smlua_call_event_hooks(HOOK_BEFORE_PLAY_MODE_UPDATE, sCurrPlayMode, &hookPlaymode)) {
|
||||
sCurrPlayMode = hookPlaymode;
|
||||
}
|
||||
|
||||
switch (sCurrPlayMode) {
|
||||
case PLAY_MODE_NORMAL:
|
||||
changeLevel = play_mode_normal();
|
||||
break;
|
||||
case PLAY_MODE_PAUSED:
|
||||
if (!network_check_singleplayer_pause()) {
|
||||
changeLevel = play_mode_normal();
|
||||
}
|
||||
|
||||
if (sCurrPlayMode == PLAY_MODE_PAUSED) {
|
||||
changeLevel = play_mode_paused();
|
||||
}
|
||||
break;
|
||||
case PLAY_MODE_CHANGE_AREA:
|
||||
changeLevel = play_mode_change_area();
|
||||
break;
|
||||
case PLAY_MODE_CHANGE_LEVEL:
|
||||
changeLevel = play_mode_change_level();
|
||||
break;
|
||||
case PLAY_MODE_FRAME_ADVANCE:
|
||||
changeLevel = play_mode_frame_advance();
|
||||
break;
|
||||
}
|
||||
s32 hookChangeLevel = changeLevel;
|
||||
if (smlua_call_event_hooks(HOOK_ON_PLAY_MODE_UPDATE, sCurrPlayMode, &hookChangeLevel)) {
|
||||
changeLevel = hookChangeLevel;
|
||||
}
|
||||
return changeLevel;
|
||||
}
|
||||
|
||||
void update_menu_level(void) {
|
||||
// figure out level
|
||||
s32 curLevel = 0;
|
||||
|
|
@ -1730,29 +1768,7 @@ s32 update_level(void) {
|
|||
gCurrentArea->localAreaTimer++;
|
||||
}
|
||||
|
||||
switch (sCurrPlayMode) {
|
||||
case PLAY_MODE_NORMAL:
|
||||
changeLevel = play_mode_normal();
|
||||
break;
|
||||
case PLAY_MODE_PAUSED:
|
||||
if (!network_check_singleplayer_pause()) {
|
||||
changeLevel = play_mode_normal();
|
||||
}
|
||||
|
||||
if (sCurrPlayMode == PLAY_MODE_PAUSED) {
|
||||
changeLevel = play_mode_paused();
|
||||
}
|
||||
break;
|
||||
case PLAY_MODE_CHANGE_AREA:
|
||||
changeLevel = play_mode_change_area();
|
||||
break;
|
||||
case PLAY_MODE_CHANGE_LEVEL:
|
||||
changeLevel = play_mode_change_level();
|
||||
break;
|
||||
case PLAY_MODE_FRAME_ADVANCE:
|
||||
changeLevel = play_mode_frame_advance();
|
||||
break;
|
||||
}
|
||||
changeLevel = update_current_play_mode();
|
||||
|
||||
if (changeLevel) {
|
||||
reset_volume();
|
||||
|
|
|
|||
|
|
@ -383,7 +383,6 @@ void patch_mtx_interpolated(f32 delta) {
|
|||
/**
|
||||
* Graph node interpolation
|
||||
*/
|
||||
|
||||
static void *sGraphNodeInterpDataMap = NULL;
|
||||
|
||||
struct GraphNodeInterpData *geo_get_interp_data(void *node, struct GraphNodeObject *obj) {
|
||||
|
|
@ -1059,7 +1058,7 @@ static void geo_process_background(struct GraphNodeBackground *node) {
|
|||
}
|
||||
}
|
||||
|
||||
static void anim_process(Vec3f translation, Vec3s rotation, u8 *animType, s16 animFrame, u16 **animAttribute) {
|
||||
static void anim_process(Vec3f translation, Vec3s rotation, Vec3f scale, u8 *animType, s16 animFrame, u16 **animAttribute) {
|
||||
if (*animType == ANIM_TYPE_TRANSLATION) {
|
||||
translation[0] += retrieve_animation_value(gCurAnim, animFrame, animAttribute) * gCurAnimTranslationMultiplier;
|
||||
translation[1] += retrieve_animation_value(gCurAnim, animFrame, animAttribute) * gCurAnimTranslationMultiplier;
|
||||
|
|
@ -1090,6 +1089,19 @@ static void anim_process(Vec3f translation, Vec3s rotation, u8 *animType, s16 an
|
|||
rotation[0] += retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
rotation[1] += retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
rotation[2] += retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
|
||||
if (gCurAnim->flags & ANIM_FLAG_BONE_SCALE) {
|
||||
s16 scaleX = retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
s16 scaleY = retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
s16 scaleZ = retrieve_animation_value(gCurAnim, animFrame, animAttribute);
|
||||
|
||||
if (scale != NULL) {
|
||||
scale[0] *= ((f32) scaleX) / 256.0f;
|
||||
scale[1] *= ((f32) scaleY) / 256.0f;
|
||||
scale[2] *= ((f32) scaleZ) / 256.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (gCurAnim->flags & ANIM_FLAG_BONE_TRANS) {
|
||||
*animType = ANIM_TYPE_TRANSLATION;
|
||||
}
|
||||
|
|
@ -1108,6 +1120,7 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
|
|||
Mat4 matrix;
|
||||
Vec3s rotation;
|
||||
Vec3f translation;
|
||||
Vec3f scale;
|
||||
|
||||
// Sanity check our stack index, If we above or equal to our stack size. Return to prevent OOB\.
|
||||
if ((gMatStackIndex + 1) >= MATRIX_STACK_SIZE) { LOG_ERROR("Preventing attempt to exceed the maximum size %i for our matrix stack with size of %i.", MATRIX_STACK_SIZE - 1, gMatStackIndex); return; }
|
||||
|
|
@ -1118,8 +1131,10 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
|
|||
// current frame
|
||||
vec3s_copy(rotation, gVec3sZero);
|
||||
vec3s_to_vec3f(translation, node->translation);
|
||||
anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||
vec3f_copy(scale, gVec3fOne);
|
||||
anim_process(translation, rotation, scale, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||
mtxf_scale_vec3f(matrix, matrix, scale);
|
||||
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
|
||||
|
||||
// previous frame
|
||||
|
|
@ -1130,8 +1145,10 @@ static void geo_process_animated_part(struct GraphNodeAnimatedPart *node) {
|
|||
node->translation
|
||||
);
|
||||
vec3s_copy(rotation, gVec3sZero);
|
||||
anim_process(translation, rotation, &animType, gPrevAnimFrame, &animAttribute);
|
||||
vec3f_copy(scale, gVec3fOne);
|
||||
anim_process(translation, rotation, scale, &animType, gPrevAnimFrame, &animAttribute);
|
||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||
mtxf_scale_vec3f(matrix, matrix, scale);
|
||||
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
|
||||
);
|
||||
|
||||
|
|
@ -1420,8 +1437,12 @@ static s32 obj_is_in_view(struct GraphNodeObject *node, Mat4 matrix) {
|
|||
|
||||
static void geo_sanitize_object_gfx(void) {
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_OPAQUE);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_OPAQUE_DECAL);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_OPAQUE_INTER);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_ALPHA);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_TRANSPARENT);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_TRANSPARENT_DECAL);
|
||||
geo_append_display_list(obj_sanitize_gfx, LAYER_TRANSPARENT_INTER);
|
||||
}
|
||||
|
||||
static struct MarioBodyState *get_mario_body_state_from_mario_object(struct Object *marioObj) {
|
||||
|
|
@ -1688,6 +1709,7 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
|
|||
node->fnNode.func(GEO_CONTEXT_HELD_OBJ, &node->fnNode.node, (struct DynamicPool *) gMatStack[gMatStackIndex + 1]);
|
||||
}
|
||||
|
||||
s32 savedMatStackIndex = gMatStackIndex;
|
||||
// Increment the matrix stack, If we fail to do so. Just return.
|
||||
if (!increment_mat_stack()) { return; }
|
||||
|
||||
|
|
@ -1708,7 +1730,13 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
|
|||
}
|
||||
|
||||
geo_sanitize_object_gfx();
|
||||
// While rendering the held object's geo tree, ensure "current object" globals
|
||||
// refer to the held object, otherwise Lua geo callbacks can accidentally
|
||||
// mutate the holder's render state (e.g. make Wario limbs disappear).
|
||||
struct GraphNodeObject *savedCurGraphNodeObject = gCurGraphNodeObject;
|
||||
gCurGraphNodeObject = &node->objNode->header.gfx;
|
||||
geo_process_node_and_siblings(node->objNode->header.gfx.sharedChild);
|
||||
gCurGraphNodeObject = savedCurGraphNodeObject;
|
||||
gCurGraphNodeHeldObject = NULL;
|
||||
gCurAnimType = gGeoTempState.type;
|
||||
gCurAnimEnabled = gGeoTempState.enabled;
|
||||
|
|
@ -1717,7 +1745,13 @@ void geo_process_held_object(struct GraphNodeHeldObject *node) {
|
|||
gCurrAnimAttribute = gGeoTempState.attribute;
|
||||
gCurAnim = gGeoTempState.anim;
|
||||
gPrevAnimFrame = gGeoTempState.prevFrame;
|
||||
gMatStackIndex--;
|
||||
// Force-restore matrix stack index to avoid any imbalance caused by
|
||||
// held object geo trees (including Lua geo callbacks).
|
||||
gMatStackIndex = savedMatStackIndex;
|
||||
|
||||
// Reset any render-state changes performed by the held object's geo tree
|
||||
// so the holder's remaining body parts render correctly.
|
||||
geo_sanitize_object_gfx();
|
||||
}
|
||||
|
||||
if (node->fnNode.node.children != NULL) {
|
||||
|
|
@ -1748,7 +1782,7 @@ static void geo_process_bone(struct GraphNodeBone *node) {
|
|||
vec3s_copy(rotation, node->rotation);
|
||||
vec3s_to_vec3f(translation, node->translation);
|
||||
vec3f_copy(scale, node->scale);
|
||||
anim_process(translation, rotation, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||
anim_process(translation, rotation, scale, &gCurAnimType, gCurrAnimFrame, &gCurrAnimAttribute);
|
||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||
mtxf_scale_vec3f(matrix, matrix, scale);
|
||||
mtxf_mul(gMatStack[gMatStackIndex + 1], matrix, gMatStack[gMatStackIndex]);
|
||||
|
|
@ -1764,7 +1798,7 @@ static void geo_process_bone(struct GraphNodeBone *node) {
|
|||
vec3s_to_vec3f(translation, node->translation);
|
||||
vec3f_copy(scale, node->scale);
|
||||
}
|
||||
anim_process(translation, rotation, &animType, gPrevAnimFrame, &animAttribute);
|
||||
anim_process(translation, rotation, scale, &animType, gPrevAnimFrame, &animAttribute);
|
||||
mtxf_rotate_xyz_and_translate(matrix, translation, rotation);
|
||||
mtxf_scale_vec3f(matrix, matrix, scale);
|
||||
mtxf_mul(gMatStackPrev[gMatStackIndex + 1], matrix, gMatStackPrev[gMatStackIndex]);
|
||||
|
|
|
|||
|
|
@ -3575,7 +3575,9 @@ char gSmluaConstants[] = ""
|
|||
"HOOK_ON_FIND_POISON_GAS_LEVEL=64\n"
|
||||
"HOOK_ON_FIND_SURFACE_ON_RAY=65\n"
|
||||
"HOOK_ON_DYNOS_PACK_TOGGLED=66\n"
|
||||
"HOOK_MAX=67\n"
|
||||
"HOOK_BEFORE_PLAY_MODE_UPDATE=67\n"
|
||||
"HOOK_ON_PLAY_MODE_UPDATE=68\n"
|
||||
"HOOK_MAX=69\n"
|
||||
"MAX_HOOKED_BEHAVIORS=1024\n"
|
||||
"HUD_DISPLAY_LIVES=0\n"
|
||||
"HUD_DISPLAY_COINS=1\n"
|
||||
|
|
@ -4675,6 +4677,7 @@ char gSmluaConstants[] = ""
|
|||
"ANIM_FLAG_6=(1 << 6)\n"
|
||||
"ANIM_FLAG_7=(1 << 7)\n"
|
||||
"ANIM_FLAG_BONE_TRANS=(1 << 8)\n"
|
||||
"ANIM_FLAG_BONE_SCALE=(1 << 9)\n"
|
||||
"OBJECT_MAX_BHV_STACK=16\n"
|
||||
"OBJECT_NUM_REGULAR_FIELDS=0x50\n"
|
||||
"OBJECT_NUM_CUSTOM_FIELDS=0x40\n"
|
||||
|
|
|
|||
|
|
@ -65,3 +65,5 @@ SMLUA_EVENT_HOOK(HOOK_ON_FIND_WATER_LEVEL, _, f32 x, f32 z, f32 *waterLevel) //
|
|||
SMLUA_EVENT_HOOK(HOOK_ON_FIND_POISON_GAS_LEVEL, _, f32 x, f32 z, f32 *gasLevel) // Manually defined hook
|
||||
SMLUA_EVENT_HOOK(HOOK_ON_FIND_SURFACE_ON_RAY, _, Vec3f orig, Vec3f dir, struct Surface **hit_surface, Vec3f hit_pos) // Manually defined hook
|
||||
SMLUA_EVENT_HOOK(HOOK_ON_DYNOS_PACK_TOGGLED, HOOK_RETURN_NEVER, const char *dynosPackName, bool enabled)
|
||||
SMLUA_EVENT_HOOK(HOOK_BEFORE_PLAY_MODE_UPDATE, HOOK_RETURN_NEVER, s16 playmode, OUTPUT s16 *overridePlaymode)
|
||||
SMLUA_EVENT_HOOK(HOOK_ON_PLAY_MODE_UPDATE, HOOK_RETURN_NEVER, s16 playmode, OUTPUT s32 *changeLevel)
|
||||
|
|
@ -1893,3 +1893,67 @@ bool smlua_call_event_hooks_HOOK_ON_DYNOS_PACK_TOGGLED(const char *dynosPackName
|
|||
}
|
||||
return hookResult;
|
||||
}
|
||||
|
||||
bool smlua_call_event_hooks_HOOK_BEFORE_PLAY_MODE_UPDATE(s16 playmode, s16 *overridePlaymode) {
|
||||
lua_State *L = gLuaState;
|
||||
if (L == NULL) { return false; }
|
||||
bool hookResult = false;
|
||||
|
||||
struct LuaHookedEvent *hook = &sHookedEvents[HOOK_BEFORE_PLAY_MODE_UPDATE];
|
||||
for (int i = 0; i < hook->count; i++) {
|
||||
s32 prevTop = lua_gettop(L);
|
||||
|
||||
// push the callback onto the stack
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
|
||||
|
||||
// push playmode
|
||||
lua_pushinteger(L, playmode);
|
||||
|
||||
// call the callback
|
||||
if (0 != smlua_call_hook(L, 1, 1, 0, hook->mod[i], hook->modFile[i])) {
|
||||
LOG_LUA("Failed to call the callback for hook %s - '%s/%s'", sLuaHookedEventTypeName[HOOK_BEFORE_PLAY_MODE_UPDATE], hook->mod[i]->relativePath, hook->modFile[i]->relativePath);
|
||||
continue;
|
||||
}
|
||||
hookResult = true;
|
||||
|
||||
// return overridePlaymode
|
||||
if (lua_type(L, -1) == LUA_TNUMBER) {
|
||||
*overridePlaymode = smlua_to_integer(L, -1);
|
||||
}
|
||||
|
||||
lua_settop(L, prevTop);
|
||||
}
|
||||
return hookResult;
|
||||
}
|
||||
|
||||
bool smlua_call_event_hooks_HOOK_ON_PLAY_MODE_UPDATE(s16 playmode, s32 *changeLevel) {
|
||||
lua_State *L = gLuaState;
|
||||
if (L == NULL) { return false; }
|
||||
bool hookResult = false;
|
||||
|
||||
struct LuaHookedEvent *hook = &sHookedEvents[HOOK_ON_PLAY_MODE_UPDATE];
|
||||
for (int i = 0; i < hook->count; i++) {
|
||||
s32 prevTop = lua_gettop(L);
|
||||
|
||||
// push the callback onto the stack
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, hook->reference[i]);
|
||||
|
||||
// push playmode
|
||||
lua_pushinteger(L, playmode);
|
||||
|
||||
// call the callback
|
||||
if (0 != smlua_call_hook(L, 1, 1, 0, hook->mod[i], hook->modFile[i])) {
|
||||
LOG_LUA("Failed to call the callback for hook %s - '%s/%s'", sLuaHookedEventTypeName[HOOK_ON_PLAY_MODE_UPDATE], hook->mod[i]->relativePath, hook->modFile[i]->relativePath);
|
||||
continue;
|
||||
}
|
||||
hookResult = true;
|
||||
|
||||
// return changeLevel
|
||||
if (lua_type(L, -1) == LUA_TNUMBER) {
|
||||
*changeLevel = smlua_to_integer(L, -1);
|
||||
}
|
||||
|
||||
lua_settop(L, prevTop);
|
||||
}
|
||||
return hookResult;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ enum LuaHookedEventType {
|
|||
HOOK_ON_FIND_POISON_GAS_LEVEL,
|
||||
HOOK_ON_FIND_SURFACE_ON_RAY,
|
||||
HOOK_ON_DYNOS_PACK_TOGGLED,
|
||||
HOOK_BEFORE_PLAY_MODE_UPDATE,
|
||||
HOOK_ON_PLAY_MODE_UPDATE,
|
||||
HOOK_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue