From aa3fc3bb5f4786325857ab7dc567a70a59b81392 Mon Sep 17 00:00:00 2001 From: Kienan Stewart Date: Sun, 25 Apr 2021 19:52:23 -0400 Subject: [PATCH] Prepping for safety upload --- project.godot | 19 +- src/GameState.gd | 537 ++++++++++++++++++++++++++++++--- src/ui/ChooseFlightIn.gd | 1 - src/ui/ChooseFlightIn.tscn | 5 +- src/ui/CrewUI.gd | 13 +- src/ui/Dialogue.gd | 4 +- src/ui/Dialogue.tscn | 8 +- src/ui/DifficultySelector.tscn | 12 +- src/ui/Encounter.gd | 100 ++++++ src/ui/Encounter.tscn | 47 +++ src/ui/EncounterChoice.gd | 26 +- src/ui/Encounters.gd | 78 +++++ src/ui/Encounters.tscn | 10 +- src/ui/End.gd | 36 +++ src/ui/End.tscn | 58 ++++ src/ui/FlashText.gd | 22 ++ src/ui/GameMenu.gd | 33 ++ src/ui/GameMenu.tscn | 102 +++---- src/ui/Intro.gd | 11 +- src/ui/MainMenu.gd | 7 + src/ui/MainMenu.tscn | 40 ++- src/ui/Map.gd | 77 ++++- src/ui/Map.tscn | 11 +- src/ui/ShipStats.gd | 34 ++- src/ui/ShipStats.tscn | 86 ++---- 25 files changed, 1165 insertions(+), 212 deletions(-) create mode 100644 src/ui/Encounter.gd create mode 100644 src/ui/Encounter.tscn create mode 100644 src/ui/Encounters.gd create mode 100644 src/ui/End.gd create mode 100644 src/ui/End.tscn create mode 100644 src/ui/FlashText.gd create mode 100644 src/ui/GameMenu.gd diff --git a/project.godot b/project.godot index 682bb6c..8e3159a 100644 --- a/project.godot +++ b/project.godot @@ -8,14 +8,23 @@ config_version=4 -_global_script_classes=[ ] +_global_script_classes=[ { +"base": "RichTextEffect", +"class": "RichTextPulse", +"language": "GDScript", +"path": "res://src/ui/FlashText.gd" +} ] _global_script_class_icons={ - +"RichTextPulse": "" } [application] -config/name="LD48" +config/name="Gravity Limbo" +config/description="An entry for Ludum Dare 48 with the theme: Deeper and Deeper + +Pilot a ship into the gravity well of a planet to rescue the Diligent, get their Warp Crystal, and see how close you can come to brushing the planet." +run/main_scene="res://src/ui/MainMenu.tscn" boot_splash/fullsize=false boot_splash/use_filter=false config/icon="res://icon.png" @@ -24,6 +33,10 @@ config/icon="res://icon.png" GameState="*res://src/GameState.tscn" +[display] + +window/size/resizable=false + [rendering] quality/driver/fallback_to_gles2=true diff --git a/src/GameState.gd b/src/GameState.gd index 730083a..36c5559 100644 --- a/src/GameState.gd +++ b/src/GameState.gd @@ -1,9 +1,13 @@ extends Node +signal orbit_updated +signal stats_updated +signal crew_updated # Declare member variables here. Examples: # var a = 2 # var b = "text" +const debug = true var current_scene = null var difficulty = null @@ -17,7 +21,7 @@ var difficulty_data = { "planet": "res://assets/moon.png", "starting_altitude": 60000, "starting_crew": 5, - "starting_drag": 1, + "starting_drag": 75, "drag_function": funcref(self, "moon_drag"), "rescue_altitude": 10000, "maximum_crew": 15, @@ -27,7 +31,7 @@ var difficulty_data = { "planet": "res://assets/planet.png", "starting_altitude": 600000, "starting_crew": 4, - "starting_drag": 10, + "starting_drag": 100, "drag_function": funcref(self, "planet_drag"), "rescue_altitude": 100000, "maximum_crew": 10, @@ -37,7 +41,7 @@ var difficulty_data = { "planet": "res://assets/blackhole.png", "starting_altitude": 200000001000000, "starting_crew": 3, - "starting_drag": 100, + "starting_drag": 125, "drag_function": funcref(self, "blackhole_drag"), "rescue_altitude": 200000000100000, "maximum_crew": 6, @@ -52,31 +56,324 @@ const TreeDepth = 5 const EncounterTypes = [ "ArtificialSatellite", "NaturalSatellite", - "Comet", - "Debris", - #"Gases", - "Mystery", - "Alien", + #"Comet", + #"Debris", + ##"Gases", + #"Mystery", + #"Alien", "Ship", - "Station", - "LocationSpecific", # Eg., Moon, Planet, Blackhole... + #"Station", + #"LocationSpecific", # Eg., Moon, Planet, Blackhole... ] const EncounterData = { - "ArtificialSattelite" : { - "tooltip": "" +# "a": { +# "tooltip": "", +# "situations": { +# 0: { +# "title": "a x", +# "picture": null, +# "text": "asdfs", +# "choices": { +# 0: { +# "title": "x", +# "tooltip": "aa", +# "then": "aa", +# "results": { +# # starting from last, if chance >= index between 0-100 +# 0: { +# "title": "a", +# "text": "a", +# "stat_changes": Dictionary(), +# }, +# } +# } +# } +# } +# } +# } + "RescueOperation": { + "tooltip": "A ship is stranded here, and they need your help", + "situations": { + 0: { + "title": "The Diligent's Rescue", + "picture": null, + "text": "", + "choices": { + 0: { + "title": "Prioritise the warp crystal", + "tooltip": "", + "then": "You shove past the haggard looking crew of the " + \ + "Diligent, ignoring their arched eyebrows and sideways " + \ + "glances as you hurry to the Engineering section. \n\n" + \ + "The [rainbow freq=0.5 sat=2 val=200]Warp Crystal[/rainbow] " + \ + "is already packed in an open carrying case. It looks like a " + \ + "good one, and should last a few jumps.\n\nYou grab the case " + \ + "and make haste back to the Wellspring before the Diligent " + \ + "sinks further into the gravity well", + "results": { + 0: { + "title": "Gaining supplies, losing morale", + "text": "", + "stat_changes": { + "supplies": 500, + }, + "crew_changes": { + "morale": -50, + } + } + } + }, + 1: { + "title": "Prioritise the crew of the Diligent", + "then": "You rush to get all the members of the Diligent's crew " + \ + "abord before the ships sink deeper into the gravity well. Your mates " + \ + "just finish getting that last stretcher on board before the a beeping klaxon " + \ + "starts to signal that the two ships are about to be torn away from each other.", + "tooltip": "", + "results": { + 0: { + "title": "Gaining crew", + "text": "", + "stat_changes": { + "extra_crew": 5, + }, + } + } + }, + 2: { + "title": "Try to repair the Diligent", + "tooltip": "", + "then": "Your crew works tirelessly hand-in-hand with" + \ + " the Diligent's trying to make their ship fully spaceworthy " + \ + "again.", + "results": { + 0: { + "title": "Lose altitude", + "text": "", + "orbit_changes": { + "altitude": -1000, + "escape_dv": 100, + } + } + } + } + } + } + } + }, + "ArtificialSatellite" : { + "tooltip": "", + "situations": { + 0: { + "title": "Abandoned observation satellite", + "picture": null, + "text": "During the coast phase of your descent, your ship is " + \ + "passing near a derelict satellite. A visual inspection shows " + \ + "scorch marks and loose panel on the side", + "choices": { + 0: { + "title": "Download data", + "tooltip": "", + "then": "Your wireless systems initialize a mesh connection " + \ + "with the object and the data begins to stream back to your ship", + "results": { + 0: { + "title": "Losing DeltaV", + "text": "The data seems to decodes itself and a malicious program " + \ + "begins to run on your ship systems. It manages to fire some of the " + \ + "thrusters before you can lock it down.", + "stat_changes": { + "deltav": -100, + }, + }, + 50: { + "title": "Gaining DeltaV", + "text": "After decoding the data, it seems to be a detailed chart of " + \ + "the local gravity well. This should help you fine tune the course " + \ + "towards the [b]Diligent[/b]", + "stat_changes": { + "deltav": 100, + }, + }, + 90: { + "title": "Nothing", + "text": "The data appears to be hopelessly corrupt, and you cannot glean anything from it", + }, + }, + }, + 1: { + "title": "Salvage the probe", + "tooltip": "", + "then": "Your crew attempts to haul the probe abord using a magnetic cable", + "results": { + 0: { + "title": "Nothing", + "text": "The materials making up the probe are so corroded that they " + \ + "are unusable and only fit for melting down", + "stat_changes": Dictionary(), + }, + 25: { + "title": "Gaining Supplies", + "text": "Despite evidence that somebody had tried to repair - or tamper - " + \ + "with the satellite, the material composition of it yields many useful " + \ + "components", + "stat_changes": { + "supplies": 100, + }, + }, + 90: { + "title": "An event occuring", + "text": "During the cable connection, the line gets caught. " + \ + "A crew member heads on EVA to try and fix it." + \ + "As they near the satellite, it explodes! Their space suit is shredded and they die instantly.", + "stat_changes": { + "extra_crew": -1, + } + }, + 95: { + "title": "An event occuring", + "text": "During the cable connection, the line gets caught." + \ + "A crew member heads on EVA to try and fix it." + \ + "Nearing the satellite, they see a blinking light just under the loose panel. Fearing a bomb, they cut the cable and come back to the ship", + } + } + }, + 2: { + "title": "Do nothing", + "tooltip": "", + "then": "You drift silently past the satellite on way down to the Diligent", + "results": { + 0: { + "title": "Nothing happening", + "text": "The satellite's collision avoidance system seems to kick in and it adjusts it's orbit away from your ship", + } + } + } + } + }, + }, + }, + "NaturalSatellite" : { + "tooltip": "", + "situations": { + 0: { + "title": "Unexpected object", + "picture": null, + "text": "The proximity sensor alarms blare suddenly, there's a rock on a collision course!", + "choices": { + 0: { + "title": "Evade", + "then": "You fire the thrusters, quickly moving yourself away from the source of danger", + "tooltip": "", + "results": { + 0: { + "title": "Losing DeltaV", + "text": "The sudden unplanned maneauver eats into your fuel reservers", + "stat_changes": { + "deltav": -100, + } + } + } + }, + 1: { + "title": "Brace for impact", + "then": "You slam the red alert button and your crew pile into their crash seats, gritting their teeth for what is to come", + "tooltip": "", + "results": { + 0: { + "title": "Losing Crew and Health", + "text": "The object pierces through your hull at hundreds of meters per second, tearing flesh and steel alike. Bulkheads clamp down and sirens wail. After a few seconds, the situation stabilises and you look around, noting that not everyone made it.", + "stat_changes": { + "extra_crew": -1, + } + }, + 50: { + "title": "Losing health", + "text": "The object pierces through your hull at hundreds of meters per second, tearing through all manners of ships systems. Chaos reigns as emergency repair systems kick in", + "stat_changes": { + "health": -250, + } + }, + } + }, + } + } + } }, - "NaturalSattelite" : {}, "Comet" : {}, "Debris" : {}, #"Gases" : {}, "Mystery" : {}, "Alien" : {}, - "Ship" : {}, + "Ship" : { + "tooltip": "", + "situations": { + 0: { + "title": "Another ship", + "picture": null, + "text": "There's the quiet remanents of a ship floating through space. " + \ + "The hull seems largely intact, but the lights are off.", + "choices": { + 0: { + "title": "Send a boarding party", + "then": "You send over a skiff with some of your crew", + "tooltip": "", + "results": { + 0: { + "title": "Gain DeltaV", + "text": "Nobody is home, but the fuel reserves are almost full", + "stat_changes": { + "deltav": 100, + } + }, + 25: { + "title": "Gain crew", + "text": "The away team finds cryo-stasis pods running on battery power", + "stat_changes": { + "extra_crew": 1 + } + }, + 50: { + "title": "Nothing", + "text": "The ship is empty of people and supplies. There is a nice diamond ring though", + }, + 80: { + "title": "Event", + "text": "An explosion rips through the ship as the boarding skiff docks with it. All hands are lost", + "stat_changes": { + "extra_crew": -2, + } + }, + 90: { + "title": "Event", + "text": "The hulk is piled full of dessicated corpses dressed in white and gold vestments, bearing aquiline sigils. Disturbing the grave seems to rub your crew the wrong way.", + "crew_changes": { + "morale": -25, + } + } + } + }, + 2: { + "title": "Do nothing", + "tooltip": "", + "then": "You drift silently past the ship on way down to the Diligent", + "results": { + 0: { + "title": "Nothing happening", + "text": "The crew looks on through sensors and portholes at the diminishing spec that may have once been a refuge in the void to some souls, now quiet.", + } + } + } + }, + } + + } + }, "Station" : {}, "LocationSpecific" : {}, } -var rng = RandomNumberGenerator.new() +var rng = null var encounters = { # 0: [ # { @@ -97,33 +394,73 @@ var states = { 3: "Set Resources and Generate Crew", 4: "Choose flight-path In", 5: "Encounters", - 6: "Choose flight-path Out", - 7: "End Game", + 6: "Going Deeper", + 7: "Choose flight-path Out", + 8: "Encounters 2", + 9: "End Game", } const default_ship_stats = { "health": 1000, "deltav": 1000, - "supplies": 1000, + "supplies": 500, "crew": [], "next_crew_id": 2, + "target_position": Vector2(0, 0), + "starting_position": Vector2(0, 0), } -var target_point = null -var ship_stats = Dictionary(default_ship_stats) -var orbit_stats = { +var ship_stats = {} +const default_orbit_stats = { "altitude": 0, "drag": 0, - "estimated_escape_dv": 0 + "record_low": 0, + "escape_dv": 0, } +var orbit_stats = {} # Called when the node enters the scene tree for the first time. func _ready(): - pass + self.rng = RandomNumberGenerator.new() + self.rng.randomize() + +func reset_to_new(): + var d = difficulty + self.reset() + self.initialize(d) + self.current_state = 4 + goto_scene("res://src/ui/ChooseFlightIn.tscn") +func reset_to_main_menu(): + goto_scene("res://src/ui/MainMenu.tscn") + self.reset() + +func reset(): + # @TODO: do we need to free the encounter or crew instances? I don't think so, + # since they are part of the tree that's freed when the scene is changed... + ship_stats = Dictionary() + + orbit_stats = Dictionary() + + # orbit stats: probably not necessary + self.current_state = 0 + self.encounters = {} + self.current_depth = 0 + self.difficulty = null + var bg = get_tree().get_root().get_node("Background") + if bg: + bg.free() + var end = get_tree().get_root().find_node("End") + if end: + end.free() + func initialize(d): self.difficulty = d - # Generate a map + for k in default_ship_stats.keys(): + ship_stats[k] = default_ship_stats[k] + ship_stats['crew'] = Array() + for k in default_orbit_stats.keys(): + orbit_stats[k] = default_orbit_stats[k] # Generate a map var i = 0 while i < self.TreeDepth: var n = 0 @@ -156,6 +493,7 @@ func initialize(d): # Set the orbit stats self.orbit_stats["altitude"] = get_difficulty_data("starting_altitude") self.orbit_stats["drag"] = get_difficulty_data("starting_drag") + self.orbit_stats["record_low"] = get_difficulty_data("starting_altitude") self.generate_crew() get_tree().get_root().call_deferred("add_child", ResourceLoader.load("res://src/ui/Background.tscn").instance()) @@ -176,19 +514,34 @@ func generate_crew(): }) var x = 0 while x < self.get_difficulty_data("starting_crew"): - self.ship_stats["crew"].append({ - "name": "Xxx", - "may_be_sacrified": true, - "picture": null, - "position": null, - "upkeep": 10, - "morale": 100, - "tooltip": null, - "personality": null, - "id": self.ship_stats['next_crew_id'], - }) + self.add_random_crew_member() x += 1 - self.ship_stats['next_crew_id'] += 1 + +func add_random_crew_member(): + self.ship_stats["crew"].append({ + "name": "Xxx", + "may_be_sacrified": true, + "picture": null, + "position": null, + "upkeep": 10, + "morale": 100, + "tooltip": null, + "personality": null, + "id": self.ship_stats['next_crew_id'], + }) + self.ship_stats['next_crew_id'] += 1 + +func generate_encounter_instance(data, level = null, index = null): + var instance = null + if index == null: + index = 0 + var source_data = self.EncounterData[data[index]["type"]] + var situation = self.rng.randi_range(0, len(source_data["situations"])-1) + instance = ResourceLoader.load("res://src/ui/Encounter.tscn").instance() + instance.initialize(source_data["situations"][situation]) + if level != null and index != null: + self.encounters[level][index]["instance"] = instance + return instance func goto_scene(scene, current = null): call_deferred("_deferred_goto_scene", scene, current) @@ -218,9 +571,119 @@ func start_encounters(picks): self.encounters[x][picks[x]]["selected"] = true self.encounters[x][picks[x]]["locked"] = true x += 1 - self.current_state = 5 + if self.current_state < 5: + self.current_state = 5 + if self.current_state > 5: + self.current_state = 8 + self.goto_scene("res://src/ui/Encounters.tscn") +func choose_flightpath_out(): + GameState.current_state = 7 + #get_tree().get_root().print_tree_pretty() + self.ship_stats['starting_position'] = get_tree().get_root().get_node("Encounters/Map/Ship").get_global_position() + self.encounters.erase(GameState.current_depth) + GameState.current_depth -= 1 + self.goto_scene("res://src/ui/ChooseFlightIn.tscn") + +func update_stats(d): + for k in d.keys(): + if k == "extra_crew": + var max_crew = get_difficulty_data("maximum_crew") + var crew_to_add = d[k] + var x = 0 + var modif = false + if crew_to_add > 0: + if d[k] + len(ship_stats['crew']) > max_crew: + crew_to_add = max_crew - len(ship_stats['crew']) + while x < crew_to_add: + self.add_random_crew_member() + modif = true + x += 1 + elif crew_to_add < 0: + print("Needing to lose crew") + while crew_to_add < 0 and len(ship_stats['crew']) > 0: + ship_stats['crew'].pop_back() + print("Lost crew") + modif = true + crew_to_add += 1 + self.update_crew({"morale": -5}) + if len(ship_stats['crew']) == 0: + self.end(false, "Everybody died") + if modif: + emit_signal("crew_updated") + continue + if d[k] == null: + continue + if d[k] is Vector2: + ship_stats[k] = d[k] + else: + print("Stat change for " + k) + print("\tOld: " + str(ship_stats[k])) + print("\tNew: " + str(ship_stats[k] + d[k])) + ship_stats[k] += d[k] + if ship_stats['deltav'] <= 0: + self.end(false, "Ran out of fuel") + if ship_stats['health'] <= 0: + self.end(false, "Your ship fell apart") + if ship_stats['supplies'] <= 0: + self.end(false, "You ran out of supplies") + if ship_stats['supplies'] > 1000: + ship_stats['supplies'] = 1000; + if ship_stats['deltav'] > 1000: + ship_stats['deltav'] = 1000 + if ship_stats['health'] > 1000: + ship_stats['health'] = 1000 + + emit_signal("stats_updated") + +func get_supply_upkeep(): + var upkeep = 0 + var x = 0 + while x < len(ship_stats['crew']): + upkeep += ship_stats['crew'][x]['upkeep'] + #if ship_stats['crew'][x]['morale'] != null: + # upkeep += ship_stats['crew'][x]['upkeep'] * + x += 1 + return upkeep + +func update_orbit(d): + for k in d.keys(): + if k == "altitude": + var old = orbit_stats[k] + if (orbit_stats[k] + d[k]) < orbit_stats[k]: + orbit_stats["record_low"] = orbit_stats[k] + d[k] + if d[k] is Vector2: + orbit_stats[k] = d[k] + else: + print("Orbit change for " + k) + print("\tOld: " + str(orbit_stats[k])) + print("\tNew: " + str(orbit_stats[k] + d[k])) + orbit_stats[k] += d[k] + emit_signal("orbit_updated") + +func update_crew(d): + var c = len(ship_stats['crew'])-1 + while c >= 0: + for k in d.keys(): + if ship_stats['crew'][c][k] != null: + ship_stats['crew'][c][k] += d[k] + if ship_stats['crew'][c][k] <= 0: + print("Crew #" + str(c) + " has taken a walk on the wrong side of the hull due to low " + k) + ship_stats['crew'].remove(c) + + c -= 1 + emit_signal("crew_updated") + +func end(win_or_fail, reason): + # Load the dialog + print("ending: " + str(win_or_fail) + " " + reason) + var e = ResourceLoader.load("res://src/ui/End.tscn").instance() + e.initialize(win_or_fail, reason) + self.add_child(e) + e.popup_centered() + self.current_state = 9 + # Called every frame. 'delta' is the elapsed time since the previous frame. #func _process(delta): # pass diff --git a/src/ui/ChooseFlightIn.gd b/src/ui/ChooseFlightIn.gd index 78d4ddd..817d3bd 100644 --- a/src/ui/ChooseFlightIn.gd +++ b/src/ui/ChooseFlightIn.gd @@ -5,7 +5,6 @@ extends Node2D # var a = 2 # var b = "text" - # Called when the node enters the scene tree for the first time. func _ready(): if GameState.difficulty == null: diff --git a/src/ui/ChooseFlightIn.tscn b/src/ui/ChooseFlightIn.tscn index c226027..50bcc11 100644 --- a/src/ui/ChooseFlightIn.tscn +++ b/src/ui/ChooseFlightIn.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=5 format=2] +[gd_scene load_steps=6 format=2] [ext_resource path="res://src/ui/ChooseFlightIn.gd" type="Script" id=1] [ext_resource path="res://src/ui/Map.tscn" type="PackedScene" id=2] [ext_resource path="res://src/ui/ShipStats.tscn" type="PackedScene" id=3] [ext_resource path="res://src/ui/CrewUI.tscn" type="PackedScene" id=4] +[ext_resource path="res://src/ui/GameMenu.tscn" type="PackedScene" id=5] [node name="ChooseFlightIn" type="Node2D"] script = ExtResource( 1 ) @@ -42,3 +43,5 @@ text = "Engage" __meta__ = { "_edit_use_anchors_": false } + +[node name="GameMenu" parent="." instance=ExtResource( 5 )] diff --git a/src/ui/CrewUI.gd b/src/ui/CrewUI.gd index eeb2632..e01747a 100644 --- a/src/ui/CrewUI.gd +++ b/src/ui/CrewUI.gd @@ -12,9 +12,19 @@ var current_page = 0 var entries = {} func _ready(): + self.current_page = 0 + GameState.connect("crew_updated", self, "_on_crew_update") + self.draw_crew() + +func _on_crew_update(): + for c in get_tree().get_nodes_in_group("CrewEntries"): + c.set_visible(false) + c.call_deferred("free") + self.draw_crew() + +func draw_crew(): self.entries = {} var count = len(GameState.ship_stats['crew']) - self.current_page = 0 var max_pages = (count / self.crew_per_page) + 1 self.print_tree_pretty() if self.current_page == 0: @@ -28,6 +38,7 @@ func _ready(): var e = crew_entry_ui.instance(); e.initialize(c) entries[c['id']] = e + e.add_to_group("CrewEntries") e.set_custom_minimum_size(Vector2(100, 137)) var x = 0 + (current_page * crew_per_page); var limit = x + crew_per_page diff --git a/src/ui/Dialogue.gd b/src/ui/Dialogue.gd index 2f5453f..d0ce031 100644 --- a/src/ui/Dialogue.gd +++ b/src/ui/Dialogue.gd @@ -50,11 +50,11 @@ func process_step(id): self.find_node("Text").append_bbcode("[b]" + action["args"][0] + ": [/b]") self.find_node("Text").append_bbcode(action["args"][1] + "\n") elif action["type"] == "wait_for_space": - self.find_node("Text").append_bbcode("[center][i]Hit space to continue[/i][/center]\n") + self.find_node("Text").append_bbcode("[center][i][pulse color=#00FFAA height=0.0 freq=4.0]Hit space to continue[/pulse][/i][/center]\n") self.waiting = true self.wait_condition = "space" elif action["type"] == "wait_for_key": - self.find_node("Text").append_bbcode("[center][i]Press any key to continue[/i][/center]\n") + self.find_node("Text").append_bbcode("[center][i][pulse color=#00FFAA height=0.0 freq=4.0]Press any key to continue[/pulse][/i][/center]\n") self.waiting = true self.wait_condition = action["args"] diff --git a/src/ui/Dialogue.tscn b/src/ui/Dialogue.tscn index 4292b2f..1a6e091 100644 --- a/src/ui/Dialogue.tscn +++ b/src/ui/Dialogue.tscn @@ -1,6 +1,10 @@ -[gd_scene load_steps=2 format=2] +[gd_scene load_steps=4 format=2] [ext_resource path="res://src/ui/Dialogue.gd" type="Script" id=1] +[ext_resource path="res://src/ui/FlashText.gd" type="Script" id=2] + +[sub_resource type="RichTextEffect" id=1] +script = ExtResource( 2 ) [node name="Control" type="Control"] anchor_right = 1.0 @@ -29,6 +33,8 @@ margin_right = 200.0 margin_bottom = 564.0 rect_min_size = Vector2( 0, 360 ) bbcode_enabled = true +scroll_following = true +custom_effects = [ SubResource( 1 ) ] [node name="ChoiceContainer" type="HBoxContainer" parent="VBoxContainer"] margin_top = 568.0 diff --git a/src/ui/DifficultySelector.tscn b/src/ui/DifficultySelector.tscn index 7246eac..9f9ae54 100644 --- a/src/ui/DifficultySelector.tscn +++ b/src/ui/DifficultySelector.tscn @@ -53,6 +53,8 @@ margin_top = 304.0 margin_right = 300.0 margin_bottom = 404.0 rect_min_size = Vector2( 0, 100 ) +bbcode_enabled = true +bbcode_text = "[center]Easy[/center]" text = "Easy" [node name="VBoxContainer3" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] @@ -77,6 +79,8 @@ margin_top = 304.0 margin_right = 300.0 margin_bottom = 404.0 rect_min_size = Vector2( 0, 100 ) +bbcode_enabled = true +bbcode_text = "[center]Medium[/center]" text = "Medium" [node name="VBoxContainer2" type="VBoxContainer" parent="VBoxContainer/HBoxContainer"] @@ -96,15 +100,13 @@ __meta__ = { "_editor_description_": "Easy" } -[node name="MarginContainer" type="MarginContainer" parent="VBoxContainer/HBoxContainer/VBoxContainer2"] +[node name="RichTextLabel" type="RichTextLabel" parent="VBoxContainer/HBoxContainer/VBoxContainer2"] margin_top = 304.0 margin_right = 300.0 margin_bottom = 404.0 - -[node name="RichTextLabel" type="RichTextLabel" parent="VBoxContainer/HBoxContainer/VBoxContainer2/MarginContainer"] -margin_right = 300.0 -margin_bottom = 100.0 rect_min_size = Vector2( 0, 100 ) +bbcode_enabled = true +bbcode_text = "[center]Hard[/center]" text = "Hard" [node name="StartButton" type="Button" parent="VBoxContainer"] diff --git a/src/ui/Encounter.gd b/src/ui/Encounter.gd new file mode 100644 index 0000000..c73aa1a --- /dev/null +++ b/src/ui/Encounter.gd @@ -0,0 +1,100 @@ +extends PopupPanel + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" +signal encounter_complete + +var data = null +# Called when the node enters the scene tree for the first time. +func _ready(): + pass + #if true: + # self.initialize(GameState.EncounterData["ArtificialSatellite"]["situations"][0]) + +func initialize(d): + #for c in get_tree().get_nodes_in_group("ChoiceButtons"): + # c.deferred_call("free") + self.data = d + get_node("V/Title").set_bbcode("[center]" + data["title"] + "[/center]") + get_node("V/Description").set_bbcode(data["text"]) + if data["picture"]: + get_node("V/Picture").set_texture(ResourceLoader.load(data['picture'])) + for i in data['choices'].keys(): + var b = Button.new() + b.set_text(data['choices'][i]['title']) + var tt = data['choices'][i]['tooltip'] + if GameState.debug: + tt += "\n" + var index = 0 + for r in data['choices'][i]['results'].keys(): + var chance = 0 + if index + 1 < len(data['choices'][i]['results'].keys()): + chance = data['choices'][i]['results'].keys()[index+1] - r + else: + chance = 100 - r + tt += str(chance) + "% chance of " + data['choices'][i]['results'][r]['title'] + "\n" + index += 1 + b.set_tooltip(tt) + b.add_to_group("ChoiceButtons") + get_node("V/Menu").add_child(b) + b.connect("pressed", self, "_on_choice_made", [i]) + +func _on_choice_made(index): + for c in get_tree().get_nodes_in_group("ChoiceButtons"): + c.set_disabled(true) + var prev = 0 + var result_indices = self.data["choices"][index]["results"].keys() + var result = null + var chance = GameState.rng.randi_range(0, 100) + print(chance) + var i = len(result_indices) - 1 + while i >= 0: + if chance >= result_indices[i]: + result = result_indices[i] + break + else: + i -= 1 + print(result) + #print(self.data["choices"][index]["results"][result]) + var action = self.data["choices"][index]["results"][result] + if action.has("stat_changes"): + GameState.update_stats(action["stat_changes"]) + if action.has("orbit_changes"): + GameState.update_orbit(action["orbit_changes"]) + if action.has("crew_changes"): + GameState.update_crew(action["crew_changes"]) + print(action) + var t = RichTextLabel.new() + t.set_use_bbcode(true) + var text = self.data["choices"][index]["then"] + if action.has("text"): + text += "\n\n" + action['text'] + if action.has("stat_changes") and action["stat_changes"]: + print("yes") + text += "\n\n[center]Effects:[/center]\n" + for k in action["stat_changes"].keys(): + print(k) + var value = action["stat_changes"][k] + var color = "green" + if value < 0: + color = "red" + print(color) + var addition = k + ": [color=" + color + "]" + str(value) + "[/color]\n" + print(addition) + text += addition + t.set_bbcode(text) + t.set_fit_content_height(true) + get_node("V").add_child(t) + var exit = Button.new() + exit.set_text("Continue") + get_node("V").add_child(exit) + exit.connect("pressed", self, "_on_exit_pressed") + +func _on_exit_pressed(): + emit_signal("encounter_complete") + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass diff --git a/src/ui/Encounter.tscn b/src/ui/Encounter.tscn new file mode 100644 index 0000000..9c3b215 --- /dev/null +++ b/src/ui/Encounter.tscn @@ -0,0 +1,47 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://src/ui/Encounter.gd" type="Script" id=1] + +[node name="Control" type="PopupPanel"] +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 1.0 +margin_top = 0.122467 +margin_right = -418.0 +margin_bottom = -181.878 +popup_exclusive = true +script = ExtResource( 1 ) + +[node name="V" type="VBoxContainer" parent="."] +margin_left = 15.8978 +margin_top = 17.6123 +margin_right = 591.898 +margin_bottom = 57.6123 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Title" type="RichTextLabel" parent="V"] +margin_right = 576.0 +margin_bottom = 15.0 +bbcode_enabled = true +bbcode_text = "[center]Title[/center]" +text = "Title" +fit_content_height = true + +[node name="Picture" type="TextureRect" parent="V"] +margin_top = 19.0 +margin_right = 576.0 +margin_bottom = 19.0 + +[node name="Description" type="RichTextLabel" parent="V"] +margin_top = 23.0 +margin_right = 576.0 +margin_bottom = 23.0 +bbcode_enabled = true +fit_content_height = true + +[node name="Menu" type="VBoxContainer" parent="V"] +margin_top = 27.0 +margin_right = 576.0 +margin_bottom = 27.0 diff --git a/src/ui/EncounterChoice.gd b/src/ui/EncounterChoice.gd index f5ad01f..a729f30 100644 --- a/src/ui/EncounterChoice.gd +++ b/src/ui/EncounterChoice.gd @@ -8,6 +8,7 @@ extends Node2D signal encounter_choice_changed var choices = 3 +var level = 0 var buttonNames = [ "Option0", "Option1", @@ -20,7 +21,8 @@ func _ready(): var button = self.find_node(n) button.connect("toggled", self, "_on_option_button_pressed", [n]) -func initialize(nOptions = null): +func initialize(l = null, nOptions = null): + self.level = l if nOptions != null: self.choices = nOptions var x = 0 @@ -34,6 +36,17 @@ func activate_options(): if c.visible: c.set_disabled(false) +func active_visited(): + var i = self.get_active_option_index() + if i == null: + print(self.get_name() + " has no active option index") + return false + if self.level == null: + print(self.get_name() + " does not have self.level set") + return false + print("Level " + str(self.level) + " is visited: " + str(GameState.encounters[self.level][i]['visited'])) + return GameState.encounters[self.level][i]['visited'] + func disable_options(): for c in self.get_children(): if c.visible: @@ -42,16 +55,25 @@ func disable_options(): func get_active_option_index(): var x = 0 for c in self.get_children(): + if not c.is_visible(): + x += 1 + continue if c.is_pressed(): return x else: x += 1 return null + +func get_active_position(): + var i = get_active_option_index() + if i == null: + return null + return get_node("Option" + str(i)).get_global_position() func has_active(): var active = false for n in buttonNames: - active = active or self.get_node(n).is_pressed() + active = active or (self.get_node(n).is_pressed() and self.get_node(n).is_visible()) return active func _on_option_button_pressed(state, buttonName): diff --git a/src/ui/Encounters.gd b/src/ui/Encounters.gd new file mode 100644 index 0000000..fdfd452 --- /dev/null +++ b/src/ui/Encounters.gd @@ -0,0 +1,78 @@ +extends Node2D + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +var going_deeper = null +var direction = 1 +# Called when the node enters the scene tree for the first time. +func _ready(): + # This is for debugging when choosing the scene directly. + if GameState.current_state == 0: + GameState.current_state = 5 + GameState.current_scene = self + # End + + if GameState.current_state == 8: + direction = -1 + var encounter = get_node("Map/Level" + str(GameState.current_depth)) + if encounter: + GameState.ship_stats["target_position"] = encounter.get_active_position() + get_node("Map").connect("ship_arrived", self, "_on_ship_arrived") + +func _on_ship_arrived(): + #var encounter = get_node("Map/Level" + str(GameState.current_depth)) + #if not encounter: + # return + # + if GameState.current_state != 5 and GameState.current_state != 8: + return + var index = get_node("Map/Level" + str(GameState.current_depth)).get_active_option_index() + GameState.encounters[GameState.current_depth][index]['visited'] = true + get_node("Map").draw_course() + var e = GameState.encounters[GameState.current_depth] + print(e[index]) + var instance = GameState.generate_encounter_instance(e, GameState.current_depth, index) + instance.add_to_group("Encounters") + self.add_child(instance) + instance.connect("encounter_complete", self, "_on_encounter_complete", [instance]) + instance.popup_centered() + +func _on_encounter_complete(instance): + instance.set_visible(false) + self.next_encounter() + +func next_encounter(): + print(GameState.current_depth) + print(GameState.current_state) + if GameState.current_state != 5 and GameState.current_state != 8: + return + if (self.direction == 1 and GameState.current_depth < (len(GameState.encounters) - 1)) \ + or (self.direction == -1 and GameState.current_depth > 0): + GameState.current_depth += self.direction + GameState.update_stats({ + "deltav": -GameState.orbit_stats["drag"], + "supplies": -GameState.get_supply_upkeep(), + }) + if get_node("Map/Level" + str(GameState.current_depth)): + GameState.update_stats({ + "target_position": get_node("Map/Level" + str(GameState.current_depth)).get_active_position(), + }) + GameState.update_orbit({ + "altitude": -self.direction * (GameState.get_difficulty_data("starting_altitude") - GameState.get_difficulty_data("minimum_altitude")) / len(GameState.encounters) + }) + else: + # Provide a choice: go deeper more reward, or start the journey out. + # Ignore going_deeper for the moment, just try to get out + if GameState.current_state == 5: + print("Going for flight out") + GameState.choose_flightpath_out() + elif GameState.current_state == 8: + GameState.end(true, "You made it out") + # These will be re-ordered +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass diff --git a/src/ui/Encounters.tscn b/src/ui/Encounters.tscn index f83b4fe..0b6b30c 100644 --- a/src/ui/Encounters.tscn +++ b/src/ui/Encounters.tscn @@ -1,13 +1,21 @@ -[gd_scene load_steps=4 format=2] +[gd_scene load_steps=6 format=2] [ext_resource path="res://src/ui/Map.tscn" type="PackedScene" id=1] [ext_resource path="res://src/ui/ShipStats.tscn" type="PackedScene" id=2] [ext_resource path="res://src/ui/CrewUI.tscn" type="PackedScene" id=3] +[ext_resource path="res://src/ui/Encounters.gd" type="Script" id=4] +[ext_resource path="res://src/ui/GameMenu.tscn" type="PackedScene" id=5] [node name="Encounters" type="Node2D"] +script = ExtResource( 4 ) [node name="Map" parent="." instance=ExtResource( 1 )] [node name="CrewUI" parent="." instance=ExtResource( 3 )] [node name="Control" parent="." instance=ExtResource( 2 )] + +[node name="GameMenu" parent="." instance=ExtResource( 5 )] +popup_exclusive = false +hide_on_item_selection = false +hide_on_checkable_item_selection = false diff --git a/src/ui/End.gd b/src/ui/End.gd new file mode 100644 index 0000000..4772e59 --- /dev/null +++ b/src/ui/End.gd @@ -0,0 +1,36 @@ +extends PopupPanel + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass # Replace with function body. + +func initialize(state, reason): + var t = "" + if state: + t = "[center][rainbow freq=0.5 sat=2 val=200]You won![/rainbow][/center]\n\n" + + else: + t = "[center][color=red]You lost![/color][/center]\n\n" + t += "[center]Because: " + reason + "[/center]\n\n" + t += "[center]Low Score: " + str(GameState.orbit_stats['record_low']) + " (lower is better!) [/center]" + get_node("VBoxContainer/Label").set_bbcode(t) + + +func _on_New_pressed(): + self.call_deferred("free") + GameState.reset_to_new() + + +func _on_Main_pressed(): + self.call_deferred("free") + GameState.reset_to_main_menu() + + +func _on_Exit_pressed(): + get_tree().quit() diff --git a/src/ui/End.tscn b/src/ui/End.tscn new file mode 100644 index 0000000..f121dbd --- /dev/null +++ b/src/ui/End.tscn @@ -0,0 +1,58 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://src/ui/End.gd" type="Script" id=1] + +[node name="End" type="PopupPanel"] +anchor_right = 0.81 +anchor_bottom = 0.719 +margin_right = -2.44006 +margin_bottom = 3.59998 +popup_exclusive = true +script = ExtResource( 1 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +margin_left = 8.0 +margin_top = 47.0 +margin_right = 825.0 +margin_bottom = 377.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Label" type="RichTextLabel" parent="VBoxContainer"] +margin_right = 817.0 +margin_bottom = 15.0 +bbcode_enabled = true +fit_content_height = true +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Picture" type="TextureRect" parent="VBoxContainer"] +margin_top = 19.0 +margin_right = 817.0 +margin_bottom = 19.0 + +[node name="New" type="Button" parent="VBoxContainer"] +margin_top = 23.0 +margin_right = 817.0 +margin_bottom = 43.0 +text = "New Game" + +[node name="Main" type="Button" parent="VBoxContainer"] +margin_top = 47.0 +margin_right = 817.0 +margin_bottom = 67.0 +text = "Back to Main Menu" + +[node name="Exit" type="Button" parent="VBoxContainer"] +margin_top = 71.0 +margin_right = 817.0 +margin_bottom = 91.0 +text = "Exit to Desktop" +[connection signal="pressed" from="VBoxContainer/New" to="." method="_on_New_pressed"] +[connection signal="pressed" from="VBoxContainer/Main" to="." method="_on_Main_pressed"] +[connection signal="pressed" from="VBoxContainer/Exit" to="." method="_on_Exit_pressed"] diff --git a/src/ui/FlashText.gd b/src/ui/FlashText.gd new file mode 100644 index 0000000..86a0e7f --- /dev/null +++ b/src/ui/FlashText.gd @@ -0,0 +1,22 @@ +tool +extends RichTextEffect +class_name RichTextPulse + +# @see https://docs.godotengine.org/en/latest/tutorials/ui/bbcode_in_richtextlabel.html +# Syntax: [pulse color=#00FFAA height=0.0 freq=2.0][/pulse] + +# Define the tag name. +var bbcode = "pulse" + +func _process_custom_fx(char_fx): + # Get parameters, or use the provided default value if missing. + var color = char_fx.env.get("color", char_fx.color) + var height = char_fx.env.get("height", 0.0) + var freq = char_fx.env.get("freq", 2.0) + + var sined_time = (sin(char_fx.elapsed_time * freq) + 1.0) / 2.0 + var y_off = sined_time * height + color.a = 1.0 + char_fx.color = char_fx.color.linear_interpolate(color, sined_time) + char_fx.offset = Vector2(0, -1) * y_off + return true diff --git a/src/ui/GameMenu.gd b/src/ui/GameMenu.gd new file mode 100644 index 0000000..b5c711c --- /dev/null +++ b/src/ui/GameMenu.gd @@ -0,0 +1,33 @@ +extends PopupMenu + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +# Called when the node enters the scene tree for the first time. +func _ready(): + pass +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass + +func _input(_ev): + if Input.is_action_just_pressed("ui_cancel"): + var menu = self + if menu.is_visible(): + menu.set_visible(false) + else: + menu.popup_centered(); + +func _on_ContinueButton_pressed(): + self.set_visible(false) + + +func _on_ExitGameButton_pressed(): + get_tree().quit() + + +func _on_LeaveGameButton_pressed(): + GameState.reset_to_main_menu() diff --git a/src/ui/GameMenu.tscn b/src/ui/GameMenu.tscn index 6389cf3..0f1250e 100644 --- a/src/ui/GameMenu.tscn +++ b/src/ui/GameMenu.tscn @@ -1,76 +1,48 @@ -[gd_scene format=2] +[gd_scene load_steps=2 format=2] -[node name="GameMenu" type="Control"] +[ext_resource path="res://src/ui/GameMenu.gd" type="Script" id=1] + +[node name="GameMenu" type="PopupMenu"] anchor_right = 0.5 anchor_bottom = 0.5 +popup_exclusive = true +script = ExtResource( 1 ) + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +anchor_left = 0.32 +anchor_top = 0.419 +anchor_right = 0.32 +anchor_bottom = 0.419 +margin_left = -2.58704 +margin_top = -25.0283 +margin_right = 174.413 +margin_bottom = 66.9717 __meta__ = { "_edit_use_anchors_": false } -[node name="ContinueButton" type="MenuButton" parent="."] -margin_left = 158.967 -margin_top = 115.601 -margin_right = 397.967 -margin_bottom = 135.601 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="RichTextLabel" type="RichTextLabel" parent="ContinueButton"] -margin_right = 76.0 -margin_bottom = 40.0 -text = "Continue" -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="HelpButton" type="MenuButton" parent="."] -margin_left = 160.494 -margin_top = 140.127 -margin_right = 448.494 -margin_bottom = 160.127 -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="RichTextLabel" type="RichTextLabel" parent="HelpButton"] -anchor_right = 0.069 -anchor_bottom = 1.0 -margin_right = 20.128 +[node name="ContinueButton" type="Button" parent="VBoxContainer"] +margin_right = 177.0 margin_bottom = 20.0 +text = "Continue" + +[node name="HelpButton" type="Button" parent="VBoxContainer"] +margin_top = 24.0 +margin_right = 177.0 +margin_bottom = 44.0 text = "Help" -__meta__ = { -"_edit_use_anchors_": false -} -[node name="LeaveGameButton" type="MenuButton" parent="."] -anchor_right = 0.246 -anchor_bottom = 0.033 -margin_right = -239.904 -margin_bottom = 0.200001 +[node name="LeaveGameButton" type="Button" parent="VBoxContainer"] +margin_top = 48.0 +margin_right = 177.0 +margin_bottom = 68.0 +text = "Abandon the Diligent" -[node name="RichTextLabel" type="RichTextLabel" parent="LeaveGameButton"] -margin_left = 157.858 -margin_top = 167.583 -margin_right = 297.858 -margin_bottom = 192.583 -text = "Abandon Game" -__meta__ = { -"_edit_use_anchors_": false -} - -[node name="ExitGameButton" type="MenuButton" parent="."] -margin_left = 90.8717 -margin_top = 99.7807 -margin_right = 114.872 -margin_bottom = 124.781 - -[node name="RichTextLabel" type="RichTextLabel" parent="ExitGameButton"] -margin_left = 67.7083 -margin_top = 96.2171 -margin_right = 238.708 -margin_bottom = 118.217 -text = "End Program" -__meta__ = { -"_edit_use_anchors_": false -} +[node name="ExitGameButton" type="Button" parent="VBoxContainer"] +margin_top = 72.0 +margin_right = 177.0 +margin_bottom = 92.0 +text = "Exit to Desktop" +[connection signal="pressed" from="VBoxContainer/ContinueButton" to="." method="_on_ContinueButton_pressed"] +[connection signal="pressed" from="VBoxContainer/LeaveGameButton" to="." method="_on_LeaveGameButton_pressed"] +[connection signal="pressed" from="VBoxContainer/ExitGameButton" to="." method="_on_ExitGameButton_pressed"] diff --git a/src/ui/Intro.gd b/src/ui/Intro.gd index a80f335..37a950b 100644 --- a/src/ui/Intro.gd +++ b/src/ui/Intro.gd @@ -48,6 +48,13 @@ var dialogue = { } ], 1.5: [ + { + "type": "add_line", + "args": [ + "*thinking*", + "Did I hear warp crystal?? We desperately need one if we're to return to Earth...\n\n", + ] + }, { "type": "add_line", "args": [ @@ -76,12 +83,12 @@ func _ready(): func _input(_ev): - if Input.is_key_pressed(KEY_ESCAPE): + if Input.is_action_just_pressed("ui_cancel"): self.end() func end(): # Leave introduction - find_node("Dialogue").end() + get_node("Dialogue").end() GameState.end_introduction() diff --git a/src/ui/MainMenu.gd b/src/ui/MainMenu.gd index 9b8b0a9..a2b073f 100644 --- a/src/ui/MainMenu.gd +++ b/src/ui/MainMenu.gd @@ -23,3 +23,10 @@ func _on_start_button_pressed(): self.find_node("DifficultySelector").find_node("StartButton").disconnect("pressed", self, "_on_start_button_pressed") GameState.initialize(chosen_difficulty) GameState.start_introduction() + +func _input(_ev): + if Input.is_action_just_pressed("ui_cancel"): + self._on_Exit_pressed() + +func _on_Exit_pressed(): + get_tree().quit() diff --git a/src/ui/MainMenu.tscn b/src/ui/MainMenu.tscn index 09413bd..570f895 100644 --- a/src/ui/MainMenu.tscn +++ b/src/ui/MainMenu.tscn @@ -9,16 +9,44 @@ script = ExtResource( 1 ) [node name="DifficultySelector" parent="." instance=ExtResource( 2 )] anchor_right = 0.0 anchor_bottom = 0.0 -margin_left = 56.1231 -margin_top = 130.328 -margin_right = 56.1231 -margin_bottom = 130.328 +margin_left = 57.1825 +margin_top = 132.447 +margin_right = 57.1825 +margin_bottom = 132.447 [node name="Title" type="RichTextLabel" parent="."] margin_right = 1026.0 margin_bottom = 129.0 -text = "Title: Gravity Well Diver -" +rect_scale = Vector2( 1.00797, 1 ) +bbcode_enabled = true +bbcode_text = " + + +[center][rainbow freq=0.5 sat=2 val=200]Gravity Limbo[/rainbow][/center] + +[center]How low can you go?[/center] + +[center]P.S. You need to make it back up too :)[/center]" +text = " + + +Gravity Limbo + +How low can you go? + +P.S. You need to make it back up too :)" __meta__ = { "_edit_use_anchors_": false } + +[node name="Exit" type="Button" parent="."] +margin_left = 372.34 +margin_top = 571.059 +margin_right = 654.34 +margin_bottom = 591.059 +text = "Quit" +__meta__ = { +"_edit_use_anchors_": false, +"_editor_description_": "Quit" +} +[connection signal="pressed" from="Exit" to="." method="_on_Exit_pressed"] diff --git a/src/ui/Map.gd b/src/ui/Map.gd index 8aa096f..bb74929 100644 --- a/src/ui/Map.gd +++ b/src/ui/Map.gd @@ -5,20 +5,28 @@ extends Node2D # var a = 2 # var b = "text" +signal ship_arrived + +var ship_moving = false # Called when the node enters the scene tree for the first time. func _ready(): # For testing + var started_ourselves = false if GameState.difficulty == null: GameState.initialize(0) - self.find_node("Planet").set_texture(ResourceLoader.load(GameState.get_difficulty_data("planet"))) + started_ourselves = true + + # + self.get_node("Ship").set_global_position(GameState.ship_stats['starting_position']) + self.get_node("Planet").set_texture(ResourceLoader.load(GameState.get_difficulty_data("planet"))) var encounterChoice = ResourceLoader.load("res://src/ui/EncounterChoice.tscn") for level in GameState.encounters.keys(): print(level) var name = "Level" + str(level) var choice = encounterChoice.instance() - choice.name = name - choice.initialize(len(GameState.encounters[level])) + choice.set_name(name) + choice.initialize(level, len(GameState.encounters[level])) choice.set_global_position(get_node("Level" + str(level) + "Location").get_global_position()) choice.set_global_rotation(get_node("Level" + str(level) + "Location").get_global_rotation()) choice.set_global_scale(get_node("Level" + str(level) + "Location").get_global_scale()) @@ -39,18 +47,73 @@ func _ready(): n.set_normal_texture(texture) if texture_pressed: n.set_pressed_texture(texture_pressed) - n.set_disabled(true) + #n.set_disabled(true) n.set_tooltip(GameState.encounters[level][x]["type"]) - if GameState.encounters[level][x]["selected"]: + if GameState.encounters[level][x]["selected"] or (x == 0 and started_ourselves): # The texture change is used since when disabled the normal_texture is shown regardless of press state. n.set_pressed(true) - n.set_normal_texture(n.get_pressed_texture()) + choice._on_option_button_pressed(true, "Option" + str(x)) + #n.set_normal_texture(n.get_pressed_texture()) + if GameState.encounters[level][x]["visited"]: + n.set_visible(false) x += 1 if GameState.current_state == 4: # picking course choice.activate_options() self.add_child(choice) - + choice.add_to_group("Levels") + choice.connect("encounter_choice_changed", self, "_on_encounter_choice_changed") + self.draw_course() + +func _process(delta): + var s = get_node("Ship") + #print(GameState.ship_stats["target_position"]) + if s.get_global_position().distance_to(GameState.ship_stats["target_position"]) >= 5: + ship_moving = true + s.set_global_position(s.get_global_position().move_toward(GameState.ship_stats["target_position"], 5.0)) + else: + if ship_moving: + emit_signal("ship_arrived") + draw_course() + ship_moving = false + +func _on_encounter_choice_changed(): + draw_course() + +func draw_course(): + # A bit brutal + for p in get_tree().get_nodes_in_group("Course"): + print(p.get_name()) + p.set_visible(false) + p.call_deferred("free") + + var x = 0 + var pairs = [] + while x < (len(GameState.encounters) - 1): + pairs.append([x, x+1]) + x += 1 + var paths = [] + print(pairs) + for p in pairs: + var first = get_node("Level" + str(p[0])) + var second = get_node("Level" + str(p[1])) + if not first or not second: + print("One is null: " + str(p)) + continue + if not first.has_active() or not second.has_active(): + print("One has no active: " + str(p)) + continue + if second.active_visited(): + print("Second has a visited active choice: " + str(p)) + continue + var l = Line2D.new() + l.add_point(first.get_active_position()) + l.add_point(second.get_active_position()) + l.set_z_index(-1) + self.add_child(l) + l.add_to_group("Course") + + # Called every frame. 'delta' is the elapsed time since the previous frame. #func _process(delta): # pass diff --git a/src/ui/Map.tscn b/src/ui/Map.tscn index 32cdea7..e5ecace 100644 --- a/src/ui/Map.tscn +++ b/src/ui/Map.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=3 format=2] +[gd_scene load_steps=4 format=2] [ext_resource path="res://assets/planet placeholder.png" type="Texture" id=1] [ext_resource path="res://src/ui/Map.gd" type="Script" id=2] +[ext_resource path="res://assets/encounterIconGases.png" type="Texture" id=3] [node name="Map" type="Node2D"] script = ExtResource( 2 ) @@ -43,8 +44,6 @@ scale = Vector2( 1.05, 1.05 ) [node name="Level5Location" type="Node2D" parent="."] position = Vector2( 506.488, 220.486 ) -[node name="Line2D" type="Line2D" parent="."] -visible = false -points = PoolVector2Array( 674.571, 84.9249, 667.428, 67.4635, 654.729, 50.0021, 622.187, 36.5092, 550.754, 19.8415, 449.16, 13.4919, 357.091, 18.2541, 229.305, 36.5092, 118.981, 68.2572 ) -width = 5.0 -default_color = Color( 0.545098, 1, 0.4, 1 ) +[node name="Ship" type="Sprite" parent="."] +position = Vector2( 1.5874, 3.96851 ) +texture = ExtResource( 3 ) diff --git a/src/ui/ShipStats.gd b/src/ui/ShipStats.gd index 189803f..45c5f29 100644 --- a/src/ui/ShipStats.gd +++ b/src/ui/ShipStats.gd @@ -8,23 +8,35 @@ extends Control # Called when the node enters the scene tree for the first time. func _ready(): - connect("ship_stats_changed", self, "_on_update_stats") + GameState.connect("stats_updated", self, "_on_update_stats") + GameState.connect("orbit_updated", self, "_on_update_stats") self.update_stats() func _on_update_stats(): self.update_stats() func update_stats(): - get_node("Container/Health").set_value(GameState.ship_stats["health"]) - get_node("Container/Supplies").set_value(GameState.ship_stats["supplies"]) - get_node("Container/Crew").set_value(len(GameState.ship_stats["crew"])) - get_node("Container/Crew").set_max(GameState.get_difficulty_data("maximum_crew")) - get_node("Container/DeltaV").set_bbcode("[center]" + str(GameState.ship_stats["deltav"]) + " DeltaV[/center]") - get_node("Container/Altitude").set_value(GameState.orbit_stats["altitude"]) - get_node("Container/Altitude").set_max(GameState.get_difficulty_data("starting_altitude")) - get_node("Container/Altitude").set_min(GameState.get_difficulty_data("minimum_altitude")) - get_node("Container/AltitudeLabel").set_bbcode("[center]xxx / yyy[/center]") - get_node("Container/DragContainer/Drag").set_text(str(GameState.orbit_stats["drag"])) + get_node("Container/Health").set_text( + "Health: " + str(GameState.ship_stats["health"]) + " / 1000" + ) + get_node("Container/Supplies").set_text( + "Supplies: " + str(GameState.ship_stats["supplies"]) + " / 1000 [upkeep: " + str(GameState.get_supply_upkeep()) +"]" + ) + get_node("Container/Crew").set_bbcode( + "Crew: " + str(len(GameState.ship_stats["crew"])) + " / " \ + + str(GameState.get_difficulty_data("maximum_crew")) + ) + get_node("Container/DeltaV").set_bbcode("DeltaV: " + str(GameState.ship_stats["deltav"])) + get_node("Container/Altitude").set_text( + "Altitude: " + str(GameState.orbit_stats["altitude"]) + " [minimum: " \ + + str(GameState.get_difficulty_data("minimum_altitude")) + "]" + ) + get_node("Container/Drag").set_text( + "Drag: " + str(GameState.orbit_stats["drag"]) + ) + get_node("Container/LowestOrbit").set_text( + "Lowest orbit: " + str(GameState.orbit_stats["record_low"]) + ) # Called every frame. 'delta' is the elapsed time since the previous frame. #func _process(delta): diff --git a/src/ui/ShipStats.tscn b/src/ui/ShipStats.tscn index 7876b9f..3cd98ee 100644 --- a/src/ui/ShipStats.tscn +++ b/src/ui/ShipStats.tscn @@ -33,98 +33,62 @@ bbcode_text = "[center]Ship Statistics[/center]" text = "Ship Statistics" fit_content_height = true -[node name="Health" type="ProgressBar" parent="Container"] +[node name="Health" type="RichTextLabel" parent="Container"] margin_top = 19.0 margin_right = 255.0 -margin_bottom = 33.0 -max_value = 1000.0 -step = 1.0 +margin_bottom = 34.0 +fit_content_height = true -[node name="Supplies" type="ProgressBar" parent="Container"] -margin_top = 37.0 +[node name="Supplies" type="RichTextLabel" parent="Container"] +margin_top = 38.0 margin_right = 255.0 -margin_bottom = 51.0 -max_value = 1000.0 -step = 1.0 +margin_bottom = 53.0 +fit_content_height = true -[node name="Crew" type="ProgressBar" parent="Container"] -margin_top = 55.0 +[node name="Crew" type="RichTextLabel" parent="Container"] +margin_top = 57.0 margin_right = 255.0 -margin_bottom = 69.0 -min_value = 1.0 -max_value = 15.0 -step = 1.0 -value = 1.0 +margin_bottom = 72.0 +bbcode_enabled = true +fit_content_height = true [node name="DeltaV" type="RichTextLabel" parent="Container"] -margin_top = 73.0 +margin_top = 76.0 margin_right = 255.0 -margin_bottom = 88.0 +margin_bottom = 91.0 bbcode_enabled = true bbcode_text = "[center]X / Y Δv[/center]" text = "X / Y Δv" fit_content_height = true [node name="Label" type="RichTextLabel" parent="Container"] -margin_top = 92.0 +margin_top = 95.0 margin_right = 255.0 -margin_bottom = 107.0 +margin_bottom = 110.0 bbcode_enabled = true bbcode_text = "[center]Orbit Statistics[/center]" text = "Orbit Statistics" fit_content_height = true -[node name="Altitude" type="HSlider" parent="Container"] -margin_top = 111.0 +[node name="Altitude" type="RichTextLabel" parent="Container"] +margin_top = 114.0 margin_right = 255.0 -margin_bottom = 127.0 +margin_bottom = 129.0 grow_horizontal = 2 grow_vertical = 2 rect_min_size = Vector2( 200, 0 ) -step = 1.0 -editable = false -scrollable = false - -[node name="AltitudeLabel" type="RichTextLabel" parent="Container"] -margin_top = 131.0 -margin_right = 255.0 -margin_bottom = 146.0 -bbcode_enabled = true fit_content_height = true -__meta__ = { -"_edit_use_anchors_": false -} -[node name="DragContainer" type="HBoxContainer" parent="Container"] -margin_top = 150.0 +[node name="Drag" type="RichTextLabel" parent="Container"] +margin_top = 133.0 margin_right = 255.0 -margin_bottom = 165.0 - -[node name="Label" type="Label" parent="Container/DragContainer"] -margin_right = 29.0 -margin_bottom = 14.0 -text = "Drag" - -[node name="Drag" type="RichTextLabel" parent="Container/DragContainer"] -margin_left = 33.0 -margin_right = 233.0 -margin_bottom = 15.0 +margin_bottom = 148.0 rect_min_size = Vector2( 200, 0 ) fit_content_height = true -[node name="DvContainer" type="HBoxContainer" parent="Container"] -margin_top = 169.0 +[node name="LowestOrbit" type="RichTextLabel" parent="Container"] +margin_top = 152.0 margin_right = 255.0 -margin_bottom = 184.0 - -[node name="Label" type="Label" parent="Container/DvContainer"] -margin_right = 49.0 -margin_bottom = 14.0 -text = "escp dv" - -[node name="EstEscapeDV" type="RichTextLabel" parent="Container/DvContainer"] -margin_left = 53.0 -margin_right = 253.0 -margin_bottom = 15.0 +margin_bottom = 167.0 rect_min_size = Vector2( 200, 0 ) fit_content_height = true