grounders-slowjam-2024/level/level.gd

111 lines
3.5 KiB
GDScript

extends Node3D
class_name Level
enum GameState {
WAITING, # Stop state to be used by default, nothing should react to this
TAGGER_GROUNDED, # Tagger is on the ground
TAGGER_UNGROUNDED, # Tagger is off the ground
TAGGER_CHANGE, # Tagger has caught someone, and new person must go to ground
}
var game_state: GameState = GameState.WAITING
var game_tagger: Player
signal state_change(old: GameState, new: GameState)
signal state_enter_tagger_grounded
signal state_leave_tagger_grounded
signal state_enter_tagger_ungrounded
signal state_leave_tagger_ungrounded
signal state_enter_tagger_change(new_tagger: Player)
signal state_leave_tagger_change
const MIN_PLAYERS := 2
const global_msg_1 := "Waiting for at least {min_players} players to join"
const global_msg_2 := "Game is starting soon, {tagger_username} is it!"
const global_msg_3 := "{tagger_username} is it! Run!"
const global_msg_4 := "{old_tagger_username} caught {tagger_username}!"
const global_msg_5 := "{old_tagger_username} left. {tagger_username} is now it!"
func set_tagger_grounded(v: bool):
if v and game_state == GameState.TAGGER_CHANGE:
_change_state(GameState.TAGGER_GROUNDED)
return
if not (game_state == GameState.TAGGER_GROUNDED or game_state == GameState.TAGGER_UNGROUNDED):
return
if (not v) and game_state == GameState.TAGGER_GROUNDED:
_change_state(GameState.TAGGER_UNGROUNDED)
if v and game_state == GameState.TAGGER_UNGROUNDED:
_change_state(GameState.TAGGER_GROUNDED)
func not_enough_players() -> bool:
if %Players.get_children().size() < MIN_PLAYERS:
_change_state(GameState.WAITING)
%GlobalMessage.text = global_msg_1.format({"min_players": MIN_PLAYERS})
return true
return false
func change_to_random_tagger():
game_tagger = %Players.get_children().pick_random()
_change_state(GameState.TAGGER_CHANGE)
func tagger_left_game():
if not_enough_players():
return
var old_tagger_username := game_tagger.username
change_to_random_tagger()
var tagger_username := game_tagger.username
%GlobalMessage.text = global_msg_5.format({
"old_tagger_username": old_tagger_username,
"tagger_username": tagger_username})
func set_tagger(who: Player):
if game_state == GameState.WAITING:
return
game_tagger.tree_exiting.disconnect(tagger_left_game)
who.tree_exiting.connect(tagger_left_game)
game_tagger = who
_change_state(GameState.TAGGER_CHANGE)
func _change_state(new_state: GameState):
if game_state == new_state:
return
if new_state == GameState.WAITING:
game_tagger = null
state_change.emit(game_state, new_state)
if new_state == GameState.TAGGER_GROUNDED:
state_enter_tagger_grounded.emit()
if new_state == GameState.TAGGER_UNGROUNDED:
state_enter_tagger_ungrounded.emit()
if new_state == GameState.TAGGER_CHANGE:
state_enter_tagger_change.emit(game_tagger)
var old_state = game_state
game_state = new_state
if old_state == GameState.TAGGER_GROUNDED:
state_leave_tagger_grounded.emit()
if old_state == GameState.TAGGER_UNGROUNDED:
state_leave_tagger_ungrounded.emit()
if old_state == GameState.TAGGER_CHANGE:
state_leave_tagger_change.emit()
func _ready():
# Hacky way to start level without going though multiplayer screens
if get_parent() == get_tree().root:
%PlayerSpawner.spawn(multiplayer.get_unique_id())
# Called from the server
func server_add_player(id: int):
%PlayerSpawner.spawn(id)
func server_remove_player(id: int):
%PlayerSpawner.despawn_player(id)
static func find_level(node: Node) -> Level:
while not (node is Level):
node = node.get_parent()
return node