Fix bugs in level transitions
This commit is contained in:
parent
d48c57a19e
commit
338b197dcc
4
Makefile
4
Makefile
|
@ -183,7 +183,7 @@ ANIM_LIST = build/assets/models/pedestal_anim.o
|
|||
MODEL_HEADERS = $(MODEL_LIST:%.blend=build/%.h)
|
||||
MODEL_OBJECTS = $(MODEL_LIST:%.blend=build/%_geo.o)
|
||||
|
||||
build/assets/models/%.h build/assets/models/%_geo.c: build/assets/models/%.fbx assets/models/%.flags assets/materials/elevator.skm.yaml assets/materials/objects.skm.yaml assets/materials/static.skm.yaml $(SKELATOOL64)
|
||||
build/assets/models/%.h build/assets/models/%_geo.c build/assets/models/%_anim.c: build/assets/models/%.fbx assets/models/%.flags assets/materials/elevator.skm.yaml assets/materials/objects.skm.yaml assets/materials/static.skm.yaml $(SKELATOOL64)
|
||||
$(SKELATOOL64) --fixed-point-scale 256 --model-scale 0.01 --name $(<:build/assets/models/%.fbx=%) $(shell cat $(<:build/assets/models/%.fbx=assets/models/%.flags)) -o $(<:%.fbx=%.h) $<
|
||||
|
||||
build/src/models/models.o: $(MODEL_HEADERS)
|
||||
|
@ -194,8 +194,6 @@ build/src/scene/portal.o: $(MODEL_HEADERS)
|
|||
|
||||
build/src/scene/signage.o: $(MODEL_HEADERS)
|
||||
|
||||
build/assets/models/%_anim.o: build/assets/models/%.h
|
||||
|
||||
build/anims.ld: $(ANIM_LIST) tools/generate_animation_ld.js
|
||||
@mkdir -p $(@D)
|
||||
node tools/generate_animation_ld.js $@ $(ANIM_LIST)
|
||||
|
|
|
@ -84,12 +84,15 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender
|
|||
|
||||
## Current TODO list
|
||||
|
||||
- [ ] Prevent Glados from talking over herself
|
||||
- [ ] It is too easy to fall through portals
|
||||
- [ ] Elevator and door sounds
|
||||
- [ ] Presort portal gun polygon order
|
||||
- [ ] Change the way player standing logic works
|
||||
- [ ] Cube dispenser
|
||||
- [ ] Signage should not always be on
|
||||
- [ ] Camera shake
|
||||
- [x] crash on level transition
|
||||
- [x] Prevent Glados from talking over herself
|
||||
- [x] NAN in overlap
|
||||
- [x] Turn level indicator board into a game object
|
||||
- [x] kill plane
|
||||
|
|
|
@ -1 +1 @@
|
|||
-r 90,0,0 -m assets/materials/static.skm.yaml -m assets/materials/objects.skm.yaml --default-material button
|
||||
-r 0,0,0 -m assets/materials/static.skm.yaml -m assets/materials/objects.skm.yaml --default-material button
|
|
@ -50,7 +50,12 @@ std::unique_ptr<StructureDataChunk> generateCutsceneStep(CutsceneStep& step, int
|
|||
if ((step.command == "play_sound" || step.command == "start_sound") && step.args.size() >= 1) {
|
||||
result->AddPrimitive<const char*>(step.command == "play_sound" ? "CutsceneStepTypePlaySound" : "CutsceneStepTypeStartSound");
|
||||
std::unique_ptr<StructureDataChunk> playSound(new StructureDataChunk());
|
||||
playSound->AddPrimitive(step.args[0]);
|
||||
|
||||
if (StartsWith(step.args[0], "SOUNDS_")) {
|
||||
playSound->AddPrimitive(step.args[0]);
|
||||
} else {
|
||||
playSound->AddPrimitive(std::string("SOUNDS_") + step.args[0]);
|
||||
}
|
||||
|
||||
if (step.args.size() >= 2) {
|
||||
playSound->AddPrimitive((int)(std::atof(step.args[1].c_str()) * 255.0f));
|
||||
|
@ -66,6 +71,35 @@ std::unique_ptr<StructureDataChunk> generateCutsceneStep(CutsceneStep& step, int
|
|||
|
||||
result->Add("playSound", std::move(playSound));
|
||||
|
||||
return result;
|
||||
} else if (step.command == "q_sound" && step.args.size() >= 2) {
|
||||
result->AddPrimitive<const char*>("CutsceneStepTypeQueueSound");
|
||||
std::unique_ptr<StructureDataChunk> queueSound(new StructureDataChunk());
|
||||
|
||||
if (StartsWith(step.args[0], "SOUNDS_")) {
|
||||
queueSound->AddPrimitive(step.args[0]);
|
||||
} else {
|
||||
queueSound->AddPrimitive(std::string("SOUNDS_") + step.args[0]);
|
||||
}
|
||||
|
||||
// channel
|
||||
queueSound->AddPrimitive(step.args[1]);
|
||||
|
||||
// volume
|
||||
if (step.args.size() >= 3) {
|
||||
queueSound->AddPrimitive((int)(std::atof(step.args[2].c_str()) * 255.0f));
|
||||
} else {
|
||||
queueSound->AddPrimitive(255);
|
||||
}
|
||||
|
||||
result->Add("queueSound", std::move(queueSound));
|
||||
|
||||
return result;
|
||||
} else if (step.command == "wait_for_channel" && step.args.size() >= 1) {
|
||||
result->AddPrimitive<const char*>("CutsceneStepTypeWaitForChannel");
|
||||
std::unique_ptr<StructureDataChunk> waitForChannel(new StructureDataChunk());
|
||||
waitForChannel->AddPrimitive(step.args[0]);
|
||||
result->Add("waitForChannel", std::move(waitForChannel));
|
||||
return result;
|
||||
} else if (step.command == "delay" && step.args.size() >= 1) {
|
||||
result->AddPrimitive<const char*>("CutsceneStepTypeDelay");
|
||||
|
|
|
@ -9,6 +9,39 @@
|
|||
struct CutsceneRunner* gRunningCutscenes;
|
||||
struct CutsceneRunner* gUnusedRunners;
|
||||
|
||||
#define MAX_QUEUE_LENGTH 16
|
||||
|
||||
struct QueuedSound {
|
||||
struct QueuedSound* next;
|
||||
u16 soundId;
|
||||
float volume;
|
||||
};
|
||||
|
||||
struct QueuedSound gCutsceneSoundNodes[MAX_QUEUE_LENGTH];
|
||||
struct QueuedSound* gCutsceneNextFreeSound;
|
||||
|
||||
struct QueuedSound* gCutsceneSoundQueues[CH_COUNT];
|
||||
ALSndId gCutsceneCurrentSound[CH_COUNT];
|
||||
|
||||
float gCutsceneChannelPitch[CH_COUNT] = {
|
||||
[CH_GLADOS] = 0.5f,
|
||||
};
|
||||
|
||||
void cutsceneRunnerReset() {
|
||||
gRunningCutscenes = NULL;
|
||||
|
||||
for (int i = 0; i < MAX_QUEUE_LENGTH; ++i) {
|
||||
gCutsceneSoundNodes[i].next = (i + 1) < MAX_QUEUE_LENGTH ? &gCutsceneSoundNodes[i + 1] : NULL;
|
||||
}
|
||||
|
||||
gCutsceneNextFreeSound = &gCutsceneSoundNodes[0];
|
||||
|
||||
for (int i = 0; i < CH_COUNT; ++i) {
|
||||
gCutsceneSoundQueues[i] = NULL;
|
||||
gCutsceneCurrentSound[i] = SOUND_ID_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
struct CutsceneRunner* cutsceneRunnerNew() {
|
||||
struct CutsceneRunner* result;
|
||||
|
||||
|
@ -31,6 +64,7 @@ void cutsceneRunnerCancel(struct CutsceneRunner* runner) {
|
|||
|
||||
switch (step->type) {
|
||||
case CutsceneStepTypePlaySound:
|
||||
case CutsceneStepTypeStartSound:
|
||||
soundPlayerStop(runner->state.playSound.soundId);
|
||||
break;
|
||||
default:
|
||||
|
@ -40,17 +74,50 @@ void cutsceneRunnerCancel(struct CutsceneRunner* runner) {
|
|||
runner->currentCutscene = NULL;
|
||||
}
|
||||
|
||||
ALSndId cutsceneRunnerPlaySound(struct CutsceneStep* step) {
|
||||
return soundPlayerPlay(
|
||||
step->playSound.soundId,
|
||||
step->playSound.volume * (1.0f / 255.0f),
|
||||
step->playSound.pitch * (1.0f / 64.0f),
|
||||
NULL
|
||||
);
|
||||
}
|
||||
|
||||
void cutsceneQueueSound(int soundId, float volume, int channel) {
|
||||
struct QueuedSound* next = gCutsceneNextFreeSound;
|
||||
|
||||
if (!next) {
|
||||
return;
|
||||
}
|
||||
|
||||
gCutsceneNextFreeSound = gCutsceneNextFreeSound->next;
|
||||
|
||||
next->next = NULL;
|
||||
next->soundId = soundId;
|
||||
next->volume = volume;
|
||||
|
||||
struct QueuedSound* tail = gCutsceneSoundQueues[channel];
|
||||
|
||||
while (tail && tail->next) {
|
||||
tail = tail->next;
|
||||
}
|
||||
|
||||
if (tail) {
|
||||
tail->next = next;
|
||||
} else {
|
||||
gCutsceneSoundQueues[channel] = next;
|
||||
}
|
||||
}
|
||||
|
||||
void cutsceneRunnerStartStep(struct CutsceneRunner* runner) {
|
||||
struct CutsceneStep* step = &runner->currentCutscene->steps[runner->currentStep];
|
||||
switch (step->type) {
|
||||
case CutsceneStepTypePlaySound:
|
||||
case CutsceneStepTypeStartSound:
|
||||
runner->state.playSound.soundId = soundPlayerPlay(
|
||||
step->playSound.soundId,
|
||||
step->playSound.volume * (1.0f / 255.0f),
|
||||
step->playSound.pitch * (1.0f / 64.0f),
|
||||
NULL
|
||||
);
|
||||
runner->state.playSound.soundId = cutsceneRunnerPlaySound(step);
|
||||
break;
|
||||
case CutsceneStepTypeQueueSound:
|
||||
cutsceneQueueSound(step->queueSound.soundId, step->queueSound.volume * (1.0f / 255.0f), step->queueSound.channel);
|
||||
break;
|
||||
case CutsceneStepTypeDelay:
|
||||
runner->state.delay = step->delay;
|
||||
|
@ -114,6 +181,11 @@ int cutsceneRunnerUpdateCurrentStep(struct CutsceneRunner* runner) {
|
|||
switch (step->type) {
|
||||
case CutsceneStepTypePlaySound:
|
||||
return !soundPlayerIsPlaying(runner->state.playSound.soundId);
|
||||
case CutsceneStepTypeWaitForChannel:
|
||||
{
|
||||
int result = !soundPlayerIsPlaying(gCutsceneCurrentSound[step->waitForChannel.channel]) && gCutsceneSoundQueues[step->waitForChannel.channel] == NULL;
|
||||
return result;
|
||||
}
|
||||
case CutsceneStepTypeDelay:
|
||||
runner->state.delay -= FIXED_DELTA_TIME;
|
||||
return runner->state.delay <= 0.0f;
|
||||
|
@ -195,10 +267,30 @@ int cutsceneIsRunning(struct Cutscene* cutscene) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void cutscenesUpdateSounds() {
|
||||
for (int i = 0; i < CH_COUNT; ++i) {
|
||||
if (!soundPlayerIsPlaying(gCutsceneCurrentSound[i])) {
|
||||
if (gCutsceneSoundQueues[i]) {
|
||||
struct QueuedSound* curr = gCutsceneSoundQueues[i];
|
||||
|
||||
gCutsceneCurrentSound[i] = soundPlayerPlay(curr->soundId, curr->volume, gCutsceneChannelPitch[i], NULL);
|
||||
gCutsceneSoundQueues[i] = curr->next;
|
||||
|
||||
curr->next = gCutsceneNextFreeSound;
|
||||
gCutsceneNextFreeSound = curr;
|
||||
} else {
|
||||
gCutsceneCurrentSound[i] = SOUND_ID_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cutscenesUpdate() {
|
||||
struct CutsceneRunner* previousCutscene = NULL;
|
||||
struct CutsceneRunner* current = gRunningCutscenes;
|
||||
|
||||
cutscenesUpdateSounds();
|
||||
|
||||
while (current) {
|
||||
if (cutsceneRunnerIsRunning(current)) {
|
||||
cutsceneRunnerUpdate(current);
|
||||
|
|
|
@ -18,7 +18,7 @@ struct CutsceneRunner {
|
|||
struct CutsceneRunner* nextRunner;
|
||||
};
|
||||
|
||||
|
||||
void cutsceneRunnerReset();
|
||||
void cutsceneStart(struct Cutscene* cutscene);
|
||||
void cutsceneStop(struct Cutscene* cutscene);
|
||||
int cutsceneIsRunning(struct Cutscene* cutscene);
|
||||
|
|
|
@ -26,6 +26,8 @@ enum CutsceneStepType {
|
|||
CutsceneStepTypeNoop,
|
||||
CutsceneStepTypePlaySound,
|
||||
CutsceneStepTypeStartSound,
|
||||
CutsceneStepTypeQueueSound,
|
||||
CutsceneStepTypeWaitForChannel,
|
||||
CutsceneStepTypeDelay,
|
||||
CutsceneStepTypeOpenPortal,
|
||||
CutsceneStepTypeSetSignal,
|
||||
|
@ -40,6 +42,11 @@ enum CutsceneStepType {
|
|||
CutsceneStepTypePointPedestal,
|
||||
};
|
||||
|
||||
#define CH_NONE 0xFF
|
||||
#define CH_GLADOS 0
|
||||
|
||||
#define CH_COUNT 1
|
||||
|
||||
struct CutsceneStep {
|
||||
enum CutsceneStepType type;
|
||||
|
||||
|
@ -49,6 +56,14 @@ struct CutsceneStep {
|
|||
u8 volume;
|
||||
u8 pitch;
|
||||
} playSound;
|
||||
struct {
|
||||
u16 soundId;
|
||||
u8 channel;
|
||||
u8 volume;
|
||||
} queueSound;
|
||||
struct {
|
||||
u8 channel;
|
||||
} waitForChannel;
|
||||
struct {
|
||||
u16 locationIndex;
|
||||
u16 portalIndex;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "audio/audio.h"
|
||||
#include "scene/portal_surface.h"
|
||||
#include "sk64/skelatool_defs.h"
|
||||
#include "levels/cutscene_runner.h"
|
||||
|
||||
#include "levels/levels.h"
|
||||
|
||||
|
@ -152,7 +153,9 @@ static void gameProc(void* arg) {
|
|||
|
||||
dynamicSceneInit();
|
||||
contactSolverInit(&gContactSolver);
|
||||
portalSurfaceCleanupQueueInit();
|
||||
levelLoad(0);
|
||||
cutsceneRunnerReset();
|
||||
controllersInit();
|
||||
initAudio();
|
||||
soundPlayerInit();
|
||||
|
@ -175,10 +178,13 @@ static void gameProc(void* arg) {
|
|||
if (levelGetQueued() != NO_QUEUED_LEVEL) {
|
||||
if (pendingGFX == 0) {
|
||||
dynamicSceneInit();
|
||||
contactSolverInit(&gContactSolver);
|
||||
portalSurfaceRevert(1);
|
||||
portalSurfaceRevert(0);
|
||||
portalSurfaceCleanupQueueInit();
|
||||
heapInit(_heapStart, memoryEnd);
|
||||
levelLoad(levelGetQueued());
|
||||
cutsceneRunnerReset();
|
||||
sceneInit(&gScene);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,12 @@ void portalSurfaceCheckCleanupQueue() {
|
|||
}
|
||||
}
|
||||
|
||||
void portalSurfaceCleanupQueueInit() {
|
||||
for (int searchIterator = 0; searchIterator < MAX_PENDING_PORTAL_CLEANUP; ++searchIterator) {
|
||||
gPortalSurfaceCleanupQueue[searchIterator].shouldCleanup = 0;
|
||||
}
|
||||
}
|
||||
|
||||
struct PortalSurfaceReplacement gPortalSurfaceReplacements[2];
|
||||
|
||||
int portalSurfaceAreBothOnSameSurface() {
|
||||
|
|
|
@ -55,6 +55,8 @@ struct PortalSurfaceReplacement {
|
|||
short roomIndex;
|
||||
};
|
||||
|
||||
void portalSurfaceCleanupQueueInit();
|
||||
|
||||
int portalSurfaceAreBothOnSameSurface();
|
||||
int portalSurfaceShouldSwapOrder(int portalToMove);
|
||||
int portalSurfaceStaticIndexForReplacement(int portalIndex);
|
||||
|
|
Loading…
Reference in a new issue