Merge branch 'master' into docker-build
This commit is contained in:
commit
85be509bab
Binary file not shown.
Binary file not shown.
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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, ¤tAlign, 1); ++currentAlign;}
|
||||
#define INCLUDE_SAVEFILE_ALIGH_CHECKS 0
|
||||
|
||||
#ifdef PORTAL64_WITH_DEBUGGER
|
||||
#if INCLUDE_SAVEFILE_ALIGH_CHECKS
|
||||
#define WRITE_ALIGN_CHECK {action(serializer, ¤tAlign, 1); ++currentAlign;}
|
||||
#define READ_ALIGN_CHECK {serializeRead(serializer, ¤tAlign, 1); if (currentAlign != expectedAlign) gdbBreak(); ++expectedAlign;}
|
||||
#else
|
||||
#define READ_ALIGN_CHECK {serializeRead(serializer, ¤tAlign, 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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ struct DoorTypeDefinition {
|
|||
short materialIndex;
|
||||
short colliderBoneIndex;
|
||||
float closeSpeed;
|
||||
struct Quaternion relativeRotation;
|
||||
};
|
||||
|
||||
struct Door {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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
|
Loading…
Reference in a new issue