extends Node2D # Signals signal game_energy_changed signal game_deck_changed signal game_discard_changed signal game_hand_changed signal game_state_changed signal game_round_start var DEBUG = false # class member variables go here, for example: # var a = 2 # var b = "textvar" export(int) var energy = 100 export(int) var base_energy_per_round = 10 const ENERGY_MAX = 100 const ENERGY_MIN = 0 const SHUFFLE_REPEATS = 3 const STARTING_DECK_SIZE = 10 # Card piles: hand, deck, discard var max_hand_size = 5 var hand = [] # Index 0 = bottom for deck and discard var deck = [] var discard = [] # Game state machine ish var actions_per_round = 1 var actions_remaining = 1 var round_counter = 0 var game_state = -2 var game_win = false var game_over_message = '' var game_states = { -2: "initializing", -1: "round_start", 0: "waiting_player_action", 1: "playing_action", 2: "round_done", 3: "waiting", # Generic let something else finish 4: "event", # Some out of player control event 5: "over", } # Cards var cards = { "card_repair": preload("res://cards/card_repair.tscn"), "card_repurpose": preload("res://cards/repurpose.tscn"), "card_battery_small": preload("res://cards/battery_small.tscn"), "card_battery_big": preload("res://cards/battery_big.tscn"), "card_spare_parts": preload("res://cards/spare_parts.tscn"), "card_injured": preload('res://cards/injured.tscn'), "card_medkit": preload('res://cards/medkit.tscn'), } func _ready(): # Called every time the node is added to the scene. # Initialization here randomize() var bar = get_node("ui/EnergyHolder/ProgressBar") bar.set_min(ENERGY_MIN) bar.set_max(ENERGY_MAX) set_process(true) get_node('ui/end_message/buttons/Replay').connect('pressed', self, 'on_game_replay') get_node('ui/end_message/buttons/Quit').connect('pressed', self, 'on_game_quit') if self.DEBUG: get_node('ui/debug').show() var areas = self.get_tree().get_nodes_in_group('areas') for a in areas: a.connect('game_area_activation_changed', self, 'on_area_activation_changed') self.on_area_activation_changed(null, null) init_game() func init_game(): # Popuplate deck self.energy = ENERGY_MAX get_node('ui/EnergyHolder/ProgressBar').set_value(self.energy) self.deck = [] # Choose starting deck: self.add_card_to_deck('card_medkit') self.add_card_to_deck('card_repurpose') self.add_card_to_deck('card_spare_parts') self.add_card_to_deck('card_spare_parts') self.add_card_to_deck('card_spare_parts') self.add_card_to_deck('card_injured') self.add_card_to_deck('card_injured') self.add_card_to_deck('card_injured') self.add_card_to_deck('card_battery_small') self.add_card_to_deck('card_battery_small') self.discard = [] self.hand = [] while self.deck.size() < STARTING_DECK_SIZE: self.add_card_to_deck(null) self.shuffle() emit_signal('game_deck_changed', self.deck.size()) emit_signal('game_hand_changed', self.hand.size()) emit_signal('game_discard_changed', self.discard.size()) get_node('areas/reactor').set_health(0) self.update_game_state(-1) func add_card_to_deck(key = null): """ If key is null, a card is randomly added @returns bool true is a card was added, false otherwise """ var node if not key: var card_keys = self.cards.keys() node = self.cards[card_keys[rand_range(0, card_keys.size() - 1)]].instance() elif self.cards.has(key): node = self.cards[key].instance() else: return false node.add_to_group('cards') node.set_game(self) get_node('cards').add_child(node) node.hide() self.deck.append(node) return true func update_game_state(new_state_idx): if self.game_state == new_state_idx: return if ! self.game_states.has(new_state_idx): print("Error: trying to change game_state to unknown index: %d" % new_state_idx) return var old_state = self.game_state self.game_state = new_state_idx print("Changed game state from %d to %d" % [old_state, new_state_idx]) emit_signal('game_state_changed', old_state, new_state_idx) func _process(): pass func update_energy(diff = 0): if self.energy + diff > self.ENERGY_MAX: diff = self.ENERGY_MAX - self.energy print('Updating energy from %d by %d to %d' % [self.energy, diff, self.energy + diff]) self.energy += diff emit_signal("game_energy_changed", self.energy) if self.energy <= 0: self.game_win = false self.game_over_message = 'Ran out of energy.... your ship is floating useless and dead in space' self.update_game_state(5) return true return false func draw_hand(cmax = null): if not cmax: cmax = self.max_hand_size var success = false while self.hand.size() < cmax: success = self.draw_card() if not success: break func draw_card(): """ returns bool: true if a card was drawn """ if self.hand.size() >= self.max_hand_size: return false # Can't exceed max hand size if self.deck.size() == 0: self.shuffle_in_discard() if self.deck.empty(): return false # Deck + Discard is milled out var c = self.deck[-1] self.deck.pop_back() self.hand.push_back(c) c.previous_location = Vector2(-200, -200) emit_signal("game_deck_changed", self.deck.size()) emit_signal("game_hand_changed", self.hand.size()) return true func shuffle_in_discard(): while not self.discard.empty(): self.deck.push_back(self.discard[-1]) self.discard.pop_back() emit_signal("game_discard_changed", self.discard.size()) self.shuffle() func shuffle(): if self.DEBUG: print("--- start shuffle ---") print(self.deck) for i in range(1, SHUFFLE_REPEATS): var new_deck = [] var x while not self.deck.empty(): x = rand_range(0, self.deck.size()-1) new_deck.append(self.deck[x]) self.deck.remove(x) self.deck = new_deck if self.DEBUG: print(self.deck) print("--- end shuffle ---") func _on_game_game_state_changed(old_state, new_state): if new_state == -1: # New Round self.round_counter += 1 self.actions_remaining = self.actions_per_round self.draw_hand() print("New round: %d" %self.round_counter) emit_signal("game_round_start", self.round_counter) self.update_game_state(0) # Waiting for player action if new_state == 2: # Round done var state_changed = self.update_energy(-get_round_energy_cost()) state_changed = state_changed || self.check_reactor_fixed() if not state_changed: self.update_game_state(-1) if new_state == 5: # Game finish var n = get_node('ui/end_message') n.set_message(self.game_over_message) n.show() func play_card(card): if self.game_state != 0: return card.start_card_play('on_card_play_done') self.update_game_state(1) # playing action func on_card_play_done(card, played): if not played: self.update_game_state(0) # Waiting for player input return self.discard_card(card) self.actions_remaining -= 1 if self.actions_remaining <= 0: self.update_game_state(2) # Round done func discard_card(card): card.hide() card.set_global_pos(Vector2(-200,-200)) var p = self.hand.find(card) print(p) if p != -1: self.hand.remove(p) self.discard.append(card) print(self.hand) print(self.discard) emit_signal('game_hand_changed', self.hand.size()) emit_signal('game_discard_changed', self.discard.size()) func get_round_energy_cost(): # @TODO base on enabled areas var areas = get_tree().get_nodes_in_group('areas') var cost = self.base_energy_per_round for a in areas: if a.activated: cost += a.energy_cost return cost func check_reactor_fixed(): var n = get_node('areas/reactor') if n.health == n.max_health: self.game_win = true self.game_over_message = 'Fixed the reactor - back on track and in it to win it :)' self.update_game_state(5) return true return false func on_game_quit(): get_tree().quit() func on_game_replay(): get_tree().change_scene('res://game.tscn') #get_node('ui/end_message').hide() #self.init_game() func on_area_activation_changed(area, activated): var c = get_round_energy_cost() get_node('ui/round_energy_label').set_text('Energy Consumption: %d' % c) func destroy_card(card): # Remove a card from the game for ar in [self.hand, self.deck, self.discard]: var i = ar.find(card) if i != -1: ar.remove(i) self.remove_child(card) emit_signal('game_hand_changed', self.hand.size()) emit_signal('game_discard_changed', self.discard.size()) emit_signal('game_deck_changed', self.deck.size())