7const DataCacheManager = preload(
"res://scripts/systems/dataCacheManager/data_cache_manager.gd")
10var manifestations := {}
14var composition_rules := {}
15var data_cache_manager = DataCacheManager.new()
19func load_catalog(file_path:String) -> void:
21 manifestations.clear()
23 composition_rules.clear()
24 load_catalog_data(data_cache_manager.load_json(file_path))
28func load_catalog_data(data) -> void:
30 manifestations.clear()
32 composition_rules.clear()
33 if not data
is Dictionary:
35 composition_rules = data.get(
"composition", {}).duplicate(true)
36 for manifestation
in data.get(
"manifestations", []):
37 if manifestation
is Dictionary:
38 var id = str(manifestation.get(
"id",
""))
40 manifestations[id] = manifestation.duplicate(true)
41 for modifier
in data.get(
"modifiers", []):
42 if modifier
is Dictionary:
43 var id = str(modifier.get(
"id",
""))
45 modifiers[id] = modifier.duplicate(true)
46 for card
in data.get(
"cards", []):
47 if card
is Dictionary:
48 var id = str(card.get(
"id",
""))
50 cards[id] = card.duplicate(true)
54func load_definitions(file_path:String) -> void:
57 load_definition_data(data_cache_manager.load_json(file_path))
61func get_cache_stats() -> Dictionary:
62 return data_cache_manager.get_cache_stats()
66func load_definition_data(data) -> void:
69 if not data
is Dictionary:
71 for element
in data.get(
"elements", []):
72 if element
is Dictionary:
73 var id = str(element.get(
"id",
""))
75 elements[id] = element.duplicate(true)
76 for compound
in data.get(
"compounds", []):
77 if compound
is Dictionary:
78 var id = str(compound.get(
"id",
""))
80 compounds[id] = compound.duplicate(true)
84func get_card(card_id:String) -> Dictionary:
85 return cards.get(card_id, {}).duplicate(true)
89func get_compound_definition(compound_id:String) -> Dictionary:
90 return _compound_definition(compound_id)
94func register_card(card:Dictionary) -> bool:
95 var id = str(card.get(
"id",
""))
98 cards[id] = card.duplicate(true)
103func unregister_card(card_id:String) -> bool:
104 if not cards.has(card_id):
111func get_cards_for_unlocks(unlocked_ids:Array, fallback_ids:Array = []) -> Array:
114 for id
in fallback_ids:
116 if cards.has(key)
and not seen.has(key):
117 rows.append(cards[key].duplicate(true))
119 for id
in unlocked_ids:
121 if cards.has(key)
and not seen.has(key):
122 rows.append(cards[key].duplicate(true))
128func get_cards_for_reaction(reaction:Dictionary) -> Array:
129 return get_cards_for_unlocks(reaction.get(
"unlocks_cards", []))
133func get_missing_unlocks(unlocked_ids:Array) -> Array:
135 for id
in unlocked_ids:
137 if key !=
"" and not cards.has(key):
144func compose_card(compound, manifestation_id:String, modifier_ids:Array = [], options:Dictionary = {}) -> Dictionary:
145 var compound_def = _compound_definition(compound)
146 var compound_id = str(compound_def.get(
"id",
""))
147 if compound_id ==
"" or not manifestations.has(manifestation_id):
149 var manifestation = manifestations[manifestation_id]
150 var clean_modifiers := []
151 for id
in modifier_ids:
153 if modifiers.has(key)
and not clean_modifiers.has(key):
154 clean_modifiers.append(key)
155 var tier = int(compound_def.get(
"tier", 0))
156 var energy = int(composition_rules.get(
"base_energy", 1)) + int(manifestation.get(
"energy_delta", 0))
157 var damage = int(composition_rules.get(
"base_damage", 6)) + tier * int(composition_rules.get(
"damage_per_tier", 4)) + int(manifestation.get(
"damage_bonus", 0))
158 var card_range = int(manifestation.get(
"range", composition_rules.get(
"default_range", 4)))
159 var aoe_radius = int(manifestation.get(
"aoe_radius", composition_rules.get(
"default_aoe_radius", 1)))
160 var duration = float(manifestation.get(
"duration", 0.24))
161 for id
in clean_modifiers:
162 var modifier = modifiers[id]
163 energy += int(modifier.get(
"energy_delta", 0))
164 damage += int(modifier.get(
"damage_delta", 0))
165 card_range += int(modifier.get(
"range_delta", 0))
166 aoe_radius += int(modifier.get(
"aoe_delta", 0))
167 duration += float(modifier.get(
"duration_delta", 0.0))
168 energy = max(0, energy)
169 damage = max(1, damage)
170 card_range = max(0, card_range)
171 aoe_radius = max(0, aoe_radius)
172 duration = max(0.05, duration)
173 var modifier_names := []
174 for id
in clean_modifiers:
175 modifier_names.append(str(modifiers[id].get(
"name", id)))
176 var compound_name = str(compound_def.get(
"name", compound_id.capitalize()))
177 var manifestation_name = str(manifestation.get(
"name", manifestation_id.capitalize()))
178 var card_name =
"%s %s" % [compound_name, manifestation_name]
179 if not modifier_names.is_empty():
180 card_name =
"%s %s" % [
" ".join(modifier_names), card_name]
181 var card_id = str(options.get(
"id", _composed_card_id(compound_id, manifestation_id, clean_modifiers)))
183 "type": str(manifestation.get(
"targeting_type", manifestation_id)),
184 "requires_direction": bool(manifestation.get(
"requires_direction", true)),
188 targeting[
"aoe_radius"] = aoe_radius
192 "compound": compound_id,
193 "manifestation": manifestation_id,
194 "modifiers": clean_modifiers,
195 "targeting": targeting,
197 "color": str(compound_def.get(
"color", composition_rules.get(
"default_color",
"#f5d36a"))),
198 "shape": str(manifestation.get(
"shape", targeting[
"type"])),
203 "description": _composition_description(compound_def, manifestation, clean_modifiers),
205 "compound": compound_id,
206 "manifestation": manifestation_id,
207 "modifiers": clean_modifiers
213func preview_composition(compound, manifestation_id:String, modifier_ids:Array = []) -> Dictionary:
214 var card = compose_card(compound, manifestation_id, modifier_ids)
215 if not card.is_empty():
216 card[
"preview"] = true
220func get_composition_issues(compound_ids:Array = []) -> Array:
222 for id
in compound_ids:
224 if key !=
"" and _compound_definition(key).is_empty():
225 issues.append({
"type":
"missing_compound",
"id": key})
226 for id
in manifestations.keys():
227 var manifestation = manifestations[id]
228 if not manifestation.has(
"targeting_type"):
229 issues.append({
"type":
"missing_targeting_type",
"id": id})
230 for id
in modifiers.keys():
231 var modifier = modifiers[id]
232 if not modifier.has(
"description"):
233 issues.append({
"type":
"missing_modifier_description",
"id": id})
237func get_state() -> Dictionary:
239 "cards": cards.duplicate(true),
240 "manifestations": manifestations.duplicate(true),
241 "modifiers": modifiers.duplicate(true),
242 "elements": elements.duplicate(true),
243 "compounds": compounds.duplicate(true),
244 "composition_rules": composition_rules.duplicate(true)
248func apply_state(state:Dictionary) -> void:
249 cards = state.get(
"cards", {}).duplicate(true)
250 manifestations = state.get(
"manifestations", {}).duplicate(true)
251 modifiers = state.get(
"modifiers", {}).duplicate(true)
252 elements = state.get(
"elements", {}).duplicate(true)
253 compounds = state.get(
"compounds", {}).duplicate(true)
254 composition_rules = state.get(
"composition_rules", {}).duplicate(true)
257func _compound_definition(compound) -> Dictionary:
258 if compound
is Dictionary:
259 return compound.duplicate(true)
260 var id = str(compound)
261 if compounds.has(id):
262 return compounds[id].duplicate(true)
264 return elements[id].duplicate(true)
268func _composed_card_id(compound_id:String, manifestation_id:String, modifier_ids:Array) -> String:
269 var parts := [
"crafted", compound_id, manifestation_id]
270 var sorted_modifiers = modifier_ids.duplicate()
271 sorted_modifiers.sort()
272 for id
in sorted_modifiers:
273 parts.append(str(id))
274 return "_".join(parts)
277func _composition_description(compound:Dictionary, manifestation:Dictionary, modifier_ids:Array) -> String:
278 var text =
"%s expressed as %s." % [
279 str(compound.get(
"name", compound.get(
"id",
"Compound"))),
280 str(manifestation.get(
"name", manifestation.get(
"id",
"Form"))).to_lower()
282 if not modifier_ids.is_empty():
284 for id
in modifier_ids:
285 names.append(str(modifiers[id].get(
"name", id)))
286 text +=
" Modified by %s." %
", ".join(names)