From 7a5267195d9ea0a9dbcbf0780ff1f87e31c20a22 Mon Sep 17 00:00:00 2001 From: James Lambert Date: Sat, 21 Oct 2023 21:35:50 -0600 Subject: [PATCH] animate ball from pedestal add camera shake and rumble when auto portals open --- README.md | 3 +- assets/materials/static.skm.yaml | 7 ++-- .../test_chamber_01/test_chamber_01.yaml | 8 ++-- .../test_chamber_07/test_chamber_07.yaml | 10 ++--- src/levels/cutscene_runner.c | 41 +++++++++++++++---- src/levels/level_definition.h | 3 +- src/player/player.c | 23 +++++------ src/scene/portal_gun.c | 24 ++++++++++- src/scene/portal_gun.h | 3 +- src/scene/scene.c | 4 +- tools/level_scripts/trigger.lua | 1 + 11 files changed, 88 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index bbba36b..30fd914 100644 --- a/README.md +++ b/README.md @@ -210,12 +210,13 @@ That will generate the rom at `/build/portal64.z64`
## Current New Feature TODO List -- [ ] valve intro +- [ ] figure out why portals somtimes are in front of window - [ ] optimize static culling - [ ] jump animation - [ ] crashed when dying in test chamber 05 when hit by pellet in mid air while touching a portal - [ ] rumble pak support - [ ] pausing while glados is speaking can end her speech early +- [x] valve intro - [x] polish up subtitles - [x] more sound settings - [x] add desk chairs and monitors diff --git a/assets/materials/static.skm.yaml b/assets/materials/static.skm.yaml index 1bfc8af..8eb29d5 100644 --- a/assets/materials/static.skm.yaml +++ b/assets/materials/static.skm.yaml @@ -1180,10 +1180,11 @@ materials: gDPSetRenderMode: flags: + - Z_CMP - IM_RD - CVG_DST_FULL - FORCE_BL - - ZMODE_OPA + - ZMODE_XLU blend: - G_BL_CLR_IN - G_BL_A_IN @@ -1194,8 +1195,8 @@ materials: color: ["1", "PRIMITIVE", "TEXEL0", "PRIMITIVE"] alpha: ["TEXEL0", "PRIMITIVE", "SHADE", "0"] gSPGeometryMode: - clear: [G_CULL_BACK, G_CULL_FRONT, G_ZBUFFER] - set: [G_FOG] + clear: [G_CULL_BACK, G_CULL_FRONT] + set: [G_FOG, G_ZBUFFER] lab_monitor_screen_text: gDPSetTile: diff --git a/assets/test_chambers/test_chamber_01/test_chamber_01.yaml b/assets/test_chambers/test_chamber_01/test_chamber_01.yaml index 445347a..6f66a75 100644 --- a/assets/test_chambers/test_chamber_01/test_chamber_01.yaml +++ b/assets/test_chambers/test_chamber_01/test_chamber_01.yaml @@ -32,19 +32,19 @@ cutscenes: portal_loop: - open_portal portal_exit 0 - label loop_start - - open_portal portal_0 1 + - open_portal portal_0 1 pedestal - delay 3 - point_pedestal portal_1 - delay 4 - - open_portal portal_1 1 + - open_portal portal_1 1 pedestal - delay 3 2 - point_pedestal portal_2 - delay 4 2 - - open_portal portal_2 1 + - open_portal portal_2 1 pedestal - delay 3 3 - point_pedestal portal_3 - delay 4 3 - - open_portal portal_3 1 + - open_portal portal_3 1 pedestal - delay 3 4 - point_pedestal portal_0 - delay 4 4 diff --git a/assets/test_chambers/test_chamber_07/test_chamber_07.yaml b/assets/test_chambers/test_chamber_07/test_chamber_07.yaml index 5fcfb2a..af2864c 100644 --- a/assets/test_chambers/test_chamber_07/test_chamber_07.yaml +++ b/assets/test_chambers/test_chamber_07/test_chamber_07.yaml @@ -38,15 +38,15 @@ cutscenes: - q_sound 07_PART2_SUCCESS_1 CH_GLADOS PORTAL_07_PART2_SUCCESS_1 portal_loop: - label loop_start - - open_portal portal_0 0 - - delay 3.001 + - open_portal portal_0 0 pedestal + - delay 3 - point_pedestal portal_1 - - delay 4.001 - - open_portal portal_1 0 + - delay 4 + - open_portal portal_1 0 pedestal - delay 3 2 - point_pedestal portal_2 - delay 4 2 - - open_portal portal_2 0 + - open_portal portal_2 0 pedestal - delay 3 3 - point_pedestal portal_3 - delay 4 3 diff --git a/src/levels/cutscene_runner.c b/src/levels/cutscene_runner.c index 3336201..f3aeb69 100644 --- a/src/levels/cutscene_runner.c +++ b/src/levels/cutscene_runner.c @@ -7,9 +7,22 @@ #include "../util/memory.h" #include "../savefile/checkpoint.h" #include "../locales/locales.h" +#include "../controls/rumble_pak.h" #include +unsigned char gPortalOpenRumbleData[] = { + 0xFF, 0xE9, 0x99, +}; + +struct RumblePakWave gPortalOpenRumbleWave = { + .samples = gPortalOpenRumbleData, + .sampleCount = 12, + .samplesPerTick = 1 << 5, +}; + +#define RUMBLE_PLAYER_DISTANCE 8.0f + struct CutsceneRunner* gRunningCutscenes; struct CutsceneRunner* gUnusedRunners; u64 gTriggeredCutscenes; @@ -154,14 +167,26 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) { case CutsceneStepTypeOpenPortal: { struct Location* location = &gCurrentLevel->locations[step->openPortal.locationIndex]; - struct Ray firingRay; - struct Vector3 transformUp; - firingRay.origin = location->transform.position; - quatMultVector(&location->transform.rotation, &gForward, &firingRay.dir); - quatMultVector(&location->transform.rotation, &gRight, &transformUp); - vector3Negate(&transformUp, &transformUp); - vector3AddScaled(&location->transform.position, &firingRay.dir, -0.1f, &firingRay.origin); - sceneFirePortal(&gScene, &firingRay, &transformUp, step->openPortal.portalIndex, location->roomIndex, 0, 0); + + if (step->openPortal.fromPedestal && gCurrentLevel->pedestalCount) { + struct Vector3 fireFrom = gScene.pedestals[0].transform.position; + fireFrom.y += 0.75f; + portalGunFireWorld(&gScene.portalGun, step->openPortal.portalIndex, &fireFrom, &location->transform.position, gScene.pedestals[0].roomIndex); + } else { + struct Ray firingRay; + struct Vector3 transformUp; + firingRay.origin = location->transform.position; + quatMultVector(&location->transform.rotation, &gForward, &firingRay.dir); + quatMultVector(&location->transform.rotation, &gRight, &transformUp); + vector3Negate(&transformUp, &transformUp); + vector3AddScaled(&location->transform.position, &firingRay.dir, -0.1f, &firingRay.origin); + sceneFirePortal(&gScene, &firingRay, &transformUp, step->openPortal.portalIndex, location->roomIndex, 0, 0); + + if (vector3DistSqrd(&location->transform.position, &gScene.player.lookTransform.position) < RUMBLE_PLAYER_DISTANCE * RUMBLE_PLAYER_DISTANCE) { + gScene.player.shakeTimer = 0.5f; + rumblePakClipPlay(&gPortalOpenRumbleWave); + } + } break; } case CutsceneStepTypeClosePortal: diff --git a/src/levels/level_definition.h b/src/levels/level_definition.h index 0aec7da..a0dc549 100644 --- a/src/levels/level_definition.h +++ b/src/levels/level_definition.h @@ -90,7 +90,8 @@ struct CutsceneStep { } waitForChannel; struct { u16 locationIndex; - u16 portalIndex; + u8 portalIndex; + u8 fromPedestal; } openPortal; struct { u16 portalIndex; diff --git a/src/player/player.c b/src/player/player.c index fd5507f..29ddcf7 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -262,18 +262,17 @@ void playerShakeUpdate(struct Player* player) { if (player->shakeTimer > 0.0f){ player->shakeTimer -= FIXED_DELTA_TIME; - float max = SHAKE_DISTANCE; - float min = -SHAKE_DISTANCE; - float x; - x = ((float)rand()/(float)(RAND_MAX)); - x = min + x * ( max - min ); - player->lookTransform.position.x += x; - x = ((float)rand()/(float)(RAND_MAX)); - x = min + x * ( max - min ); - player->lookTransform.position.y += x; - x = ((float)rand()/(float)(RAND_MAX)); - x = min + x * ( max - min ); - player->lookTransform.position.z += x; + float magnitude = 1.0f; + + if (player->shakeTimer < 1.0f) { + magnitude = player->shakeTimer; + } + + float max = SHAKE_DISTANCE * magnitude; + float min = -SHAKE_DISTANCE * magnitude; + player->lookTransform.position.x += randomInRangef(min, max); + player->lookTransform.position.y += randomInRangef(min, max); + player->lookTransform.position.z += randomInRangef(min, max); if (player->shakeTimer < 0.0f){ player->shakeTimer = 0.0f; diff --git a/src/scene/portal_gun.c b/src/scene/portal_gun.c index 6cdc87f..10a6658 100644 --- a/src/scene/portal_gun.c +++ b/src/scene/portal_gun.c @@ -114,7 +114,7 @@ void portalBallRender(struct PortalGunProjectile* projectile, struct RenderState gSPPopMatrix(renderState->dl++, G_MTX_MODELVIEW); } -void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera) { +void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera, int portalGunVisible) { struct MaterialState materialState; materialStateInit(&materialState, DEFAULT_INDEX); @@ -130,6 +130,10 @@ void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* render portalBallRender(projectile, renderState, &materialState, &fromCamera->transform, i); } + if (!portalGunVisible) { + return; + } + portalGun->rigidBody.transform.scale = gOneVec; Mtx* matrix = renderStateRequestMatrices(renderState, 1); @@ -267,6 +271,24 @@ void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray portalTrailPlay(&projectile->trail, &fireFrom, &hit.at); } + + +void portalGunFireWorld(struct PortalGun* portalGun, int portalIndex, struct Vector3* from, struct Vector3* to, int roomIndex) { + struct PortalGunProjectile* projectile = &portalGun->projectiles[portalIndex]; + vector3Sub(to, from, &projectile->positionDirection.dir); + vector3Normalize(&projectile->positionDirection.dir, &projectile->positionDirection.dir); + projectile->positionDirection.origin = *from; + projectile->roomIndex = roomIndex; + projectile->playerUp = gUp; + + projectile->distance = 0.0f; + projectile->maxDistance = sqrtf(vector3DistSqrd(from, to)); + + projectile->effectOffset = gZeroVec; + + portalTrailPlay(&projectile->trail, from, to); +} + int portalGunIsFiring(struct PortalGun* portalGun){ if (portalGun->shootTotalAnimationTimer > 0.0f){ return 1; diff --git a/src/scene/portal_gun.h b/src/scene/portal_gun.h index 05789f3..be7ea6e 100644 --- a/src/scene/portal_gun.h +++ b/src/scene/portal_gun.h @@ -39,9 +39,10 @@ struct PortalGun { void portalGunInit(struct PortalGun* portalGun, struct Transform* at); // void portalGunDummyRender(void* data, struct DynamicRenderDataList* renderList, struct RenderState* renderState); void portalGunUpdate(struct PortalGun* portalGun, struct Player* player); -void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera); +void portalGunRenderReal(struct PortalGun* portalGun, struct RenderState* renderState, struct Camera* fromCamera, int portalGunVisible); void portalGunFire(struct PortalGun* portalGun, int portalIndex, struct Ray* ray, struct Vector3* playerUp, int roomIndex); +void portalGunFireWorld(struct PortalGun* portalGun, int portalIndex, struct Vector3* from, struct Vector3* to, int roomIndex); int portalGunIsFiring(struct PortalGun* portalGun); #endif \ No newline at end of file diff --git a/src/scene/scene.c b/src/scene/scene.c index 019e16e..ea45077 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -306,9 +306,7 @@ void sceneRender(struct Scene* scene, struct RenderState* renderState, struct Gr // contactSolverDebugDraw(&gContactSolver, renderState); - if (scene->portalGun.portalGunVisible){ - portalGunRenderReal(&scene->portalGun, renderState, &scene->camera); - } + portalGunRenderReal(&scene->portalGun, renderState, &scene->camera, scene->portalGun.portalGunVisible); gDPPipeSync(renderState->dl++); gDPSetRenderMode(renderState->dl++, G_RM_OPA_SURF, G_RM_OPA_SURF2); diff --git a/tools/level_scripts/trigger.lua b/tools/level_scripts/trigger.lua index 4820406..82e2e46 100644 --- a/tools/level_scripts/trigger.lua +++ b/tools/level_scripts/trigger.lua @@ -120,6 +120,7 @@ local function generate_cutscene_step(cutscene_name, step, step_index, label_loc result.openPortal = { find_location_index(step.args[1]), step.args[2] == "1" and 1 or 0, + step.args[3] == "pedestal" and 1 or 0 } elseif step.command == "close_portal" and #step.args >= 1 then result.type = sk_definition_writer.raw('CutsceneStepTypeClosePortal')