mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-08-13 17:03:47 -04:00
289 lines
10 KiB
C
289 lines
10 KiB
C
|
/*
|
||
|
* File: z_obj_kibako.c
|
||
|
* Overlay: ovl_Obj_Kibako
|
||
|
* Description: Small wooden box
|
||
|
*/
|
||
|
|
||
|
#include "z_obj_kibako.h"
|
||
|
#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h"
|
||
|
#include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h"
|
||
|
|
||
|
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_26)
|
||
|
|
||
|
void ObjKibako_Init(Actor* thisx, GlobalContext* globalCtx);
|
||
|
void ObjKibako_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||
|
void ObjKibako_Update(Actor* thisx, GlobalContext* globalCtx);
|
||
|
void ObjKibako_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||
|
|
||
|
void ObjKibako_SetupIdle(ObjKibako* this);
|
||
|
void ObjKibako_Idle(ObjKibako* this, GlobalContext* globalCtx);
|
||
|
void ObjKibako_SetupHeld(ObjKibako* this);
|
||
|
void ObjKibako_Held(ObjKibako* this, GlobalContext* globalCtx);
|
||
|
void ObjKibako_SetupThrown(ObjKibako* this);
|
||
|
void ObjKibako_Thrown(ObjKibako* this, GlobalContext* globalCtx);
|
||
|
|
||
|
const ActorInit Obj_Kibako_InitVars = {
|
||
|
ACTOR_OBJ_KIBAKO,
|
||
|
ACTORCAT_PROP,
|
||
|
FLAGS,
|
||
|
OBJECT_GAMEPLAY_DANGEON_KEEP,
|
||
|
sizeof(ObjKibako),
|
||
|
(ActorFunc)ObjKibako_Init,
|
||
|
(ActorFunc)ObjKibako_Destroy,
|
||
|
(ActorFunc)ObjKibako_Update,
|
||
|
(ActorFunc)ObjKibako_Draw,
|
||
|
NULL,
|
||
|
};
|
||
|
|
||
|
static ColliderCylinderInit sCylinderInit = {
|
||
|
{
|
||
|
COLTYPE_NONE,
|
||
|
AT_ON | AT_TYPE_PLAYER,
|
||
|
AC_ON | AC_TYPE_PLAYER,
|
||
|
OC1_ON | OC1_TYPE_ALL,
|
||
|
OC2_TYPE_2,
|
||
|
COLSHAPE_CYLINDER,
|
||
|
},
|
||
|
{
|
||
|
ELEMTYPE_UNK0,
|
||
|
{ 0x00000002, 0x00, 0x01 },
|
||
|
{ 0x4FC00748, 0x00, 0x00 },
|
||
|
TOUCH_ON | TOUCH_SFX_NORMAL,
|
||
|
BUMP_ON,
|
||
|
OCELEM_ON,
|
||
|
},
|
||
|
{ 12, 27, 0, { 0, 0, 0 } },
|
||
|
};
|
||
|
|
||
|
static CollisionCheckInfoInit sCCInfoInit = { 0, 12, 60, MASS_HEAVY };
|
||
|
|
||
|
static InitChainEntry sInitChain[] = {
|
||
|
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_CONTINUE),
|
||
|
ICHAIN_F32(uncullZoneForward, 1000, ICHAIN_CONTINUE),
|
||
|
ICHAIN_F32(uncullZoneScale, 60, ICHAIN_CONTINUE),
|
||
|
ICHAIN_F32(uncullZoneDownward, 1000, ICHAIN_STOP),
|
||
|
};
|
||
|
|
||
|
void ObjKibako_SpawnCollectible(ObjKibako* this, GlobalContext* globalCtx) {
|
||
|
s16 collectible;
|
||
|
|
||
|
collectible = this->actor.params & 0x1F;
|
||
|
if ((collectible >= 0) && (collectible <= 0x19)) {
|
||
|
Item_DropCollectible(globalCtx, &this->actor.world.pos,
|
||
|
collectible | (((this->actor.params >> 8) & 0x3F) << 8));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ObjKibako_ApplyGravity(ObjKibako* this) {
|
||
|
this->actor.velocity.y += this->actor.gravity;
|
||
|
if (this->actor.velocity.y < this->actor.minVelocityY) {
|
||
|
this->actor.velocity.y = this->actor.minVelocityY;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ObjKibako_InitCollider(Actor* thisx, GlobalContext* globalCtx) {
|
||
|
ObjKibako* this = (ObjKibako*)thisx;
|
||
|
|
||
|
Collider_InitCylinder(globalCtx, &this->collider);
|
||
|
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
|
||
|
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||
|
}
|
||
|
|
||
|
void ObjKibako_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||
|
s32 pad;
|
||
|
ObjKibako* this = (ObjKibako*)thisx;
|
||
|
|
||
|
Actor_ProcessInitChain(&this->actor, sInitChain);
|
||
|
this->actor.gravity = -1.2f;
|
||
|
this->actor.minVelocityY = -13.0f;
|
||
|
ObjKibako_InitCollider(&this->actor, globalCtx);
|
||
|
CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sCCInfoInit);
|
||
|
ObjKibako_SetupIdle(this);
|
||
|
// "wooden box"
|
||
|
osSyncPrintf("(dungeon keep 木箱)(arg_data 0x%04x)\n", this->actor.params);
|
||
|
}
|
||
|
|
||
|
void ObjKibako_Destroy(Actor* thisx, GlobalContext* globalCtx2) {
|
||
|
GlobalContext* globalCtx = globalCtx2;
|
||
|
ObjKibako* this = (ObjKibako*)thisx;
|
||
|
|
||
|
Collider_DestroyCylinder(globalCtx, &this->collider);
|
||
|
}
|
||
|
|
||
|
void ObjKibako_AirBreak(ObjKibako* this, GlobalContext* globalCtx) {
|
||
|
s16 angle;
|
||
|
s32 i;
|
||
|
Vec3f* breakPos = &this->actor.world.pos;
|
||
|
Vec3f pos;
|
||
|
Vec3f velocity;
|
||
|
|
||
|
for (i = 0, angle = 0; i < 12; i++, angle += 0x4E20) {
|
||
|
f32 sn = Math_SinS(angle);
|
||
|
f32 cs = Math_CosS(angle);
|
||
|
f32 temp_rand;
|
||
|
s16 phi_s0;
|
||
|
|
||
|
pos.x = sn * 16.0f;
|
||
|
pos.y = (Rand_ZeroOne() * 5.0f) + 2.0f;
|
||
|
pos.z = cs * 16.0f;
|
||
|
velocity.x = pos.x * 0.2f;
|
||
|
velocity.y = (Rand_ZeroOne() * 6.0f) + 2.0f;
|
||
|
velocity.z = pos.z * 0.2f;
|
||
|
pos.x += breakPos->x;
|
||
|
pos.y += breakPos->y;
|
||
|
pos.z += breakPos->z;
|
||
|
temp_rand = Rand_ZeroOne();
|
||
|
if (temp_rand < 0.1f) {
|
||
|
phi_s0 = 0x60;
|
||
|
} else if (temp_rand < 0.7f) {
|
||
|
phi_s0 = 0x40;
|
||
|
} else {
|
||
|
phi_s0 = 0x20;
|
||
|
}
|
||
|
EffectSsKakera_Spawn(globalCtx, &pos, &velocity, breakPos, -200, phi_s0, 10, 10, 0,
|
||
|
(Rand_ZeroOne() * 30.0f) + 10.0f, 0, 32, 60, KAKERA_COLOR_NONE,
|
||
|
OBJECT_GAMEPLAY_DANGEON_KEEP, gSmallWoodenBoxFragmentDL);
|
||
|
}
|
||
|
func_80033480(globalCtx, &this->actor.world.pos, 40.0f, 3, 50, 140, 1);
|
||
|
}
|
||
|
|
||
|
void ObjKibako_WaterBreak(ObjKibako* this, GlobalContext* globalCtx) {
|
||
|
s16 angle;
|
||
|
s32 i;
|
||
|
Vec3f* breakPos = &this->actor.world.pos;
|
||
|
Vec3f pos;
|
||
|
Vec3f velocity;
|
||
|
|
||
|
pos = *breakPos;
|
||
|
pos.y += this->actor.yDistToWater;
|
||
|
EffectSsGSplash_Spawn(globalCtx, &pos, NULL, NULL, 0, 500);
|
||
|
|
||
|
for (i = 0, angle = 0; i < 12; i++, angle += 0x4E20) {
|
||
|
f32 sn = Math_SinS(angle);
|
||
|
f32 cs = Math_CosS(angle);
|
||
|
f32 temp_rand;
|
||
|
s16 phi_s0;
|
||
|
|
||
|
pos.x = sn * 16.0f;
|
||
|
pos.y = (Rand_ZeroOne() * 5.0f) + 2.0f;
|
||
|
pos.z = cs * 16.0f;
|
||
|
velocity.x = pos.x * 0.18f;
|
||
|
velocity.y = (Rand_ZeroOne() * 4.0f) + 2.0f;
|
||
|
velocity.z = pos.z * 0.18f;
|
||
|
pos.x += breakPos->x;
|
||
|
pos.y += breakPos->y;
|
||
|
pos.z += breakPos->z;
|
||
|
temp_rand = Rand_ZeroOne();
|
||
|
phi_s0 = (temp_rand < 0.2f) ? 0x40 : 0x20;
|
||
|
EffectSsKakera_Spawn(globalCtx, &pos, &velocity, breakPos, -180, phi_s0, 30, 30, 0,
|
||
|
(Rand_ZeroOne() * 30.0f) + 10.0f, 0, 32, 70, KAKERA_COLOR_NONE,
|
||
|
OBJECT_GAMEPLAY_DANGEON_KEEP, gSmallWoodenBoxFragmentDL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ObjKibako_SetupIdle(ObjKibako* this) {
|
||
|
this->actionFunc = ObjKibako_Idle;
|
||
|
this->actor.colChkInfo.mass = MASS_HEAVY;
|
||
|
}
|
||
|
|
||
|
void ObjKibako_Idle(ObjKibako* this, GlobalContext* globalCtx) {
|
||
|
s32 pad;
|
||
|
|
||
|
if (Actor_HasParent(&this->actor, globalCtx)) {
|
||
|
ObjKibako_SetupHeld(this);
|
||
|
} else if ((this->actor.bgCheckFlags & 0x20) && (this->actor.yDistToWater > 19.0f)) {
|
||
|
ObjKibako_WaterBreak(this, globalCtx);
|
||
|
SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_WOODBOX_BREAK);
|
||
|
ObjKibako_SpawnCollectible(this, globalCtx);
|
||
|
Actor_Kill(&this->actor);
|
||
|
} else if (this->collider.base.acFlags & AC_HIT) {
|
||
|
ObjKibako_AirBreak(this, globalCtx);
|
||
|
SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_WOODBOX_BREAK);
|
||
|
ObjKibako_SpawnCollectible(this, globalCtx);
|
||
|
Actor_Kill(&this->actor);
|
||
|
} else {
|
||
|
Actor_MoveForward(&this->actor);
|
||
|
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 19.0f, 20.0f, 0.0f, 5);
|
||
|
if (!(this->collider.base.ocFlags1 & OC1_TYPE_PLAYER) && (this->actor.xzDistToPlayer > 28.0f)) {
|
||
|
this->collider.base.ocFlags1 |= OC1_TYPE_PLAYER;
|
||
|
}
|
||
|
if (this->actor.xzDistToPlayer < 600.0f) {
|
||
|
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||
|
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||
|
if (this->actor.xzDistToPlayer < 180.0f) {
|
||
|
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||
|
}
|
||
|
}
|
||
|
if (this->actor.xzDistToPlayer < 100.0f) {
|
||
|
func_8002F580(&this->actor, globalCtx);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ObjKibako_SetupHeld(ObjKibako* this) {
|
||
|
this->actionFunc = ObjKibako_Held;
|
||
|
this->actor.room = -1;
|
||
|
func_8002F7DC(&this->actor, NA_SE_PL_PULL_UP_WOODBOX);
|
||
|
}
|
||
|
|
||
|
void ObjKibako_Held(ObjKibako* this, GlobalContext* globalCtx) {
|
||
|
if (Actor_HasNoParent(&this->actor, globalCtx)) {
|
||
|
this->actor.room = globalCtx->roomCtx.curRoom.num;
|
||
|
if (fabsf(this->actor.speedXZ) < 0.1f) {
|
||
|
Audio_PlayActorSound2(&this->actor, NA_SE_EV_PUT_DOWN_WOODBOX);
|
||
|
ObjKibako_SetupIdle(this);
|
||
|
this->collider.base.ocFlags1 &= ~OC1_TYPE_PLAYER;
|
||
|
} else {
|
||
|
ObjKibako_SetupThrown(this);
|
||
|
ObjKibako_ApplyGravity(this);
|
||
|
func_8002D7EC(&this->actor);
|
||
|
}
|
||
|
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 19.0f, 20.0f, 0.0f, 5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ObjKibako_SetupThrown(ObjKibako* this) {
|
||
|
this->actor.velocity.x = Math_SinS(this->actor.world.rot.y) * this->actor.speedXZ;
|
||
|
this->actor.velocity.z = Math_CosS(this->actor.world.rot.y) * this->actor.speedXZ;
|
||
|
this->actor.colChkInfo.mass = 240;
|
||
|
this->actionFunc = ObjKibako_Thrown;
|
||
|
}
|
||
|
|
||
|
void ObjKibako_Thrown(ObjKibako* this, GlobalContext* globalCtx) {
|
||
|
s32 pad;
|
||
|
s32 pad2;
|
||
|
|
||
|
if ((this->actor.bgCheckFlags & 0xB) || (this->collider.base.atFlags & AT_HIT)) {
|
||
|
ObjKibako_AirBreak(this, globalCtx);
|
||
|
SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_WOODBOX_BREAK);
|
||
|
ObjKibako_SpawnCollectible(this, globalCtx);
|
||
|
Actor_Kill(&this->actor);
|
||
|
} else if (this->actor.bgCheckFlags & 0x40) {
|
||
|
ObjKibako_WaterBreak(this, globalCtx);
|
||
|
SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_WOODBOX_BREAK);
|
||
|
ObjKibako_SpawnCollectible(this, globalCtx);
|
||
|
Actor_Kill(&this->actor);
|
||
|
} else {
|
||
|
ObjKibako_ApplyGravity(this);
|
||
|
func_8002D7EC(&this->actor);
|
||
|
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 19.0f, 20.0f, 0.0f, 5);
|
||
|
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||
|
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||
|
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ObjKibako_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||
|
s32 pad;
|
||
|
ObjKibako* this = (ObjKibako*)thisx;
|
||
|
|
||
|
this->actionFunc(this, globalCtx);
|
||
|
}
|
||
|
|
||
|
void ObjKibako_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||
|
s32 pad;
|
||
|
ObjKibako* this = (ObjKibako*)thisx;
|
||
|
|
||
|
Gfx_DrawDListOpa(globalCtx, gSmallWoodenBoxDL);
|
||
|
}
|