Generate cutscene yaml and operators yaml

This commit is contained in:
James Lambert 2023-09-02 17:59:01 -06:00
parent e83a23325e
commit 6395378285
16 changed files with 539 additions and 2 deletions

View file

@ -124,6 +124,7 @@ That will generate the rom at `/build/portal64.z64`
<br />
## Current New Feature TODO List
- [ ] rumble pak support?
- [ ] Change default controls
- [ ] Add puzzle element connections and additional signs
- [ ] Use a much nearer clipping plane when rendering the portal gun

View file

@ -0,0 +1,43 @@
operators:
[]
cutscenes:
START_SECOND_ROOM:
- start_cutscene SECOND_ROOM_INSTRUCTIONS
- open_portal stationary_portal 1
- label portal_loop
- open_portal button_room 0
- delay 5 1
- open_portal door_room 0
- delay 5 2
- open_portal cube_room 0
- delay 5 0
- goto portal_loop
SECOND_ROOM_INSTRUCTIONS:
- q_sound SOUNDS_00_PART2_ENTRY_1 CH_GLADOS
- wait_for_signal success_1
- q_sound SOUNDS_00_PART2_SUCCESS_1 CH_GLADOS
INTRO:
- play_animation player player_intro
- play_animation glass_cover_0 glass_cover_0_open
- play_animation glass_cover_1 glass_cover_1_open
- delay 23
- set_signal room_divider
- delay 5 21.34
- q_sound SOUNDS_00_PART1_ENTRY_1 CH_GLADOS
- q_sound SOUNDS_00_PART1_ENTRY_2 CH_GLADOS
- q_sound SOUNDS_00_PART1_ENTRY_3 CH_GLADOS
- q_sound SOUNDS_00_PART1_ENTRY_4 CH_GLADOS
- q_sound SOUNDS_00_PART1_ENTRY_5 CH_GLADOS
- q_sound SOUNDS_00_PART1_ENTRY_6 CH_GLADOS
- q_sound SOUNDS_00_PART1_ENTRY_7 CH_GLADOS
- wait_for_channel CH_GLADOS
- open_portal portal_room 0
- open_portal room_exit 1
FIRST_PUZZLE:
- clear_signal room_divider
- delay 3
- set_signal cube_dropper
- wait_for_signal success
- q_sound SOUNDS_00_PART1_SUCCESS_1 CH_GLADOS
- q_sound SOUNDS_00_PART1_SUCCESS_2 CH_GLADOS
- q_sound SOUNDS_00_PART1_SUCCESS_3 CH_GLADOS

View file

@ -0,0 +1,49 @@
operators:
[]
cutscenes:
GET_GUN:
- set_signal room_0_exit
- "hide_pedestal "
- stop_cutscene portal_loop
- q_sound 01_PART1_GET_PORTAL_GUN_1 CH_GLADOS
- q_sound 01_PART1_GET_PORTAL_GUN_2 CH_GLADOS
- q_sound 01_PART1_GET_PORTAL_GUN_3 CH_GLADOS
- q_sound 01_PART1_GET_PORTAL_GUN_4 CH_GLADOS
- q_sound 01_PART1_GET_PORTAL_GUN_5 CH_GLADOS
- q_sound 01_PART1_GET_PORTAL_GUN_6 CH_GLADOS
- q_sound 01_PART1_GET_PORTAL_GUN_7 CH_GLADOS
- q_sound 01_PART1_GET_PORTAL_GUN_8 CH_GLADOS
MIND_THE_GAP:
- open_portal portal_gap 0
- q_sound SOUNDS_01_PART2_ENTRY_1 CH_GLADOS
START:
- delay 1
- start_cutscene portal_loop
- set_signal FIRST_ELEVATOR
FINISH_03:
- q_sound SOUNDS_01_PART2_SUCCESS_1 CH_GLADOS
INTRO_CUTSCENE:
- q_sound SOUNDS_01_PART1_ENTRY_1 CH_GLADOS
- q_sound SOUNDS_01_PART1_ENTRY_2 CH_GLADOS
- wait_for_channel CH_GLADOS
- set_signal room_0_entrance
portal_loop:
- open_portal portal_exit 0
- label loop_start
- open_portal portal_0 1
- delay 3
- point_pedestal portal_1
- delay 4
- open_portal portal_1 1
- delay 3 2
- point_pedestal portal_2
- delay 4 2
- open_portal portal_2 1
- delay 3 3
- point_pedestal portal_3
- delay 4 3
- open_portal portal_3 1
- delay 3 4
- point_pedestal portal_0
- delay 4 4
- goto loop_start

View file

@ -0,0 +1,20 @@
cutscenes:
DROP_CUBE:
- set_signal cube_dropper
ENTER_BUTTON_ROOM:
- open_portal portal_1
ENTER_SMALL_ROOM:
- set_signal double_door
- open_portal portal_2 0
- q_sound SOUNDS_02_PART2_SUCCESS_1 CH_GLADOS
- q_sound SOUNDS_02_PART2_SUCCESS_2 CH_GLADOS
INTRO:
- q_sound SOUNDS_02_PART1_ENTRY_1 CH_GLADOS
- wait_for_channel CH_GLADOS
- open_portal portal_0 0
- q_sound SOUNDS_02_PART1_ENTRY_2 CH_GLADOS
- wait_for_signal success
- q_sound SOUNDS_02_PART1_SUCCESS_1 CH_GLADOS
- q_sound SOUNDS_02_PART1_SUCCESS_2 CH_GLADOS
operators:
- double_door = exit_2_0 and exit_2_1

View file

@ -0,0 +1,36 @@
operators:
- not_on_piston = not on_piston
cutscenes:
BALL_2:
- delay 3
- set_signal launch_ball_2
- wait_for_signal horizontal_activiate
- label horizontal_loop
- play_animation horizontal horizontal_slide
- wait_for_animation horizontal
- goto horizontal_loop
INTRO_2:
- save_checkpoint 0.001
- open_portal ground_portal_2
- start_cutscene BALL_2
- q_sound SOUNDS_03_PART2_ENTRY_1 CH_GLADOS
- wait_for_signal horizontal_activiate 2
- q_sound 03_PART2_PLATFORM_ACTIVATED_1 CH_GLADOS
INTRO:
- save_checkpoint 0
- open_portal ground_portal 0
- q_sound SOUNDS_03_PART1_ENTRY_1 CH_GLADOS
- q_sound SOUNDS_03_PART1_ENTRY_2 CH_GLADOS
- wait_for_signal exit_activate 2
- q_sound SOUNDS_03_PART1_SUCCESS_1 CH_GLADOS
START_BALL:
- set_signal launch_ball
- wait_for_signal exit_activate
- label piston_loop
- play_animation exit_piston piston_move_down
- wait_for_animation exit_piston 0
- wait_for_signal on_piston
- play_animation exit_piston piston_move_up
- wait_for_animation exit_piston
- wait_for_signal not_on_piston
- goto piston_loop

View file

@ -0,0 +1,19 @@
cutscenes:
SUCCESS:
- q_sound SOUNDS_04_PART1_SUCCESS_1 CH_GLADOS
INTRO_CUTSCENE:
- q_sound SOUNDS_04_PART1_ENTRY_1 CH_GLADOS
DROWN_PLAYER:
- kill_player water
OPEN_PORTAL:
- "save_checkpoint "
- delay 1
- open_portal stationary_portal 0
- set_signal launch_ball
- wait_for_signal exit_activate
- label horizontal_loop
- play_animation horizontal horizontal_slide
- wait_for_animation horizontal
- goto horizontal_loop
operators:
[]

View file

@ -0,0 +1,23 @@
operators:
[]
cutscenes:
INTRO_CUTSCENE:
- set_signal cube_dropper
- open_portal portal_0 0
- q_sound SOUNDS_05_PART1_ENTRY_1 CH_GLADOS
- q_sound SOUNDS_05_PART1_ENTRY_2 CH_GLADOS
- start_cutscene NAG
- wait_for_signal success
- stop_cutscene NAG
- q_sound SOUNDS_05_PART1_SUCCESS_1 CH_GLADOS
NAG:
- delay 28
- q_sound SOUNDS_05_PART1_NAG1_1 CH_GLADOS
- delay 20
- q_sound SOUNDS_05_PART1_NAG2_1 CH_GLADOS
- delay 25
- q_sound SOUNDS_05_PART1_NAG3_1 CH_GLADOS
- delay 25.001
- q_sound SOUNDS_05_PART1_NAG4_1 CH_GLADOS
- delay 26
- q_sound SOUNDS_05_PART1_NAG5_1 CH_GLADOS

View file

@ -0,0 +1,27 @@
operators:
[]
cutscenes:
THIRD_ROOM:
- clear_signal room_1_exit
- open_portal third_room_portal 0
- close_portal 1 room2
- 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
- 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
- play_animation piston_top piston_top_1
FIRST_SUCCESS:
- q_sound SOUNDS_06_PART1_SUCCESS_1_1 CH_GLADOS
SECOND_ROOM:
- close_portal 0
- close_portal 1
- clear_signal room_0_exit
- delay 3
- set_signal room_1_exit
- open_portal second_room_portal 0

View file

@ -0,0 +1,72 @@
cutscenes:
platform_ferry:
- wait_for_signal move_platform
- delay 1.5 pre_slide
- label anim_loop_start
- play_animation horizontal slide 1
- wait_for_animation horizontal
- wait_for_signal move_to_gun
- play_animation horizontal slide -1
- wait_for_signal not_move_to_gun
- goto anim_loop_start
platform_loop:
- label anim_platform_loop_start
- play_animation horizontal slide 1 loop
- wait_for_animation horizontal loop_out
- delay 3 anim_pause
- play_animation horizontal slide -1 slide_
- wait_for_animation horizontal loop_in
- delay 3 anim_pause_end
- goto anim_platform_loop_start
DROWN_PLAYER:
- kill_player water
START:
- delay 1
- start_cutscene portal_loop
- start_cutscene platform_ferry
- set_signal launch_ball
- q_sound 07_PART1_ENTRY_1 CH_GLADOS
- q_sound 07_PART1_ENTRY_2 CH_GLADOS
- q_sound 07_PART1_ENTRY_3 CH_GLADOS
TILT:
- delay 4
- set_signal cube_dropper
- play_animation tilt tilt
START_1:
- q_sound 07_PART2_ENTRY_1 CH_GLADOS
- wait_for_signal weeeee
- q_sound 07_PART2_SUCCESS_1 CH_GLADOS
portal_loop:
- label loop_start
- open_portal portal_0 0
- delay 3.001
- point_pedestal portal_1
- delay 4.001
- open_portal portal_1 0
- delay 3 2
- point_pedestal portal_2
- delay 4 2
- open_portal portal_2 0
- delay 3 3
- point_pedestal portal_3
- delay 4 3
- point_pedestal portal_0
- delay 4 4
- goto loop_start
GET_GUN:
- "hide_pedestal "
- stop_cutscene portal_loop
- stop_cutscene platform_ferry
- start_cutscene platform_loop
- close_portal 0
- q_sound 07_PART1_GET_DEVICE_COMPONENT_1 CH_GLADOS
- q_sound 07_PART1_GET_DEVICE_COMPONENT_2 CH_GLADOS
- q_sound 07_PART1_GET_DEVICE_COMPONENT_3 CH_GLADOS
- wait_for_signal trapped
- q_sound 07_PART1_TRAPPED_1 CH_GLADOS
- q_sound 07_PART1_TRAPPED_2 CH_GLADOS
- wait_for_channel CH_GLADOS
- set_signal trap_door
operators:
- weeeee = exit_1 and flying
- not_move_to_gun = not move_to_gun

View file

@ -8,6 +8,7 @@
#include "LuaMesh.h"
#include "LuaDisplayListSettings.h"
#include "LuaBasicTypes.h"
#include "LuaYaml.h"
#include <lua5.4/lua.hpp>
#include <iostream>
@ -82,6 +83,7 @@ void generateFromLuaScript(
lua_State *L = luaL_newstate();
luaL_openlibs(L);
generateLuaTransform(L);
generateLuaYaml(L);
populateLuaMesh(L, scene, fileDefinition, settings);
lua_getglobal(L, "package");

View file

@ -0,0 +1,176 @@
#include "LuaYaml.h"
#include "yaml-cpp/yaml.h"
#include <stdlib.h>
#include <sstream>
#include "./LuaUtils.h"
void toLua(lua_State* L, const YAML::Node& node) {
if (!node.IsDefined() || node.IsNull()) {
lua_pushnil(L);
return;
}
if (node.IsSequence()) {
lua_createtable(L, node.size(), 0);
for (unsigned i = 0; i < node.size(); ++i) {
toLua(L, node[i]);
lua_seti(L, -2, i + 1);
}
return;
}
if (node.IsMap()) {
lua_createtable(L, 0, node.size());
for (auto it = node.begin(); it != node.end(); ++it) {
std::string name = it->first.as<std::string>();
toLua(L, node[name]);
lua_setfield(L, -2, name.c_str());
}
return;
}
if (node.IsScalar()) {
std::string asString = node.as<std::string>();
if (asString == "true") {
lua_pushboolean(L, true);
return;
}
if (asString == "false") {
lua_pushboolean(L, false);
return;
}
std::istringstream asStream(asString);
lua_Integer asInt;
if (!(asStream >> asInt).fail()) {
lua_pushinteger(L, asInt);
return;
}
asStream = std::istringstream(asString);
lua_Number asDouble;
if (!(asStream >> asDouble).fail()) {
lua_pushnumber(L, asDouble);
return;
}
lua_pushstring(L, asString.c_str());
return;
}
lua_pushnil(L);
}
bool luaIsSequence(lua_State* L, int idx) {
if (idx < 0) {
idx = lua_gettop(L) + idx + 1;
}
lua_pushnil(L);
if (!lua_next(L, idx)) {
// empty sequence
return true;
}
// first key is not a number
if (!lua_isnumber(L, -2)) {
lua_pop(L, 2);
return false;
}
lua_pop(L, 2);
// check iteration after end of sequence
lua_len(L, idx);
if (lua_next(L, idx)) {
// has additional key value pairs
lua_pop(L, 2);
return false;
}
return true;
}
void fromLua(lua_State* L, YAML::Node& node) {
switch (lua_type(L, -1))
{
case LUA_TBOOLEAN:
node = YAML::Node(lua_toboolean(L, -1) ? true : false);
break;
case LUA_TNUMBER:
node = YAML::Node(lua_tonumber(L, -1));
break;
case LUA_TSTRING:
node = YAML::Node(lua_tostring(L, -1));
break;
case LUA_TTABLE:
if (luaIsSequence(L, -1)) {
node = YAML::Node(YAML::NodeType::Sequence);
lua_pushnil(L);
while (lua_next(L, -2)) {
YAML::Node element;
fromLua(L, element);
node.push_back(element);
}
} else {
node = YAML::Node(YAML::NodeType::Map);
lua_pushnil(L);
while (lua_next(L, -2)) {
YAML::Node element;
fromLua(L, element);
node[lua_tostring(L, -1)] = element;
}
}
break;
default:
node = YAML::Node(YAML::NodeType::Null);
break;
}
lua_pop(L, 1);
}
int luaYamlParse(lua_State* L) {
const char* value = luaL_checkstring(L, 1);
YAML::Node doc = YAML::Load(value);
toLua(L, doc);
return 1;
}
int luaYamlStringify(lua_State* L) {
lua_settop(L, 1);
YAML::Node doc;
fromLua(L, doc);
std::string result = YAML::Dump(doc);
lua_pushstring(L, result.c_str());
return 1;
}
int buildYamlModule(lua_State* L) {
lua_newtable(L);
lua_pushcfunction(L, luaYamlParse);
lua_setfield(L, -2, "parse");
lua_pushcfunction(L, luaYamlStringify);
lua_setfield(L, -2, "stringify");
return 1;
}
void generateLuaYaml(lua_State* L) {
lua_pushcfunction(L, buildYamlModule);
luaSetModuleLoader(L, "yaml");
}

View file

@ -0,0 +1,8 @@
#ifndef __LUA_YAML_H__
#define __LUA_YAML_H__
#include <lua5.4/lua.hpp>
void generateLuaYaml(lua_State* L);
#endif

View file

@ -10,6 +10,14 @@ local entities = require('tools.level_scripts.entities')
local signals = require('tools.level_scripts.signals')
local animation = require('tools.level_scripts.animation')
local dynamic_collision = require('tools.level_scripts.dynamic_collision_export')
local yaml_loader = require('tools.level_scripts.yaml_loader')
local jsonFile = {
operators = signals.operator_json,
cutscenes = trigger.cutscene_json,
}
yaml_loader.dump_json(jsonFile)
sk_definition_writer.add_definition("level", "struct LevelDefinition", "_geo", {
collisionQuads = sk_definition_writer.reference_to(collision_export.collision_objects, 1),

View file

@ -102,10 +102,28 @@ local function generate_operator_data(operator)
}
end
local function format_operation(operation)
local result = operation.output .. ' = '
if operation.type == 'SignalOperatorTypeNot' then
return result .. 'not ' .. operation.input[1]
elseif operation.type == 'SignalOperatorTypeAnd' then
return result .. table.concat(operation.input, ' and ')
elseif operation.type == 'SignalOperatorTypeOr' then
return result .. table.concat(operation.input, ' or ')
end
return result;
end
local operators = {}
local operator_json = {}
for _, operation in pairs(ordered_operators) do
table.insert(operators, generate_operator_data(operation))
table.insert(operator_json, format_operation(operation))
end
sk_definition_writer.add_definition('signal_operations', 'struct SignalOperator[]', '_geo', operators)
@ -113,4 +131,5 @@ sk_definition_writer.add_definition('signal_operations', 'struct SignalOperator[
return {
signal_index_for_name = signal_index_for_name,
operators = operators,
operator_json = operator_json,
}

View file

@ -289,6 +289,8 @@ local function generate_cutscenes()
local cutscenes_result = {}
local cutscene_data = {}
local cutscene_json = {}
for _, cutscene in pairs(cutscenes) do
local first_step = cutscene.steps[1]
local other_steps = {table.unpack(cutscene.steps, 2)}
@ -297,6 +299,12 @@ local function generate_cutscenes()
return distance_from_start(first_step, a) < distance_from_start(first_step, b)
end)
local string_steps = {}
for step_index, step in pairs(other_steps) do
table.insert(string_steps, step.command .. ' ' .. table.concat(step.args, ' '))
end
local label_locations = find_label_locations(other_steps)
local steps = {}
@ -305,6 +313,8 @@ local function generate_cutscenes()
table.insert(steps, generate_cutscene_step(cutscene.name, step, step_index, label_locations, cutscenes))
end
cutscene_json[cutscene.name] = string_steps
sk_definition_writer.add_definition(cutscene.name .. '_steps', 'struct CutsceneStep[]', '_geo', steps)
table.insert(cutscenes_result, {
@ -319,7 +329,7 @@ local function generate_cutscenes()
})
end
return cutscenes_result, cutscene_data
return cutscenes_result, cutscene_data, cutscene_json
end
local function generate_triggers(cutscenes)
@ -342,7 +352,7 @@ local function generate_triggers(cutscenes)
return result
end
local cutscenes, cutscene_data = generate_cutscenes()
local cutscenes, cutscene_data, cutscene_json = generate_cutscenes()
local triggers = generate_triggers(cutscenes)
sk_definition_writer.add_definition("triggers", "struct Trigger[]", "_geo", triggers)
@ -355,6 +365,7 @@ end
return {
triggers = triggers,
cutscene_data = cutscene_data,
cutscene_json = cutscene_json,
location_data = location_data,
find_location_index = find_location_index,
find_cutscene_index = find_cutscene_index,

View file

@ -0,0 +1,23 @@
local yaml = require('yaml')
local sk_input = require('sk_input')
local file_location = string.sub(sk_input.input_filename, 7, -4) .. 'yaml'
local input_file = io.open(file_location, 'r')
local json_contents = yaml.parse(input_file:read('a'))
input_file:close()
local function dump_json(value)
local file_contents = yaml.stringify(value)
print(file_contents)
print(file_location)
local file = io.open(file_location, 'w');
file:write(file_contents)
file:close()
end
return {
dump_json = dump_json,
json_contents = json_contents,
}