9const DEFAULT_RARITY_ORDER := {
18var rarity_order := DEFAULT_RARITY_ORDER.duplicate(true)
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])
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:
34 if matches_filter(instance, filter_id, inventory_manager):
35 filtered.append(instance)
39func matches_filter(instance:Dictionary, filter_id:String, inventory_manager = null) -> bool:
40 var card = card_from_instance(instance)
43 if inventory_manager != null
and inventory_manager.has_method(
"count_card"):
44 return inventory_manager.count_card(str(instance.get(
"base_id",
""))) > 1
47 return int(instance.get(
"level", 1)) > 1
or has_boosted_stats(card)
or not instance.get(
"modifier_ids", []).is_empty()
49 return bool(instance.get(
"locked", false))
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))
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)
65 result = compare_values(instance_base_name(a), instance_base_name(b))
67 result = compare_values(int(card_a.get(
"value", 0)), int(card_b.get(
"value", 0)))
69 result = compare_values(card_stat_total(card_a), card_stat_total(card_b))
71 result = compare_values(int(card_a.get(
"health", 0)), int(card_b.get(
"health", 0)))
73 result = compare_values(int(card_a.get(
"attack", 0)), int(card_b.get(
"attack", 0)))
75 result = compare_values(int(card_a.get(
"defense", 0)), int(card_b.get(
"defense", 0)))
77 result = compare_values(rarity_rank(card_a), rarity_rank(card_b))
79 result = compare_values(instance_base_name(a), instance_base_name(b))
81 result = compare_values(instance_base_name(a), instance_base_name(b))
83 result = compare_values(str(a.get(
"uid",
"")), str(b.get(
"uid",
"")))
84 return result < 0
if ascending
else result > 0
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",
""))
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
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}
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):
116 "selected": uid == selected_id,
117 "border_color": border,
120 if icon_callback.is_valid():
121 record[
"icon"] = icon_callback.call(card, instance, int(options.get(
"icon_size", 38)))
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))
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)
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)
145func base_card_for(card:Dictionary) -> Dictionary:
146 if card_manager == null
or not card_manager.has_method(
"get_card"):
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)
152func has_boosted_stats(card:Dictionary) -> bool:
153 var base_card = base_card_for(card)
154 if base_card.is_empty():
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))
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)):
168func format_card_name(card:Dictionary) -> String:
169 return str(card.get(
"name",
"Card"))
172func format_rarity_effects(card:Dictionary) -> String:
173 var parts:Array = [str(card.get(
"rarity",
"Common"))]
174 var level := int(card.get(
"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)
185func card_stat_total(card:Dictionary) -> int:
186 return int(card.get(
"health", 0)) + int(card.get(
"attack", 0)) + int(card.get(
"defense", 0))
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()
196func rarity_rank(card:Dictionary) -> int:
197 return int(rarity_order.get(str(card.get(
"rarity",
"Common")), 99))
200func compare_values(a, b) -> int: