mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-08-13 17:03:47 -04:00
c80f9fbd57
* WIP Multiversion support * GC PAL Non-MQ support complete * Updated OtrGui to handle different game versions * Added version file * Added new extract mode to ZAPD and optimized OTR gen time * Fixed bug causing crash * Further optimized OTRExporter, saving around ~20 seconds. * ZAPD is now multi-threaded. * Fixed merge issue * Fixed memory leak and fog issue on pause screen. * Additional fog fixes. Co-authored-by: Jack Walker <7463599+Jack-Walker@users.noreply.github.com>
204 lines
6.9 KiB
C
204 lines
6.9 KiB
C
/*
|
|
* File: z_elf_msg.c
|
|
* Overlay: ovl_Elf_Msg
|
|
* Description: Readable Navi call spot
|
|
*/
|
|
|
|
#include "z_elf_msg.h"
|
|
#include "vt.h"
|
|
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
|
|
|
|
#define FLAGS ACTOR_FLAG_4
|
|
|
|
void ElfMsg_Init(Actor* thisx, GlobalContext* globalCtx);
|
|
void ElfMsg_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|
void ElfMsg_Update(Actor* thisx, GlobalContext* globalCtx);
|
|
void ElfMsg_Draw(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void ElfMsg_CallNaviCuboid(ElfMsg* this, GlobalContext* globalCtx);
|
|
void ElfMsg_CallNaviCylinder(ElfMsg* this, GlobalContext* globalCtx);
|
|
|
|
const ActorInit Elf_Msg_InitVars = {
|
|
ACTOR_ELF_MSG,
|
|
ACTORCAT_ITEMACTION,
|
|
FLAGS,
|
|
OBJECT_GAMEPLAY_KEEP,
|
|
sizeof(ElfMsg),
|
|
(ActorFunc)ElfMsg_Init,
|
|
(ActorFunc)ElfMsg_Destroy,
|
|
(ActorFunc)ElfMsg_Update,
|
|
(ActorFunc)ElfMsg_Draw,
|
|
NULL,
|
|
};
|
|
|
|
static InitChainEntry sInitChain[] = {
|
|
ICHAIN_VEC3F_DIV1000(scale, 1000, ICHAIN_CONTINUE),
|
|
ICHAIN_F32(uncullZoneForward, 1000, ICHAIN_STOP),
|
|
};
|
|
|
|
void ElfMsg_SetupAction(ElfMsg* this, ElfMsgActionFunc actionFunc) {
|
|
this->actionFunc = actionFunc;
|
|
}
|
|
|
|
/**
|
|
* Checks a scene flag - if flag is set, the actor is killed and function returns 1. Otherwise returns 0.
|
|
* Can also set a switch flag from params while killing.
|
|
*/
|
|
s32 ElfMsg_KillCheck(ElfMsg* this, GlobalContext* globalCtx) {
|
|
if ((this->actor.world.rot.y > 0) && (this->actor.world.rot.y < 0x41) &&
|
|
Flags_GetSwitch(globalCtx, this->actor.world.rot.y - 1)) {
|
|
LOG_STRING("共倒れ", "../z_elf_msg.c", 161); // "Mutual destruction"
|
|
if (((this->actor.params >> 8) & 0x3F) != 0x3F) {
|
|
Flags_SetSwitch(globalCtx, (this->actor.params >> 8) & 0x3F);
|
|
}
|
|
Actor_Kill(&this->actor);
|
|
return 1;
|
|
} else if ((this->actor.world.rot.y == -1) && Flags_GetClear(globalCtx, this->actor.room)) {
|
|
LOG_STRING("共倒れ", "../z_elf_msg.c", 172); // "Mutual destruction"
|
|
if (((this->actor.params >> 8) & 0x3F) != 0x3F) {
|
|
Flags_SetSwitch(globalCtx, (this->actor.params >> 8) & 0x3F);
|
|
}
|
|
Actor_Kill(&this->actor);
|
|
return 1;
|
|
} else if (((this->actor.params >> 8) & 0x3F) == 0x3F) {
|
|
return 0;
|
|
} else if (Flags_GetSwitch(globalCtx, (this->actor.params >> 8) & 0x3F)) {
|
|
Actor_Kill(&this->actor);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ElfMsg_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|
ElfMsg* this = (ElfMsg*)thisx;
|
|
|
|
// "Conditions for Elf Tag disappearing"
|
|
osSyncPrintf(VT_FGCOL(CYAN) "\nエルフ タグ 消える条件 %d" VT_RST "\n", (thisx->params >> 8) & 0x3F);
|
|
osSyncPrintf(VT_FGCOL(CYAN) "\nthisx->shape.angle.sy = %d\n" VT_RST, thisx->shape.rot.y);
|
|
if (thisx->shape.rot.y >= 0x41) {
|
|
// "Conditions for Elf Tag appearing"
|
|
osSyncPrintf(VT_FGCOL(CYAN) "\nエルフ タグ 出現条件 %d" VT_RST "\n", thisx->shape.rot.y - 0x41);
|
|
}
|
|
|
|
if (!ElfMsg_KillCheck(this, globalCtx)) {
|
|
Actor_ProcessInitChain(thisx, sInitChain);
|
|
if (thisx->world.rot.x == 0) {
|
|
thisx->scale.z = 0.4f;
|
|
thisx->scale.x = 0.4f;
|
|
} else {
|
|
thisx->scale.x = thisx->scale.z = thisx->world.rot.x * 0.04f;
|
|
}
|
|
|
|
if (thisx->world.rot.z == 0) {
|
|
thisx->scale.y = 0.4f;
|
|
} else {
|
|
thisx->scale.y = thisx->world.rot.z * 0.04f;
|
|
}
|
|
|
|
if (thisx->params & 0x4000) {
|
|
ElfMsg_SetupAction(this, ElfMsg_CallNaviCuboid);
|
|
} else {
|
|
ElfMsg_SetupAction(this, ElfMsg_CallNaviCylinder);
|
|
}
|
|
|
|
thisx->shape.rot.x = thisx->shape.rot.y = thisx->shape.rot.z = 0;
|
|
}
|
|
}
|
|
|
|
void ElfMsg_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
|
}
|
|
|
|
s32 ElfMsg_GetMessageId(ElfMsg* this) {
|
|
// Negative message ID forces link to talk to Navi
|
|
if (this->actor.params & 0x8000) {
|
|
return (this->actor.params & 0xFF) + 0x100;
|
|
} else {
|
|
return -((this->actor.params & 0xFF) + 0x100);
|
|
}
|
|
}
|
|
|
|
void ElfMsg_CallNaviCuboid(ElfMsg* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
EnElf* navi = (EnElf*)player->naviActor;
|
|
|
|
if ((fabsf(player->actor.world.pos.x - this->actor.world.pos.x) < (100.0f * this->actor.scale.x)) &&
|
|
(this->actor.world.pos.y <= player->actor.world.pos.y) &&
|
|
((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y)) &&
|
|
(fabsf(player->actor.world.pos.z - this->actor.world.pos.z) < (100.0f * this->actor.scale.z))) {
|
|
player->naviTextId = ElfMsg_GetMessageId(this);
|
|
navi->elfMsg = this;
|
|
}
|
|
}
|
|
|
|
s32 ElfMsg_WithinXZDistance(Vec3f* pos1, Vec3f* pos2, f32 distance) {
|
|
return (SQ(pos2->x - pos1->x) + SQ(pos2->z - pos1->z)) < SQ(distance);
|
|
}
|
|
|
|
void ElfMsg_CallNaviCylinder(ElfMsg* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
EnElf* navi = (EnElf*)player->naviActor;
|
|
|
|
// This fixes a crash when using a grotto exit when you never properly entered
|
|
if (navi == NULL)
|
|
return;
|
|
|
|
if (ElfMsg_WithinXZDistance(&player->actor.world.pos, &this->actor.world.pos, this->actor.scale.x * 100.0f) &&
|
|
(this->actor.world.pos.y <= player->actor.world.pos.y) &&
|
|
((player->actor.world.pos.y - this->actor.world.pos.y) < (100.0f * this->actor.scale.y))) {
|
|
player->naviTextId = ElfMsg_GetMessageId(this);
|
|
navi->elfMsg = this;
|
|
}
|
|
}
|
|
|
|
void ElfMsg_Update(Actor* thisx, GlobalContext* globalCtx) {
|
|
ElfMsg* this = (ElfMsg*)thisx;
|
|
|
|
if (!ElfMsg_KillCheck(this, globalCtx)) {
|
|
if (Actor_ProcessTalkRequest(&this->actor, globalCtx)) {
|
|
if (((this->actor.params >> 8) & 0x3F) != 0x3F) {
|
|
Flags_SetSwitch(globalCtx, (this->actor.params >> 8) & 0x3F);
|
|
}
|
|
Actor_Kill(&this->actor);
|
|
return;
|
|
}
|
|
if ((this->actor.world.rot.y <= 0x41) || (this->actor.world.rot.y > 0x80) ||
|
|
Flags_GetSwitch(globalCtx, this->actor.world.rot.y - 0x41)) {
|
|
this->actionFunc(this, globalCtx);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef ZELDA_DEBUG
|
|
#include "overlays/ovl_Elf_Msg/ovl_Elf_Msg.h"
|
|
#endif
|
|
|
|
void ElfMsg_Draw(Actor* thisx, GlobalContext* globalCtx)
|
|
{
|
|
#ifdef ZELDA_DEBUG
|
|
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_elf_msg.c", 436);
|
|
|
|
if (R_NAVI_MSG_REGION_ALPHA == 0) {
|
|
return;
|
|
}
|
|
|
|
func_80093D18(globalCtx->state.gfxCtx);
|
|
if (thisx->params & 0x8000) {
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 100, 100, R_NAVI_MSG_REGION_ALPHA);
|
|
} else {
|
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, R_NAVI_MSG_REGION_ALPHA);
|
|
}
|
|
|
|
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_elf_msg.c", 448),
|
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
gSPDisplayList(POLY_XLU_DISP++, D_809AD278);
|
|
|
|
if (thisx->params & 0x4000) {
|
|
gSPDisplayList(POLY_XLU_DISP++, sCubeDL);
|
|
} else {
|
|
gSPDisplayList(POLY_XLU_DISP++, sCylinderDL);
|
|
}
|
|
|
|
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_elf_msg.c", 457);
|
|
#endif
|
|
}
|