ld58-collector/game_manager.gd
2025-10-06 13:53:32 -07:00

200 lines
6.1 KiB
GDScript

class_name GameManager extends Node2D
@export var audience_manager: AudienceManager
@export var desk: Desk
@export var turn_manager: TurnManager
enum bidding_state {CLOSED, READY, ASKING, BID}
signal lost
signal won
var paintings_sold := 0
const PAINTINGS_TOTAL := 7
var paintings: Array[PaintingInfo] = []
var current_painting_idx := 0
# tracker variables for bid markers, proposing bids happens between numpad and audience
var current_bid := 0:
set(value):
if is_instance_valid(going_price_label):
going_price_label.text = "Bid: $%sk" % [int(floor(value / 1000.0))]
current_bid = value
var starting_price := 0:
set(value):
if is_instance_valid(starting_price_label):
if value == 0 or state == bidding_state.CLOSED:
starting_price_label.text = "Starting Price: Pending"
else:
starting_price_label.text = "Starting Price: $%sk" % [int(floor(value / 1000.0))]
starting_price = value
var final_bid := 0:
set(value):
if is_instance_valid(going_price_label):
going_price_label.text = "Sold for $%sk!" % [int(floor(value / 1000.0))]
final_bid = value
var target_sales := 0:
set(value):
if is_instance_valid(quota_label):
quota_label.text = "Quota: $%sk Progress: 0%%" % [int(floor(value / 1000.0))]
target_sales = value
#var total_sales: int = 0
@export var sales_magnitude := 100000
@export var single_painting_magnitude := 1000
@export var initial_value_reduction := 0.6
# state tracker for a given painting's auction
var bidding_open := false
var state := bidding_state.CLOSED
@export var quota_label: Label
@export var starting_price_label: Label
@export var going_price_label: Label
func _ready() -> void:
audience_manager.ask_accepted.connect(_handle_ask_accepted)
desk.gavel.gavel_hit.connect(_handle_gavel_hit)
# Associate collectors with their collections
var collectors: Array[Node] = get_tree().get_nodes_in_group("ArtCollectors")
assert(%PaintingPiles.get_child_count() == collectors.size())
for idx in collectors.size(): collectors[idx].painting_pile = %PaintingPiles.get_child(idx)
randomize_auction()
for idx in PAINTINGS_TOTAL:
var pd: PaintingDisplay = %Paintings.get_child(idx)
pd.configure_painting(paintings[idx].id)
next_painting()
var intro_msg := "You have %s paintings. Sell them fast for at least $%s or face the consequences!" % [PAINTINGS_TOTAL, target_sales]
intro_msg += "\nHit the gavel and input the starting price to begin!"
turn_manager.speak_sentence(intro_msg)
#build out the initialization process, which should:
# -- generate paintings and assign values
# -- start the turn timer/auction timer
# ---- also add an auction timer
# -- have tts announcement of starting bid and start of auction
func _handle_gavel_hit():
match state:
bidding_state.CLOSED:
state = bidding_state.READY
starting_price = starting_price
bidding_state.ASKING:
if current_bid != 0:
sell_painting()
if next_painting():
print("The next painting is valued at $%s (should be $%s)" % [starting_price, paintings[current_painting_idx].value])
else:
end_auction()
func destroy_painting():
$FailedPainting.play()
if get_painting_display().damage_deal():
cancel_bidding()
get_painting_display().move_painting_to_pile(%PaintingPileDiscard)
if not next_painting():
end_auction()
else:
turn_manager.speak_sentence("Oh nooooooo! Took too long!\nTry to make it up on the next painting!")
else:
turn_manager.restart_turn()
turn_manager.speak_sentence("Oops! Took too long! Quickly, try again!")
func sell_painting():
cancel_bidding()
move_painting_to_bidders_pile()
paintings[current_painting_idx].sold_for = current_bid
turn_manager.speak_sentence("Sold for $%s!" % [current_bid])
quota_label.text = "Quota: $%sk Progress: %s%%" % [floor(target_sales / 1000.0), floor((float(get_total_sales()) / float(target_sales) * 100.0))]
print("Congrats on selling your painting for $%s! You have made $%s so far." % [current_bid, get_total_sales()])
func move_painting_to_bidders_pile() -> void:
get_painting_display().move_painting_to_pile(audience_manager.latest_bidder.painting_pile)
func get_painting_display() -> PaintingDisplay:
return %Paintings.get_child(current_painting_idx)
func next_painting() -> bool:
current_painting_idx += 1
if current_painting_idx >= PAINTINGS_TOTAL: return false
var info := paintings[current_painting_idx]
starting_price = info.value
current_bid = 0
$NextPainting.play()
get_painting_display().animate_show_painting()
return true
func _handle_ask_accepted():
pass
func end_auction():
#add in logic for displaying/transitioning to score screen
if get_total_sales() >= target_sales:
#add context specific score text?
turn_manager.speak_sentence("Congratulations! The auction house will run another day.")
emit_signal("won")
else:
#add context specific score text?
turn_manager.speak_sentence("You have failed. We must find a new auctioneer.")
emit_signal("lost")
func sum_total_sales(acculator: int, info: PaintingInfo) -> int:
return acculator + info.sold_for
func get_total_sales() -> int:
return paintings.reduce(sum_total_sales, 0)
func randomize_auction() -> void:
#paintings_total = randi_range(7,10)
target_sales = randi_range(2, 5) * sales_magnitude
var custom_ids: Array[int] = %PaintingDisplay1.get_n_unique_custom_paintings(3)
for idx in PAINTINGS_TOTAL:
var info := PaintingInfo.new()
info.id = custom_ids.pop_back() if not custom_ids.is_empty() else -absi(randi())
@warning_ignore('integer_division')
info.value = target_sales / randi_range(PAINTINGS_TOTAL - 2, PAINTINGS_TOTAL + 2)
info.value = snappedi(info.value, single_painting_magnitude)
paintings.append(info)
paintings.shuffle()
class PaintingInfo:
var id := 0
var value := 0
var sold_for := 0
var is_sold: bool:
get(): return sold_for > 0
# OTHER THINGS TO ADD:
# UI elements for score
# Bark manager
func _on_turn_manager_timer_timeout() -> void:
destroy_painting()
func cancel_bidding() -> void:
if not (state == bidding_state.ASKING or state == bidding_state.BID):
push_error('bidding state should not be ', state)
state = bidding_state.CLOSED
desk.numpad.reminder_timer.stop()