RapidGameFramework
Reusable Godot managers for data-driven small games
Loading...
Searching...
No Matches
card_inventory_adapter.gd
Go to the documentation of this file.
1extends RefCounted
2
3
8
9const DEFAULT_RARITY_ORDER := {
10 "Common": 0,
11 "Rare": 1,
12 "Epic": 2,
13 "Legendary": 3
14}
15
16var card_manager
17var modifier_manager
18var rarity_order := DEFAULT_RARITY_ORDER.duplicate(true)
19
20
21func configure(next_card_manager, next_modifier_manager = null, options:Dictionary = {}) -> void:
22 card_manager = next_card_manager
23 modifier_manager = next_modifier_manager
24 rarity_order = DEFAULT_RARITY_ORDER.duplicate(true)
25 for key in options.get("rarity_order", {}).keys():
26 rarity_order[str(key)] = int(options["rarity_order"][key])
27
28
29func filter_instances(instances:Array, filter_id:String, inventory_manager = null) -> Array:
30 var filtered:Array = []
31 for instance in instances:
32 if not instance is Dictionary:
33 continue
34 if matches_filter(instance, filter_id, inventory_manager):
35 filtered.append(instance)
36 return filtered
37
38
39func matches_filter(instance:Dictionary, filter_id:String, inventory_manager = null) -> bool:
40 var card = card_from_instance(instance)
41 match filter_id:
42 "duplicates":
43 if inventory_manager != null and inventory_manager.has_method("count_card"):
44 return inventory_manager.count_card(str(instance.get("base_id", ""))) > 1
45 return false
46 "upgraded":
47 return int(instance.get("level", 1)) > 1 or has_boosted_stats(card) or not instance.get("modifier_ids", []).is_empty()
48 "locked":
49 return bool(instance.get("locked", false))
50 return true
51
52
53func sort_instances(instances:Array, sort_key:String = "rarity", ascending:bool = true) -> Array:
54 var sorted:Array = instances.duplicate(true)
55 sorted.sort_custom(func(a, b): return compare_instances(a, b, sort_key, ascending))
56 return sorted
57
58
59func compare_instances(a:Dictionary, b:Dictionary, sort_key:String = "rarity", ascending:bool = true) -> bool:
60 var card_a = card_from_instance(a)
61 var card_b = card_from_instance(b)
62 var result := 0
63 match sort_key:
64 "name":
65 result = compare_values(instance_base_name(a), instance_base_name(b))
66 "sell":
67 result = compare_values(int(card_a.get("value", 0)), int(card_b.get("value", 0)))
68 "stats":
69 result = compare_values(card_stat_total(card_a), card_stat_total(card_b))
70 "hp":
71 result = compare_values(int(card_a.get("health", 0)), int(card_b.get("health", 0)))
72 "atk":
73 result = compare_values(int(card_a.get("attack", 0)), int(card_b.get("attack", 0)))
74 "def":
75 result = compare_values(int(card_a.get("defense", 0)), int(card_b.get("defense", 0)))
76 "rarity":
77 result = compare_values(rarity_rank(card_a), rarity_rank(card_b))
78 if result == 0:
79 result = compare_values(instance_base_name(a), instance_base_name(b))
80 _:
81 result = compare_values(instance_base_name(a), instance_base_name(b))
82 if result == 0:
83 result = compare_values(str(a.get("uid", "")), str(b.get("uid", "")))
84 return result < 0 if ascending else result > 0
85
86
87func table_record(instance:Dictionary, options:Dictionary = {}) -> Dictionary:
88 var card = card_from_instance(instance)
89 var selected_id := str(options.get("selected_id", ""))
90 var include_sell := bool(options.get("include_sell", true))
91 var text_color:Color = options.get("text_color", Color.WHITE)
92 var muted_color:Color = options.get("muted_color", Color(0.7, 0.7, 0.7))
93 var accent_color:Color = options.get("accent_color", Color(0.95, 0.78, 0.42))
94 var boost_color:Color = options.get("boost_color", Color(0.33, 0.85, 0.47))
95 var icon_callback:Callable = options.get("icon_callback", Callable())
96 var uid := str(instance.get("uid", ""))
97 var values = {
98 "name": {
99 "text": "%s%s" % ["Selected: " if uid == selected_id and not include_sell else "", format_card_name(card)],
100 "color": accent_color if uid == selected_id and not include_sell else text_color
101 },
102 "rarity": {"text": format_rarity_effects(card), "color": accent_color if bool(instance.get("locked", false)) else boost_color if has_boosted_stats(card) else muted_color},
103 "hp": {"text": str(int(card.get("health", 0))), "color": stat_display_color(card, "health", text_color, boost_color), "align": HORIZONTAL_ALIGNMENT_CENTER},
104 "atk": {"text": str(int(card.get("attack", 0))), "color": stat_display_color(card, "attack", text_color, boost_color), "align": HORIZONTAL_ALIGNMENT_CENTER},
105 "def": {"text": str(int(card.get("defense", 0))), "color": stat_display_color(card, "defense", text_color, boost_color), "align": HORIZONTAL_ALIGNMENT_CENTER}
106 }
107 if include_sell:
108 values["sell"] = {"text": "$%d" % int(card.get("value", 0)), "color": accent_color, "align": HORIZONTAL_ALIGNMENT_RIGHT}
109 var border:Color = options.get("border_color", Color(0.25, 0.25, 0.25))
110 if bool(instance.get("locked", false)):
111 border = accent_color
112 elif has_boosted_stats(card):
113 border = boost_color
114 var record := {
115 "id": uid,
116 "selected": uid == selected_id,
117 "border_color": border,
118 "values": values
119 }
120 if icon_callback.is_valid():
121 record["icon"] = icon_callback.call(card, instance, int(options.get("icon_size", 38)))
122 return record
123
124
125func table_records(instances:Array, options:Dictionary = {}) -> Array:
126 var records:Array = []
127 for instance in instances:
128 if instance is Dictionary:
129 records.append(table_record(instance, options))
130 return records
131
132
133func card_from_instance(instance:Dictionary) -> Dictionary:
134 if card_manager == null or not card_manager.has_method("get_card"):
135 return instance.duplicate(true)
136 var base_id = str(instance.get("base_id", instance.get("id", "")))
137 var card = card_manager.get_card(base_id).duplicate(true)
138 if card.is_empty():
139 return instance.duplicate(true)
140 if modifier_manager != null and modifier_manager.has_method("apply_instance"):
141 card = modifier_manager.apply_instance(card, instance)
142 return card
143
144
145func base_card_for(card:Dictionary) -> Dictionary:
146 if card_manager == null or not card_manager.has_method("get_card"):
147 return {}
148 var base_id = str(card.get("base_id", card.get("base_card_id", card.get("id", ""))))
149 return card_manager.get_card(base_id)
150
151
152func has_boosted_stats(card:Dictionary) -> bool:
153 var base_card = base_card_for(card)
154 if base_card.is_empty():
155 return false
156 return int(card.get("health", 0)) > int(base_card.get("health", 0)) \
157 or int(card.get("attack", 0)) > int(base_card.get("attack", 0)) \
158 or int(card.get("defense", 0)) > int(base_card.get("defense", 0))
159
160
161func stat_display_color(card:Dictionary, stat:String, normal_color:Color, boost_color:Color) -> Color:
162 var base_card = base_card_for(card)
163 if not base_card.is_empty() and int(card.get(stat, 0)) > int(base_card.get(stat, 0)):
164 return boost_color
165 return normal_color
166
167
168func format_card_name(card:Dictionary) -> String:
169 return str(card.get("name", "Card"))
170
171
172func format_rarity_effects(card:Dictionary) -> String:
173 var parts:Array = [str(card.get("rarity", "Common"))]
174 var level := int(card.get("level", 1))
175 if level > 1:
176 parts.append("+%d" % (level - 1))
177 var modifier_names:Array = []
178 if modifier_manager != null and modifier_manager.has_method("get_modifier_names"):
179 modifier_names = modifier_manager.get_modifier_names(card.get("modifier_ids", []))
180 for name in modifier_names:
181 parts.append(str(name))
182 return ", ".join(parts)
183
184
185func card_stat_total(card:Dictionary) -> int:
186 return int(card.get("health", 0)) + int(card.get("attack", 0)) + int(card.get("defense", 0))
187
188
189func instance_base_name(instance:Dictionary) -> String:
190 if card_manager == null or not card_manager.has_method("get_card"):
191 return str(instance.get("name", "")).to_lower()
192 var base_card = card_manager.get_card(str(instance.get("base_id", instance.get("id", ""))))
193 return str(base_card.get("name", "")).to_lower()
194
195
196func rarity_rank(card:Dictionary) -> int:
197 return int(rarity_order.get(str(card.get("rarity", "Common")), 99))
198
199
200func compare_values(a, b) -> int:
201 if a < b:
202 return -1
203 if a > b:
204 return 1
205 return 0