mirror of
https://github.com/zeldaret/oot.git
synced 2024-11-25 09:45:02 +00:00
Document Bg_Ice_Shelter (Red Ice) (#1358)
* Doc BgIceShelter * Fix comment and add macro * Various fixes * Rename switch flag macro
This commit is contained in:
parent
9771afdc69
commit
8c17339e06
3 changed files with 198 additions and 128 deletions
|
@ -2,23 +2,23 @@
|
||||||
<File Name="object_ice_objects" Segment="6">
|
<File Name="object_ice_objects" Segment="6">
|
||||||
<DList Name="object_ice_objects_DL_000190" Offset="0x190"/>
|
<DList Name="object_ice_objects_DL_000190" Offset="0x190"/>
|
||||||
<Collision Name="object_ice_objects_Col_0003F0" Offset="0x3F0"/>
|
<Collision Name="object_ice_objects_Col_0003F0" Offset="0x3F0"/>
|
||||||
<DList Name="object_ice_objects_DL_0006F0" Offset="0x6F0"/>
|
<DList Name="gRedIceBlockDL" Offset="0x6F0"/>
|
||||||
<DList Name="object_ice_objects_DL_0012A0" Offset="0x12A0"/>
|
<DList Name="gRedIcePlatformDL" Offset="0x12A0"/>
|
||||||
<Collision Name="object_ice_objects_Col_001C1C" Offset="0x1C1C"/>
|
<Collision Name="gRedIcePlatformCol" Offset="0x1C1C"/>
|
||||||
<DList Name="object_ice_objects_DL_001D10" Offset="0x1D10"/>
|
<DList Name="object_ice_objects_DL_001D10" Offset="0x1D10"/>
|
||||||
<DList Name="object_ice_objects_DL_0021F0" Offset="0x21F0"/>
|
<DList Name="object_ice_objects_DL_0021F0" Offset="0x21F0"/>
|
||||||
<DList Name="object_ice_objects_DL_0023D0" Offset="0x23D0"/>
|
<DList Name="object_ice_objects_DL_0023D0" Offset="0x23D0"/>
|
||||||
<Collision Name="object_ice_objects_Col_002594" Offset="0x2594"/>
|
<Collision Name="object_ice_objects_Col_002594" Offset="0x2594"/>
|
||||||
<DList Name="object_ice_objects_DL_002640" Offset="0x2640"/>
|
<DList Name="gRedIceWallDL" Offset="0x2640"/>
|
||||||
<DList Name="object_ice_objects_DL_002740" Offset="0x2740"/>
|
<DList Name="object_ice_objects_DL_002740" Offset="0x2740"/>
|
||||||
<Collision Name="object_ice_objects_Col_002854" Offset="0x2854"/>
|
<Collision Name="object_ice_objects_Col_002854" Offset="0x2854"/>
|
||||||
<Collision Name="object_ice_objects_Col_002920" Offset="0x2920"/>
|
<Collision Name="gRedIceWallCol" Offset="0x2920"/>
|
||||||
<Texture Name="object_ice_objects_Tex_002950" OutName="tex_00002950" Format="rgba16" Width="32" Height="32" Offset="0x2950"/>
|
<Texture Name="object_ice_objects_Tex_002950" OutName="tex_00002950" Format="rgba16" Width="32" Height="32" Offset="0x2950"/>
|
||||||
<Texture Name="object_ice_objects_Tex_003150" OutName="tex_00003150" Format="i8" Width="32" Height="128" Offset="0x3150"/>
|
<Texture Name="gRedIceWallTex" OutName="red_ice_wall" Format="i8" Width="32" Height="128" Offset="0x3150"/>
|
||||||
<Texture Name="object_ice_objects_Tex_004150" OutName="tex_00004150" Format="rgba16" Width="32" Height="32" Offset="0x4150"/>
|
<Texture Name="object_ice_objects_Tex_004150" OutName="tex_00004150" Format="rgba16" Width="32" Height="32" Offset="0x4150"/>
|
||||||
<Texture Name="object_ice_objects_Tex_004950" OutName="tex_00004950" Format="rgba16" Width="32" Height="32" Offset="0x4950"/>
|
<Texture Name="object_ice_objects_Tex_004950" OutName="tex_00004950" Format="rgba16" Width="32" Height="32" Offset="0x4950"/>
|
||||||
<Texture Name="object_ice_objects_Tex_005150" OutName="tex_00005150" Format="i8" Width="32" Height="32" Offset="0x5150"/>
|
<Texture Name="gRedIceBlockTex" OutName="red_ice_block" Format="i8" Width="32" Height="32" Offset="0x5150"/>
|
||||||
<Texture Name="object_ice_objects_Tex_005550" OutName="tex_00005550" Format="i4" Width="64" Height="64" Offset="0x5550"/>
|
<Texture Name="gRedIcePlatformTex" OutName="red_ice_platform" Format="i4" Width="64" Height="64" Offset="0x5550"/>
|
||||||
<Texture Name="object_ice_objects_Tex_005D50" OutName="tex_00005D50" Format="i8" Width="64" Height="64" Offset="0x5D50"/>
|
<Texture Name="object_ice_objects_Tex_005D50" OutName="tex_00005D50" Format="i8" Width="64" Height="64" Offset="0x5D50"/>
|
||||||
<Texture Name="object_ice_objects_Tex_006D50" OutName="tex_00006D50" Format="rgba16" Width="32" Height="64" Offset="0x6D50"/>
|
<Texture Name="object_ice_objects_Tex_006D50" OutName="tex_00006D50" Format="rgba16" Width="32" Height="64" Offset="0x6D50"/>
|
||||||
<Texture Name="object_ice_objects_Tex_007D50" OutName="tex_00007D50" Format="ia8" Width="64" Height="64" Offset="0x7D50"/>
|
<Texture Name="object_ice_objects_Tex_007D50" OutName="tex_00007D50" Format="ia8" Width="64" Height="64" Offset="0x7D50"/>
|
||||||
|
|
|
@ -1,18 +1,27 @@
|
||||||
|
/*
|
||||||
|
* File: z_bg_ice_shelter.c
|
||||||
|
* Overlay: Bg_Ice_Shelter
|
||||||
|
* Description: Red Ice
|
||||||
|
*/
|
||||||
|
|
||||||
#include "z_bg_ice_shelter.h"
|
#include "z_bg_ice_shelter.h"
|
||||||
#include "assets/objects/object_ice_objects/object_ice_objects.h"
|
#include "assets/objects/object_ice_objects/object_ice_objects.h"
|
||||||
|
|
||||||
#define FLAGS 0
|
#define FLAGS 0
|
||||||
|
|
||||||
|
#define BGICESHELTER_GET_TYPE(thisx) (((thisx)->params >> 8) & 7)
|
||||||
|
#define BGICESHELTER_NO_SWITCH_FLAG(thisx) (((thisx)->params >> 6) & 1)
|
||||||
|
|
||||||
void BgIceShelter_Init(Actor* thisx, PlayState* play);
|
void BgIceShelter_Init(Actor* thisx, PlayState* play);
|
||||||
void BgIceShelter_Destroy(Actor* thisx, PlayState* play);
|
void BgIceShelter_Destroy(Actor* thisx, PlayState* play);
|
||||||
void BgIceShelter_Update(Actor* thisx, PlayState* play);
|
void BgIceShelter_Update(Actor* thisx, PlayState* play);
|
||||||
void BgIceShelter_Draw(Actor* thisx, PlayState* play2);
|
void BgIceShelter_Draw(Actor* thisx, PlayState* play2);
|
||||||
|
|
||||||
void func_80891064(BgIceShelter* this);
|
void BgIceShelter_SetupIdle(BgIceShelter* this);
|
||||||
void func_808911BC(BgIceShelter* this);
|
void BgIceShelter_SetupMelt(BgIceShelter* this);
|
||||||
|
|
||||||
void func_8089107C(BgIceShelter* this, PlayState* play);
|
void BgIceShelter_Idle(BgIceShelter* this, PlayState* play);
|
||||||
void func_808911D4(BgIceShelter* this, PlayState* play);
|
void BgIceShelter_Melt(BgIceShelter* this, PlayState* play);
|
||||||
|
|
||||||
const ActorInit Bg_Ice_Shelter_InitVars = {
|
const ActorInit Bg_Ice_Shelter_InitVars = {
|
||||||
ACTOR_BG_ICE_SHELTER,
|
ACTOR_BG_ICE_SHELTER,
|
||||||
|
@ -26,12 +35,12 @@ const ActorInit Bg_Ice_Shelter_InitVars = {
|
||||||
(ActorFunc)BgIceShelter_Draw,
|
(ActorFunc)BgIceShelter_Draw,
|
||||||
};
|
};
|
||||||
|
|
||||||
static f32 sScales[] = { 0.1f, 0.06f, 0.1f, 0.1f, 0.25f };
|
static f32 sRedIceScales[] = { 0.1f, 0.06f, 0.1f, 0.1f, 0.25f };
|
||||||
|
|
||||||
static Color_RGBA8 sDustPrimColor = { 250, 250, 250, 255 };
|
static Color_RGBA8 sSteamPrimColor = { 250, 250, 250, 255 };
|
||||||
static Color_RGBA8 sDustEnvColor = { 180, 180, 180, 255 };
|
static Color_RGBA8 sSteamEnvColor = { 180, 180, 180, 255 };
|
||||||
|
|
||||||
static ColliderCylinderInit D_8089170C = {
|
static ColliderCylinderInit sCylinderInit1 = {
|
||||||
{
|
{
|
||||||
COLTYPE_NONE,
|
COLTYPE_NONE,
|
||||||
AT_NONE,
|
AT_NONE,
|
||||||
|
@ -51,7 +60,7 @@ static ColliderCylinderInit D_8089170C = {
|
||||||
{ 0, 0, 0, { 0, 0, 0 } },
|
{ 0, 0, 0, { 0, 0, 0 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
static ColliderCylinderInit D_80891738 = {
|
static ColliderCylinderInit sCylinderInit2 = {
|
||||||
{
|
{
|
||||||
COLTYPE_HARD,
|
COLTYPE_HARD,
|
||||||
AT_NONE,
|
AT_NONE,
|
||||||
|
@ -71,34 +80,39 @@ static ColliderCylinderInit D_80891738 = {
|
||||||
{ 0, 0, 0, { 0, 0, 0 } },
|
{ 0, 0, 0, { 0, 0, 0 } },
|
||||||
};
|
};
|
||||||
|
|
||||||
void func_80890740(BgIceShelter* this, PlayState* play) {
|
/**
|
||||||
|
* Initializes either one or both cylinder colliders, depending on the actor's type.
|
||||||
|
*/
|
||||||
|
void BgIceShelter_InitColliders(BgIceShelter* this, PlayState* play) {
|
||||||
static s16 cylinderRadii[] = { 47, 33, 44, 41, 100 };
|
static s16 cylinderRadii[] = { 47, 33, 44, 41, 100 };
|
||||||
static s16 cylinderHeights[] = { 80, 54, 90, 60, 200 };
|
static s16 cylinderHeights[] = { 80, 54, 90, 60, 200 };
|
||||||
s32 pad;
|
s32 pad;
|
||||||
s32 type = (this->dyna.actor.params >> 8) & 7;
|
s32 type = BGICESHELTER_GET_TYPE(&this->dyna.actor);
|
||||||
|
|
||||||
|
// All types use at least one collider in order to detect blue fire
|
||||||
Collider_InitCylinder(play, &this->cylinder1);
|
Collider_InitCylinder(play, &this->cylinder1);
|
||||||
Collider_SetCylinder(play, &this->cylinder1, &this->dyna.actor, &D_8089170C);
|
Collider_SetCylinder(play, &this->cylinder1, &this->dyna.actor, &sCylinderInit1);
|
||||||
Collider_UpdateCylinder(&this->dyna.actor, &this->cylinder1);
|
Collider_UpdateCylinder(&this->dyna.actor, &this->cylinder1);
|
||||||
|
|
||||||
this->cylinder1.dim.radius = cylinderRadii[type];
|
this->cylinder1.dim.radius = cylinderRadii[type];
|
||||||
this->cylinder1.dim.height = cylinderHeights[type];
|
this->cylinder1.dim.height = cylinderHeights[type];
|
||||||
|
|
||||||
if (type == 0 || type == 1 || type == 4) {
|
// The wall and platform types use DynaPoly for collision, so they don't need the second collider
|
||||||
|
if (type == RED_ICE_LARGE || type == RED_ICE_SMALL || type == RED_ICE_KING_ZORA) {
|
||||||
Collider_InitCylinder(play, &this->cylinder2);
|
Collider_InitCylinder(play, &this->cylinder2);
|
||||||
Collider_SetCylinder(play, &this->cylinder2, &this->dyna.actor, &D_80891738);
|
Collider_SetCylinder(play, &this->cylinder2, &this->dyna.actor, &sCylinderInit2);
|
||||||
Collider_UpdateCylinder(&this->dyna.actor, &this->cylinder2);
|
Collider_UpdateCylinder(&this->dyna.actor, &this->cylinder2);
|
||||||
this->cylinder2.dim.radius = cylinderRadii[type];
|
this->cylinder2.dim.radius = cylinderRadii[type];
|
||||||
this->cylinder2.dim.height = cylinderHeights[type];
|
this->cylinder2.dim.height = cylinderHeights[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 4) {
|
if (type == RED_ICE_KING_ZORA) {
|
||||||
this->cylinder1.dim.pos.z += 30;
|
this->cylinder1.dim.pos.z += 30;
|
||||||
this->cylinder2.dim.pos.z += 30;
|
this->cylinder2.dim.pos.z += 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80890874(BgIceShelter* this, PlayState* play, CollisionHeader* collision, s32 moveFlag) {
|
void BgIceShelter_InitDynaPoly(BgIceShelter* this, PlayState* play, CollisionHeader* collision, s32 moveFlag) {
|
||||||
s32 pad;
|
s32 pad;
|
||||||
CollisionHeader* colHeader = NULL;
|
CollisionHeader* colHeader = NULL;
|
||||||
s32 pad2;
|
s32 pad2;
|
||||||
|
@ -114,7 +128,7 @@ void func_80890874(BgIceShelter* this, PlayState* play, CollisionHeader* collisi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_808908FC(Vec3f* dest, Vec3f* src, s16 angle) {
|
void BgIceShelter_RotateY(Vec3f* dest, Vec3f* src, s16 angle) {
|
||||||
f32 sin = Math_SinS(angle);
|
f32 sin = Math_SinS(angle);
|
||||||
f32 cos = Math_CosS(angle);
|
f32 cos = Math_CosS(angle);
|
||||||
|
|
||||||
|
@ -132,42 +146,45 @@ static InitChainEntry sInitChain[] = {
|
||||||
void BgIceShelter_Init(Actor* thisx, PlayState* play) {
|
void BgIceShelter_Init(Actor* thisx, PlayState* play) {
|
||||||
static Vec3f kzIceScale = { 0.18f, 0.27f, 0.24f };
|
static Vec3f kzIceScale = { 0.18f, 0.27f, 0.24f };
|
||||||
BgIceShelter* this = (BgIceShelter*)thisx;
|
BgIceShelter* this = (BgIceShelter*)thisx;
|
||||||
s16 type = (this->dyna.actor.params >> 8) & 7;
|
s16 type = BGICESHELTER_GET_TYPE(&this->dyna.actor);
|
||||||
|
|
||||||
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
|
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
|
||||||
|
|
||||||
if (type == 4) {
|
if (type == RED_ICE_KING_ZORA) {
|
||||||
this->dyna.actor.world.rot.x += 0xBB8;
|
this->dyna.actor.world.rot.x += 0xBB8;
|
||||||
this->dyna.actor.world.pos.y -= 45.0f;
|
this->dyna.actor.world.pos.y -= 45.0f;
|
||||||
this->dyna.actor.shape.rot.x = this->dyna.actor.world.rot.x;
|
this->dyna.actor.shape.rot.x = this->dyna.actor.world.rot.x;
|
||||||
this->dyna.actor.world.pos.z -= 38.0f;
|
this->dyna.actor.world.pos.z -= 38.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 4) {
|
if (type == RED_ICE_KING_ZORA) {
|
||||||
Math_Vec3f_Copy(&this->dyna.actor.scale, &kzIceScale);
|
Math_Vec3f_Copy(&this->dyna.actor.scale, &kzIceScale);
|
||||||
} else {
|
} else {
|
||||||
Actor_SetScale(&this->dyna.actor, sScales[type]);
|
Actor_SetScale(&this->dyna.actor, sRedIceScales[type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only 2 types use DynaPoly
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 2:
|
case RED_ICE_PLATFORM:
|
||||||
func_80890874(this, play, &object_ice_objects_Col_001C1C, 0);
|
BgIceShelter_InitDynaPoly(this, play, &gRedIcePlatformCol, 0);
|
||||||
break;
|
break;
|
||||||
case 3:
|
case RED_ICE_WALL:
|
||||||
func_80890874(this, play, &object_ice_objects_Col_002920, 0);
|
BgIceShelter_InitDynaPoly(this, play, &gRedIceWallCol, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
func_80890740(this, play);
|
// All types use at least one collider
|
||||||
|
BgIceShelter_InitColliders(this, play);
|
||||||
|
|
||||||
this->dyna.actor.colChkInfo.mass = MASS_IMMOVABLE;
|
this->dyna.actor.colChkInfo.mass = MASS_IMMOVABLE;
|
||||||
|
|
||||||
if (!((this->dyna.actor.params >> 6) & 1) && (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F))) {
|
// The only red ice actor in the game that doesn't use a switch flag is the one for King Zora
|
||||||
|
if (!BGICESHELTER_NO_SWITCH_FLAG(&this->dyna.actor) && (Flags_GetSwitch(play, this->dyna.actor.params & 0x3F))) {
|
||||||
Actor_Kill(&this->dyna.actor);
|
Actor_Kill(&this->dyna.actor);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
func_80891064(this);
|
BgIceShelter_SetupIdle(this);
|
||||||
|
|
||||||
osSyncPrintf("(ice shelter)(arg_data 0x%04x)\n", this->dyna.actor.params);
|
osSyncPrintf("(ice shelter)(arg_data 0x%04x)\n", this->dyna.actor.params);
|
||||||
}
|
}
|
||||||
|
@ -175,15 +192,15 @@ void BgIceShelter_Init(Actor* thisx, PlayState* play) {
|
||||||
void BgIceShelter_Destroy(Actor* thisx, PlayState* play) {
|
void BgIceShelter_Destroy(Actor* thisx, PlayState* play) {
|
||||||
BgIceShelter* this = (BgIceShelter*)thisx;
|
BgIceShelter* this = (BgIceShelter*)thisx;
|
||||||
|
|
||||||
switch ((this->dyna.actor.params >> 8) & 7) {
|
switch (BGICESHELTER_GET_TYPE(&this->dyna.actor)) {
|
||||||
case 2:
|
case RED_ICE_PLATFORM:
|
||||||
case 3:
|
case RED_ICE_WALL:
|
||||||
DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId);
|
DynaPoly_DeleteBgActor(play, &play->colCtx.dyna, this->dyna.bgId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0:
|
case RED_ICE_LARGE:
|
||||||
case 1:
|
case RED_ICE_SMALL:
|
||||||
case 4:
|
case RED_ICE_KING_ZORA:
|
||||||
Collider_DestroyCylinder(play, &this->cylinder2);
|
Collider_DestroyCylinder(play, &this->cylinder2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -191,126 +208,155 @@ void BgIceShelter_Destroy(Actor* thisx, PlayState* play) {
|
||||||
Collider_DestroyCylinder(play, &this->cylinder1);
|
Collider_DestroyCylinder(play, &this->cylinder1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static s16 D_80891794[] = { 0x0000, 0x4000, 0x2000, 0x6000, 0x1000, 0x5000, 0x3000, 0x7000 };
|
/**
|
||||||
static s16 D_808917A4[] = { 0x0000, 0x003C, 0x0018, 0x0054, 0x0030, 0x000C, 0x0048, 0x0024 };
|
* Angles used to spawn steam particles in a circle.
|
||||||
|
*/
|
||||||
|
static s16 sSteamCircleAngles[] = { 0x0000, 0x4000, 0x2000, 0x6000, 0x1000, 0x5000, 0x3000, 0x7000 };
|
||||||
|
|
||||||
void func_80890B8C(BgIceShelter* this, PlayState* play, f32 chance, f32 scale) {
|
/**
|
||||||
|
* Positions used to spawn steam particles in a straight line.
|
||||||
|
*/
|
||||||
|
static s16 sSteamLinePositions[] = { 0x0000, 0x003C, 0x0018, 0x0054, 0x0030, 0x000C, 0x0048, 0x0024 };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns steam particle effects in a circle around the ice block.
|
||||||
|
*
|
||||||
|
* On each frame the function is called, two particles have a chance to appear, at the same distance and opposite
|
||||||
|
* sides from the center.
|
||||||
|
*/
|
||||||
|
void BgIceShelter_SpawnSteamAround(BgIceShelter* this, PlayState* play, f32 particleSpawningChance,
|
||||||
|
f32 steamEffectScale) {
|
||||||
f32 cos;
|
f32 cos;
|
||||||
f32 sin;
|
f32 sin;
|
||||||
f32 xzOffset;
|
f32 distance;
|
||||||
Vec3f* icePos;
|
Vec3f* icePos;
|
||||||
s16 angle;
|
s16 angle;
|
||||||
s16 frames;
|
s16 frameCounter;
|
||||||
s32 i;
|
s32 i;
|
||||||
s32 pad[2];
|
s32 pad[2];
|
||||||
Vec3f dustPos;
|
Vec3f steamPos;
|
||||||
Vec3f dustVel;
|
Vec3f steamVel;
|
||||||
Vec3f dustAccel;
|
Vec3f steamAccel;
|
||||||
|
|
||||||
frames = (s16)play->state.frames & 7;
|
frameCounter = (s16)play->state.frames & 7;
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
if (chance < Rand_ZeroOne()) {
|
if (particleSpawningChance < Rand_ZeroOne()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
xzOffset = 42.0f * scale;
|
// The steamEffectScale is used here to make the particles appear at the edges of the red ice.
|
||||||
|
distance = 42.0f * steamEffectScale;
|
||||||
icePos = &this->dyna.actor.world.pos;
|
icePos = &this->dyna.actor.world.pos;
|
||||||
angle = D_80891794[frames] + (i * 0x8000);
|
angle = sSteamCircleAngles[frameCounter] + (i * 0x8000);
|
||||||
sin = Math_SinS(angle);
|
sin = Math_SinS(angle);
|
||||||
cos = Math_CosS(angle);
|
cos = Math_CosS(angle);
|
||||||
|
|
||||||
dustPos.x = (xzOffset * sin) + icePos->x;
|
steamPos.x = (distance * sin) + icePos->x;
|
||||||
dustPos.y = (16.0f * scale) + icePos->y;
|
steamPos.y = (16.0f * steamEffectScale) + icePos->y;
|
||||||
dustPos.z = (xzOffset * cos) + icePos->z;
|
steamPos.z = (distance * cos) + icePos->z;
|
||||||
|
|
||||||
dustVel.x = ((Rand_ZeroOne() * 3.0f) - 1.0f) * sin;
|
steamVel.x = ((Rand_ZeroOne() * 3.0f) - 1.0f) * sin;
|
||||||
dustVel.y = 0.0f;
|
steamVel.y = 0.0f;
|
||||||
dustVel.z = ((Rand_ZeroOne() * 3.0f) - 1.0f) * cos;
|
steamVel.z = ((Rand_ZeroOne() * 3.0f) - 1.0f) * cos;
|
||||||
|
|
||||||
dustAccel.x = 0.07f * sin;
|
steamAccel.x = 0.07f * sin;
|
||||||
dustAccel.y = 0.8f;
|
steamAccel.y = 0.8f;
|
||||||
dustAccel.z = 0.07f * cos;
|
steamAccel.z = 0.07f * cos;
|
||||||
|
|
||||||
func_8002829C(play, &dustPos, &dustVel, &dustAccel, &sDustPrimColor, &sDustEnvColor, 450.0f * scale,
|
func_8002829C(play, &steamPos, &steamVel, &steamAccel, &sSteamPrimColor, &sSteamEnvColor,
|
||||||
(s16)((Rand_ZeroOne() * 40.0f) + 40.0f) * scale);
|
450.0f * steamEffectScale, (s16)((Rand_ZeroOne() * 40.0f) + 40.0f) * steamEffectScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80890E00(BgIceShelter* this, PlayState* play, f32 chance, f32 arg3) {
|
/**
|
||||||
static f32 D_808917B4[] = { -1.0f, 1.0f };
|
* Spawns steam particle effects in a straight line. Only used for the ice wall type.
|
||||||
|
*
|
||||||
|
* On each frame the function is called, two particles have a chance to appear, at the same distance and opposite
|
||||||
|
* sides from the midpoint.
|
||||||
|
*
|
||||||
|
* The last argument is unused because only one red ice type can call this function, so the scale isn't needed.
|
||||||
|
*/
|
||||||
|
void BgIceShelter_SpawnSteamAlong(BgIceShelter* this, PlayState* play, f32 particleSpawningChance, f32 unusedArg) {
|
||||||
|
static f32 signs[] = { -1.0f, 1.0f };
|
||||||
Vec3f* icePos;
|
Vec3f* icePos;
|
||||||
s16 frames;
|
s16 frameCounter;
|
||||||
s32 pad[2];
|
s32 pad[2];
|
||||||
Vec3f dustPos;
|
Vec3f steamPos;
|
||||||
Vec3f dustVel;
|
Vec3f steamVel;
|
||||||
Vec3f dustAccel;
|
Vec3f steamAccel;
|
||||||
Vec3f posOffset;
|
Vec3f posOffset;
|
||||||
s32 i;
|
s32 i;
|
||||||
|
|
||||||
frames = (s16)play->state.frames & 7;
|
frameCounter = (s16)play->state.frames & 7;
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
icePos = &this->dyna.actor.world.pos;
|
icePos = &this->dyna.actor.world.pos;
|
||||||
|
|
||||||
if (chance < Rand_ZeroOne()) {
|
if (particleSpawningChance < Rand_ZeroOne()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
posOffset.x = (D_808917A4[frames] + ((Rand_ZeroOne() * 12.0f) - 6.0f)) * D_808917B4[i];
|
posOffset.x = (sSteamLinePositions[frameCounter] + ((Rand_ZeroOne() * 12.0f) - 6.0f)) * signs[i];
|
||||||
posOffset.y = 15.0f;
|
posOffset.y = 15.0f;
|
||||||
posOffset.z = ((84.0f - posOffset.x) * 0.2f) + (Rand_ZeroOne() * 20.0f);
|
posOffset.z = ((84.0f - posOffset.x) * 0.2f) + (Rand_ZeroOne() * 20.0f);
|
||||||
|
|
||||||
func_808908FC(&dustPos, &posOffset, this->dyna.actor.world.rot.y);
|
// Convert the position offset from relative to the ice wall to absolute.
|
||||||
Math_Vec3f_Sum(&dustPos, icePos, &dustPos);
|
BgIceShelter_RotateY(&steamPos, &posOffset, this->dyna.actor.world.rot.y);
|
||||||
|
Math_Vec3f_Sum(&steamPos, icePos, &steamPos);
|
||||||
|
|
||||||
dustVel.x = (Rand_ZeroOne() * 3.0f) - 1.5f;
|
steamVel.x = (Rand_ZeroOne() * 3.0f) - 1.5f;
|
||||||
dustVel.y = 0.0f;
|
steamVel.y = 0.0f;
|
||||||
dustVel.z = (Rand_ZeroOne() * 3.0f) - 1.5f;
|
steamVel.z = (Rand_ZeroOne() * 3.0f) - 1.5f;
|
||||||
|
|
||||||
dustAccel.x = (Rand_ZeroOne() * 0.14f) - 0.07f;
|
steamAccel.x = (Rand_ZeroOne() * 0.14f) - 0.07f;
|
||||||
dustAccel.y = 0.8f;
|
steamAccel.y = 0.8f;
|
||||||
dustAccel.z = (Rand_ZeroOne() * 0.14f) - 0.07f;
|
steamAccel.z = (Rand_ZeroOne() * 0.14f) - 0.07f;
|
||||||
|
|
||||||
func_8002829C(play, &dustPos, &dustVel, &dustAccel, &sDustPrimColor, &sDustEnvColor, 450,
|
func_8002829C(play, &steamPos, &steamVel, &steamAccel, &sSteamPrimColor, &sSteamEnvColor, 450,
|
||||||
(Rand_ZeroOne() * 40.0f) + 40.0f);
|
(Rand_ZeroOne() * 40.0f) + 40.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_80891064(BgIceShelter* this) {
|
void BgIceShelter_SetupIdle(BgIceShelter* this) {
|
||||||
this->actionFunc = func_8089107C;
|
this->actionFunc = BgIceShelter_Idle;
|
||||||
this->alpha = 255;
|
this->alpha = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_8089107C(BgIceShelter* this, PlayState* play) {
|
/**
|
||||||
|
* Checks for collision with blue fire. Also used to freeze King Zora's actor.
|
||||||
|
*/
|
||||||
|
void BgIceShelter_Idle(BgIceShelter* this, PlayState* play) {
|
||||||
s32 pad;
|
s32 pad;
|
||||||
s16 type = (this->dyna.actor.params >> 8) & 7;
|
s16 type = BGICESHELTER_GET_TYPE(&this->dyna.actor);
|
||||||
|
|
||||||
if (type == 4) {
|
// Freeze King Zora
|
||||||
|
if (type == RED_ICE_KING_ZORA) {
|
||||||
if (this->dyna.actor.parent != NULL) {
|
if (this->dyna.actor.parent != NULL) {
|
||||||
this->dyna.actor.parent->freezeTimer = 10000;
|
this->dyna.actor.parent->freezeTimer = 10000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Detect blue fire
|
||||||
if (this->cylinder1.base.acFlags & AC_HIT) {
|
if (this->cylinder1.base.acFlags & AC_HIT) {
|
||||||
this->cylinder1.base.acFlags &= ~AC_HIT;
|
this->cylinder1.base.acFlags &= ~AC_HIT;
|
||||||
|
|
||||||
if ((this->cylinder1.base.ac != NULL) && (this->cylinder1.base.ac->id == ACTOR_EN_ICE_HONO)) {
|
if ((this->cylinder1.base.ac != NULL) && (this->cylinder1.base.ac->id == ACTOR_EN_ICE_HONO)) {
|
||||||
if (type == 4) {
|
if (type == RED_ICE_KING_ZORA) {
|
||||||
if (this->dyna.actor.parent != NULL) {
|
if (this->dyna.actor.parent != NULL) {
|
||||||
this->dyna.actor.parent->freezeTimer = 50;
|
this->dyna.actor.parent->freezeTimer = 50;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func_808911BC(this);
|
BgIceShelter_SetupMelt(this);
|
||||||
Audio_PlayActorSfx2(&this->dyna.actor, NA_SE_EV_ICE_MELT);
|
Audio_PlayActorSfx2(&this->dyna.actor, NA_SE_EV_ICE_MELT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case RED_ICE_LARGE:
|
||||||
case 1:
|
case RED_ICE_SMALL:
|
||||||
case 4:
|
case RED_ICE_KING_ZORA:
|
||||||
CollisionCheck_SetOC(play, &play->colChkCtx, &this->cylinder1.base);
|
CollisionCheck_SetOC(play, &play->colChkCtx, &this->cylinder1.base);
|
||||||
CollisionCheck_SetAC(play, &play->colChkCtx, &this->cylinder2.base);
|
CollisionCheck_SetAC(play, &play->colChkCtx, &this->cylinder2.base);
|
||||||
break;
|
break;
|
||||||
|
@ -319,57 +365,73 @@ void func_8089107C(BgIceShelter* this, PlayState* play) {
|
||||||
CollisionCheck_SetAC(play, &play->colChkCtx, &this->cylinder1.base);
|
CollisionCheck_SetAC(play, &play->colChkCtx, &this->cylinder1.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
void func_808911BC(BgIceShelter* this) {
|
void BgIceShelter_SetupMelt(BgIceShelter* this) {
|
||||||
this->actionFunc = func_808911D4;
|
this->actionFunc = BgIceShelter_Melt;
|
||||||
this->alpha = 255;
|
this->alpha = 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
static f32 D_808917BC[] = { -0.0015f, -0.0009f, -0.0016f, -0.0016f, -0.00375f };
|
/**
|
||||||
static f32 D_808917D0[] = { 1.0f, 0.6f, 1.2f, 1.0f, 1.8f };
|
* Values added to the ice block's height every frame while it's melting.
|
||||||
|
*/
|
||||||
|
static f32 sMeltingRates[] = { -0.0015f, -0.0009f, -0.0016f, -0.0016f, -0.00375f };
|
||||||
|
|
||||||
static void (*sEffSpawnFuncs[])(BgIceShelter* this, PlayState* play, f32 chance, f32 scale) = {
|
/**
|
||||||
func_80890B8C, func_80890B8C, func_80890B8C, func_80890E00, func_80890B8C,
|
* Values used to scale and position the steam effects so they match the ice block's size.
|
||||||
|
*/
|
||||||
|
static f32 sSteamEffectScales[] = { 1.0f, 0.6f, 1.2f, 1.0f, 1.8f };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functions used to spawn steam effects at the base of the red ice.
|
||||||
|
*/
|
||||||
|
static void (*sSteamSpawnFuncs[])(BgIceShelter* this, PlayState* play, f32 particleSpawningChance,
|
||||||
|
f32 steamEffectScale) = {
|
||||||
|
BgIceShelter_SpawnSteamAround, BgIceShelter_SpawnSteamAround, BgIceShelter_SpawnSteamAround,
|
||||||
|
BgIceShelter_SpawnSteamAlong, BgIceShelter_SpawnSteamAround,
|
||||||
};
|
};
|
||||||
|
|
||||||
void func_808911D4(BgIceShelter* this, PlayState* play) {
|
/**
|
||||||
|
* Progressively reduces the height and opacity of the red ice, while spawning steam effects at its base.
|
||||||
|
*/
|
||||||
|
void BgIceShelter_Melt(BgIceShelter* this, PlayState* play) {
|
||||||
|
|
||||||
s32 pad;
|
s32 pad;
|
||||||
s32 type = (this->dyna.actor.params >> 8) & 7;
|
s32 type = BGICESHELTER_GET_TYPE(&this->dyna.actor);
|
||||||
f32 phi_f0;
|
f32 particleSpawningChance;
|
||||||
|
|
||||||
this->alpha -= 5;
|
this->alpha -= 5;
|
||||||
this->alpha = CLAMP(this->alpha, 0, 255);
|
this->alpha = CLAMP(this->alpha, 0, 255);
|
||||||
|
|
||||||
this->dyna.actor.scale.y += D_808917BC[type];
|
this->dyna.actor.scale.y += sMeltingRates[type];
|
||||||
this->dyna.actor.scale.y = CLAMP_MIN(this->dyna.actor.scale.y, 0.0001f);
|
this->dyna.actor.scale.y = CLAMP_MIN(this->dyna.actor.scale.y, 0.0001f);
|
||||||
|
|
||||||
if (this->alpha > 80) {
|
if (this->alpha > 80) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0:
|
case RED_ICE_LARGE:
|
||||||
case 1:
|
case RED_ICE_SMALL:
|
||||||
case 4:
|
case RED_ICE_KING_ZORA:
|
||||||
CollisionCheck_SetOC(play, &play->colChkCtx, &this->cylinder1.base);
|
CollisionCheck_SetOC(play, &play->colChkCtx, &this->cylinder1.base);
|
||||||
CollisionCheck_SetAC(play, &play->colChkCtx, &this->cylinder2.base);
|
CollisionCheck_SetAC(play, &play->colChkCtx, &this->cylinder2.base);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As the ice melts, the steam intensity is reduced by lowering the chance of each steam particle to appear
|
||||||
if (this->alpha > 180) {
|
if (this->alpha > 180) {
|
||||||
phi_f0 = 1.0f;
|
particleSpawningChance = 1.0f;
|
||||||
} else if (this->alpha > 60) {
|
} else if (this->alpha > 60) {
|
||||||
phi_f0 = 0.5f;
|
particleSpawningChance = 0.5f;
|
||||||
} else {
|
} else {
|
||||||
phi_f0 = 0.0f;
|
particleSpawningChance = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
sEffSpawnFuncs[type](this, play, phi_f0, D_808917D0[type]);
|
sSteamSpawnFuncs[type](this, play, particleSpawningChance, sSteamEffectScales[type]);
|
||||||
|
|
||||||
if (this->alpha <= 0) {
|
if (this->alpha <= 0) {
|
||||||
if (!((this->dyna.actor.params >> 6) & 1)) {
|
if (!BGICESHELTER_NO_SWITCH_FLAG(&this->dyna.actor)) {
|
||||||
Flags_SetSwitch(play, this->dyna.actor.params & 0x3F);
|
Flags_SetSwitch(play, this->dyna.actor.params & 0x3F);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == 4) {
|
if (type == RED_ICE_KING_ZORA) {
|
||||||
func_80078884(NA_SE_SY_CORRECT_CHIME);
|
func_80078884(NA_SE_SY_CORRECT_CHIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,29 +456,29 @@ void BgIceShelter_Draw(Actor* thisx, PlayState* play2) {
|
||||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_bg_ice_shelter.c", 751),
|
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_bg_ice_shelter.c", 751),
|
||||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
|
||||||
switch ((this->dyna.actor.params >> 8) & 7) {
|
switch (BGICESHELTER_GET_TYPE(&this->dyna.actor)) {
|
||||||
case 0:
|
case RED_ICE_LARGE:
|
||||||
case 1:
|
case RED_ICE_SMALL:
|
||||||
case 2:
|
case RED_ICE_PLATFORM:
|
||||||
case 4:
|
case RED_ICE_KING_ZORA:
|
||||||
func_8002ED80(&this->dyna.actor, play, 0);
|
func_8002ED80(&this->dyna.actor, play, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, this->alpha);
|
gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 0, this->alpha);
|
||||||
|
|
||||||
switch ((this->dyna.actor.params >> 8) & 7) {
|
switch (BGICESHELTER_GET_TYPE(&this->dyna.actor)) {
|
||||||
case 0:
|
case RED_ICE_LARGE:
|
||||||
case 1:
|
case RED_ICE_SMALL:
|
||||||
case 4:
|
case RED_ICE_KING_ZORA:
|
||||||
gSPSegment(POLY_XLU_DISP++, 0x08,
|
gSPSegment(POLY_XLU_DISP++, 0x08,
|
||||||
Gfx_TwoTexScroll(play->state.gfxCtx, G_TX_RENDERTILE, -play->gameplayFrames & 0x7F,
|
Gfx_TwoTexScroll(play->state.gfxCtx, G_TX_RENDERTILE, -play->gameplayFrames & 0x7F,
|
||||||
-play->gameplayFrames & 0x7F, 0x20, 0x20, 1, -play->gameplayFrames & 0x7F,
|
-play->gameplayFrames & 0x7F, 0x20, 0x20, 1, -play->gameplayFrames & 0x7F,
|
||||||
play->gameplayFrames & 0x7F, 0x20, 0x20));
|
play->gameplayFrames & 0x7F, 0x20, 0x20));
|
||||||
gSPDisplayList(POLY_XLU_DISP++, object_ice_objects_DL_0006F0);
|
gSPDisplayList(POLY_XLU_DISP++, gRedIceBlockDL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case RED_ICE_PLATFORM:
|
||||||
gSPSegment(POLY_XLU_DISP++, 0x08,
|
gSPSegment(POLY_XLU_DISP++, 0x08,
|
||||||
Gfx_TwoTexScroll(play->state.gfxCtx, G_TX_RENDERTILE, 0, play->gameplayFrames & 0xFF, 0x40, 0x40,
|
Gfx_TwoTexScroll(play->state.gfxCtx, G_TX_RENDERTILE, 0, play->gameplayFrames & 0xFF, 0x40, 0x40,
|
||||||
1, 0, -play->gameplayFrames & 0xFF, 0x40, 0x40));
|
1, 0, -play->gameplayFrames & 0xFF, 0x40, 0x40));
|
||||||
|
@ -424,11 +486,11 @@ void BgIceShelter_Draw(Actor* thisx, PlayState* play2) {
|
||||||
Gfx_TwoTexScroll(play->state.gfxCtx, G_TX_RENDERTILE, -play->gameplayFrames & 0xFF,
|
Gfx_TwoTexScroll(play->state.gfxCtx, G_TX_RENDERTILE, -play->gameplayFrames & 0xFF,
|
||||||
play->gameplayFrames & 0xFF, 0x40, 0x40, 1, play->gameplayFrames & 0xFF,
|
play->gameplayFrames & 0xFF, 0x40, 0x40, 1, play->gameplayFrames & 0xFF,
|
||||||
play->gameplayFrames & 0xFF, 0x40, 0x40));
|
play->gameplayFrames & 0xFF, 0x40, 0x40));
|
||||||
gSPDisplayList(POLY_XLU_DISP++, object_ice_objects_DL_0012A0);
|
gSPDisplayList(POLY_XLU_DISP++, gRedIcePlatformDL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case RED_ICE_WALL:
|
||||||
gSPDisplayList(POLY_XLU_DISP++, object_ice_objects_DL_002640);
|
gSPDisplayList(POLY_XLU_DISP++, gRedIceWallDL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,19 @@ struct BgIceShelter;
|
||||||
|
|
||||||
typedef void (*BgIceShelterActionFunc)(struct BgIceShelter*, PlayState*);
|
typedef void (*BgIceShelterActionFunc)(struct BgIceShelter*, PlayState*);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* 0 */ RED_ICE_LARGE, // Large red ice block
|
||||||
|
/* 1 */ RED_ICE_SMALL, // Small red ice block
|
||||||
|
/* 2 */ RED_ICE_PLATFORM, // Complex structure that can be climbed and walked on. Unused in vanilla OoT, used in MQ to cover the Ice Cavern Map chest
|
||||||
|
/* 3 */ RED_ICE_WALL, // Vertical ice sheets blocking corridors
|
||||||
|
/* 4 */ RED_ICE_KING_ZORA // Giant red ice block covering King Zora
|
||||||
|
} RedIceType;
|
||||||
|
|
||||||
typedef struct BgIceShelter {
|
typedef struct BgIceShelter {
|
||||||
/* 0x0000 */ DynaPolyActor dyna;
|
/* 0x0000 */ DynaPolyActor dyna;
|
||||||
/* 0x0164 */ BgIceShelterActionFunc actionFunc;
|
/* 0x0164 */ BgIceShelterActionFunc actionFunc;
|
||||||
/* 0x0168 */ ColliderCylinder cylinder1;
|
/* 0x0168 */ ColliderCylinder cylinder1; // Used to detect blue fire and also as OC for no-dynapoly types
|
||||||
/* 0x01B4 */ ColliderCylinder cylinder2;
|
/* 0x01B4 */ ColliderCylinder cylinder2; // Only used by no-dynapoly types to make weapons bounce off
|
||||||
/* 0x0200 */ s16 alpha;
|
/* 0x0200 */ s16 alpha;
|
||||||
} BgIceShelter; // size = 0x0204
|
} BgIceShelter; // size = 0x0204
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue