extends Node ## difficulty levels enum Difficulty { SWEET, # slower enemies, infinite lives SALTY, # normal enemies, infinite lives SPICY, # normal enemies, 3 lives, DEFAULT PUNGENT, # faster enemies, 3 lives } ## resolution the game renders at const RESOLUTION := Vector2(256,192) const DIFFICULTY_NAMES := ["Sweet","Salty","Spicy","Pungent"] #== collectibles ==# var keys: int = 0 # collected keys ## which stars are collected var stars_collected := [false,false,false,false,false] var stars : int setget , _get_stars # total stars ## which stars are collected var shards_collected := [false,false,false,false,false,false,false,false] ## how many shards collected var shards: int setget , _get_shards # total shards var arrows: int = 0 # current arrows #== stats ==# var lives: int = 2 var deaths: int = 0 var time: float = 0.0 #== score ==# var score: int = 0 var arrows_bonus: int = 0 var collection_bonus: int = 0 var time_bonus: int = 0 var life_bonus: int = 0 var perfect_bonus: int = 0 var final_score: int = 0 #== state ==# var current_sector := Vector2.ZERO var respawn_point := Vector2(32,166) var current_level: int = 0 var difficulty: int = Difficulty.SPICY setget _set_difficulty var enemy_speed_factor: float = 1.0 # multiplier of enemy speed var is_easy_mode: bool = false # whether to do easy-specific behaviors var use_lives: bool = true var can_pause: bool = true var can_restart: bool = true var current_palette: String = "default" var still_playing: bool = false # demo hack marathon mode var marathon_mode: bool = true var marathon_score: int = 0 var marathon_lives: int = 2 var marathon_shards: int = 0 var next_level: PackedScene func _ready(): pause_mode = Node.PAUSE_MODE_PROCESS func _get_stars() -> int: return stars_collected.count(true) func _get_shards() -> int: return shards_collected.count(true) # stuff to change when setting difficulty func _set_difficulty(value: int) -> void: difficulty = value match difficulty: Difficulty.SWEET: is_easy_mode = true enemy_speed_factor = 0.75 # use_lives = false Difficulty.SALTY: is_easy_mode = false enemy_speed_factor = 1.0 # use_lives = false Difficulty.SPICY: is_easy_mode = false enemy_speed_factor = 1.0 # use_lives = true Difficulty.PUNGENT: is_easy_mode = false enemy_speed_factor = 1.25 # use_lives = true #Instances a node func instance_node(node:PackedScene,x:float,y:float,parent): var Instance = node.instance() Instance.global_position = Vector2(x,y) parent.add_child(Instance) #Get position in sectors func get_sector(pos): return (pos / RESOLUTION).floor() #Return the current Map func get_map(): return get_tree().get_nodes_in_group("map")[0] ## tally up scores func tally_scores() -> void: var map = get_map() # arrows bonus arrows_bonus = arrows * 100 # collection bonus if keys >= 50: collection_bonus += 500 if _get_shards() >= 5: collection_bonus += 500 # 100% collection if keys >= 50 and _get_shards() >= 5: collection_bonus += 250 shards_collected[5] = true # 100% time bonus if time < map.target_time_100: time_bonus = max(2500 - int(2500.0 * time / map.target_time_100), 0) shards_collected[6] = true else: # any% time bonus if time < map.target_time_any: time_bonus = max(2500 - int(2500.0 * time / map.target_time_any), 0) shards_collected[6] = true # life bonus if deaths == 0: life_bonus = 1500 shards_collected[7] = true elif deaths == 1: life_bonus = 500 # perfect bonus if shards_collected[5] and shards_collected[6] and shards_collected[7]: perfect_bonus += 1000 # final score final_score = score + arrows_bonus + collection_bonus + time_bonus + life_bonus + perfect_bonus marathon_score += final_score marathon_shards += _get_shards() Game.save() #Go to new map func change_map(map: PackedScene) -> void: get_tree().paused = true can_pause = false Fade.fade_out(0.4) yield(Fade, "fade_finished") can_pause = true # save deaths var save_id = LevelData.levels[current_level].save_id var save_data: Save.LevelSaveData = Save.current_file.levels[save_id] save_data.deaths += deaths Save.current_file.save_to_file() # clear clear_collectibles() StainLayer.reset() #Loop is so no more than one level is loaded at a time SceneManager.current_scene = map.instance() #Clear data func clear_collectibles() -> void: # collectibles keys = 0 stars_collected.fill(false) shards_collected.fill(false) arrows = 0 if not marathon_mode: lives = 0 deaths = 0 # score score = 0 collection_bonus = 0 time_bonus = 0 life_bonus = 0 perfect_bonus = 0 final_score = 0 #Save func save(): # get level's save data object var save_id = LevelData.levels[current_level].save_id var save_data: Save.LevelSaveData = Save.current_file.levels[save_id] # save score and time depending on completion if _get_shards() >= 5 && keys >= 50: save_data.score_100 = max(save_data.score_100, final_score) save_data.time_100 = min(save_data.time_100, time) else: save_data.score_any = max(save_data.score_any, final_score) save_data.time_any = min(save_data.time_any, time) # set shards for i in 8: if shards_collected[i]: save_data.shards_collected[i] = true # set keys save_data.keys_collected = max(save_data.keys_collected, keys) # mark as completed save_data.completed = true # add to playtime Save.current_file.play_time += time # save the file Save.current_file.save_to_file() # smaller save function for bosses func save_boss() -> void: var save_id = LevelData.levels[current_level].save_id var save_data: Save.LevelSaveData = Save.current_file.levels[save_id] save_data.time_any = min(save_data.time_any, time) save_data.completed = true Save.current_file.play_time += time Save.current_file.save_to_file() # !!DEPRECATED!! convert milliseconds into M:SS:MS func timeify(input): if input <= 5999099: var seconds = fmod(Game.time / 1000,60) var minutes = floor((Game.time / 1000) / 60) var centiseconds = fmod(floor(seconds * 100),100) return ("%02d" % minutes) + ":" + ("%02d" % seconds) + "." + ("%02d" % centiseconds) elif input == INF: return "-:--.--" else: return "99:59.99" # convert seconds into M:SS.MS func format_time(seconds: float) -> String: if is_inf(seconds) or is_nan(seconds): # infinite return "-:--.--" elif seconds >= 600.0: # 10 minutes or greater return "9:99.99" else: var minutes = floor(seconds / 60.0) var centiseconds = fmod(floor(seconds * 100.0), 100.0) return "%01d:%02d.%02d" % [minutes, fmod(seconds, 60.0), centiseconds] #Restart level func restart_level(): if can_restart: clear_collectibles() Audio.ac_climb.stop() Audio.ac_die.stop() Engine.time_scale = 1.0 for tween in get_tree().get_processed_tweens(): tween.kill() change_map(load(get_map().filename)) Audio.ac_music.stream_paused = false #Freeze frame func freeze_frame(time): get_tree().paused = true var timer = get_tree().create_timer(time, true) timer.connect("timeout", get_tree(), "set_pause", [false]) return timer #Check if 100%ed func has_collection_bonus(): return _get_shards() == 5 && keys == 50 # called when player dies func _on_player_died() -> void: deaths += 1 if use_lives and lives <= 0: can_restart = false can_pause = false Audio.play_sound(Audio.a_game_over, Audio.ac_die) get_tree().get_nodes_in_group("player")[0].queue_free() var time_tween = create_tween() time_tween.tween_property(Engine, "time_scale", 0.1, 0.3) Audio.ac_music.stream_paused = true yield(time_tween, "finished") yield(get_tree().create_timer(1.0 * 0.1), "timeout") Engine.time_scale = 1.0 Fade.fade_out(0.4) yield(Fade, "fade_finished") var map = get_map() var gover = load("res://menus/game_over.tscn").instance() map.add_child(gover) can_restart = true can_pause = true else: # count death lives -= 1 # play death sound Audio.play_sound(Audio.a_die, Audio.ac_die) # death score penalty if use_lives == false && lives < 0: score = max(0, score - 500) # freezeframe Game.freeze_frame(0.3)