287 lines
8.1 KiB
GDScript
287 lines
8.1 KiB
GDScript
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()) |