`z_fcurve_data` OK, match last function in `z_fcurve_data_skelanime`, document SkelCurve system (#776)

* Match SkelCurve_Update

Co-authored-by: Kelebek1 <34639600+Kelebek1@users.noreply.github.com>

* Match and document z_fcurve_data

* Begin documenting SkelCurve

* More documentation

* Deformat header

* Pluralise knotCount

* Sort out jointTable

* Rename frameCount

* Format

* More documentation

* Cleanup on DemoEffect

* Remove space on typedef

* Format, couple of fixes in the header

* Review

* Oops

* Fix EnBox, DemoTreLgt, use macros in EnTorch

Co-authored-by: Kelebek1 <34639600+Kelebek1@users.noreply.github.com>
This commit is contained in:
EllipticEllipsis 2022-06-19 03:38:10 +01:00 committed by GitHub
parent 5ae4ef87cd
commit af0123de1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 505 additions and 327 deletions

View File

@ -1454,14 +1454,6 @@ s16 ActorCutscene_GetCurrentCamera(s16 index);
s16 func_800F21CC(void);
s32 func_800F22C4(s16 param_1, Actor* actor);
void ActorCutscene_SetReturnCamera(s16 index);
// void func_800F23E0(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6);
f32 func_800F2478(f32 target, TransformData* transData, s32 refIdx);
void SkelCurve_Clear(SkelAnimeCurve* skelCurve);
s32 SkelCurve_Init(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve, SkelCurveLimbList* limbListSeg, TransformUpdateIndex* transUpdIdx);
void SkelCurve_Destroy(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve);
void SkelCurve_SetAnim(SkelAnimeCurve* skelCurve, TransformUpdateIndex* transUpdIdx, f32 arg2, f32 animFinalFrame, f32 animCurFrame, f32 animSpeed);
s32 SkelCurve_Update(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve);
void SkelCurve_Draw(Actor* actor, GlobalContext* globalCtx, SkelAnimeCurve* skelCurve, OverrideCurveLimbDraw overrideLimbDraw, PostCurveLimbDraw postLimbDraw, s32 lod, Actor* thisx);
void FireObj_SetPosition(FireObj* fire, Vec3f* pos);
void FireObj_Draw(GlobalContext* globalCtx, FireObj* fire);
void FireObj_Init(GlobalContext* globalCtx, FireObj* fire, FireObjInitParams* init, Actor* actor);

View File

@ -1,7 +1,7 @@
#ifndef _OS_INTERNAL_H_
#define _OS_INTERNAL_H_
typedef struct {
typedef struct {
/* 0x00 */ OSMesgQueue* queue;
/* 0x04 */ OSMesg msg;
} __osHwInt; // size = 0x08

View File

@ -30,6 +30,7 @@
#include "z64audio.h"
#include "z64bgcheck.h"
#include "z64collision_check.h"
#include "z64curve.h"
#include "z64cutscene.h"
#include "z64dma.h"
#include "z64effect.h"

View File

@ -224,56 +224,6 @@ typedef void (*AnimationEntryCallback)(struct GlobalContext*, AnimationEntryData
extern u32 link_animetion_segment;
// fcurve_skelanime structs
typedef struct {
/* 0x0000 */ u16 unk00; // appears to be flags
/* 0x0002 */ s16 unk02;
/* 0x0004 */ s16 unk04;
/* 0x0006 */ s16 unk06;
/* 0x0008 */ f32 unk08;
} TransformData; // size = 0xC
typedef struct {
/* 0x0000 */ u8* refIndex;
/* 0x0004 */ TransformData* transformData;
/* 0x0008 */ s16* copyValues;
/* 0x000C */ s16 unk0C;
/* 0x000E */ s16 unk10;
} TransformUpdateIndex; // size 0x10
typedef struct {
/* 0x0000 */ u8 firstChildIdx;
/* 0x0001 */ u8 nextLimbIdx;
/* 0x0004 */ Gfx* dList[2];
} SkelCurveLimb; // size >= 0x8
typedef struct {
/* 0x0000 */ SkelCurveLimb** limbs;
/* 0x0004 */ u8 limbCount;
} SkelCurveLimbList; // size = 0x8
typedef struct {
/* 0x0000 */ Vec3s scale;
/* 0x0006 */ Vec3s rot;
/* 0x000C */ Vec3s pos;
} LimbTransform; // size = 0x12
typedef struct {
/* 0x0000 */ u8 limbCount;
/* 0x0004 */ SkelCurveLimb** limbList;
/* 0x0008 */ TransformUpdateIndex* transUpdIdx;
/* 0x000C */ f32 unk0C; // seems to be unused
/* 0x0010 */ f32 animFinalFrame;
/* 0x0014 */ f32 animSpeed;
/* 0x0018 */ f32 animCurFrame;
/* 0x001C */ LimbTransform* transforms;
} SkelAnimeCurve; // size = 0x20
typedef s32 (*OverrideCurveLimbDraw)(struct GlobalContext* globalCtx, SkelAnimeCurve* skelCuve, s32 limbIndex,
struct Actor* actor);
typedef void (*PostCurveLimbDraw)(struct GlobalContext* globalCtx, SkelAnimeCurve* skelCuve, s32 limbIndex,
struct Actor* actor);
typedef struct {
/* 0x00 */ AnimationHeader* animation;
/* 0x04 */ f32 playSpeed;

68
include/z64curve.h Normal file
View File

@ -0,0 +1,68 @@
#ifndef Z64_CURVE_H
#define Z64_CURVE_H
#include "PR/ultratypes.h"
#include "z64math.h"
struct GlobalContext;
typedef struct {
/* 0x0 */ u16 flags; // Only the bottom two bits are used, although others are set in objects
/* 0x2 */ s16 abscissa; // knot input value
/* 0x4 */ s16 leftGradient; // left derivative at the point
/* 0x6 */ s16 rightGradient; // right derivative at the point
/* 0x8 */ f32 ordinate; // output value
} CurveInterpKnot; // size = 0xC
typedef struct {
/* 0x0 */ u8* knotCounts;
/* 0x4 */ CurveInterpKnot* interpolationData;
/* 0x8 */ s16* constantData;
/* 0xC */ s16 unk_0C; // Set but not used, always 1 in objects
/* 0xE */ s16 frameCount; // Not used, inferred from use in objects
} CurveAnimationHeader; // size = 0x10
typedef struct {
/* 0x0 */ u8 child;
/* 0x1 */ u8 sibling;
/* 0x4 */ Gfx* dList[2];
} SkelCurveLimb; // size = 0xC
typedef struct {
/* 0x0 */ SkelCurveLimb** limbs;
/* 0x4 */ u8 limbCount;
} CurveSkeletonHeader; // size = 0x8
typedef struct {
/* 0x00 */ u8 limbCount;
/* 0x04 */ SkelCurveLimb** skeleton;
/* 0x08 */ CurveAnimationHeader* animation;
/* 0x0C */ f32 unk_0C; // set but not used
/* 0x10 */ f32 endFrame;
/* 0x14 */ f32 playSpeed;
/* 0x18 */ f32 curFrame;
/* 0x1C */ s16 (*jointTable)[9];
} SkelCurve; // size = 0x20
typedef s32 (*OverrideCurveLimbDraw)(struct GlobalContext* globalCtx, SkelCurve* skelCuve, s32 limbIndex, struct Actor* actor);
typedef void (*PostCurveLimbDraw)(struct GlobalContext* globalCtx, SkelCurve* skelCuve, s32 limbIndex, struct Actor* actor);
f32 Curve_Interpolate(f32 x, CurveInterpKnot* knots, s32 knotCount);
void SkelCurve_Clear(SkelCurve* skelCurve);
s32 SkelCurve_Init(struct GlobalContext* globalCtx, SkelCurve* skelCurve, CurveSkeletonHeader* skeletonHeaderSeg, CurveAnimationHeader* animation);
void SkelCurve_Destroy(struct GlobalContext* globalCtx, SkelCurve* skelCurve);
void SkelCurve_SetAnim(SkelCurve* skelCurve, CurveAnimationHeader* animation, f32 arg2, f32 endFrame, f32 curFrame, f32 playSpeed);
s32 SkelCurve_Update(struct GlobalContext* globalCtx, SkelCurve* skelCurve);
void SkelCurve_Draw(Actor* actor, struct GlobalContext* globalCtx, SkelCurve* skelCurve, OverrideCurveLimbDraw overrideLimbDraw, PostCurveLimbDraw postLimbDraw, s32 lod, Actor* thisx);
// ZAPD compatibility typedefs
// TODO: Remove when ZAPD adds support for them
typedef CurveInterpKnot TransformData;
typedef CurveAnimationHeader TransformUpdateIndex;
typedef CurveSkeletonHeader SkelCurveLimbList;
#endif // Z64_CURVE_H

View File

@ -280,7 +280,9 @@ typedef enum {
/* 0x0C */ GI_HEART_PIECE = 0x0C,
/* 0x0D */ GI_HEART_CONTAINER,
/* 0x11 */ GI_STRAY_FAIRY = 0x11,
/* 0x16 */ GI_BOMBS_10 = 0x16,
/* 0x14 */ GI_BOMBS_1 = 0x14,
/* 0x15 */ GI_BOMBS_5,
/* 0x16 */ GI_BOMBS_10,
/* 0x19 */ GI_STICKS_1 = 0x19,
/* 0x1A */ GI_BOMBCHUS_10,
/* 0x1B */ GI_BOMB_BAG_20,
@ -298,6 +300,8 @@ typedef enum {
/* 0x32 */ GI_SHIELD_HERO = 0x32,
/* 0x33 */ GI_SHIELD_MIRROR,
/* 0x35 */ GI_MAGIC_BEANS = 0x35,
/* 0x36 */ GI_BOMBCHUS_1,
/* 0x3A */ GI_BOMBCHUS_5 = 0x3A,
/* 0x3C */ GI_KEY_SMALL = 0x3C,
/* 0x3D */ GI_KEY_BOSS,
/* 0x3E */ GI_MAP,

View File

@ -109,17 +109,19 @@ typedef struct {
#define IS_ZERO(f) (fabsf(f) < 0.008f)
// Trig macros
#define DEGF_TO_BINANG(degreesf) (s16)(degreesf * 182.04167f + .5f)
#define RADF_TO_BINANG(radf) (s16)(radf * (0x8000 / M_PI))
#define RADF_TO_DEGF(radf) (radf * (180.0f / M_PI))
#define DEGF_TO_RADF(degf) (degf * (M_PI / 180.0f))
// Angle conversion macros
#define DEG_TO_BINANG(degrees) (s16)((degrees) * (0x8000 / 180.0f))
#define DEGF_TO_BINANG(degreesf) (s16)((degreesf) * 182.04167f + .5f)
#define RADF_TO_BINANG(radf) (s16)((radf) * (0x8000 / M_PI))
#define RADF_TO_DEGF(radf) ((radf) * (180.0f / M_PI))
#define DEGF_TO_RADF(degf) ((degf) * (M_PI / 180.0f))
#define BINANG_TO_DEGF(binang) ((f32)binang * (360.0001525f / 65535.0f))
#define BINANG_TO_RAD(binang) (((f32)binang / 0x8000) * M_PI)
// Angle arithmetic macros
#define BINANG_ROT180(angle) ((s16)(angle + 0x8000))
#define BINANG_SUB(a, b) ((s16)(a - b))
#define BINANG_ADD(a, b) ((s16)(a + b))
#define DEG_TO_RAD(degrees) ((degrees) * (M_PI / 180.0f))
#define BINANG_TO_DEGF(binang) ((f32)binang * (360.0001525f / 65535.0f))
#define BINANG_TO_RAD(binang) (((f32)binang / 0x8000) * M_PI)
// Vector macros
#define SQXZ(vec) ((vec.x) * (vec.x) + (vec.z) * (vec.z))

View File

@ -1,5 +1,86 @@
/**
* @file z_fcurve_data.c
* @brief Interpolation functions for use with Curve SkelAnime
*/
#include "global.h"
#include "z64curve.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data/func_800F23E0.s")
#define FCURVE_INTERP_CUBIC 0 // Interpolate using a Hermite cubic spline
#define FCURVE_INTERP_NONE 1 // Return the value at the left endpoint instead of interpolating
#define FCURVE_INTERP_LINEAR 2 // Interpolate linearly
#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data/func_800F2478.s")
/**
* Hermite cubic spline interpolation between two endpoints, a,b. More information available at
* https://en.wikipedia.org/wiki/Cubic_Hermite_spline
*
* @param t interpolation parameter rescaled to lie in [0,1], (x-a)/(b-a)
* @param interval distance (b-a) between the endpoints
* @param y0 p(a)
* @param y1 p(b)
* @param m0 p'(a)
* @param m1 p'(b)
* @return f32 p(t), value of the cubic interpolating polynomial
*/
f32 Curve_CubicHermiteSpline(f32 t, f32 interval, f32 y0, f32 y1, f32 m0, f32 m1) {
f32 t2 = t * t;
f32 t3 = t2 * t;
f32 t3x2 = t3 * 2.0f;
f32 t2x3 = t2 * 3.0f;
// Hermite basis cubics h_{ij} satisfy h_{ij}^{(j)}(i) = 1, the other three values being 0
f32 h00 = t3x2 - t2x3 + 1.0f; // h_{00}(t) = 2t^3 - 3t^2 + 1
f32 h01 = t2x3 - t3x2; // h_{01}(t) = 3t^2 - 2t^3
f32 h10 = t3 - t2 * 2.0f + t; // h_{10}(t) = t^3 - 2t^2 + t
f32 h11 = t3 - t2; // h_{11}(t) = t^3 - t^2
f32 ret = h00 * y0;
ret += h01 * y1;
ret += h10 * m0 * interval;
ret += h11 * m1 * interval;
return ret;
}
/**
* Interpolates based on an array of CurveInterpKnot.
*
* @param x point at which to interpolate.
* @param knots Beginning of CurveInterpKnot array to use.
* @param knotCount number of knots to read from the array.
* @return f32 interpolated value
*/
f32 Curve_Interpolate(f32 x, CurveInterpKnot* knots, s32 knotCount) {
// If outside the entire interpolation interval, return the value at the near endpoint.
if (x <= knots[0].abscissa) {
return knots[0].ordinate;
} else if (x >= knots[knotCount - 1].abscissa) {
return knots[knotCount - 1].ordinate;
} else {
s32 cur;
for (cur = 0;; cur++) {
s32 next = cur + 1;
// Find the subinterval in which x lies
if (x < knots[next].abscissa) {
if (knots[cur].flags & FCURVE_INTERP_NONE) {
// No interpolation
return knots[cur].ordinate;
} else if (knots[cur].flags & FCURVE_INTERP_LINEAR) {
// Linear interpolation
return knots[cur].ordinate +
((x - (f32)knots[cur].abscissa) / ((f32)knots[next].abscissa - (f32)knots[cur].abscissa)) *
(knots[next].ordinate - knots[cur].ordinate);
} else {
// Cubic interpolation
f32 diff = (f32)knots[next].abscissa - (f32)knots[cur].abscissa;
f32 t = (x - (f32)knots[cur].abscissa) / ((f32)knots[next].abscissa - (f32)knots[cur].abscissa);
return Curve_CubicHermiteSpline(t, diff * (1.0f / 30.0f), knots[cur].ordinate, knots[next].ordinate,
knots[cur].rightGradient, knots[next].leftGradient);
}
}
}
}
}

View File

@ -1,130 +1,187 @@
/**
* @file z_fcurve_data_skelanime.c
* @brief Curve skeleton animation system
*
* A curve skeleton has a fixed number of limbs, each of which has 9 properties that may be changed by the animation:
* - 3 scales,
* - 3 rotations,
* - 3 positions
* (note the position is stored in the animations instead of being stored in the limbs like SkelAnime would). Otherwise
* the structure is similar to an ordinary SkelAnime-compatible skeleton.
*
* The animations are significantly more complex than SkelAnime. A curve animation consists of 4 parts:
* - a header (CurveAnimationHeader)
* - a list of counts, one for each of the 9 properties of each limb (u8)
* - a list of interpolation data (CurveInterpKnot). The length is the sum of the counts.
* - a list of constant data (s16[9]). The length is the number of 0s in counts.
*
* If the interpolation count for a property is 0, the value of the property is copied from the next number in the
* constant data; there are no gaps for nonzero interpolation count.
* If the interpolation count N for a property is larger than 0, the next N elements of the interpolation data array
* are used to interpolate the value of the property, using Curve_Interpolate.
*
* Curve limbs may use LOD:
* - lower detail draws only the first displaylist
* - higher detail draws both.
*/
#include "global.h"
#include "z64curve.h"
void SkelCurve_Clear(SkelAnimeCurve* skelCurve) {
void SkelCurve_Clear(SkelCurve* skelCurve) {
skelCurve->limbCount = 0;
skelCurve->limbList = NULL;
skelCurve->transUpdIdx = NULL;
skelCurve->animCurFrame = 0.0f;
skelCurve->animSpeed = 0.0f;
skelCurve->animFinalFrame = 0.0f;
skelCurve->unk0C = 0.0f;
skelCurve->transforms = NULL;
skelCurve->skeleton = NULL;
skelCurve->animation = NULL;
skelCurve->curFrame = 0.0f;
skelCurve->playSpeed = 0.0f;
skelCurve->endFrame = 0.0f;
skelCurve->unk_0C = 0.0f;
skelCurve->jointTable = NULL;
}
s32 SkelCurve_Init(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve, SkelCurveLimbList* limbListSeg,
TransformUpdateIndex* transUpdIdx) {
/**
* Initialises the SkelCurve struct and mallocs the joint table.
*
* @return bool always true
*/
s32 SkelCurve_Init(GlobalContext* globalCtx, SkelCurve* skelCurve, CurveSkeletonHeader* skeletonHeaderSeg,
CurveAnimationHeader* animation) {
SkelCurveLimb** limbs;
SkelCurveLimbList* limbList = Lib_SegmentedToVirtual(limbListSeg);
CurveSkeletonHeader* skeletonHeader = Lib_SegmentedToVirtual(skeletonHeaderSeg);
skelCurve->limbCount = limbList->limbCount;
skelCurve->limbList = Lib_SegmentedToVirtual(limbList->limbs);
skelCurve->limbCount = skeletonHeader->limbCount;
skelCurve->skeleton = Lib_SegmentedToVirtual(skeletonHeader->limbs);
skelCurve->transforms = ZeldaArena_Malloc(sizeof(*skelCurve->transforms) * skelCurve->limbCount);
skelCurve->jointTable = ZeldaArena_Malloc(sizeof(*skelCurve->jointTable) * skelCurve->limbCount);
do {
skelCurve->animCurFrame = 0.0f;
} while (0);
return 1;
skelCurve->curFrame = 0.0f;
return true;
}
void SkelCurve_Destroy(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve) {
if (skelCurve->transforms != NULL) {
ZeldaArena_Free(skelCurve->transforms);
/**
* Frees the joint table.
*/
void SkelCurve_Destroy(GlobalContext* globalCtx, SkelCurve* skelCurve) {
if (skelCurve->jointTable != NULL) {
ZeldaArena_Free(skelCurve->jointTable);
}
}
void SkelCurve_SetAnim(SkelAnimeCurve* skelCurve, TransformUpdateIndex* transUpdIdx, f32 arg2, f32 animFinalFrame,
f32 animCurFrame, f32 animSpeed) {
skelCurve->unk0C = arg2 - skelCurve->animSpeed;
skelCurve->animFinalFrame = animFinalFrame;
skelCurve->animCurFrame = animCurFrame;
skelCurve->animSpeed = animSpeed;
skelCurve->transUpdIdx = transUpdIdx;
void SkelCurve_SetAnim(SkelCurve* skelCurve, CurveAnimationHeader* animation, f32 arg2, f32 endFrame, f32 curFrame,
f32 playSpeed) {
skelCurve->unk_0C = arg2 - skelCurve->playSpeed;
skelCurve->endFrame = endFrame;
skelCurve->curFrame = curFrame;
skelCurve->playSpeed = playSpeed;
skelCurve->animation = animation;
}
#ifdef NON_MATCHING
/* Should be functionally equivalent, also migrating rodata makes it a lot cleaner */
s32 SkelCurve_Update(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve) {
s16* transforms;
u8* transformRefIdx;
TransformUpdateIndex* transformIndex;
u16* transformCopyValues;
s32 i;
s32 ret = 0;
s32 k;
TransformData* transData;
f32 transformValue;
s32 j;
typedef enum {
/* 0 */ SKELCURVE_VEC_TYPE_SCALE,
/* 1 */ SKELCURVE_VEC_TYPE_ROTATION,
/* 2 */ SKELCURVE_VEC_TYPE_POSIITON,
/* 3 */ SKELCURVE_VEC_TYPE_MAX
} SkelCurveVecType;
transformIndex = Lib_SegmentedToVirtual(skelCurve->transUpdIdx);
transformRefIdx = Lib_SegmentedToVirtual(transformIndex->refIndex);
transData = Lib_SegmentedToVirtual(transformIndex->transformData);
transformCopyValues = Lib_SegmentedToVirtual(transformIndex->copyValues);
transforms = (s16*)skelCurve->transforms;
#define SKELCURVE_SCALE_SCALE 1024.0f
#define SKELCURVE_SCALE_POSITION 100
skelCurve->animCurFrame += skelCurve->animSpeed * (globalCtx->state.framerateDivisor * 0.5f);
/**
* The only animation updating function.
*
* @return bool true when the animation has finished.
*/
s32 SkelCurve_Update(GlobalContext* globalCtx, SkelCurve* skelCurve) {
s16* jointData;
u8* knotCounts;
CurveAnimationHeader* animation;
u16* constantData;
s32 curLimb;
s32 ret = false;
s32 coord;
CurveInterpKnot* startKnot;
s32 vecType;
if ((skelCurve->animSpeed >= 0.0f && skelCurve->animCurFrame > skelCurve->animFinalFrame) ||
(skelCurve->animSpeed < 0.0f && skelCurve->animCurFrame < skelCurve->animFinalFrame)) {
skelCurve->animCurFrame = skelCurve->animFinalFrame;
ret = 1;
animation = Lib_SegmentedToVirtual(skelCurve->animation);
knotCounts = Lib_SegmentedToVirtual(animation->knotCounts);
startKnot = Lib_SegmentedToVirtual(animation->interpolationData);
constantData = Lib_SegmentedToVirtual(animation->constantData);
jointData = *skelCurve->jointTable;
skelCurve->curFrame += skelCurve->playSpeed * ((s32)globalCtx->state.framerateDivisor * 0.5f);
if (((skelCurve->playSpeed >= 0.0f) && (skelCurve->curFrame > skelCurve->endFrame)) ||
((skelCurve->playSpeed < 0.0f) && (skelCurve->curFrame < skelCurve->endFrame))) {
skelCurve->curFrame = skelCurve->endFrame;
ret = true;
}
for (i = 0; i < skelCurve->limbCount; i++) {
for (j = 0; j < 3; j++) {
for (k = 0; k < 3; k++, transformRefIdx++, transforms++) {
if (*transformRefIdx == 0) {
transformValue = *transformCopyValues;
*transforms = transformValue;
transformCopyValues++;
for (curLimb = 0; curLimb < skelCurve->limbCount; curLimb++) {
// scale/rotation/position
for (vecType = SKELCURVE_VEC_TYPE_SCALE; vecType < SKELCURVE_VEC_TYPE_MAX; vecType++) {
// x/y/z
for (coord = 0; coord < 3; coord++) {
f32 transformValue;
if (*knotCounts == 0) {
transformValue = *constantData;
*jointData = transformValue;
constantData++;
} else {
transformValue = func_800F2478(skelCurve->animCurFrame, transData, *transformRefIdx);
transData += *transformRefIdx;
if (j == 0) {
*transforms = transformValue * 1024.0f;
} else if (j == 1) {
*transforms = transformValue * (32768.0f / 180.0f);
} else {
*transforms = transformValue * 100.0f;
transformValue = Curve_Interpolate(skelCurve->curFrame, startKnot, *knotCounts);
startKnot += *knotCounts;
if (vecType == SKELCURVE_VEC_TYPE_SCALE) {
// Rescaling allows for more refined scaling using an s16
*jointData = transformValue * SKELCURVE_SCALE_SCALE;
} else if (vecType == SKELCURVE_VEC_TYPE_ROTATION) {
// Convert value from degrees to a binary angle
*jointData = DEG_TO_BINANG(transformValue);
} else { // SKELCURVE_VEC_TYPE_POSIITON
// Model to world scale conversion
*jointData = transformValue * SKELCURVE_SCALE_POSITION;
}
}
knotCounts++;
jointData++;
}
}
}
return ret;
}
#else
#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/SkelCurve_Update.s")
#endif
void SkelCurve_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, SkelAnimeCurve* skelCurve,
/**
* Recursively draws limbs with appropriate properties.
*/
void SkelCurve_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, SkelCurve* skelCurve,
OverrideCurveLimbDraw overrideLimbDraw, PostCurveLimbDraw postLimbDraw, s32 lod, Actor* thisx) {
SkelCurveLimb* limb = Lib_SegmentedToVirtual(skelCurve->limbList[limbIndex]);
SkelCurveLimb* limb = Lib_SegmentedToVirtual(skelCurve->skeleton[limbIndex]);
OPEN_DISPS(globalCtx->state.gfxCtx);
Matrix_Push();
if (overrideLimbDraw == NULL ||
(overrideLimbDraw != NULL && overrideLimbDraw(globalCtx, skelCurve, limbIndex, thisx))) {
if ((overrideLimbDraw == NULL) ||
((overrideLimbDraw != NULL) && overrideLimbDraw(globalCtx, skelCurve, limbIndex, thisx))) {
Vec3f scale;
Vec3s rot;
Vec3f pos;
Gfx* dList;
Vec3s* transform = (Vec3s*)&skelCurve->transforms[limbIndex];
s16* jointData = skelCurve->jointTable[limbIndex];
scale.x = transform->x / 1024.0f;
scale.y = transform->y / 1024.0f;
scale.z = transform->z / 1024.0f;
transform++;
rot.x = transform->x;
rot.y = transform->y;
rot.z = transform->z;
transform++;
pos.x = transform->x;
pos.y = transform->y;
pos.z = transform->z;
scale.x = jointData[0] / SKELCURVE_SCALE_SCALE;
scale.y = jointData[1] / SKELCURVE_SCALE_SCALE;
scale.z = jointData[2] / SKELCURVE_SCALE_SCALE;
jointData += 3;
rot.x = jointData[0];
rot.y = jointData[1];
rot.z = jointData[2];
jointData += 3;
pos.x = jointData[0];
pos.y = jointData[1];
pos.z = jointData[2];
Matrix_TranslateRotateZYX(&pos, &rot);
Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY);
@ -160,22 +217,22 @@ void SkelCurve_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, SkelAnimeCurve*
postLimbDraw(globalCtx, skelCurve, limbIndex, thisx);
}
if (limb->firstChildIdx != LIMB_DONE) {
SkelCurve_DrawLimb(globalCtx, limb->firstChildIdx, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
if (limb->child != LIMB_DONE) {
SkelCurve_DrawLimb(globalCtx, limb->child, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
}
Matrix_Pop();
if (limb->nextLimbIdx != LIMB_DONE) {
SkelCurve_DrawLimb(globalCtx, limb->nextLimbIdx, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
if (limb->sibling != LIMB_DONE) {
SkelCurve_DrawLimb(globalCtx, limb->sibling, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
void SkelCurve_Draw(Actor* actor, GlobalContext* globalCtx, SkelAnimeCurve* skelCurve,
void SkelCurve_Draw(Actor* actor, GlobalContext* globalCtx, SkelCurve* skelCurve,
OverrideCurveLimbDraw overrideLimbDraw, PostCurveLimbDraw postLimbDraw, s32 lod, Actor* thisx) {
if (skelCurve->transforms != NULL) {
if (skelCurve->jointTable != NULL) {
SkelCurve_DrawLimb(globalCtx, 0, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
}
}

View File

@ -627,9 +627,7 @@ void SkelAnime_GetFrameData(AnimationHeader* animation, s32 frame, s32 limbCount
for (i = 0; i < limbCount; i++) {
// Debug prints here, this is needed to prevent loop unrolling
if (0) {
if (0) {};
}
if ((frameTable == NULL) || (jointIndices == NULL) || (dynamicData == NULL)) {}
frameTable->x = jointIndices->x >= staticIndexMax ? dynamicData[jointIndices->x] : frameData[jointIndices->x];
frameTable->y = jointIndices->y >= staticIndexMax ? dynamicData[jointIndices->y] : frameData[jointIndices->y];
frameTable->z = jointIndices->z >= staticIndexMax ? dynamicData[jointIndices->z] : frameData[jointIndices->z];

View File

@ -32,15 +32,15 @@ void func_809DD2F8(GlobalContext* globalCtx);
void func_809DD934(Boss02* this, GlobalContext* globalCtx);
void func_809DEAC4(Boss02* this, GlobalContext* globalCtx);
static u8 D_809E0420;
static u8 D_809E0421;
static u8 D_809E0422;
static Boss02* D_809E0424;
static Boss02* D_809E0428;
static Boss02* D_809E042C;
static u8 D_809E0430;
static DoorWarp1* D_809E0434;
static Boss02Effects D_809E0438[150];
u8 D_809E0420;
u8 D_809E0421;
u8 D_809E0422;
Boss02* D_809E0424;
Boss02* D_809E0428;
Boss02* D_809E042C;
u8 D_809E0430;
DoorWarp1* D_809E0434;
Boss02Effects D_809E0438[150];
static DamageTable sDamageTable1 = {
/* Deku Nut */ DMG_ENTRY(0, 0x0),

View File

@ -38,59 +38,64 @@ const ActorInit Demo_Effect_InitVars = {
};
void DemoEffect_Init(Actor* thisx, GlobalContext* globalCtx) {
static s16 D_808CE2C0[] = {
static s16 sEffectTypeObjects[] = {
OBJECT_EFC_TW, OBJECT_EFC_TW, OBJECT_EFC_TW, OBJECT_EFC_TW, GAMEPLAY_KEEP,
GAMEPLAY_KEEP, GAMEPLAY_KEEP, GAMEPLAY_KEEP, GAMEPLAY_KEEP,
};
s32 pad;
DemoEffect* this = THIS;
s32 sp3C = DEMOEFFECT_GET_FF(&this->actor);
s32 phi_v1;
s32 type = DEMO_EFFECT_GET_TYPE(&this->actor);
s32 objectIndex;
s32 pad2;
Color_RGB8 sp24[] = {
Color_RGB8 colors[] = {
{ 200, 200, 0 }, { 255, 40, 100 }, { 50, 255, 0 }, { 0, 0, 255 }, { 255, 255, 80 },
};
if (D_808CE2C0[sp3C] == 1) {
phi_v1 = 0;
if (sEffectTypeObjects[type] == GAMEPLAY_KEEP) {
objectIndex = 0;
} else {
phi_v1 = Object_GetIndex(&globalCtx->objectCtx, D_808CE2C0[sp3C]);
objectIndex = Object_GetIndex(&globalCtx->objectCtx, sEffectTypeObjects[type]);
}
if (phi_v1 >= 0) {
this->unk_164 = phi_v1;
if (objectIndex < 0) {
// assert on debug
} else {
this->initObjectIndex = objectIndex;
}
Actor_SetScale(&this->actor, 0.2f);
switch (sp3C) {
case 0:
case 1:
switch (type) {
case DEMO_EFFECT_TYPE_0:
case DEMO_EFFECT_TYPE_1:
this->actor.flags |= ACTOR_FLAG_2000000;
case 2:
case 3:
this->unk_174 = func_808CDFF8;
this->unk_170 = func_808CD998;
this->unk_168[0] = 0;
this->unk_168[1] = 100;
this->unk_168[2] = 255;
case DEMO_EFFECT_TYPE_2:
case DEMO_EFFECT_TYPE_3:
this->initDrawFunc = func_808CDFF8;
this->initActionFunc = func_808CD998;
this->envXluColor[0] = 0;
this->envXluColor[1] = 100;
this->envXluColor[2] = 255;
SkelCurve_Clear(&this->skelCurve);
this->unk_16C = 0;
this->timer = 0;
break;
case 4:
case 5:
case 6:
case 7:
case 8:
this->unk_168[0] = sp24[sp3C - 4].r;
this->unk_168[1] = sp24[sp3C - 4].g;
this->unk_168[2] = sp24[sp3C - 4].b;
case DEMO_EFFECT_TYPE_4:
case DEMO_EFFECT_TYPE_5:
case DEMO_EFFECT_TYPE_6:
case DEMO_EFFECT_TYPE_7:
case DEMO_EFFECT_TYPE_8:
this->envXluColor[0] = colors[type - 4].r;
this->envXluColor[1] = colors[type - 4].g;
this->envXluColor[2] = colors[type - 4].b;
Actor_SetScale(&this->actor, 0.0f);
this->unk_174 = func_808CE078;
this->unk_170 = func_808CDDE0;
this->unk_16C = 0;
this->initDrawFunc = func_808CE078;
this->initActionFunc = func_808CDDE0;
this->timer = 0;
break;
default:
break;
}
@ -98,33 +103,32 @@ void DemoEffect_Init(Actor* thisx, GlobalContext* globalCtx) {
this->actionFunc = func_808CD940;
}
u8 D_808CE2D4[] = {
1, 1, 2, 0, 1, 1, 2, 0, 1, 2, 0, 2, 1, 0, 1, 0, 2, 0, 2, 2, 0,
};
void DemoEffect_Destroy(Actor* thisx, GlobalContext* globalCtx) {
DemoEffect* this = THIS;
switch (DEMOEFFECT_GET_FF(&this->actor)) {
case 0:
case 1:
case 2:
case 3:
switch (DEMO_EFFECT_GET_TYPE(&this->actor)) {
case DEMO_EFFECT_TYPE_0:
case DEMO_EFFECT_TYPE_1:
case DEMO_EFFECT_TYPE_2:
case DEMO_EFFECT_TYPE_3:
SkelCurve_Destroy(globalCtx, &this->skelCurve);
break;
default:
break;
}
}
void func_808CD940(DemoEffect* this, GlobalContext* globalCtx) {
if (Object_IsLoaded(&globalCtx->objectCtx, this->unk_164)) {
this->actor.objBankIndex = this->unk_164;
this->actor.draw = this->unk_174;
this->actionFunc = this->unk_170;
if (Object_IsLoaded(&globalCtx->objectCtx, this->initObjectIndex)) {
this->actor.objBankIndex = this->initObjectIndex;
this->actor.draw = this->initDrawFunc;
this->actionFunc = this->initActionFunc;
}
}
void func_808CD998(DemoEffect* this, GlobalContext* globalCtx) {
s32 sp34 = DEMOEFFECT_GET_FF(&this->actor);
s32 type = DEMO_EFFECT_GET_TYPE(&this->actor);
if (SkelCurve_Init(globalCtx, &this->skelCurve, &object_efc_tw_Skel_0012E8, &object_efc_tw_CurveAnim_000050)) {}
@ -132,20 +136,20 @@ void func_808CD998(DemoEffect* this, GlobalContext* globalCtx) {
SkelCurve_Update(globalCtx, &this->skelCurve);
this->actionFunc = func_808CDCEC;
switch (sp34) {
case 0:
switch (type) {
case DEMO_EFFECT_TYPE_0:
Actor_SetScale(&this->actor, 0.16800001f);
break;
case 1:
case DEMO_EFFECT_TYPE_1:
Actor_SetScale(&this->actor, 0.08400001f);
break;
case 2:
case DEMO_EFFECT_TYPE_2:
Actor_SetScale(&this->actor, 0.16800001f);
break;
case 3:
case DEMO_EFFECT_TYPE_3:
Actor_SetScale(&this->actor, 0.28f);
break;
@ -155,53 +159,57 @@ void func_808CD998(DemoEffect* this, GlobalContext* globalCtx) {
}
}
void func_808CDAD0(f32 arg0) {
void func_808CDAD0(f32 alphaScale) {
static u8 sAlphaTypes[] = { 1, 1, 2, 0, 1, 1, 2, 0, 1, 2, 0, 2, 1, 0, 1, 0, 2, 0, 2, 2, 0 };
Vtx* vtx = Lib_SegmentedToVirtual(object_efc_tw_Vtx_000060);
s32 i;
Vtx* temp_v0 = Lib_SegmentedToVirtual(object_efc_tw_Vtx_000060);
u8 sp24[3];
u8 alphas[3];
sp24[0] = 0;
sp24[1] = (s8)(202.0f * arg0);
sp24[2] = (s8)(255.0f * arg0);
alphas[0] = 0;
alphas[1] = (s32)(202.0f * alphaScale);
alphas[2] = (s32)(255.0f * alphaScale);
for (i = 0; i < ARRAY_COUNT(D_808CE2D4); i++) {
if (D_808CE2D4[i] != 0) {
temp_v0[i].v.cn[3] = sp24[D_808CE2D4[i]];
for (i = 0; i < ARRAY_COUNT(sAlphaTypes); i++) {
if (sAlphaTypes[i] != 0) {
vtx[i].v.cn[3] = alphas[sAlphaTypes[i]];
}
}
}
void func_808CDBDC(DemoEffect* this, GlobalContext* globalCtx) {
s32 params = DEMOEFFECT_GET_FF(&this->actor);
f32 temp_f0;
f32 temp_f12;
s32 type = DEMO_EFFECT_GET_TYPE(&this->actor);
f32 scale;
f32 alphaScale;
this->unk_16C++;
if (this->unk_16C <= 100) {
temp_f12 = (100 - this->unk_16C) * 0.01f;
temp_f0 = temp_f12 * 0.14f;
this->timer++;
if (this->timer <= 100) {
alphaScale = (100 - this->timer) * 0.01f;
scale = alphaScale * 0.14f;
switch (params) {
case 0:
temp_f0 *= 1.2f;
switch (type) {
case DEMO_EFFECT_TYPE_0:
scale *= 1.2f;
break;
case 1:
temp_f0 *= 0.6f;
case DEMO_EFFECT_TYPE_1:
scale *= 0.6f;
break;
case 2:
temp_f0 *= 1.2f;
case DEMO_EFFECT_TYPE_2:
scale *= 1.2f;
break;
case 3:
temp_f0 *= 2.0f;
case DEMO_EFFECT_TYPE_3:
scale *= 2.0f;
break;
default:
break;
}
this->actor.scale.x = temp_f0;
this->actor.scale.z = temp_f0;
func_808CDAD0(temp_f12);
this->actor.scale.x = scale;
this->actor.scale.z = scale;
func_808CDAD0(alphaScale);
func_800B8FE8(&this->actor, NA_SE_EV_TIMETRIP_LIGHT - SFX_FLAG);
} else {
func_808CDAD0(1.0f);
@ -215,14 +223,14 @@ void func_808CDCEC(DemoEffect* this, GlobalContext* globalCtx) {
if (SkelCurve_Update(globalCtx, &this->skelCurve)) {
SkelCurve_SetAnim(&this->skelCurve, &object_efc_tw_CurveAnim_000050, 1.0f, 60.0f, 59.0f, 0.0f);
this->actionFunc = func_808CDBDC;
this->unk_16C = 0;
this->timer = 0;
}
}
void func_808CDD70(DemoEffect* this, GlobalContext* globalCtx) {
Actor_SetScale(&this->actor, this->actor.scale.x - 0.02f);
this->unk_16C++;
this->timer++;
if (this->actor.scale.x < 0.02f) {
Actor_MarkForDeath(&this->actor);
}
@ -231,8 +239,8 @@ void func_808CDD70(DemoEffect* this, GlobalContext* globalCtx) {
void func_808CDDE0(DemoEffect* this, GlobalContext* globalCtx) {
Actor_SetScale(&this->actor, (this->actor.scale.x * 0.5f) + 0.2f);
this->unk_16C++;
if (this->unk_16C >= 3) {
this->timer++;
if (this->timer >= 3) {
this->actionFunc = func_808CDD70;
}
}
@ -243,29 +251,28 @@ void DemoEffect_Update(Actor* thisx, GlobalContext* globalCtx) {
this->actionFunc(this, globalCtx);
}
s32 func_808CDE78(GlobalContext* globalCtx, SkelAnimeCurve* skelCuve, s32 limbIndex, Actor* thisx) {
s32 func_808CDE78(GlobalContext* globalCtx, SkelCurve* skelCurve, s32 limbIndex, Actor* thisx) {
s32 pad;
DemoEffect* this = THIS;
u32 sp4C = globalCtx->gameplayFrames;
u32 frames = globalCtx->gameplayFrames;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C2DC(globalCtx->state.gfxCtx);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, 255);
gDPSetEnvColor(POLY_XLU_DISP++, this->unk_168[0], this->unk_168[1], this->unk_168[2], 255);
gDPSetEnvColor(POLY_XLU_DISP++, this->envXluColor[0], this->envXluColor[1], this->envXluColor[2], 255);
gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (sp4C * 6) % 1024, 255 - ((sp4C * 16) % 256), 0x100, 0x40,
1, (sp4C * 4) % 512, 127 - ((sp4C * 12) % 128), 0x80, 0x20));
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (frames * 6) % 1024, 255 - ((frames * 16) % 256), 0x100,
0x40, 1, (frames * 4) % 512, 127 - ((frames * 12) % 128), 0x80, 0x20));
CLOSE_DISPS(globalCtx->state.gfxCtx);
if (limbIndex == 0) {
LimbTransform* transform = skelCuve->transforms;
s16* transform = skelCurve->jointTable[0];
transform->scale.x = 0x400;
transform->scale.y = 0x400;
transform->scale.z = transform->scale.x;
transform[2] = transform[0] = 1024;
transform[1] = 1024;
}
return true;
@ -288,24 +295,24 @@ void func_808CDFF8(Actor* thisx, GlobalContext* globalCtx) {
void func_808CE078(Actor* thisx, GlobalContext* globalCtx2) {
GlobalContext* globalCtx = globalCtx2;
DemoEffect* this = THIS;
s16 sp46 = (this->unk_16C * 0x400) & 0xFFFF;
s16 zRot = (this->timer * 0x400) & 0xFFFF;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C2DC(globalCtx->state.gfxCtx);
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 255, 255);
gDPSetEnvColor(POLY_XLU_DISP++, this->unk_168[0], this->unk_168[1], this->unk_168[2], 255);
gDPSetEnvColor(POLY_XLU_DISP++, this->envXluColor[0], this->envXluColor[1], this->envXluColor[2], 255);
Matrix_Mult(&globalCtx->billboardMtxF, MTXMODE_APPLY);
Matrix_Push();
Matrix_RotateZS(sp46, MTXMODE_APPLY);
Matrix_RotateZS(zRot, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_023288);
Matrix_Pop();
Matrix_RotateZS(sp46 * -1, MTXMODE_APPLY);
Matrix_RotateZS(-zRot, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_023288);

View File

@ -2,24 +2,35 @@
#define Z_DEMO_EFFECT_H
#include "global.h"
#include "z64curve.h"
struct DemoEffect;
typedef void (*DemoEffectActionFunc)(struct DemoEffect*, GlobalContext*);
typedef void (*DemoEffectUnkFunc)(struct DemoEffect*, GlobalContext*);
typedef void (*DemoEffectUnkFunc2)(Actor*, GlobalContext*);
#define DEMOEFFECT_GET_FF(thisx) ((thisx)->params & 0xFF)
#define DEMO_EFFECT_GET_TYPE(thisx) ((thisx)->params & 0xFF)
typedef enum {
/* 0 */ DEMO_EFFECT_TYPE_0,
/* 1 */ DEMO_EFFECT_TYPE_1,
/* 2 */ DEMO_EFFECT_TYPE_2,
/* 3 */ DEMO_EFFECT_TYPE_3,
/* 4 */ DEMO_EFFECT_TYPE_4,
/* 5 */ DEMO_EFFECT_TYPE_5,
/* 6 */ DEMO_EFFECT_TYPE_6,
/* 7 */ DEMO_EFFECT_TYPE_7,
/* 8 */ DEMO_EFFECT_TYPE_8
} DemoEffectType;
typedef struct DemoEffect {
/* 0x0000 */ Actor actor;
/* 0x0144 */ SkelAnimeCurve skelCurve;
/* 0x0164 */ u8 unk_164;
/* 0x0165 */ UNK_TYPE1 unk_165[3];
/* 0x0168 */ u8 unk_168[3];
/* 0x016C */ s16 unk_16C;
/* 0x0170 */ DemoEffectUnkFunc unk_170;
/* 0x0174 */ DemoEffectUnkFunc2 unk_174;
/* 0x0144 */ SkelCurve skelCurve;
/* 0x0164 */ u8 initObjectIndex;
/* 0x0165 */ u8 primXluColor[3];
/* 0x0168 */ u8 envXluColor[3];
/* 0x016C */ s16 timer;
/* 0x0170 */ DemoEffectActionFunc initActionFunc;
/* 0x0174 */ ActorFunc initDrawFunc;
/* 0x0178 */ DemoEffectActionFunc actionFunc;
} DemoEffect; // size = 0x17C

View File

@ -52,6 +52,11 @@ static TransformUpdateIndex* sBoxLightAnimations[] = {
&gBoxLightChildCurveAnim,
};
typedef enum {
/* 0x00 */ DEMO_TRE_LGT_ACTION_WAIT, // wait until animation is needed
/* 0x01 */ DEMO_TRE_LGT_ACTION_ANIMATE
} DemoTreLgtAction;
static DemoTreLgtActionFunc sActionFuncs[] = {
DemoTreLgt_Wait,
DemoTreLgt_Animate,
@ -101,7 +106,7 @@ void DemoTreLgt_SetupAnimate(DemoTreLgt* this, GlobalContext* globalCtx, f32 fra
}
void DemoTreLgt_Animate(DemoTreLgt* this, GlobalContext* globalCtx) {
f32 curFrame = this->skelCurve.animCurFrame;
f32 curFrame = this->skelCurve.curFrame;
if (curFrame < D_808E1490[this->animationType].unk4) {
this->colorAlpha1 = 255;
@ -136,7 +141,7 @@ void DemoTreLgt_Update(Actor* thisx, GlobalContext* globalCtx) {
sActionFuncs[this->action](this, globalCtx);
}
s32 DemoTreLgt_OverrideLimbDraw(GlobalContext* globalCtx, SkelAnimeCurve* skelCuve, s32 limbIndex, Actor* thisx) {
s32 DemoTreLgt_OverrideLimbDraw(GlobalContext* globalCtx, SkelCurve* skelCuve, s32 limbIndex, Actor* thisx) {
s32 pad;
DemoTreLgt* this = THIS;
@ -148,8 +153,8 @@ s32 DemoTreLgt_OverrideLimbDraw(GlobalContext* globalCtx, SkelAnimeCurve* skelCu
if (limbIndex == OBJECT_BOX_LIGHT_LIMB_01) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 180, this->colorAlpha1);
} else if (limbIndex == OBJECT_BOX_LIGHT_LIMB_13 || limbIndex == OBJECT_BOX_LIGHT_LIMB_07 ||
limbIndex == OBJECT_BOX_LIGHT_LIMB_04 || limbIndex == OBJECT_BOX_LIGHT_LIMB_10) {
} else if ((limbIndex == OBJECT_BOX_LIGHT_LIMB_13) || (limbIndex == OBJECT_BOX_LIGHT_LIMB_07) ||
(limbIndex == OBJECT_BOX_LIGHT_LIMB_04) || (limbIndex == OBJECT_BOX_LIGHT_LIMB_10)) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 180, this->colorAlpha2);
}

View File

@ -2,6 +2,7 @@
#define Z_DEMO_TRE_LGT_H
#include "global.h"
#include "z64curve.h"
struct DemoTreLgt;
@ -9,7 +10,7 @@ typedef void (*DemoTreLgtActionFunc)(struct DemoTreLgt* this, GlobalContext* glo
typedef struct DemoTreLgt {
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnimeCurve skelCurve;
/* 0x144 */ SkelCurve skelCurve;
/* 0x164 */ s32 action;
/* 0x168 */ u32 colorAlpha1;
/* 0x16C */ u32 colorAlpha2;
@ -17,11 +18,6 @@ typedef struct DemoTreLgt {
/* 0x174 */ s32 animationType;
} DemoTreLgt; // size = 0x178
typedef enum {
/* 0x00 */ DEMO_TRE_LGT_ACTION_WAIT, // wait until animation is needed
/* 0x01 */ DEMO_TRE_LGT_ACTION_ANIMATE
} DemoTreLgtAction;
extern const ActorInit Demo_Tre_Lgt_InitVars;
#endif // Z_DEMO_TRE_LGT_H

View File

@ -126,7 +126,7 @@ void func_80867C8C(func_80867BDC_a0* arg0, GlobalContext* globalCtx) {
for (i = 0; i < temp_s6; i++) {
f32 temp_f0 = (f32)i / temp_s6;
s16 temp_s0 = ((f32)arg0->unk_18 - arg0->unk_1C) * temp_f0 + arg0->unk_1C;
f32 temp_f24 = 1.0f - (temp_s0 * 0.011764706f);
f32 temp_f24 = 1.0f - (temp_s0 * (1 / 85.0f));
f32 temp_f26 = Rand_ZeroOne() * 0.03f * temp_f0 * temp_f24;
f32 temp_f28;
f32 temp_f30 = Math_SinS(temp_s0 * 0x9A6) * 45.0f + arg0->pos.x;
@ -186,9 +186,9 @@ void EnBox_ClipToGround(EnBox* this, GlobalContext* globalCtx) {
}
void EnBox_Init(Actor* thisx, GlobalContext* globalCtx) {
s16 cutsceneIdx;
EnBox* this = (EnBox*)thisx;
s32 pad;
EnBox* this = THIS;
s16 cutsceneIdx;
CollisionHeader* colHeader;
f32 animFrame;
f32 animFrameEnd;
@ -227,7 +227,7 @@ void EnBox_Init(Actor* thisx, GlobalContext* globalCtx) {
EnBox_SetupAction(this, EnBox_Open);
this->movementFlags |= ENBOX_MOVE_STICK_TO_GROUND;
animFrame = animFrameEnd;
} else if ((this->type == ENBOX_TYPE_BIG_SWITCH_FLAG_FALL || this->type == ENBOX_TYPE_SMALL_SWITCH_FLAG_FALL) &&
} else if (((this->type == ENBOX_TYPE_BIG_SWITCH_FLAG_FALL) || (this->type == ENBOX_TYPE_SMALL_SWITCH_FLAG_FALL)) &&
!Flags_GetSwitch(globalCtx, this->switchFlag)) {
func_800C62BC(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
if (Rand_ZeroOne() < 0.5f) {
@ -238,7 +238,7 @@ void EnBox_Init(Actor* thisx, GlobalContext* globalCtx) {
this->alpha = 0;
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
this->dyna.actor.flags |= ACTOR_FLAG_10;
} else if ((this->type == ENBOX_TYPE_BIG_ROOM_CLEAR || this->type == ENBOX_TYPE_SMALL_ROOM_CLEAR) &&
} else if (((this->type == ENBOX_TYPE_BIG_ROOM_CLEAR) || (this->type == ENBOX_TYPE_SMALL_ROOM_CLEAR)) &&
!Flags_GetClear(globalCtx, this->dyna.actor.room)) {
EnBox_SetupAction(this, EnBox_AppearOnRoomClear);
func_800C62BC(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
@ -250,9 +250,9 @@ void EnBox_Init(Actor* thisx, GlobalContext* globalCtx) {
this->alpha = 0;
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
this->dyna.actor.flags |= ACTOR_FLAG_10;
} else if (this->type == ENBOX_TYPE_BIG_SONG_ZELDAS_LULLABY || this->type == ENBOX_TYPE_BIG_SONG_SUNS) {
} else if ((this->type == ENBOX_TYPE_BIG_SONG_ZELDAS_LULLABY) || (this->type == ENBOX_TYPE_BIG_SONG_SUNS)) {
} else if ((this->type == ENBOX_TYPE_BIG_SWITCH_FLAG || this->type == ENBOX_TYPE_SMALL_SWITCH_FLAG) &&
} else if (((this->type == ENBOX_TYPE_BIG_SWITCH_FLAG) || (this->type == ENBOX_TYPE_SMALL_SWITCH_FLAG)) &&
!Flags_GetSwitch(globalCtx, this->switchFlag)) {
EnBox_SetupAction(this, EnBox_AppearSwitchFlag);
func_800C62BC(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
@ -265,7 +265,7 @@ void EnBox_Init(Actor* thisx, GlobalContext* globalCtx) {
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
this->dyna.actor.flags |= ACTOR_FLAG_10;
} else {
if (this->type == ENBOX_TYPE_BIG_INVISIBLE || this->type == ENBOX_TYPE_SMALL_INVISIBLE) {
if ((this->type == ENBOX_TYPE_BIG_INVISIBLE) || (this->type == ENBOX_TYPE_SMALL_INVISIBLE)) {
this->dyna.actor.flags |= ACTOR_FLAG_80;
}
EnBox_SetupAction(this, EnBox_WaitOpen);
@ -273,7 +273,7 @@ void EnBox_Init(Actor* thisx, GlobalContext* globalCtx) {
this->movementFlags |= ENBOX_MOVE_STICK_TO_GROUND;
}
if (this->getItem == GI_STRAY_FAIRY && !Flags_GetTreasure(globalCtx, ENBOX_GET_CHEST_FLAG(&this->dyna.actor))) {
if ((this->getItem == GI_STRAY_FAIRY) && !Flags_GetTreasure(globalCtx, ENBOX_GET_CHEST_FLAG(&this->dyna.actor))) {
this->dyna.actor.flags |= ACTOR_FLAG_10;
}
@ -307,7 +307,7 @@ void EnBox_Init(Actor* thisx, GlobalContext* globalCtx) {
}
void EnBox_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnBox* this = (EnBox*)thisx;
EnBox* this = THIS;
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
}
@ -414,7 +414,7 @@ void EnBox_AppearOnRoomClear(EnBox* this, GlobalContext* globalCtx) {
}
void func_80868AFC(EnBox* this, GlobalContext* globalCtx) {
if (func_800F22C4(this->cutsceneIdxA, &this->dyna.actor) != 0 || this->unk_1A0 != 0) {
if ((func_800F22C4(this->cutsceneIdxA, &this->dyna.actor) != 0) || (this->unk_1A0 != 0)) {
EnBox_SetupAction(this, func_80868B74);
this->unk_1A0 = 0;
func_80867FBC(&this->unk_1F4, globalCtx, (this->movementFlags & ENBOX_MOVE_0x80) != 0);
@ -433,7 +433,7 @@ void func_80868B74(EnBox* this, GlobalContext* globalCtx) {
this->dyna.actor.world.pos.y += 1.25f;
}
this->unk_1A0++;
if (this->cutsceneIdxA != -1 && ActorCutscene_GetCurrentIndex() == this->cutsceneIdxA) {
if ((this->cutsceneIdxA != -1) && ActorCutscene_GetCurrentIndex() == this->cutsceneIdxA) {
if (this->unk_1A0 == 2) {
func_800B724C(globalCtx, &this->dyna.actor, 4);
} else if (this->unk_1A0 == 22) {
@ -461,8 +461,8 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) {
this->alpha = 255;
this->movementFlags |= ENBOX_MOVE_IMMOBILE;
if (this->unk_1EC != 0 && (this->cutsceneIdxB < 0 || ActorCutscene_GetCurrentIndex() == this->cutsceneIdxB ||
ActorCutscene_GetCurrentIndex() == -1)) {
if ((this->unk_1EC != 0) && ((this->cutsceneIdxB < 0) || (ActorCutscene_GetCurrentIndex() == this->cutsceneIdxB) ||
(ActorCutscene_GetCurrentIndex() == -1))) {
if (this->unk_1EC < 0) {
animHeader = &gBoxChestOpenAnim;
playbackSpeed = 1.5f;
@ -489,7 +489,7 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) {
if (this->getItem == GI_STRAY_FAIRY) {
this->movementFlags |= ENBOX_MOVE_0x20;
} else {
if (this->getItem == GI_HEART_PIECE || this->getItem == GI_BOTTLE) {
if ((this->getItem == GI_HEART_PIECE) || (this->getItem == GI_BOTTLE)) {
Flags_SetCollectible(globalCtx, this->collectableFlag);
}
Flags_SetTreasure(globalCtx, ENBOX_GET_CHEST_FLAG(&this->dyna.actor));
@ -499,14 +499,14 @@ void EnBox_WaitOpen(EnBox* this, GlobalContext* globalCtx) {
Actor_OffsetOfPointInActorCoords(&this->dyna.actor, &offset, &player->actor.world.pos);
if (offset.z > -50.0f && offset.z < 0.0f && fabsf(offset.y) < 10.0f && fabsf(offset.x) < 20.0f &&
Player_IsFacingActor(&this->dyna.actor, 0x3000, globalCtx)) {
if ((this->getItem == GI_HEART_PIECE || this->getItem == GI_BOTTLE) &&
if (((this->getItem == GI_HEART_PIECE) || (this->getItem == GI_BOTTLE)) &&
Flags_GetCollectible(globalCtx, this->collectableFlag)) {
this->getItem = GI_RECOVERY_HEART;
}
if (this->getItem == GI_MASK_CAPTAIN && INV_CONTENT(ITEM_MASK_CAPTAIN) == ITEM_MASK_CAPTAIN) {
if ((this->getItem == GI_MASK_CAPTAIN) && (INV_CONTENT(ITEM_MASK_CAPTAIN) == ITEM_MASK_CAPTAIN)) {
this->getItem = GI_RECOVERY_HEART;
}
if (this->getItem == GI_MASK_GIANT && INV_CONTENT(ITEM_MASK_GIANT) == ITEM_MASK_GIANT) {
if ((this->getItem == GI_MASK_GIANT) && (INV_CONTENT(ITEM_MASK_GIANT) == ITEM_MASK_GIANT)) {
this->getItem = GI_RECOVERY_HEART;
}
Actor_PickUpNearby(&this->dyna.actor, globalCtx, -this->getItem);
@ -568,7 +568,7 @@ void EnBox_Open(EnBox* this, GlobalContext* globalCtx) {
}
if (WaterBox_GetSurfaceImpl(globalCtx, &globalCtx->colCtx, this->dyna.actor.world.pos.x,
this->dyna.actor.world.pos.z, &waterSurface, &waterBox, &bgId) &&
this->dyna.actor.floorHeight < waterSurface) {
(this->dyna.actor.floorHeight < waterSurface)) {
EffectSsBubble_Spawn(globalCtx, &this->dyna.actor.world.pos, 5.0f, 2.0f, 20.0f, 0.3f);
}
}
@ -598,13 +598,13 @@ void EnBox_SpawnIceSmoke(EnBox* this, GlobalContext* globalCtx) {
}
void EnBox_Update(Actor* thisx, GlobalContext* globalCtx) {
EnBox* this = (EnBox*)thisx;
EnBox* this = THIS;
if (this->movementFlags & ENBOX_MOVE_STICK_TO_GROUND) {
this->movementFlags &= ~ENBOX_MOVE_STICK_TO_GROUND;
EnBox_ClipToGround(this, globalCtx);
}
if (this->getItem == GI_STRAY_FAIRY && !Flags_GetTreasure(globalCtx, ENBOX_GET_CHEST_FLAG(&this->dyna.actor))) {
if ((this->getItem == GI_STRAY_FAIRY) && !Flags_GetTreasure(globalCtx, ENBOX_GET_CHEST_FLAG(&this->dyna.actor))) {
globalCtx->actorCtx.unk5 |= 8;
}
this->actionFunc(this, globalCtx);
@ -616,8 +616,8 @@ void EnBox_Update(Actor* thisx, GlobalContext* globalCtx) {
Actor_UpdateBgCheckInfo(globalCtx, &this->dyna.actor, 0.0f, 0.0f, 0.0f, 0x1C);
}
Actor_SetFocus(&this->dyna.actor, 40.0f);
if (this->getItem == GI_ICE_TRAP && this->actionFunc == EnBox_Open && this->skelAnime.curFrame > 45.0f &&
this->iceSmokeTimer < 100) {
if ((this->getItem == GI_ICE_TRAP) && (this->actionFunc == EnBox_Open) && (this->skelAnime.curFrame > 45.0f) &&
(this->iceSmokeTimer < 100)) {
EnBox_SpawnIceSmoke(this, globalCtx);
}
if (this->unk_1F4.unk_0C != NULL) {
@ -626,8 +626,8 @@ void EnBox_Update(Actor* thisx, GlobalContext* globalCtx) {
}
void EnBox_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx, Gfx** gfx) {
EnBox* this = THIS;
s32 pad;
EnBox* this = THIS;
if (limbIndex == OBJECT_BOX_CHEST_LIMB_01) {
gSPMatrix((*gfx)++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
@ -688,16 +688,17 @@ Gfx* EnBox_SetRenderMode3(GraphicsContext* gfxCtx) {
}
void EnBox_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnBox* this = (EnBox*)thisx;
s32 pad;
EnBox* this = THIS;
OPEN_DISPS(globalCtx->state.gfxCtx);
if (this->unk_1F4.unk_10 != NULL) {
this->unk_1F4.unk_10(&this->unk_1F4, globalCtx);
}
if ((this->alpha == 255 && this->type != ENBOX_TYPE_BIG_INVISIBLE && this->type != ENBOX_TYPE_SMALL_INVISIBLE) ||
if (((this->alpha == 255) && (this->type != ENBOX_TYPE_BIG_INVISIBLE) &&
(this->type != ENBOX_TYPE_SMALL_INVISIBLE)) ||
(!CHECK_FLAG_ALL(this->dyna.actor.flags, ACTOR_FLAG_80) &&
(this->type == ENBOX_TYPE_BIG_INVISIBLE || this->type == ENBOX_TYPE_SMALL_INVISIBLE))) {
((this->type == ENBOX_TYPE_BIG_INVISIBLE) || (this->type == ENBOX_TYPE_SMALL_INVISIBLE)))) {
gDPPipeSync(POLY_OPA_DISP++);
gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
gSPSegment(POLY_OPA_DISP++, 0x08, EnBox_SetRenderMode1(globalCtx->state.gfxCtx));
@ -708,7 +709,7 @@ void EnBox_Draw(Actor* thisx, GlobalContext* globalCtx) {
gDPPipeSync(POLY_XLU_DISP++);
func_8012C2DC(globalCtx->state.gfxCtx);
gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha);
if (this->type == ENBOX_TYPE_BIG_INVISIBLE || this->type == ENBOX_TYPE_SMALL_INVISIBLE) {
if ((this->type == ENBOX_TYPE_BIG_INVISIBLE) || (this->type == ENBOX_TYPE_SMALL_INVISIBLE)) {
gSPSegment(POLY_XLU_DISP++, 0x08, EnBox_SetRenderMode3(globalCtx->state.gfxCtx));
} else {
gSPSegment(POLY_XLU_DISP++, 0x08, EnBox_SetRenderMode2(globalCtx->state.gfxCtx));

View File

@ -36,6 +36,13 @@ typedef enum {
/* 12 */ ENBOX_TYPE_SMALL_SWITCH_FLAG // small, appear on switch flag set
} EnBoxType;
#define ENBOX_GET_TYPE(thisx) (((thisx)->params >> 12) & 0xF)
#define ENBOX_GET_ITEM(thisx) (((thisx)->params >> 5) & 0x7F)
#define ENBOX_GET_CHEST_FLAG(thisx) ((thisx)->params & 0x1F)
#define ENBOX_GET_SWITCH_FLAG(thisx) ((thisx)->world.rot.z)
// Codegen in EnTorch_Init() requires leaving out the & 0x7F for `item`
#define ENBOX_PARAMS(type, item, chestFlag) ((((type) & 0xF) << 12) | ((item) << 5) | ((chestFlag) & 0x1F))
typedef struct EnBox {
/* 0x0000 */ DynaPolyActor dyna;
/* 0x015C */ SkelAnime skelAnime;
@ -61,9 +68,5 @@ typedef struct EnBox {
extern const ActorInit En_Box_InitVars;
#define ENBOX_GET_TYPE(thisx) (((thisx)->params >> 12) & 0xF)
#define ENBOX_GET_ITEM(thisx) (((thisx)->params >> 5) & 0x7F)
#define ENBOX_GET_CHEST_FLAG(thisx) ((thisx)->params & 0x1F)
#define ENBOX_GET_SWITCH_FLAG(thisx) ((thisx)->world.rot.z)
#endif // Z_EN_BOX_H

View File

@ -5,6 +5,7 @@
*/
#include "z_en_torch.h"
#include "overlays/actors/ovl_En_Box/z_en_box.h"
#define FLAGS 0x00000000
@ -17,7 +18,9 @@ const ActorInit En_Torch_InitVars = {
(ActorFunc)EnTorch_Init, (ActorFunc)NULL, (ActorFunc)NULL, (ActorFunc)NULL,
};
static u8 sChestContents[] = { 0x02, 0x04, 0x05, 0x06, 0x36, 0x3A, 0x14, 0x14 };
static u8 sChestContents[] = {
GI_RUPEE_BLUE, GI_RUPEE_RED, GI_RUPEE_PURPLE, GI_RUPEE_SILVER, GI_BOMBCHUS_1, GI_BOMBCHUS_5, GI_BOMBS_1, GI_BOMBS_1,
};
void EnTorch_Init(Actor* thisx, GlobalContext* globalCtx) {
EnTorch* this = THIS;
@ -25,6 +28,6 @@ void EnTorch_Init(Actor* thisx, GlobalContext* globalCtx) {
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_BOX, this->actor.world.pos.x, this->actor.world.pos.y,
this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0,
(sChestContents[(returnData >> 0x5) & 0x7] << 0x5) | 0x5000 | (returnData & 0x1F));
ENBOX_PARAMS(ENBOX_TYPE_SMALL, sChestContents[(returnData >> 0x5) & 0x7], returnData));
Actor_MarkForDeath(&this->actor);
}

View File

@ -1661,8 +1661,8 @@
0x800F21CC:("func_800F21CC",),
0x800F22C4:("func_800F22C4",),
0x800F23C4:("ActorCutscene_SetReturnCamera",),
0x800F23E0:("func_800F23E0",),
0x800F2478:("func_800F2478",),
0x800F23E0:("Curve_CubicHermiteSpline",),
0x800F2478:("Curve_Interpolate",),
0x800F2620:("SkelCurve_Clear",),
0x800F2650:("SkelCurve_Init",),
0x800F26C0:("SkelCurve_Destroy",),

View File

@ -6826,9 +6826,8 @@
0x808CD5E8:("D_808CD5E8","f32","",0x4),
0x808CE290:("Demo_Effect_InitVars","UNK_TYPE1","",0x1),
0x808CE2B0:("D_808CE2B0","UNK_TYPE4","",0x4),
0x808CE2C0:("D_808CE2C0","UNK_TYPE1","",0x1),
0x808CE2D4:("D_808CE2D4","UNK_TYPE1","",0x1),
0x808CE2D5:("D_808CE2D5","UNK_TYPE1","",0x1),
0x808CE2C0:("sEffectTypeObjects","s16","",0x12),
0x808CE2D4:("sAlphaTypes","u8","",0x15),
0x808CE2F0:("jtbl_808CE2F0","UNK_PTR","",0x4),
0x808CE314:("D_808CE314","f32","",0x4),
0x808CE318:("D_808CE318","f32","",0x4),