mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-08-13 17:03:47 -04:00
0f7a88bd5a
* This should fix (all?) 60fps interpolation issues left. Resolves #631 #917 * Update z_fishing.c * Re-adds Emil's interpolation in certain places. * move open/close disps out of if statments checking timer based vars, revert fishing to use recordopen/closed child * move disps out of ifs for morpha * use recordopen/recordclose for volv * recordopen/recordclose for ganondorf * switch back to recordopen/recordclose for ganondorf floor * Frame interpolation now uses a 64bit parameter rather than 32. * More 60fps fixes * Fix close child typo * add todo calls to recordopen/recordclose * fix build * revert long long frame interpolation * add some epochs * add more epochs * bongo epochs * the rest of the epochs * fix the typo fix the build * interpolation fixes pr cleanup * init/cleanup bongo epochs * bongo hand trails * Fixes niw feathers * Fixes bongo bongo hands, and replaces epoch * i with epoch + i * don't update epochs Co-authored-by: briaguya <briaguya@alice>
611 lines
24 KiB
C
611 lines
24 KiB
C
/*
|
||
* File: z_en_g_switch.c
|
||
* Overlay: ovl_En_G_Switch
|
||
* Description: Silver rupees, shooting gallery targets, and horseback archery pots
|
||
*/
|
||
|
||
#include "z_en_g_switch.h"
|
||
#include "vt.h"
|
||
#include "overlays/actors/ovl_En_Syateki_Itm/z_en_syateki_itm.h"
|
||
#include "overlays/effects/ovl_Effect_Ss_Kakera/z_eff_ss_kakera.h"
|
||
#include "overlays/effects/ovl_Effect_Ss_HitMark/z_eff_ss_hitmark.h"
|
||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||
#include "objects/object_tsubo/object_tsubo.h"
|
||
#include "objects/object_gi_rupy/object_gi_rupy.h"
|
||
#include "soh/frame_interpolation.h"
|
||
|
||
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_5)
|
||
|
||
typedef enum {
|
||
/* 0 */ MOVE_TARGET,
|
||
/* 1 */ MOVE_HOME
|
||
} GSwitchMoveState;
|
||
|
||
void EnGSwitch_Init(Actor* thisx, GlobalContext* globalCtx);
|
||
void EnGSwitch_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||
void EnGSwitch_Update(Actor* thisx, GlobalContext* globalCtx);
|
||
void EnGSwitch_DrawRupee(Actor* thisx, GlobalContext* globalCtx);
|
||
void EnGSwitch_DrawPot(Actor* thisx, GlobalContext* globalCtx);
|
||
|
||
void EnGSwitch_SilverRupeeTracker(EnGSwitch* this, GlobalContext* globalCtx);
|
||
void EnGSwitch_SilverRupeeIdle(EnGSwitch* this, GlobalContext* globalCtx);
|
||
void EnGSwitch_WaitForObject(EnGSwitch* this, GlobalContext* globalCtx);
|
||
void EnGSwitch_SilverRupeeCollected(EnGSwitch* this, GlobalContext* globalCtx);
|
||
void EnGSwitch_GalleryRupee(EnGSwitch* this, GlobalContext* globalCtx);
|
||
void EnGSwitch_ArcheryPot(EnGSwitch* this, GlobalContext* globalCtx);
|
||
void EnGSwitch_Kill(EnGSwitch* this, GlobalContext* globalCtx);
|
||
|
||
void EnGSwitch_SpawnEffects(EnGSwitch* this, Vec3f* pos, s16 scale, s16 colorIdx);
|
||
void EnGSwitch_UpdateEffects(EnGSwitch* this, GlobalContext* globalCtx);
|
||
void EnGSwitch_DrawEffects(EnGSwitch* this, GlobalContext* globalCtx);
|
||
|
||
static s16 sCollectedCount = 0;
|
||
|
||
static ColliderCylinderInit sCylinderInit = {
|
||
{
|
||
COLTYPE_NONE,
|
||
AT_NONE,
|
||
AC_ON | AC_TYPE_PLAYER,
|
||
OC1_NONE,
|
||
OC2_TYPE_2,
|
||
COLSHAPE_CYLINDER,
|
||
},
|
||
{
|
||
ELEMTYPE_UNK2,
|
||
{ 0x00000000, 0x00, 0x00 },
|
||
{ 0xFFCFFFFF, 0x00, 0x00 },
|
||
TOUCH_NONE,
|
||
BUMP_ON,
|
||
OCELEM_NONE,
|
||
},
|
||
{ 13, 40, 0, { 0, 0, 0 } },
|
||
};
|
||
|
||
// Unused, but probably intended to be this
|
||
static s16 sRupeeTypes[] = {
|
||
ITEM00_RUPEE_GREEN, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_RED, ITEM00_RUPEE_ORANGE, ITEM00_RUPEE_PURPLE,
|
||
};
|
||
|
||
const ActorInit En_G_Switch_InitVars = {
|
||
ACTOR_EN_G_SWITCH,
|
||
ACTORCAT_PROP,
|
||
FLAGS,
|
||
OBJECT_GAMEPLAY_KEEP,
|
||
sizeof(EnGSwitch),
|
||
(ActorFunc)EnGSwitch_Init,
|
||
(ActorFunc)EnGSwitch_Destroy,
|
||
(ActorFunc)EnGSwitch_Update,
|
||
NULL,
|
||
NULL,
|
||
};
|
||
|
||
void EnGSwitch_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||
s32 pad;
|
||
EnGSwitch* this = (EnGSwitch*)thisx;
|
||
|
||
this->type = (this->actor.params >> 0xC) & 0xF;
|
||
this->switchFlag = this->actor.params & 0x3F;
|
||
this->numEffects = ARRAY_COUNT(this->effects);
|
||
// "index"
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ インデックス ☆☆☆☆☆ %x\n" VT_RST, this->type);
|
||
// "save"
|
||
osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ セーブ\t ☆☆☆☆☆ %x\n" VT_RST, this->switchFlag);
|
||
switch (this->type) {
|
||
case ENGSWITCH_SILVER_TRACKER:
|
||
osSyncPrintf("\n\n");
|
||
// "parent switch spawn"
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 親スイッチ発生 ☆☆☆☆☆ %x\n" VT_RST, this->actor.params);
|
||
sCollectedCount = 0;
|
||
this->silverCount = this->actor.params >> 6;
|
||
this->silverCount &= 0x3F;
|
||
// "maximum number of checks"
|
||
osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ 最大チェック数 ☆☆☆☆☆ %d\n" VT_RST, this->silverCount);
|
||
osSyncPrintf("\n\n");
|
||
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
|
||
// This is a reference to Hokuto no Ken
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ You are Shock! ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag);
|
||
Actor_Kill(&this->actor);
|
||
} else {
|
||
this->actionFunc = EnGSwitch_SilverRupeeTracker;
|
||
}
|
||
break;
|
||
case ENGSWITCH_SILVER_RUPEE:
|
||
osSyncPrintf("\n\n");
|
||
// "child switch spawn"
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 子スイッチ発生 ☆☆☆☆☆ %x\n" VT_RST, this->actor.params);
|
||
this->colorIdx = 5;
|
||
this->numEffects = 20;
|
||
Collider_InitCylinder(globalCtx, &this->collider);
|
||
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
|
||
this->actor.draw = EnGSwitch_DrawRupee;
|
||
this->actor.shape.yOffset = 700.0f;
|
||
|
||
if (CVar_GetS32("gNewDrops", 0) !=0) {
|
||
this->actor.shape.yOffset = 35.0f;
|
||
} else {
|
||
this->actor.shape.yOffset = 700.0f;
|
||
}
|
||
|
||
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ You are Shock! ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag);
|
||
Actor_Kill(&this->actor);
|
||
} else {
|
||
if (CVar_GetS32("gNewDrops", 0) !=0) {
|
||
Actor_SetScale(&this->actor, 0.6f);
|
||
} else {
|
||
Actor_SetScale(&this->actor, 0.03f);
|
||
}
|
||
this->actionFunc = EnGSwitch_SilverRupeeIdle;
|
||
}
|
||
break;
|
||
case ENGSWITCH_ARCHERY_POT:
|
||
osSyncPrintf("\n\n");
|
||
// "Horseback archery destructible pot"
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ やぶさめぶち抜き壷 ☆☆☆☆☆ \n" VT_RST);
|
||
this->actor.gravity = -3.0f;
|
||
this->colorIdx = Rand_ZeroFloat(2.99f);
|
||
Collider_InitCylinder(globalCtx, &this->collider);
|
||
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
|
||
this->actor.scale.x = 0.25f;
|
||
this->actor.scale.y = 0.45f;
|
||
this->actor.scale.z = 0.25f;
|
||
this->collider.info.bumper.dmgFlags = 0x1F820;
|
||
this->objId = OBJECT_TSUBO;
|
||
this->objIndex = Object_GetIndex(&globalCtx->objectCtx, this->objId);
|
||
if (this->objIndex < 0) {
|
||
Actor_Kill(&this->actor);
|
||
// "what?"
|
||
osSyncPrintf(VT_FGCOL(PURPLE) " なにみの? %d\n" VT_RST "\n", this->objIndex);
|
||
// "bank is funny"
|
||
osSyncPrintf(VT_FGCOL(CYAN) " バンクおかしいしぞ!%d\n" VT_RST "\n", this->actor.params);
|
||
}
|
||
this->collider.dim.radius = 24;
|
||
this->collider.dim.height = 74;
|
||
this->collider.dim.yShift = 0;
|
||
this->actionFunc = EnGSwitch_WaitForObject;
|
||
break;
|
||
case ENGSWITCH_TARGET_RUPEE:
|
||
if (CVar_GetS32("gNewDrops", 0) !=0) {
|
||
this->actor.shape.yOffset = 35.0f;
|
||
Actor_SetScale(&this->actor, 0.9f);
|
||
} else {
|
||
this->actor.shape.yOffset = 700.0f;
|
||
Actor_SetScale(&this->actor, 0.05f);
|
||
}
|
||
|
||
Collider_InitCylinder(globalCtx, &this->collider);
|
||
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
|
||
this->actor.draw = EnGSwitch_DrawRupee;
|
||
this->collider.dim.radius = 20;
|
||
this->collider.dim.height = 60;
|
||
this->collider.dim.yShift = 5;
|
||
this->actionFunc = EnGSwitch_GalleryRupee;
|
||
break;
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||
s32 pad;
|
||
EnGSwitch* this = (EnGSwitch*)thisx;
|
||
|
||
Collider_DestroyCylinder(globalCtx, &this->collider);
|
||
}
|
||
|
||
void EnGSwitch_Break(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
Vec3f randPos;
|
||
Vec3f hitPos;
|
||
Vec3f accel = { 0.0f, 0.0f, 0.0f };
|
||
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
|
||
s32 i;
|
||
|
||
randPos.x = this->actor.world.pos.x + Rand_CenteredFloat(40.0f);
|
||
randPos.y = this->actor.world.pos.y + 30.0f + Rand_CenteredFloat(35.0f);
|
||
randPos.z = this->actor.world.pos.z + Rand_CenteredFloat(40.0f);
|
||
hitPos.x = this->collider.info.bumper.hitPos.x;
|
||
hitPos.y = this->collider.info.bumper.hitPos.y;
|
||
hitPos.z = this->collider.info.bumper.hitPos.z;
|
||
EffectSsHitMark_SpawnCustomScale(globalCtx, EFFECT_HITMARK_WHITE, 700, &hitPos);
|
||
if (this->type == ENGSWITCH_ARCHERY_POT) {
|
||
velocity.y = 15.0f;
|
||
EffectSsExtra_Spawn(globalCtx, &hitPos, &velocity, &accel, 5, 2);
|
||
}
|
||
if (this->type == ENGSWITCH_TARGET_RUPEE) {
|
||
for (i = 0; i < this->numEffects; i++) {
|
||
EnGSwitch_SpawnEffects(this, &randPos, 100, this->colorIdx);
|
||
}
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_WaitForObject(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
if (Object_IsLoaded(&globalCtx->objectCtx, this->objIndex)) {
|
||
gSegments[6] = VIRTUAL_TO_PHYSICAL(globalCtx->objectCtx.status[this->objIndex].segment);
|
||
this->actor.objBankIndex = this->objIndex;
|
||
this->actor.draw = EnGSwitch_DrawPot;
|
||
this->actionFunc = EnGSwitch_ArcheryPot;
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_SilverRupeeTracker(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
static s8 majorScale[] = { 0, 2, 4, 5, 7 };
|
||
|
||
if (this->noteIndex < sCollectedCount) {
|
||
if (sCollectedCount < 5) {
|
||
// "sound?"
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 音? ☆☆☆☆☆ %d\n" VT_RST, this->noteIndex);
|
||
Audio_PlaySoundTransposed(&D_801333D4, NA_SE_EV_FIVE_COUNT_LUPY, majorScale[this->noteIndex]);
|
||
this->noteIndex = sCollectedCount;
|
||
}
|
||
}
|
||
if (sCollectedCount >= this->silverCount) {
|
||
// "It is now the end of the century."
|
||
// This another reference to Hokuto no Ken.
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 時はまさに世紀末〜 ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag);
|
||
// "Last!"
|
||
osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ らすとぉ! ☆☆☆☆☆ \n" VT_RST);
|
||
if ((globalCtx->sceneNum == SCENE_MEN) && (this->actor.room == 2)) {
|
||
Flags_SetTempClear(globalCtx, this->actor.room);
|
||
} else {
|
||
func_80078884(NA_SE_SY_CORRECT_CHIME);
|
||
Flags_SetSwitch(globalCtx, this->switchFlag);
|
||
}
|
||
func_80078884(NA_SE_SY_GET_RUPY);
|
||
Actor_Kill(&this->actor);
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_SilverRupeeIdle(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
Player* player = GET_PLAYER(globalCtx);
|
||
|
||
this->actor.shape.rot.y += 0x800;
|
||
if (this->actor.xyzDistToPlayerSq < 900.0f) {
|
||
Rupees_ChangeBy(5);
|
||
sCollectedCount++;
|
||
func_80078884(NA_SE_SY_GET_RUPY);
|
||
this->actor.world.pos = player->actor.world.pos;
|
||
this->actor.world.pos.y += 40.0f;
|
||
if (LINK_IS_ADULT) {
|
||
this->actor.world.pos.y += 20.0f;
|
||
}
|
||
this->actor.gravity = 0.0f;
|
||
this->killTimer = 15;
|
||
this->actionFunc = EnGSwitch_SilverRupeeCollected;
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_SilverRupeeCollected(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
Player* player = GET_PLAYER(globalCtx);
|
||
|
||
this->actor.shape.rot.y += 0x3C0;
|
||
if (this->killTimer == 0) {
|
||
Actor_Kill(&this->actor);
|
||
return;
|
||
}
|
||
this->actor.world.pos = player->actor.world.pos;
|
||
this->actor.world.pos.y =
|
||
player->actor.world.pos.y + 40.0f + (this->killTimer * 0.3f) * Math_SinS(this->killTimer * 0x3A98);
|
||
if (LINK_IS_ADULT) {
|
||
this->actor.world.pos.y += 20.0f;
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_GalleryRupee(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
EnSyatekiItm* gallery;
|
||
|
||
this->actor.shape.rot.y += 0x3C0;
|
||
if (this->delayTimer == 0) {
|
||
switch (this->moveMode) {
|
||
case GSWITCH_THROW:
|
||
Actor_MoveForward(&this->actor);
|
||
if ((this->actor.velocity.y < 0.0f) && (this->actor.world.pos.y < (this->actor.home.pos.y - 50.0f))) {
|
||
gallery = ((EnSyatekiItm*)this->actor.parent);
|
||
this->actor.velocity.y = 0.0f;
|
||
this->actor.gravity = 0.0f;
|
||
if (gallery->actor.update != NULL) {
|
||
gallery->targetState[this->index] = ENSYATEKIHIT_MISS;
|
||
}
|
||
Actor_Kill(&this->actor);
|
||
}
|
||
break;
|
||
case GSWITCH_LEFT:
|
||
func_8002D7EC(&this->actor);
|
||
if ((this->actor.velocity.x < 0.0f) && (this->actor.world.pos.x < this->targetPos.x)) {
|
||
gallery = ((EnSyatekiItm*)this->actor.parent);
|
||
if (gallery->actor.update != NULL) {
|
||
gallery->targetState[this->index] = ENSYATEKIHIT_MISS;
|
||
}
|
||
Actor_Kill(&this->actor);
|
||
}
|
||
break;
|
||
case GSWITCH_RIGHT:
|
||
func_8002D7EC(&this->actor);
|
||
if (this->actor.world.pos.x > this->targetPos.x) {
|
||
gallery = ((EnSyatekiItm*)this->actor.parent);
|
||
if (gallery->actor.update != NULL) {
|
||
gallery->targetState[this->index] = ENSYATEKIHIT_MISS;
|
||
}
|
||
Actor_Kill(&this->actor);
|
||
}
|
||
break;
|
||
default:
|
||
switch (this->moveState) {
|
||
case MOVE_TARGET:
|
||
if ((fabsf(this->actor.world.pos.x - this->targetPos.x) > 5.0f) ||
|
||
(fabsf(this->actor.world.pos.y - this->targetPos.y) > 5.0f)) {
|
||
Math_ApproachF(&this->actor.world.pos.x, this->targetPos.x, 0.3f, 30.0f);
|
||
Math_ApproachF(&this->actor.world.pos.y, this->targetPos.y, 0.3f, 30.0f);
|
||
} else {
|
||
this->moveState = MOVE_HOME;
|
||
this->waitTimer = 60;
|
||
}
|
||
break;
|
||
case MOVE_HOME:
|
||
if (this->waitTimer == 0) {
|
||
if ((fabsf(this->actor.world.pos.x - this->actor.home.pos.x) > 5.0f) ||
|
||
(fabsf(this->actor.world.pos.y - this->actor.home.pos.y) > 5.0f)) {
|
||
Math_ApproachF(&this->actor.world.pos.x, this->actor.home.pos.x, 0.3f, 30.0f);
|
||
Math_ApproachF(&this->actor.world.pos.y, this->actor.home.pos.y, 0.3f, 30.0f);
|
||
} else {
|
||
gallery = ((EnSyatekiItm*)this->actor.parent);
|
||
if (gallery->actor.update != NULL) {
|
||
gallery->targetState[this->index] = ENSYATEKIHIT_MISS;
|
||
}
|
||
Actor_Kill(&this->actor);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
break;
|
||
}
|
||
if ((this->collider.base.acFlags & AC_HIT) || BREG(8)) {
|
||
gallery = ((EnSyatekiItm*)this->actor.parent);
|
||
this->collider.base.acFlags &= ~AC_HIT;
|
||
if (gallery->actor.update != NULL) {
|
||
gallery->hitCount++;
|
||
gallery->targetState[this->index] = ENSYATEKIHIT_HIT;
|
||
func_80078884(NA_SE_EV_HIT_SOUND);
|
||
func_80078884(NA_SE_SY_GET_RUPY);
|
||
// "Yeah !"
|
||
osSyncPrintf(VT_FGCOL(YELLOW) "☆☆☆☆☆ いぇぇーす!HIT!! ☆☆☆☆☆ %d\n" VT_RST, gallery->hitCount);
|
||
EnGSwitch_Break(this, globalCtx);
|
||
this->killTimer = 50;
|
||
this->broken = true;
|
||
this->actionFunc = EnGSwitch_Kill;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_ArcheryPot(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
s32 i;
|
||
s16 angle;
|
||
Vec3f* thisPos = &this->actor.world.pos;
|
||
|
||
this->actor.shape.rot.y += 0x3C0;
|
||
if (this->collider.base.acFlags & AC_HIT) {
|
||
this->collider.base.acFlags &= ~AC_HIT;
|
||
for (i = 0, angle = 0; i < 30; i++, angle += 0x4E20) {
|
||
Vec3f pos;
|
||
Vec3f vel;
|
||
f32 sn = Math_SinS(angle);
|
||
f32 cs = Math_CosS(angle);
|
||
f32 rand;
|
||
s32 phi_s0;
|
||
s32 scale;
|
||
s32 pad;
|
||
|
||
pos.x = sn * 8.0f;
|
||
pos.y = 10.0f + Rand_CenteredFloat(5.0f);
|
||
pos.z = cs * 8.0f;
|
||
|
||
vel.x = pos.x / 2.0f;
|
||
vel.y = 10.0f + Rand_ZeroOne() * 15.0f;
|
||
vel.z = pos.z / 2.0f;
|
||
|
||
pos.x += thisPos->x;
|
||
pos.y += thisPos->y;
|
||
pos.z += thisPos->z;
|
||
|
||
rand = Rand_ZeroOne();
|
||
if (rand < 0.2f) {
|
||
phi_s0 = 0x60;
|
||
} else if (rand < 0.6f) {
|
||
phi_s0 = 0x40;
|
||
} else {
|
||
phi_s0 = 0x20;
|
||
}
|
||
|
||
scale = 30.0f + Rand_ZeroOne() * 130.0f;
|
||
|
||
EffectSsKakera_Spawn(globalCtx, &pos, &vel, thisPos, -240, phi_s0, 10, 10, 0, scale, 0, 0x20, 60,
|
||
KAKERA_COLOR_NONE, OBJECT_TSUBO, object_tsubo_DL_001960);
|
||
}
|
||
func_80033480(globalCtx, thisPos, 30.0f, 4, 20, 50, 0);
|
||
SoundSource_PlaySfxAtFixedWorldPos(globalCtx, thisPos, 40, NA_SE_EV_POT_BROKEN);
|
||
EnGSwitch_Break(this, globalCtx);
|
||
this->killTimer = 50;
|
||
this->broken = true;
|
||
this->actionFunc = EnGSwitch_Kill;
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_Kill(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
if (this->killTimer == 0) {
|
||
Actor_Kill(&this->actor);
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||
s32 pad;
|
||
EnGSwitch* this = (EnGSwitch*)thisx;
|
||
|
||
this->actionFunc(this, globalCtx);
|
||
if (this->killTimer != 0) {
|
||
this->killTimer--;
|
||
}
|
||
if (this->waitTimer != 0) {
|
||
this->waitTimer--;
|
||
}
|
||
if (this->delayTimer != 0) {
|
||
this->delayTimer--;
|
||
}
|
||
if ((this->type != ENGSWITCH_SILVER_TRACKER) && (this->type != ENGSWITCH_SILVER_RUPEE) &&
|
||
(this->type != ENGSWITCH_TARGET_RUPEE)) {
|
||
Actor_MoveForward(&this->actor);
|
||
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 50.0f, 50.0f, 100.0f, 0x1C);
|
||
}
|
||
if (this->actor.draw != NULL) {
|
||
if (this->type == ENGSWITCH_TARGET_RUPEE) {
|
||
EnGSwitch_UpdateEffects(this, globalCtx);
|
||
}
|
||
if ((this->actionFunc != EnGSwitch_Kill) && (this->actionFunc != EnGSwitch_SilverRupeeIdle)) {
|
||
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||
}
|
||
}
|
||
if (BREG(0) && (this->type == ENGSWITCH_SILVER_TRACKER)) {
|
||
DebugDisplay_AddObject(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z,
|
||
this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z, 1.0f, 1.0f,
|
||
1.0f, 255, 0, 0, 255, 4, globalCtx->state.gfxCtx);
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_DrawPot(Actor* thisx, GlobalContext* globalCtx) {
|
||
s32 pad;
|
||
EnGSwitch* this = (EnGSwitch*)thisx;
|
||
|
||
if (!this->broken) {
|
||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||
func_80093D18(globalCtx->state.gfxCtx);
|
||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
|
||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||
gSPDisplayList(POLY_OPA_DISP++, object_tsubo_DL_0017C0);
|
||
CLOSE_DISPS(globalCtx->state.gfxCtx);
|
||
}
|
||
}
|
||
|
||
static void* sRupeeTextures[] = {
|
||
gRupeeGreenTex, gRupeeBlueTex, gRupeeRedTex, gRupeePinkTex, gRupeeOrangeTex, gRupeeSilverTex,
|
||
};
|
||
static void* sRupeeTexturesNew[] = {
|
||
GID_RUPEE_GREEN, GID_RUPEE_BLUE, GID_RUPEE_RED, GID_RUPEE_PURPLE, GID_RUPEE_GOLD,
|
||
};
|
||
void EnGSwitch_DrawRupee(Actor* thisx, GlobalContext* globalCtx) {
|
||
s32 pad;
|
||
EnGSwitch* this = (EnGSwitch*)thisx;
|
||
|
||
if (!this->broken) {
|
||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||
func_80093D18(globalCtx->state.gfxCtx);
|
||
func_8002EBCC(&this->actor, globalCtx, 0);
|
||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||
if (CVar_GetS32("gNewDrops", 0) !=0) {
|
||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD);
|
||
if (this->type == ENGSWITCH_TARGET_RUPEE) {
|
||
GetItem_Draw(globalCtx, sRupeeTexturesNew[this->colorIdx]);
|
||
} else {
|
||
gsDPSetGrayscaleColor(POLY_OPA_DISP++, 255, 255, 255, 255);
|
||
gsSPGrayscale(POLY_OPA_DISP++, true);
|
||
func_80093D18(globalCtx->state.gfxCtx);
|
||
gSPDisplayList(POLY_OPA_DISP++, gGiRupeeInnerDL);
|
||
gSPDisplayList(POLY_OPA_DISP++, gGiGoldRupeeInnerColorDL);
|
||
func_80093D84(globalCtx->state.gfxCtx);
|
||
gSPDisplayList(POLY_OPA_DISP++, gGiRupeeOuterDL);
|
||
gSPDisplayList(POLY_OPA_DISP++, gGiGoldRupeeOuterColorDL);
|
||
gsSPGrayscale(POLY_OPA_DISP++, false);
|
||
}
|
||
} else {
|
||
gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sRupeeTextures[this->colorIdx]));
|
||
gSPDisplayList(POLY_OPA_DISP++, gRupeeDL);
|
||
}
|
||
CLOSE_DISPS(globalCtx->state.gfxCtx);
|
||
}
|
||
if (this->type == ENGSWITCH_TARGET_RUPEE) {
|
||
EnGSwitch_DrawEffects(this, globalCtx);
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_SpawnEffects(EnGSwitch* this, Vec3f* pos, s16 scale, s16 colorIdx) {
|
||
EnGSwitchEffect* effect = this->effects;
|
||
s16 i;
|
||
|
||
for (i = 0; i < this->numEffects; i++, effect++) {
|
||
if (!effect->flag) {
|
||
Vec3f baseVel;
|
||
f32 pitch;
|
||
f32 yaw;
|
||
|
||
effect->epoch++;
|
||
effect->pos = *pos;
|
||
effect->scale = scale;
|
||
effect->colorIdx = colorIdx;
|
||
effect->timer = 30;
|
||
effect->rot.x = effect->rot.y = effect->rot.z = 0.0f;
|
||
pitch = Rand_CenteredFloat(1000.0f) - 13000.0f;
|
||
yaw = Rand_CenteredFloat(65535.0f);
|
||
Matrix_RotateY(yaw, MTXMODE_NEW);
|
||
Matrix_RotateX(pitch, MTXMODE_APPLY);
|
||
baseVel.x = baseVel.y = 0.0f;
|
||
baseVel.z = 20.0f;
|
||
Matrix_MultVec3f(&baseVel, &effect->velocity);
|
||
effect->flag = true;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_UpdateEffects(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
Vec3f temp;
|
||
s16 i;
|
||
EnGSwitchEffect* effect = this->effects;
|
||
|
||
for (i = 0; i < this->numEffects; i++, effect++) {
|
||
if (effect->flag) {
|
||
effect->rot.x += Rand_ZeroOne() * 10.0f + 15.0f;
|
||
effect->rot.y += Rand_ZeroOne() * 10.0f + 15.0f;
|
||
effect->rot.z += Rand_ZeroOne() * 10.0f + 15.0f;
|
||
temp.x = effect->pos.x + effect->velocity.x;
|
||
temp.y = effect->pos.y + effect->velocity.y;
|
||
temp.z = effect->pos.z + effect->velocity.z;
|
||
Math_ApproachF(&effect->pos.x, temp.x, 0.3f, 30.0f);
|
||
Math_ApproachF(&effect->pos.y, temp.y, 0.8f, 250.0f);
|
||
Math_ApproachF(&effect->pos.z, temp.z, 0.3f, 30.0f);
|
||
Math_ApproachF(&effect->velocity.y, -20.0f, 0.9f, 1.0f);
|
||
if (effect->timer != 0) {
|
||
effect->timer--;
|
||
} else if (effect->scale < 10) {
|
||
effect->flag = false;
|
||
} else {
|
||
effect->scale -= 2;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void EnGSwitch_DrawEffects(EnGSwitch* this, GlobalContext* globalCtx) {
|
||
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
|
||
EnGSwitchEffect* effect = this->effects;
|
||
s16 i;
|
||
f32 scale;
|
||
s32 pad;
|
||
|
||
OPEN_DISPS(gfxCtx);
|
||
func_80093D18(globalCtx->state.gfxCtx);
|
||
for (i = 0; i < this->numEffects; i++, effect++) {
|
||
if (effect->flag) {
|
||
FrameInterpolation_RecordOpenChild(effect, effect->epoch);
|
||
scale = effect->scale / 10000.0f;
|
||
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
|
||
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
|
||
Matrix_RotateX(effect->rot.x, MTXMODE_APPLY);
|
||
Matrix_RotateY(effect->rot.y, MTXMODE_APPLY);
|
||
Matrix_RotateZ(effect->rot.z, MTXMODE_APPLY);
|
||
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
|
||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||
gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sRupeeTextures[effect->colorIdx]));
|
||
gSPDisplayList(POLY_OPA_DISP++, gRupeeDL);
|
||
FrameInterpolation_RecordCloseChild();
|
||
}
|
||
}
|
||
CLOSE_DISPS(gfxCtx);
|
||
}
|