mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-19 22:27:36 -04:00
Dynamic Captions Building and Enhancements
- python file added and invoked at make that produces a subtitles.c and subtitles.h synamically based on the closed captions files present inside of the resource/ folder - added an in-game slider to choose from the languages which were dynamically loaded at time of building. - if no closecaption files are present at the time of building, the script will still make the subtitles.c/.h but it just wont have any data. This will also result in the two menu items relating to closed captions being removed. - the names of subtitles in the .yaml files are the upercase versions of the names of subtitles in each subtitle file, so that they are easy to find. - fixed margins on sides of subtitles - fixed color of subtitles to be more visible - sped up the fade in and out animations. - automated new-line breaks. Issues I have seen: - if you load more than like 6 closed caption languages into the resource/ folder the game doesnt seem to want to start up once built. I think this is due to the sheer size of the subtitles.c file that is generated. I would love some feedback on how to make this work a little better/be more memory efficient, as it would be nice to have every closed caption language available on every build. - languages with very unique characters (chinese, japanese, korean, greek, etc.) do not work because the python codec that is used to decode/encode the files doesnt support them. for now that logic is in a try/except so it wont fail, it will simply skip a language that is not supported.
This commit is contained in:
parent
13e20dd002
commit
b2bde849ba
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -15,9 +15,13 @@ vpk/
|
|||
portal_pak_dir/
|
||||
portal_pak_modified/
|
||||
|
||||
resource/closecaption_*
|
||||
|
||||
tools/skeletool64
|
||||
tools/vtf2png
|
||||
|
||||
skelatool64/*.zip
|
||||
|
||||
src/controls/controller-data.h
|
||||
src/audio/subtitles.c
|
||||
src/audio/subtitles.h
|
||||
|
|
9
Makefile
9
Makefile
|
@ -67,21 +67,26 @@ LDFLAGS = -L/usr/lib/n64 $(N64LIB) -L$(N64_LIBGCCDIR) -lgcc
|
|||
default: english_audio
|
||||
|
||||
english_audio: portal_pak_dir
|
||||
@python tools/level_scripts/subtitle_generate.py
|
||||
@$(MAKE) buildgame
|
||||
|
||||
german_audio: vpk/portal_sound_vo_german_dir.vpk vpk/portal_sound_vo_german_000.vpk portal_pak_dir
|
||||
@python tools/level_scripts/subtitle_generate.py
|
||||
vpk -x portal_pak_dir vpk/portal_sound_vo_german_dir.vpk
|
||||
@$(MAKE) buildgame
|
||||
|
||||
french_audio: vpk/portal_sound_vo_french_dir.vpk vpk/portal_sound_vo_french_000.vpk portal_pak_dir
|
||||
@python tools/level_scripts/subtitle_generate.py
|
||||
vpk -x portal_pak_dir vpk/portal_sound_vo_french_dir.vpk
|
||||
@$(MAKE) buildgame
|
||||
|
||||
russian_audio: vpk/portal_sound_vo_russian_dir.vpk vpk/portal_sound_vo_russian_000.vpk portal_pak_dir
|
||||
@python tools/level_scripts/subtitle_generate.py
|
||||
vpk -x portal_pak_dir vpk/portal_sound_vo_russian_dir.vpk
|
||||
@$(MAKE) buildgame
|
||||
|
||||
spanish_audio: vpk/portal_sound_vo_spanish_dir.vpk vpk/portal_sound_vo_spanish_000.vpk portal_pak_dir
|
||||
@python tools/level_scripts/subtitle_generate.py
|
||||
vpk -x portal_pak_dir vpk/portal_sound_vo_spanish_dir.vpk
|
||||
@$(MAKE) buildgame
|
||||
|
||||
|
@ -509,4 +514,8 @@ clean-assets:
|
|||
|
||||
fix:
|
||||
wine tools/romfix64.exe build/portal.z64
|
||||
|
||||
subtitles: tools/level_scripts/subtitle_generate.py
|
||||
python3 tools/level_scripts/subtitle_generate.py
|
||||
|
||||
.SECONDARY:
|
||||
|
|
|
@ -87,6 +87,12 @@ sudo apt install nodejs
|
|||
|
||||
<br />
|
||||
|
||||
Optionally, for closed captions you will need to add the following files from where Portal is installed to the folder `resource/`. If no files are placed here Portal64 will still build without them, it simply wont have an option for close captions in the game menu. 2-3 languages seems to work best.
|
||||
```
|
||||
portal/resource/closecaption_<your desired language 1>.txt
|
||||
portal/resource/closecaption_<your desired language 2>.txt
|
||||
```
|
||||
|
||||
You then need to add the following files from where Portal is installed to the folder `vpk`. (see vpk/add_vpk_here.md for more details!)
|
||||
```
|
||||
portal/portal_pak_000.vpk
|
||||
|
|
Binary file not shown.
|
@ -12,13 +12,13 @@ cutscenes:
|
|||
- delay 2
|
||||
- show_prompt CutscenePromptTypeJump
|
||||
- delay 3
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_1 CH_GLADOS SUBTITLE_00_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_2 CH_GLADOS SUBTITLE_00_PART1_ENTRY_2
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_3 CH_GLADOS SUBTITLE_00_PART1_ENTRY_3
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_4 CH_GLADOS SUBTITLE_00_PART1_ENTRY_4
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_5 CH_GLADOS SUBTITLE_00_PART1_ENTRY_5
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_6 CH_GLADOS SUBTITLE_00_PART1_ENTRY_6
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_7 CH_GLADOS SUBTITLE_00_PART1_ENTRY_7
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_1 CH_GLADOS PORTAL_00_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_2 CH_GLADOS PORTAL_00_PART1_ENTRY_2
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_3 CH_GLADOS PORTAL_00_PART1_ENTRY_3
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_4 CH_GLADOS PORTAL_00_PART1_ENTRY_4
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_5 CH_GLADOS PORTAL_00_PART1_ENTRY_5
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_6 CH_GLADOS PORTAL_00_PART1_ENTRY_6
|
||||
- q_sound SOUNDS_00_PART1_ENTRY_7 CH_GLADOS PORTAL_00_PART1_ENTRY_7
|
||||
- delay 7
|
||||
- show_prompt CutscenePromptTypeNone
|
||||
- wait_for_channel CH_GLADOS
|
||||
|
@ -30,9 +30,9 @@ cutscenes:
|
|||
- set_signal cube_dropper
|
||||
- show_prompt CutscenePromptTypePickup
|
||||
- wait_for_signal success
|
||||
- q_sound SOUNDS_00_PART1_SUCCESS_1 CH_GLADOS SUBTITLE_00_PART1_SUCCESS_1
|
||||
- q_sound SOUNDS_00_PART1_SUCCESS_2 CH_GLADOS SUBTITLE_00_PART1_SUCCESS_2
|
||||
- q_sound SOUNDS_00_PART1_SUCCESS_3 CH_GLADOS SUBTITLE_00_PART1_SUCCESS_3
|
||||
- q_sound SOUNDS_00_PART1_SUCCESS_1 CH_GLADOS PORTAL_00_PART1_SUCCESS_1
|
||||
- q_sound SOUNDS_00_PART1_SUCCESS_2 CH_GLADOS PORTAL_00_PART1_SUCCESS_2
|
||||
- q_sound SOUNDS_00_PART1_SUCCESS_3 CH_GLADOS PORTAL_00_PART1_SUCCESS_3
|
||||
START_SECOND_ROOM:
|
||||
- start_cutscene SECOND_ROOM_INSTRUCTIONS
|
||||
- open_portal stationary_portal 1
|
||||
|
@ -45,8 +45,8 @@ cutscenes:
|
|||
- delay 5
|
||||
- goto portal_loop
|
||||
SECOND_ROOM_INSTRUCTIONS:
|
||||
- q_sound SOUNDS_00_PART2_ENTRY_1 CH_GLADOS SUBTITLE_00_PART2_ENTRY_1
|
||||
- q_sound SOUNDS_00_PART2_ENTRY_1 CH_GLADOS PORTAL_00_PART2_ENTRY_1
|
||||
- wait_for_signal success_1
|
||||
- q_sound SOUNDS_00_PART2_SUCCESS_1 CH_GLADOS SUBTITLE_00_PART2_SUCCESS_1
|
||||
- q_sound SOUNDS_00_PART2_SUCCESS_1 CH_GLADOS PORTAL_00_PART2_SUCCESS_1
|
||||
HOVER_CUBE_PROMPT:
|
||||
- show_prompt CutscenePromptTypeDrop
|
||||
|
|
|
@ -6,8 +6,8 @@ cutscenes:
|
|||
- start_cutscene portal_loop
|
||||
- set_signal FIRST_ELEVATOR
|
||||
INTRO_CUTSCENE:
|
||||
- q_sound SOUNDS_01_PART1_ENTRY_1 CH_GLADOS SUBTITLE_01_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_01_PART1_ENTRY_2 CH_GLADOS SUBTITLE_01_PART1_ENTRY_2
|
||||
- q_sound SOUNDS_01_PART1_ENTRY_1 CH_GLADOS PORTAL_01_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_01_PART1_ENTRY_2 CH_GLADOS PORTAL_01_PART1_ENTRY_2
|
||||
- wait_for_channel CH_GLADOS
|
||||
- set_signal room_0_entrance
|
||||
GET_GUN:
|
||||
|
@ -16,19 +16,19 @@ cutscenes:
|
|||
- hide_pedestal
|
||||
- stop_cutscene portal_loop
|
||||
- show_prompt CutscenePromptTypePortal1
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_1 CH_GLADOS SUBTITLE_01_PART1_GET_PORTAL_GUN_1
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_2 CH_GLADOS SUBTITLE_01_PART1_GET_PORTAL_GUN_2
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_3 CH_GLADOS SUBTITLE_01_PART1_GET_PORTAL_GUN_3
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_4 CH_GLADOS SUBTITLE_01_PART1_GET_PORTAL_GUN_4
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_5 CH_GLADOS SUBTITLE_01_PART1_GET_PORTAL_GUN_5
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_6 CH_GLADOS SUBTITLE_01_PART1_GET_PORTAL_GUN_6
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_7 CH_GLADOS SUBTITLE_01_PART1_GET_PORTAL_GUN_7
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_8 CH_GLADOS SUBTITLE_01_PART1_GET_PORTAL_GUN_8
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_1 CH_GLADOS PORTAL_01_PART1_GET_PORTAL_GUN_1
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_2 CH_GLADOS PORTAL_01_PART1_GET_PORTAL_GUN_2
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_3 CH_GLADOS PORTAL_01_PART1_GET_PORTAL_GUN_3
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_4 CH_GLADOS PORTAL_01_PART1_GET_PORTAL_GUN_4
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_5 CH_GLADOS PORTAL_01_PART1_GET_PORTAL_GUN_5
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_6 CH_GLADOS PORTAL_01_PART1_GET_PORTAL_GUN_6
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_7 CH_GLADOS PORTAL_01_PART1_GET_PORTAL_GUN_7
|
||||
- q_sound 01_PART1_GET_PORTAL_GUN_8 CH_GLADOS PORTAL_01_PART1_GET_PORTAL_GUN_8
|
||||
MIND_THE_GAP:
|
||||
- open_portal portal_gap 0
|
||||
- q_sound SOUNDS_01_PART2_ENTRY_1 CH_GLADOS SUBTITLE_01_PART2_ENTRY_1
|
||||
- q_sound SOUNDS_01_PART2_ENTRY_1 CH_GLADOS PORTAL_01_PART2_ENTRY_1
|
||||
FINISH_03:
|
||||
- q_sound SOUNDS_01_PART2_SUCCESS_1 CH_GLADOS SUBTITLE_01_PART2_SUCCESS_1
|
||||
- q_sound SOUNDS_01_PART2_SUCCESS_1 CH_GLADOS PORTAL_01_PART2_SUCCESS_1
|
||||
portal_loop:
|
||||
- open_portal portal_exit 0
|
||||
- label loop_start
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
cutscenes:
|
||||
INTRO:
|
||||
- q_sound SOUNDS_02_PART1_ENTRY_1 CH_GLADOS SUBTITLE_02_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_02_PART1_ENTRY_1 CH_GLADOS PORTAL_02_PART1_ENTRY_1
|
||||
- wait_for_channel CH_GLADOS
|
||||
- open_portal portal_0 0
|
||||
- q_sound SOUNDS_02_PART1_ENTRY_2 CH_GLADOS SUBTITLE_02_PART1_ENTRY_2
|
||||
- q_sound SOUNDS_02_PART1_ENTRY_2 CH_GLADOS PORTAL_02_PART1_ENTRY_2
|
||||
- wait_for_signal success
|
||||
- q_sound SOUNDS_02_PART1_SUCCESS_1 CH_GLADOS SUBTITLE_02_PART1_SUCCESS_1
|
||||
- q_sound SOUNDS_02_PART1_SUCCESS_2 CH_GLADOS SUBTITLE_02_PART1_SUCCESS_2
|
||||
- q_sound SOUNDS_02_PART1_SUCCESS_1 CH_GLADOS PORTAL_02_PART1_SUCCESS_1
|
||||
- q_sound SOUNDS_02_PART1_SUCCESS_2 CH_GLADOS PORTAL_02_PART1_SUCCESS_2
|
||||
DROP_CUBE:
|
||||
- set_signal cube_dropper
|
||||
ENTER_BUTTON_ROOM:
|
||||
- open_portal portal_1
|
||||
BAD_PERSON:
|
||||
- q_sound SOUNDS_ESCAPE_01_PART1_NAG01_1 CH_GLADOS SUBTITLE_ESCAPE_01_PART1_NAG01_1
|
||||
- q_sound SOUNDS_ESCAPE_01_PART1_NAG01_1 CH_GLADOS PORTAL_ESCAPE_01_PART1_NAG01_1
|
||||
- wait_for_channel CH_GLADOS
|
||||
- set_signal bad_person
|
||||
ENTER_SMALL_ROOM:
|
||||
- set_signal in_room
|
||||
- open_portal portal_2 0
|
||||
- q_sound SOUNDS_02_PART2_SUCCESS_1 CH_GLADOS SUBTITLE_02_PART2_SUCCESS_1
|
||||
- q_sound SOUNDS_02_PART2_SUCCESS_2 CH_GLADOS SUBTITLE_02_PART2_SUCCESS_2
|
||||
- q_sound SOUNDS_02_PART2_SUCCESS_1 CH_GLADOS PORTAL_02_PART2_SUCCESS_1
|
||||
- q_sound SOUNDS_02_PART2_SUCCESS_2 CH_GLADOS PORTAL_02_PART2_SUCCESS_2
|
||||
operators:
|
||||
- should_open_door = exit_2_0 and exit_2_1
|
||||
- should_open_door = should_open_door or bad_person
|
||||
|
|
|
@ -13,16 +13,16 @@ cutscenes:
|
|||
- save_checkpoint 0.001
|
||||
- open_portal ground_portal_2
|
||||
- start_cutscene BALL_2
|
||||
- q_sound SOUNDS_03_PART2_ENTRY_1 CH_GLADOS SUBTITLE_03_PART2_ENTRY_1
|
||||
- q_sound SOUNDS_03_PART2_ENTRY_1 CH_GLADOS PORTAL_03_PART2_ENTRY_1
|
||||
- wait_for_signal horizontal_activiate 2
|
||||
- q_sound 03_PART2_PLATFORM_ACTIVATED_1 CH_GLADOS SUBTITLE_03_PART2_PLATFORM_ACTIVATED_1
|
||||
- q_sound 03_PART2_PLATFORM_ACTIVATED_1 CH_GLADOS PORTAL_03_PART2_PLATFORM_ACTIVATED_1
|
||||
INTRO:
|
||||
- save_checkpoint 0
|
||||
- open_portal ground_portal 0
|
||||
- q_sound SOUNDS_03_PART1_ENTRY_1 CH_GLADOS SUBTITLE_03_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_03_PART1_ENTRY_2 CH_GLADOS SUBTITLE_03_PART1_ENTRY_2
|
||||
- q_sound SOUNDS_03_PART1_ENTRY_1 CH_GLADOS PORTAL_03_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_03_PART1_ENTRY_2 CH_GLADOS PORTAL_03_PART1_ENTRY_2
|
||||
- wait_for_signal exit_activate 2
|
||||
- q_sound SOUNDS_03_PART1_SUCCESS_1 CH_GLADOS SUBTITLE_03_PART1_SUCCESS_1
|
||||
- q_sound SOUNDS_03_PART1_SUCCESS_1 CH_GLADOS PORTAL_03_PART1_SUCCESS_1
|
||||
START_BALL:
|
||||
- set_signal launch_ball
|
||||
- wait_for_signal exit_activate
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
cutscenes:
|
||||
SUCCESS:
|
||||
- q_sound SOUNDS_04_PART1_SUCCESS_1 CH_GLADOS SUBTITLE_04_PART1_SUCCESS_1
|
||||
- q_sound SOUNDS_04_PART1_SUCCESS_1 CH_GLADOS PORTAL_04_PART1_SUCCESS_1
|
||||
INTRO_CUTSCENE:
|
||||
- q_sound SOUNDS_04_PART1_ENTRY_1 CH_GLADOS SUBTITLE_04_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_04_PART1_ENTRY_1 CH_GLADOS PORTAL_04_PART1_ENTRY_1
|
||||
DROWN_PLAYER:
|
||||
- kill_player water
|
||||
OPEN_PORTAL:
|
||||
|
|
|
@ -4,20 +4,20 @@ cutscenes:
|
|||
INTRO_CUTSCENE:
|
||||
- set_signal cube_dropper
|
||||
- open_portal portal_0 0
|
||||
- q_sound SOUNDS_05_PART1_ENTRY_1 CH_GLADOS SUBTITLE_05_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_05_PART1_ENTRY_2 CH_GLADOS SUBTITLE_05_PART1_ENTRY_2
|
||||
- q_sound SOUNDS_05_PART1_ENTRY_1 CH_GLADOS PORTAL_05_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_05_PART1_ENTRY_2 CH_GLADOS PORTAL_05_PART1_ENTRY_2
|
||||
- start_cutscene NAG
|
||||
- wait_for_signal success
|
||||
- stop_cutscene NAG
|
||||
- q_sound SOUNDS_05_PART1_SUCCESS_1 CH_GLADOS SUBTITLE_05_PART1_SUCCESS_1
|
||||
- q_sound SOUNDS_05_PART1_SUCCESS_1 CH_GLADOS PORTAL_05_PART1_SUCCESS_1
|
||||
NAG:
|
||||
- delay 28
|
||||
- q_sound SOUNDS_05_PART1_NAG1_1 CH_GLADOS SUBTITLE_05_PART1_NAG1_1
|
||||
- q_sound SOUNDS_05_PART1_NAG1_1 CH_GLADOS PORTAL_05_PART1_NAG1_1
|
||||
- delay 20
|
||||
- q_sound SOUNDS_05_PART1_NAG2_1 CH_GLADOS SUBTITLE_05_PART1_NAG2_1
|
||||
- q_sound SOUNDS_05_PART1_NAG2_1 CH_GLADOS PORTAL_05_PART1_NAG2_1
|
||||
- delay 25
|
||||
- q_sound SOUNDS_05_PART1_NAG3_1 CH_GLADOS SUBTITLE_05_PART1_NAG3_1
|
||||
- q_sound SOUNDS_05_PART1_NAG3_1 CH_GLADOS PORTAL_05_PART1_NAG3_1
|
||||
- delay 25.001
|
||||
- q_sound SOUNDS_05_PART1_NAG4_1 CH_GLADOS SUBTITLE_05_PART1_NAG4_1
|
||||
- q_sound SOUNDS_05_PART1_NAG4_1 CH_GLADOS PORTAL_05_PART1_NAG4_1
|
||||
- delay 26
|
||||
- q_sound SOUNDS_05_PART1_NAG5_1 CH_GLADOS SUBTITLE_05_PART1_NAG5_1
|
||||
- q_sound SOUNDS_05_PART1_NAG5_1 CH_GLADOS PORTAL_05_PART1_NAG5_1
|
|
@ -8,16 +8,16 @@ cutscenes:
|
|||
- play_animation piston_top piston_top_0
|
||||
- play_animation piston_bottom piston_bottom_0
|
||||
FIRST_ROOM:
|
||||
- q_sound SOUNDS_06_PART1_ENTRY_1 CH_GLADOS SUBTITLE_06_PART1_ENTRY_1
|
||||
- q_sound SOUNDS_06_PART1_ENTRY_1 CH_GLADOS PORTAL_06_PART1_ENTRY_1
|
||||
- delay 4
|
||||
- open_portal first_room_portal 0
|
||||
OPEN_FIRST_DOOR:
|
||||
- set_signal room_0_exit
|
||||
SECOND_SUCCESS:
|
||||
- q_sound SOUNDS_06_PART1_SUCCESS_2_1 CH_GLADOS SUBTITLE_06_PART1_SUCCESS_2_1
|
||||
- q_sound SOUNDS_06_PART1_SUCCESS_2_1 CH_GLADOS PORTAL_06_PART1_SUCCESS_2_1
|
||||
- play_animation piston_top piston_top_1
|
||||
FIRST_SUCCESS:
|
||||
- q_sound SOUNDS_06_PART1_SUCCESS_1_1 CH_GLADOS SUBTITLE_06_PART1_SUCCESS_1_1
|
||||
- q_sound SOUNDS_06_PART1_SUCCESS_1_1 CH_GLADOS PORTAL_06_PART1_SUCCESS_1_1
|
||||
SECOND_ROOM:
|
||||
- close_portal 0
|
||||
- close_portal 1
|
||||
|
|
|
@ -25,17 +25,17 @@ cutscenes:
|
|||
- start_cutscene portal_loop
|
||||
- start_cutscene platform_ferry
|
||||
- set_signal launch_ball
|
||||
- q_sound 07_PART1_ENTRY_1 CH_GLADOS SUBTITLE_07_PART1_ENTRY_1
|
||||
- q_sound 07_PART1_ENTRY_2 CH_GLADOS SUBTITLE_07_PART1_ENTRY_2
|
||||
- q_sound 07_PART1_ENTRY_3 CH_GLADOS SUBTITLE_07_PART1_ENTRY_3
|
||||
- q_sound 07_PART1_ENTRY_1 CH_GLADOS PORTAL_07_PART1_ENTRY_1
|
||||
- q_sound 07_PART1_ENTRY_2 CH_GLADOS PORTAL_07_PART1_ENTRY_2
|
||||
- q_sound 07_PART1_ENTRY_3 CH_GLADOS PORTAL_07_PART1_ENTRY_3
|
||||
TILT:
|
||||
- delay 4
|
||||
- set_signal cube_dropper
|
||||
- play_animation tilt tilt
|
||||
START_1:
|
||||
- q_sound 07_PART2_ENTRY_1 CH_GLADOS SUBTITLE_07_PART2_ENTRY_1
|
||||
- q_sound 07_PART2_ENTRY_1 CH_GLADOS PORTAL_07_PART2_ENTRY_1
|
||||
- wait_for_signal weeeee
|
||||
- q_sound 07_PART2_SUCCESS_1 CH_GLADOS SUBTITLE_07_PART2_SUCCESS_1
|
||||
- q_sound 07_PART2_SUCCESS_1 CH_GLADOS PORTAL_07_PART2_SUCCESS_1
|
||||
portal_loop:
|
||||
- label loop_start
|
||||
- open_portal portal_0 0
|
||||
|
@ -60,12 +60,12 @@ cutscenes:
|
|||
- start_cutscene platform_loop
|
||||
- close_portal 0
|
||||
- show_prompt CutscenePromptTypePortal0
|
||||
- q_sound 07_PART1_GET_DEVICE_COMPONENT_1 CH_GLADOS SUBTITLE_07_PART1_GET_DEVICE_COMPONENT_1
|
||||
- q_sound 07_PART1_GET_DEVICE_COMPONENT_2 CH_GLADOS SUBTITLE_07_PART1_GET_DEVICE_COMPONENT_2
|
||||
- q_sound 07_PART1_GET_DEVICE_COMPONENT_3 CH_GLADOS SUBTITLE_07_PART1_GET_DEVICE_COMPONENT_3
|
||||
- q_sound 07_PART1_GET_DEVICE_COMPONENT_1 CH_GLADOS PORTAL_07_PART1_GET_DEVICE_COMPONENT_1
|
||||
- q_sound 07_PART1_GET_DEVICE_COMPONENT_2 CH_GLADOS PORTAL_07_PART1_GET_DEVICE_COMPONENT_2
|
||||
- q_sound 07_PART1_GET_DEVICE_COMPONENT_3 CH_GLADOS PORTAL_07_PART1_GET_DEVICE_COMPONENT_3
|
||||
- wait_for_signal trapped
|
||||
- q_sound 07_PART1_TRAPPED_1 CH_GLADOS SUBTITLE_07_PART1_TRAPPED_1
|
||||
- q_sound 07_PART1_TRAPPED_2 CH_GLADOS SUBTITLE_07_PART1_TRAPPED_2
|
||||
- q_sound 07_PART1_TRAPPED_1 CH_GLADOS PORTAL_07_PART1_TRAPPED_1
|
||||
- q_sound 07_PART1_TRAPPED_2 CH_GLADOS PORTAL_07_PART1_TRAPPED_2
|
||||
- wait_for_channel CH_GLADOS
|
||||
- set_signal trap_door
|
||||
PROMPT_SWITCH:
|
||||
|
|
0
resource/.gitignore
vendored
Normal file
0
resource/.gitignore
vendored
Normal file
|
@ -10,6 +10,7 @@
|
|||
#include "../sk64/skelatool_clip.h"
|
||||
#include "../sk64/skelatool_armature.h"
|
||||
#include "../physics/collision_box.h"
|
||||
#include "../audio/subtitles.h"
|
||||
|
||||
#define NO_TRANSFORM_INDEX 0xFF
|
||||
|
||||
|
@ -63,68 +64,6 @@ enum CutscenePromptType {
|
|||
CutscenePromptTypeJump,
|
||||
};
|
||||
|
||||
enum CutsceneSubtitleType {
|
||||
CutsceneSubtitleTypeNone,
|
||||
SUBTITLE_00_PART1_ENTRY_1,
|
||||
SUBTITLE_00_PART1_ENTRY_2,
|
||||
SUBTITLE_00_PART1_ENTRY_3,
|
||||
SUBTITLE_00_PART1_ENTRY_4,
|
||||
SUBTITLE_00_PART1_ENTRY_5,
|
||||
SUBTITLE_00_PART1_ENTRY_6,
|
||||
SUBTITLE_00_PART1_ENTRY_7,
|
||||
SUBTITLE_00_PART1_SUCCESS_1,
|
||||
SUBTITLE_00_PART1_SUCCESS_2,
|
||||
SUBTITLE_00_PART1_SUCCESS_3,
|
||||
SUBTITLE_00_PART2_ENTRY_1,
|
||||
SUBTITLE_00_PART2_SUCCESS_1,
|
||||
SUBTITLE_01_PART1_ENTRY_1,
|
||||
SUBTITLE_01_PART1_ENTRY_2,
|
||||
SUBTITLE_01_PART1_GET_PORTAL_GUN_1,
|
||||
SUBTITLE_01_PART1_GET_PORTAL_GUN_2,
|
||||
SUBTITLE_01_PART1_GET_PORTAL_GUN_3,
|
||||
SUBTITLE_01_PART1_GET_PORTAL_GUN_4,
|
||||
SUBTITLE_01_PART1_GET_PORTAL_GUN_5,
|
||||
SUBTITLE_01_PART1_GET_PORTAL_GUN_6,
|
||||
SUBTITLE_01_PART1_GET_PORTAL_GUN_7,
|
||||
SUBTITLE_01_PART1_GET_PORTAL_GUN_8,
|
||||
SUBTITLE_01_PART2_ENTRY_1,
|
||||
SUBTITLE_01_PART2_SUCCESS_1,
|
||||
SUBTITLE_02_PART1_ENTRY_1,
|
||||
SUBTITLE_02_PART1_ENTRY_2,
|
||||
SUBTITLE_02_PART1_SUCCESS_1,
|
||||
SUBTITLE_02_PART1_SUCCESS_2,
|
||||
SUBTITLE_ESCAPE_01_PART1_NAG01_1,
|
||||
SUBTITLE_02_PART2_SUCCESS_1,
|
||||
SUBTITLE_02_PART2_SUCCESS_2,
|
||||
SUBTITLE_03_PART2_ENTRY_1,
|
||||
SUBTITLE_03_PART2_PLATFORM_ACTIVATED_1,
|
||||
SUBTITLE_03_PART1_ENTRY_1,
|
||||
SUBTITLE_03_PART1_ENTRY_2,
|
||||
SUBTITLE_03_PART1_SUCCESS_1,
|
||||
SUBTITLE_04_PART1_SUCCESS_1,
|
||||
SUBTITLE_04_PART1_ENTRY_1,
|
||||
SUBTITLE_05_PART1_ENTRY_1,
|
||||
SUBTITLE_05_PART1_ENTRY_2,
|
||||
SUBTITLE_05_PART1_SUCCESS_1,
|
||||
SUBTITLE_05_PART1_NAG1_1,
|
||||
SUBTITLE_05_PART1_NAG2_1,
|
||||
SUBTITLE_05_PART1_NAG3_1,
|
||||
SUBTITLE_05_PART1_NAG4_1,
|
||||
SUBTITLE_05_PART1_NAG5_1,
|
||||
SUBTITLE_06_PART1_ENTRY_1,
|
||||
SUBTITLE_06_PART1_SUCCESS_2_1,
|
||||
SUBTITLE_06_PART1_SUCCESS_1_1,
|
||||
SUBTITLE_07_PART1_ENTRY_1,
|
||||
SUBTITLE_07_PART1_ENTRY_2,
|
||||
SUBTITLE_07_PART1_ENTRY_3,
|
||||
SUBTITLE_07_PART2_ENTRY_1,
|
||||
SUBTITLE_07_PART2_SUCCESS_1,
|
||||
SUBTITLE_07_PART1_GET_DEVICE_COMPONENT_1,
|
||||
SUBTITLE_07_PART1_GET_DEVICE_COMPONENT_2,
|
||||
SUBTITLE_07_PART1_GET_DEVICE_COMPONENT_3,
|
||||
SUBTITLE_07_PART1_TRAPPED_1,
|
||||
SUBTITLE_07_PART1_TRAPPED_2,
|
||||
};
|
||||
|
||||
|
||||
#define CH_NONE 0xFF
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../savefile/savefile.h"
|
||||
#include "../font/dejavusans.h"
|
||||
#include "../audio/soundplayer.h"
|
||||
#include "../audio/subtitles.h"
|
||||
#include "../build/assets/materials/ui.h"
|
||||
#include "../build/src/audio/clips.h"
|
||||
|
||||
|
@ -12,11 +13,57 @@
|
|||
#define GAMEPLAY_HEIGHT 124
|
||||
#define GAMEPLAY_X ((SCREEN_WD - GAMEPLAY_WIDTH) / 2)
|
||||
|
||||
#define SCROLL_TICKS NUM_SUBTITLE_LANGUAGES
|
||||
#define SCROLL_INTERVALS (SCROLL_TICKS - 1)
|
||||
#define FULL_SCROLL_TIME 2.0f
|
||||
#define SCROLL_MULTIPLIER (int)(0xFFFF * FIXED_DELTA_TIME / (80 * FULL_SCROLL_TIME))
|
||||
#define SCROLL_CHUNK_SIZE (0x10000 / SCROLL_INTERVALS)
|
||||
|
||||
void audioOptionsInit(struct AudioOptions* audioOptions) {
|
||||
audioOptions->selectedItem = AudioOptionSubtitlesEnabled;
|
||||
|
||||
audioOptions->subtitlesEnabled = menuBuildCheckbox(&gDejaVuSansFont, "Closed Captions", GAMEPLAY_X + 8, GAMEPLAY_Y + 8);
|
||||
audioOptions->subtitlesEnabled.checked = (gSaveData.controls.flags & ControlSaveSubtitlesEnabled) != 0;
|
||||
if (NUM_SUBTITLE_LANGUAGES){
|
||||
audioOptions->subtitlesEnabled = menuBuildCheckbox(&gDejaVuSansFont, "Closed Captions", GAMEPLAY_X + 8, GAMEPLAY_Y + 8);
|
||||
audioOptions->subtitlesEnabled.checked = (gSaveData.controls.flags & ControlSaveSubtitlesEnabled) != 0;
|
||||
|
||||
audioOptions->subtitlesLanguageText = menuBuildText(&gDejaVuSansFont, "Captions Language: ", GAMEPLAY_X + 8, GAMEPLAY_Y + 28);
|
||||
audioOptions->subtitlesLanguageDynamicText = menuBuildText(&gDejaVuSansFont, SubtitleLanguages[gSaveData.controls.subtitleLanguage], GAMEPLAY_X + 150, GAMEPLAY_Y + 28);
|
||||
|
||||
audioOptions->subtitlesLanguage= menuBuildSlider(GAMEPLAY_X + 8, GAMEPLAY_Y + 48, 200, SCROLL_TICKS);
|
||||
audioOptions->subtitles_language_temp = (0xFFFF/SCROLL_TICKS)* gSaveData.controls.subtitleLanguage;
|
||||
audioOptions->subtitlesLanguage.value = (int)gSaveData.controls.subtitleLanguage * (0xFFFF/SCROLL_TICKS);
|
||||
}
|
||||
}
|
||||
|
||||
void audioOptionsHandleSlider(unsigned short* settingValue, float* sliderValue) {
|
||||
OSContPad* pad = controllersGetControllerData(0);
|
||||
|
||||
int newValue = (int)*settingValue + pad->stick_x * SCROLL_MULTIPLIER;
|
||||
|
||||
if (controllerGetButtonDown(0, A_BUTTON | R_JPAD)) {
|
||||
if (newValue >= 0xFFFF && controllerGetButtonDown(0, A_BUTTON)) {
|
||||
newValue = 0;
|
||||
} else {
|
||||
newValue = newValue + SCROLL_CHUNK_SIZE;
|
||||
newValue = newValue - (newValue % SCROLL_CHUNK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
if (controllerGetButtonDown(0, L_JPAD)) {
|
||||
newValue = newValue - 1;
|
||||
newValue = newValue - (newValue % SCROLL_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
if (newValue < 0) {
|
||||
newValue = 0;
|
||||
}
|
||||
|
||||
if (newValue > 0xFFFF) {
|
||||
newValue = 0xFFFF;
|
||||
}
|
||||
|
||||
*settingValue = newValue;
|
||||
*sliderValue = (float)newValue / 0xFFFF;
|
||||
}
|
||||
|
||||
enum MenuDirection audioOptionsUpdate(struct AudioOptions* audioOptions) {
|
||||
|
@ -42,6 +89,7 @@ enum MenuDirection audioOptionsUpdate(struct AudioOptions* audioOptions) {
|
|||
}
|
||||
}
|
||||
|
||||
if (NUM_SUBTITLE_LANGUAGES){
|
||||
switch (audioOptions->selectedItem) {
|
||||
case AudioOptionSubtitlesEnabled:
|
||||
if (controllerGetButtonDown(0, A_BUTTON)) {
|
||||
|
@ -54,16 +102,32 @@ enum MenuDirection audioOptionsUpdate(struct AudioOptions* audioOptions) {
|
|||
gSaveData.controls.flags &= ~ControlSaveSubtitlesEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case AudioOptionSubtitlesLanguage:
|
||||
audioOptionsHandleSlider(&audioOptions->subtitles_language_temp, &audioOptions->subtitlesLanguage.value);
|
||||
int temp = (int)((audioOptions->subtitles_language_temp * (1.0f/0xFFFF) * NUM_SUBTITLE_LANGUAGES));
|
||||
temp = (int)minf(maxf(0.0, temp), NUM_SUBTITLE_LANGUAGES-1);
|
||||
gSaveData.controls.subtitleLanguage = temp;
|
||||
audioOptions->subtitlesLanguageDynamicText = menuBuildText(&gDejaVuSansFont, SubtitleLanguages[gSaveData.controls.subtitleLanguage], GAMEPLAY_X + 150, GAMEPLAY_Y + 28);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((controllerDir & ControllerDirectionLeft || controllerGetButtonDown(0, L_TRIG) || controllerGetButtonDown(0, Z_TRIG))) {
|
||||
return MenuDirectionLeft;
|
||||
}
|
||||
|
||||
if ((controllerDir & ControllerDirectionRight || controllerGetButtonDown(0, R_TRIG))) {
|
||||
return MenuDirectionRight;
|
||||
if (audioOptions->selectedItem == AudioOptionSubtitlesLanguage){
|
||||
if ((controllerGetButtonDown(0, L_TRIG) || controllerGetButtonDown(0, Z_TRIG))) {
|
||||
return MenuDirectionLeft;
|
||||
}
|
||||
if ((controllerGetButtonDown(0, R_TRIG))) {
|
||||
return MenuDirectionRight;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (controllerDir & ControllerDirectionLeft || controllerGetButtonDown(0, L_TRIG) || controllerGetButtonDown(0, Z_TRIG)) {
|
||||
return MenuDirectionLeft;
|
||||
}
|
||||
if (controllerDir & ControllerDirectionRight || controllerGetButtonDown(0, R_TRIG)) {
|
||||
return MenuDirectionRight;
|
||||
}
|
||||
}
|
||||
|
||||
return MenuDirectionStay;
|
||||
|
@ -72,16 +136,31 @@ enum MenuDirection audioOptionsUpdate(struct AudioOptions* audioOptions) {
|
|||
void audioOptionsRender(struct AudioOptions* audioOptions, struct RenderState* renderState, struct GraphicsTask* task) {
|
||||
gSPDisplayList(renderState->dl++, ui_material_list[SOLID_ENV_INDEX]);
|
||||
|
||||
gSPDisplayList(renderState->dl++, audioOptions->subtitlesEnabled.outline);
|
||||
renderState->dl = menuCheckboxRender(&audioOptions->subtitlesEnabled, renderState->dl);
|
||||
if (NUM_SUBTITLE_LANGUAGES){
|
||||
gSPDisplayList(renderState->dl++, audioOptions->subtitlesEnabled.outline);
|
||||
renderState->dl = menuCheckboxRender(&audioOptions->subtitlesEnabled, renderState->dl);
|
||||
|
||||
gSPDisplayList(renderState->dl++, audioOptions->subtitlesLanguage.back);
|
||||
renderState->dl = menuSliderRender(&audioOptions->subtitlesLanguage, renderState->dl);
|
||||
}
|
||||
|
||||
gSPDisplayList(renderState->dl++, ui_material_revert_list[SOLID_ENV_INDEX]);
|
||||
|
||||
gSPDisplayList(renderState->dl++, ui_material_list[DEJAVU_SANS_INDEX]);
|
||||
|
||||
gDPPipeSync(renderState->dl++);
|
||||
menuSetRenderColor(renderState, audioOptions->selectedItem == AudioOptionSubtitlesEnabled, &gSelectionGray, &gColorWhite);
|
||||
gSPDisplayList(renderState->dl++, audioOptions->subtitlesEnabled.text);
|
||||
if (NUM_SUBTITLE_LANGUAGES){
|
||||
gDPPipeSync(renderState->dl++);
|
||||
menuSetRenderColor(renderState, audioOptions->selectedItem == AudioOptionSubtitlesEnabled, &gSelectionGray, &gColorWhite);
|
||||
gSPDisplayList(renderState->dl++, audioOptions->subtitlesEnabled.text);
|
||||
|
||||
gDPPipeSync(renderState->dl++);
|
||||
menuSetRenderColor(renderState, audioOptions->selectedItem == AudioOptionSubtitlesLanguage, &gSelectionGray, &gColorWhite);
|
||||
gSPDisplayList(renderState->dl++, audioOptions->subtitlesLanguageText);
|
||||
|
||||
gDPPipeSync(renderState->dl++);
|
||||
menuSetRenderColor(renderState, audioOptions->selectedItem == AudioOptionSubtitlesLanguage, &gSelectionGray, &gColorWhite);
|
||||
gSPDisplayList(renderState->dl++, audioOptions->subtitlesLanguageDynamicText);
|
||||
}
|
||||
|
||||
gSPDisplayList(renderState->dl++, ui_material_revert_list[DEJAVU_SANS_INDEX]);
|
||||
}
|
|
@ -6,12 +6,17 @@
|
|||
|
||||
enum AudioOption {
|
||||
AudioOptionSubtitlesEnabled,
|
||||
AudioOptionSubtitlesLanguage,
|
||||
|
||||
AudioOptionCount,
|
||||
};
|
||||
|
||||
struct AudioOptions {
|
||||
struct MenuCheckbox subtitlesEnabled;
|
||||
struct MenuSlider subtitlesLanguage;
|
||||
Gfx* subtitlesLanguageText;
|
||||
Gfx* subtitlesLanguageDynamicText;
|
||||
unsigned short subtitles_language_temp;
|
||||
short selectedItem;
|
||||
};
|
||||
|
||||
|
|
|
@ -461,8 +461,8 @@ void controlsMenuRender(struct ControlsMenu* controlsMenu, struct RenderState* r
|
|||
#define CONTROL_PROMPT_HEIGHT 24
|
||||
#define CONTROL_PROMPT_PADDING 6
|
||||
|
||||
#define SUBTITLE_LEFT_MARGIN 10
|
||||
#define SUBTITLE_BOTTOM_MARGIN 10
|
||||
#define SUBTITLE_SIDE_MARGIN 17
|
||||
#define SUBTITLE_BOTTOM_MARGIN 11
|
||||
#define SUBTITLE_PADDING 5
|
||||
|
||||
|
||||
|
@ -521,22 +521,22 @@ void controlsRenderSubtitle(char* message, float opacity, struct RenderState* re
|
|||
opacityAsInt = 0;
|
||||
}
|
||||
|
||||
int textPositionX = (SUBTITLE_LEFT_MARGIN + SUBTITLE_PADDING);
|
||||
int textPositionX = (SUBTITLE_SIDE_MARGIN + SUBTITLE_PADDING);
|
||||
int textPositionY = (SCREEN_HT - SUBTITLE_BOTTOM_MARGIN - SUBTITLE_PADDING) - size.y;
|
||||
|
||||
gSPDisplayList(renderState->dl++, ui_material_list[SOLID_TRANSPARENT_OVERLAY_INDEX]);
|
||||
gDPSetEnvColor(renderState->dl++, 0, 0, 0, opacityAsInt / 3);
|
||||
gDPSetEnvColor(renderState->dl++, 0, 0, 0, opacityAsInt / 2);
|
||||
gDPFillRectangle(
|
||||
renderState->dl++,
|
||||
textPositionX - CONTROL_PROMPT_PADDING,
|
||||
textPositionY - CONTROL_PROMPT_PADDING,
|
||||
textPositionX + size.x + CONTROL_PROMPT_PADDING,
|
||||
SCREEN_WD - SUBTITLE_SIDE_MARGIN,
|
||||
SCREEN_HT - SUBTITLE_BOTTOM_MARGIN
|
||||
);
|
||||
gSPDisplayList(renderState->dl++, ui_material_revert_list[SOLID_TRANSPARENT_OVERLAY_INDEX]);
|
||||
|
||||
gSPDisplayList(renderState->dl++, ui_material_list[DEJAVU_SANS_INDEX]);
|
||||
gDPSetEnvColor(renderState->dl++, 255, 60, 60, opacityAsInt);
|
||||
gDPSetEnvColor(renderState->dl++, 255, 140, 155, opacityAsInt);
|
||||
renderState->dl = fontRender(
|
||||
&gDejaVuSansFont,
|
||||
message,
|
||||
|
|
|
@ -95,6 +95,7 @@ void savefileNew() {
|
|||
gSaveData.controls.acceleration = 0x4000;
|
||||
gSaveData.controls.deadzone = 0x4000;
|
||||
gSaveData.controls.portalRenderDepth = 2;
|
||||
gSaveData.controls.subtitleLanguage = 0;
|
||||
|
||||
gSaveData.audio.soundVolume = 0xFF;
|
||||
gSaveData.audio.musicVolume = 0xFF;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "./checkpoint.h"
|
||||
#include "../controls/controller_actions.h"
|
||||
#include "../audio/subtitles.h"
|
||||
|
||||
#define SRAM_START_ADDR 0x08000000
|
||||
#define SRAM_SIZE 0x8000
|
||||
|
@ -51,6 +52,7 @@ struct ControlSaveState {
|
|||
unsigned short acceleration;
|
||||
unsigned short deadzone;
|
||||
unsigned char portalRenderDepth;
|
||||
int subtitleLanguage;
|
||||
};
|
||||
|
||||
struct AudioSettingsSaveState {
|
||||
|
|
|
@ -32,12 +32,13 @@
|
|||
#define RETICLE_HEIGHT 16
|
||||
|
||||
#define PROMPT_FADE_TIME 2.0f
|
||||
#define SUBTITLE_FADE_TIME 0.75f
|
||||
|
||||
void hudInit(struct Hud* hud) {
|
||||
hud->promptType = CutscenePromptTypeNone;
|
||||
hud->promptOpacity = 0.0f;
|
||||
hud->subtitleOpacity = 0.0f;
|
||||
|
||||
hud->chosenLanguage = gSaveData.controls.subtitleLanguage;
|
||||
hud->flags = 0;
|
||||
hud->resolvedPrompts = 0;
|
||||
hud->lastPortalIndexShot = -1;
|
||||
|
@ -59,15 +60,17 @@ void hudUpdate(struct Hud* hud) {
|
|||
}
|
||||
}
|
||||
|
||||
hud->chosenLanguage = gSaveData.controls.subtitleLanguage;
|
||||
|
||||
float targetPromptOpacity = (hud->flags & HudFlagsShowingPrompt) ? 1.0 : 0.0f;
|
||||
float targetSubtitleOpacity = (hud->flags & HudFlagsShowingSubtitle) ? 0.7: 0.0f;
|
||||
float targetSubtitleOpacity = (hud->flags & HudFlagsShowingSubtitle) ? 0.85: 0.0f;
|
||||
|
||||
if (targetPromptOpacity != hud->promptOpacity) {
|
||||
hud->promptOpacity = mathfMoveTowards(hud->promptOpacity, targetPromptOpacity, FIXED_DELTA_TIME / PROMPT_FADE_TIME);
|
||||
}
|
||||
|
||||
if (targetSubtitleOpacity != hud->subtitleOpacity) {
|
||||
hud->subtitleOpacity = mathfMoveTowards(hud->subtitleOpacity, targetSubtitleOpacity, FIXED_DELTA_TIME / PROMPT_FADE_TIME);
|
||||
hud->subtitleOpacity = mathfMoveTowards(hud->subtitleOpacity, targetSubtitleOpacity, FIXED_DELTA_TIME / SUBTITLE_FADE_TIME);
|
||||
}
|
||||
|
||||
if (targetPromptOpacity && (hud->resolvedPrompts & (1 << hud->promptType)) != 0) {
|
||||
|
@ -125,71 +128,6 @@ char* gPromptText[] = {
|
|||
"TO JUMP",
|
||||
};
|
||||
|
||||
char* gSubtitleText[] = {
|
||||
"",
|
||||
"Hello and, again, welcome to the Aperture Science \ncomputer-aided enrichment center.",
|
||||
"We hope your brief detention in the relaxation \nvault has been a pleasant one.",
|
||||
"Your specimen has been processed and we are now\nready to begin the test proper.",
|
||||
"Before we start, however, keep in mind that \nalthough fun and learning are the primary goals of\nall enrichment center activities, serious\ninjuries may occur.",
|
||||
"For your own safety and the safety of others, \nplease refrain from t-*bzzzzzt*",
|
||||
"Por favor bordón de fallar. Muchos gracias de \nfallar gra-*bzzt*",
|
||||
"Stand back. The portal will open in three, two, one.",
|
||||
"Excellent. Please proceed into the chamberlock\nafter completing each test.",
|
||||
"First, however, note the incandescent particle\nfield across the exit.",
|
||||
"This Aperture Science Material Emancipation Grid\nwill vaporize any unauthorized equipment that\npasses through it - for instance, the Aperture\nScience Weighted Storage Cube.",
|
||||
"Please place the Weighted Storage Cube on the \nFifteen Hundred Megawatt Aperture Science Heavy \nDuty Super-Colliding Super Button.",
|
||||
"Perfect. Please move quickly to the chamberlock,\nas the effects of prolonged exposure to the \nbutton are not part of this test.",
|
||||
"You're doing very well!",
|
||||
"Please be advised that a noticeable taste of blood\nis not part of any test protocol but is an \nunintended side effect of the Aperture Science \nMaterial Emancipation Grill, which may,\nin semi-rare cases, emancipate dental \nfillings, crowns, tooth enamel and teeth.",
|
||||
"Very good! You are now in possession of the \nAperture Science Handheld Portal Device.",
|
||||
"With it, you can create your own portals.",
|
||||
"These intra dimensional gates have proven to \nbe completely safe.",
|
||||
"The device, however, has not.",
|
||||
"Do not touch the operational end of the device.",
|
||||
"Do not look directly at the operational end of the\ndevice.",
|
||||
"Do not submerge the device in liquid, even partially.",
|
||||
"Most importantly, under no circumstances should \nyou-*bzzzpt*",
|
||||
"Please proceed to the chamberlock. Mind the gap.",
|
||||
"Well done! Remember: The Aperture Science Bring \nYour Daughter to Work Day is the perfect time to\nhave her tested.",
|
||||
"Welcome to test chamber four.",
|
||||
"You're doing quite well.",
|
||||
"Once again, excellent work.",
|
||||
"As part of a required test protocol, we will not \nmonitor the next test chamber. You will be \nentirely on your own.Good luck.",
|
||||
"You're not a good person. You know that, right?",
|
||||
"As part of a required test protocol, our previous\nstatement suggesting that we would not monitor \nthis chamber was an outright fabrication.",
|
||||
"Good job! As part of a required test protocol, we\nwill stop enhancing the truth in three, two, o-\n*bzzt*",
|
||||
"Warning devices are required on all mobile \nequipment. However, alarms and flashing hazard lights \nhave been found to agitate the high energy pellet\nand have therefore been disabled for \nyour safety.",
|
||||
"Good. Now use the Aperture Science Unstationary\nScaffold to reach the chamberlock.",
|
||||
"While safety is one of many Enrichment Center goals,\nthe Aperture Science High Energy Pellet, seen \nto the left of the chamber, can and has \ncaused permanent disabilities such as \nvaporization.",
|
||||
"Please be careful.",
|
||||
"Unbelievable! You, <B>Subject Name Here<B>, must be\nthe pride of <B>Subject Hometown Here<B>.",
|
||||
"Very impressive. Please note that any appearance of\ndanger is merely a device to enhance your \ntesting experience.",
|
||||
"Please note that we have added a consequence for \nfailure. Any contact with the chamber floor will \nresult in an 'unsatisfactory' mark on your \nofficial testing record followed by \ndeath. Good luck!",
|
||||
"The Enrichment Center regrets to inform you that\nthis next test is impossible.",
|
||||
"Make no attempt to solve it.",
|
||||
"Fantastic! You remained resolute and resourceful in\nan atmosphere of extreme pessimism.",
|
||||
"The Enrichment Center apologizes for this clearly \nbroken test chamber.",
|
||||
"Once again, the Enrichment Center offers its most \nsincere apologies on the occasion of this \nunsolvable test environment.",
|
||||
"Frankly, this chamber was a mistake. If we were you,\nwe would quit now.",
|
||||
"No one will blame you for giving up. In fact, quitting\nat this point is a perfectly reasonable \nresponse.",
|
||||
"Quit now and cake will be served immediately.",
|
||||
"Hello again. To reiterate our previous warning: This\ntest (garbled) -ard momentum.",
|
||||
"Momentum, a function of mass and velocity, is\nconserved between portals. In layman's terms: speedy\nthing goes in, speedy thing comes out.",
|
||||
"Spectacular. You appear to understand how a portal\naffects forward momentum, or to be more precise,\nhow it does not.",
|
||||
"The Enrichment Center promises to always provide a\nsafe testing environment.",
|
||||
"In dangerous testing environments, the Enrichment \nCenter promises to always provide useful advice.",
|
||||
"For instance, the floor here will kill you - try to \navoid it.",
|
||||
"Get ot ydaer f-f-fling yourself. F-Fling into sp\n-*bzzt*",
|
||||
"Weeeeeeeeeeeeeeeeeeeeee-*bzzt*",
|
||||
"The device has been modified so that it can now \nmanufacture two linked portals at once.",
|
||||
"As part of an optional test protocol, we are pleased\nto present an amusing fact:",
|
||||
"The device is now more valuable than the organs \nand combined incomes of everyone in <B>Subject \nHometown Here<B>.",
|
||||
"Through no fault of the Enrichment Center, you \nhave managed to trap yourself in this room.",
|
||||
"An escape hatch will open in three, two, one."
|
||||
};
|
||||
|
||||
|
||||
|
||||
void hudShowActionPrompt(struct Hud* hud, enum CutscenePromptType promptType) {
|
||||
if (promptType == CutscenePromptTypeNone) {
|
||||
hud->flags &= ~HudFlagsShowingPrompt;
|
||||
|
@ -200,8 +138,8 @@ void hudShowActionPrompt(struct Hud* hud, enum CutscenePromptType promptType) {
|
|||
hud->promptType = promptType;
|
||||
}
|
||||
|
||||
void hudShowSubtitle(struct Hud* hud, enum CutsceneSubtitleType subtitleType) {
|
||||
if (subtitleType == CutsceneSubtitleTypeNone) {
|
||||
void hudShowSubtitle(struct Hud* hud, enum SubtitleKey subtitleType) {
|
||||
if (subtitleType == SubtitleKeyNone) {
|
||||
hud->flags &= ~HudFlagsShowingSubtitle;
|
||||
return;
|
||||
}
|
||||
|
@ -334,6 +272,6 @@ void hudRender(struct Hud* hud, struct Player* player, struct RenderState* rende
|
|||
}
|
||||
|
||||
if (hud->subtitleOpacity > 0.0f && gSaveData.controls.flags & ControlSaveSubtitlesEnabled) {
|
||||
controlsRenderSubtitle(gSubtitleText[hud->subtitleType], hud->subtitleOpacity, renderState);
|
||||
controlsRenderSubtitle(SubtitleLanguageValues[hud->chosenLanguage][hud->subtitleType], hud->subtitleOpacity, renderState);
|
||||
}
|
||||
}
|
|
@ -4,6 +4,9 @@
|
|||
#include "../graphics/renderstate.h"
|
||||
#include "../player/player.h"
|
||||
#include "../controls/controller_actions.h"
|
||||
#include "../audio/subtitles.h"
|
||||
|
||||
|
||||
|
||||
#define INTRO_BLACK_TIME 3.0f
|
||||
#define INTRO_FADE_TIME 1.0f
|
||||
|
@ -17,8 +20,9 @@ enum HudFlags {
|
|||
};
|
||||
|
||||
struct Hud {
|
||||
int chosenLanguage;
|
||||
enum CutscenePromptType promptType;
|
||||
enum CutsceneSubtitleType subtitleType;
|
||||
enum SubtitleKey subtitleType;
|
||||
float promptOpacity;
|
||||
float subtitleOpacity;
|
||||
|
||||
|
@ -38,7 +42,7 @@ void hudUpdatePortalIndicators(struct Hud* hud, struct Ray* raycastRay, struct
|
|||
void hudPortalFired(struct Hud* hud, int index);
|
||||
void hudShowActionPrompt(struct Hud* hud, enum CutscenePromptType promptType);
|
||||
void hudResolvePrompt(struct Hud* hud, enum CutscenePromptType promptType);
|
||||
void hudShowSubtitle(struct Hud* hud, enum CutsceneSubtitleType subtitleType);
|
||||
void hudShowSubtitle(struct Hud* hud, enum SubtitleKey subtitleType);
|
||||
void hudResolveSubtitle(struct Hud* hud);
|
||||
|
||||
void hudRender(struct Hud* hud, struct Player* player, struct RenderState* renderState);
|
||||
|
|
|
@ -171,7 +171,7 @@ void securityCamerasCheckPortal(struct SecurityCamera* securityCameras, int came
|
|||
|
||||
if (!cutsceneRunnerIsChannelPlaying(CH_GLADOS)) {
|
||||
short clipIndex = randomInRange(0, sizeof(gCameraDestroyClips) / sizeof(*gCameraDestroyClips));
|
||||
cutsceneQueueSoundInChannel(gCameraDestroyClips[clipIndex], 1.0f, CH_GLADOS, CutsceneSubtitleTypeNone);
|
||||
cutsceneQueueSoundInChannel(gCameraDestroyClips[clipIndex], 1.0f, CH_GLADOS, SubtitleKeyNone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "../physics/collision_object.h"
|
||||
#include "../levels/level_definition.h"
|
||||
#include "../sk64/skelatool_armature.h"
|
||||
#include "../audio/subtitles.h"
|
||||
|
||||
struct SecurityCamera {
|
||||
struct CollisionObject collisionObject;
|
||||
|
|
178
tools/level_scripts/subtitle_generate.py
Normal file
178
tools/level_scripts/subtitle_generate.py
Normal file
|
@ -0,0 +1,178 @@
|
|||
#!/usr/bin/env python3
|
||||
import os
|
||||
import re
|
||||
|
||||
def get_caption_keys_values_language(lines):
|
||||
language = "English"
|
||||
keys = []
|
||||
values = []
|
||||
|
||||
found_language = False
|
||||
found_tokens = False
|
||||
for line in lines:
|
||||
if not found_language:
|
||||
if not '"Language"' in line:
|
||||
continue
|
||||
found_language = True
|
||||
line = line.replace('"', "")
|
||||
key, val = line.split()
|
||||
language = val
|
||||
continue
|
||||
if not found_tokens:
|
||||
if not '"Tokens"' in line:
|
||||
continue
|
||||
found_tokens = True
|
||||
continue
|
||||
if ("{" in line) or ("}" in line) :
|
||||
continue
|
||||
keyval= line.split('"\t"')
|
||||
if len(keyval) != 2:
|
||||
keyval= line.split('" "')
|
||||
if len(keyval) != 2:
|
||||
continue
|
||||
if "[english]" in keyval[0]:
|
||||
continue
|
||||
key = keyval[0].replace('"', "").replace(".", "_").replace("-", "_").replace('\\', "_").replace('#', "").upper()
|
||||
val = keyval[1].replace('"', "").replace("\n", "").replace("\\", "")
|
||||
val = re.sub(r'\<clr.+\>','',val)
|
||||
val = re.sub(r'\<norepeat.+\>','',val)
|
||||
val = val.replace("<sfx>", "")
|
||||
val = re.sub(r'\<len:.+\>','',val)
|
||||
val = val.replace("<len>", "")
|
||||
newval = ""
|
||||
last_space = 0
|
||||
addition = 0
|
||||
for i,ch in enumerate(val):
|
||||
if (i%40 == 0) and (i != 0):
|
||||
newval = newval[:last_space+addition] + '\\n' + newval[last_space+addition+1:]
|
||||
addition += 1
|
||||
newval = newval + ch
|
||||
else:
|
||||
if ch == " ":
|
||||
last_space = i
|
||||
newval = newval + ch
|
||||
keys.append(key)
|
||||
values.append(newval)
|
||||
|
||||
return keys, values, language
|
||||
|
||||
def make_overall_subtitles_header(all_header_lines, languages_list):
|
||||
header_lines = []
|
||||
header_lines.append("#ifndef __SUBTITLES_H__\n")
|
||||
header_lines.append("#define __SUBTITLES_H__\n")
|
||||
header_lines.append("\n")
|
||||
header_lines.append(f"#define NUM_SUBTITLE_LANGUAGES {len(languages_list)}\n")
|
||||
header_lines.append("\n")
|
||||
header_lines.append("extern char* SubtitleLanguages[];\n")
|
||||
header_lines.append("extern char* SubtitleLanguageValues[][508];\n")
|
||||
header_lines.append("\n")
|
||||
if len(languages_list) > 0:
|
||||
header_lines.extend(all_header_lines)
|
||||
else:
|
||||
header_lines.append(f"enum SubtitleKey\n")
|
||||
header_lines.append("{\n")
|
||||
header_lines.append(' SubtitleKeyNone,\n')
|
||||
header_lines.append("};\n")
|
||||
header_lines.append("\n")
|
||||
|
||||
header_lines.append("#endif")
|
||||
|
||||
with open("src/audio/subtitles.h", "w") as f:
|
||||
f.writelines(header_lines)
|
||||
|
||||
def make_SubtitleKey_headerlines(keys):
|
||||
header_lines = []
|
||||
header_lines.append("\n")
|
||||
header_lines.append(f"enum SubtitleKey\n")
|
||||
header_lines.append("{\n")
|
||||
header_lines.append(' SubtitleKeyNone,\n')
|
||||
for key in keys:
|
||||
header_lines.append(f' {key},\n')
|
||||
header_lines.append("};\n")
|
||||
header_lines.append("\n")
|
||||
return header_lines
|
||||
|
||||
def make_SubtitleLanguageValues(values_list):
|
||||
sourcefile_lines = []
|
||||
if len(values_list) <= 0:
|
||||
sourcefile_lines.append("\n")
|
||||
sourcefile_lines.append("char * SubtitleLanguageValues[][508] =\n")
|
||||
sourcefile_lines.append("{\n")
|
||||
sourcefile_lines.append(" {\n")
|
||||
for val in range(508):
|
||||
sourcefile_lines.append(f' "",\n')
|
||||
sourcefile_lines.append(" },\n")
|
||||
sourcefile_lines.append("};\n")
|
||||
sourcefile_lines.append("\n")
|
||||
return sourcefile_lines
|
||||
sourcefile_lines.append("\n")
|
||||
sourcefile_lines.append("char * SubtitleLanguageValues[][508] =\n")
|
||||
sourcefile_lines.append("{\n")
|
||||
for lang in values_list:
|
||||
sourcefile_lines.append(" {\n")
|
||||
sourcefile_lines.append(' "",\n')
|
||||
for value in lang:
|
||||
sourcefile_lines.append(f' "{value}",\n')
|
||||
sourcefile_lines.append(" },\n")
|
||||
sourcefile_lines.append("};\n")
|
||||
sourcefile_lines.append("\n")
|
||||
return sourcefile_lines
|
||||
|
||||
def make_overall_subtitles_sourcefile(other_sourcefile_lines, language_list):
|
||||
sourcefile_lines = []
|
||||
sourcefile_lines.append('#include "subtitles.h"\n')
|
||||
|
||||
sourcefile_lines.append("\n")
|
||||
sourcefile_lines.append("char* SubtitleLanguages[] =\n")
|
||||
sourcefile_lines.append("{\n")
|
||||
if len(language_list) <= 0:
|
||||
sourcefile_lines.append(f' "",\n')
|
||||
else:
|
||||
for language in language_list:
|
||||
sourcefile_lines.append(f' "{language.upper()}",\n')
|
||||
sourcefile_lines.append("};\n")
|
||||
sourcefile_lines.append("\n")
|
||||
sourcefile_lines.extend(other_sourcefile_lines)
|
||||
|
||||
with open("src/audio/subtitles.c", "w") as f:
|
||||
f.writelines(sourcefile_lines)
|
||||
|
||||
def process_all_closecaption_files(dir):
|
||||
values_list = []
|
||||
header_lines = []
|
||||
sourcefile_lines = []
|
||||
language_list = []
|
||||
SubtitleKey_generated = False
|
||||
for filename in os.listdir(dir):
|
||||
if "closecaption_" not in filename:
|
||||
continue
|
||||
try:
|
||||
filepath = os.path.join(dir, filename)
|
||||
lines = []
|
||||
|
||||
with open(filepath, "r", encoding='cp1252') as f:
|
||||
lines = f.readlines()
|
||||
|
||||
new_lines = []
|
||||
for line in lines:
|
||||
line = line.replace("\x00", "")
|
||||
if "\n" != line:
|
||||
new_lines.append(line)
|
||||
|
||||
k,v,l = get_caption_keys_values_language(new_lines)
|
||||
values_list.append(v)
|
||||
if not SubtitleKey_generated:
|
||||
header_lines = make_SubtitleKey_headerlines(k)
|
||||
SubtitleKey_generated = True
|
||||
language_list.append(l)
|
||||
print(filename, " - PASSED")
|
||||
except:
|
||||
print(filename, " - FAILED")
|
||||
continue
|
||||
sourcefile_lines = make_SubtitleLanguageValues(values_list)
|
||||
make_overall_subtitles_header(header_lines, language_list)
|
||||
make_overall_subtitles_sourcefile(sourcefile_lines, language_list)
|
||||
|
||||
|
||||
|
||||
process_all_closecaption_files("resource/")
|
Loading…
Reference in a new issue