mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-22 20:15:17 +00:00
27db236b5d
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.
195 lines
6.2 KiB
C++
195 lines
6.2 KiB
C++
#include <map>
|
|
#include <algorithm>
|
|
#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"
|
|
}
|
|
|
|
// Static maps/arrays
|
|
static std::map<const void*, ActorGfx>& DynosValidActors() {
|
|
static std::map<const void*, ActorGfx> sDynosValidActors;
|
|
return sDynosValidActors;
|
|
}
|
|
|
|
static Array<Pair<const char*, void *>>& DynosCustomActors() {
|
|
static Array<Pair<const char*, void *>> sDynosCustomActors;
|
|
return sDynosCustomActors;
|
|
}
|
|
|
|
// TODO: the cleanup/refactor didn't really go as planned.
|
|
// clean up the actor management code more
|
|
|
|
void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) {
|
|
|
|
const void* georef = DynOS_Builtin_Actor_GetFromName(aActorName);
|
|
|
|
u16 actorLen = strlen(aActorName);
|
|
char* actorName = (char*)calloc(1, sizeof(char) * (actorLen + 1));
|
|
strcpy(actorName, aActorName);
|
|
|
|
GfxData *_GfxData = DynOS_Actor_LoadFromBinary(aFilename, actorName, aFilename, false);
|
|
if (!_GfxData) {
|
|
Print(" ERROR: Couldn't load Actor Binary \"%s\" from \"%s\"", actorName, aFilename.c_str());
|
|
free(actorName);
|
|
return;
|
|
}
|
|
|
|
void* geoLayout = (*(_GfxData->mGeoLayouts.end() - 1))->mData;
|
|
if (!geoLayout) {
|
|
Print(" ERROR: Couldn't load geo layout for \"%s\"", actorName);
|
|
free(actorName);
|
|
return;
|
|
}
|
|
|
|
// Alloc and init the actors gfx list
|
|
ActorGfx actorGfx = { };
|
|
actorGfx.mGfxData = _GfxData;
|
|
actorGfx.mGraphNode = (GraphNode *) DynOS_Geo_GetGraphNode(geoLayout, false);
|
|
actorGfx.mPackIndex = MOD_PACK_INDEX;
|
|
actorGfx.mGraphNode->georef = georef;
|
|
|
|
// Add to custom actors
|
|
if (georef == NULL) {
|
|
DynosCustomActors().Add({ actorName, geoLayout });
|
|
georef = geoLayout;
|
|
}
|
|
|
|
// Add to list
|
|
DynOS_Actor_Valid(georef, actorGfx);
|
|
}
|
|
|
|
const void *DynOS_Actor_GetLayoutFromName(const char *aActorName) {
|
|
if (aActorName == NULL) { return NULL; }
|
|
|
|
// check levels
|
|
auto& levelsArray = DynOS_Lvl_GetArray();
|
|
for (auto& lvl : levelsArray) {
|
|
for (auto& geo : lvl.second->mGeoLayouts) {
|
|
if (geo->mName == aActorName) {
|
|
return geo->mData;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check custom actors
|
|
for (auto& pair : DynosCustomActors()) {
|
|
if (!strcmp(aActorName, pair.first)) {
|
|
return pair.second;
|
|
}
|
|
}
|
|
|
|
// check loaded actors
|
|
for (auto& pair : DynosValidActors()) {
|
|
for (auto& geo : pair.second.mGfxData->mGeoLayouts) {
|
|
if (!strcmp(aActorName, geo->mName.begin())) {
|
|
return geo->mData;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check built in actors
|
|
for (s32 i = 0; i < DynOS_Builtin_Actor_GetCount(); ++i) {
|
|
auto name = DynOS_Builtin_Actor_GetNameFromIndex(i);
|
|
if (!strcmp(aActorName, name)) {
|
|
return DynOS_Builtin_Actor_GetFromIndex(i);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
ActorGfx* DynOS_Actor_GetActorGfx(const GraphNode* aGraphNode) {
|
|
if (aGraphNode == NULL) { return NULL; }
|
|
auto& _ValidActors = DynosValidActors();
|
|
|
|
// If georef is not NULL, check georef
|
|
if (aGraphNode->georef != NULL) {
|
|
if (_ValidActors.count(aGraphNode->georef) != 0) {
|
|
return &_ValidActors[aGraphNode->georef];
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// Check graph node
|
|
auto it = std::find_if(_ValidActors.begin(), _ValidActors.end(),
|
|
[&aGraphNode](const auto& _Actor) { return _Actor.second.mGraphNode == aGraphNode; }
|
|
);
|
|
if (it != _ValidActors.end()) {
|
|
return &it->second;
|
|
}
|
|
|
|
// No actor found
|
|
return NULL;
|
|
}
|
|
|
|
void DynOS_Actor_Valid(const void* aGeoref, ActorGfx& aActorGfx) {
|
|
if (aGeoref == NULL) { return; }
|
|
auto& _ValidActors = DynosValidActors();
|
|
_ValidActors[aGeoref] = aActorGfx;
|
|
DynOS_Tex_Valid(aActorGfx.mGfxData);
|
|
}
|
|
|
|
void DynOS_Actor_Invalid(const void* aGeoref, s32 aPackIndex) {
|
|
if (aGeoref == NULL) { return; }
|
|
auto& _ValidActors = DynosValidActors();
|
|
if (_ValidActors.count(aGeoref) == 0) { return; }
|
|
if (_ValidActors[aGeoref].mPackIndex != aPackIndex) { return; }
|
|
|
|
DynOS_Tex_Invalid(_ValidActors[aGeoref].mGfxData);
|
|
_ValidActors.erase(aGeoref);
|
|
}
|
|
|
|
void DynOS_Actor_Override(void** aSharedChild) {
|
|
if ((aSharedChild == NULL) || (*aSharedChild == NULL)) { return; }
|
|
|
|
const void* georef = (*(GraphNode**)aSharedChild)->georef;
|
|
if (georef == NULL) { return; }
|
|
|
|
auto& _ValidActors = DynosValidActors();
|
|
if (_ValidActors.count(georef) == 0) { return; }
|
|
|
|
*aSharedChild = (void*)_ValidActors[georef].mGraphNode;
|
|
}
|
|
|
|
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 }) {
|
|
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->header.gfx.sharedChild != NULL && _Object->header.gfx.sharedChild->georef != NULL) {
|
|
GraphNode* georef = (GraphNode*)_Object->header.gfx.sharedChild->georef;
|
|
_Object->header.gfx.sharedChild = (GraphNode *) DynOS_Geo_GetGraphNode(georef, true);
|
|
}
|
|
DynOS_Actor_Override((void**)&_Object->header.gfx.sharedChild);
|
|
}
|
|
}
|
|
}
|
|
|
|
void DynOS_Actor_ModShutdown() {
|
|
auto& _DynosCustomActors = DynosCustomActors();
|
|
while (_DynosCustomActors.Count() > 0) {
|
|
auto& pair = _DynosCustomActors[0];
|
|
DynOS_Actor_Invalid(pair.second, MOD_PACK_INDEX);
|
|
free((void*)pair.first);
|
|
_DynosCustomActors.Remove(0);
|
|
}
|
|
|
|
auto& _ValidActors = DynosValidActors();
|
|
for (auto it = _ValidActors.cbegin(); it != _ValidActors.cend();) {
|
|
auto& actorGfx = it->second;
|
|
if (actorGfx.mPackIndex == MOD_PACK_INDEX) {
|
|
free(actorGfx.mGraphNode);
|
|
DynOS_Gfx_Free(actorGfx.mGfxData);
|
|
_ValidActors.erase(it++);
|
|
} else {
|
|
++it;
|
|
}
|
|
}
|
|
|
|
DynOS_Actor_Override_All();
|
|
}
|