Alt Toggle for Custom animation (#6433)

Add explicit alt prefix checking to animation loading

Makes ResourceMgr_LoadAnimByName alt-toggleable this will work for Link and any other animations files
This commit is contained in:
PurpleHato 2026-04-06 21:01:12 +02:00 committed by GitHub
parent e86e0ff693
commit 262958a2eb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 64 additions and 2 deletions

View file

@ -517,7 +517,47 @@ extern "C" int ResourceMgr_OTRSigCheck(char* imgData) {
return 0;
}
// Load animation with explicit alt asset path checking.
// When Alt Assets is OFF: use original path directly (O2R or vanilla)
// When Alt Assets is ON: try alt/ prefix first, fall back to regular path if not found or invalid
extern "C" AnimationHeaderCommon* ResourceMgr_LoadAnimByName(const char* path) {
bool isAlt = ResourceMgr_IsAltAssetsEnabled();
if (isAlt) {
std::string pathStr = std::string(path);
static const std::string sOtr = "__OTR__";
if (pathStr.starts_with(sOtr)) {
pathStr = pathStr.substr(sOtr.length());
}
// Try alt/ first
pathStr = Ship::IResource::gAltAssetPrefix + pathStr;
AnimationHeaderCommon* animHeader = (AnimationHeaderCommon*)ResourceGetDataByName(pathStr.c_str());
// If alt loaded successfully, verify it has valid data
if (animHeader != NULL) {
// Check for valid frame count (> 0)
if (animHeader->frameCount > 0) {
// For Normal animations: check frameData (comes after frameCount in AnimationHeader)
// For Link animations: check segment (comes after frameCount in LinkAnimationHeader)
// We check both to be safe - if either is valid, the animation is usable
AnimationHeader* normalAnim = (AnimationHeader*)animHeader;
LinkAnimationHeader* linkAnim = (LinkAnimationHeader*)animHeader;
// Valid if Normal animation has frameData OR Link animation has segment
if (normalAnim->frameData != NULL || linkAnim->segment != NULL) {
return animHeader;
}
}
// Alt loaded but is invalid (broken), fall through to original path
}
// Fall back to original path
return (AnimationHeaderCommon*)ResourceGetDataByName(path);
}
// Alt OFF: use original path directly
return (AnimationHeaderCommon*)ResourceGetDataByName(path);
}

View file

@ -78,15 +78,33 @@ ResourceFactoryBinaryAnimationV0::ReadResource(std::shared_ptr<Ship::File> file,
}
animation->animationData.transformUpdateIndex.copyValues = animation->copyValuesArr.data();
} else if (animType == AnimationType::Link) {
// Initialize segment to nullptr (important for alt asset fallback)
animation->animationData.linkAnimationHeader.segment = nullptr;
// Read the frame count
animation->animationData.linkAnimationHeader.common.frameCount = reader->ReadInt16();
// Read the segment pointer (always 32 bit, doesn't adjust for system pointer size)
std::string path = reader->ReadString();
const auto animData = std::static_pointer_cast<Animation>(
auto animData = std::static_pointer_cast<Animation>(
Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(path.c_str()));
// If direct load failed and alt assets are enabled, try with alt/ prefix
if (animData == nullptr && Ship::Context::GetInstance()->GetResourceManager()->IsAltAssetsEnabled()) {
std::string altPath = path;
if (altPath.find("__OTR__") == 0) {
altPath = altPath.substr(7); // Strip __OTR__
}
altPath = "alt/" + altPath;
animData = std::static_pointer_cast<Animation>(
Ship::Context::GetInstance()->GetResourceManager()->LoadResourceProcess(altPath.c_str()));
}
if (animData != nullptr) {
animation->animationData.linkAnimationHeader.segment = animData->GetPointer();
} else {
SPDLOG_WARN("Animation data segment not found: {}", path);
}
} else if (animType == AnimationType::Legacy) {
SPDLOG_DEBUG("BEYTAH ANIMATION?!");
}

View file

@ -902,6 +902,10 @@ void AnimationContext_SetLoadFrame(PlayState* play, LinkAnimationHeader* animati
if (frame < 0) {
frame = 0;
}
// SOH [Alt Assets] Check if animData is null (can happen if animation data segment failed to load)
if (animData == NULL) {
return;
}
memcpy(ram, (uintptr_t)animData + (((sizeof(Vec3s) * limbCount + 2) * frame)), sizeof(Vec3s) * limbCount + 2);
}
}