mirror of
https://github.com/zeldaret/oot.git
synced 2025-08-05 22:00:15 +00:00
DoorKiller OK (#631)
* Init done * slight tweak * Destroy done * func_80995020 * func_809951C4 done * started func_80995A84 * func_80995A84, func_80995284, func_809952B8 done * started the mess that is func_80995368 * most functions done except for 3 trouble cases * func_80995368 done * func_809958E4 done * fully matching. Documentation and cleanup to come * fixed fake matches * documentation progress * More documentation * getting close on tidying up everything * Finalised documentation and made some comments and name changes in player and other door files * formatting and final touches to comments * pr stuff * merge master * merge * format * remove unused asm after merge * review * \n Co-authored-by: fig02 <fig02srl@gmail.com>
This commit is contained in:
parent
ca5a9aa7d1
commit
8a730123b6
36 changed files with 544 additions and 1554 deletions
|
@ -118,7 +118,7 @@ void func_8099485C(DoorGerudo* this, GlobalContext* globalCtx) {
|
|||
} else if (!Flags_GetCollectible(globalCtx, (this->dyna.actor.params >> 8) & 0x1F)) {
|
||||
player->naviTextId = -0x225;
|
||||
} else {
|
||||
player->doorType = 2;
|
||||
player->doorType = PLAYER_DOORTYPE_SLIDING;
|
||||
player->doorDirection = direction;
|
||||
player->doorActor = &this->dyna.actor;
|
||||
player->doorTimer = 10;
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
/*
|
||||
* File: z_door_killer.c
|
||||
* Overlay: ovl_Door_Killer
|
||||
* Description: Fake doors which attack player
|
||||
*/
|
||||
|
||||
#include "z_door_killer.h"
|
||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||
|
||||
|
@ -5,13 +11,24 @@
|
|||
|
||||
#define THIS ((DoorKiller*)thisx)
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ DOOR_KILLER_DOOR,
|
||||
/* 1 */ DOOR_KILLER_RUBBLE_PIECE_1,
|
||||
/* 2 */ DOOR_KILLER_RUBBLE_PIECE_2,
|
||||
/* 3 */ DOOR_KILLER_RUBBLE_PIECE_3,
|
||||
/* 4 */ DOOR_KILLER_RUBBLE_PIECE_4
|
||||
} DoorKillerBehaviour;
|
||||
|
||||
void DoorKiller_Init(Actor* thisx, GlobalContext* globalCtx);
|
||||
void DoorKiller_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||||
void DoorKiller_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void DoorKiller_Wait(DoorKiller* this, GlobalContext* globalCtx);
|
||||
void DoorKiller_SetProperties(DoorKiller* this, GlobalContext* globalCtx);
|
||||
void DoorKiller_DrawDoor(Actor* thisx, GlobalContext* globalCtx);
|
||||
void DoorKiller_DrawRubble(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
extern UNK_TYPE D_06001BC8;
|
||||
extern FlexSkeletonHeader D_06001BC8;
|
||||
|
||||
/*
|
||||
const ActorInit Door_Killer_InitVars = {
|
||||
ACTOR_DOOR_KILLER,
|
||||
ACTORCAT_BG,
|
||||
|
@ -24,7 +41,7 @@ const ActorInit Door_Killer_InitVars = {
|
|||
NULL,
|
||||
};
|
||||
|
||||
static ColliderCylinderInit D_80995FB0 = {
|
||||
static ColliderCylinderInit sCylinderInit = {
|
||||
{
|
||||
COLTYPE_METAL,
|
||||
AT_ON | AT_TYPE_ENEMY,
|
||||
|
@ -44,7 +61,7 @@ static ColliderCylinderInit D_80995FB0 = {
|
|||
{ 20, 100, 0, { 0, 0, 0 } },
|
||||
};
|
||||
|
||||
static ColliderJntSphElementInit D_80995FDC[1] = {
|
||||
static ColliderJntSphElementInit sJntSphItemsInit[1] = {
|
||||
{
|
||||
{
|
||||
ELEMTYPE_UNK0,
|
||||
|
@ -58,7 +75,7 @@ static ColliderJntSphElementInit D_80995FDC[1] = {
|
|||
},
|
||||
};
|
||||
|
||||
static ColliderJntSphInit D_80996000 = {
|
||||
static ColliderJntSphInit sJntSphInit = {
|
||||
{
|
||||
COLTYPE_NONE,
|
||||
AT_NONE,
|
||||
|
@ -68,41 +85,439 @@ static ColliderJntSphInit D_80996000 = {
|
|||
COLSHAPE_JNTSPH,
|
||||
},
|
||||
1,
|
||||
D_80995FDC,
|
||||
sJntSphItemsInit,
|
||||
};
|
||||
*/
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/DoorKiller_Init.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/DoorKiller_Destroy.s")
|
||||
static DoorKillerTextureEntry sDoorTextures[4] = {
|
||||
{ OBJECT_HIDAN_OBJECTS, 0x0600E5A0 },
|
||||
{ OBJECT_MIZU_OBJECTS, 0x060035C0 },
|
||||
{ OBJECT_HAKA_DOOR, 0x06000000 },
|
||||
{ OBJECT_GAMEPLAY_KEEP, 0x0400EF38 },
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995020.s")
|
||||
void DoorKiller_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
GlobalContext* globalCtx2 = globalCtx;
|
||||
f32 randF;
|
||||
DoorKiller* this = THIS;
|
||||
s32 bankIndex;
|
||||
s32 i;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_809951C4.s")
|
||||
// Look in the object bank for one of the four objects containing door textures
|
||||
bankIndex = -1;
|
||||
for (i = 0; bankIndex < 0; i++) {
|
||||
bankIndex = Object_GetIndex(&globalCtx2->objectCtx, sDoorTextures[i].objectId);
|
||||
this->textureEntryIndex = i;
|
||||
}
|
||||
osSyncPrintf("bank_ID = %d\n", bankIndex);
|
||||
osSyncPrintf("status = %d\n", this->textureEntryIndex);
|
||||
this->doorObjBankIndex = bankIndex;
|
||||
this->texture = sDoorTextures[this->textureEntryIndex].texture;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995284.s")
|
||||
ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f);
|
||||
Actor_SetScale(&this->actor, 0.01f);
|
||||
this->timer = 0;
|
||||
this->hasHitPlayerOrGround = 0;
|
||||
this->animStyle = 0;
|
||||
this->playerIsOpening = 0;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_809952B8.s")
|
||||
switch ((u8)(this->actor.params & 0xFF)) {
|
||||
case DOOR_KILLER_DOOR:
|
||||
// `jointTable` is used for both the `jointTable` and `morphTable` args here. Because this actor doesn't
|
||||
// play any animations it does not cause problems, but it would need to be changed otherwise.
|
||||
SkelAnime_InitFlex(globalCtx2, &this->skelAnime, &D_06001BC8, NULL, this->jointTable, this->jointTable, 9);
|
||||
this->actionFunc = DoorKiller_SetProperties;
|
||||
DoorKiller_SetProperties(this, globalCtx2);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995318.s")
|
||||
// manually set the overall rotation of the door
|
||||
this->jointTable[1].x = this->jointTable[1].z = 0x4000;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995368.s")
|
||||
// Set a cylinder collider to detect link attacks and larger sphere collider to detect explosions
|
||||
Collider_InitCylinder(globalCtx2, &this->colliderCylinder);
|
||||
Collider_SetCylinder(globalCtx2, &this->colliderCylinder, &this->actor, &sCylinderInit);
|
||||
Collider_InitJntSph(globalCtx2, &this->colliderJntSph);
|
||||
Collider_SetJntSph(globalCtx2, &this->colliderJntSph, &this->actor, &sJntSphInit,
|
||||
this->colliderJntSphItems);
|
||||
this->colliderJntSph.elements[0].dim.worldSphere.radius = 80;
|
||||
this->colliderJntSph.elements[0].dim.worldSphere.center.x = (s16)this->actor.world.pos.x;
|
||||
this->colliderJntSph.elements[0].dim.worldSphere.center.y = (s16)this->actor.world.pos.y + 50;
|
||||
this->colliderJntSph.elements[0].dim.worldSphere.center.z = (s16)this->actor.world.pos.z;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995518.s")
|
||||
// If tied to a switch flag and that switch flag is already set, kill the actor.
|
||||
if ((((this->actor.params >> 8) & 0x3F) != 0x3F) &&
|
||||
Flags_GetSwitch(globalCtx2, ((this->actor.params >> 8) & 0x3F))) {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
break;
|
||||
case DOOR_KILLER_RUBBLE_PIECE_1:
|
||||
case DOOR_KILLER_RUBBLE_PIECE_2:
|
||||
case DOOR_KILLER_RUBBLE_PIECE_3:
|
||||
case DOOR_KILLER_RUBBLE_PIECE_4:
|
||||
this->actionFunc = DoorKiller_SetProperties;
|
||||
DoorKiller_SetProperties(this, globalCtx2);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_809958E4.s")
|
||||
this->actor.gravity = -0.6f;
|
||||
this->actor.minVelocityY = -6.0f;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995A50.s")
|
||||
// Random trajectories for rubble pieces
|
||||
randF = Rand_CenteredFloat(8.0f);
|
||||
this->actor.velocity.z = Rand_ZeroFloat(8.0f);
|
||||
this->actor.velocity.x = (Math_CosS(this->actor.world.rot.y) * randF) +
|
||||
(Math_SinS(this->actor.world.rot.y) * this->actor.velocity.z);
|
||||
this->actor.velocity.z = (-Math_SinS(this->actor.world.rot.y) * randF) +
|
||||
(Math_CosS(this->actor.world.rot.y) * this->actor.velocity.z);
|
||||
this->actor.velocity.y = Rand_ZeroFloat(4.0f) + 4.0f;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995A84.s")
|
||||
// These are used as the x,y,z rotational velocities in DoorKiller_FallAsRubble
|
||||
this->actor.world.rot.x = Rand_CenteredFloat(0x1000);
|
||||
this->actor.world.rot.y = Rand_CenteredFloat(0x1000);
|
||||
this->actor.world.rot.z = Rand_CenteredFloat(0x1000);
|
||||
this->timer = 80;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995CDC.s")
|
||||
void DoorKiller_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
DoorKiller* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995D6C.s")
|
||||
if ((thisx->params & 0xFF) == DOOR_KILLER_DOOR) {
|
||||
Collider_DestroyCylinder(globalCtx, &this->colliderCylinder);
|
||||
Collider_DestroyJntSph(globalCtx, &this->colliderJntSph);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/DoorKiller_Update.s")
|
||||
void DoorKiller_SpawnRubble(Actor* thisx, GlobalContext* globalCtx) {
|
||||
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_DOOR_KILLER, thisx->world.pos.x, thisx->world.pos.y + 9.0f,
|
||||
thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y, thisx->shape.rot.z,
|
||||
DOOR_KILLER_RUBBLE_PIECE_1);
|
||||
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_DOOR_KILLER, thisx->world.pos.x + 7.88f,
|
||||
thisx->world.pos.y + 39.8f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y,
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_2);
|
||||
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_DOOR_KILLER, thisx->world.pos.x - 15.86f,
|
||||
thisx->world.pos.y + 61.98f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y,
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_3);
|
||||
Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_DOOR_KILLER, thisx->world.pos.x + 3.72f,
|
||||
thisx->world.pos.y + 85.1f, thisx->world.pos.z, thisx->shape.rot.x, thisx->shape.rot.y,
|
||||
thisx->shape.rot.z, DOOR_KILLER_RUBBLE_PIECE_4);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995E40.s")
|
||||
/**
|
||||
* action function for the individual door pieces that spawn and fall down when the door is destroyed
|
||||
*/
|
||||
void DoorKiller_FallAsRubble(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
this->actor.velocity.y += this->actor.gravity;
|
||||
if (this->actor.velocity.y < this->actor.minVelocityY) {
|
||||
this->actor.velocity.y = this->actor.minVelocityY;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995EC4.s")
|
||||
this->actor.velocity.x *= 0.98f;
|
||||
this->actor.velocity.z *= 0.98f;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Door_Killer/func_80995F1C.s")
|
||||
// world.rot is repurposed to be the rotation velocity for the rubble pieces
|
||||
this->actor.shape.rot.x += this->actor.world.rot.x;
|
||||
this->actor.shape.rot.y += this->actor.world.rot.y;
|
||||
this->actor.shape.rot.z += this->actor.world.rot.z;
|
||||
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
} else {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
func_8002D7EC(&this->actor);
|
||||
}
|
||||
|
||||
s32 DoorKiller_IsHit(Actor* thisx, GlobalContext* globalCtx) {
|
||||
DoorKiller* this = THIS;
|
||||
if ((this->colliderCylinder.base.acFlags & 2) && (this->colliderCylinder.info.acHitInfo != NULL)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DoorKiller_SetAC(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
Collider_UpdateCylinder(&this->actor, &this->colliderCylinder);
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderCylinder.base);
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderJntSph.base);
|
||||
}
|
||||
|
||||
void DoorKiller_Die(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
s32 switchFlag = (this->actor.params >> 8) & 0x3F;
|
||||
|
||||
// Can set a switch flag on death based on params
|
||||
if (switchFlag != 0x3F) {
|
||||
Flags_SetSwitch(globalCtx, switchFlag);
|
||||
}
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
|
||||
/**
|
||||
* After slamming on the floor, rise back upright
|
||||
*/
|
||||
void DoorKiller_RiseBackUp(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
s32 i;
|
||||
s16 rotation;
|
||||
|
||||
if (this->timer > 0) {
|
||||
this->timer--;
|
||||
} else {
|
||||
this->actionFunc = DoorKiller_Wait;
|
||||
this->timer = 16;
|
||||
DoorKiller_SetAC(this, globalCtx);
|
||||
return;
|
||||
}
|
||||
|
||||
this->actor.shape.rot.x = (this->timer >= 8) ? (this->timer * 0x800) - 0x4000 : 0;
|
||||
|
||||
if (this->timer >= 12) {
|
||||
rotation = (-this->timer * -500) - 8000;
|
||||
} else if (this->timer >= 8) {
|
||||
rotation = -2000;
|
||||
} else if (this->timer >= 5) {
|
||||
rotation = (this->timer * -500) + 2000;
|
||||
} else {
|
||||
rotation = 0;
|
||||
}
|
||||
|
||||
for (i = 2; i < 9; i++) {
|
||||
this->jointTable[i].z = -rotation;
|
||||
}
|
||||
|
||||
if (this->timer < 8) {
|
||||
rotation = Math_SinS(this->timer * 0x2000) * this->timer * 100.0f;
|
||||
for (i = 2; i < 9; i++) {
|
||||
this->jointTable[i].y = rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After wobbling, fall over and slam onto the floor, damaging the player if they are in the way. Uses manual distance
|
||||
* check for damaging player, not AT system.
|
||||
*/
|
||||
void DoorKiller_FallOver(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
s32 i;
|
||||
s16 rotation;
|
||||
|
||||
if (this->timer > 0) {
|
||||
this->timer--;
|
||||
} else {
|
||||
this->actionFunc = DoorKiller_RiseBackUp;
|
||||
this->timer = 16;
|
||||
return;
|
||||
}
|
||||
|
||||
this->actor.shape.rot.x = (this->timer >= 4) ? 0x8000 + (-this->timer * 0x1000) : 0x4000;
|
||||
|
||||
if (this->timer >= 6) {
|
||||
rotation = (-this->timer * -500) - 4000;
|
||||
} else if (this->timer >= 4) {
|
||||
rotation = -1000;
|
||||
} else if (this->timer >= 3) {
|
||||
rotation = (this->timer * -500) + 1000;
|
||||
} else {
|
||||
rotation = 0;
|
||||
}
|
||||
|
||||
for (i = 2; i < 9; i++) {
|
||||
this->jointTable[i].z = rotation;
|
||||
}
|
||||
|
||||
if (this->timer == 4) {
|
||||
// spawn 20 random dust particles just before slamming down
|
||||
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
|
||||
Vec3f accel = { 0.0f, 1.0f, 0.0f };
|
||||
Vec3f pos;
|
||||
s32 j;
|
||||
f32 randF;
|
||||
|
||||
for (j = 0; j != 20; j++) {
|
||||
pos.y = 0.0f;
|
||||
randF = Rand_CenteredFloat(40.0f);
|
||||
pos.z = Rand_ZeroFloat(100.0f);
|
||||
pos.x = (Math_CosS(this->actor.world.rot.y) * randF) + (Math_SinS(this->actor.world.rot.y) * pos.z);
|
||||
pos.z = (-Math_SinS(this->actor.world.rot.y) * randF) + (Math_CosS(this->actor.world.rot.y) * pos.z);
|
||||
velocity.x = pos.x * 0.2f;
|
||||
velocity.z = pos.z * 0.2f;
|
||||
accel.x = -(velocity.x) * 0.1f;
|
||||
accel.z = -(velocity.z) * 0.1f;
|
||||
pos.x += this->actor.world.pos.x;
|
||||
pos.y += this->actor.world.pos.y;
|
||||
pos.z += this->actor.world.pos.z;
|
||||
func_8002865C(globalCtx, &pos, &velocity, &accel, 300, 30);
|
||||
}
|
||||
}
|
||||
if (!(this->hasHitPlayerOrGround & 1)) {
|
||||
Vec3f playerPosRelToDoor;
|
||||
Player* player = PLAYER;
|
||||
func_8002DBD0(&this->actor, &playerPosRelToDoor, &player->actor.world.pos);
|
||||
if ((fabsf(playerPosRelToDoor.y) < 20.0f) && (fabsf(playerPosRelToDoor.x) < 20.0f) &&
|
||||
(playerPosRelToDoor.z < 100.0f) && (playerPosRelToDoor.z > 0.0f)) {
|
||||
this->hasHitPlayerOrGround |= 1;
|
||||
func_8002F6D4(globalCtx, &this->actor, 6.0f, this->actor.yawTowardsPlayer, 6.0f, 16);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_KDOOR_HIT);
|
||||
func_8002F7DC(&player->actor, NA_SE_PL_BODY_HIT);
|
||||
}
|
||||
}
|
||||
if (!(this->hasHitPlayerOrGround & 1) && (this->timer == 2)) {
|
||||
this->hasHitPlayerOrGround |= 1;
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_KDOOR_HIT_GND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wobble around, signifying the door is about to fall over. Does not set AC and so cannot be destroyed during this.
|
||||
*/
|
||||
void DoorKiller_Wobble(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
s16 rotation;
|
||||
s32 i;
|
||||
|
||||
if ((this->timer == 16) || (this->timer == 8)) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_KDOOR_WAVE);
|
||||
}
|
||||
|
||||
if (this->timer > 0) {
|
||||
this->timer--;
|
||||
} else {
|
||||
this->actionFunc = DoorKiller_FallOver;
|
||||
this->timer = 8;
|
||||
this->hasHitPlayerOrGround &= ~1;
|
||||
return;
|
||||
}
|
||||
|
||||
rotation = Math_SinS(this->timer * 0x2000) * this->timer * 100.0f;
|
||||
for (i = 2; i < 9; i++) {
|
||||
this->jointTable[i].y = rotation;
|
||||
}
|
||||
rotation = (u16)(s32)(-Math_CosS(this->timer * 0x1000) * 1000.0f) + 1000;
|
||||
for (i = 2; i < 9; i++) {
|
||||
this->jointTable[i].z = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Idle while the player attempts to open the door and then begin to wobble
|
||||
*/
|
||||
void DoorKiller_WaitBeforeWobble(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
if (this->timer > 0) {
|
||||
this->timer--;
|
||||
} else {
|
||||
this->timer = 16;
|
||||
this->actionFunc = DoorKiller_Wobble;
|
||||
}
|
||||
}
|
||||
|
||||
void DoorKiller_Wait(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
Player* player = PLAYER;
|
||||
Vec3f playerPosRelToDoor;
|
||||
s16 angleToFacingPlayer;
|
||||
|
||||
func_8002DBD0(&this->actor, &playerPosRelToDoor, &player->actor.world.pos);
|
||||
|
||||
// playerIsOpening is set by player
|
||||
if (this->playerIsOpening) {
|
||||
this->actionFunc = DoorKiller_WaitBeforeWobble;
|
||||
this->timer = 10;
|
||||
this->playerIsOpening = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (DoorKiller_IsHit(&this->actor, globalCtx)) {
|
||||
// AC cylinder: wobble if hit by most weapons, die if hit by explosives or hammer
|
||||
if ((this->colliderCylinder.info.acHitInfo->toucher.dmgFlags & 0x1FFA6) != 0) {
|
||||
this->timer = 16;
|
||||
this->actionFunc = DoorKiller_Wobble;
|
||||
} else if ((this->colliderCylinder.info.acHitInfo->toucher.dmgFlags & 0x48) != 0) {
|
||||
DoorKiller_SpawnRubble(&this->actor, globalCtx);
|
||||
this->actionFunc = DoorKiller_Die;
|
||||
Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 20, NA_SE_EN_KDOOR_BREAK);
|
||||
}
|
||||
} else if (Actor_GetCollidedExplosive(globalCtx, &this->colliderJntSph.base) != NULL) {
|
||||
// AC sphere: die if hit by explosive
|
||||
DoorKiller_SpawnRubble(&this->actor, globalCtx);
|
||||
this->actionFunc = DoorKiller_Die;
|
||||
Audio_PlaySoundAtPosition(globalCtx, &this->actor.world.pos, 20, NA_SE_EN_KDOOR_BREAK);
|
||||
} else if (!Player_InCsMode(globalCtx) && (fabsf(playerPosRelToDoor.y) < 20.0f) &&
|
||||
(fabsf(playerPosRelToDoor.x) < 20.0f) && (playerPosRelToDoor.z < 50.0f) &&
|
||||
(playerPosRelToDoor.z > 0.0f)) {
|
||||
// Set player properties to make the door openable if within range
|
||||
angleToFacingPlayer = player->actor.shape.rot.y - this->actor.shape.rot.y;
|
||||
if (playerPosRelToDoor.z > 0.0f) {
|
||||
angleToFacingPlayer = 0x8000 - angleToFacingPlayer;
|
||||
}
|
||||
if (ABS(angleToFacingPlayer) < 0x3000) {
|
||||
player->doorType = PLAYER_DOORTYPE_FAKE;
|
||||
player->doorDirection = (playerPosRelToDoor.z >= 0.0f) ? 1.0f : -1.0f;
|
||||
player->doorActor = &this->actor;
|
||||
}
|
||||
}
|
||||
|
||||
DoorKiller_SetAC(this, globalCtx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs the virtual address of the texture from the relevant door object
|
||||
*/
|
||||
void DoorKiller_UpdateTexture(Actor* thisx, GlobalContext* globalCtx) {
|
||||
DoorKiller* this = THIS;
|
||||
|
||||
gSegments[6] = VIRTUAL_TO_PHYSICAL(globalCtx->objectCtx.status[this->doorObjBankIndex].segment);
|
||||
this->texture = SEGMENTED_TO_VIRTUAL(this->texture);
|
||||
gSegments[6] = VIRTUAL_TO_PHYSICAL(globalCtx->objectCtx.status[thisx->objBankIndex].segment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the correct door texture, defines the appropriate draw fucntion and action function based on type behaviour
|
||||
* (door or rubble).
|
||||
*/
|
||||
void DoorKiller_SetProperties(DoorKiller* this, GlobalContext* globalCtx) {
|
||||
if (Object_IsLoaded(&globalCtx->objectCtx, this->doorObjBankIndex)) {
|
||||
DoorKiller_UpdateTexture(&this->actor, globalCtx);
|
||||
switch (this->actor.params & 0xFF) {
|
||||
case DOOR_KILLER_DOOR:
|
||||
this->actionFunc = DoorKiller_Wait;
|
||||
this->actor.draw = DoorKiller_DrawDoor;
|
||||
break;
|
||||
case DOOR_KILLER_RUBBLE_PIECE_1:
|
||||
case DOOR_KILLER_RUBBLE_PIECE_2:
|
||||
case DOOR_KILLER_RUBBLE_PIECE_3:
|
||||
case DOOR_KILLER_RUBBLE_PIECE_4:
|
||||
this->actionFunc = DoorKiller_FallAsRubble;
|
||||
this->actor.draw = DoorKiller_DrawRubble;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoorKiller_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
DoorKiller* this = THIS;
|
||||
|
||||
this->actionFunc(this, globalCtx);
|
||||
}
|
||||
|
||||
void DoorKiller_SetTexture(Actor* thisx, GlobalContext* globalCtx) {
|
||||
DoorKiller* this = THIS;
|
||||
u64* doorTexture = this->texture;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_door_killer.c", 883);
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, doorTexture);
|
||||
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_door_killer.c", 885);
|
||||
}
|
||||
|
||||
void DoorKiller_DrawDoor(Actor* thisx, GlobalContext* globalCtx) {
|
||||
DoorKiller* this = THIS;
|
||||
|
||||
func_800943C8(globalCtx->state.gfxCtx);
|
||||
DoorKiller_SetTexture(&this->actor, globalCtx);
|
||||
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
|
||||
NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void DoorKiller_DrawRubble(Actor* thisx, GlobalContext* globalCtx) {
|
||||
static Gfx* dLists[] = { 0x06001250, 0x06001550, 0x060017B8, 0x06001A58 };
|
||||
s32 rubblePieceIndex = (thisx->params & 0xFF) - 1;
|
||||
DoorKiller* this = THIS;
|
||||
|
||||
if ((this->timer >= 20) || ((this->timer & 1) == 0)) {
|
||||
DoorKiller_SetTexture(thisx, globalCtx);
|
||||
Gfx_DrawDListOpa(globalCtx, dLists[rubblePieceIndex]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,35 @@
|
|||
#include "ultra64.h"
|
||||
#include "global.h"
|
||||
|
||||
/*
|
||||
* Associated switch flag: (params >> 8) & 0x3F
|
||||
* ((params >> 8) & 0x3F) == 0x3F means no switch flag is checked / set
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ s16 objectId;
|
||||
/* 0x04 */ u64* texture;
|
||||
} DoorKillerTextureEntry; // size 0x8
|
||||
|
||||
struct DoorKiller;
|
||||
|
||||
typedef void (*DoorKillerActionFunc)(struct DoorKiller*, GlobalContext*);
|
||||
|
||||
typedef struct DoorKiller {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ char unk_14C[0x138];
|
||||
/* 0x014C */ SkelAnime skelAnime;
|
||||
/* 0x0190 */ u8 animStyle; // Must be at same offset as animStyle in EnDoor due to the cast in func_80839800
|
||||
/* 0x0191 */ u8 playerIsOpening; // Must be at same offset as playerIsOpening in EnDoor
|
||||
/* 0x0192 */ Vec3s jointTable[9];
|
||||
/* 0x01C8 */ ColliderCylinder colliderCylinder;
|
||||
/* 0x0214 */ u64* texture;
|
||||
/* 0x0218 */ u16 hasHitPlayerOrGround;
|
||||
/* 0x021A */ u16 timer;
|
||||
/* 0x021C */ u8 doorObjBankIndex;
|
||||
/* 0x021D */ u8 textureEntryIndex;
|
||||
/* 0x0220 */ ColliderJntSph colliderJntSph;
|
||||
/* 0x0240 */ ColliderJntSphElement colliderJntSphItems[1];
|
||||
/* 0x0280 */ DoorKillerActionFunc actionFunc;
|
||||
} DoorKiller; // size = 0x0284
|
||||
|
||||
extern const ActorInit Door_Killer_InitVars;
|
||||
|
|
|
@ -385,7 +385,7 @@ void func_80996B0C(DoorShutter* this, GlobalContext* globalCtx) {
|
|||
}
|
||||
player->doorTimer = 10;
|
||||
}
|
||||
player->doorType = 2;
|
||||
player->doorType = PLAYER_DOORTYPE_SLIDING;
|
||||
player->doorDirection = doorDirection;
|
||||
player->doorActor = &this->dyna.actor;
|
||||
}
|
||||
|
|
|
@ -358,7 +358,7 @@ void EnArrow_Fly(EnArrow* this, GlobalContext* globalCtx) {
|
|||
} else {
|
||||
Math_Vec3f_Sum(&this->actor.world.pos, &this->unk_250, &this->hitActor->world.pos);
|
||||
}
|
||||
|
||||
|
||||
if (this->touchedPoly && (this->hitActor != NULL)) {
|
||||
this->hitActor->flags &= ~0x8000;
|
||||
this->hitActor = NULL;
|
||||
|
|
|
@ -140,7 +140,8 @@ void func_809CAEF4(EnBrob* this) {
|
|||
}
|
||||
|
||||
void func_809CAF88(EnBrob* this) {
|
||||
Animation_Change(&this->skelAnime, &D_06001750, -1.0f, Animation_GetLastFrame(&D_06001750), 0.0f, ANIMMODE_ONCE, -5.0f);
|
||||
Animation_Change(&this->skelAnime, &D_06001750, -1.0f, Animation_GetLastFrame(&D_06001750), 0.0f, ANIMMODE_ONCE,
|
||||
-5.0f);
|
||||
this->unk_1AE = 8250;
|
||||
this->actionFunc = func_809CB354;
|
||||
}
|
||||
|
@ -251,8 +252,8 @@ void func_809CB458(EnBrob* this, GlobalContext* globalCtx) {
|
|||
dist2 = -dist2;
|
||||
}
|
||||
pos.y = (((Rand_ZeroOne() * 15000.0f) + 1000.0f) * this->dyna.actor.scale.y) + this->dyna.actor.world.pos.y;
|
||||
EffectSsLightning_Spawn(globalCtx, &pos, &primColor, &envColor,
|
||||
this->dyna.actor.scale.y * 8000.0f, Rand_ZeroOne() * 65536.0f, 4, 1);
|
||||
EffectSsLightning_Spawn(globalCtx, &pos, &primColor, &envColor, this->dyna.actor.scale.y * 8000.0f,
|
||||
Rand_ZeroOne() * 65536.0f, 4, 1);
|
||||
}
|
||||
|
||||
if (this->timer == 0) {
|
||||
|
@ -278,10 +279,11 @@ void EnBrob_Update(Actor* thisx, GlobalContext* globalCtx2) {
|
|||
|
||||
func_809CAEF4(this);
|
||||
} else if ((this->colliders[0].base.atFlags & AT_HIT) || (this->colliders[1].base.atFlags & AT_HIT) ||
|
||||
(acHits[0] && (this->colliders[0].info.acHitInfo->toucher.dmgFlags & 0x100)) ||
|
||||
(acHits[1] && (this->colliders[1].info.acHitInfo->toucher.dmgFlags & 0x100))) {
|
||||
(acHits[0] && (this->colliders[0].info.acHitInfo->toucher.dmgFlags & 0x100)) ||
|
||||
(acHits[1] && (this->colliders[1].info.acHitInfo->toucher.dmgFlags & 0x100))) {
|
||||
|
||||
if (this->actionFunc == func_809CB114 && !(this->colliders[0].base.atFlags & AT_BOUNCED) && !(this->colliders[1].base.atFlags & AT_BOUNCED)) {
|
||||
if (this->actionFunc == func_809CB114 && !(this->colliders[0].base.atFlags & AT_BOUNCED) &&
|
||||
!(this->colliders[1].base.atFlags & AT_BOUNCED)) {
|
||||
func_8002F71C(globalCtx, &this->dyna.actor, 5.0f, this->dyna.actor.yawTowardsPlayer, 1.0f);
|
||||
} else if (this->actionFunc != func_809CB114) {
|
||||
func_809CB008(this);
|
||||
|
|
|
@ -179,14 +179,14 @@ void EnDoor_SetupType(EnDoor* this, GlobalContext* globalCtx) {
|
|||
void EnDoor_Idle(EnDoor* this, GlobalContext* globalCtx) {
|
||||
Player* player = PLAYER;
|
||||
s32 doorType;
|
||||
Vec3f sp2C;
|
||||
Vec3f playerPosRelToDoor;
|
||||
s16 phi_v0;
|
||||
|
||||
doorType = this->actor.params >> 7 & 7;
|
||||
func_8002DBD0(&this->actor, &sp2C, &player->actor.world.pos);
|
||||
if (this->unk_191 != 0) {
|
||||
func_8002DBD0(&this->actor, &playerPosRelToDoor, &player->actor.world.pos);
|
||||
if (this->playerIsOpening != 0) {
|
||||
this->actionFunc = EnDoor_Open;
|
||||
Animation_PlayOnceSetSpeed(&this->skelAnime, D_809FCECC[this->unk_190],
|
||||
Animation_PlayOnceSetSpeed(&this->skelAnime, D_809FCECC[this->animStyle],
|
||||
(player->stateFlags1 & 0x8000000) ? 0.75f : 1.5f);
|
||||
if (this->lockTimer != 0) {
|
||||
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]--;
|
||||
|
@ -194,9 +194,10 @@ void EnDoor_Idle(EnDoor* this, GlobalContext* globalCtx) {
|
|||
Audio_PlayActorSound2(&this->actor, NA_SE_EV_CHAIN_KEY_UNLOCK);
|
||||
}
|
||||
} else if (!Player_InCsMode(globalCtx)) {
|
||||
if (fabsf(sp2C.y) < 20.0f && fabsf(sp2C.x) < 20.0f && fabsf(sp2C.z) < 50.0f) {
|
||||
if (fabsf(playerPosRelToDoor.y) < 20.0f && fabsf(playerPosRelToDoor.x) < 20.0f &&
|
||||
fabsf(playerPosRelToDoor.z) < 50.0f) {
|
||||
phi_v0 = player->actor.shape.rot.y - this->actor.shape.rot.y;
|
||||
if (sp2C.z > 0.0f) {
|
||||
if (playerPosRelToDoor.z > 0.0f) {
|
||||
phi_v0 = 0x8000 - phi_v0;
|
||||
}
|
||||
if (ABS(phi_v0) < 0x3000) {
|
||||
|
@ -210,8 +211,8 @@ void EnDoor_Idle(EnDoor* this, GlobalContext* globalCtx) {
|
|||
player->doorTimer = 10;
|
||||
}
|
||||
}
|
||||
player->doorType = (doorType == DOOR_AJAR) ? -1 : 1;
|
||||
player->doorDirection = (sp2C.z >= 0.0f) ? 1.0f : -1.0f;
|
||||
player->doorType = (doorType == DOOR_AJAR) ? PLAYER_DOORTYPE_AJAR : PLAYER_DOORTYPE_HANDLE;
|
||||
player->doorDirection = (playerPosRelToDoor.z >= 0.0f) ? 1.0f : -1.0f;
|
||||
player->doorActor = &this->actor;
|
||||
}
|
||||
} else if (doorType == DOOR_AJAR && this->actor.xzDistToPlayer > DOOR_AJAR_OPEN_RANGE) {
|
||||
|
@ -261,8 +262,8 @@ void EnDoor_Open(EnDoor* this, GlobalContext* globalCtx) {
|
|||
if (DECR(this->lockTimer) == 0) {
|
||||
if (SkelAnime_Update(&this->skelAnime)) {
|
||||
this->actionFunc = EnDoor_Idle;
|
||||
this->unk_191 = 0;
|
||||
} else if (Animation_OnFrame(&this->skelAnime, sDoorAnimOpenFrames[this->unk_190])) {
|
||||
this->playerIsOpening = 0;
|
||||
} else if (Animation_OnFrame(&this->skelAnime, sDoorAnimOpenFrames[this->animStyle])) {
|
||||
Audio_PlayActorSound2(&this->actor,
|
||||
(globalCtx->sceneNum == SCENE_HAKADAN || globalCtx->sceneNum == SCENE_HAKADANCH ||
|
||||
globalCtx->sceneNum == SCENE_HIDAN)
|
||||
|
@ -274,7 +275,7 @@ void EnDoor_Open(EnDoor* this, GlobalContext* globalCtx) {
|
|||
EffectSsBubble_Spawn(globalCtx, &this->actor.world.pos, 60.0f, 100.0f, 50.0f, 0.15f);
|
||||
}
|
||||
}
|
||||
} else if (Animation_OnFrame(&this->skelAnime, sDoorAnimCloseFrames[this->unk_190])) {
|
||||
} else if (Animation_OnFrame(&this->skelAnime, sDoorAnimCloseFrames[this->animStyle])) {
|
||||
Audio_PlayActorSound2(&this->actor,
|
||||
(globalCtx->sceneNum == SCENE_HAKADAN || globalCtx->sceneNum == SCENE_HAKADANCH ||
|
||||
globalCtx->sceneNum == SCENE_HIDAN)
|
||||
|
|
|
@ -46,8 +46,8 @@ typedef void (*EnDoorActionFunc)(struct EnDoor*, GlobalContext*);
|
|||
typedef struct EnDoor {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ SkelAnime skelAnime;
|
||||
/* 0x0190 */ u8 unk_190;
|
||||
/* 0x0191 */ u8 unk_191;
|
||||
/* 0x0190 */ u8 animStyle; // Must be at same offset as animStyle in DoorKiller due to the cast in func_80839800
|
||||
/* 0x0191 */ u8 playerIsOpening; // Must be at same offset as playerIsOpening in DoorKiller due to the cast in func_80839800
|
||||
/* 0x0192 */ u8 unk_192;
|
||||
/* 0x0193 */ s8 requiredObjBankIndex;
|
||||
/* 0x0194 */ s8 dListIndex;
|
||||
|
|
|
@ -111,7 +111,6 @@ void EnFu_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|||
|
||||
void EnFu_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnFu* this = THIS;
|
||||
|
||||
Collider_DestroyCylinder(globalCtx, &this->collider);
|
||||
}
|
||||
|
||||
|
|
|
@ -775,7 +775,6 @@ u16 EnGo2_GetTextId(GlobalContext* globalCtx, Actor* thisx) {
|
|||
|
||||
s16 EnGo2_GetState(GlobalContext* globalCtx, Actor* thisx) {
|
||||
EnGo2* this = THIS;
|
||||
|
||||
switch (this->actor.params & 0x1F) {
|
||||
case GORON_CITY_ROLLING_BIG:
|
||||
return EnGo2_GetStateGoronCityRollingBig(globalCtx, this);
|
||||
|
|
|
@ -419,7 +419,6 @@ u16 EnMd_GetText(GlobalContext* globalCtx, Actor* thisx) {
|
|||
|
||||
s16 func_80AAAF04(GlobalContext* globalCtx, Actor* thisx) {
|
||||
EnMd* this = THIS;
|
||||
|
||||
switch (func_80AAAC78(this, globalCtx)) {
|
||||
case 0:
|
||||
case 1:
|
||||
|
|
|
@ -569,7 +569,6 @@ void func_80AEBA2C(EnRu1* this, GlobalContext* globalCtx) {
|
|||
f32 temp_ret_2;
|
||||
CsCmdActorAction* csCmdNPCAction = func_80AEB438(globalCtx);
|
||||
s32 pad2;
|
||||
|
||||
if (csCmdNPCAction != NULL) {
|
||||
temp_ret_2 = func_80AEB7E0(csCmdNPCAction, globalCtx);
|
||||
thisPos = &this->actor.world.pos;
|
||||
|
|
|
@ -143,7 +143,7 @@ void func_80B86BC8(ItemShield* this, GlobalContext* globalCtx) {
|
|||
|
||||
void func_80B86CA8(ItemShield* this, GlobalContext* globalCtx) {
|
||||
static Vec3f D_80B871F4 = { 0.0f, 0.0f, 0.0f };
|
||||
static f32 D_80B87200[] = { 0.3f, 0.6f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
static f32 D_80B87200[] = { 0.3f, 0.6f, 0.9f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 0.85f, 0.7f, 0.55f, 0.4f, 0.25f, 0.1f, 0.0f };
|
||||
static f32 D_80B87240[] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.8f,
|
||||
0.6f, 0.4f, 0.2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
@ -159,7 +159,8 @@ void func_80B86CA8(ItemShield* this, GlobalContext* globalCtx) {
|
|||
D_80B871F4.x = this->unk_1A8[i].x;
|
||||
D_80B871F4.y = this->unk_1A8[i].y + (this->actor.shape.yOffset * 0.01f) + (D_80B87200[temp] * -10.0f * 0.2f);
|
||||
D_80B871F4.z = this->unk_1A8[i].z;
|
||||
EffectSsFireTail_SpawnFlame(globalCtx, &this->actor, &D_80B871F4, D_80B87200[temp] * 0.2f, -1, D_80B87240[temp]);
|
||||
EffectSsFireTail_SpawnFlame(globalCtx, &this->actor, &D_80B871F4, D_80B87200[temp] * 0.2f, -1,
|
||||
D_80B87240[temp]);
|
||||
if (this->unk_19E[i] != 0) {
|
||||
this->unk_19E[i]--;
|
||||
} else if (this->timer > 16) {
|
||||
|
|
|
@ -37,6 +37,13 @@ typedef struct {
|
|||
#define GET_ITEM_NONE \
|
||||
{ ITEM_NONE, 0, 0, 0, 0 }
|
||||
|
||||
typedef enum {
|
||||
/* 0x00 */ KNOB_ANIM_ADULT_L,
|
||||
/* 0x01 */ KNOB_ANIM_CHILD_L,
|
||||
/* 0x02 */ KNOB_ANIM_ADULT_R,
|
||||
/* 0x03 */ KNOB_ANIM_CHILD_R
|
||||
} KnobDoorAnim;
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ u8 itemId;
|
||||
/* 0x02 */ s16 actorId;
|
||||
|
@ -2218,7 +2225,7 @@ s32 func_80834EB8(Player* this, GlobalContext* globalCtx) {
|
|||
}
|
||||
|
||||
s32 func_80834F2C(Player* this, GlobalContext* globalCtx) {
|
||||
if ((this->doorType == 0) && !(this->stateFlags1 & 0x2000000)) {
|
||||
if ((this->doorType == PLAYER_DOORTYPE_NONE) && !(this->stateFlags1 & 0x2000000)) {
|
||||
if (D_80853614 || func_80834E44(globalCtx)) {
|
||||
if (func_80834D2C(this, globalCtx)) {
|
||||
return func_80834EB8(this, globalCtx);
|
||||
|
@ -4033,8 +4040,8 @@ s32 func_80839768(GlobalContext* globalCtx, Player* this, Vec3f* arg2, Collision
|
|||
|
||||
s32 func_80839800(Player* this, GlobalContext* globalCtx) {
|
||||
DoorShutter* doorShutter;
|
||||
EnDoor* enDoor;
|
||||
s32 sp7C;
|
||||
EnDoor* door; // Can also be DoorKiller*
|
||||
s32 doorDirection;
|
||||
f32 sp78;
|
||||
f32 sp74;
|
||||
Actor* doorActor;
|
||||
|
@ -4046,26 +4053,26 @@ s32 func_80839800(Player* this, GlobalContext* globalCtx) {
|
|||
CollisionPoly* sp58;
|
||||
Vec3f sp4C;
|
||||
|
||||
if ((this->doorType != 0) &&
|
||||
if ((this->doorType != PLAYER_DOORTYPE_NONE) &&
|
||||
(!(this->stateFlags1 & 0x800) || ((this->heldActor != NULL) && (this->heldActor->id == ACTOR_EN_RU1)))) {
|
||||
if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A) || (func_8084F9A0 == this->func_674)) {
|
||||
doorActor = this->doorActor;
|
||||
|
||||
if (this->doorType < 0) {
|
||||
if (this->doorType <= PLAYER_DOORTYPE_AJAR) {
|
||||
doorActor->textId = 0xD0; // "It won't open!"
|
||||
func_80853148(globalCtx, doorActor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sp7C = this->doorDirection;
|
||||
doorDirection = this->doorDirection;
|
||||
sp78 = Math_CosS(doorActor->shape.rot.y);
|
||||
sp74 = Math_SinS(doorActor->shape.rot.y);
|
||||
|
||||
if (this->doorType == 2) {
|
||||
if (this->doorType == PLAYER_DOORTYPE_SLIDING) {
|
||||
doorShutter = (DoorShutter*)doorActor;
|
||||
|
||||
this->currentYaw = doorShutter->dyna.actor.home.rot.y;
|
||||
if (sp7C > 0) {
|
||||
if (doorDirection > 0) {
|
||||
this->currentYaw -= 0x8000;
|
||||
}
|
||||
this->actor.shape.rot.y = this->currentYaw;
|
||||
|
@ -4080,10 +4087,10 @@ s32 func_80839800(Player* this, GlobalContext* globalCtx) {
|
|||
this->unk_447 = this->doorType;
|
||||
this->stateFlags1 |= 0x20000000;
|
||||
|
||||
this->unk_450.x = this->actor.world.pos.x + ((sp7C * 20.0f) * sp74);
|
||||
this->unk_450.z = this->actor.world.pos.z + ((sp7C * 20.0f) * sp78);
|
||||
this->unk_45C.x = this->actor.world.pos.x + ((sp7C * -120.0f) * sp74);
|
||||
this->unk_45C.z = this->actor.world.pos.z + ((sp7C * -120.0f) * sp78);
|
||||
this->unk_450.x = this->actor.world.pos.x + ((doorDirection * 20.0f) * sp74);
|
||||
this->unk_450.z = this->actor.world.pos.z + ((doorDirection * 20.0f) * sp78);
|
||||
this->unk_45C.x = this->actor.world.pos.x + ((doorDirection * -120.0f) * sp74);
|
||||
this->unk_45C.z = this->actor.world.pos.z + ((doorDirection * -120.0f) * sp78);
|
||||
|
||||
doorShutter->unk_164 = 1;
|
||||
func_80832224(this);
|
||||
|
@ -4098,21 +4105,25 @@ s32 func_80839800(Player* this, GlobalContext* globalCtx) {
|
|||
|
||||
if (doorShutter->dyna.actor.category == ACTORCAT_DOOR) {
|
||||
this->unk_46A = globalCtx->transitionActorList[(u16)doorShutter->dyna.actor.params >> 10]
|
||||
.sides[(sp7C > 0) ? 0 : 1]
|
||||
.sides[(doorDirection > 0) ? 0 : 1]
|
||||
.effects;
|
||||
|
||||
func_800304B0(globalCtx);
|
||||
}
|
||||
} else {
|
||||
enDoor = (EnDoor*)doorActor;
|
||||
// This actor can be either EnDoor or DoorKiller.
|
||||
// Don't try to access any struct vars other than `animStyle` and `playerIsOpening`! These two variables
|
||||
// are common across the two actors' structs however most other variables are not!
|
||||
door = (EnDoor*)doorActor;
|
||||
|
||||
enDoor->unk_190 = (sp7C < 0.0f) ? ((LINK_IS_ADULT) ? 0 : 1) : ((LINK_IS_ADULT) ? 2 : 3);
|
||||
door->animStyle = (doorDirection < 0.0f) ? ((LINK_IS_ADULT) ? KNOB_ANIM_ADULT_L : KNOB_ANIM_CHILD_L)
|
||||
: ((LINK_IS_ADULT) ? KNOB_ANIM_ADULT_R : KNOB_ANIM_CHILD_R);
|
||||
|
||||
if (enDoor->unk_190 == 0) {
|
||||
if (door->animStyle == KNOB_ANIM_ADULT_L) {
|
||||
sp5C = D_808539EC[this->modelAnimType];
|
||||
} else if (enDoor->unk_190 == 1) {
|
||||
} else if (door->animStyle == KNOB_ANIM_CHILD_L) {
|
||||
sp5C = D_80853A04[this->modelAnimType];
|
||||
} else if (enDoor->unk_190 == 2) {
|
||||
} else if (door->animStyle == KNOB_ANIM_ADULT_R) {
|
||||
sp5C = D_80853A1C[this->modelAnimType];
|
||||
} else {
|
||||
sp5C = D_80853A34[this->modelAnimType];
|
||||
|
@ -4121,7 +4132,7 @@ s32 func_80839800(Player* this, GlobalContext* globalCtx) {
|
|||
func_80835C58(globalCtx, this, func_80845EF8, 0);
|
||||
func_80832528(globalCtx, this);
|
||||
|
||||
if (sp7C < 0) {
|
||||
if (doorDirection < 0) {
|
||||
this->actor.shape.rot.y = doorActor->shape.rot.y;
|
||||
} else {
|
||||
this->actor.shape.rot.y = doorActor->shape.rot.y - 0x8000;
|
||||
|
@ -4129,7 +4140,7 @@ s32 func_80839800(Player* this, GlobalContext* globalCtx) {
|
|||
|
||||
this->currentYaw = this->actor.shape.rot.y;
|
||||
|
||||
sp6C = (sp7C * 22.0f);
|
||||
sp6C = (doorDirection * 22.0f);
|
||||
this->actor.world.pos.x = doorActor->world.pos.x + sp6C * sp74;
|
||||
this->actor.world.pos.z = doorActor->world.pos.z + sp6C * sp78;
|
||||
|
||||
|
@ -4143,12 +4154,12 @@ s32 func_80839800(Player* this, GlobalContext* globalCtx) {
|
|||
func_80832F54(globalCtx, this, 0x28F);
|
||||
|
||||
if (doorActor->parent != NULL) {
|
||||
sp7C = -sp7C;
|
||||
doorDirection = -doorDirection;
|
||||
}
|
||||
|
||||
enDoor->unk_191 = 1;
|
||||
door->playerIsOpening = 1;
|
||||
|
||||
if (this->doorType != 3) {
|
||||
if (this->doorType != PLAYER_DOORTYPE_FAKE) {
|
||||
this->stateFlags1 |= 0x20000000;
|
||||
func_800304B0(globalCtx);
|
||||
|
||||
|
@ -4166,15 +4177,17 @@ s32 func_80839800(Player* this, GlobalContext* globalCtx) {
|
|||
} else {
|
||||
Camera_ChangeDoorCam(Gameplay_GetCamera(globalCtx, 0), doorActor,
|
||||
globalCtx->transitionActorList[(u16)doorActor->params >> 10]
|
||||
.sides[(sp7C > 0) ? 0 : 1]
|
||||
.sides[(doorDirection > 0) ? 0 : 1]
|
||||
.effects,
|
||||
0, 38.0f * D_808535EC, 26.0f * D_808535EC, 10.0f * D_808535EC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((this->doorType != 3) && (doorActor->category == ACTORCAT_DOOR)) {
|
||||
frontRoom = globalCtx->transitionActorList[(u16)doorActor->params >> 10].sides[(sp7C > 0) ? 0 : 1].room;
|
||||
if ((this->doorType != PLAYER_DOORTYPE_FAKE) && (doorActor->category == ACTORCAT_DOOR)) {
|
||||
frontRoom = globalCtx->transitionActorList[(u16)doorActor->params >> 10]
|
||||
.sides[(doorDirection > 0) ? 0 : 1]
|
||||
.room;
|
||||
|
||||
if ((frontRoom >= 0) && (frontRoom != globalCtx->roomCtx.curRoom.num)) {
|
||||
func_8009728C(globalCtx, &globalCtx->roomCtx, frontRoom);
|
||||
|
@ -9168,7 +9181,7 @@ void func_808473D4(GlobalContext* globalCtx, Player* this) {
|
|||
doAction = 0x14;
|
||||
}
|
||||
} else if ((func_8084E3C4 != this->func_674) && !(this->stateFlags2 & 0x40000)) {
|
||||
if ((this->doorType != 0) &&
|
||||
if ((this->doorType != PLAYER_DOORTYPE_NONE) &&
|
||||
(!(this->stateFlags1 & 0x800) || ((heldActor != NULL) && (heldActor->id == ACTOR_EN_RU1)))) {
|
||||
doAction = 4;
|
||||
} else if ((!(this->stateFlags1 & 0x800) || (heldActor == NULL)) && (interactRangeActor != NULL) &&
|
||||
|
@ -10121,7 +10134,7 @@ void Player_UpdateCommon(Player* this, GlobalContext* globalCtx, Input* input) {
|
|||
|
||||
temp_f0 = this->actor.world.pos.y - this->actor.prevPos.y;
|
||||
|
||||
this->doorType = 0;
|
||||
this->doorType = PLAYER_DOORTYPE_NONE;
|
||||
this->unk_8A1 = 0;
|
||||
this->unk_684 = NULL;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue