Skip to content

Commit

Permalink
Add collision + shadow
Browse files Browse the repository at this point in the history
  • Loading branch information
Kewlan committed Apr 23, 2024
1 parent 7a0850e commit a0cd629
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 81 deletions.
2 changes: 1 addition & 1 deletion code/include/z3D/z3D.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ typedef struct OcLine OcLine; // TODO
#define COLLISION_CHECK_OC_MAX 50
#define COLLISION_CHECK_OC_LINE_MAX 3

typedef struct {
typedef struct CollisionCheckContext {
/* 0x000 */ s16 colAtCount;
/* 0x002 */ u16 sacFlags;
/* 0x004 */ Collider* colAt[COLLISION_CHECK_AT_MAX];
Expand Down
52 changes: 26 additions & 26 deletions code/include/z3D/z3Dactor.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define _Z3DACTOR_H_

#include "z3Dvec.h"
#include "z3Dcollision_check.h"

struct Actor;
struct GlobalContext;
Expand Down Expand Up @@ -137,34 +138,18 @@ typedef struct {
/* 0x1B */ u8 acHitEffect;
} CollisionCheckInfo; // size = 0x1C

typedef struct {
/* 0x00 */ struct Actor* actor; // Attached actor
/* 0x04 */ struct Actor* at; // Actor attached to what it collided with as an AT collider.
/* 0x08 */ struct Actor* ac; // Actor attached to what it collided with as an AC collider.
/* 0x0C */ struct Actor* oc; // Actor attached to what it collided with as an OC collider.
/* 0x10 */ u8 atFlags; // Information flags for AT collisions.
/* 0x11 */ u8 acFlags; // Information flags for AC collisions.
/* 0x12 */ u8 ocFlags1; // Information flags for OC collisions.
/* 0x13 */ u8 ocFlags2; // Flags related to which colliders it can OC collide with.
/* 0x14 */ u8 colType; // Determines hitmarks and sound effects during AC collisions.
/* 0x15 */ u8 shape; // JntSph, Cylinder, Tris, or Quad
} Collider; // size = 0x18

typedef struct {
/* 0x00 */ Collider base;
/* 0x18 */ char unk_18[0x28]; // ColliderInfo info;
/* 0x40 */ char unk_40[0x18]; // Cylinderf dim;
} ColliderCylinder; // size = 0x58

typedef struct {
/* 0x00 */ Vec3s rot; // Current actor shape rotation
/* 0x06 */ u8 unk_06;
/* 0x08 */ f32 unk_08; // Model y axis offset. Represents model space units. collision mesh related
/* 0x06 */ s16 face;
/* 0x08 */ f32 yOffset; // Model y axis offset. Represents model space units. collision mesh related
/* 0x0C */ void (*shadowDrawFunc)(struct Actor*, struct LightMapper*, struct GlobalContext*);
/* 0x10 */ f32 unk_10;
/* 0x14 */ u8 unk_14;
/* 0x15 */ u8 unk_15;
} ActorShape; // size = 0x18
/* 0x10 */ f32 shadowScale;
/* 0x14 */ u8 shadowAlpha;
/* 0x15 */ u8 feetFloorFlag;
/* 0x16 */ char unk_16[2]; // Required padding?
/* 0x18 */ Vec3f feetPos[2];
} ActorShape; // size = 0x30
_Static_assert(sizeof(ActorShape) == 0x30, "ActorShape size");

typedef struct Actor {
/* 0x000 */ s16 id; // Actor Id
Expand Down Expand Up @@ -201,7 +186,6 @@ typedef struct Actor {
/* 0x09C */ f32 yDistToPlayer; // Dist is negative if the actor is above the player
/* 0x0A0 */ CollisionCheckInfo colChkInfo; // Variables related to the Collision Check system
/* 0x0BC */ ActorShape shape; // Variables related to the physical shape of the actor
/* 0x0D4 */ Vec3f unk_D4[2];
/* 0x0EC */ Vec3f unk_EC; // Stores result of some vector transformation involving actor xyz vector, and a matrix at
// Global Context + 11D60
/* 0x0F8 */ f32 unk_F8; // Related to above
Expand Down Expand Up @@ -239,6 +223,7 @@ typedef struct Actor {
/* 0x1A0 */ f32 unk_1A0;
/* From here on, the structure and size varies for each actor */
} Actor; // size = 0x1A4
_Static_assert(sizeof(Actor) == 0x1A4, "Actor size");

typedef struct DynaPolyActor {
/* 0x000 */ struct Actor actor;
Expand Down Expand Up @@ -320,7 +305,9 @@ typedef struct {
/* 0x24E0 */ void* zarInfo;
/* 0x24E4 */ char unk_24E4[0x0220];
/* 0x2704 */ struct SkeletonAnimationModel_unk_0C* bodyTexAnim;
/* 0x2708 */ char unk_2708[0x344];
} Player; // total size (from init vars): 2A4C
_Static_assert(sizeof(Player) == 0x2A4C, "Player size");

typedef enum {
/* 0x00 */ ACTORTYPE_SWITCH,
Expand Down Expand Up @@ -355,4 +342,17 @@ typedef u32 (*Actor_HasParent_proc)(Actor* actor, struct GlobalContext* globalCt
typedef f32 (*Actor_WorldDistXYZToActor_proc)(Actor* a, Actor* b) __attribute__((pcs("aapcs-vfp")));
#define Actor_WorldDistXYZToActor ((Actor_WorldDistXYZToActor_proc)0x3306C4)

typedef void (*ActorShape_Init_proc)(ActorShape* shape, f32 yOffset, void* shadowDrawFunc, f32 shadowScale)
__attribute__((pcs("aapcs-vfp")));
#define ActorShape_Init ((ActorShape_Init_proc)0x372D4C)

typedef void (*Actor_SetFeetPos_proc)(Actor* actor, nn_math_MTX34* mtx, int param_3, int param_4, Vec3f* param_5,
int param_6, Vec3f* param_7);
#define Actor_SetFeetPos ((Actor_SetFeetPos_proc)0x34CBB4)

typedef void (*Actor_UpdateBgCheckInfo_proc)(struct GlobalContext* globalCtx, Actor* actor, f32 wallCheckHeight,
f32 wallCheckRadius, f32 ceilingCheckHeight, s32 flags)
__attribute__((pcs("aapcs-vfp")));
#define Actor_UpdateBgCheckInfo ((Actor_UpdateBgCheckInfo_proc)0x376340)

#endif
119 changes: 119 additions & 0 deletions code/include/z3D/z3Dcollision_check.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#ifndef _Z3DCOLLISION_CHECK_H_
#define _Z3DCOLLISION_CHECK_H_

#include "z3Dvec.h"

struct GlobalContext;
struct CollisionCheckContext;

typedef struct {
/* 0x00 */ struct Actor* actor; // Attached actor
/* 0x04 */ struct Actor* at; // Actor attached to what it collided with as an AT collider.
/* 0x08 */ struct Actor* ac; // Actor attached to what it collided with as an AC collider.
/* 0x0C */ struct Actor* oc; // Actor attached to what it collided with as an OC collider.
/* 0x10 */ u8 atFlags; // Information flags for AT collisions.
/* 0x11 */ u8 acFlags; // Information flags for AC collisions.
/* 0x12 */ u8 ocFlags1; // Information flags for OC collisions.
/* 0x13 */ u8 ocFlags2; // Flags related to which colliders it can OC collide with.
/* 0x14 */ u8 colType; // Determines hitmarks and sound effects during AC collisions.
/* 0x15 */ u8 shape; // JntSph, Cylinder, Tris, or Quad
} Collider; // size = 0x18
_Static_assert(sizeof(Collider) == 0x18, "Collider size");

typedef struct {
/* 0x00 */ u32 damageFlags;
/* 0x04 */ u8 effect;
/* 0x05 */ u8 damage;
} ColliderTouch; // size = 0x8
_Static_assert(sizeof(ColliderTouch) == 0x8, "ColliderTouch size");

typedef struct {
/* 0x00 */ u32 damageFlags;
/* 0x04 */ u8 effect;
/* 0x05 */ u8 defense;
/* 0x06 */ Vec3s hitPos;
} ColliderBump; // size = 0xC
_Static_assert(sizeof(ColliderBump) == 0xC, "ColliderBump size");

typedef struct {
/* 0x00 */ ColliderTouch toucher;
/* 0x08 */ ColliderBump bumper;
/* 0x14 */ u8 elementType;
/* 0x15 */ u8 toucherFlags;
/* 0x16 */ u8 bumperFlags;
/* 0x17 */ u8 ocElementFlags;
/* 0x18 */ Collider* at_hit;
/* 0x1C */ Collider* ac_hit;
/* 0x20 */ Collider* at_hit_info;
/* 0x24 */ Collider* ac_hit_info;
} ColliderInfo; // size = 0x28
_Static_assert(sizeof(ColliderInfo) == 0x28, "ColliderInfo size");

typedef struct {
/* 0x00 */ f32 radius;
/* 0x04 */ f32 height;
/* 0x08 */ f32 yShift;
/* 0x0C */ Vec3f position;
} Cylinderf; // size = 0x18
_Static_assert(sizeof(Cylinderf) == 0x18, "Cylinderf size");

typedef struct {
/* 0x00 */ Collider base;
/* 0x18 */ ColliderInfo info;
/* 0x40 */ Cylinderf dim;
} ColliderCylinder; // size = 0x58
_Static_assert(sizeof(ColliderCylinder) == 0x58, "ColliderCylinder size");

typedef struct {
/* 0x00 */ u8 type;
/* 0x01 */ u8 atFlags;
/* 0x02 */ u8 acFlags;
/* 0x03 */ u8 maskA;
/* 0x04 */ u8 maskB;
/* 0x05 */ u8 shape;
} ColliderInit; // size = 0x6
_Static_assert(sizeof(ColliderInit) == 0x6, "ColliderInit size");

typedef struct {
/* 0x00 */ u32 damageFlags;
/* 0x04 */ u8 effect;
/* 0x05 */ u8 defense;
} ColliderBumpInit; // size = 0x8
_Static_assert(sizeof(ColliderBumpInit) == 0x8, "ColliderBumpInit size");

typedef struct {
/* 0x00 */ u8 elementType;
/* 0x04 */ ColliderTouch toucher;
/* 0x0C */ ColliderBumpInit bumper;
/* 0x14 */ u8 toucherFlags;
/* 0x15 */ u8 bumperFlags;
/* 0x16 */ u8 ocElementFlags;
} ColliderInfoInit; // size = 0x18
_Static_assert(sizeof(ColliderInfoInit) == 0x18, "ColliderInfoInit size");

typedef struct {
/* 0x00 */ ColliderInit base;
/* 0x08 */ ColliderInfoInit info;
/* 0x20 */ Cylinderf dim;
} ColliderCylinderInit; // size = 0x58
_Static_assert(sizeof(ColliderCylinderInit) == 0x38, "ColliderCylinderInit size");

typedef void (*Collider_InitCylinder_proc)(struct GlobalContext* globalCtx, ColliderCylinder* collider);
#define Collider_InitCylinder ((Collider_InitCylinder_proc)0x353DD0)

typedef void (*Collider_SetCylinder_proc)(struct GlobalContext* globalCtx, ColliderCylinder* collider,
struct Actor* actor, void* cylinderInitData);
#define Collider_SetCylinder ((Collider_SetCylinder_proc)0x353D24)

typedef void (*Collider_UpdateCylinder_proc)(struct Actor* actor, ColliderCylinder* collider);
#define Collider_UpdateCylinder ((Collider_UpdateCylinder_proc)0x37632C)

typedef void (*CollisionCheck_SetOC_proc)(struct GlobalContext* globalCtx, struct CollisionCheckContext* colChkCtx,
void* collider);
#define CollisionCheck_SetOC ((CollisionCheck_SetOC_proc)0x3762A4)

typedef void (*CollisionCheck_SetAC_proc)(struct GlobalContext* globalCtx, struct CollisionCheckContext* colChkCtx,
void* collider);
#define CollisionCheck_SetAC ((CollisionCheck_SetAC_proc)0x376168)

#endif //_Z3DCOLLISION_CHECK_H_
105 changes: 66 additions & 39 deletions code/src/actors/link_puppet.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,36 @@
#define MAX_PUPPETS_AT_ONCE 3

ActorInit EnLinkPuppet_InitVars = {
0x1, // ID
ACTORTYPE_NPC, // Type
0xFF, // Room
0b110000, // Flags
21, // Object ID (20: Adult, 21: Child)
sizeof(EnLinkPuppet), //
EnLinkPuppet_Init, //
EnLinkPuppet_Destroy, //
EnLinkPuppet_Update, //
EnLinkPuppet_Draw, //
0x1, // ID
ACTORTYPE_NPC, // Type
0xFF, // Room
0x2000410, // Flags
21, // Object ID (20: Adult, 21: Child)
sizeof(EnLinkPuppet), //
(ActorFunc)EnLinkPuppet_Init, //
(ActorFunc)EnLinkPuppet_Destroy, //
(ActorFunc)EnLinkPuppet_Update, //
(ActorFunc)EnLinkPuppet_Draw, //
};

static ColliderCylinderInit EnLinkPupper_ColliderCylinderInit = {
{
0x7,
0x0,
0x9,
0x9,
0x10,
0x1,
},
{
0x1,
{ 0x0, 0x0, 0x0 },
{ 0xFFCFFFFF, 0x0, 0x0 },
0x0,
0x5,
0x1,
},
{ 12.0f, 50.0f, 0.0f, { 0.0f, 0.0f, 0.0f } },
};

typedef void (*SkelAnime_InitLink_proc)(SkelAnime* skelAnime, ZARInfo* zarInfo, GlobalContext* globalCtx, void* cmbMan,
Expand All @@ -31,12 +51,10 @@ typedef void (*SkelAnime_InitLink_proc)(SkelAnime* skelAnime, ZARInfo* zarInfo,
// When posing the model by copying the joint table, the model for some reason gets raised about 12 units.
static const f32 childOffsetY = 12.5f;

void EnLinkPuppet_Init(Actor* thisx, GlobalContext* globalCtx) {
EnLinkPuppet* this = (EnLinkPuppet*)thisx;

void EnLinkPuppet_Init(EnLinkPuppet* this, GlobalContext* globalCtx) {
this->base.room = -1;

SkelAnime_InitLink(&this->skelAnime, PLAYER->zarInfo, globalCtx, PLAYER->cmbMan, thisx->unk_178, 0, 9,
SkelAnime_InitLink(&this->skelAnime, PLAYER->zarInfo, globalCtx, PLAYER->cmbMan, this->base.unk_178, 0, 9,
this->ghostPtr->ghostData.jointTable, NULL);

// Tunic
Expand All @@ -63,32 +81,26 @@ void EnLinkPuppet_Init(Actor* thisx, GlobalContext* globalCtx) {
for (size_t index = 0; index < BIT_COUNT(this->ghostPtr->ghostData.meshGroups2); index++) {
Model_DisableMeshGroupByIndex(this->skelAnime.unk_28, index + BIT_COUNT(u32));
}

// Collision
Collider_InitCylinder(gGlobalContext, &this->collider);
Collider_SetCylinder(gGlobalContext, &this->collider, &this->base, &EnLinkPupper_ColliderCylinderInit);

// Shadow
f32 feetShadowScale = (this->ghostPtr->ghostData.age == 0) ? 90.0f : 60.0f;
ActorShape_Init(&this->base.shape, 0.0f, (void*)0x1D04F4, feetShadowScale);
}

typedef void (*SkelAnime_Free2_proc)(SkelAnime* anime);
#define SkelAnime_Free2 ((SkelAnime_Free2_proc)0x350BE0)

void EnLinkPuppet_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnLinkPuppet* this = (EnLinkPuppet*)thisx;

void EnLinkPuppet_Destroy(EnLinkPuppet* this, GlobalContext* globalCtx) {
SkelAnime_Free2(&this->skelAnime);
}

void EnLinkPuppet_Update(Actor* thisx, GlobalContext* globalCtx) {
EnLinkPuppet* this = (EnLinkPuppet*)thisx;

if (this->ghostPtr == NULL) {
// Need to set the ghost data pointer first!
return;
}

if (!this->ghostPtr->inUse) {
Actor_Kill(thisx);
return;
}

if (this->ghostPtr->ghostData.currentScene != gGlobalContext->sceneNum) {
Actor_Kill(thisx);
void EnLinkPuppet_Update(EnLinkPuppet* this, GlobalContext* globalCtx) {
if (!this->ghostPtr->inUse || this->ghostPtr->ghostData.currentScene != gGlobalContext->sceneNum) {
Actor_Kill(&this->base);
return;
}

Expand All @@ -114,14 +126,31 @@ void EnLinkPuppet_Update(Actor* thisx, GlobalContext* globalCtx) {
// Tunic
this->skelAnime.unk_28->unk_0C->curFrame = this->ghostPtr->ghostData.currentTunic;

// Collider
Collider_UpdateCylinder(&this->base, &this->collider);
CollisionCheck_SetOC(gGlobalContext, &gGlobalContext->colChkCtx, &this->collider);
CollisionCheck_SetAC(gGlobalContext, &gGlobalContext->colChkCtx, &this->collider);

// Shadow
f32 ceilingCheckHeight = (this->ghostPtr->ghostData.age == 0) ? 56.0f : 40.0f;
Actor_UpdateBgCheckInfo(gGlobalContext, (Actor*)this, 26.0f, 6.0f, ceilingCheckHeight, 7);

// Child Y position workaround
if (this->ghostPtr->ghostData.age != 0) {
this->base.world.pos.y -= childOffsetY;
}
}

typedef void (*SkelAnime_DrawOpa_proc)(SkelAnime* skelAnime, nn_math_MTX34* modelMtx, u32* overrideLimbDraw,
u32* postLimbDraw, Actor* param_5, u32 param_6);
#define Vec3f_PlayerFeet_unk ((Vec3f*)0x53CACC)
void EnLinkPuppet_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, nn_math_MTX34* mtx, EnLinkPuppet* this) {
if (limbIndex != 0x15) {
Actor_SetFeetPos((Actor*)this, mtx, limbIndex, 5, &Vec3f_PlayerFeet_unk[gSaveContext.linkAge], 8,
&Vec3f_PlayerFeet_unk[gSaveContext.linkAge]);
}
}

typedef void (*SkelAnime_DrawOpa_proc)(SkelAnime* skelAnime, nn_math_MTX34* modelMtx, void* overrideLimbDraw,
void* postLimbDraw, Actor* param_5, u32 param_6);
#define SkelAnime_DrawOpa ((SkelAnime_DrawOpa_proc)0x35E240)

typedef void (*EffectSsDeadDb_Spawn_proc)(GlobalContext* globalCtx, Vec3f* position, Vec3f* velocity,
Expand All @@ -131,14 +160,12 @@ typedef void (*EffectSsDeadDb_Spawn_proc)(GlobalContext* globalCtx, Vec3f* posit
#define EffectSsDeadDb_Spawn_addr 0x3642F4
#define EffectSsDeadDb_Spawn ((EffectSsDeadDb_Spawn_proc)EffectSsDeadDb_Spawn_addr)

void EnLinkPuppet_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnLinkPuppet* this = (EnLinkPuppet*)thisx;

void EnLinkPuppet_Draw(EnLinkPuppet* this, GlobalContext* globalCtx) {
// Check how many Link puppets already exist before this one.
u8 linkPuppetCount = 0;
Actor* firstActor = gGlobalContext->actorCtx.actorList[EnLinkPuppet_InitVars.type].first;
for (Actor* actor = firstActor; actor != NULL; actor = actor->next) {
if (actor == thisx) {
if (actor == &this->base) {
break;
}
if (actor->id == EnLinkPuppet_InitVars.id) {
Expand All @@ -147,7 +174,7 @@ void EnLinkPuppet_Draw(Actor* thisx, GlobalContext* globalCtx) {
}

if (linkPuppetCount < MAX_PUPPETS_AT_ONCE && this->ghostPtr->ghostData.age == gSaveContext.linkAge) {
SkelAnime_DrawOpa(&this->skelAnime, &this->base.modelMtx, NULL, NULL, thisx, 0);
SkelAnime_DrawOpa(&this->skelAnime, &this->base.modelMtx, NULL, EnLinkPuppet_PostLimbDraw, &this->base, 0);
return;
}

Expand Down
Loading

0 comments on commit a0cd629

Please sign in to comment.