RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
putt_putt_minigame_manager.gd
Go to the documentation of this file.
1extends RefCounted
2
3
6
7const DEFAULT_DEFINITIONS_PATH := "res://data/games/putt_putt_roguelike/minigames.json"
8
9var definitions_path:String = DEFAULT_DEFINITIONS_PATH
10var definitions:Array = []
11var definition_lookup:Dictionary = {}
12
13
14func load_definitions(path:String = DEFAULT_DEFINITIONS_PATH) -> Dictionary:
15 definitions_path = path
16 definitions.clear()
17 definition_lookup.clear()
18 var file = FileAccess.open(path, FileAccess.READ)
19 if file == null:
20 return {"ok": false, "minigames": 0, "error": "missing_file"}
21 var parsed:Variant = JSON.parse_string(file.get_as_text())
22 if not parsed is Dictionary:
23 return {"ok": false, "minigames": 0, "error": "invalid_json"}
24 var rows:Array = parsed.get("minigames", []) if parsed.get("minigames", []) is Array else []
25 for row in rows:
26 if not row is Dictionary:
27 continue
28 var definition:Dictionary = Dictionary(row).duplicate(true)
29 var id:String = str(definition.get("id", ""))
30 if id == "":
31 continue
32 definitions.append(definition)
33 definition_lookup[id] = definition
34 return {"ok": true, "minigames": definitions.size(), "error": ""}
35
36
37func get_definition(minigame_id:String) -> Dictionary:
38 _ensure_definitions_loaded()
39 if definition_lookup.has(minigame_id):
40 return Dictionary(definition_lookup[minigame_id]).duplicate(true)
41 return {}
42
43
44func create_minigame(minigame_id:String, seed:int, options:Dictionary = {}) -> Dictionary:
45 var definition:Dictionary = get_definition(minigame_id)
46 var type:String = str(options.get("type", definition.get("type", _minigame_type(minigame_id))))
47 var target_score:int = int(options.get("target_score", definition.get("target_score", _default_target_score(minigame_id))))
48 var step_score:int = int(options.get("step_score", definition.get("step_score", _default_step_score(type))))
49 return {
50 "schema_version": 1,
51 "id": minigame_id,
52 "seed": seed,
53 "name": str(options.get("name", definition.get("name", minigame_id.capitalize()))),
54 "description": str(options.get("description", definition.get("description", ""))),
55 "type": type,
56 "preview": str(options.get("preview", definition.get("preview", type))),
57 "target_score": max(1, target_score),
58 "step_score": max(1, step_score),
59 "score": 0,
60 "turns": 0,
61 "complete": false,
62 "result": ""
63 }
64
65
66func advance_minigame(state:Dictionary, options:Dictionary = {}) -> Dictionary:
67 var next:Dictionary = state.duplicate(true)
68 if bool(next.get("complete", false)):
69 return next
70 var amount:int = max(1, int(options.get("score", next.get("step_score", _default_step_score(str(next.get("type", "")))))))
71 next["turns"] = int(next.get("turns", 0)) + 1
72 next["score"] = int(next.get("score", 0)) + amount
73 if int(next.get("score", 0)) >= int(next.get("target_score", 1)):
74 next["score"] = int(next.get("target_score", 1))
75 next["complete"] = true
76 next["result"] = "won"
77 return next
78
79
80func is_complete(state:Dictionary) -> bool:
81 return bool(state.get("complete", false))
82
83
84func progress_text(state:Dictionary) -> String:
85 return "%s %d/%d" % [
86 _label_for_type(str(state.get("type", ""))),
87 int(state.get("score", 0)),
88 int(state.get("target_score", 1))
89 ]
90
91
92func _ensure_definitions_loaded() -> void:
93 if definitions.is_empty():
94 load_definitions(definitions_path)
95
96
97func _minigame_type(minigame_id:String) -> String:
98 var id:String = minigame_id.to_lower()
99 if id.contains("pong"):
100 return "pong"
101 if id.contains("breakout"):
102 return "breakout"
103 if id.contains("boss"):
104 return "scripted_boss"
105 return "ball_challenge"
106
107
108func _default_target_score(minigame_id:String) -> int:
109 match _minigame_type(minigame_id):
110 "breakout":
111 return 6
112 "pong":
113 return 5
114 "scripted_boss":
115 return 9
116 _:
117 return 4
118
119
120func _default_step_score(type:String) -> int:
121 match type:
122 "scripted_boss":
123 return 2
124 _:
125 return 1
126
127
128func _label_for_type(type:String) -> String:
129 match type:
130 "breakout":
131 return "Blocks"
132 "pong":
133 return "Rallies"
134 "scripted_boss":
135 return "Boss"
136 _:
137 return "Progress"