diff --git a/Makefile b/Makefile index 1a51eb7..4bd28cd 100644 --- a/Makefile +++ b/Makefile @@ -379,7 +379,8 @@ ANIM_TEST_CHAMBERS = build/assets/test_chambers/test_chamber_00/test_chamber_00_ build/assets/test_chambers/test_chamber_03/test_chamber_03_anim.o \ build/assets/test_chambers/test_chamber_04/test_chamber_04_anim.o \ build/assets/test_chambers/test_chamber_06/test_chamber_06_anim.o \ - build/assets/test_chambers/test_chamber_07/test_chamber_07_anim.o + build/assets/test_chambers/test_chamber_07/test_chamber_07_anim.o \ + build/assets/test_chambers/test_chamber_08/test_chamber_08_anim.o build/anims.ld: $(ANIM_LIST) $(ANIM_TEST_CHAMBERS) tools/generate_animation_ld.js @mkdir -p $(@D) @@ -396,7 +397,8 @@ TEST_CHAMBERS = assets/test_chambers/test_chamber_00/test_chamber_00.blend \ assets/test_chambers/test_chamber_04/test_chamber_04.blend \ assets/test_chambers/test_chamber_05/test_chamber_05.blend \ assets/test_chambers/test_chamber_06/test_chamber_06.blend \ - assets/test_chambers/test_chamber_07/test_chamber_07.blend + assets/test_chambers/test_chamber_07/test_chamber_07.blend \ + assets/test_chambers/test_chamber_08/test_chamber_08.blend TEST_CHAMBER_HEADERS = $(TEST_CHAMBERS:%.blend=build/%.h) TEST_CHAMBER_OBJECTS = $(TEST_CHAMBERS:%.blend=build/%_geo.o) diff --git a/assets/materials/static.skm.yaml b/assets/materials/static.skm.yaml index 19020d4..46f1122 100644 --- a/assets/materials/static.skm.yaml +++ b/assets/materials/static.skm.yaml @@ -174,7 +174,7 @@ materials: gSPGeometryMode: set: [G_SHADE] - clear: [G_LIGHTING] + clear: [G_LIGHTING, G_CULL_BACK] properties: tileSizeS: 0.125 diff --git a/assets/sound/vo/aperture_ai/08_part1_entry-1.sox b/assets/sound/vo/aperture_ai/08_part1_entry-1.sox new file mode 100644 index 0000000..5ad82e6 --- /dev/null +++ b/assets/sound/vo/aperture_ai/08_part1_entry-1.sox @@ -0,0 +1 @@ +-c 1 -r 22050 diff --git a/assets/sound/vo/aperture_ai/08_part1_entry-2.sox b/assets/sound/vo/aperture_ai/08_part1_entry-2.sox new file mode 100644 index 0000000..5ad82e6 --- /dev/null +++ b/assets/sound/vo/aperture_ai/08_part1_entry-2.sox @@ -0,0 +1 @@ +-c 1 -r 22050 diff --git a/assets/sound/vo/aperture_ai/08_part1_entry-3.sox b/assets/sound/vo/aperture_ai/08_part1_entry-3.sox new file mode 100644 index 0000000..5ad82e6 --- /dev/null +++ b/assets/sound/vo/aperture_ai/08_part1_entry-3.sox @@ -0,0 +1 @@ +-c 1 -r 22050 diff --git a/assets/sound/vo/aperture_ai/08_part1_success-1.sox b/assets/sound/vo/aperture_ai/08_part1_success-1.sox new file mode 100644 index 0000000..5ad82e6 --- /dev/null +++ b/assets/sound/vo/aperture_ai/08_part1_success-1.sox @@ -0,0 +1 @@ +-c 1 -r 22050 diff --git a/assets/sound/vo/aperture_ai/08_part1_success-2.sox b/assets/sound/vo/aperture_ai/08_part1_success-2.sox new file mode 100644 index 0000000..5ad82e6 --- /dev/null +++ b/assets/sound/vo/aperture_ai/08_part1_success-2.sox @@ -0,0 +1 @@ +-c 1 -r 22050 diff --git a/assets/sound/vo/aperture_ai/08_part1_trapped-1.sox b/assets/sound/vo/aperture_ai/08_part1_trapped-1.sox new file mode 100644 index 0000000..5ad82e6 --- /dev/null +++ b/assets/sound/vo/aperture_ai/08_part1_trapped-1.sox @@ -0,0 +1 @@ +-c 1 -r 22050 diff --git a/assets/sound/vo/aperture_ai/08_part1_trapped-2.sox b/assets/sound/vo/aperture_ai/08_part1_trapped-2.sox new file mode 100644 index 0000000..5ad82e6 --- /dev/null +++ b/assets/sound/vo/aperture_ai/08_part1_trapped-2.sox @@ -0,0 +1 @@ +-c 1 -r 22050 diff --git a/assets/test_chambers/test_chamber_08/test_chamber_08.blend b/assets/test_chambers/test_chamber_08/test_chamber_08.blend index 719c8e5..3805121 100644 Binary files a/assets/test_chambers/test_chamber_08/test_chamber_08.blend and b/assets/test_chambers/test_chamber_08/test_chamber_08.blend differ diff --git a/assets/test_chambers/test_chamber_08/test_chamber_08.yaml b/assets/test_chambers/test_chamber_08/test_chamber_08.yaml index 1048e11..502f7e6 100644 --- a/assets/test_chambers/test_chamber_08/test_chamber_08.yaml +++ b/assets/test_chambers/test_chamber_08/test_chamber_08.yaml @@ -1,10 +1,32 @@ cutscenes: - INTRO_CUTSCENE: + START: - set_signal launch_ball + - start_cutscene CHECK_TRAPPED - wait_for_signal move_platform - label horizontal_loop - play_animation horizontal horizontal_slide - wait_for_animation horizontal - goto horizontal_loop + INTRO_CUTSCENE: + - activate_signage 13 + - q_sound 08_PART1_ENTRY_1 CH_GLADOS PORTAL_08_PART1_ENTRY_1 + - q_sound 08_PART1_ENTRY_2 CH_GLADOS PORTAL_08_PART1_ENTRY_2 + - q_sound 08_PART1_ENTRY_3 CH_GLADOS PORTAL_08_PART1_ENTRY_3 + FINISH: + - q_sound 08_PART1_SUCCESS_1 CH_GLADOS PORTAL_08_PART1_SUCCESS_1 + - q_sound 08_PART1_SUCCESS_2 CH_GLADOS PORTAL_08_PART1_SUCCESS_2 + CHECK_TRAPPED: + - wait_for_signal trapped 30 + - q_sound 08_PART1_TRAPPED_1 CH_GLADOS PORTAL_08_PART1_TRAPPED_1 + - q_sound 08_PART1_TRAPPED_2 CH_GLADOS PORTAL_08_PART1_TRAPPED_2 + - wait_for_channel CH_GLADOS + - set_signal room_exit operators: - - room_exit = room_exit_0 and room_exit_1 \ No newline at end of file + - room_exit = room_exit_0 and room_exit_1 + - side_cube_access = player_in_side and has_cube_side + - main_cube_access = player_in_main and has_cube_main + - has_cube_any = has_cube_side or has_cube_main + - side_cube_access_with_door = room_enter and has_cube_any + - direct_cube_access = side_cube_access or main_cube_access + - any_cube_access = direct_cube_access or side_cube_access_with_door + - trapped = not any_cube_access \ No newline at end of file diff --git a/src/levels/cutscene_runner.c b/src/levels/cutscene_runner.c index c8b6d82..757068b 100644 --- a/src/levels/cutscene_runner.c +++ b/src/levels/cutscene_runner.c @@ -204,6 +204,9 @@ void cutsceneRunnerStartStep(struct CutsceneRunner* runner) { case CutsceneStepTypeDelay: runner->state.delay = step->delay; break; + case CutsceneStepTypeWaitForSignal: + runner->state.waitForSignal.currentFrame = step->waitForSignal.forFrames; + break; case CutsceneStepTypeOpenPortal: { struct Location* location = &gCurrentLevel->locations[step->openPortal.locationIndex]; @@ -348,7 +351,17 @@ int cutsceneRunnerUpdateCurrentStep(struct CutsceneRunner* runner) { runner->state.delay -= FIXED_DELTA_TIME; return runner->state.delay <= 0.0f; case CutsceneStepTypeWaitForSignal: - return signalsRead(step->waitForSignal.signalIndex); + if (signalsRead(step->waitForSignal.signalIndex)) { + if (runner->state.waitForSignal.currentFrame > 0) { + --runner->state.waitForSignal.currentFrame; + } else { + return 1; + } + } else { + runner->state.waitForSignal.currentFrame = step->waitForSignal.forFrames; + } + + return 0; case CutsceneStepTypeWaitForCutscene: return !cutsceneIsRunning(&gCurrentLevel->cutscenes[step->cutscene.cutsceneIndex]); case CutsceneStepWaitForAnimation: diff --git a/src/levels/cutscene_runner.h b/src/levels/cutscene_runner.h index 24613a7..1b1458f 100644 --- a/src/levels/cutscene_runner.h +++ b/src/levels/cutscene_runner.h @@ -10,6 +10,9 @@ union CutsceneStepState { struct { ALSndId soundId; } playSound; + struct { + u8 currentFrame; + } waitForSignal; float delay; }; diff --git a/src/levels/level_definition.h b/src/levels/level_definition.h index cf25fe5..9192184 100644 --- a/src/levels/level_definition.h +++ b/src/levels/level_definition.h @@ -121,6 +121,7 @@ struct CutsceneStep { } setSignal; struct { u16 signalIndex; + u8 forFrames; } waitForSignal; struct { u16 fromLocation; diff --git a/src/scene/trigger_listener.c b/src/scene/trigger_listener.c index 40ed366..4449197 100644 --- a/src/scene/trigger_listener.c +++ b/src/scene/trigger_listener.c @@ -8,15 +8,17 @@ extern struct ColliderTypeData gPlayerColliderData; +#define TRIGGER_TYPE_TO_MASK(type) (1 << (type)) + enum ObjectTriggerType triggerDetermineType(struct CollisionObject* objectEnteringTrigger) { if (objectEnteringTrigger->collider == &gPlayerColliderData) { - return ObjectTriggerTypePlayer; + return TRIGGER_TYPE_TO_MASK(ObjectTriggerTypePlayer); } int decorType = decorIdForObjectDefinition((struct DecorObjectDefinition*)objectEnteringTrigger->collider); if (decorType == DECOR_TYPE_CUBE || decorType == DECOR_TYPE_CUBE_UNIMPORTANT) { - return gScene.player.grabConstraint.object == objectEnteringTrigger ? ObjectTriggerTypeCubeHover : ObjectTriggerTypeCube; + return gScene.player.grabConstraint.object == objectEnteringTrigger ? TRIGGER_TYPE_TO_MASK(ObjectTriggerTypeCubeHover) | TRIGGER_TYPE_TO_MASK(ObjectTriggerTypeCube) : TRIGGER_TYPE_TO_MASK(ObjectTriggerTypeCube); } return ObjectTriggerTypeNone; @@ -41,7 +43,12 @@ void triggerTrigger(void* data, struct CollisionObject* objectEnteringTrigger) { enum ObjectTriggerType triggerType = triggerDetermineType(objectEnteringTrigger); - listener->lastTriggerMask |= (1 << triggerType); + if (triggerType & listener->usedTriggerMask) { + // an object activating a signal should not sleep + objectEnteringTrigger->body->sleepFrames = IDLE_SLEEP_FRAMES; + } + + listener->lastTriggerMask |= triggerType; } void triggerInit(struct TriggerListener* listener, struct Trigger* trigger, int triggerIndex) { @@ -69,10 +76,16 @@ void triggerInit(struct TriggerListener* listener, struct Trigger* trigger, int collisionSceneAddDynamicObject(&listener->collisionObject); listener->lastTriggerMask = 0; + listener->usedTriggerMask = 0; + + for (int i = 0; i < trigger->triggerCount; ++i) { + struct ObjectTriggerInfo* triggerInfo = &trigger->triggers[i]; + listener->usedTriggerMask |= 1 << triggerInfo->objectType; + } } void triggerListenerUpdate(struct TriggerListener* listener) { - if (!listener->lastTriggerMask) { + if (!(listener->lastTriggerMask & listener->usedTriggerMask)) { return; } diff --git a/src/scene/trigger_listener.h b/src/scene/trigger_listener.h index b443f5c..39ce20e 100644 --- a/src/scene/trigger_listener.h +++ b/src/scene/trigger_listener.h @@ -16,6 +16,7 @@ struct TriggerListener { struct Trigger* trigger; short triggerIndex; short lastTriggerMask; + short usedTriggerMask; }; void triggerInit(struct TriggerListener* listener, struct Trigger* trigger, int triggerIndex); diff --git a/tools/level_scripts/trigger.lua b/tools/level_scripts/trigger.lua index 8e2ec5d..f12cf81 100644 --- a/tools/level_scripts/trigger.lua +++ b/tools/level_scripts/trigger.lua @@ -137,6 +137,7 @@ local function generate_cutscene_step(cutscene_name, step, step_index, label_loc result.type = sk_definition_writer.raw('CutsceneStepTypeWaitForSignal') result.waitForSignal = { signals.signal_index_for_name(step.args[1]), + tonumber(step.args[2] or "0"), } elseif step.command == "teleport_player" and #step.args >= 2 then result.type = sk_definition_writer.raw('CutsceneStepTypeTeleportPlayer')