sm64coopdx/data/dynos_mgr_anim.cpp
PeachyPeach 27db236b5d
Various bug fixes + Added is_game_paused() and more background music functions to lua (#93)
Bug: DynOS models with animations cannot swap animations if they are
     loaded via lua (smlua_model_util_get_id and
     obj_set_model_extended).
Fix: DynOS_Actor_GetActorGfx takes a graph node instead of a georef,
     and checks for DynosValidActors graph nodes if georef is NULL.

Bug: The game can crash when calling obj_set_model_extended inside a
     HOOK_ON_OBJECT_RENDER hook.
Fix: The crash happens in smlua_model_util_load_with_pool_and_cache_id
     due to pool being NULL. If the game can't allocate an
     AllocOnlyPool object, use DynOS to generate the graph node.

Bug: warp_to_level and similar functions don't trigger HOOK_ON_WARP.
Fix: Call HOOK_ON_WARP hooks in DynOS_Warp_UpdateWarp and
     DynOS_Warp_UpdateExit after level and mario initialization.

Bug: The game sometimes calls HOOK_ON_OBJECT_RENDER hooks for
     unintended objects.
Fix: Initialize hookRender field to 0 when creating an object.

Bug: Actions can't apply gfx offsets to characters that have an anim
     offset (Waluigi, Wario)
Fix: Add m->curAnimOffset to gfx.pos[1] instead of setting it to
     m->pos[1] + m->curAnimOffset, except during the jumbo star
     cutscene.
2022-05-14 14:28:25 -07:00

106 lines
3.5 KiB
C++

#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"
}
//
// Update animations
//
// Retrieve the current Mario's animation index
static s32 RetrieveCurrentMarioAnimationIndex(u32 aPlayerIndex) {
struct MarioAnimDmaRelatedThing *_AnimDmaTable = gMarioStates[aPlayerIndex].animation->animDmaTable;
for (s32 i = 0; i != (s32) _AnimDmaTable->count; ++i) {
void *_AnimAddr = _AnimDmaTable->srcAddr + _AnimDmaTable->anim[i].offset;
if (_AnimAddr == gMarioStates[aPlayerIndex].animation->currentAnimAddr) {
return i;
}
}
return -1;
}
// Retrieve the current animation index
// As we don't know the length of the table, let's hope that we'll always find the animation...
static s32 RetrieveCurrentAnimationIndex(struct Object *aObject) {
if (!aObject->oAnimations || !aObject->header.gfx.animInfo.curAnim) {
return -1;
}
for (s32 i = 0; aObject->oAnimations[i] != NULL; ++i) {
if (aObject->oAnimations[i] == aObject->header.gfx.animInfo.curAnim) {
return i;
}
}
return -1;
}
// Must be called twice, before and after geo_set_animation_globals
void DynOS_Anim_Swap(void *aPtr) {
static Animation *pDefaultAnimation = NULL;
static Animation sGfxDataAnimation;
// Does the object has a model?
struct Object *_Object = (struct Object *) aPtr;
if (!_Object->header.gfx.sharedChild) {
return;
}
// Swap the current animation with the one from the Gfx data
if (!pDefaultAnimation) {
pDefaultAnimation = _Object->header.gfx.animInfo.curAnim;
// ActorGfx data
ActorGfx* _ActorGfx = DynOS_Actor_GetActorGfx(_Object->header.gfx.sharedChild);
if (!_ActorGfx) {
return;
}
// GfxData
GfxData* _GfxData = _ActorGfx->mGfxData;
if (!_GfxData) {
return;
}
// Animation table
if (_GfxData->mAnimationTable.Empty()) {
return;
}
// Animation index
s32 _AnimIndex = -1;
for (u32 i = 0; i < MAX_PLAYERS; i++) {
if (gMarioStates[i].marioObj == NULL) { continue; }
if (_Object == gMarioStates[i].marioObj) {
_AnimIndex = RetrieveCurrentMarioAnimationIndex(i);
}
}
if (_AnimIndex == -1) {
_AnimIndex = RetrieveCurrentAnimationIndex(_Object);
}
if (_AnimIndex == -1) {
return;
}
// 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 = _AnimData->mValues.second.begin();
sGfxDataAnimation.index = _AnimData->mIndex.second.begin();
sGfxDataAnimation.length = _AnimData->mLength;
_Object->header.gfx.animInfo.curAnim = &sGfxDataAnimation;
}
// Restore the default animation
} else {
_Object->header.gfx.animInfo.curAnim = pDefaultAnimation;
pDefaultAnimation = NULL;
}
}