From c4868130ebd75745cc26f6bb087730db9989d3fa Mon Sep 17 00:00:00 2001 From: Bram Dingelstad Date: Sun, 21 Nov 2021 23:10:48 +0100 Subject: [PATCH] did a bunch things to finalize --- Dialogue.tscn | 2 + addons/Wol/Wol.gd | 25 ++++-- addons/Wol/core/FunctionInfo.gd | 17 ++-- addons/Wol/core/StandardLibrary.gd | 21 ++--- addons/Wol/core/VirtualMachine.gd | 68 ++++++++------ addons/Wol/core/compiler/compiler.gd | 24 +++-- addons/Wol/core/compiler/lexer.gd | 99 +++++++++++++++------ addons/Wol/core/compiler/parser.gd | 128 ++++++++++++++++++++++++--- addons/Wol/core/constants.gd | 12 ++- addons/Wol/core/library.gd | 1 + addons/Wol/core/program.gd | 12 +++ addons/Wol/core/value.gd | 5 +- dialogue.yarn | 51 ++++++++--- project.godot | 18 ---- 14 files changed, 345 insertions(+), 138 deletions(-) diff --git a/Dialogue.tscn b/Dialogue.tscn index 66c83bb..964a0cd 100644 --- a/Dialogue.tscn +++ b/Dialogue.tscn @@ -16,6 +16,8 @@ __meta__ = { script = ExtResource( 2 ) path = "res://dialogue.yarn" auto_start = true +variable_storage = { +} [node name="RichTextLabel" type="RichTextLabel" parent="."] anchor_right = 1.0 diff --git a/addons/Wol/Wol.gd b/addons/Wol/Wol.gd index f049974..8aa3946 100644 --- a/addons/Wol/Wol.gd +++ b/addons/Wol/Wol.gd @@ -17,15 +17,17 @@ signal started signal finished export(String, FILE, '*.wol,*.yarn') var path setget set_path -export(String) var start_node = 'Start' -export(bool) var auto_start = false + +export var starting_node = 'Start' +export var auto_start = false export var auto_show_options = true +export var auto_substitute = true export(Dictionary) var variable_storage = {} const Constants = preload('res://addons/Wol/core/Constants.gd') -const WolCompiler = preload('res://addons/Wol/core/compiler/Compiler.gd') -const WolLibrary = preload('res://addons/Wol/core/Library.gd') +const Compiler = preload('res://addons/Wol/core/compiler/Compiler.gd') +const Library = preload('res://addons/Wol/core/Library.gd') const VirtualMachine = preload('res://addons/Wol/core/VirtualMachine.gd') const StandardLibrary = preload('res://addons/Wol/core/StandardLibrary.gd') @@ -35,10 +37,11 @@ func _ready(): if Engine.editor_hint: return - var libraries = WolLibrary.new() - libraries.import_library(StandardLibrary.new()) + var libraries = Library.new() virtual_machine = VirtualMachine.new(self, libraries) + libraries.import_library(StandardLibrary.new()) + set_path(path) if auto_start: @@ -48,10 +51,16 @@ func set_path(_path): path = _path if not Engine.editor_hint and virtual_machine: - var compiler = WolCompiler.new(path) + var compiler = Compiler.new(path) virtual_machine.program = compiler.compile() func _on_line(line): + if auto_substitute: + var index = 0 + for substitute in line.substitutions: + line.text = line.text.replace('{%d}' % index, substitute) + index += 1 + call_deferred('emit_signal', 'line', line) if auto_show_options \ and virtual_machine.get_next_instruction().operation == Constants.ByteCode.AddOption: @@ -88,7 +97,7 @@ func select_option(id): func pause(): virtual_machine.call_deferred('pause') -func start(node = start_node): +func start(node = starting_node): emit_signal('started') virtual_machine.set_node(node) diff --git a/addons/Wol/core/FunctionInfo.gd b/addons/Wol/core/FunctionInfo.gd index c1c4f35..263a4f1 100644 --- a/addons/Wol/core/FunctionInfo.gd +++ b/addons/Wol/core/FunctionInfo.gd @@ -1,5 +1,6 @@ extends Object -var Value : GDScript = load("res://addons/Wol/core/Value.gd") + +const Value = preload("res://addons/Wol/core/Value.gd") var name = '' # NOTE: -1 means variable arguments @@ -18,12 +19,18 @@ func invoke(parameters = []): if parameters != null: length = parameters.size() - if check_param_count(length): + if check_parameter_count(length): if returns_value: + var return_value if length > 0: - return Value.new(function.call_funcv(parameters)) + return_value = function.call_funcv(parameters) else: - return Value.new(function.call_func()) + return_value = function.call_func() + + if return_value is Value: + return return_value + else: + return Value.new(return_value) else: if length > 0: function.call_funcv(parameters) @@ -31,5 +38,5 @@ func invoke(parameters = []): function.call_func() return null -func check_param_count(_parameter_count): +func check_parameter_count(_parameter_count): return parameter_count == _parameter_count or parameter_count == -1 diff --git a/addons/Wol/core/StandardLibrary.gd b/addons/Wol/core/StandardLibrary.gd index ad2f63f..9f5abf5 100644 --- a/addons/Wol/core/StandardLibrary.gd +++ b/addons/Wol/core/StandardLibrary.gd @@ -72,25 +72,14 @@ func xor(param1, param2): func lnot(param1): return not param1.as_bool() -var visited_node_count = {} - -func is_node_visited(node = virtual_machine.current_node_name()): +func is_node_visited(node = virtual_machine.current_node.name): return node_visit_count(node) > 0 -func node_visit_count(node = virtual_machine.current_node_name()): +func node_visit_count(node = virtual_machine.current_node.name): if node is Value: node = virtual_machine.program.strings[node.value()].text - var visit_count = 0 - if visited_node_count.has(node): - visit_count = visited_node_count[node] + var variable_storage = virtual_machine.dialogue.variable_storage + var visited_node_count = variable_storage[virtual_machine.program.filename] - return visit_count - -func get_visited_nodes(): - return visited_node_count.keys() - -func set_visited_nodes(visitedList): - visited_node_count.clear() - for string in visitedList: - visited_node_count[string] = 1 + return visited_node_count[node] if visited_node_count.has(node) else 0 diff --git a/addons/Wol/core/VirtualMachine.gd b/addons/Wol/core/VirtualMachine.gd index 96a5e94..b86b503 100644 --- a/addons/Wol/core/VirtualMachine.gd +++ b/addons/Wol/core/VirtualMachine.gd @@ -1,6 +1,7 @@ -extends Node +extends Object const Constants = preload('res://addons/Wol/core/Constants.gd') +const Program = preload('res://addons/Wol/core/Program.gd') const Value = preload('res://addons/Wol/core/Value.gd') # Function references to handlers @@ -59,8 +60,17 @@ func set_node(name): current_node = program.nodes[name] reset() + state.current_node_name = name node_start_handler.call_func(name) + + if not dialogue.variable_storage.has(program.filename): + dialogue.variable_storage[program.filename] = {} + + if not dialogue.variable_storage[program.filename].has(name): + dialogue.variable_storage[program.filename][name] = 0 + + dialogue.variable_storage[program.filename][name] += 1 return true func pause(): @@ -91,8 +101,8 @@ func reset(): state = VmState.new() func get_next_instruction(): - if current_node.instructions.size() - 1 > state.programCounter: - return current_node.instructions[state.programCounter + 1] + if current_node.instructions.size() - 1 > state.program_counter: + return current_node.instructions[state.program_counter + 1] return func start(): @@ -115,14 +125,13 @@ func resume(): execution_state = Constants.ExecutionState.Running - #execute instruction until something cool happens while execution_state == Constants.ExecutionState.Running: - var current_instruction = current_node.instructions[state.programCounter] + var current_instruction = current_node.instructions[state.program_counter] run_instruction(current_instruction) - state.programCounter += 1 + state.program_counter += 1 - if state.programCounter >= current_node.instructions.size(): - node_finished_handler.call_func(current_node.nodeName) + if state.program_counter >= current_node.instructions.size(): + node_finished_handler.call_func(current_node.name) execution_state = Constants.ExecutionState.Stopped reset() dialogue_finished_handler.call_func() @@ -142,17 +151,22 @@ func run_instruction(instruction): # Jump to named label Constants.ByteCode.JumpTo: - state.programCounter = find_label_instruction(instruction.operands[0].value) - 1 + state.program_counter = find_label_instruction(instruction.operands[0].value) - 1 Constants.ByteCode.RunLine: # Lookup string and give back as line var key = instruction.operands[0].value - var line = program.strings[key] + var line = program.strings[key].clone() # The second operand is the expression count of format function - # TODO: Add format functions supportk + # TODO: Add format functions support + line.substitutions = [] if instruction.operands.size() > 1: - pass + var expression_count = int(instruction.operands[1].value) + + while expression_count > 0: + line.substitutions.append(state.pop_value().as_string()) + expression_count -= 1 var return_state = line_handler.call_func(line) @@ -177,12 +191,12 @@ func run_instruction(instruction): # Jump to named label if value of stack top is false Constants.ByteCode.JumpIfFalse: if not state.peek_value().as_bool(): - state.programCounter = find_label_instruction(instruction.operands[0].value) - 1 + state.program_counter = find_label_instruction(instruction.operands[0].value) - 1 # Jump to label whose name is on the stack Constants.ByteCode.Jump: var destination = state.peek_value().as_string() - state.programCounter = find_label_instruction(destination) - 1 + state.program_counter = find_label_instruction(destination) - 1 Constants.ByteCode.Pop: state.pop_value() @@ -204,25 +218,29 @@ func run_instruction(instruction): if actual_parameter_count == 0: result = function.invoke() else: - var params = [] + var parameters = [] for _i in range(actual_parameter_count): - params.push_front(state.pop_value()) + parameters.push_front(state.pop_value()) - result = function.invoke(params) + result = function.invoke(parameters) if function.returns_value: state.push_value(result) Constants.ByteCode.PushVariable: var name = instruction.operands[0].value - var godot_value = dialogue.variable_storage[name] - var value = Value.new(godot_value) + var value = dialogue.variable_storage[name.replace('$', '')] state.push_value(value) Constants.ByteCode.StoreVariable: var value = state.peek_value() + if value.type == Constants.ValueType.Str: + value = program.strings[value.value()].text + else: + value = value.value() + var name = instruction.operands[0].value.replace('$', '') - dialogue.variable_storage[name] = value.value() + dialogue.variable_storage[name] = value Constants.ByteCode.Stop: node_finished_handler.call_func(current_node.name) @@ -239,15 +257,15 @@ func run_instruction(instruction): var return_state = node_finished_handler.call_func(current_node.name) set_node(name) - state.programCounter -= 1 + if return_state == Constants.HandlerState.PauseExecution: execution_state = Constants.ExecutionState.Suspended Constants.ByteCode.AddOption: var key = instruction.operands[0].value - var line = program.strings[key] + var line = program.strings[key].clone() - # TODO: Add format functions supportk + # TODO: Add format functions support if instruction.operands.size() > 2: pass @@ -280,11 +298,11 @@ func run_instruction(instruction): class VmState: var current_node_name = '' - var programCounter = 0 + var program_counter = 0 var current_options = [] var stack = [] - func push_value(value)->void: + func push_value(value): if value is Value: stack.push_back(value) else: diff --git a/addons/Wol/core/compiler/compiler.gd b/addons/Wol/core/compiler/compiler.gd index 00a6cd8..aafd6a7 100644 --- a/addons/Wol/core/compiler/compiler.gd +++ b/addons/Wol/core/compiler/compiler.gd @@ -79,7 +79,6 @@ func compile(): line_number += 1 body = PoolStringArray(body_lines).join('\n') - var lexer = Lexer.new(filename, title, body) var tokens = lexer.tokenize() @@ -94,6 +93,7 @@ func compile(): line_number += 1 var program = Program.new() + program.filename = filename for node in parsed_nodes: compile_node(program, node) @@ -203,7 +203,7 @@ func generate_statement(node, statement): generate_assignment(node, statement.assignment) Constants.StatementTypes.Line: - generate_line(node, statement,statement.line) + generate_line(node, statement) _: assert(false, 'Illegal statement type [%s]. Could not generate code.' % statement.type) @@ -218,12 +218,19 @@ func generate_custom_command(node, command): else : emit(Constants.ByteCode.RunCommand, node, [Program.Operand.new(command_string)]) -func generate_line(node, statement, line): +func generate_line(node, statement): # TODO: Implement proper line numbers (global and local) - var num = register_string(line, node.name, '', statement.line_number, []); - emit(Constants.ByteCode.RunLine, node, [Program.Operand.new(num)]) + var line = statement.line + var expression_count = line.substitutions.size() -func generate_shortcut_group(node,shortcut_group): + while not line.substitutions.empty(): + var inline_expression = line.substitutions.pop_back() + generate_expression(node, inline_expression.expression) + + var num = register_string(line.line_text, node.name, line.line_id, statement.line_number, line.tags); + emit(Constants.ByteCode.RunLine, node,[Program.Operand.new(num), Program.Operand.new(expression_count)]) + +func generate_shortcut_group(node, shortcut_group): var end = register_label('group_end') var labels = [] var option_count = 0 @@ -243,7 +250,8 @@ func generate_shortcut_group(node,shortcut_group): var label_string_id = register_string( option.label, node.name, - label_line_id,option.line_number, + label_line_id, + option.line_number, [] ) @@ -287,7 +295,7 @@ func generate_if(node, if_statement): generate_expression(node, clause.expression) emit(Constants.ByteCode.JumpIfFalse, node, [Program.Operand.new(end_clause)]) - generate_block(node,clause.statements) + generate_block(node, clause.statements) emit(Constants.ByteCode.JumpTo, node, [Program.Operand.new(endif)]) if clause.expression != null: diff --git a/addons/Wol/core/compiler/lexer.gd b/addons/Wol/core/compiler/lexer.gd index 929772f..2287b3e 100644 --- a/addons/Wol/core/compiler/lexer.gd +++ b/addons/Wol/core/compiler/lexer.gd @@ -17,6 +17,8 @@ const ASSIGNMENT = 'assignment' const OPTION = 'option' const OR = 'or' const DESTINATION = 'destination' +const INLINE = 'inline' +const FORMAT_FUNCTION = 'format' var WHITESPACE = '\\s*' @@ -84,27 +86,40 @@ func createstates(): patterns[Constants.TokenType.EndIf] = ['endif(?!\\w)', '"endif"'] patterns[Constants.TokenType.Set] = ['set(?!\\w)', '"set"'] patterns[Constants.TokenType.ShortcutOption] = ['\\-\\>\\s*', '"->"'] + patterns[Constants.TokenType.ExpressionFunctionStart] = ['\\{', '"{"'] + patterns[Constants.TokenType.ExpressionFunctionEnd] = ['\\}', '"}"'] + patterns[Constants.TokenType.FormatFunctionStart] = ['(? 0: line_number = tokens.front().line_number - else: - line_number = -1 tags = [] @@ -132,6 +130,105 @@ class WolNode extends ParseNode: class Header extends ParseNode: pass +class InlineExpression extends ParseNode: + var expression + + func _init(parent, parser).(parent, parser): + parser.expect_symbol([Constants.TokenType.ExpressionFunctionStart]) + expression = ExpressionNode.parse(self, parser) + parser.expect_symbol([Constants.TokenType.ExpressionFunctionEnd]) + + static func can_parse(parser): + return parser.next_symbol_is([Constants.TokenType.ExpressionFunctionStart]) + + func tree_string(_indent_level): + return "InlineExpression:" + +# Returns a format_text string as [ name "{0}" key1="value1" key2="value2" ] +class FormatFunctionNode extends ParseNode: + var format_text = '' + var expression_value + + func _init(parent:ParseNode, parser, expressionCount:int).(parent, parser): + format_text="[" + parser.expect_symbol([Constants.TokenType.FormatFunctionStart]) + + while !parser.next_symbol_is([Constants.TokenType.FormatFunctionEnd]): + if parser.next_symbol_is([Constants.TokenType.Text]): + format_text += parser.expect_symbol().value + + if InlineExpression.can_parse(parser): + expression_value = InlineExpression.new(self, parser) + format_text +=" \"{%d}\" " % expressionCount + parser.expect_symbol() + format_text+="]" + + static func can_parse(parser): + return parser.next_symbol_is([Constants.TokenType.FormatFunctionStart]) + + # TODO: Make format prettier and add more information + func tree_string(_indent_level): + return "FormatFunction" + +class LineNode extends ParseNode: + var line_text = '' + # FIXME: Right now we are putting the formatfunctions and inline expressions in the same + # list but if at some point we want to stronly type our sub list we need to make a new + # parse node that can have either an InlineExpression or a FunctionFormat + # .. This is a consideration for Godot4.x + var substitutions = [] + var line_id = '' + var line_tags = [] + + # NOTE: If format function an inline functions are both present + # returns a line in the format "Some text {0} and some other {1}[format "{2}" key="value" key="value"]" + + func _init(parent, parser).(parent, parser): + while parser.next_symbol_is( + [ + Constants.TokenType.FormatFunctionStart, + Constants.TokenType.ExpressionFunctionStart, + Constants.TokenType.Text, + Constants.TokenType.TagMarker + ] + ): + + if FormatFunctionNode.can_parse(parser): + var format_function = FormatFunctionNode.new(self, parser, substitutions.size()) + if format_function.expression_value != null: + substitutions.append(format_function.expression_value) + + line_text += format_function.format_text + + elif InlineExpression.can_parse(parser): + var inline_expression = InlineExpression.new(self, parser) + line_text += '{%d}' % substitutions.size() + substitutions.append(inline_expression) + + elif parser.next_symbols_are([Constants.TokenType.TagMarker, Constants.TokenType.Identifier]): + parser.expect_symbol() + var tag_token = parser.expect_symbol([ Constants.TokenType.Identifier ]) + if tag_token.value.begins_with("line:"): + if line_id.empty(): + line_id = tag_token.value + else: + printerr("Too many line_tags @[%s:%d]" %[parser.currentNodeName, tag_token.line_number]) + return + else: + tags.append(tag_token.value) + + else: + var token = parser.expect_symbol() + if token.line_number == line_number and token.type != Constants.TokenType.BeginCommand: + line_text += token.value + else: + parser.tokens.push_front(token) + break + + + func tree_string(indent_level): + return tab(indent_level, 'Line: (%s)[%d]' % [line_text, substitutions.size()]) + class Statement extends ParseNode: var Type = Constants.StatementTypes @@ -142,7 +239,7 @@ class Statement extends ParseNode: var assignment var shortcut_option_group var custom_command - var line = '' + var line func _init(parent, parser).(parent, parser): if Block.can_parse(parser): @@ -170,7 +267,7 @@ class Statement extends ParseNode: type = Type.CustomCommand elif parser.next_symbol_is([Constants.TokenType.Text]): - line = parser.expect_symbol([Constants.TokenType.Text]).value + line = LineNode.new(self, parser) type = Type.Line else: @@ -203,7 +300,7 @@ class Statement extends ParseNode: Type.CustomCommand: info.append(custom_command.tree_string(indent_level)) Type.Line: - info.append(tab(indent_level, 'Line: %s' % line)) + info.append(line.tree_string(indent_level)) _: printerr('Cannot print statement') @@ -233,11 +330,14 @@ class CustomCommand extends ParseNode: #if first token is identifier and second is leftt parenthesis #evaluate as function - if (command_tokens.size() > 1 && command_tokens[0].type == Constants.TokenType.Identifier - && command_tokens[1].type == Constants.TokenType.LeftParen): + if command_tokens.size() > 1 \ + and command_tokens[0].type == Constants.TokenType.Identifier \ + and command_tokens[1].type == Constants.TokenType.LeftParen: + var p = get_script().new(command_tokens, parser.library) expression = ExpressionNode.parse(self, p) type = Type.Expression + else: #otherwise evaluuate command type = Type.ClientCommand @@ -545,10 +645,10 @@ class ExpressionNode extends ParseNode: var parameters = [] func _init(parent, parser, _value, _function = '', _parameters = []).(parent, parser): - if _value != null: type = Constants.ExpressionType.Value value = _value + else: type = Constants.ExpressionType.FunctionCall function = _function @@ -568,7 +668,7 @@ class ExpressionNode extends ParseNode: return info.join('') - # using Djikstra's shunting-yard algorithm to convert stream of expresions into postfix notation, + # Using Djikstra's shunting-yard algorithm to convert stream of expresions into postfix notation, # & then build a tree of expressions static func parse(parent, parser): var rpn = [] @@ -595,7 +695,7 @@ class ExpressionNode extends ParseNode: var last #read expression content - while parser.tokens.size() > 0 && parser.next_symbol_is(valid_types): + while parser.tokens.size() > 0 and parser.next_symbol_is(valid_types): var next = parser.expect_symbol(valid_types) if next.type == Constants.TokenType.Variable \ @@ -633,7 +733,7 @@ class ExpressionNode extends ParseNode: #find the closest function on stack #increment parameters - func_stack.back().param_count+=1 + func_stack.back().parameter_count+=1 elif Operator.is_op(next.type): #this is an operator @@ -685,7 +785,7 @@ class ExpressionNode extends ParseNode: #else #we have more than 1 param if last.type != Constants.TokenType.LeftParen: - func_stack.back().param_count+=1 + func_stack.back().parameter_count+=1 rpn.append(op_stack.pop_back()) func_stack.pop_back() @@ -730,7 +830,7 @@ class ExpressionNode extends ParseNode: var function_name = next.value var function_parameters = [] - for _i in range(next.param_count): + for _i in range(next.parameter_count): function_parameters.append(eval_stack.pop_back()) function_parameters.invert() @@ -802,7 +902,7 @@ class Assignment extends ParseNode: info.append(tab(indent_level + 1, destination)) info.append(tab(indent_level + 1, Constants.token_type_name(operation))) info.append(value.tree_string(indent_level + 1)) - return info.join('') + return PoolStringArray(info).join('') static func can_parse(parser): diff --git a/addons/Wol/core/constants.gd b/addons/Wol/core/constants.gd index 5c818c0..c44b85e 100644 --- a/addons/Wol/core/constants.gd +++ b/addons/Wol/core/constants.gd @@ -76,6 +76,12 @@ enum TokenType { #8 Command syntax ('<>') BeginCommand, EndCommand, + ExpressionFunctionStart, # { + ExpressionFunctionEnd, # } + + FormatFunctionStart, # [ + FormatFunctionEnd, # ] + #10 Variables ('$foo') Variable, @@ -145,7 +151,8 @@ enum TokenType { } enum ExpressionType { - Value, FunctionCall + Value, + FunctionCall } enum StatementTypes { @@ -155,7 +162,8 @@ enum StatementTypes { IfStatement, OptionStatement, AssignmentStatement, - Line + Line, + InlineExpression } enum ValueType { diff --git a/addons/Wol/core/library.gd b/addons/Wol/core/library.gd index cd40a0d..a0ff7c5 100644 --- a/addons/Wol/core/library.gd +++ b/addons/Wol/core/library.gd @@ -15,6 +15,7 @@ func get_function(name): func import_library(other): Constants.merge_dir(functions, other.functions) + other.virtual_machine = virtual_machine func register_function(name, parameter_count, function, returns_value): var functionInfo = FunctionInfo.new(name, parameter_count, function, returns_value) diff --git a/addons/Wol/core/program.gd b/addons/Wol/core/program.gd index ebd57ad..fa94140 100644 --- a/addons/Wol/core/program.gd +++ b/addons/Wol/core/program.gd @@ -3,6 +3,7 @@ extends Object const Constants = preload('res://addons/Wol/core/Constants.gd') var name = '' +var filename = '' var strings = {} var nodes = {} @@ -12,6 +13,7 @@ class Line: var line_number = -1 var file_name = '' var implicit = false + var substitutions = [] var meta = [] func _init(_text, _node_name, _line_number, _file_name, _implicit, _meta): @@ -21,6 +23,13 @@ class Line: implicit = _implicit meta = _meta + func clone(): + return get_script().new(text, node_name, line_number, file_name, implicit, meta) + + func _to_string(): + return '%s:%d: "%s"' % [file_name.get_file(), line_number, text] + + class Option: var line var id = -1 @@ -31,6 +40,9 @@ class Option: id = _id destination = _destination + func clone(): + return get_script().new(self) + class Command: var command = '' diff --git a/addons/Wol/core/value.gd b/addons/Wol/core/value.gd index 8da0295..161df5a 100644 --- a/addons/Wol/core/value.gd +++ b/addons/Wol/core/value.gd @@ -2,9 +2,6 @@ extends Object const Constants = preload('res://addons/Wol/core/Constants.gd') -const NULL_STRING = 'null' -const FALSE_STRING = 'false' -const TRUE_STRING = 'true' const NANI = 'NaN' var type = Constants.ValueType.Nullean @@ -74,7 +71,7 @@ func set_value(value): func add(other): if type == Constants.ValueType.Str or other.type == Constants.ValueType.Str: - return get_script().new('%s%s'%[value(),other.value()]) + return get_script().new('%s%s' % [value(), other.value()]) if type == Constants.ValueType.Number and other.type == Constants.ValueType.Number: return get_script().new(number + other.number) return null diff --git a/dialogue.yarn b/dialogue.yarn index be89d6c..d34b431 100644 --- a/dialogue.yarn +++ b/dialogue.yarn @@ -7,24 +7,53 @@ position: 0, 0 <> // remove "to" to trigger error -<> +<> <> // Implement inline expressions -Bob: Theresa, {$direction} way! #line:5d7a7c -Theresa: Did you know one + one equals {$one + $one}? -Bob: You wanna go somewhere? +<> +Narrator: You, {$direction} way! +<> +Narrator: Do you know you've been here {visit_count()} times? +You: Did you know one + one equals {$one + $one}? +Narrator: You wanna go somewhere? -[[Go to the store|TheStore]] -[[Lets stay here and talk|Talk]] + -> Go to the store + [[TheStore]] +// -> Wait, how many times have I been to the store? +// Narrator: You've been to the store {visit_count('TheStore')} times. +// [[Start]] +-> Lets stay here and talk + [[Talk]] === title: TheStore tags: colorID: 0 position: 0, 200 --- -Clerk: Welcome to the store. -Clerk: Can I help you with anything? +Guy: Hey what's up I need your help can you come here? +You: Well I can't I'm buying clothes. +All right well hurry up and come over here. +You: I can't find them. +Guy: What do you mean you can't find them? +You: I can't find them there's only soup. +Guy: What do you mean there's only soup?! +You: It means there's only soup. +Guy: WELL THEN GET OUT OF THE SOUP ISLE!! +You: Alright you dont have to shout at me! +You: There's more soup. +Guy: What do you mean there's more soup? +You: There's just more soup. +Guy: Then go to the next aisle! +You: There's still soup! +Guy: Where are you right now?! +You: I'm at soup! +Guy: What do you mean you're at soup?! +You: I mean I'm at soup. +Guy: WHAT STORE ARE YOU IN?! +You: IM AT THE SOUP STORE!! +Guy: WHY ARE YOU BUYING CLOTHES AT THE SOUP STORE?! +You: FUCK YOU! [[Go home|Start]] === title: Talk @@ -32,9 +61,9 @@ tags: colorID: 0 position: 0, 400 --- -Bob: So how are you really? -Theresa: I'm good! -Bob: Do you want to continue talking? +Narrator: So how are you really? +You: I'm good! +Narrator: Do you want to continue talking? -> Yes [[Start]] -> No diff --git a/project.godot b/project.godot index baff818..aa96519 100644 --- a/project.godot +++ b/project.godot @@ -9,30 +9,12 @@ config_version=4 _global_script_classes=[ { -"base": "Object", -"class": "Compiler", -"language": "GDScript", -"path": "res://addons/Wol/core/compiler/Compiler.gd" -}, { -"base": "Object", -"class": "Lexer", -"language": "GDScript", -"path": "res://addons/Wol/core/compiler/Lexer.gd" -}, { -"base": "Object", -"class": "Program", -"language": "GDScript", -"path": "res://addons/Wol/core/Program.gd" -}, { "base": "Node", "class": "Wol", "language": "GDScript", "path": "res://addons/Wol/Wol.gd" } ] _global_script_class_icons={ -"Compiler": "", -"Lexer": "", -"Program": "", "Wol": "" }