Merge branch 'master' into docker-build

This commit is contained in:
David Voswinkel 2023-05-21 17:20:41 +02:00 committed by GitHub
commit 85be509bab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 161 additions and 58 deletions

View file

@ -33,6 +33,7 @@ void cutsceneRunnerCancel(struct CutsceneRunner* runner);
void cutsceneRunnerReset() {
gRunningCutscenes = NULL;
gTriggeredCutscenes = 0;
for (int i = 0; i < MAX_QUEUE_LENGTH; ++i) {
gCutsceneSoundNodes[i].next = (i + 1) < MAX_QUEUE_LENGTH ? &gCutsceneSoundNodes[i + 1] : NULL;
@ -191,7 +192,7 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
&gZeroVec,
gCurrentLevel->locations[step->teleportPlayer.toLocation].roomIndex
);
checkpointSave(&gScene);
sceneQueueCheckpoint(&gScene);
break;
case CutsceneStepTypeLoadLevel:
{
@ -249,7 +250,7 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
);
break;
case CutsceneStepSaveCheckpoint:
checkpointSave(&gScene);
sceneQueueCheckpoint(&gScene);
break;
case CutsceneStepKillPlayer:
playerKill(&gScene.player, step->killPlayer.isWater);

View file

@ -123,7 +123,7 @@ void levelQueueLoad(int index, struct Transform* relativeExitTransform, struct V
gQueuedLevel = gCurrentLevelIndex + 1;
if (gQueuedLevel == LEVEL_COUNT) {
gQueuedLevel = 0;
gQueuedLevel = MAIN_MENU;
}
} else {
gQueuedLevel = index;

View file

@ -264,6 +264,10 @@ static void gameProc(void* arg) {
case (OS_SC_DONE_MSG):
--pendingGFX;
portalSurfaceCheckCleanupQueue();
if (gScene.checkpointState == SceneCheckpointStatePendingRender) {
gScene.checkpointState = SceneCheckpointStateReady;
}
break;
case (OS_SC_PRE_NMI_MSG):
pendingGFX += 2;

View file

@ -21,7 +21,7 @@ void loadGamePopulate(struct LoadGameMenu* loadGame) {
for (int i = 0; i < numberOfSaves; ++i) {
savefileInfo[i].slotIndex = saveSlots[i].saveSlot;
savefileInfo[i].testchamberIndex = saveSlots[i].testChamber;
savefileInfo[i].savefileName = NULL;
savefileInfo[i].savefileName = saveSlots[i].saveSlot == 0 ? "AUTO" : NULL;
savefileInfo[i].screenshot = (u16*)SCREEN_SHOT_SRAM(saveSlots[i].saveSlot);
}

View file

@ -204,6 +204,7 @@ void savefileListRender(struct SavefileListMenu* savefileList, struct RenderStat
continue;
}
gDPPipeSync(renderState->dl++);
menuSetRenderColor(renderState, savefileList->indexOffset + i == savefileList->selectedSave, &gSelectionOrange, &gColorBlack);
renderStateInlineBranch(renderState, slot->border);
@ -229,6 +230,7 @@ void savefileListRender(struct SavefileListMenu* savefileList, struct RenderStat
continue;
}
gDPPipeSync(renderState->dl++);
menuSetRenderColor(renderState, savefileList->indexOffset + i == savefileList->selectedSave, &gSelectionOrange, &gColorWhite);
renderStateInlineBranch(renderState, slot->testChamberText);
@ -276,27 +278,6 @@ void savefileListRender(struct SavefileListMenu* savefileList, struct RenderStat
gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WD, SCREEN_HT);
}
u16 gScreenGrabBuffer[SAVE_SLOT_IMAGE_W * SAVE_SLOT_IMAGE_H];
#define IMAGE_SCALE_FACTOR (int)((SCREEN_WD << 16) / SAVE_SLOT_IMAGE_W)
#define SCALE_TO_SOURCE(value) ((IMAGE_SCALE_FACTOR * (value)) >> 16)
void savefileGrabScreenshot() {
u16* cfb = osViGetCurrentFramebuffer();
u16* dst = gScreenGrabBuffer;
for (int y = 0; y < SAVE_SLOT_IMAGE_H; ++y) {
for (int x = 0; x < SAVE_SLOT_IMAGE_W; ++x) {
int srcX = SCALE_TO_SOURCE(x);
int srcY = SCALE_TO_SOURCE(y);
*dst = cfb[srcX + srcY * SCREEN_WD];
++dst;
}
}
}
int savefileGetSlot(struct SavefileListMenu* savefileList) {
return savefileList->savefileInfo[savefileList->selectedSave].slotIndex;
}

View file

@ -6,8 +6,6 @@
#include "../savefile/savefile.h"
#include "./new_game_menu.h"
extern u16 gScreenGrabBuffer[SAVE_SLOT_IMAGE_W * SAVE_SLOT_IMAGE_H];
struct SavefileInfo {
short slotIndex;
short testchamberIndex;
@ -43,6 +41,4 @@ enum MenuDirection savefileListUpdate(struct SavefileListMenu* savefileList);
void savefileListRender(struct SavefileListMenu* savefileList, struct RenderState* renderState, struct GraphicsTask* task);
int savefileGetSlot(struct SavefileListMenu* savefileList);
void savefileGrabScreenshot();
#endif

View file

@ -5,7 +5,7 @@
#include "collision_scene.h"
#include "../math/mathf.h"
#include "mesh_collider.h"
// 0x807572ac
void collisionObjectInit(struct CollisionObject* object, struct ColliderTypeData *collider, struct RigidBody* body, float mass, int collisionLayers) {
object->collider = collider;
object->body = body;
@ -28,6 +28,10 @@ int collisionObjectIsActive(struct CollisionObject* object) {
return object->body && ((object->body->flags & (RigidBodyIsKinematic | RigidBodyIsSleeping)) == 0);
}
int collisionObjectIsGrabbable(struct CollisionObject* object) {
return object->body && ((object->body->flags & (RigidBodyFlagsGrabbable)) != 0);
}
int collisionObjectShouldGenerateConctacts(struct CollisionObject* object) {
return collisionObjectIsActive(object) || (object->body->flags & RigidBodyIsPlayer) != 0;
}

View file

@ -36,6 +36,7 @@ struct SweptCollisionObject {
};
int collisionObjectIsActive(struct CollisionObject* object);
int collisionObjectIsGrabbable(struct CollisionObject* object);
int collisionObjectShouldGenerateConctacts(struct CollisionObject* object);
void collisionObjectInit(struct CollisionObject* object, struct ColliderTypeData *collider, struct RigidBody* body, float mass, int collisionLayers);

View file

@ -210,6 +210,9 @@ void playerHandleCollision(struct Player* player) {
// objects being grabbed by the player shouldn't push the player
continue;
}
float prevY = player->body.transform.position.y;
float prevVelY = player->body.velocity.y;
if (offset != 0.0f) {
vector3AddScaled(
@ -220,13 +223,17 @@ void playerHandleCollision(struct Player* player) {
);
}
float relativeVelocity = vector3Dot(&contact->normal, &player->body.velocity);
if ((contact->shapeA == &player->collisionObject) == (relativeVelocity > 0.0f)) {
vector3ProjectPlane(&player->body.velocity, &contact->normal, &player->body.velocity);
}
if (collisionObjectIsGrabbable(contact->shapeA) || collisionObjectIsGrabbable(contact->shapeB)) {
player->body.transform.position.y = MAX(player->body.transform.position.y, prevY);
player->body.velocity.y = MAX(player->body.velocity.y, prevVelY);
}
if (((isColliderForBall(contact->shapeA) || isColliderForBall(contact->shapeB)) && !playerIsDead(player))) {
playerKill(player, 0);
soundPlayerPlay(soundsBallKill, 1.0f, 1.0f, NULL, NULL);
@ -523,7 +530,7 @@ struct SKAnimationClip* playerDetermineNextClip(struct Player* player, float* bl
}
}
void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
void playerUpdate(struct Player* player) {
struct Vector3 forward;
struct Vector3 right;
@ -781,17 +788,11 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
player->pitchVelocity = 0.0f;
}
cameraTransform->rotation = player->lookTransform.rotation;
cameraTransform->position = player->lookTransform.position;
playerUpdateGrabbedObject(player);
playerUpdateGunObject(player);
collisionObjectUpdateBB(&player->collisionObject);
if (player->flags & PlayerIsDead) {
cameraTransform->position.y += DEAD_OFFSET;
}
player->body.currentRoom = worldCheckDoorwayCrossings(&gCurrentLevel->world, &player->lookTransform.position, player->body.currentRoom, doorwayMask);
dynamicSceneSetRoomFlags(player->dynamicId, ROOM_FLAG_FROM_INDEX(player->body.currentRoom));
@ -828,3 +829,12 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) {
}
}
void playerApplyCameraTransform(struct Player* player, struct Transform* cameraTransform) {
cameraTransform->rotation = player->lookTransform.rotation;
cameraTransform->position = player->lookTransform.position;
if (player->flags & PlayerIsDead) {
cameraTransform->position.y += DEAD_OFFSET;
}
}

View file

@ -54,7 +54,8 @@ struct Player {
};
void playerInit(struct Player* player, struct Location* startLocation, struct Vector3* velocity, struct CollisionObject* portalGunObject);
void playerUpdate(struct Player* player, struct Transform* cameraTransform);
void playerUpdate(struct Player* player);
void playerApplyCameraTransform(struct Player* player, struct Transform* cameraTransform);
void playerGetMoveBasis(struct Transform* transform, struct Vector3* forward, struct Vector3* right);

View file

@ -5,9 +5,10 @@
#include "../levels/levels.h"
#include "./scene_serialize.h"
#include "serializer.h"
#include "./savefile.h"
char gHasCheckpoint = 0;
char gCheckpoint[MAX_CHECKPOINT_SIZE];
char __attribute__((aligned(8))) gCheckpoint[MAX_CHECKPOINT_SIZE];
void ckeckpointSerialize(struct Serializer* serializer, SerializeAction action, void* data) {
struct Scene* scene = data;
@ -48,8 +49,10 @@ int checkpointExists() {
}
void checkpointSave(struct Scene* scene) {
savefileGrabScreenshot();
gHasCheckpoint = checkpointSaveInto(scene, gCheckpoint);
gHasCheckpoint = 1;
// slot 0 is the autosave slot
savefileSaveGame(gCheckpoint, gScreenGrabBuffer, gCurrentLevelIndex, gCurrentTestSubject, 0);
}
void checkpointLoadLast(struct Scene* scene) {

View file

@ -5,7 +5,7 @@
#include "../controls/controller_actions.h"
struct SaveData gSaveData;
struct SaveData __attribute__((aligned(8))) gSaveData;
int gCurrentTestSubject = -1;
#ifdef DEBUG
@ -210,7 +210,7 @@ int savefileListSaves(struct SaveSlotInfo* slots, int includeAuto) {
continue;
}
if (gSaveData.saveSlotMetadata[i].testSubjectNumber == TEST_SUBJECT_AUTOSAVE && !includeAuto) {
if (i == 0 && !includeAuto) {
continue;
}
@ -303,4 +303,26 @@ void savefileLoadScreenshot(u16* target, u16* location) {
} else {
memCopy(target, location, THUMBANIL_IMAGE_SIZE);
}
}
u16 gScreenGrabBuffer[SAVE_SLOT_IMAGE_W * SAVE_SLOT_IMAGE_H];
#define IMAGE_SCALE_FACTOR (int)((SCREEN_WD << 16) / SAVE_SLOT_IMAGE_W)
#define SCALE_TO_SOURCE(value) ((IMAGE_SCALE_FACTOR * (value)) >> 16)
void savefileGrabScreenshot() {
u16* cfb = osViGetCurrentFramebuffer();
u16* dst = gScreenGrabBuffer;
for (int y = 0; y < SAVE_SLOT_IMAGE_H; ++y) {
for (int x = 0; x < SAVE_SLOT_IMAGE_W; ++x) {
int srcX = SCALE_TO_SOURCE(x);
int srcY = SCALE_TO_SOURCE(y);
*dst = cfb[srcX + srcY * SCREEN_WD];
++dst;
}
}
}

View file

@ -20,7 +20,7 @@
#define SCREEN_SHOT_SRAM(slotIndex) (((slotIndex) + 1) * SAVE_SLOT_SIZE + MAX_CHECKPOINT_SIZE + SRAM_START_ADDR)
#define SAVEFILE_HEADER 0xDEA1
#define SAVEFILE_HEADER 0xDEAD
// first save slot is always reserved for auto save
#define MAX_SAVE_SLOTS ((int)(SRAM_SIZE / SAVE_SLOT_SIZE) - 1)
@ -50,7 +50,6 @@ struct AudioSettingsSaveState {
};
#define NO_TEST_CHAMBER 0xFF
#define TEST_SUBJECT_AUTOSAVE 0xFF
#define TEST_SUBJECT_MAX 99
struct SaveSlotMetadata {
@ -90,4 +89,8 @@ int savefileFirstFreeSlot();
void savefileLoadGame(int slot, Checkpoint checkpoint, int* testChamberIndex, int* subjectNumber);
void savefileLoadScreenshot(u16* target, u16* location);
extern u16 gScreenGrabBuffer[SAVE_SLOT_IMAGE_W * SAVE_SLOT_IMAGE_H];
void savefileGrabScreenshot();
#endif

View file

@ -277,18 +277,23 @@ void boxDropperDeserialize(struct Serializer* serializer, struct Scene* scene) {
void elevatorSerializeRW(struct Serializer* serializer, SerializeAction action, struct Scene* scene) {
for (int i = 0; i < scene->elevatorCount; ++i) {
action(serializer, &scene->elevators[i].flags, sizeof(short));
action(serializer, &scene->elevators[i].timer, sizeof(float));
}
}
void pedestalSerialize(struct Serializer* serializer, SerializeAction action, struct Scene* scene) {
for (int i = 0; i < scene->pedestalCount; ++i) {
action(serializer, &scene->pedestals[i].flags, sizeof(short));
action(serializer, &scene->pedestals[i].pointAt, sizeof(struct Vector3));
action(serializer, &scene->pedestals[i].currentRotation, sizeof(struct Vector2));
}
}
void pedestalDeserialize(struct Serializer* serializer, struct Scene* scene) {
for (int i = 0; i < scene->pedestalCount; ++i) {
serializeRead(serializer, &scene->pedestals[i].flags, sizeof(short));
serializeRead(serializer, &scene->pedestals[i].pointAt, sizeof(struct Vector3));
serializeRead(serializer, &scene->pedestals[i].currentRotation, sizeof(struct Vector2));
if (scene->pedestals[i].flags & PedestalFlagsDown) {
pedestalSetDown(&scene->pedestals[i]);
@ -364,7 +369,7 @@ void catcherDeserialize(struct Serializer* serializer, struct Scene* scene) {
}
struct BallCatcher* catcher = &scene->ballCatchers[i];
catcher->caughtBall = &scene->ballLaunchers[caughtIndex].currentBall;
ballCatcherHandBall(catcher, &scene->ballLaunchers[caughtIndex].currentBall);
}
}
@ -423,16 +428,20 @@ void sceneAnimatorDeserialize(struct Serializer* serializer, struct Scene* scene
}
}
#define WRITE_ALIGN_CHECK {action(serializer, &currentAlign, 1); ++currentAlign;}
#define INCLUDE_SAVEFILE_ALIGH_CHECKS 0
#ifdef PORTAL64_WITH_DEBUGGER
#if INCLUDE_SAVEFILE_ALIGH_CHECKS
#define WRITE_ALIGN_CHECK {action(serializer, &currentAlign, 1); ++currentAlign;}
#define READ_ALIGN_CHECK {serializeRead(serializer, &currentAlign, 1); if (currentAlign != expectedAlign) gdbBreak(); ++expectedAlign;}
#else
#define READ_ALIGN_CHECK {serializeRead(serializer, &currentAlign, 1); if (currentAlign != expectedAlign) return; ++expectedAlign;}
#define WRITE_ALIGN_CHECK
#define READ_ALIGN_CHECK
#endif
void sceneSerialize(struct Serializer* serializer, SerializeAction action, struct Scene* scene) {
#if INCLUDE_SAVEFILE_ALIGH_CHECKS
char currentAlign = 0;
#endif
playerSerialize(serializer, action, &scene->player);
WRITE_ALIGN_CHECK;
sceneSerializePortals(serializer, action, scene);
@ -458,8 +467,10 @@ void sceneSerialize(struct Serializer* serializer, SerializeAction action, struc
}
void sceneDeserialize(struct Serializer* serializer, struct Scene* scene) {
#if INCLUDE_SAVEFILE_ALIGH_CHECKS
char currentAlign = 0;
char expectedAlign = 0;
#endif
playerDeserialize(serializer, &scene->player);
READ_ALIGN_CHECK;
sceneDeserializePortals(serializer, scene);

View file

@ -84,6 +84,8 @@ void ballBurnRender(void* data, struct DynamicRenderDataList* renderList, struct
}
void ballInitInactive(struct Ball* ball) {
collisionObjectInit(&ball->collisionObject, &gBallCollider, &ball->rigidBody, 1.0f, 0);
ball->targetSpeed = 0.0f;
ball->flags = 0;
ball->soundLoopId = SOUND_ID_NONE;

View file

@ -87,7 +87,7 @@ void ballCatcherCheckBalls(struct BallCatcher* catcher, struct BallLauncher* bal
for (int i = 0; i < ballLauncherCount; ++i) {
struct BallLauncher* launcher = &ballLaunchers[i];
if (!ballIsActive(&launcher->currentBall)) {
if (!ballIsActive(&launcher->currentBall) || ballIsCaught(&launcher->currentBall)) {
continue;
}
@ -135,4 +135,11 @@ void ballCatcherUpdate(struct BallCatcher* catcher, struct BallLauncher* ballLau
} else {
ballCatcherCheckBalls(catcher, ballLaunchers, ballLauncherCount);
}
}
void ballCatcherHandBall(struct BallCatcher* catcher, struct Ball* caughtBall) {
catcher->caughtBall = caughtBall;
struct Vector3 targetPosition;
transformPoint(&catcher->rigidBody.transform, &gLocalCatcherLocation, &targetPosition);
catcher->caughtBall->rigidBody.transform.position = targetPosition;
}

View file

@ -25,4 +25,6 @@ struct BallCatcher {
void ballCatcherInit(struct BallCatcher* catcher, struct BallCatcherDefinition* definition);
void ballCatcherUpdate(struct BallCatcher* catcher, struct BallLauncher* ballLaunchers, int ballLauncherCount);
void ballCatcherHandBall(struct BallCatcher* catcher, struct Ball* caughtBall);
#endif

View file

@ -41,6 +41,7 @@ struct DoorTypeDefinition gDoorTypeDefinitions[] = {
DOOR_01_INDEX,
-1,
1.0f,
{0.0f, 0.0f, 0.0f, 1.0f},
},
[DoorType02] = {
&props_door_02_armature,
@ -51,6 +52,7 @@ struct DoorTypeDefinition gDoorTypeDefinitions[] = {
DOOR_02_INDEX,
PROPS_DOOR_02_DOOR_BONE,
3.0f,
{0.707106781f, 0.0f, 0.0f, 0.707106781f},
},
};
@ -93,7 +95,7 @@ void doorInit(struct Door* door, struct DoorDefinition* doorDefinition, struct W
door->rigidBody.transform.position = doorDefinition->location;
door->rigidBody.transform.position.y += 1.0f;
door->rigidBody.transform.rotation = doorDefinition->rotation;
quatMultiply(&doorDefinition->rotation, &typeDefinition->relativeRotation, &door->rigidBody.transform.rotation);
door->rigidBody.transform.scale = gOneVec;
collisionObjectUpdateBB(&door->collisionObject);
@ -151,9 +153,13 @@ void doorUpdate(struct Door* door) {
if (typeDefinition->colliderBoneIndex == -1) {
door->collisionObject.collisionLayers = isDoorwayOpen ? 0 : (COLLISION_LAYERS_TANGIBLE | COLLISION_LAYERS_STATIC);
} else {
struct Vector3 finalPos;
skCalculateBonePosition(&door->armature, typeDefinition->colliderBoneIndex, &gZeroVec, &finalPos);
door->rigidBody.transform.position.y =
door->doorDefinition->location.y +
door->armature.pose[typeDefinition->colliderBoneIndex].position.y * (1.0f / SCENE_SCALE);
1.0f +
finalPos.z * (1.0f / SCENE_SCALE);
}
}

View file

@ -21,6 +21,7 @@ struct DoorTypeDefinition {
short materialIndex;
short colliderBoneIndex;
float closeSpeed;
struct Quaternion relativeRotation;
};
struct Door {

View file

@ -8,6 +8,8 @@
#include "../audio/soundplayer.h"
#include "../audio/clips.h"
#include "../savefile/checkpoint.h"
#include "../../build/assets/models/props/round_elevator_collision.h"
#include "../../build/assets/models/props/round_elevator_interior.h"
#include "../../build/assets/models/props/round_elevator.h"
@ -153,8 +155,16 @@ int elevatorUpdate(struct Elevator* elevator, struct Player* player) {
}
if (shouldLock) {
int shouldSaveCheckpoint = (elevator->flags & (ElevatorFlagsIsLocked | ElevatorFlagsIsExit)) == ElevatorFlagsIsExit;
elevator->flags |= ElevatorFlagsIsLocked;
if (shouldSaveCheckpoint) {
// save the checkpoint after flag ElevatorFlagsIsLocked is set
// so loading this checkpoint doesn't immediately create another
// save checkpoint
sceneQueueCheckpoint(&gScene);
}
}
if ((elevator->flags & ElevatorFlagsIsLocked) != 0) {

View file

@ -80,8 +80,9 @@ void sceneInit(struct Scene* scene) {
gameMenuInit(&gGameMenu, gPauseMenuOptions, sizeof(gPauseMenuOptions) / sizeof(*gPauseMenuOptions), 1);
if (!checkpointExists()) {
checkpointSave(scene);
scene->checkpointState = SceneCheckpointStatePendingRender;
} else {
scene->checkpointState = SceneCheckpointStateSaved;
checkpointLoadLast(scene);
}
@ -217,6 +218,7 @@ void sceneInitNoPauseMenu(struct Scene* scene) {
scene->looked_wall_portalable_0=0;
scene->looked_wall_portalable_1=0;
scene->continuouslyAttemptingPortalOpen=0;
scene->checkpointState = SceneCheckpointStateSaved;
scene->freeCameraOffset = gZeroVec;
@ -246,6 +248,8 @@ void sceneRenderPerformanceMetrics(struct Scene* scene, struct RenderState* rend
LookAt gLookAt = gdSPDefLookAt(127, 0, 0, 0, 127, 0);
void sceneRender(struct Scene* scene, struct RenderState* renderState, struct GraphicsTask* task) {
playerApplyCameraTransform(&scene->player, &scene->camera.transform);
gSPSetLights1(renderState->dl++, gSceneLights);
LookAt* lookAt = renderStateRequestLookAt(renderState);
@ -476,18 +480,23 @@ void sceneUpdateAnimatedObjects(struct Scene* scene) {
}
void sceneUpdate(struct Scene* scene) {
if (scene->checkpointState == SceneCheckpointStateReady) {
checkpointSave(scene);
scene->checkpointState = SceneCheckpointStateSaved;
}
OSTime frameStart = osGetTime();
scene->lastFrameTime = frameStart - scene->lastFrameStart;
if (gGameMenu.state != GameMenuStateResumeGame) {
gameMenuUpdate(&gGameMenu);
if (controllerActionGet(ControllerActionPause) ||
(gGameMenu.state == GameMenuStateLanding && controllerGetButtonDown(0, B_BUTTON))) {
gGameMenu.state = GameMenuStateResumeGame;
savefileSave();
}
gameMenuUpdate(&gGameMenu);
if (gGameMenu.state == GameMenuStateResumeGame) {
soundPlayerResume();
}
@ -508,7 +517,7 @@ void sceneUpdate(struct Scene* scene) {
signalsReset();
portalGunUpdate(&scene->portalGun, &scene->player);
playerUpdate(&scene->player, &scene->camera.transform);
playerUpdate(&scene->player);
sceneUpdateListeners(scene);
sceneCheckPortals(scene);
@ -591,7 +600,7 @@ void sceneUpdate(struct Scene* scene) {
&gZeroVec,
scene->elevators[teleportTo].roomIndex
);
checkpointSave(&gScene);
sceneQueueCheckpoint(&gScene);
sceneClosePortal(&gScene, 0);
sceneClosePortal(&gScene, 1);
}
@ -662,6 +671,10 @@ void sceneUpdate(struct Scene* scene) {
}
}
void sceneQueueCheckpoint(struct Scene* scene) {
scene->checkpointState = SceneCheckpointStateReady;
}
int sceneOpenPortal(struct Scene* scene, struct Transform* at, int transformIndex, int portalIndex, struct PortalSurfaceMappingRange surfaceMapping, struct CollisionObject* collisionObject, int roomIndex, int fromPlayer, int just_checking) {
struct Transform finalAt;

View file

@ -29,6 +29,12 @@ struct SavedPortal {
int roomIndex;
};
enum SceneCheckpointState {
SceneCheckpointStateSaved,
SceneCheckpointStatePendingRender,
SceneCheckpointStateReady,
};
struct Scene {
struct Camera camera;
struct Player player;
@ -63,10 +69,12 @@ struct Scene {
u8 switchCount;
u8 ballLancherCount;
u8 ballCatcherCount;
u8 last_portal_indx_shot;
u8 looked_wall_portalable_0;
u8 looked_wall_portalable_1;
u8 continuouslyAttemptingPortalOpen;
u8 checkpointState;
};
extern struct Scene gScene;
@ -77,6 +85,7 @@ void sceneInit(struct Scene* scene);
void sceneInitNoPauseMenu(struct Scene* scene);
void sceneRender(struct Scene* scene, struct RenderState* renderState, struct GraphicsTask* task);
void sceneUpdate(struct Scene* scene);
void sceneQueueCheckpoint(struct Scene* scene);
int sceneFirePortal(struct Scene* scene, struct Ray* ray, struct Vector3* playerUp, int portalIndex, int roomIndex, int fromPlayer, int just_checking);
void sceneClosePortal(struct Scene* scene, int portalIndex);

View file

@ -93,4 +93,19 @@ void skCalculateBonePosition(struct SKArmature* object, unsigned short boneIndex
transformPoint(&object->pose[boneIndex], out, out);
boneIndex = object->boneParentIndex[boneIndex];
}
}
void skCalculateBoneRotation(struct SKArmature* object, unsigned short boneIndex, struct Quaternion* out) {
if (!object->boneParentIndex) {
return;
}
quatIdent(out);
while (boneIndex < object->numberOfBones) {
struct Quaternion next;
quatMultiply(&object->pose[boneIndex].rotation, out, &next);
*out = next;
boneIndex = object->boneParentIndex[boneIndex];
}
}

View file

@ -29,5 +29,6 @@ void skRenderObject(struct SKArmature* object, Gfx** attachements, struct Render
void skCalculateTransforms(struct SKArmature* object, Mtx* into);
void skCleanupObject(struct SKArmature* object);
void skCalculateBonePosition(struct SKArmature* object, unsigned short boneIndex, struct Vector3* bonePosition, struct Vector3* out);
void skCalculateBoneRotation(struct SKArmature* object, unsigned short boneIndex, struct Quaternion* out);
#endif