LevelSelect.gd 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. extends Control
  2. var selected_level := 0
  3. signal level_selected
  4. signal cancelled
  5. var active := false
  6. var starting_value := -1
  7. @export var has_speedrun_stuff := false
  8. @export var has_disco_stuff := false
  9. const LEVEL_ICONS := {
  10. "SMB1": SMB1_ICONS,
  11. "SMBLL": SMBLL_ICONS,
  12. "SMBS": SMBS_ICONS,
  13. "SMBANN": SMB1_ICONS
  14. }
  15. const SMB1_ICONS := [
  16. "0123",
  17. "0453",
  18. "0023",
  19. "0163",
  20. "8893",
  21. "8893",
  22. "8AB3",
  23. "8883"
  24. ]
  25. const SMBLL_ICONS := [
  26. "0123",
  27. "0053",
  28. "0423",
  29. "0023",
  30. "8193",
  31. "8AB3",
  32. "8993",
  33. "88D3",
  34. "8888",
  35. "0123",
  36. "0423",
  37. "0523",
  38. "0003"
  39. ]
  40. const SMBS_ICONS := [
  41. "0123",
  42. "0453",
  43. "0023",
  44. "0163",
  45. "8893",
  46. "8893",
  47. "8AB3",
  48. "CA13"
  49. ]
  50. const NUMBER_Y := [
  51. "Overworld",
  52. "Underground",
  53. "Castle",
  54. "Snow",
  55. "Space",
  56. "Volcano"
  57. ]
  58. func _ready() -> void:
  59. for i in %SlotContainer.get_children():
  60. i.focus_entered.connect(slot_selected.bind(i.get_index()))
  61. for i in [$Panel/MarginContainer/VBoxContainer/HBoxContainer/ScrollContainer/SlotContainer/Slot1/Icon/RankMedal/SRankParticles, $Panel/MarginContainer/VBoxContainer/HBoxContainer/ScrollContainer/SlotContainer/Slot1/Icon/RankMedal/PRankParticles, $Panel/MarginContainer/VBoxContainer/HBoxContainer/ScrollContainer/SlotContainer/Slot2/Icon/RankMedal/SRankParticles, $Panel/MarginContainer/VBoxContainer/HBoxContainer/ScrollContainer/SlotContainer/Slot2/Icon/RankMedal/PRankParticles, $Panel/MarginContainer/VBoxContainer/HBoxContainer/ScrollContainer/SlotContainer/Slot3/Icon/RankMedal/SRankParticles, $Panel/MarginContainer/VBoxContainer/HBoxContainer/ScrollContainer/SlotContainer/Slot3/Icon/RankMedal/PRankParticles, $Panel/MarginContainer/VBoxContainer/HBoxContainer/ScrollContainer/SlotContainer/Slot4/Icon/RankMedal/SRankParticles, $Panel/MarginContainer/VBoxContainer/HBoxContainer/ScrollContainer/SlotContainer/Slot4/Icon/RankMedal/PRankParticles]:
  62. start_particle(i)
  63. func start_particle(particle: GPUParticles2D) -> void:
  64. await get_tree().create_timer(randf_range(0, 5)).timeout
  65. particle.emitting = true
  66. func _process(_delta: float) -> void:
  67. if active:
  68. handle_input()
  69. Global.level_num = selected_level + 1
  70. func open() -> void:
  71. if starting_value == -1:
  72. starting_value = Global.level_num
  73. print([Global.level_num, starting_value])
  74. selected_level = Global.level_num - 1
  75. setup_visuals()
  76. update_pb()
  77. show()
  78. $%SlotContainer.get_child(selected_level).grab_focus()
  79. await get_tree().create_timer(0.1).timeout
  80. active = true
  81. const CHARSET := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  82. var visited_levels := "0000"
  83. func setup_visuals() -> void:
  84. %MarathonBits.visible = Global.current_game_mode == Global.GameMode.MARATHON_PRACTICE
  85. var idx := 0
  86. for i in %SlotContainer.get_children():
  87. if i.visible == false:
  88. continue
  89. var level_theme = Global.LEVEL_THEMES[Global.current_campaign][Global.world_num - 1]
  90. visited_levels = (SaveManager.visited_levels.substr((Global.world_num - 1) * 4, 4))
  91. var level_visited = SaveManager.visited_levels[SaveManager.get_level_idx(Global.world_num, idx + 1)] != "0" or Global.debug_mode
  92. var num = CHARSET.find(LEVEL_ICONS[Global.current_campaign][Global.world_num - 1][idx])
  93. if level_visited == false:
  94. num = 7
  95. i.get_node("ChallengeModeBits").visible = Global.current_game_mode == Global.GameMode.CHALLENGE
  96. if Global.current_game_mode == Global.GameMode.CHALLENGE:
  97. setup_challenge_mode_bits(i.get_node("ChallengeModeBits"), idx + 1)
  98. i.get_node("Icon").region_rect = Rect2((num % 4) * 56, (num / 4) * 32, 56, 32)
  99. i.get_node("Icon/Number").region_rect.position.y = clamp(NUMBER_Y.find(level_theme) * 12, 0, 9999)
  100. i.get_node("Icon/Number").region_rect.position.x = (idx) * 12
  101. i.get_node("Icon/RankMedal").visible = Global.current_campaign == "SMBANN"
  102. if Global.current_campaign == "SMBANN":
  103. i.get_node("Icon/RankMedal").frame = "ZFDCBASP".find(DiscoLevel.level_ranks[SaveManager.get_level_idx(Global.world_num, idx + 1)])
  104. i.get_node("Icon/RankMedal/SRankParticles").visible = i.get_node("Icon/RankMedal").frame == 6
  105. i.get_node("Icon/RankMedal/PRankParticles").visible = i.get_node("Icon/RankMedal").frame == 7
  106. idx += 1
  107. func setup_challenge_mode_bits(container: HBoxContainer, level_num := 1) -> void:
  108. for i in [container.get_node("1"), container.get_node("2"), container.get_node("3"), container.get_node("4"), container.get_node("5"), container.get_node("6")]:
  109. var collected = ChallengeModeHandler.is_coin_collected(int(i.name) - 1, ChallengeModeHandler.red_coins_collected[Global.world_num - 1][level_num - 1])
  110. i.get_node("Full").visible = collected
  111. container.get_node("Score/Full").visible = ChallengeModeHandler.top_challenge_scores[Global.world_num - 1][level_num - 1] >= ChallengeModeHandler.CHALLENGE_TARGETS[Global.current_campaign][Global.world_num - 1][level_num - 1]
  112. func update_pb() -> void:
  113. if has_speedrun_stuff == false: return
  114. var best_warpless_time = SpeedrunHandler.best_level_warpless_times[Global.world_num - 1][selected_level]
  115. print(SpeedrunHandler.best_level_warpless_times)
  116. var best_any_time = SpeedrunHandler.best_level_any_times.get(str(Global.world_num) + "-" + str(selected_level + 1), -1)
  117. %FullRunPB.text = "--:--:--" if best_warpless_time == -1 else SpeedrunHandler.gen_time_string(SpeedrunHandler.format_time(best_warpless_time))
  118. %WarpRunPB.text = "--:--:--" if best_any_time == -1 else SpeedrunHandler.gen_time_string(SpeedrunHandler.format_time(best_any_time))
  119. %Flag.visible = selected_level < 3
  120. %Axe.visible = selected_level >= 3
  121. $Panel/MarginContainer/VBoxContainer/MarathonBits/VBoxContainer/Warp.modulate = Color.WHITE if SpeedrunHandler.WARP_LEVELS[Global.current_campaign].has(str(Global.world_num) + "-" + str(selected_level + 1)) else Color(0.25, 0.25, 0.25)
  122. var gold_warpless_time = SpeedrunHandler.LEVEL_GOLD_WARPLESS_TIMES[Global.current_campaign][Global.world_num - 1][selected_level]
  123. var gold_any_time := -1.0
  124. if SpeedrunHandler.LEVEL_GOLD_ANY_TIMES[Global.current_campaign].has(str(Global.world_num) + "-" + str(selected_level + 1)):
  125. gold_any_time = SpeedrunHandler.LEVEL_GOLD_ANY_TIMES[Global.current_campaign][str(Global.world_num) + "-" + str(selected_level + 1)]
  126. for i in %FullRunMedals.get_children():
  127. var target_time = gold_warpless_time * SpeedrunHandler.MEDAL_CONVERSIONS[i.get_index()]
  128. i.get_node("Full").visible = best_warpless_time <= target_time and best_warpless_time > 0
  129. if gold_any_time != -1:
  130. for i in %WarpRunMedals.get_children():
  131. var target_time = gold_any_time * SpeedrunHandler.MEDAL_CONVERSIONS[i.get_index()]
  132. i.get_node("Full").visible = best_any_time <= target_time and best_any_time > 0
  133. else:
  134. for i in %WarpRunMedals.get_children():
  135. i.get_node("Full").hide()
  136. func handle_input() -> void:
  137. selected_level = clamp(selected_level, 0, 3)
  138. if Input.is_action_just_pressed("ui_accept"):
  139. if visited_levels[selected_level] == "0" and selected_level != 0 and not Global.debug_mode:
  140. AudioManager.play_sfx("bump")
  141. else:
  142. select_world()
  143. elif Input.is_action_just_pressed("ui_back"):
  144. close()
  145. cleanup()
  146. cancelled.emit()
  147. return
  148. func select_world() -> void:
  149. if owner is Level:
  150. owner.level_id = selected_level + 1
  151. Global.level_num = selected_level + 1
  152. level_selected.emit()
  153. close()
  154. func slot_selected(idx := 0) -> void:
  155. selected_level = idx
  156. update_pb()
  157. func cleanup() -> void:
  158. await get_tree().process_frame
  159. Global.level_num = starting_value
  160. starting_value = -1
  161. Global.level_num = clamp(Global.level_num, 1, 4)
  162. if owner is Level:
  163. owner.level_id = clamp(owner.level_id, 1, 8)
  164. func close() -> void:
  165. active = false
  166. hide()