class_name WorldManager extends Resource ## Autoloaded singleton encapsulating game world state. # TODO a lot of this should really be a property of the world. ## Emitted just after `delta` is added to the player's grunk tank. signal grunk_collected(delta: float) ## Emitted just after the grunk tank is emptied, where `amount` is how much had been collected. signal grunk_emptied(amount: float) ## Emitted just before the alert level is raised to `new_value`. signal alert_raised(new_value: int) ## Emitted just before the alert level is reset to the clear level. signal alert_cleared ## Emitted after the player's grunk vault reaches a new milestone. signal milestone_reached(milestone: Milestone) ## Emitted after the player collects a new MP3 signal mp3_collected(mp3_track: MP3Track) ## Emitted as soon as the player dies. signal player_dead const MAX_ALERT := 6 const CLEAR_LEVEL := 2 const BASE_TANK_LIMIT := 96000 const BIG_TANK_LIMIT := 198000 ## Maximum amount of grunk the player can carry in their tank. @export var grunk_tank_limit := BASE_TANK_LIMIT # TODO figure this out @export var grunk_quota := 2000000 ## Grunk collection milestones @export var vault_milestones: Dictionary[int, Milestone] @export_group("Progress") @export var mp3_player_unlocked := false @export var toothbrush_unlocked := false @export var stickers_unlocked := false @export var mp3_collection: Array[MP3Track] = [] ## Amount of grunk the player is currently carrying. @export var grunk_tank := 0.0 ## Total amount of grunk that has been deposited by the player. @export var grunk_vault := 0.0 ## Level of grunk agressiveness, raised whenever the player messes up. var alert_level := 0 func _init() -> void: milestone_reached.connect(_on_milestone) ## Add to the player's grunk tank. func collect_grunk(delta: float) -> void: grunk_tank += delta grunk_collected.emit(delta) ## Empty the player's grunk tank, e.g. when depositing grunk. func empty_tank() -> void: var amount := grunk_tank grunk_tank = 0.0 grunk_emptied.emit(amount) ## Deposit the player's grunk in the vault, emptying the player's tank. func deposit_tank() -> void: var prev_milestone := latest_milestone() grunk_vault += grunk_tank empty_tank() var new_milestone := latest_milestone() if new_milestone != prev_milestone: milestone_reached.emit(new_milestone) if alert_level >= CLEAR_LEVEL: clear_alert() World.instance.save_progress() func is_tank_full() -> bool: return grunk_tank >= grunk_tank_limit func get_tank_fill_pct() -> float: return grunk_tank / grunk_tank_limit ## Raise the alert level, if possible. func raise_alert(delta: int) -> void: var new_value := clampi(alert_level + delta, 0, MAX_ALERT) if new_value != alert_level: alert_raised.emit(new_value) alert_level = new_value ## Reset the alert level to the clear level. func clear_alert() -> void: alert_cleared.emit() alert_level = CLEAR_LEVEL ## Returns the latest vault milestone reached by the player. ## ## Returns null if the player has not reached a milestone (shouldn't be possible). func latest_milestone() -> Milestone: var prev: Milestone = null for milestone_amt: int in vault_milestones: if grunk_vault < milestone_amt: return prev prev = vault_milestones[milestone_amt] return prev ## Returns the next vault milestone for the player to reach. ## ## Returns null if all milestones have been reached. func next_milestone() -> Milestone: var amt := next_milestone_amount() if amt >= 0: return vault_milestones[amt] return null ## Returns the grunk amount needed for the player to reach the next milestone. ## ## Returns <0 if all milestones have been reached. func next_milestone_amount() -> int: for milestone_amt: int in vault_milestones: if grunk_vault < milestone_amt: return milestone_amt return -1 func _on_milestone(milestone: Milestone) -> void: if milestone.mp3_player: mp3_player_unlocked = true if milestone.toothbrush: toothbrush_unlocked = true if milestone.stickers: stickers_unlocked = true if milestone.big_tank: grunk_tank_limit = BIG_TANK_LIMIT if milestone.bonus_track: collect_mp3(milestone.bonus_track) # TODO the rest ## Add an MP3 player track to the player's collection. func collect_mp3(track: MP3Track) -> void: mp3_collection.append(track) mp3_collected.emit(track) ## Called by Player on death. func on_player_death() -> void: player_dead.emit() # TODO reload from save? # REMOVEME # workaround until saving & loading is implemented grunk_tank_limit = BASE_TANK_LIMIT grunk_tank = 0.0 grunk_vault = 0.0