1
0
mirror of https://github.com/zeldaret/oot.git synced 2024-09-22 21:35:27 +00:00
oot/src/code/z_kankyo.c
Dragorn421 6336df5fcd
Defines for SaveContext flags (eventChkInf, itemGetInf, infTable, eventInf) (#1094)
* script-assisted `itemGetInf` flags

* comment near non-trivial `itemGetInf` usage

* Run formatter

* Try something with the itemgetinf flags that can't use the packed value

* Add defines for `eventChkInf` (direct access)

* Add defines for `eventChkInf` (access through `Flags_GetEventChkInf`)

* Add defines for `eventChkInf` (access through `Flags_SetEventChkInf`)

* Add defines for `infTable` (direct access)

* Add defines for `infTable` (used by `Flags_GetInfTable`)

* Add defines for `infTable` (used by `Flags_SetInfTable`)

* Add defines for `eventInf`

* parenthesis cleanup near `GET_EVENTCHKINF` usage

* parenthesis cleanup near `GET_ITEMGETINF` usage

* parenthesis cleanup near `GET_INFTABLE` usage

* fixup one `eventInf` usage

* parenthesis cleanup near `GET_EVENTINF` usage

* parenthesis cleanup near `Flags_GetEventChkInf` usage

* slight `z64save.h` formatting improvement

* Improve itemGetInf flags in z_bg_dy_yoseizo

* Questionable improvement in z_en_ge2

* Questionable improvement in z_en_daiku

* Questionable improvement in z_en_mu

* Run formatter

* Parentheses around `gSaveContext` macros arguments

* Move individual flags define to the end of z64save.h, and improve comments separating the groups
2022-04-29 14:19:48 -04:00

2464 lines
96 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "global.h"
#include "ultra64.h"
#include "vt.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
typedef enum {
/* 0 */ LENS_FLARE_CIRCLE0,
/* 1 */ LENS_FLARE_CIRCLE1,
/* 2 */ LENS_FLARE_RING
} LensFlareType;
typedef enum {
/* 0x00 */ LIGHTNING_BOLT_START,
/* 0x01 */ LIGHTNING_BOLT_WAIT,
/* 0x02 */ LIGHTNING_BOLT_DRAW,
/* 0xFF */ LIGHTNING_BOLT_INACTIVE = 0xFF
} LightningBoltState;
typedef struct {
/* 0x00 */ u16 startTime;
/* 0x02 */ u16 endTime;
/* 0x04 */ u8 unk_04;
/* 0x05 */ u8 unk_05;
} struct_8011FB48; // size = 0x6
typedef struct {
/* 0x00 */ u8 state;
/* 0x04 */ Vec3f offset;
/* 0x10 */ Vec3f pos;
/* 0x1C */ s8 pitch;
/* 0x1D */ s8 roll;
/* 0x1E */ u8 textureIndex;
/* 0x1F */ u8 delayTimer;
} LightningBolt; // size = 0x20
typedef struct {
/* 0x00 */ s32 unk_00;
/* 0x04 */ s32 unk_04;
} Struct_8011FAF0; // size = 0x8
Struct_8011FAF0 D_8011FAF0[] = {
{ 6, 0x00000000 }, { 5, 0x00020000 }, { 4, 0x00030000 }, { 3, 0x00038000 },
{ 2, 0x0003C000 }, { 1, 0x0003E000 }, { 0, 0x0003F000 }, { 0, 0x0003F800 },
};
u8 gWeatherMode = 0; // "E_wether_flg"
u8 D_8011FB34 = 0;
u8 D_8011FB38 = 0;
u8 gSkyboxBlendingEnabled = false;
u16 gTimeIncrement = 0;
u16 D_8011FB44 = 0xFFFC;
struct_8011FB48 D_8011FB48[][7] = {
{
{ 0x0000, 0x2AAC, 3, 3 },
{ 0x2AAC, 0x4000, 3, 0 },
{ 0x4000, 0x5556, 0, 1 },
{ 0x5556, 0xAAAB, 1, 1 },
{ 0xAAAB, 0xB556, 1, 2 },
{ 0xB556, 0xCAAC, 2, 3 },
{ 0xCAAC, 0xFFFF, 3, 3 },
},
{
{ 0x0000, 0x2AAC, 7, 7 },
{ 0x2AAC, 0x4000, 7, 4 },
{ 0x4000, 0x5556, 4, 5 },
{ 0x5556, 0xAAAB, 5, 5 },
{ 0xAAAB, 0xB556, 5, 6 },
{ 0xB556, 0xCAAC, 6, 7 },
{ 0xCAAC, 0xFFFF, 7, 7 },
},
{
{ 0x0000, 0x2AAC, 11, 11 },
{ 0x2AAC, 0x4000, 11, 8 },
{ 0x4000, 0x5556, 8, 9 },
{ 0x5556, 0xAAAB, 9, 9 },
{ 0xAAAB, 0xB556, 9, 10 },
{ 0xB556, 0xCAAC, 10, 11 },
{ 0xCAAC, 0xFFFF, 11, 11 },
},
{
{ 0x0000, 0x2AAC, 15, 15 },
{ 0x2AAC, 0x4000, 15, 12 },
{ 0x4000, 0x5556, 12, 13 },
{ 0x5556, 0xAAAB, 13, 13 },
{ 0xAAAB, 0xB556, 13, 14 },
{ 0xB556, 0xCAAC, 14, 15 },
{ 0xCAAC, 0xFFFF, 15, 15 },
},
{
{ 0x0000, 0x2AAC, 23, 23 },
{ 0x2AAC, 0x4000, 23, 20 },
{ 0x4000, 0x5556, 20, 21 },
{ 0x5556, 0xAAAB, 21, 21 },
{ 0xAAAB, 0xB556, 21, 22 },
{ 0xB556, 0xCAAC, 22, 23 },
{ 0xCAAC, 0xFFFF, 23, 23 },
},
};
struct_8011FC1C D_8011FC1C[][9] = {
{
{ 0x0000, 0x2AAC, 0, 3, 3 },
{ 0x2AAC, 0x3556, 1, 3, 0 },
{ 0x3556, 0x4000, 0, 0, 0 },
{ 0x4000, 0x5556, 1, 0, 1 },
{ 0x5556, 0xAAAB, 0, 1, 1 },
{ 0xAAAB, 0xB556, 1, 1, 2 },
{ 0xB556, 0xC001, 0, 2, 2 },
{ 0xC001, 0xCAAC, 1, 2, 3 },
{ 0xCAAC, 0xFFFF, 0, 3, 3 },
},
{
{ 0x0000, 0x2AAC, 0, 7, 7 },
{ 0x2AAC, 0x3556, 1, 7, 4 },
{ 0x3556, 0x4000, 0, 4, 4 },
{ 0x4000, 0x5556, 1, 4, 5 },
{ 0x5556, 0xAAAB, 0, 5, 5 },
{ 0xAAAB, 0xB556, 1, 5, 6 },
{ 0xB556, 0xC001, 0, 6, 6 },
{ 0xC001, 0xCAAC, 1, 6, 7 },
{ 0xCAAC, 0xFFFF, 0, 7, 7 },
},
{
{ 0x0000, 0x1556, 0, 3, 3 },
{ 0x1556, 0x2AAC, 1, 3, 0 },
{ 0x2AAC, 0x5556, 0, 0, 0 },
{ 0x5556, 0x6AAB, 1, 0, 1 },
{ 0x6AAB, 0x9556, 0, 1, 1 },
{ 0x9556, 0xAAAB, 1, 1, 2 },
{ 0xAAAB, 0xD556, 0, 2, 2 },
{ 0xD556, 0xEAAB, 1, 2, 3 },
{ 0xEAAB, 0xFFFF, 0, 3, 3 },
},
{
{ 0x0000, 0x3556, 0, 11, 11 },
{ 0x3556, 0x4000, 1, 11, 8 },
{ 0x4000, 0x4AAB, 0, 8, 8 },
{ 0x4AAB, 0x5556, 1, 8, 9 },
{ 0x5556, 0xAAAB, 0, 9, 9 },
{ 0xAAAB, 0xB556, 1, 9, 10 },
{ 0xB556, 0xC001, 0, 10, 10 },
{ 0xC001, 0xCAAC, 1, 10, 11 },
{ 0xCAAC, 0xFFFF, 0, 11, 11 },
},
};
SkyboxFile gSkyboxFiles[] = {
{
ROM_FILE(vr_fine0_static),
ROM_FILE(vr_fine0_pal_static),
},
{
ROM_FILE(vr_fine1_static),
ROM_FILE(vr_fine1_pal_static),
},
{
ROM_FILE(vr_fine2_static),
ROM_FILE(vr_fine2_pal_static),
},
{
ROM_FILE(vr_fine3_static),
ROM_FILE(vr_fine3_pal_static),
},
{
ROM_FILE(vr_cloud0_static),
ROM_FILE(vr_cloud0_pal_static),
},
{
ROM_FILE(vr_cloud1_static),
ROM_FILE(vr_cloud1_pal_static),
},
{
ROM_FILE(vr_cloud2_static),
ROM_FILE(vr_cloud2_pal_static),
},
{
ROM_FILE(vr_cloud3_static),
ROM_FILE(vr_cloud3_pal_static),
},
{
ROM_FILE(vr_holy0_static),
ROM_FILE(vr_holy0_pal_static),
},
};
u8 D_8011FDCC = 0;
u8 D_8011FDD0 = 0;
f32 D_8011FDD4 = 0.0f;
u8 gCustomLensFlareOn;
Vec3f gCustomLensFlarePos;
s16 gLensFlareUnused;
s16 gLensFlareScale;
f32 gLensFlareColorIntensity;
s16 gLensFlareScreenFillAlpha;
LightningBolt sLightningBolts[3];
LightningStrike gLightningStrike;
s16 sLightningFlashAlpha;
s16 D_8015FD7E;
s16 D_8015FD80;
LightNode* sNGameOverLightNode;
LightInfo sNGameOverLightInfo;
LightNode* sSGameOverLightNode;
LightInfo sSGameOverLightInfo;
u8 sGameOverLightsIntensity;
u16 D_8015FDB0;
s32 func_8006F0A0(s32 a0) {
s32 ret = ((a0 >> 4 & 0x7FF) << D_8011FAF0[a0 >> 15 & 7].unk_00) + D_8011FAF0[a0 >> 15 & 7].unk_04;
return ret;
}
u16 Environment_GetPixelDepth(s32 x, s32 y) {
s32 pixelDepth = gZBuffer[y][x];
return pixelDepth;
}
void Environment_GraphCallback(GraphicsContext* gfxCtx, void* param) {
GlobalContext* globalCtx = (GlobalContext*)param;
D_8011FB44 = Environment_GetPixelDepth(D_8015FD7E, D_8015FD80);
Lights_GlowCheck(globalCtx);
}
void Environment_Init(GlobalContext* globalCtx2, EnvironmentContext* envCtx, s32 unused) {
u8 i;
GlobalContext* globalCtx = globalCtx2;
gSaveContext.sunsSongState = SUNSSONG_INACTIVE;
if (((void)0, gSaveContext.dayTime) > 0xC000 || ((void)0, gSaveContext.dayTime) < 0x4555) {
((void)0, gSaveContext.nightFlag = 1);
} else {
((void)0, gSaveContext.nightFlag = 0);
}
globalCtx->state.gfxCtx->callback = Environment_GraphCallback;
globalCtx->state.gfxCtx->callbackParam = globalCtx;
Lights_DirectionalSetInfo(&envCtx->dirLight1, 80, 80, 80, 80, 80, 80);
LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, &envCtx->dirLight1);
Lights_DirectionalSetInfo(&envCtx->dirLight2, 80, 80, 80, 80, 80, 80);
LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, &envCtx->dirLight2);
envCtx->skybox1Index = 99;
envCtx->skybox2Index = 99;
envCtx->unk_19 = 0;
envCtx->unk_1A = 0;
envCtx->unk_21 = 0;
envCtx->unk_22 = 0;
envCtx->skyboxDmaState = SKYBOX_DMA_INACTIVE;
envCtx->unk_1F = 0;
envCtx->unk_20 = 0;
envCtx->unk_84 = 0.0f;
envCtx->unk_88 = 0.0f;
envCtx->unk_BD = 0;
envCtx->unk_BE = 0;
envCtx->unk_D8 = 1.0f;
envCtx->unk_DC = 0;
envCtx->gloomySkyMode = 0;
envCtx->unk_DE = 0;
envCtx->lightningMode = LIGHTNING_MODE_OFF;
envCtx->unk_E0 = 0;
envCtx->fillScreen = false;
envCtx->screenFillColor[0] = 0;
envCtx->screenFillColor[1] = 0;
envCtx->screenFillColor[2] = 0;
envCtx->screenFillColor[3] = 0;
envCtx->customSkyboxFilter = false;
envCtx->skyboxFilterColor[0] = 0;
envCtx->skyboxFilterColor[1] = 0;
envCtx->skyboxFilterColor[2] = 0;
envCtx->skyboxFilterColor[3] = 0;
envCtx->sandstormState = SANDSTORM_OFF;
envCtx->sandstormPrimA = 0;
envCtx->sandstormEnvA = 0;
gLightningStrike.state = LIGHTNING_STRIKE_WAIT;
gLightningStrike.flashRed = 0;
gLightningStrike.flashGreen = 0;
gLightningStrike.flashBlue = 0;
sLightningFlashAlpha = 0;
gSaveContext.cutsceneTransitionControl = 0;
envCtx->adjAmbientColor[0] = envCtx->adjAmbientColor[1] = envCtx->adjAmbientColor[2] = envCtx->adjLight1Color[0] =
envCtx->adjLight1Color[1] = envCtx->adjLight1Color[2] = envCtx->adjFogColor[0] = envCtx->adjFogColor[1] =
envCtx->adjFogColor[2] = envCtx->adjFogNear = envCtx->adjFogFar = 0;
envCtx->sunPos.x = -(Math_SinS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f) * 25.0f;
envCtx->sunPos.y = +(Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f) * 25.0f;
envCtx->sunPos.z = +(Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 20.0f) * 25.0f;
envCtx->windDirection.x = 80;
envCtx->windDirection.y = 80;
envCtx->windDirection.z = 80;
envCtx->blendIndoorLights = false;
envCtx->unk_BF = 0xFF;
envCtx->unk_D6 = 0xFFFF;
R_ENV_TIME_INCREMENT = gTimeIncrement = envCtx->timeIncrement = 0;
R_ENV_DISABLE_DBG = true;
if (CREG(3) != 0) {
gSaveContext.chamberCutsceneNum = CREG(3) - 1;
}
globalCtx->envCtx.unk_EE[0] = 0;
globalCtx->envCtx.unk_EE[1] = 0;
globalCtx->envCtx.unk_EE[2] = 0;
globalCtx->envCtx.unk_EE[3] = 0;
globalCtx->envCtx.unk_F2[0] = 0;
if (gSaveContext.unk_13C3 != 0) {
if (((void)0, gSaveContext.sceneSetupIndex) < 4) {
switch (gWeatherMode) {
case 1:
envCtx->unk_17 = 1;
envCtx->unk_18 = 1;
envCtx->unk_1F = 3;
envCtx->unk_20 = 3;
globalCtx->envCtx.unk_EE[3] = 0;
globalCtx->envCtx.unk_EE[2] = 0;
break;
case 2:
case 3:
case 4:
envCtx->unk_17 = 1;
envCtx->unk_18 = 1;
envCtx->unk_1F = 2;
envCtx->unk_20 = 2;
globalCtx->envCtx.unk_EE[3] = 0;
globalCtx->envCtx.unk_EE[2] = 0;
break;
case 5:
envCtx->unk_17 = 1;
envCtx->unk_18 = 1;
envCtx->unk_1F = 4;
envCtx->unk_20 = 4;
globalCtx->envCtx.unk_EE[3] = 0;
globalCtx->envCtx.unk_EE[2] = 0;
break;
default:
break;
}
if (globalCtx->skyboxId == SKYBOX_NORMAL_SKY) {
if (gWeatherMode == 3) {
globalCtx->envCtx.unk_EE[2] = globalCtx->envCtx.unk_EE[3] = 0x40;
} else if (gWeatherMode == 4) {
globalCtx->envCtx.unk_EE[0] = 0x14;
globalCtx->envCtx.unk_EE[1] = 0x14;
} else if (gWeatherMode == 5) {
globalCtx->envCtx.unk_EE[0] = 0x1E;
globalCtx->envCtx.unk_EE[1] = 0x1E;
}
}
}
} else {
gWeatherMode = 0;
}
D_8011FB38 = 0;
D_8011FB34 = 0;
gSkyboxBlendingEnabled = false;
gSaveContext.unk_13C3 = 0;
R_ENV_LIGHT1_DIR(0) = 80;
R_ENV_LIGHT1_DIR(1) = 80;
R_ENV_LIGHT1_DIR(2) = 80;
R_ENV_LIGHT2_DIR(0) = -80;
R_ENV_LIGHT2_DIR(1) = -80;
R_ENV_LIGHT2_DIR(2) = -80;
cREG(9) = 10;
cREG(10) = 0;
cREG(11) = 0;
cREG(12) = 0;
cREG(13) = 0;
cREG(14) = 0;
D_8015FCC8 = 1;
for (i = 0; i < ARRAY_COUNT(sLightningBolts); i++) {
sLightningBolts[i].state = LIGHTNING_BOLT_INACTIVE;
}
globalCtx->roomCtx.unk_74[0] = 0;
globalCtx->roomCtx.unk_74[1] = 0;
for (i = 0; i < ARRAY_COUNT(globalCtx->csCtx.npcActions); i++) {
globalCtx->csCtx.npcActions[i] = 0;
}
if (Object_GetIndex(&globalCtx->objectCtx, OBJECT_GAMEPLAY_FIELD_KEEP) < 0 && !globalCtx->envCtx.sunMoonDisabled) {
globalCtx->envCtx.sunMoonDisabled = true;
// "Sun setting other than field keep! So forced release!"
osSyncPrintf(VT_COL(YELLOW, BLACK) "\n\nフィールド常駐以外、太陽設定!よって強制解除!\n" VT_RST);
}
gCustomLensFlareOn = false;
func_800AA15C();
}
u8 Environment_SmoothStepToU8(u8* pvalue, u8 target, u8 scale, u8 step, u8 minStep) {
s16 stepSize = 0;
s16 diff = target - *pvalue;
if (target != *pvalue) {
stepSize = diff / scale;
if ((stepSize >= (s16)minStep) || ((s16)-minStep >= stepSize)) {
if ((s16)step < stepSize) {
stepSize = step;
}
if ((s16)-step > stepSize) {
stepSize = -step;
}
*pvalue += (u8)stepSize;
} else {
if (stepSize < (s16)minStep) {
stepSize = minStep;
*pvalue += (u8)stepSize;
if (target < *pvalue) {
*pvalue = target;
}
}
if ((s16)-minStep < stepSize) {
stepSize = -minStep;
*pvalue += (u8)stepSize;
if (*pvalue < target) {
*pvalue = target;
}
}
}
}
return diff;
}
u8 Environment_SmoothStepToS8(s8* pvalue, s8 target, u8 scale, u8 step, u8 minStep) {
s16 stepSize = 0;
s16 diff = target - *pvalue;
if (target != *pvalue) {
stepSize = diff / scale;
if ((stepSize >= (s16)minStep) || ((s16)-minStep >= stepSize)) {
if ((s16)step < stepSize) {
stepSize = step;
}
if ((s16)-step > stepSize) {
stepSize = -step;
}
*pvalue += (s8)stepSize;
} else {
if (stepSize < (s16)minStep) {
stepSize = minStep;
*pvalue += (s8)stepSize;
if (target < *pvalue) {
*pvalue = target;
}
}
if ((s16)-minStep < stepSize) {
stepSize = -minStep;
*pvalue += (s8)stepSize;
if (*pvalue < target) {
*pvalue = target;
}
}
}
}
return diff;
}
f32 Environment_LerpWeight(u16 max, u16 min, u16 val) {
f32 diff = max - min;
f32 ret;
if (diff != 0.0f) {
ret = 1.0f - (max - val) / diff;
if (!(ret >= 1.0f)) {
return ret;
}
}
return 1.0f;
}
f32 Environment_LerpWeightAccelDecel(u16 endFrame, u16 startFrame, u16 curFrame, u16 accelDuration, u16 decelDuration) {
f32 endFrameF;
f32 startFrameF;
f32 curFrameF;
f32 accelDurationF;
f32 decelDurationF;
f32 totalFrames;
f32 temp;
f32 framesElapsed;
f32 ret;
if (curFrame <= startFrame) {
return 0.0f;
}
if (curFrame >= endFrame) {
return 1.0f;
}
endFrameF = (s32)endFrame;
startFrameF = (s32)startFrame;
curFrameF = (s32)curFrame;
totalFrames = endFrameF - startFrameF;
framesElapsed = curFrameF - startFrameF;
accelDurationF = (s32)accelDuration;
decelDurationF = (s32)decelDuration;
if ((startFrameF >= endFrameF) || (accelDurationF + decelDurationF > totalFrames)) {
// "The frame relation between end_frame and start_frame is wrong!!!"
osSyncPrintf(VT_COL(RED, WHITE) "\nend_frameとstart_frameのフレーム関係がおかしい!!!" VT_RST);
osSyncPrintf(VT_COL(RED, WHITE) "\nby get_parcent_forAccelBrake!!!!!!!!!" VT_RST);
return 0.0f;
}
temp = 1.0f / ((totalFrames * 2.0f) - accelDurationF - decelDurationF);
if (accelDurationF != 0.0f) {
if (framesElapsed <= accelDurationF) {
return temp * framesElapsed * framesElapsed / accelDurationF;
}
ret = temp * accelDurationF;
} else {
ret = 0.0f;
}
if (framesElapsed <= totalFrames - decelDurationF) {
ret += 2.0f * temp * (framesElapsed - accelDurationF);
return ret;
}
ret += 2.0f * temp * (totalFrames - accelDurationF - decelDurationF);
if (decelDurationF != 0.0f) {
ret += temp * decelDurationF;
if (framesElapsed < totalFrames) {
ret -= temp * (totalFrames - framesElapsed) * (totalFrames - framesElapsed) / decelDurationF;
}
}
return ret;
}
void func_8006FB94(EnvironmentContext* envCtx, u8 unused) {
if (envCtx->gloomySkyMode != 0) {
switch (envCtx->unk_DE) {
case 0:
if ((envCtx->gloomySkyMode == 1) && !gSkyboxBlendingEnabled) {
envCtx->unk_19 = 1;
envCtx->unk_17 = 0;
envCtx->unk_18 = 1;
envCtx->unk_1A = 100;
envCtx->unk_21 = 1;
envCtx->unk_1F = 0;
envCtx->unk_20 = 2;
D_8011FB34 = 2;
envCtx->unk_22 = envCtx->unk_24 = 100;
envCtx->unk_DE++;
}
break;
case 1:
if (!gSkyboxBlendingEnabled && (envCtx->gloomySkyMode == 2)) {
gWeatherMode = 0;
envCtx->unk_19 = 1;
envCtx->unk_17 = 1;
envCtx->unk_18 = 0;
envCtx->unk_1A = 100;
envCtx->unk_21 = 1;
envCtx->unk_1F = 2;
envCtx->unk_20 = 0;
D_8011FB34 = 0;
envCtx->unk_22 = envCtx->unk_24 = 100;
envCtx->unk_EE[0] = 0;
envCtx->gloomySkyMode = 0;
envCtx->unk_DE = 0;
}
break;
}
}
}
void Environment_UpdateSkybox(u8 skyboxId, EnvironmentContext* envCtx, SkyboxContext* skyboxCtx) {
u32 size;
u8 i;
u8 newSkybox1Index = 0xFF;
u8 newSkybox2Index = 0xFF;
u8 skyboxBlend = 0;
if (skyboxId == SKYBOX_CUTSCENE_MAP) {
envCtx->unk_17 = 3;
for (i = 0; i < ARRAY_COUNT(D_8011FC1C[envCtx->unk_17]); i++) {
if (gSaveContext.skyboxTime >= D_8011FC1C[envCtx->unk_17][i].startTime &&
(gSaveContext.skyboxTime < D_8011FC1C[envCtx->unk_17][i].endTime ||
D_8011FC1C[envCtx->unk_17][i].endTime == 0xFFFF)) {
if (D_8011FC1C[envCtx->unk_17][i].blend) {
envCtx->skyboxBlend = Environment_LerpWeight(D_8011FC1C[envCtx->unk_17][i].endTime,
D_8011FC1C[envCtx->unk_17][i].startTime,
((void)0, gSaveContext.skyboxTime)) *
255;
} else {
envCtx->skyboxBlend = 0;
}
break;
}
}
} else if (skyboxId == SKYBOX_NORMAL_SKY && !envCtx->skyboxDisabled) {
for (i = 0; i < ARRAY_COUNT(D_8011FC1C[envCtx->unk_17]); i++) {
if (gSaveContext.skyboxTime >= D_8011FC1C[envCtx->unk_17][i].startTime &&
(gSaveContext.skyboxTime < D_8011FC1C[envCtx->unk_17][i].endTime ||
D_8011FC1C[envCtx->unk_17][i].endTime == 0xFFFF)) {
newSkybox1Index = D_8011FC1C[envCtx->unk_17][i].skybox1Index;
newSkybox2Index = D_8011FC1C[envCtx->unk_17][i].skybox2Index;
gSkyboxBlendingEnabled = D_8011FC1C[envCtx->unk_17][i].blend;
if (gSkyboxBlendingEnabled) {
skyboxBlend = Environment_LerpWeight(D_8011FC1C[envCtx->unk_17][i].endTime,
D_8011FC1C[envCtx->unk_17][i].startTime,
((void)0, gSaveContext.skyboxTime)) *
255;
} else {
skyboxBlend = Environment_LerpWeight(D_8011FC1C[envCtx->unk_17][i].endTime,
D_8011FC1C[envCtx->unk_17][i].startTime,
((void)0, gSaveContext.skyboxTime)) *
255;
skyboxBlend = (skyboxBlend < 0x80) ? 0xFF : 0;
if ((envCtx->unk_19 != 0) && (envCtx->unk_19 < 3)) {
envCtx->unk_19++;
skyboxBlend = 0;
}
}
break;
}
}
func_8006FB94(envCtx, skyboxBlend);
if (envCtx->unk_19 >= 3) {
newSkybox1Index = D_8011FC1C[envCtx->unk_17][i].skybox1Index;
newSkybox2Index = D_8011FC1C[envCtx->unk_18][i].skybox2Index;
skyboxBlend = ((f32)envCtx->unk_24 - envCtx->unk_1A--) / (f32)envCtx->unk_24 * 255;
if (envCtx->unk_1A <= 0) {
envCtx->unk_19 = 0;
envCtx->unk_17 = envCtx->unk_18;
}
}
if (newSkybox1Index == 0xFF) {
// "Environment VR data acquisition failed! Report to Sasaki!"
osSyncPrintf(VT_COL(RED, WHITE) "\n環境VRデータ取得失敗! ささきまでご報告を!" VT_RST);
}
if ((envCtx->skybox1Index != newSkybox1Index) && (envCtx->skyboxDmaState == SKYBOX_DMA_INACTIVE)) {
envCtx->skyboxDmaState = SKYBOX_DMA_FILE1_START;
size = gSkyboxFiles[newSkybox1Index].file.vromEnd - gSkyboxFiles[newSkybox1Index].file.vromStart;
osCreateMesgQueue(&envCtx->loadQueue, &envCtx->loadMsg, 1);
DmaMgr_SendRequest2(&envCtx->dmaRequest, (u32)skyboxCtx->staticSegments[0],
gSkyboxFiles[newSkybox1Index].file.vromStart, size, 0, &envCtx->loadQueue, NULL,
"../z_kankyo.c", 1264);
envCtx->skybox1Index = newSkybox1Index;
}
if ((envCtx->skybox2Index != newSkybox2Index) && (envCtx->skyboxDmaState == SKYBOX_DMA_INACTIVE)) {
envCtx->skyboxDmaState = SKYBOX_DMA_FILE2_START;
size = gSkyboxFiles[newSkybox2Index].file.vromEnd - gSkyboxFiles[newSkybox2Index].file.vromStart;
osCreateMesgQueue(&envCtx->loadQueue, &envCtx->loadMsg, 1);
DmaMgr_SendRequest2(&envCtx->dmaRequest, (u32)skyboxCtx->staticSegments[1],
gSkyboxFiles[newSkybox2Index].file.vromStart, size, 0, &envCtx->loadQueue, NULL,
"../z_kankyo.c", 1281);
envCtx->skybox2Index = newSkybox2Index;
}
if (envCtx->skyboxDmaState == SKYBOX_DMA_FILE1_DONE) {
envCtx->skyboxDmaState = SKYBOX_DMA_PAL1_START;
if ((newSkybox1Index & 1) ^ ((newSkybox1Index & 4) >> 2)) {
size = gSkyboxFiles[newSkybox1Index].palette.vromEnd - gSkyboxFiles[newSkybox1Index].palette.vromStart;
osCreateMesgQueue(&envCtx->loadQueue, &envCtx->loadMsg, 1);
DmaMgr_SendRequest2(&envCtx->dmaRequest, (u32)skyboxCtx->palettes,
gSkyboxFiles[newSkybox1Index].palette.vromStart, size, 0, &envCtx->loadQueue, NULL,
"../z_kankyo.c", 1307);
} else {
size = gSkyboxFiles[newSkybox1Index].palette.vromEnd - gSkyboxFiles[newSkybox1Index].palette.vromStart;
osCreateMesgQueue(&envCtx->loadQueue, &envCtx->loadMsg, 1);
DmaMgr_SendRequest2(&envCtx->dmaRequest, (u32)skyboxCtx->palettes + size,
gSkyboxFiles[newSkybox1Index].palette.vromStart, size, 0, &envCtx->loadQueue, NULL,
"../z_kankyo.c", 1320);
}
}
if (envCtx->skyboxDmaState == SKYBOX_DMA_FILE2_DONE) {
envCtx->skyboxDmaState = SKYBOX_DMA_PAL2_START;
if ((newSkybox2Index & 1) ^ ((newSkybox2Index & 4) >> 2)) {
size = gSkyboxFiles[newSkybox2Index].palette.vromEnd - gSkyboxFiles[newSkybox2Index].palette.vromStart;
osCreateMesgQueue(&envCtx->loadQueue, &envCtx->loadMsg, 1);
DmaMgr_SendRequest2(&envCtx->dmaRequest, (u32)skyboxCtx->palettes,
gSkyboxFiles[newSkybox2Index].palette.vromStart, size, 0, &envCtx->loadQueue, NULL,
"../z_kankyo.c", 1342);
} else {
size = gSkyboxFiles[newSkybox2Index].palette.vromEnd - gSkyboxFiles[newSkybox2Index].palette.vromStart;
osCreateMesgQueue(&envCtx->loadQueue, &envCtx->loadMsg, 1);
DmaMgr_SendRequest2(&envCtx->dmaRequest, (u32)skyboxCtx->palettes + size,
gSkyboxFiles[newSkybox2Index].palette.vromStart, size, 0, &envCtx->loadQueue, NULL,
"../z_kankyo.c", 1355);
}
}
if ((envCtx->skyboxDmaState == SKYBOX_DMA_FILE1_START) || (envCtx->skyboxDmaState == SKYBOX_DMA_FILE2_START)) {
if (osRecvMesg(&envCtx->loadQueue, NULL, OS_MESG_NOBLOCK) == 0) {
envCtx->skyboxDmaState++;
}
} else if (envCtx->skyboxDmaState >= SKYBOX_DMA_FILE1_DONE) {
if (osRecvMesg(&envCtx->loadQueue, NULL, OS_MESG_NOBLOCK) == 0) {
envCtx->skyboxDmaState = SKYBOX_DMA_INACTIVE;
}
}
envCtx->skyboxBlend = skyboxBlend;
}
}
void Environment_EnableUnderwaterLights(GlobalContext* globalCtx, s32 waterLightsIndex) {
if (waterLightsIndex == 0x1F) {
waterLightsIndex = 0;
// "Underwater color is not set in the water poly data!"
osSyncPrintf(VT_COL(YELLOW, BLACK) "\n水ポリゴンデータに水中カラーが設定されておりません!" VT_RST);
}
if (!globalCtx->envCtx.indoors) {
D_8011FB34 = globalCtx->envCtx.unk_20;
if (globalCtx->envCtx.unk_1F != waterLightsIndex) {
globalCtx->envCtx.unk_1F = waterLightsIndex;
globalCtx->envCtx.unk_20 = waterLightsIndex;
}
} else {
globalCtx->envCtx.blendIndoorLights = false; // instantly switch to water lights
globalCtx->envCtx.unk_BF = waterLightsIndex;
}
}
void Environment_DisableUnderwaterLights(GlobalContext* globalCtx) {
if (!globalCtx->envCtx.indoors) {
globalCtx->envCtx.unk_1F = D_8011FB34;
globalCtx->envCtx.unk_20 = D_8011FB34;
} else {
globalCtx->envCtx.blendIndoorLights = false; // instantly switch to previous lights
globalCtx->envCtx.unk_BF = 0xFF;
globalCtx->envCtx.unk_D8 = 1.0f;
}
}
void Environment_PrintDebugInfo(GlobalContext* globalCtx, Gfx** gfx) {
GfxPrint printer;
s32 pad[2];
GfxPrint_Init(&printer);
GfxPrint_Open(&printer, *gfx);
GfxPrint_SetPos(&printer, 22, 7);
GfxPrint_SetColor(&printer, 155, 155, 255, 64);
GfxPrint_Printf(&printer, "T%03d ", ((void)0, gSaveContext.totalDays));
GfxPrint_Printf(&printer, "E%03d", ((void)0, gSaveContext.bgsDayCount));
GfxPrint_SetColor(&printer, 255, 255, 55, 64);
GfxPrint_SetPos(&printer, 22, 8);
GfxPrint_Printf(&printer, "%s", "ZELDATIME ");
GfxPrint_SetColor(&printer, 255, 255, 255, 64);
GfxPrint_Printf(&printer, "%02d", (u8)(24 * 60 / (f32)0x10000 * ((void)0, gSaveContext.dayTime) / 60.0f));
if ((gSaveContext.dayTime & 0x1F) >= 0x10 || gTimeIncrement >= 6) {
GfxPrint_Printf(&printer, "%s", ":");
} else {
GfxPrint_Printf(&printer, "%s", " ");
}
GfxPrint_Printf(&printer, "%02d", (s16)(24 * 60 / (f32)0x10000 * ((void)0, gSaveContext.dayTime)) % 60);
GfxPrint_SetColor(&printer, 255, 255, 55, 64);
GfxPrint_SetPos(&printer, 22, 9);
GfxPrint_Printf(&printer, "%s", "VRBOXTIME ");
GfxPrint_SetColor(&printer, 255, 255, 255, 64);
GfxPrint_Printf(&printer, "%02d", (u8)(24 * 60 / (f32)0x10000 * ((void)0, gSaveContext.skyboxTime) / 60.0f));
if ((((void)0, gSaveContext.skyboxTime) & 0x1F) >= 0x10 || gTimeIncrement >= 6) {
GfxPrint_Printf(&printer, "%s", ":");
} else {
GfxPrint_Printf(&printer, "%s", " ");
}
GfxPrint_Printf(&printer, "%02d", (s16)(24 * 60 / (f32)0x10000 * ((void)0, gSaveContext.skyboxTime)) % 60);
GfxPrint_SetColor(&printer, 55, 255, 255, 64);
GfxPrint_SetPos(&printer, 22, 6);
if (!IS_DAY) {
GfxPrint_Printf(&printer, "%s", "YORU"); // "night"
} else {
GfxPrint_Printf(&printer, "%s", "HIRU"); // "day"
}
*gfx = GfxPrint_Close(&printer);
GfxPrint_Destroy(&printer);
}
#define TIME_ENTRY_1F (D_8011FB48[envCtx->unk_1F][i])
#define TIME_ENTRY_20 (D_8011FB48[envCtx->unk_20][i])
void func_80075B44(GlobalContext* globalCtx);
void func_800766C4(GlobalContext* globalCtx);
void Environment_Update(GlobalContext* globalCtx, EnvironmentContext* envCtx, LightContext* lightCtx,
PauseContext* pauseCtx, MessageContext* msgCtx, GameOverContext* gameOverCtx,
GraphicsContext* gfxCtx) {
f32 sp8C;
f32 sp88 = 0.0f;
u16 i;
u16 j;
u16 time;
EnvLightSettings* lightSettingsList = globalCtx->envCtx.lightSettingsList;
s32 adjustment;
if ((((void)0, gSaveContext.gameMode) != 0) && (((void)0, gSaveContext.gameMode) != 3)) {
func_800AA16C();
}
if (pauseCtx->state == 0) {
if ((globalCtx->pauseCtx.state == 0) && (globalCtx->pauseCtx.debugState == 0)) {
if (globalCtx->skyboxId == SKYBOX_NORMAL_SKY) {
globalCtx->skyboxCtx.rot.y -= 0.001f;
} else if (globalCtx->skyboxId == SKYBOX_CUTSCENE_MAP) {
globalCtx->skyboxCtx.rot.y -= 0.005f;
}
}
func_800766C4(globalCtx); // increments or decrements unk_EE[1] depending on some condition
func_80075B44(globalCtx); // updates bgm/sfx and other things as the day progresses
if (((void)0, gSaveContext.nextDayTime) >= 0xFF00 && ((void)0, gSaveContext.nextDayTime) != 0xFFFF) {
gSaveContext.nextDayTime -= 0x10;
osSyncPrintf("\nnext_zelda_time=[%x]", ((void)0, gSaveContext.nextDayTime));
if (((void)0, gSaveContext.nextDayTime) == 0xFF0E) {
func_80078884(NA_SE_EV_CHICKEN_CRY_M);
gSaveContext.nextDayTime = 0xFFFF;
} else if (((void)0, gSaveContext.nextDayTime) == 0xFF0D) {
func_800788CC(NA_SE_EV_DOG_CRY_EVENING);
gSaveContext.nextDayTime = 0xFFFF;
}
}
if ((pauseCtx->state == 0) && (gameOverCtx->state == GAMEOVER_INACTIVE)) {
if (((msgCtx->msgLength == 0) && (msgCtx->msgMode == 0)) || (((void)0, gSaveContext.gameMode) == 3)) {
if ((envCtx->unk_1A == 0) && !FrameAdvance_IsEnabled(globalCtx) &&
(globalCtx->transitionMode == TRANS_MODE_OFF || ((void)0, gSaveContext.gameMode) != 0)) {
if (IS_DAY || gTimeIncrement >= 0x190) {
gSaveContext.dayTime += gTimeIncrement;
} else {
gSaveContext.dayTime += gTimeIncrement * 2; // time moves twice as fast at night
}
}
}
}
//! @bug `gTimeIncrement` is unsigned, it can't be negative
if (((((void)0, gSaveContext.sceneSetupIndex) >= 5 || gTimeIncrement != 0) &&
((void)0, gSaveContext.dayTime) > gSaveContext.skyboxTime) ||
(((void)0, gSaveContext.dayTime) < 0xAAB || gTimeIncrement < 0)) {
gSaveContext.skyboxTime = ((void)0, gSaveContext.dayTime);
}
time = gSaveContext.dayTime;
if (time > 0xC000 || time < 0x4555) {
gSaveContext.nightFlag = 1;
} else {
gSaveContext.nightFlag = 0;
}
if (SREG(0) != 0 || CREG(2) != 0) {
Gfx* displayList;
Gfx* prevDisplayList;
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 1682);
prevDisplayList = POLY_OPA_DISP;
displayList = Graph_GfxPlusOne(POLY_OPA_DISP);
gSPDisplayList(OVERLAY_DISP++, displayList);
Environment_PrintDebugInfo(globalCtx, &displayList);
gSPEndDisplayList(displayList++);
Graph_BranchDlist(prevDisplayList, displayList);
POLY_OPA_DISP = displayList;
if (1) {}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 1690);
}
if ((envCtx->unk_BF != 0xFF) && (envCtx->unk_DC != 2) && (envCtx->unk_BD != envCtx->unk_BF) &&
(envCtx->unk_D8 >= 1.0f) && (envCtx->unk_BF < 0x20)) {
envCtx->unk_BE = envCtx->unk_BD;
envCtx->unk_BD = envCtx->unk_BF;
envCtx->unk_D8 = 0.0f;
}
if (envCtx->unk_BF != 0xFE) {
if (!envCtx->indoors && (envCtx->unk_BF == 0xFF)) {
for (i = 0; i < ARRAY_COUNT(D_8011FB48[envCtx->unk_1F]); i++) {
if ((gSaveContext.skyboxTime >= TIME_ENTRY_1F.startTime) &&
((gSaveContext.skyboxTime < TIME_ENTRY_1F.endTime) || TIME_ENTRY_1F.endTime == 0xFFFF)) {
u8 blend8[2];
s16 blend16[2];
sp8C = Environment_LerpWeight(TIME_ENTRY_1F.endTime, TIME_ENTRY_1F.startTime,
((void)0, gSaveContext.skyboxTime));
D_8011FDCC = TIME_ENTRY_1F.unk_04 & 3;
D_8011FDD0 = TIME_ENTRY_1F.unk_05 & 3;
D_8011FDD4 = sp8C;
if (envCtx->unk_21) {
sp88 = ((f32)envCtx->unk_24 - envCtx->unk_22) / envCtx->unk_24;
envCtx->unk_22--;
if (envCtx->unk_22 <= 0) {
envCtx->unk_21 = 0;
envCtx->unk_1F = envCtx->unk_20;
}
}
for (j = 0; j < 3; j++) {
// blend ambient color
blend8[0] = LERP(lightSettingsList[TIME_ENTRY_1F.unk_04].ambientColor[j],
lightSettingsList[TIME_ENTRY_1F.unk_05].ambientColor[j], sp8C);
blend8[1] = LERP(lightSettingsList[TIME_ENTRY_20.unk_04].ambientColor[j],
lightSettingsList[TIME_ENTRY_20.unk_05].ambientColor[j], sp8C);
*(envCtx->lightSettings.ambientColor + j) = LERP(blend8[0], blend8[1], sp88);
}
// set light1 direction for the sun
envCtx->lightSettings.light1Dir[0] =
-(Math_SinS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f);
envCtx->lightSettings.light1Dir[1] =
Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f;
envCtx->lightSettings.light1Dir[2] =
(Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 20.0f);
// set light2 direction for the moon
envCtx->lightSettings.light2Dir[0] = -envCtx->lightSettings.light1Dir[0];
envCtx->lightSettings.light2Dir[1] = -envCtx->lightSettings.light1Dir[1];
envCtx->lightSettings.light2Dir[2] = -envCtx->lightSettings.light1Dir[2];
for (j = 0; j < 3; j++) {
// blend light1Color
blend8[0] = LERP(lightSettingsList[TIME_ENTRY_1F.unk_04].light1Color[j],
lightSettingsList[TIME_ENTRY_1F.unk_05].light1Color[j], sp8C);
blend8[1] = LERP(lightSettingsList[TIME_ENTRY_20.unk_04].light1Color[j],
lightSettingsList[TIME_ENTRY_20.unk_05].light1Color[j], sp8C);
*(envCtx->lightSettings.light1Color + j) = LERP(blend8[0], blend8[1], sp88);
// blend light2Color
blend8[0] = LERP(lightSettingsList[TIME_ENTRY_1F.unk_04].light2Color[j],
lightSettingsList[TIME_ENTRY_1F.unk_05].light2Color[j], sp8C);
blend8[1] = LERP(lightSettingsList[TIME_ENTRY_20.unk_04].light2Color[j],
lightSettingsList[TIME_ENTRY_20.unk_05].light2Color[j], sp8C);
*(envCtx->lightSettings.light2Color + j) = LERP(blend8[0], blend8[1], sp88);
}
// blend fogColor
for (j = 0; j < 3; j++) {
blend8[0] = LERP(lightSettingsList[TIME_ENTRY_1F.unk_04].fogColor[j],
lightSettingsList[TIME_ENTRY_1F.unk_05].fogColor[j], sp8C);
blend8[1] = LERP(lightSettingsList[TIME_ENTRY_20.unk_04].fogColor[j],
lightSettingsList[TIME_ENTRY_20.unk_05].fogColor[j], sp8C);
*(envCtx->lightSettings.fogColor + j) = LERP(blend8[0], blend8[1], sp88);
}
blend16[0] = LERP16((lightSettingsList[TIME_ENTRY_1F.unk_04].fogNear & 0x3FF),
(lightSettingsList[TIME_ENTRY_1F.unk_05].fogNear & 0x3FF), sp8C);
blend16[1] = LERP16(lightSettingsList[TIME_ENTRY_20.unk_04].fogNear & 0x3FF,
lightSettingsList[TIME_ENTRY_20.unk_05].fogNear & 0x3FF, sp8C);
envCtx->lightSettings.fogNear = LERP16(blend16[0], blend16[1], sp88);
blend16[0] = LERP16(lightSettingsList[TIME_ENTRY_1F.unk_04].fogFar,
lightSettingsList[TIME_ENTRY_1F.unk_05].fogFar, sp8C);
blend16[1] = LERP16(lightSettingsList[TIME_ENTRY_20.unk_04].fogFar,
lightSettingsList[TIME_ENTRY_20.unk_05].fogFar, sp8C);
envCtx->lightSettings.fogFar = LERP16(blend16[0], blend16[1], sp88);
if (TIME_ENTRY_20.unk_05 >= envCtx->numLightSettings) {
// "The color palette setting seems to be wrong!"
osSyncPrintf(VT_COL(RED, WHITE) "\nカラーパレットの設定がおかしいようです!" VT_RST);
// "Palette setting = [] Last palette number = []"
osSyncPrintf(VT_COL(RED, WHITE) "\n設定パレット=[%d] 最後パレット番号=[%d]\n" VT_RST,
TIME_ENTRY_20.unk_05, envCtx->numLightSettings - 1);
}
break;
}
}
} else {
if (!envCtx->blendIndoorLights) {
for (i = 0; i < 3; i++) {
envCtx->lightSettings.ambientColor[i] = lightSettingsList[envCtx->unk_BD].ambientColor[i];
envCtx->lightSettings.light1Dir[i] = lightSettingsList[envCtx->unk_BD].light1Dir[i];
envCtx->lightSettings.light1Color[i] = lightSettingsList[envCtx->unk_BD].light1Color[i];
envCtx->lightSettings.light2Dir[i] = lightSettingsList[envCtx->unk_BD].light2Dir[i];
envCtx->lightSettings.light2Color[i] = lightSettingsList[envCtx->unk_BD].light2Color[i];
envCtx->lightSettings.fogColor[i] = lightSettingsList[envCtx->unk_BD].fogColor[i];
}
envCtx->lightSettings.fogNear = lightSettingsList[envCtx->unk_BD].fogNear & 0x3FF;
envCtx->lightSettings.fogFar = lightSettingsList[envCtx->unk_BD].fogFar;
envCtx->unk_D8 = 1.0f;
} else {
u8 blendRate = (lightSettingsList[envCtx->unk_BD].fogNear >> 0xA) * 4;
if (blendRate == 0) {
blendRate++;
}
if (envCtx->unk_D6 != 0xFFFF) {
blendRate = envCtx->unk_D6;
}
if (envCtx->unk_DC == 0) {
envCtx->unk_D8 += blendRate / 255.0f;
}
if (envCtx->unk_D8 > 1.0f) {
envCtx->unk_D8 = 1.0f;
}
for (i = 0; i < 3; i++) {
envCtx->lightSettings.ambientColor[i] =
LERP(lightSettingsList[envCtx->unk_BE].ambientColor[i],
lightSettingsList[envCtx->unk_BD].ambientColor[i], envCtx->unk_D8);
envCtx->lightSettings.light1Dir[i] =
LERP16(lightSettingsList[envCtx->unk_BE].light1Dir[i],
lightSettingsList[envCtx->unk_BD].light1Dir[i], envCtx->unk_D8);
envCtx->lightSettings.light1Color[i] =
LERP(lightSettingsList[envCtx->unk_BE].light1Color[i],
lightSettingsList[envCtx->unk_BD].light1Color[i], envCtx->unk_D8);
envCtx->lightSettings.light2Dir[i] =
LERP16(lightSettingsList[envCtx->unk_BE].light2Dir[i],
lightSettingsList[envCtx->unk_BD].light2Dir[i], envCtx->unk_D8);
envCtx->lightSettings.light2Color[i] =
LERP(lightSettingsList[envCtx->unk_BE].light2Color[i],
lightSettingsList[envCtx->unk_BD].light2Color[i], envCtx->unk_D8);
envCtx->lightSettings.fogColor[i] =
LERP(lightSettingsList[envCtx->unk_BE].fogColor[i],
lightSettingsList[envCtx->unk_BD].fogColor[i], envCtx->unk_D8);
}
envCtx->lightSettings.fogNear =
LERP16(lightSettingsList[envCtx->unk_BE].fogNear & 0x3FF,
lightSettingsList[envCtx->unk_BD].fogNear & 0x3FF, envCtx->unk_D8);
envCtx->lightSettings.fogFar = LERP16(lightSettingsList[envCtx->unk_BE].fogFar,
lightSettingsList[envCtx->unk_BD].fogFar, envCtx->unk_D8);
}
if (envCtx->unk_BD >= envCtx->numLightSettings) {
// "The color palette seems to be wrong!"
osSyncPrintf("\n" VT_FGCOL(RED) "カラーパレットがおかしいようです!");
// "Palette setting = [] Last palette number = []"
osSyncPrintf("\n" VT_FGCOL(YELLOW) "設定パレット=[%d] パレット数=[%d]\n" VT_RST, envCtx->unk_BD,
envCtx->numLightSettings);
}
}
}
envCtx->blendIndoorLights = true;
// Apply lighting adjustments
for (i = 0; i < 3; i++) {
if ((s16)(envCtx->lightSettings.ambientColor[i] + envCtx->adjAmbientColor[i]) > 255) {
lightCtx->ambientColor[i] = 255;
} else if ((s16)(envCtx->lightSettings.ambientColor[i] + envCtx->adjAmbientColor[i]) < 0) {
lightCtx->ambientColor[i] = 0;
} else {
lightCtx->ambientColor[i] = (s16)(envCtx->lightSettings.ambientColor[i] + envCtx->adjAmbientColor[i]);
}
if ((s16)(envCtx->lightSettings.light1Color[i] + envCtx->adjLight1Color[i]) > 255) {
envCtx->dirLight1.params.dir.color[i] = 255;
} else if ((s16)(envCtx->lightSettings.light1Color[i] + envCtx->adjLight1Color[i]) < 0) {
envCtx->dirLight1.params.dir.color[i] = 0;
} else {
envCtx->dirLight1.params.dir.color[i] =
(s16)(envCtx->lightSettings.light1Color[i] + envCtx->adjLight1Color[i]);
}
if ((s16)(envCtx->lightSettings.light2Color[i] + envCtx->adjLight1Color[i]) > 255) {
envCtx->dirLight2.params.dir.color[i] = 255;
} else if ((s16)(envCtx->lightSettings.light2Color[i] + envCtx->adjLight1Color[i]) < 0) {
envCtx->dirLight2.params.dir.color[i] = 0;
} else {
envCtx->dirLight2.params.dir.color[i] =
(s16)(envCtx->lightSettings.light2Color[i] + envCtx->adjLight1Color[i]);
}
if ((s16)(envCtx->lightSettings.fogColor[i] + envCtx->adjFogColor[i]) > 255) {
lightCtx->fogColor[i] = 255;
} else if ((s16)(envCtx->lightSettings.fogColor[i] + envCtx->adjFogColor[i]) < 0) {
lightCtx->fogColor[i] = 0;
} else {
lightCtx->fogColor[i] = (s16)(envCtx->lightSettings.fogColor[i] + envCtx->adjFogColor[i]);
}
}
// Set both directional light directions
envCtx->dirLight1.params.dir.x = envCtx->lightSettings.light1Dir[0];
envCtx->dirLight1.params.dir.y = envCtx->lightSettings.light1Dir[1];
envCtx->dirLight1.params.dir.z = envCtx->lightSettings.light1Dir[2];
envCtx->dirLight2.params.dir.x = envCtx->lightSettings.light2Dir[0];
envCtx->dirLight2.params.dir.y = envCtx->lightSettings.light2Dir[1];
envCtx->dirLight2.params.dir.z = envCtx->lightSettings.light2Dir[2];
// Adjust fog near and far if necessary
adjustment = envCtx->lightSettings.fogNear + envCtx->adjFogNear;
if (adjustment <= 996) {
lightCtx->fogNear = adjustment;
} else {
lightCtx->fogNear = 996;
}
adjustment = envCtx->lightSettings.fogFar + envCtx->adjFogFar;
if (adjustment <= 12800) {
lightCtx->fogFar = adjustment;
} else {
lightCtx->fogFar = 12800;
}
// When environment debug is enabled, various environment related variables can be configured via the reg editor
if (R_ENV_DISABLE_DBG) {
R_ENV_AMBIENT_COLOR(0) = lightCtx->ambientColor[0];
R_ENV_AMBIENT_COLOR(1) = lightCtx->ambientColor[1];
R_ENV_AMBIENT_COLOR(2) = lightCtx->ambientColor[2];
R_ENV_LIGHT1_COLOR(0) = envCtx->dirLight1.params.dir.color[0];
R_ENV_LIGHT1_COLOR(1) = envCtx->dirLight1.params.dir.color[1];
R_ENV_LIGHT1_COLOR(2) = envCtx->dirLight1.params.dir.color[2];
R_ENV_LIGHT2_COLOR(0) = envCtx->dirLight2.params.dir.color[0];
R_ENV_LIGHT2_COLOR(1) = envCtx->dirLight2.params.dir.color[1];
R_ENV_LIGHT2_COLOR(2) = envCtx->dirLight2.params.dir.color[2];
R_ENV_FOG_COLOR(0) = lightCtx->fogColor[0];
R_ENV_FOG_COLOR(1) = lightCtx->fogColor[1];
R_ENV_FOG_COLOR(2) = lightCtx->fogColor[2];
R_ENV_FOG_FAR = lightCtx->fogFar;
R_ENV_FOG_NEAR = lightCtx->fogNear;
R_ENV_LIGHT1_DIR(0) = envCtx->dirLight1.params.dir.x;
R_ENV_LIGHT1_DIR(1) = envCtx->dirLight1.params.dir.y;
R_ENV_LIGHT1_DIR(2) = envCtx->dirLight1.params.dir.z;
R_ENV_LIGHT2_DIR(0) = envCtx->dirLight2.params.dir.x;
R_ENV_LIGHT2_DIR(1) = envCtx->dirLight2.params.dir.y;
R_ENV_LIGHT2_DIR(2) = envCtx->dirLight2.params.dir.z;
R_ENV_WIND_DIR(0) = envCtx->windDirection.x;
R_ENV_WIND_DIR(1) = envCtx->windDirection.y;
R_ENV_WIND_DIR(2) = envCtx->windDirection.z;
R_ENV_WIND_SPEED = envCtx->windSpeed;
} else {
lightCtx->ambientColor[0] = R_ENV_AMBIENT_COLOR(0);
lightCtx->ambientColor[1] = R_ENV_AMBIENT_COLOR(1);
lightCtx->ambientColor[2] = R_ENV_AMBIENT_COLOR(2);
envCtx->dirLight1.params.dir.color[0] = R_ENV_LIGHT1_COLOR(0);
envCtx->dirLight1.params.dir.color[1] = R_ENV_LIGHT1_COLOR(1);
envCtx->dirLight1.params.dir.color[2] = R_ENV_LIGHT1_COLOR(2);
envCtx->dirLight2.params.dir.color[0] = R_ENV_LIGHT2_COLOR(0);
envCtx->dirLight2.params.dir.color[1] = R_ENV_LIGHT2_COLOR(1);
envCtx->dirLight2.params.dir.color[2] = R_ENV_LIGHT2_COLOR(2);
lightCtx->fogColor[0] = R_ENV_FOG_COLOR(0);
lightCtx->fogColor[1] = R_ENV_FOG_COLOR(1);
lightCtx->fogColor[2] = R_ENV_FOG_COLOR(2);
lightCtx->fogNear = R_ENV_FOG_NEAR;
lightCtx->fogFar = R_ENV_FOG_FAR;
if (cREG(14)) {
R_ENV_LIGHT1_DIR(0) = Math_CosS(cREG(10)) * Math_CosS(cREG(11)) * 120.0f;
envCtx->dirLight1.params.dir.x = R_ENV_LIGHT1_DIR(0);
R_ENV_LIGHT1_DIR(1) = Math_SinS(cREG(10)) * Math_CosS(cREG(11)) * 120.0f;
envCtx->dirLight1.params.dir.y = R_ENV_LIGHT1_DIR(1);
R_ENV_LIGHT1_DIR(2) = Math_SinS(cREG(11)) * 120.0f;
envCtx->dirLight1.params.dir.z = R_ENV_LIGHT1_DIR(2);
R_ENV_LIGHT2_DIR(0) = Math_CosS(cREG(12)) * Math_CosS(cREG(13)) * 120.0f;
envCtx->dirLight2.params.dir.x = R_ENV_LIGHT2_DIR(0);
R_ENV_LIGHT2_DIR(1) = Math_SinS(cREG(12)) * Math_CosS(cREG(13)) * 120.0f;
envCtx->dirLight2.params.dir.y = R_ENV_LIGHT2_DIR(1);
R_ENV_LIGHT2_DIR(2) = Math_SinS(cREG(13)) * 120.0f;
envCtx->dirLight2.params.dir.z = R_ENV_LIGHT2_DIR(2);
} else {
envCtx->dirLight1.params.dir.x = R_ENV_LIGHT1_DIR(0);
envCtx->dirLight1.params.dir.y = R_ENV_LIGHT1_DIR(1);
envCtx->dirLight1.params.dir.z = R_ENV_LIGHT1_DIR(2);
envCtx->dirLight2.params.dir.x = R_ENV_LIGHT2_DIR(0);
envCtx->dirLight2.params.dir.y = R_ENV_LIGHT2_DIR(1);
envCtx->dirLight2.params.dir.z = R_ENV_LIGHT2_DIR(2);
}
envCtx->windDirection.x = R_ENV_WIND_DIR(0);
envCtx->windDirection.y = R_ENV_WIND_DIR(1);
envCtx->windDirection.z = R_ENV_WIND_DIR(2);
envCtx->windSpeed = R_ENV_WIND_SPEED;
}
if ((envCtx->dirLight1.params.dir.x == 0) && (envCtx->dirLight1.params.dir.y == 0) &&
(envCtx->dirLight1.params.dir.z == 0)) {
envCtx->dirLight1.params.dir.x = 1;
}
if ((envCtx->dirLight2.params.dir.x == 0) && (envCtx->dirLight2.params.dir.y == 0) &&
(envCtx->dirLight2.params.dir.z == 0)) {
envCtx->dirLight2.params.dir.x = 1;
}
}
}
void Environment_DrawSunAndMoon(GlobalContext* globalCtx) {
f32 alpha;
f32 color;
f32 y;
f32 scale;
f32 temp;
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 2266);
if (globalCtx->csCtx.state != 0) {
Math_SmoothStepToF(&globalCtx->envCtx.sunPos.x,
-(Math_SinS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f) * 25.0f, 1.0f, 0.8f, 0.8f);
Math_SmoothStepToF(&globalCtx->envCtx.sunPos.y,
(Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f) * 25.0f, 1.0f, 0.8f, 0.8f);
//! @bug This should be z.
Math_SmoothStepToF(&globalCtx->envCtx.sunPos.y,
(Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 20.0f) * 25.0f, 1.0f, 0.8f, 0.8f);
} else {
globalCtx->envCtx.sunPos.x = -(Math_SinS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f) * 25.0f;
globalCtx->envCtx.sunPos.y = +(Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f) * 25.0f;
globalCtx->envCtx.sunPos.z = +(Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 20.0f) * 25.0f;
}
if (gSaveContext.entranceIndex != 0xCD || ((void)0, gSaveContext.sceneSetupIndex) != 5) {
Matrix_Translate(globalCtx->view.eye.x + globalCtx->envCtx.sunPos.x,
globalCtx->view.eye.y + globalCtx->envCtx.sunPos.y,
globalCtx->view.eye.z + globalCtx->envCtx.sunPos.z, MTXMODE_NEW);
y = globalCtx->envCtx.sunPos.y / 25.0f;
temp = y / 80.0f;
alpha = temp * 255.0f;
if (alpha < 0.0f) {
alpha = 0.0f;
}
if (alpha > 255.0f) {
alpha = 255.0f;
}
alpha = 255.0f - alpha;
color = temp;
if (color < 0.0f) {
color = 0.0f;
}
if (color > 1.0f) {
color = 1.0f;
}
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, (u8)(color * 75.0f) + 180, (u8)(color * 155.0f) + 100, 255);
gDPSetEnvColor(POLY_OPA_DISP++, 255, (u8)(color * 255.0f), (u8)(color * 255.0f), alpha);
scale = (color * 2.0f) + 10.0f;
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_kankyo.c", 2364), G_MTX_LOAD);
func_80093AD0(globalCtx->state.gfxCtx);
gSPDisplayList(POLY_OPA_DISP++, gSunDL);
Matrix_Translate(globalCtx->view.eye.x - globalCtx->envCtx.sunPos.x,
globalCtx->view.eye.y - globalCtx->envCtx.sunPos.y,
globalCtx->view.eye.z - globalCtx->envCtx.sunPos.z, MTXMODE_NEW);
color = -y / 120.0f;
color = CLAMP_MIN(color, 0.0f);
scale = -15.0f * color + 25.0f;
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
temp = -y / 80.0f;
temp = CLAMP_MAX(temp, 1.0f);
alpha = temp * 255.0f;
if (alpha > 0.0f) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_kankyo.c", 2406), G_MTX_LOAD);
func_8009398C(globalCtx->state.gfxCtx);
gDPPipeSync(POLY_OPA_DISP++);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 240, 255, 180, alpha);
gDPSetEnvColor(POLY_OPA_DISP++, 80, 70, 20, alpha);
gSPDisplayList(POLY_OPA_DISP++, gMoonDL);
}
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 2429);
}
void Environment_DrawSunLensFlare(GlobalContext* globalCtx, EnvironmentContext* envCtx, View* view,
GraphicsContext* gfxCtx, Vec3f pos, s32 unused) {
if ((globalCtx->envCtx.unk_EE[1] == 0) && (globalCtx->envCtx.unk_17 == 0)) {
Environment_DrawLensFlare(globalCtx, &globalCtx->envCtx, &globalCtx->view, globalCtx->state.gfxCtx, pos, 2000,
370, Math_CosS(((void)0, gSaveContext.dayTime) - 0x8000) * 120.0f, 400, 1);
}
}
f32 sLensFlareScales[] = { 23.0f, 12.0f, 7.0f, 5.0f, 3.0f, 10.0f, 6.0f, 2.0f, 3.0f, 1.0f };
void Environment_DrawLensFlare(GlobalContext* globalCtx, EnvironmentContext* envCtx, View* view,
GraphicsContext* gfxCtx, Vec3f pos, s32 unused, s16 scale, f32 colorIntensity,
s16 screenFillAlpha, u8 arg9) {
s16 i;
f32 tempX;
f32 tempY;
f32 tempZ;
f32 lookDirX;
f32 lookDirY;
f32 lookDirZ;
f32 tempX2;
f32 tempY2;
f32 tempZ2;
f32 posDirX;
f32 posDirY;
f32 posDirZ;
f32 length;
f32 dist;
f32 halfPosX;
f32 halfPosY;
f32 halfPosZ;
f32 cosAngle;
f32 pad160;
f32 unk88Target;
u32 isOffScreen = false;
f32 alpha;
f32 adjScale;
Vec3f screenPos;
f32 fogInfluence;
f32 temp;
f32 alphaScale;
Color_RGB8 lensFlareColors[] = {
{ 155, 205, 255 }, // blue
{ 255, 255, 205 }, // yellow
{ 255, 255, 205 }, // yellow
{ 255, 255, 205 }, // yellow
{ 155, 255, 205 }, // green
{ 205, 255, 255 }, // light blue
{ 155, 155, 255 }, // dark blue
{ 205, 175, 255 }, // purple
{ 175, 255, 205 }, // light green
{ 255, 155, 235 }, // pink
};
u32 lensFlareAlphas[] = {
50, 10, 25, 40, 70, 30, 50, 70, 50, 40,
};
u32 lensFlareTypes[] = {
LENS_FLARE_RING, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1,
LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1, LENS_FLARE_CIRCLE1,
};
OPEN_DISPS(gfxCtx, "../z_kankyo.c", 2516);
dist = Math3D_Vec3f_DistXYZ(&pos, &view->eye) / 12.0f;
// compute a unit vector in the look direction
tempX = view->at.x - view->eye.x;
tempY = view->at.y - view->eye.y;
tempZ = view->at.z - view->eye.z;
length = sqrtf(SQ(tempX) + SQ(tempY) + SQ(tempZ));
lookDirX = tempX / length;
lookDirY = tempY / length;
lookDirZ = tempZ / length;
// compute a position along the look vector half as far as pos
halfPosX = view->eye.x + lookDirX * (dist * 6.0f);
halfPosY = view->eye.y + lookDirY * (dist * 6.0f);
halfPosZ = view->eye.z + lookDirZ * (dist * 6.0f);
// compute a unit vector in the direction from halfPos to pos
tempX2 = pos.x - halfPosX;
tempY2 = pos.y - halfPosY;
tempZ2 = pos.z - halfPosZ;
length = sqrtf(SQ(tempX2) + SQ(tempY2) + SQ(tempZ2));
posDirX = tempX2 / length;
posDirY = tempY2 / length;
posDirZ = tempZ2 / length;
// compute the cosine of the angle between lookDir and posDir
cosAngle = (lookDirX * posDirX + lookDirY * posDirY + lookDirZ * posDirZ) /
sqrtf((SQ(lookDirX) + SQ(lookDirY) + SQ(lookDirZ)) * (SQ(posDirX) + SQ(posDirY) + SQ(posDirZ)));
unk88Target = cosAngle * 3.5f;
unk88Target = CLAMP_MAX(unk88Target, 1.0f);
if (arg9 == 0) {
unk88Target = cosAngle;
}
if (cosAngle < 0.0f) {
} else {
if (arg9) {
func_800C016C(globalCtx, &pos, &screenPos);
D_8015FD7E = (s16)screenPos.x;
D_8015FD80 = (s16)screenPos.y - 5.0f;
if (D_8011FB44 != 0xFFFC || screenPos.x < 0.0f || screenPos.y < 0.0f || screenPos.x > SCREEN_WIDTH ||
screenPos.y > SCREEN_HEIGHT) {
isOffScreen = true;
}
}
for (i = 0; i < ARRAY_COUNT(lensFlareTypes); i++) {
Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_NEW);
if (arg9) {
temp = Environment_LerpWeight(60, 15, globalCtx->view.fovy);
}
Matrix_Translate(-posDirX * i * dist, -posDirY * i * dist, -posDirZ * i * dist, MTXMODE_APPLY);
adjScale = sLensFlareScales[i] * cosAngle;
if (arg9) {
adjScale *= 0.001 * (scale + 630.0f * temp);
} else {
adjScale *= 0.0001f * scale * (2.0f * dist);
}
Matrix_Scale(adjScale, adjScale, adjScale, MTXMODE_APPLY);
alpha = colorIntensity / 10.0f;
alpha = CLAMP_MAX(alpha, 1.0f);
alpha = alpha * lensFlareAlphas[i];
alpha = CLAMP_MIN(alpha, 0.0f);
fogInfluence = (996 - globalCtx->lightCtx.fogNear) / 50.0f;
fogInfluence = CLAMP_MAX(fogInfluence, 1.0f);
alpha *= 1.0f - fogInfluence;
if (1) {}
if (!(isOffScreen ^ 0)) {
Math_SmoothStepToF(&envCtx->unk_88, unk88Target, 0.5f, 0.05f, 0.001f);
} else {
Math_SmoothStepToF(&envCtx->unk_88, 0.0f, 0.5f, 0.05f, 0.001f);
}
POLY_XLU_DISP = func_800947AC(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, lensFlareColors[i].r, lensFlareColors[i].g, lensFlareColors[i].b,
alpha * envCtx->unk_88);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_kankyo.c", 2662),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetCombineLERP(POLY_XLU_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0,
0, PRIMITIVE, 0);
gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_DISABLE);
gDPSetColorDither(POLY_XLU_DISP++, G_CD_DISABLE);
gSPMatrix(POLY_XLU_DISP++, &D_01000000, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
switch (lensFlareTypes[i]) {
case LENS_FLARE_CIRCLE0:
case LENS_FLARE_CIRCLE1:
gSPDisplayList(POLY_XLU_DISP++, gLensFlareCircleDL);
break;
case LENS_FLARE_RING:
gSPDisplayList(POLY_XLU_DISP++, gLensFlareRingDL);
break;
}
}
alphaScale = cosAngle - (1.5f - cosAngle);
if (screenFillAlpha != 0) {
if (alphaScale > 0.0f) {
POLY_XLU_DISP = func_800937C0(POLY_XLU_DISP);
alpha = colorIntensity / 10.0f;
alpha = CLAMP_MAX(alpha, 1.0f);
alpha = alpha * screenFillAlpha;
alpha = CLAMP_MIN(alpha, 0.0f);
fogInfluence = (996 - globalCtx->lightCtx.fogNear) / 50.0f;
fogInfluence = CLAMP_MAX(fogInfluence, 1.0f);
alpha *= 1.0f - fogInfluence;
gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_DISABLE);
gDPSetColorDither(POLY_XLU_DISP++, G_CD_DISABLE);
if (!(isOffScreen ^ 0)) {
Math_SmoothStepToF(&envCtx->unk_84, alpha * alphaScale, 0.5f, 50.0f, 0.1f);
} else {
Math_SmoothStepToF(&envCtx->unk_84, 0.0f, 0.5f, 50.0f, 0.1f);
}
temp = colorIntensity / 120.0f;
temp = CLAMP_MIN(temp, 0.0f);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, (u8)(temp * 75.0f) + 180, (u8)(temp * 155.0f) + 100,
(u8)envCtx->unk_84);
gDPFillRectangle(POLY_XLU_DISP++, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
} else {
envCtx->unk_84 = 0.0f;
}
}
}
CLOSE_DISPS(gfxCtx, "../z_kankyo.c", 2750);
}
f32 func_800746DC(void) {
return Rand_ZeroOne() - 0.5f;
}
void Environment_DrawRain(GlobalContext* globalCtx, View* view, GraphicsContext* gfxCtx) {
s16 i;
s32 pad;
Vec3f vec;
f32 temp1;
f32 temp2;
f32 temp3;
f32 length;
f32 rotX;
f32 rotY;
f32 x50;
f32 y50;
f32 z50;
f32 x280;
f32 z280;
Vec3f unused = { 0.0f, 0.0f, 0.0f };
Vec3f windDirection = { 0.0f, 0.0f, 0.0f };
Player* player = GET_PLAYER(globalCtx);
if (!(globalCtx->cameraPtrs[0]->unk_14C & 0x100) && (globalCtx->envCtx.unk_EE[2] == 0)) {
OPEN_DISPS(gfxCtx, "../z_kankyo.c", 2799);
vec.x = view->at.x - view->eye.x;
vec.y = view->at.y - view->eye.y;
vec.z = view->at.z - view->eye.z;
length = sqrtf(SQXYZ(vec));
temp1 = vec.x / length;
temp2 = vec.y / length;
temp3 = vec.z / length;
x50 = view->eye.x + temp1 * 50.0f;
y50 = view->eye.y + temp2 * 50.0f;
z50 = view->eye.z + temp3 * 50.0f;
x280 = view->eye.x + temp1 * 280.0f;
z280 = view->eye.z + temp3 * 280.0f;
if (globalCtx->envCtx.unk_EE[1]) {
gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 150, 255, 255, 30);
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20);
}
// draw rain drops
for (i = 0; i < globalCtx->envCtx.unk_EE[1]; i++) {
temp2 = Rand_ZeroOne();
temp1 = Rand_ZeroOne();
temp3 = Rand_ZeroOne();
Matrix_Translate((temp2 - 0.7f) * 100.0f + x50, (temp1 - 0.7f) * 100.0f + y50,
(temp3 - 0.7f) * 100.0f + z50, MTXMODE_NEW);
windDirection.x = globalCtx->envCtx.windDirection.x;
windDirection.y = globalCtx->envCtx.windDirection.y;
windDirection.z = globalCtx->envCtx.windDirection.z;
vec.x = windDirection.x;
vec.y = windDirection.y + 500.0f + Rand_ZeroOne() * 200.0f;
vec.z = windDirection.z;
length = sqrtf(SQXZ(vec));
gSPMatrix(POLY_XLU_DISP++, &D_01000000, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
rotX = Math_Atan2F(length, -vec.y);
rotY = Math_Atan2F(vec.z, vec.x);
Matrix_RotateY(-rotY, MTXMODE_APPLY);
Matrix_RotateX(M_PI / 2 - rotX, MTXMODE_APPLY);
Matrix_Scale(0.4f, 1.2f, 0.4f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_kankyo.c", 2887),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gRaindropDL);
}
// draw droplet rings on the ground
if (player->actor.world.pos.y < view->eye.y) {
u8 firstDone = false;
for (i = 0; i < globalCtx->envCtx.unk_EE[1]; i++) {
if (!firstDone) {
func_80093D84(gfxCtx);
gDPSetEnvColor(POLY_XLU_DISP++, 155, 155, 155, 0);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 120);
firstDone++;
}
Matrix_Translate(func_800746DC() * 280.0f + x280, player->actor.world.pos.y + 2.0f,
func_800746DC() * 280.0f + z280, MTXMODE_NEW);
if ((LINK_IS_ADULT && ((player->actor.world.pos.y + 2.0f - view->eye.y) > -48.0f)) ||
(!LINK_IS_ADULT && ((player->actor.world.pos.y + 2.0f - view->eye.y) > -30.0f))) {
Matrix_Scale(0.02f, 0.02f, 0.02f, MTXMODE_APPLY);
} else {
Matrix_Scale(0.1f, 0.1f, 0.1f, MTXMODE_APPLY);
}
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_kankyo.c", 2940),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gEffShockwaveDL);
}
}
CLOSE_DISPS(gfxCtx, "../z_kankyo.c", 2946);
}
}
void func_80074CE8(GlobalContext* globalCtx, u32 arg1) {
if ((globalCtx->envCtx.unk_BD != arg1) && (globalCtx->envCtx.unk_D8 >= 1.0f) &&
(globalCtx->envCtx.unk_BF == 0xFF)) {
if (arg1 > 30) {
arg1 = 0;
}
globalCtx->envCtx.unk_D8 = 0.0f;
globalCtx->envCtx.unk_BE = globalCtx->envCtx.unk_BD;
globalCtx->envCtx.unk_BD = arg1;
}
}
/**
* Draw color filters over the skybox. There are two filters.
* The first uses the global fog color, and an alpha calculated with `fogNear`.
* This filter draws unconditionally for skybox 29 at full alpha.
* (note: skybox 29 is unused in the original game)
* For the rest of the skyboxes it will draw if fogNear is less than 980.
*
* The second filter uses a custom color specified in `skyboxFilterColor`
* and can be enabled with `customSkyboxFilter`.
*
* An example usage of a filter is to dim the skybox in cloudy conditions.
*/
void Environment_DrawSkyboxFilters(GlobalContext* globalCtx) {
if (((globalCtx->skyboxId != SKYBOX_NONE) && (globalCtx->lightCtx.fogNear < 980)) ||
(globalCtx->skyboxId == SKYBOX_UNSET_1D)) {
f32 alpha;
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 3032);
func_800938B4(globalCtx->state.gfxCtx);
alpha = (1000 - globalCtx->lightCtx.fogNear) * 0.02f;
if (globalCtx->skyboxId == SKYBOX_UNSET_1D) {
alpha = 1.0f;
}
if (alpha > 1.0f) {
alpha = 1.0f;
}
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, globalCtx->lightCtx.fogColor[0], globalCtx->lightCtx.fogColor[1],
globalCtx->lightCtx.fogColor[2], 255.0f * alpha);
gDPFillRectangle(POLY_OPA_DISP++, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 3043);
}
if (globalCtx->envCtx.customSkyboxFilter) {
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 3048);
func_800938B4(globalCtx->state.gfxCtx);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, globalCtx->envCtx.skyboxFilterColor[0],
globalCtx->envCtx.skyboxFilterColor[1], globalCtx->envCtx.skyboxFilterColor[2],
globalCtx->envCtx.skyboxFilterColor[3]);
gDPFillRectangle(POLY_OPA_DISP++, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 3056);
}
}
void Environment_DrawLightningFlash(GlobalContext* globalCtx, u8 red, u8 green, u8 blue, u8 alpha) {
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 3069);
func_800938B4(globalCtx->state.gfxCtx);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, red, green, blue, alpha);
gDPFillRectangle(POLY_OPA_DISP++, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 3079);
}
void Environment_UpdateLightningStrike(GlobalContext* globalCtx) {
if (globalCtx->envCtx.lightningMode != LIGHTNING_MODE_OFF) {
switch (gLightningStrike.state) {
case LIGHTNING_STRIKE_WAIT:
// every frame theres a 10% chance of the timer advancing 50 units
if (Rand_ZeroOne() < 0.1f) {
gLightningStrike.delayTimer += 50.0f;
}
gLightningStrike.delayTimer += Rand_ZeroOne();
if (gLightningStrike.delayTimer > 500.0f) {
gLightningStrike.flashRed = 200;
gLightningStrike.flashGreen = 200;
gLightningStrike.flashBlue = 255;
gLightningStrike.flashAlphaTarget = 200;
gLightningStrike.delayTimer = 0.0f;
Environment_AddLightningBolts(globalCtx,
(u8)(Rand_ZeroOne() * (ARRAY_COUNT(sLightningBolts) - 0.1f)) + 1);
sLightningFlashAlpha = 0;
gLightningStrike.state++;
}
break;
case LIGHTNING_STRIKE_START:
gLightningStrike.flashRed = 200;
gLightningStrike.flashGreen = 200;
gLightningStrike.flashBlue = 255;
globalCtx->envCtx.adjAmbientColor[0] += 80;
globalCtx->envCtx.adjAmbientColor[1] += 80;
globalCtx->envCtx.adjAmbientColor[2] += 100;
sLightningFlashAlpha += 100;
if (sLightningFlashAlpha >= gLightningStrike.flashAlphaTarget) {
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_LIGHTNING, CHANNEL_IO_PORT_0, 0);
gLightningStrike.state++;
gLightningStrike.flashAlphaTarget = 0;
}
break;
case LIGHTNING_STRIKE_END:
if (globalCtx->envCtx.adjAmbientColor[0] > 0) {
globalCtx->envCtx.adjAmbientColor[0] -= 10;
globalCtx->envCtx.adjAmbientColor[1] -= 10;
}
if (globalCtx->envCtx.adjAmbientColor[2] > 0) {
globalCtx->envCtx.adjAmbientColor[2] -= 10;
}
sLightningFlashAlpha -= 10;
if (sLightningFlashAlpha <= gLightningStrike.flashAlphaTarget) {
globalCtx->envCtx.adjAmbientColor[0] = 0;
globalCtx->envCtx.adjAmbientColor[1] = 0;
globalCtx->envCtx.adjAmbientColor[2] = 0;
gLightningStrike.state = LIGHTNING_STRIKE_WAIT;
if (globalCtx->envCtx.lightningMode == LIGHTNING_MODE_LAST) {
globalCtx->envCtx.lightningMode = LIGHTNING_MODE_OFF;
}
}
break;
}
}
if (gLightningStrike.state != LIGHTNING_STRIKE_WAIT) {
Environment_DrawLightningFlash(globalCtx, gLightningStrike.flashRed, gLightningStrike.flashGreen,
gLightningStrike.flashBlue, sLightningFlashAlpha);
}
}
/**
* Request the number of lightning bolts specified by `num`
* Note: only 3 lightning bolts can be active at the same time.
*/
void Environment_AddLightningBolts(GlobalContext* globalCtx, u8 num) {
s16 boltsAdded = 0;
s16 i;
for (i = 0; i < ARRAY_COUNT(sLightningBolts); i++) {
if (sLightningBolts[i].state == LIGHTNING_BOLT_INACTIVE) {
sLightningBolts[i].state = LIGHTNING_BOLT_START;
boltsAdded++;
if (boltsAdded >= num) {
break;
}
}
}
}
/**
* Draw any active lightning bolt entries contained in `sLightningBolts`
*/
void Environment_DrawLightning(GlobalContext* globalCtx, s32 unused) {
static void* lightningTextures[] = {
gEffLightning1Tex, gEffLightning2Tex, gEffLightning3Tex,
gEffLightning4Tex, gEffLightning5Tex, gEffLightning6Tex,
gEffLightning7Tex, gEffLightning8Tex, NULL,
};
s16 i;
f32 dx;
f32 dz;
f32 x;
f32 z;
s32 pad[2];
Vec3f unused1 = { 0.0f, 0.0f, 0.0f };
Vec3f unused2 = { 0.0f, 0.0f, 0.0f };
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 3253);
for (i = 0; i < ARRAY_COUNT(sLightningBolts); i++) {
switch (sLightningBolts[i].state) {
case LIGHTNING_BOLT_START:
dx = globalCtx->view.at.x - globalCtx->view.eye.x;
dz = globalCtx->view.at.z - globalCtx->view.eye.z;
x = dx / sqrtf(SQ(dx) + SQ(dz));
z = dz / sqrtf(SQ(dx) + SQ(dz));
sLightningBolts[i].pos.x = globalCtx->view.eye.x + x * 9500.0f;
sLightningBolts[i].pos.y = Rand_ZeroOne() * 1000.0f + 4000.0f;
sLightningBolts[i].pos.z = globalCtx->view.eye.z + z * 9500.0f;
sLightningBolts[i].offset.x = (Rand_ZeroOne() - 0.5f) * 5000.0f;
sLightningBolts[i].offset.y = 0.0f;
sLightningBolts[i].offset.z = (Rand_ZeroOne() - 0.5f) * 5000.0f;
sLightningBolts[i].textureIndex = 0;
sLightningBolts[i].pitch = (Rand_ZeroOne() - 0.5f) * 40.0f;
sLightningBolts[i].roll = (Rand_ZeroOne() - 0.5f) * 40.0f;
sLightningBolts[i].delayTimer = 3 * (i + 1);
sLightningBolts[i].state++;
break;
case LIGHTNING_BOLT_WAIT:
sLightningBolts[i].delayTimer--;
if (sLightningBolts[i].delayTimer <= 0) {
sLightningBolts[i].state++;
}
break;
case LIGHTNING_BOLT_DRAW:
if (sLightningBolts[i].textureIndex < 7) {
sLightningBolts[i].textureIndex++;
} else {
sLightningBolts[i].state = LIGHTNING_BOLT_INACTIVE;
}
break;
}
if (sLightningBolts[i].state == LIGHTNING_BOLT_DRAW) {
Matrix_Translate(sLightningBolts[i].pos.x + sLightningBolts[i].offset.x,
sLightningBolts[i].pos.y + sLightningBolts[i].offset.y,
sLightningBolts[i].pos.z + sLightningBolts[i].offset.z, MTXMODE_NEW);
Matrix_RotateX(DEG_TO_RAD(sLightningBolts[i].pitch), MTXMODE_APPLY);
Matrix_RotateZ(DEG_TO_RAD(sLightningBolts[i].roll), MTXMODE_APPLY);
Matrix_Scale(22.0f, 100.0f, 22.0f, MTXMODE_APPLY);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 128);
gDPSetEnvColor(POLY_XLU_DISP++, 0, 255, 255, 128);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_kankyo.c", 3333),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(lightningTextures[sLightningBolts[i].textureIndex]));
func_80094C50(globalCtx->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, &D_01000000, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gEffLightningDL);
}
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 3353);
}
void Environment_PlaySceneSequence(GlobalContext* globalCtx) {
globalCtx->envCtx.unk_E0 = 0xFF;
// both lost woods exits on the bridge from kokiri to hyrule field
if (((void)0, gSaveContext.entranceIndex) == 0x4DE || ((void)0, gSaveContext.entranceIndex) == 0x5E0) {
Audio_PlayNatureAmbienceSequence(NATURE_ID_KOKIRI_REGION);
} else if (((void)0, gSaveContext.forcedSeqId) != NA_BGM_GENERAL_SFX) {
if (!Environment_IsForcedSequenceDisabled()) {
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | (s32)((void)0, gSaveContext.forcedSeqId));
}
gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX;
} else if (globalCtx->sequenceCtx.seqId == NA_BGM_NO_MUSIC) {
if (globalCtx->sequenceCtx.natureAmbienceId == NATURE_ID_NONE) {
return;
}
if (((void)0, gSaveContext.natureAmbienceId) != globalCtx->sequenceCtx.natureAmbienceId) {
Audio_PlayNatureAmbienceSequence(globalCtx->sequenceCtx.natureAmbienceId);
}
} else if (globalCtx->sequenceCtx.natureAmbienceId == NATURE_ID_NONE) {
// "BGM Configuration"
osSyncPrintf("\n\n\nBGM設定game_play->sound_info.BGM=[%d] old_bgm=[%d]\n\n", globalCtx->sequenceCtx.seqId,
((void)0, gSaveContext.seqId));
if (((void)0, gSaveContext.seqId) != globalCtx->sequenceCtx.seqId) {
func_800F5550(globalCtx->sequenceCtx.seqId);
}
} else if (((void)0, gSaveContext.dayTime) > 0x4AAA && ((void)0, gSaveContext.dayTime) < 0xB71D) {
if (((void)0, gSaveContext.seqId) != globalCtx->sequenceCtx.seqId) {
func_800F5550(globalCtx->sequenceCtx.seqId);
}
globalCtx->envCtx.unk_E0 = 1;
} else {
if (((void)0, gSaveContext.natureAmbienceId) != globalCtx->sequenceCtx.natureAmbienceId) {
Audio_PlayNatureAmbienceSequence(globalCtx->sequenceCtx.natureAmbienceId);
}
if (((void)0, gSaveContext.dayTime) > 0xB71C && ((void)0, gSaveContext.dayTime) < 0xCAAC) {
globalCtx->envCtx.unk_E0 = 3;
} else if (((void)0, gSaveContext.dayTime) > 0xCAAC || ((void)0, gSaveContext.dayTime) < 0x4555) {
globalCtx->envCtx.unk_E0 = 5;
} else {
globalCtx->envCtx.unk_E0 = 7;
}
}
osSyncPrintf("\n-----------------\n", ((void)0, gSaveContext.forcedSeqId));
osSyncPrintf("\n 強制BGM=[%d]", ((void)0, gSaveContext.forcedSeqId)); // "Forced BGM"
osSyncPrintf("\n =[%d]", globalCtx->sequenceCtx.seqId);
osSyncPrintf("\n エンブ=[%d]", globalCtx->sequenceCtx.natureAmbienceId);
osSyncPrintf("\n status=[%d]", globalCtx->envCtx.unk_E0);
Audio_SetEnvReverb(globalCtx->roomCtx.curRoom.echo);
}
// updates bgm/sfx and other things as the day progresses
void func_80075B44(GlobalContext* globalCtx) {
switch (globalCtx->envCtx.unk_E0) {
case 0:
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_4 << 4 | NATURE_CHANNEL_CRITTER_5,
CHANNEL_IO_PORT_1, 0);
if (globalCtx->envCtx.unk_EE[0] == 0 && globalCtx->envCtx.unk_F2[0] == 0) {
osSyncPrintf("\n\n\nNa_StartMorinigBgm\n\n");
func_800F5510(globalCtx->sequenceCtx.seqId);
}
globalCtx->envCtx.unk_E0++;
break;
case 1:
if (gSaveContext.dayTime > 0xB71C) {
if (globalCtx->envCtx.unk_EE[0] == 0 && globalCtx->envCtx.unk_F2[0] == 0) {
Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0xF000FF);
}
globalCtx->envCtx.unk_E0++;
}
break;
case 2:
if (gSaveContext.dayTime > 0xC000) {
func_800788CC(NA_SE_EV_DOG_CRY_EVENING);
globalCtx->envCtx.unk_E0++;
}
break;
case 3:
if (globalCtx->envCtx.unk_EE[0] == 0 && globalCtx->envCtx.unk_F2[0] == 0) {
Audio_PlayNatureAmbienceSequence(globalCtx->sequenceCtx.natureAmbienceId);
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_0, CHANNEL_IO_PORT_1, 1);
}
globalCtx->envCtx.unk_E0++;
break;
case 4:
if (gSaveContext.dayTime > 0xCAAB) {
globalCtx->envCtx.unk_E0++;
}
break;
case 5:
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_0, CHANNEL_IO_PORT_1, 0);
if (globalCtx->envCtx.unk_EE[0] == 0 && globalCtx->envCtx.unk_F2[0] == 0) {
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_1 << 4 | NATURE_CHANNEL_CRITTER_3,
CHANNEL_IO_PORT_1, 1);
}
globalCtx->envCtx.unk_E0++;
break;
case 6:
if ((gSaveContext.dayTime < 0xCAAC) && (gSaveContext.dayTime > 0x4555)) {
gSaveContext.totalDays++;
gSaveContext.bgsDayCount++;
gSaveContext.dogIsLost = true;
func_80078884(NA_SE_EV_CHICKEN_CRY_M);
if ((Inventory_ReplaceItem(globalCtx, ITEM_WEIRD_EGG, ITEM_CHICKEN) ||
Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO)) &&
globalCtx->csCtx.state == 0 && !Player_InCsMode(globalCtx)) {
Message_StartTextbox(globalCtx, 0x3066, NULL);
}
globalCtx->envCtx.unk_E0++;
}
break;
case 7:
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_1 << 4 | NATURE_CHANNEL_CRITTER_3,
CHANNEL_IO_PORT_1, 0);
if (globalCtx->envCtx.unk_EE[0] == 0 && globalCtx->envCtx.unk_F2[0] == 0) {
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_CRITTER_4 << 4 | NATURE_CHANNEL_CRITTER_5,
CHANNEL_IO_PORT_1, 1);
}
globalCtx->envCtx.unk_E0++;
break;
case 8:
if (gSaveContext.dayTime > 0x4AAB) {
globalCtx->envCtx.unk_E0 = 0;
}
break;
}
}
void Environment_DrawCustomLensFlare(GlobalContext* globalCtx) {
Vec3f pos;
if (gCustomLensFlareOn) {
pos.x = gCustomLensFlarePos.x;
pos.y = gCustomLensFlarePos.y;
pos.z = gCustomLensFlarePos.z;
Environment_DrawLensFlare(globalCtx, &globalCtx->envCtx, &globalCtx->view, globalCtx->state.gfxCtx, pos,
gLensFlareUnused, gLensFlareScale, gLensFlareColorIntensity,
gLensFlareScreenFillAlpha, 0);
}
}
void Environment_InitGameOverLights(GlobalContext* globalCtx) {
s32 pad;
Player* player = GET_PLAYER(globalCtx);
sGameOverLightsIntensity = 0;
Lights_PointNoGlowSetInfo(&sNGameOverLightInfo, (s16)player->actor.world.pos.x - 10.0f,
(s16)player->actor.world.pos.y + 10.0f, (s16)player->actor.world.pos.z - 10.0f, 0, 0, 0,
255);
sNGameOverLightNode = LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, &sNGameOverLightInfo);
Lights_PointNoGlowSetInfo(&sSGameOverLightInfo, (s16)player->actor.world.pos.x + 10.0f,
(s16)player->actor.world.pos.y + 10.0f, (s16)player->actor.world.pos.z + 10.0f, 0, 0, 0,
255);
sSGameOverLightNode = LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, &sSGameOverLightInfo);
}
void Environment_FadeInGameOverLights(GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s16 i;
Lights_PointNoGlowSetInfo(&sNGameOverLightInfo, (s16)player->actor.world.pos.x - 10.0f,
(s16)player->actor.world.pos.y + 10.0f, (s16)player->actor.world.pos.z - 10.0f,
sGameOverLightsIntensity, sGameOverLightsIntensity, sGameOverLightsIntensity, 255);
Lights_PointNoGlowSetInfo(&sSGameOverLightInfo, (s16)player->actor.world.pos.x + 10.0f,
(s16)player->actor.world.pos.y + 10.0f, (s16)player->actor.world.pos.z + 10.0f,
sGameOverLightsIntensity, sGameOverLightsIntensity, sGameOverLightsIntensity, 255);
if (sGameOverLightsIntensity < 254) {
sGameOverLightsIntensity += 2;
}
if (func_800C0CB8(globalCtx)) {
for (i = 0; i < 3; i++) {
if (globalCtx->envCtx.adjAmbientColor[i] > -255) {
globalCtx->envCtx.adjAmbientColor[i] -= 12;
globalCtx->envCtx.adjLight1Color[i] -= 12;
}
globalCtx->envCtx.adjFogColor[i] = -255;
}
if (globalCtx->envCtx.lightSettings.fogFar + globalCtx->envCtx.adjFogFar > 900) {
globalCtx->envCtx.adjFogFar -= 100;
}
if (globalCtx->envCtx.lightSettings.fogNear + globalCtx->envCtx.adjFogNear > 950) {
globalCtx->envCtx.adjFogNear -= 10;
}
} else {
globalCtx->envCtx.fillScreen = true;
globalCtx->envCtx.screenFillColor[0] = 0;
globalCtx->envCtx.screenFillColor[1] = 0;
globalCtx->envCtx.screenFillColor[2] = 0;
globalCtx->envCtx.screenFillColor[3] = sGameOverLightsIntensity;
}
}
void Environment_FadeOutGameOverLights(GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s16 i;
if (sGameOverLightsIntensity >= 3) {
sGameOverLightsIntensity -= 3;
} else {
sGameOverLightsIntensity = 0;
}
if (sGameOverLightsIntensity == 1) {
LightContext_RemoveLight(globalCtx, &globalCtx->lightCtx, sNGameOverLightNode);
LightContext_RemoveLight(globalCtx, &globalCtx->lightCtx, sSGameOverLightNode);
} else if (sGameOverLightsIntensity >= 2) {
Lights_PointNoGlowSetInfo(&sNGameOverLightInfo, (s16)player->actor.world.pos.x - 10.0f,
(s16)player->actor.world.pos.y + 10.0f, (s16)player->actor.world.pos.z - 10.0f,
sGameOverLightsIntensity, sGameOverLightsIntensity, sGameOverLightsIntensity, 255);
Lights_PointNoGlowSetInfo(&sSGameOverLightInfo, (s16)player->actor.world.pos.x + 10.0f,
(s16)player->actor.world.pos.y + 10.0f, (s16)player->actor.world.pos.z + 10.0f,
sGameOverLightsIntensity, sGameOverLightsIntensity, sGameOverLightsIntensity, 255);
}
if (func_800C0CB8(globalCtx)) {
for (i = 0; i < 3; i++) {
Math_SmoothStepToS(&globalCtx->envCtx.adjAmbientColor[i], 0, 5, 12, 1);
Math_SmoothStepToS(&globalCtx->envCtx.adjLight1Color[i], 0, 5, 12, 1);
globalCtx->envCtx.adjFogColor[i] = 0;
}
globalCtx->envCtx.adjFogFar = 0;
globalCtx->envCtx.adjFogNear = 0;
} else {
globalCtx->envCtx.fillScreen = true;
globalCtx->envCtx.screenFillColor[0] = 0;
globalCtx->envCtx.screenFillColor[1] = 0;
globalCtx->envCtx.screenFillColor[2] = 0;
globalCtx->envCtx.screenFillColor[3] = sGameOverLightsIntensity;
if (sGameOverLightsIntensity == 0) {
globalCtx->envCtx.fillScreen = false;
}
}
}
void func_800766C4(GlobalContext* globalCtx) {
u8 max = MAX(globalCtx->envCtx.unk_EE[0], globalCtx->envCtx.unk_F2[0]);
if (globalCtx->envCtx.unk_EE[1] != max && ((globalCtx->state.frames % 8) == 0)) {
if (globalCtx->envCtx.unk_EE[1] < max) {
globalCtx->envCtx.unk_EE[1] += 2;
} else {
globalCtx->envCtx.unk_EE[1] -= 2;
}
}
}
void Environment_FillScreen(GraphicsContext* gfxCtx, u8 red, u8 green, u8 blue, u8 alpha, u8 drawFlags) {
if (alpha != 0) {
OPEN_DISPS(gfxCtx, "../z_kankyo.c", 3835);
if (drawFlags & FILL_SCREEN_OPA) {
POLY_OPA_DISP = func_800937C0(POLY_OPA_DISP);
gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, red, green, blue, alpha);
gDPSetAlphaDither(POLY_OPA_DISP++, G_AD_DISABLE);
gDPSetColorDither(POLY_OPA_DISP++, G_CD_DISABLE);
gDPFillRectangle(POLY_OPA_DISP++, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
}
if (drawFlags & FILL_SCREEN_XLU) {
POLY_XLU_DISP = func_800937C0(POLY_XLU_DISP);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, red, green, blue, alpha);
if ((u32)alpha == 255) {
gDPSetRenderMode(POLY_XLU_DISP++, G_RM_OPA_SURF, G_RM_OPA_SURF2);
}
gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_DISABLE);
gDPSetColorDither(POLY_XLU_DISP++, G_CD_DISABLE);
gDPFillRectangle(POLY_XLU_DISP++, 0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1);
}
CLOSE_DISPS(gfxCtx, "../z_kankyo.c", 3863);
}
}
Color_RGB8 sSandstormPrimColors[] = {
{ 210, 156, 85 },
{ 255, 200, 100 },
{ 225, 160, 50 },
{ 105, 90, 40 },
};
Color_RGB8 sSandstormEnvColors[] = {
{ 155, 106, 35 },
{ 200, 150, 50 },
{ 170, 110, 0 },
{ 50, 40, 0 },
};
void Environment_DrawSandstorm(GlobalContext* globalCtx, u8 sandstormState) {
s32 primA1;
s32 envA1;
s32 primA = globalCtx->envCtx.sandstormPrimA;
s32 envA = globalCtx->envCtx.sandstormEnvA;
Color_RGBA8 primColor;
Color_RGBA8 envColor;
s32 pad;
f32 sp98;
u16 sp96;
u16 sp94;
u16 sp92;
switch (sandstormState) {
case SANDSTORM_ACTIVE:
if ((globalCtx->sceneNum == SCENE_SPOT13) && (globalCtx->roomCtx.curRoom.num == 0)) {
envA1 = 0;
primA1 = (globalCtx->envCtx.sandstormEnvA > 128) ? 255 : globalCtx->envCtx.sandstormEnvA >> 1;
} else {
primA1 = globalCtx->state.frames % 128;
if (primA1 > 64) {
primA1 = 128 - primA1;
}
primA1 += 73;
envA1 = 128;
}
break;
case SANDSTORM_FILL:
primA1 = 255;
envA1 = (globalCtx->envCtx.sandstormPrimA >= 255) ? 255 : 128;
break;
case SANDSTORM_UNFILL:
envA1 = 128;
if (globalCtx->envCtx.sandstormEnvA > 128) {
primA1 = 0xFF;
} else {
primA1 = globalCtx->state.frames % 128;
if (primA1 > 64) {
primA1 = 128 - primA1;
}
primA1 += 73;
}
if ((primA1 >= primA) && (primA1 != 255)) {
globalCtx->envCtx.sandstormState = SANDSTORM_ACTIVE;
}
break;
case SANDSTORM_DISSIPATE:
envA1 = 0;
primA1 = (globalCtx->envCtx.sandstormEnvA > 128) ? 255 : globalCtx->envCtx.sandstormEnvA >> 1;
if (primA == 0) {
globalCtx->envCtx.sandstormState = SANDSTORM_OFF;
}
break;
}
if (ABS(primA - primA1) < 9) {
primA = primA1;
} else if (primA1 < primA) {
primA = primA - 9;
} else {
primA = primA + 9;
}
if (ABS(envA - envA1) < 9) {
envA = envA1;
} else if (envA1 < envA) {
envA = envA - 9;
} else {
envA = envA + 9;
}
globalCtx->envCtx.sandstormPrimA = primA;
globalCtx->envCtx.sandstormEnvA = envA;
sp98 = (512.0f - (primA + envA)) * (3.0f / 128.0f);
if (sp98 > 6.0f) {
sp98 = 6.0f;
}
if (globalCtx->envCtx.indoors || (globalCtx->envCtx.unk_BF != 0xFF)) {
primColor.r = sSandstormPrimColors[1].r;
primColor.g = sSandstormPrimColors[1].g;
primColor.b = sSandstormPrimColors[1].b;
envColor.r = sSandstormEnvColors[1].r;
envColor.g = sSandstormEnvColors[1].g;
envColor.b = sSandstormEnvColors[1].b;
} else if (D_8011FDCC == D_8011FDD0) {
primColor.r = sSandstormPrimColors[D_8011FDCC].r;
primColor.g = sSandstormPrimColors[D_8011FDCC].g;
primColor.b = sSandstormPrimColors[D_8011FDCC].b;
envColor.r = sSandstormEnvColors[D_8011FDCC].r;
envColor.g = sSandstormEnvColors[D_8011FDCC].g;
envColor.b = sSandstormEnvColors[D_8011FDCC].b;
} else {
primColor.r = (s32)F32_LERP(sSandstormPrimColors[D_8011FDCC].r, sSandstormPrimColors[D_8011FDD0].r, D_8011FDD4);
primColor.g = (s32)F32_LERP(sSandstormPrimColors[D_8011FDCC].g, sSandstormPrimColors[D_8011FDD0].g, D_8011FDD4);
primColor.b = (s32)F32_LERP(sSandstormPrimColors[D_8011FDCC].b, sSandstormPrimColors[D_8011FDD0].b, D_8011FDD4);
envColor.r = (s32)F32_LERP(sSandstormEnvColors[D_8011FDCC].r, sSandstormEnvColors[D_8011FDD0].r, D_8011FDD4);
envColor.g = (s32)F32_LERP(sSandstormEnvColors[D_8011FDCC].g, sSandstormEnvColors[D_8011FDD0].g, D_8011FDD4);
envColor.b = (s32)F32_LERP(sSandstormEnvColors[D_8011FDCC].b, sSandstormEnvColors[D_8011FDD0].b, D_8011FDD4);
}
envColor.r = ((envColor.r * sp98) + ((6.0f - sp98) * primColor.r)) * (1.0f / 6.0f);
envColor.g = ((envColor.g * sp98) + ((6.0f - sp98) * primColor.g)) * (1.0f / 6.0f);
envColor.b = ((envColor.b * sp98) + ((6.0f - sp98) * primColor.b)) * (1.0f / 6.0f);
sp96 = (s32)(D_8015FDB0 * (11.0f / 6.0f));
sp94 = (s32)(D_8015FDB0 * (9.0f / 6.0f));
sp92 = (s32)(D_8015FDB0 * (6.0f / 6.0f));
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 4044);
POLY_XLU_DISP = func_80093F34(POLY_XLU_DISP);
gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_NOISE);
gDPSetColorDither(POLY_XLU_DISP++, G_CD_NOISE);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, primColor.r, primColor.g, primColor.b, globalCtx->envCtx.sandstormPrimA);
gDPSetEnvColor(POLY_XLU_DISP++, envColor.r, envColor.g, envColor.b, globalCtx->envCtx.sandstormEnvA);
gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (u32)sp96 % 0x1000, 0, 0x200, 0x20, 1, (u32)sp94 % 0x1000,
0xFFF - ((u32)sp92 % 0x1000), 0x100, 0x40));
gDPSetTextureLUT(POLY_XLU_DISP++, G_TT_NONE);
gSPDisplayList(POLY_XLU_DISP++, gFieldSandstormDL);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_kankyo.c", 4068);
D_8015FDB0 += (s32)sp98;
}
void Environment_AdjustLights(GlobalContext* globalCtx, f32 arg1, f32 arg2, f32 arg3, f32 arg4) {
f32 temp;
s32 i;
if (globalCtx->roomCtx.curRoom.unk_03 != 5 && func_800C0CB8(globalCtx)) {
arg1 = CLAMP_MIN(arg1, 0.0f);
arg1 = CLAMP_MAX(arg1, 1.0f);
temp = arg1 - arg3;
if (arg1 < arg3) {
temp = 0.0f;
}
globalCtx->envCtx.adjFogNear = (arg2 - globalCtx->envCtx.lightSettings.fogNear) * temp;
if (arg1 == 0.0f) {
for (i = 0; i < 3; i++) {
globalCtx->envCtx.adjFogColor[i] = 0;
}
} else {
temp = arg1 * 5.0f;
temp = CLAMP_MAX(temp, 1.0f);
for (i = 0; i < 3; i++) {
globalCtx->envCtx.adjFogColor[i] = -(s16)(globalCtx->envCtx.lightSettings.fogColor[i] * temp);
}
}
if (arg4 <= 0.0f) {
return;
}
arg1 *= arg4;
for (i = 0; i < 3; i++) {
globalCtx->envCtx.adjAmbientColor[i] = -(s16)(globalCtx->envCtx.lightSettings.ambientColor[i] * arg1);
globalCtx->envCtx.adjLight1Color[i] = -(s16)(globalCtx->envCtx.lightSettings.light1Color[i] * arg1);
}
}
}
s32 Environment_GetBgsDayCount(void) {
return gSaveContext.bgsDayCount;
}
void Environment_ClearBgsDayCount(void) {
gSaveContext.bgsDayCount = 0;
}
s32 Environment_GetTotalDays(void) {
return gSaveContext.totalDays;
}
void Environment_ForcePlaySequence(u16 seqId) {
gSaveContext.forcedSeqId = seqId;
}
s32 Environment_IsForcedSequenceDisabled(void) {
s32 isDisabled = false;
if (gSaveContext.forcedSeqId == NA_BGM_DISABLED) {
isDisabled = true;
}
return isDisabled;
}
void Environment_PlayStormNatureAmbience(GlobalContext* globalCtx) {
if (globalCtx->sequenceCtx.natureAmbienceId == NATURE_ID_NONE) {
Audio_PlayNatureAmbienceSequence(NATURE_ID_MARKET_NIGHT);
} else {
Audio_PlayNatureAmbienceSequence(globalCtx->sequenceCtx.natureAmbienceId);
}
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_RAIN, CHANNEL_IO_PORT_1, 1);
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_LIGHTNING, CHANNEL_IO_PORT_1, 1);
}
void Environment_StopStormNatureAmbience(GlobalContext* globalCtx) {
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_RAIN, CHANNEL_IO_PORT_1, 0);
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_LIGHTNING, CHANNEL_IO_PORT_1, 0);
if (func_800FA0B4(SEQ_PLAYER_BGM_MAIN) == NA_BGM_NATURE_AMBIENCE) {
gSaveContext.seqId = NA_BGM_NATURE_SFX_RAIN;
Environment_PlaySceneSequence(globalCtx);
}
}
void Environment_WarpSongLeave(GlobalContext* globalCtx) {
gWeatherMode = 0;
gSaveContext.cutsceneIndex = 0;
gSaveContext.respawnFlag = -3;
globalCtx->nextEntranceIndex = gSaveContext.respawn[RESPAWN_MODE_RETURN].entranceIndex;
globalCtx->transitionTrigger = TRANS_TRIGGER_START;
globalCtx->transitionType = TRANS_TYPE_FADE_WHITE;
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE;
switch (globalCtx->nextEntranceIndex) {
case 0x147:
Flags_SetEventChkInf(EVENTCHKINF_B9);
break;
case 0x0102:
Flags_SetEventChkInf(EVENTCHKINF_B1);
break;
case 0x0123:
Flags_SetEventChkInf(EVENTCHKINF_B8);
break;
case 0x00E4:
Flags_SetEventChkInf(EVENTCHKINF_B6);
break;
case 0x0053:
Flags_SetEventChkInf(EVENTCHKINF_A7);
break;
case 0x00FC:
break;
}
}