Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions soh/assets/objects/object_link_boy/object_link_boy_flipbook_DL.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef OBJECTS_OBJECT_LINK_BOY_FACE_DLS_H
#define OBJECTS_OBJECT_LINK_BOY_FACE_DLS_H

#include "align_asset_macro.h"

#define dgLinkAdultEyesOpenDL "__OTR__objects/object_link_boy/gLinkAdultEyesOpenDL"
static const ALIGN_ASSET(2) char gLinkAdultEyesOpenDL[] = dgLinkAdultEyesOpenDL;

#define dgLinkAdultEyesHalfDL "__OTR__objects/object_link_boy/gLinkAdultEyesHalfDL"
static const ALIGN_ASSET(2) char gLinkAdultEyesHalfDL[] = dgLinkAdultEyesHalfDL;

#define dgLinkAdultEyesClosedfDL "__OTR__objects/object_link_boy/gLinkAdultEyesClosedfDL"
static const ALIGN_ASSET(2) char gLinkAdultEyesClosedfDL[] = dgLinkAdultEyesClosedfDL;

#define dgLinkAdultEyesRollLeftDL "__OTR__objects/object_link_boy/gLinkAdultEyesRollLeftDL"
static const ALIGN_ASSET(2) char gLinkAdultEyesRollLeftDL[] = dgLinkAdultEyesRollLeftDL;

#define dgLinkAdultEyesRollRightDL "__OTR__objects/object_link_boy/gLinkAdultEyesRollRightDL"
static const ALIGN_ASSET(2) char gLinkAdultEyesRollRightDL[] = dgLinkAdultEyesRollRightDL;

#define dgLinkAdultEyesShockDL "__OTR__objects/object_link_boy/gLinkAdultEyesShockDL"
static const ALIGN_ASSET(2) char gLinkAdultEyesShockDL[] = dgLinkAdultEyesShockDL;

#define dgLinkAdultEyesUnk1DL "__OTR__objects/object_link_boy/gLinkAdultEyesUnk1DL"
static const ALIGN_ASSET(2) char gLinkAdultEyesUnk1DL[] = dgLinkAdultEyesUnk1DL;

#define dgLinkAdultEyesUnk2DL "__OTR__objects/object_link_boy/gLinkAdultEyesUnk2DL"
static const ALIGN_ASSET(2) char gLinkAdultEyesUnk2DL[] = dgLinkAdultEyesUnk2DL;

#define dgLinkAdultMouth1DL "__OTR__objects/object_link_boy/gLinkAdultMouth1DL"
static const ALIGN_ASSET(2) char gLinkAdultMouth1DL[] = dgLinkAdultMouth1DL;

#define dgLinkAdultMouth2DL "__OTR__objects/object_link_boy/gLinkAdultMouth2DL"
static const ALIGN_ASSET(2) char gLinkAdultMouth2DL[] = dgLinkAdultMouth2DL;

#define dgLinkAdultMouth3DL "__OTR__objects/object_link_boy/gLinkAdultMouth3DL"
static const ALIGN_ASSET(2) char gLinkAdultMouth3DL[] = dgLinkAdultMouth3DL;

#define dgLinkAdultMouth4DL "__OTR__objects/object_link_boy/gLinkAdultMouth4DL"
static const ALIGN_ASSET(2) char gLinkAdultMouth4DL[] = dgLinkAdultMouth4DL;

#endif // OBJECTS_OBJECT_LINK_BOY_FACE_DLS_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#ifndef OBJECTS_OBJECT_LINK_CHILD_FACE_DLS_H
#define OBJECTS_OBJECT_LINK_CHILD_FACE_DLS_H

#include "align_asset_macro.h"

#define dgLinkChildEyesOpenDL "__OTR__objects/object_link_child/gLinkChildEyesOpenDL"
static const ALIGN_ASSET(2) char gLinkChildEyesOpenDL[] = dgLinkChildEyesOpenDL;

#define dgLinkChildEyesHalfDL "__OTR__objects/object_link_child/gLinkChildEyesHalfDL"
static const ALIGN_ASSET(2) char gLinkChildEyesHalfDL[] = dgLinkChildEyesHalfDL;

#define dgLinkChildEyesClosedfDL "__OTR__objects/object_link_child/gLinkChildEyesClosedfDL"
static const ALIGN_ASSET(2) char gLinkChildEyesClosedfDL[] = dgLinkChildEyesClosedfDL;

#define dgLinkChildEyesRollLeftDL "__OTR__objects/object_link_child/gLinkChildEyesRollLeftDL"
static const ALIGN_ASSET(2) char gLinkChildEyesRollLeftDL[] = dgLinkChildEyesRollLeftDL;

#define dgLinkChildEyesRollRightDL "__OTR__objects/object_link_child/gLinkChildEyesRollRightDL"
static const ALIGN_ASSET(2) char gLinkChildEyesRollRightDL[] = dgLinkChildEyesRollRightDL;

#define dgLinkChildEyesShockDL "__OTR__objects/object_link_child/gLinkChildEyesShockDL"
static const ALIGN_ASSET(2) char gLinkChildEyesShockDL[] = dgLinkChildEyesShockDL;

#define dgLinkChildEyesUnk1DL "__OTR__objects/object_link_child/gLinkChildEyesUnk1DL"
static const ALIGN_ASSET(2) char gLinkChildEyesUnk1DL[] = dgLinkChildEyesUnk1DL;

#define dgLinkChildEyesUnk2DL "__OTR__objects/object_link_child/gLinkChildEyesUnk2DL"
static const ALIGN_ASSET(2) char gLinkChildEyesUnk2DL[] = dgLinkChildEyesUnk2DL;

#define dgLinkChildMouth1DL "__OTR__objects/object_link_child/gLinkChildMouth1DL"
static const ALIGN_ASSET(2) char gLinkChildMouth1DL[] = dgLinkChildMouth1DL;

#define dgLinkChildMouth2DL "__OTR__objects/object_link_child/gLinkChildMouth2DL"
static const ALIGN_ASSET(2) char gLinkChildMouth2DL[] = dgLinkChildMouth2DL;

#define dgLinkChildMouth3DL "__OTR__objects/object_link_child/gLinkChildMouth3DL"
static const ALIGN_ASSET(2) char gLinkChildMouth3DL[] = dgLinkChildMouth3DL;

#define dgLinkChildMouth4DL "__OTR__objects/object_link_child/gLinkChildMouth4DL"
static const ALIGN_ASSET(2) char gLinkChildMouth4DL[] = dgLinkChildMouth4DL;

#endif // OBJECTS_OBJECT_LINK_CHILD_FACE_DLS_H
153 changes: 153 additions & 0 deletions soh/soh/Enhancements/cosmetics/FlipbookDisplayLists.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/ShipInit.hpp"

extern "C" {
#include "macros.h"
#include "objects/object_link_boy/object_link_boy_flipbook_DL.h"
#include "objects/object_link_child/object_link_child_flipbook_DL.h"
#include "variables.h"
#include "functions.h"
#include "z64animation.h"
#include "z64player.h"
extern PlayState* gPlayState;
}

extern "C" uint8_t Player_IsCustomLinkModel();

// File-local helpers
// Set this limb index to the head limb in your custom player skeleton.
// Use -1 to disable. Limb index must be < player->skelAnime.limbCount.
static const s16 kHeadLimbIndex = 11;

// Use the texture name conventions and append "DL" for display lists.
static const char* kEyeDlPaths[2][8] = {
{
gLinkAdultEyesOpenDL,
gLinkAdultEyesHalfDL,
gLinkAdultEyesClosedfDL,
gLinkAdultEyesRollLeftDL,
gLinkAdultEyesRollRightDL,
gLinkAdultEyesShockDL,
gLinkAdultEyesUnk1DL,
gLinkAdultEyesUnk2DL,
},
{
gLinkChildEyesOpenDL,
gLinkChildEyesHalfDL,
gLinkChildEyesClosedfDL,
gLinkChildEyesRollLeftDL,
gLinkChildEyesRollRightDL,
gLinkChildEyesShockDL,
gLinkChildEyesUnk1DL,
gLinkChildEyesUnk2DL,
},
};

static const char* kMouthDlPaths[2][4] = {
{
gLinkAdultMouth1DL,
gLinkAdultMouth2DL,
gLinkAdultMouth3DL,
gLinkAdultMouth4DL,
},
{
gLinkChildMouth1DL,
gLinkChildMouth2DL,
gLinkChildMouth3DL,
gLinkChildMouth4DL,
},
};

static const u8 kEyeMouthIndexes[16][2] = {
{ 0, 0 }, { 1, 0 }, { 2, 0 }, { 0, 0 }, { 1, 0 }, { 2, 0 }, { 4, 0 }, { 5, 1 },
{ 7, 2 }, { 0, 2 }, { 3, 0 }, { 4, 0 }, { 2, 2 }, { 1, 1 }, { 0, 2 }, { 0, 0 },
};

static bool HasFaceDlConfigured() {
return kHeadLimbIndex >= 0;
}

static s16 sLastEyeIndex = -1;
static s16 sLastMouthIndex = -1;
static s16 sLastFaceIndex = -1;
static s16 sLastLinkAge = -1;

static void UpdateFaceFlipbookDlists(s16 eyeIndex, s16 mouthIndex, s16 faceIndex, s16 linkAge) {
if (!GameInteractor::IsSaveLoaded(true) || gPlayState == nullptr) {
return;
}

Player* player = GET_PLAYER(gPlayState);
if (eyeIndex < 0 || mouthIndex < 0) {
const s32 face = CLAMP(faceIndex, 0, static_cast<s16>(ARRAY_COUNT(kEyeMouthIndexes) - 1));
if (eyeIndex < 0) {
eyeIndex = kEyeMouthIndexes[face][0];
}
if (mouthIndex < 0) {
mouthIndex = kEyeMouthIndexes[face][1];
}
}

sLastEyeIndex = eyeIndex;
sLastMouthIndex = mouthIndex;
sLastFaceIndex = faceIndex;
sLastLinkAge = linkAge;
}

extern "C" void DrawFaceFlipbookDlists(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
Player* player = (Player*)thisx;

if (player == nullptr || limbIndex != kHeadLimbIndex) {
return;
}

if (!Player_IsCustomLinkModel() || !HasFaceDlConfigured()) {
return;
}

s16 eyeIndex = sLastEyeIndex;
s16 mouthIndex = sLastMouthIndex;
s16 faceIndex = sLastFaceIndex;
s16 linkAge = sLastLinkAge;

if (eyeIndex < 0 || mouthIndex < 0) {
const s32 face = CLAMP(faceIndex, 0, static_cast<s16>(ARRAY_COUNT(kEyeMouthIndexes) - 1));
if (eyeIndex < 0) {
eyeIndex = kEyeMouthIndexes[face][0];
}
if (mouthIndex < 0) {
mouthIndex = kEyeMouthIndexes[face][1];
}
}

eyeIndex = CLAMP(eyeIndex, 0, static_cast<s32>(ARRAY_COUNT(kEyeDlPaths[0]) - 1));
mouthIndex = CLAMP(mouthIndex, 0, static_cast<s32>(ARRAY_COUNT(kMouthDlPaths[0]) - 1));

const s32 ageIndex = CLAMP(linkAge, 0, 1);
const char* eyeDl = kEyeDlPaths[ageIndex][eyeIndex];
const char* mouthDl = kMouthDlPaths[ageIndex][mouthIndex];

OPEN_DISPS(play->state.gfxCtx);

const bool hasEyeDl = eyeDl != nullptr && ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileAltExists(eyeDl);
const bool hasMouthDl =
mouthDl != nullptr && ResourceMgr_IsAltAssetsEnabled() && ResourceMgr_FileAltExists(mouthDl);

if (hasEyeDl) {
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)eyeDl);
}

if (hasMouthDl) {
gSPDisplayList(POLY_OPA_DISP++, (Gfx*)mouthDl);
}

CLOSE_DISPS(play->state.gfxCtx);
}

static void RegisterFaceFlipbookDlists() {
COND_HOOK(OnPlayerFaceUpdate, true, UpdateFaceFlipbookDlists);
COND_HOOK(OnPlayerPostLimbDraw, true, DrawFaceFlipbookDlists);
}

static RegisterShipInitFunc initFunc(RegisterFaceFlipbookDlists);
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ DEFINE_HOOK(OnSceneSpawnActors, ());
DEFINE_HOOK(OnLinkSkeletonInit, ());
DEFINE_HOOK(OnLinkEquipmentChange, ());
DEFINE_HOOK(OnPlayerUpdate, ());
DEFINE_HOOK(OnPlayerFaceUpdate, (s16 eyeIndex, s16 mouthIndex, s16 faceIndex, s16 linkAge));
DEFINE_HOOK(OnPlayerPostLimbDraw, (PlayState * play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx));
DEFINE_HOOK(OnSetDoAction, (uint16_t action));
DEFINE_HOOK(OnPlayerSfx, (u16 sfxId));
DEFINE_HOOK(OnOcarinaSongAction, ());
Expand Down
23 changes: 23 additions & 0 deletions soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,29 @@ void GameInteractor_ExecuteOnPlayerUpdate() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerUpdate>();
}

void GameInteractor_ExecuteOnPlayerFaceUpdate(s16 eyeIndex, s16 mouthIndex, s16 faceIndex, s16 linkAge) {
static s16 lastEyeIndex = -1;
static s16 lastMouthIndex = -1;
static s16 lastFaceIndex = -1;
static s16 lastLinkAge = -1;

if (lastEyeIndex == eyeIndex && lastMouthIndex == mouthIndex && lastFaceIndex == faceIndex &&
lastLinkAge == linkAge) {
return;
}

lastEyeIndex = eyeIndex;
lastMouthIndex = mouthIndex;
lastFaceIndex = faceIndex;
lastLinkAge = linkAge;
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerFaceUpdate>(eyeIndex, mouthIndex, faceIndex,
linkAge);
}

void GameInteractor_ExecuteOnPlayerPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnPlayerPostLimbDraw>(play, limbIndex, dList, rot, thisx);
}

void GameInteractor_ExecuteOnSetDoAction(uint16_t action) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSetDoAction>(action);
}
Expand Down
2 changes: 2 additions & 0 deletions soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ void GameInteractor_ExecuteOnSceneSpawnActors();
void GameInteractor_ExecuteOnLinkSkeletonInit();
void GameInteractor_ExecuteOnLinkEquipmentChange();
void GameInteractor_ExecuteOnPlayerUpdate();
void GameInteractor_ExecuteOnPlayerFaceUpdate(s16 eyeIndex, s16 mouthIndex, s16 faceIndex, s16 linkAge);
void GameInteractor_ExecuteOnPlayerPostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx);
void GameInteractor_ExecuteOnSetDoAction(uint16_t action);
void GameInteractor_ExecuteOnPlayerSfx(u16 sfxId);
void GameInteractor_ExecuteOnOcarinaSongAction();
Expand Down
4 changes: 4 additions & 0 deletions soh/src/code/z_player_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1063,6 +1063,8 @@ void Player_DrawImpl(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dL
if (mouthIndex > 3)
mouthIndex = 3;

GameInteractor_ExecuteOnPlayerFaceUpdate(eyeIndex, mouthIndex, face, gSaveContext.linkAge);

#if defined(MODDING) || defined(_MSC_VER) || defined(__GNUC__)
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(sMouthTextures[gSaveContext.linkAge][mouthIndex]));
#else
Expand Down Expand Up @@ -2025,6 +2027,8 @@ void Player_PostLimbDrawGameplay(PlayState* play, s32 limbIndex, Gfx** dList, Ve
Actor_SetFeetPos(&this->actor, limbIndex, PLAYER_LIMB_L_FOOT, vec, PLAYER_LIMB_R_FOOT, vec);
}
}

GameInteractor_ExecuteOnPlayerPostLimbDraw(play, limbIndex, dList, rot, thisx);
}

u32 func_80091738(PlayState* play, u8* segment, SkelAnime* skelAnime) {
Expand Down
Loading