diff options
| author | Garrett Cox <garrettjcox@gmail.com> | 2024-12-06 00:56:48 -0600 |
|---|---|---|
| committer | Garrett Cox <garrettjcox@gmail.com> | 2024-12-06 00:56:48 -0600 |
| commit | a108880a8c159bb59530821bb358dfa9cba04ee9 (patch) | |
| tree | 848a4ae527f1282ddfc7213ead68fc06756624a6 /mm/src/code | |
| parent | d1df056e40c0c4cbdb441edc9dd025f7b3883306 (diff) | |
| parent | 1d2a94561fab7d8608c0ac6be615f70f3fb1b769 (diff) | |
Merge branch 'develop' of garrettjoecox.github.com:HarbourMasters/2ship2harkinian into develop-rando
Diffstat (limited to 'mm/src/code')
| -rw-r--r-- | mm/src/code/z_actor.c | 24 | ||||
| -rw-r--r-- | mm/src/code/z_collision_check.c | 16 | ||||
| -rw-r--r-- | mm/src/code/z_eff_blure.c | 1 | ||||
| -rw-r--r-- | mm/src/code/z_fbdemo_circle.c | 10 | ||||
| -rw-r--r-- | mm/src/code/z_kankyo.c | 69 | ||||
| -rw-r--r-- | mm/src/code/z_message.c | 17 | ||||
| -rw-r--r-- | mm/src/code/z_player_lib.c | 4 |
7 files changed, 119 insertions, 22 deletions
diff --git a/mm/src/code/z_actor.c b/mm/src/code/z_actor.c index 7f193158a..a770f2b01 100644 --- a/mm/src/code/z_actor.c +++ b/mm/src/code/z_actor.c @@ -131,6 +131,9 @@ void ActorShadow_Draw(Actor* actor, Lights* lights, PlayState* play, Gfx* dlist, if ((dlist != gCircleShadowDL) || (actor->scale.x != actor->scale.z)) { Matrix_RotateYS(actor->shape.rot.y, MTXMODE_APPLY); + } else { + // Mark non-rotating shadows to ignore the actor mtx prevents interpolation glitches when actor moves + FrameInterpolation_IgnoreActorMtx(); } shadowScale *= actor->shape.shadowScale; @@ -179,6 +182,9 @@ void ActorShadow_DrawFoot(PlayState* play, Light* light, MtxF* arg2, s32 lightNu OPEN_DISPS(play->state.gfxCtx); + // Ignore the players rotation prevents feet shadow from glitching when turning abruptly + FrameInterpolation_IgnoreActorMtx(); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, (u8)(CLAMP_MAX(lightNum * 1.3e-05f, 1.0f) * shadowAlpha)); dir0 = light->l.dir[0]; @@ -5101,6 +5107,10 @@ TexturePtr sElectricSparkTextures[] = { */ void Actor_DrawDamageEffects(PlayState* play, Actor* actor, Vec3f bodyPartsPos[], s16 bodyPartsCount, f32 effectScale, f32 frozenSteamScale, f32 effectAlpha, u8 type) { + if (!GameInteractor_Should(VB_DRAW_DAMAGE_EFFECT, true, actor, &type)) { + return; + } + if (effectAlpha > 0.001f) { s32 twoTexScrollParam; s16 bodyPartIndex; @@ -5113,7 +5123,6 @@ void Actor_DrawDamageEffects(PlayState* play, Actor* actor, Vec3f bodyPartsPos[] Vec3f* bodyPartsPosStart = bodyPartsPos; u32 gameplayFrames = play->gameplayFrames; f32 effectAlphaScaled; - static int effectEpoch = 0; currentMatrix = Matrix_GetCurrent(); @@ -5153,8 +5162,7 @@ void Actor_DrawDamageEffects(PlayState* play, Actor* actor, Vec3f bodyPartsPos[] // Apply and draw ice over each body part of frozen actor for (bodyPartIndex = 0; bodyPartIndex < bodyPartsCount; bodyPartIndex++, bodyPartsPos++) { - // BENTODO is using bodyPartsPos OK here? should actor be used instead? - FrameInterpolation_RecordOpenChild(bodyPartsPos, effectEpoch++); + FrameInterpolation_RecordOpenChild(bodyPartsPos, type); alpha = bodyPartIndex & 3; alpha = effectAlphaScaled - (30.0f * alpha); if (effectAlphaScaled < (30.0f * (bodyPartIndex & 3))) { @@ -5201,7 +5209,7 @@ void Actor_DrawDamageEffects(PlayState* play, Actor* actor, Vec3f bodyPartsPos[] // Apply and draw steam over each body part of frozen actor for (bodyPartIndex = 0; bodyPartIndex < bodyPartsCount; bodyPartIndex++, bodyPartsPos++) { - FrameInterpolation_RecordOpenChild(bodyPartsPos, effectEpoch++); + FrameInterpolation_RecordOpenChild(bodyPartsPos, type); twoTexScrollParam = ((bodyPartIndex * 3) + gameplayFrames); gSPSegment(POLY_XLU_DISP++, 0x08, Gfx_TwoTexScroll(play->state.gfxCtx, 0, twoTexScrollParam * 3, twoTexScrollParam * -12, @@ -5237,7 +5245,7 @@ void Actor_DrawDamageEffects(PlayState* play, Actor* actor, Vec3f bodyPartsPos[] // Apply and draw fire on every body part for (bodyPartIndex = 0; bodyPartIndex < bodyPartsCount; bodyPartIndex++, bodyPartsPos++) { - FrameInterpolation_RecordOpenChild(bodyPartsPos, effectEpoch++); + FrameInterpolation_RecordOpenChild(bodyPartsPos, type); alpha = bodyPartIndex & 3; alpha = effectAlphaScaled - 30.0f * alpha; if (effectAlphaScaled < 30.0f * (bodyPartIndex & 3)) { @@ -5299,7 +5307,7 @@ void Actor_DrawDamageEffects(PlayState* play, Actor* actor, Vec3f bodyPartsPos[] // Apply and draw a light orb over each body part of frozen actor for (bodyPartIndex = 0; bodyPartIndex < bodyPartsCount; bodyPartIndex++, bodyPartsPos++) { - FrameInterpolation_RecordOpenChild(bodyPartsPos, effectEpoch++); + FrameInterpolation_RecordOpenChild(bodyPartsPos, type); Matrix_RotateZF(Rand_CenteredFloat(2 * M_PI), MTXMODE_APPLY); currentMatrix->mf[3][0] = bodyPartsPos->x; currentMatrix->mf[3][1] = bodyPartsPos->y; @@ -5339,7 +5347,7 @@ void Actor_DrawDamageEffects(PlayState* play, Actor* actor, Vec3f bodyPartsPos[] // Every body part draws two electric sparks at random orientations for (bodyPartIndex = 0; bodyPartIndex < bodyPartsCount; bodyPartIndex++, bodyPartsPos++) { - FrameInterpolation_RecordOpenChild(bodyPartsPos, effectEpoch++); + FrameInterpolation_RecordOpenChild(bodyPartsPos, type); // first electric spark Matrix_RotateXFApply(Rand_ZeroFloat(2 * M_PI)); Matrix_RotateZF(Rand_ZeroFloat(2 * M_PI), MTXMODE_APPLY); @@ -5368,7 +5376,7 @@ void Actor_DrawDamageEffects(PlayState* play, Actor* actor, Vec3f bodyPartsPos[] break; } - effectEpoch = 0; + CLOSE_DISPS(play->state.gfxCtx); } } diff --git a/mm/src/code/z_collision_check.c b/mm/src/code/z_collision_check.c index b3a2723af..107d95cc2 100644 --- a/mm/src/code/z_collision_check.c +++ b/mm/src/code/z_collision_check.c @@ -1,5 +1,6 @@ #include "global.h" #include "z64collision_check.h" +#include "2s2h/GameInteractor/GameInteractor.h" typedef s32 (*ColChkResetFunc)(struct PlayState*, Collider*); typedef void (*ColChkBloodFunc)(struct PlayState*, Collider*, Vec3f*); @@ -59,8 +60,16 @@ f32 CollisionCheck_GetDamageAndEffectOnBumper(Collider* at, ColliderInfo* atInfo dmgFlags >>= 1; } - damage *= damageMultipliers[ac->actor->colChkInfo.damageTable->attack[i] & 0xF]; - *effect = (ac->actor->colChkInfo.damageTable->attack[i] >> 4) & 0xF; + // #region 2S2H - Enhancements - Damage Multiplier and Effect + if ((GameInteractor_Should(VB_DAMAGE_MULTIPLIER, true, i, ac->actor->colChkInfo.damageTable, &damage, + damageMultipliers))) { + damage *= damageMultipliers[ac->actor->colChkInfo.damageTable->attack[i] & 0xF]; + } + + if ((GameInteractor_Should(VB_DAMAGE_EFFECT, true, i, ac->actor->colChkInfo.damageTable, effect, ac->actor))) { + *effect = (ac->actor->colChkInfo.damageTable->attack[i] >> 4) & 0xF; + } + // #endregion } return damage; } @@ -1361,7 +1370,8 @@ s32 CollisionCheck_SkipBump(ColliderInfo* info) { * If the AT element has no dmgFlags in common with the AC element, no collision happens. */ s32 CollisionCheck_NoSharedFlags(ColliderInfo* toucher, ColliderInfo* bumper) { - if (!(toucher->toucher.dmgFlags & bumper->bumper.dmgFlags)) { + if (GameInteractor_Should(VB_CHECK_BUMPER_COLLISION, !(toucher->toucher.dmgFlags & bumper->bumper.dmgFlags), + toucher, bumper)) { return 1; } return 0; diff --git a/mm/src/code/z_eff_blure.c b/mm/src/code/z_eff_blure.c index 77fb627f4..e8b865965 100644 --- a/mm/src/code/z_eff_blure.c +++ b/mm/src/code/z_eff_blure.c @@ -649,6 +649,7 @@ void EffectBlure_DrawSmooth(EffectBlure* this2, GraphicsContext* gfxCtx) { interpolationEpoch++; OPEN_DISPS(gfxCtx); + // Force blure effects to never interpolate FrameInterpolation_RecordOpenChild(this, interpolationEpoch); if (this->numElements < 2) { diff --git a/mm/src/code/z_fbdemo_circle.c b/mm/src/code/z_fbdemo_circle.c index 22dac2f59..5dfbbc735 100644 --- a/mm/src/code/z_fbdemo_circle.c +++ b/mm/src/code/z_fbdemo_circle.c @@ -120,11 +120,8 @@ void TransitionCircle_LoadAndSetTexture(Gfx** gfxp, TexturePtr texture, s32 fmt, } // #region 2S2H [Cosmetic] Adjust circle overlay to support widescreen - // The first wide rectangle instruction renders the tile information on the extra space on the left edge - // The second instruction renders the original overlay in the center and has it extend to the right edge - // gSPTextureRectangle(gfx++, 0, 0, xh << 2, yh << 2, G_TX_RENDERTILE, (s32)(s * (1 << 5)), (s32)(t * (1 << 5)), - // dsdx, - // dtdy); + // The first wide rectangle instruction renders the tile information on the extra space off the left edge + // The second instruction renders the original overlay in the center and has it extended to the right edge s32 x = OTRGetRectDimensionFromLeftEdge(0) << 2; if (x < 0) { // Only render if the screen is wider then original @@ -152,6 +149,9 @@ void TransitionCircle_Draw(void* thisx, Gfx** gfxp) { gDPSetCombineLERP(gfx++, 0, 0, 0, PRIMITIVE, 1, TEXEL0, PRIM_LOD_FRAC, PRIMITIVE, 0, 0, 0, PRIMITIVE, 1, TEXEL0, PRIM_LOD_FRAC, PRIMITIVE); } + // 2S2H [Port] We need to set the render mode to XLU_SURF for alpha logic to be used in Fast3D + // If Fast3D changes how it decides alpha in the future, we may be able to remove this line + gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2); TransitionCircle_LoadAndSetTexture(&gfx, this->texture, G_IM_FMT_I, 0, this->masks, this->maskt, this->referenceRadius); gDPPipeSync(gfx++); diff --git a/mm/src/code/z_kankyo.c b/mm/src/code/z_kankyo.c index 86d8abb27..fff939230 100644 --- a/mm/src/code/z_kankyo.c +++ b/mm/src/code/z_kankyo.c @@ -3172,6 +3172,64 @@ void Environment_DrawSkyboxStar(Gfx** gfxp, f32 x, f32 y, s32 width, s32 height) *gfxp = gfx; } +// 2S2H [Enhancement] Renders a star as a quad against the projection matrix by rotating it with the billboard matrix +void Ship_DrawSkyboxStarInterpolated(Gfx** gfxP, PlayState* play, Vec3f pos, u32 width, u32 height, s32 starNum) { + static MtxF origBillboardMtxF; + static Vtx starVtxData[] = { + VTX(-1, -1, 0, 0, 0, 0, 0, 0, 255), + VTX(1, -1, 0, 0, 0, 0, 0, 0, 255), + VTX(-1, 1, 0, 0, 0, 0, 0, 0, 255), + VTX(1, 1, 0, 0, 0, 0, 0, 0, 255), + }; + + Gfx* gfx = *gfxP; + + // One time logic before drawing the first star + if (starNum == 0) { + // play->billboardMtxF is overwitten by the skybox stars draw earlier, + // so we need to derive the MtxF from the original Mtx + Matrix_MtxToMtxF(play->billboardMtx, &origBillboardMtxF); + + gSPLoadGeometryMode(gfx++, G_CULL_BACK); + } + + if (width >= 2) { + // The following math is used to compute new position values for each star such that they are + // each 5500 units from the view eye. This is necessary as some stars are further way than the zFar + // of the loaded view projection, which caused those stars to be clipped away. + // 5500 was choosen as this is roughly the largest distance that the sun is ever from the view eye. + f32 eyeDist = Math3D_Vec3f_DistXYZ(&pos, &play->view.eye); + f32 distRatio = 5500.0f / eyeDist; + + f32 x = play->view.eye.x + (pos.x - play->view.eye.x) * distRatio; + f32 y = play->view.eye.y + (pos.y - play->view.eye.y) * distRatio; + f32 z = play->view.eye.z + (pos.z - play->view.eye.z) * distRatio; + + // This scale mulitplier is set to draw the stars at a matching size as the texture rectangle + // and made to cancel out field of view changes so that the stars always have the same + // apparent size, preventing stars from appearing larger in first person mode or when looking through the + // telescope. + f32 scaleMultiplier = 3.0f / (60.0f / play->view.fovy); + + Matrix_Push(); + + // Set the matrix so the star renders billboarded and scale to "stretch" it so that it matches + // roughly how the texture rectangle would have looked + Matrix_Translate(x, y, z, MTXMODE_NEW); + Matrix_Scale(width * scaleMultiplier, height * scaleMultiplier, 1.0f, MTXMODE_APPLY); + Matrix_ReplaceRotation(&origBillboardMtxF); + + gSPMatrix(gfx++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + gSPVertex(gfx++, starVtxData, ARRAY_COUNT(starVtxData), 0); + gSP2Triangles(gfx++, 0, 1, 2, 0, 1, 3, 2, 0); + + Matrix_Pop(); + } + + *gfxP = gfx; +} + void Environment_DrawSkyboxStarsImpl(PlayState* play, Gfx** gfxP) { static const Vec3s D_801DD880[] = { { 0x0384, 0x2328, 0xD508 }, { 0x09C4, 0x2328, 0xDA1C }, { 0x0E74, 0x22D8, 0xDA1C }, { 0x1450, 0x2468, 0xD8F0 }, @@ -3230,6 +3288,10 @@ void Environment_DrawSkyboxStarsImpl(PlayState* play, Gfx** gfxP) { G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_NPRIMITIVE, G_AC_NONE | G_ZS_PRIM | G_RM_AA_XLU_LINE | G_RM_AA_XLU_LINE2); + // 2S2H [Port] We need to set the render mode to XLU_SURF for alpha logic to be used in Fast3D + // If Fast3D changes how it decides alpha in the future, we may be able to remove this line + gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + randInt = ((u32)gSaveContext.save.saveInfo.playerData.playerName[0] << 0x18) ^ ((u32)gSaveContext.save.saveInfo.playerData.playerName[1] << 0x14) ^ ((u32)gSaveContext.save.saveInfo.playerData.playerName[2] << 0x10) ^ @@ -3301,6 +3363,13 @@ void Environment_DrawSkyboxStarsImpl(PlayState* play, Gfx** gfxP) { imgYPtr = &imgY; viewProjectionMtxF = play->viewProjectionMtxF.mf; + // 2S2H [Enhancement] The stars are originally drawn as texture rectangles which cannot be interpolated, + // so if interpolation is enabled we branch and render the stars through the projection matrix instead. + if (Ship_GetInterpolationFPS() != 20) { + Ship_DrawSkyboxStarInterpolated(&gfx, play, pos, imgWidth, 4, i); + continue; + } + if (imgWidth >= 2) { // w component scale = pos.x * play->viewProjectionMtxF.mf[0][3] + pos.y * play->viewProjectionMtxF.mf[1][3] + diff --git a/mm/src/code/z_message.c b/mm/src/code/z_message.c index cb794d522..6c7756495 100644 --- a/mm/src/code/z_message.c +++ b/mm/src/code/z_message.c @@ -4536,7 +4536,10 @@ void Message_DrawMain(PlayState* play, Gfx** gfxP) { if ((msgCtx->ocarinaAction == OCARINA_ACTION_PROMPT_EVAN_PART1_SECOND_HALF) || (msgCtx->ocarinaAction == OCARINA_ACTION_PROMPT_EVAN_PART2_SECOND_HALF)) { AudioOcarina_StartForSongCheck( - (1 << (OCARINA_ACTION_PROMPT_SONATA + msgCtx->ocarinaAction)) | 0x80000000, 4); + (1 << ((msgCtx->ocarinaAction - OCARINA_ACTION_PROMPT_EVAN_PART1_SECOND_HALF) + + OCARINA_SONG_EVAN_PART1)) | + 0x80000000, + 4); msgCtx->msgMode = MSGMODE_SONG_PROMPT; } else { if ((msgCtx->ocarinaAction >= OCARINA_ACTION_PROMPT_WIND_FISH_HUMAN) && @@ -6029,12 +6032,14 @@ void Message_Update(PlayState* play) { } else if (sLastPlayedSong == OCARINA_SONG_DOUBLE_TIME) { if (interfaceCtx->restrictions.songOfDoubleTime == 0) { if ((CURRENT_DAY != 3) || (gSaveContext.save.isNight == 0)) { - if (gSaveContext.save.isNight) { - Message_StartTextbox(play, D_801D0464[CURRENT_DAY - 1], NULL); - } else { - Message_StartTextbox(play, D_801D045C[CURRENT_DAY - 1], NULL); + if (GameInteractor_Should(VB_DISPLAY_SONG_OF_DOUBLE_TIME_PROMPT, true)) { + if (gSaveContext.save.isNight) { + Message_StartTextbox(play, D_801D0464[CURRENT_DAY - 1], NULL); + } else { + Message_StartTextbox(play, D_801D045C[CURRENT_DAY - 1], NULL); + } + play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_DOUBLE_TIME; } - play->msgCtx.ocarinaMode = OCARINA_MODE_PROCESS_DOUBLE_TIME; } else { Message_StartTextbox(play, 0x1B94, NULL); play->msgCtx.ocarinaMode = OCARINA_MODE_END; diff --git a/mm/src/code/z_player_lib.c b/mm/src/code/z_player_lib.c index 9f624b93d..12c6e86e9 100644 --- a/mm/src/code/z_player_lib.c +++ b/mm/src/code/z_player_lib.c @@ -46,6 +46,7 @@ #include "2s2h/BenPort.h" #include "2s2h/GameInteractor/GameInteractor.h" +#include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h" void PlayerCall_Init(Actor* thisx, PlayState* play); void PlayerCall_Destroy(Actor* thisx, PlayState* play); @@ -3186,6 +3187,9 @@ void Player_DrawBunnyHood(PlayState* play) { OPEN_DISPS(play->state.gfxCtx); + // Ignoring the players actor mtx allows the bunny hood to render interpolated without issues + FrameInterpolation_IgnoreActorMtx(); + gSPSegment(POLY_OPA_DISP++, 0x0B, mtx); Matrix_Push(); |
