179 lines
4.6 KiB
GDScript
179 lines
4.6 KiB
GDScript
class_name CPPool
|
|
extends RefCounted
|
|
|
|
## CPPool - Tracks Crystal Points generated during a turn
|
|
|
|
# CP stored by element
|
|
var _cp: Dictionary = {}
|
|
|
|
func _init() -> void:
|
|
clear()
|
|
|
|
## Clear all CP (called at end of each action)
|
|
func clear() -> void:
|
|
for element in Enums.Element.values():
|
|
_cp[element] = 0
|
|
|
|
## Add CP of a specific element
|
|
func add_cp(element: Enums.Element, amount: int) -> void:
|
|
_cp[element] = _cp.get(element, 0) + amount
|
|
|
|
## Get CP of a specific element
|
|
func get_cp(element: Enums.Element) -> int:
|
|
return _cp.get(element, 0)
|
|
|
|
## Get total CP available
|
|
func get_total_cp() -> int:
|
|
var total = 0
|
|
for element in _cp:
|
|
total += _cp[element]
|
|
return total
|
|
|
|
## Check if we can afford a card cost
|
|
func can_afford_card(card_data: CardDatabase.CardData) -> bool:
|
|
if not card_data:
|
|
return false
|
|
|
|
var cost = card_data.cost
|
|
var elements = card_data.elements
|
|
|
|
# For Light/Dark cards, just need total CP
|
|
var is_light_dark = false
|
|
for element in elements:
|
|
if Enums.is_light_or_dark(element):
|
|
is_light_dark = true
|
|
break
|
|
|
|
if is_light_dark:
|
|
return get_total_cp() >= cost
|
|
|
|
# For multi-element cards, need at least 1 CP of each element
|
|
if elements.size() > 1:
|
|
for element in elements:
|
|
if get_cp(element) < 1:
|
|
return false
|
|
# Total must be at least the cost
|
|
return get_total_cp() >= cost
|
|
|
|
# For single element cards, need at least 1 CP of that element
|
|
var primary_element = elements[0] if elements.size() > 0 else Enums.Element.FIRE
|
|
if get_cp(primary_element) < 1:
|
|
return false
|
|
|
|
return get_total_cp() >= cost
|
|
|
|
## Spend CP to pay a card cost
|
|
## Returns true if successful, false if cannot afford
|
|
func spend_for_card(card_data: CardDatabase.CardData) -> bool:
|
|
if not can_afford_card(card_data):
|
|
return false
|
|
|
|
var cost = card_data.cost
|
|
var elements = card_data.elements
|
|
var remaining = cost
|
|
|
|
# For multi-element, spend 1 of each required element first
|
|
if elements.size() > 1:
|
|
for element in elements:
|
|
_cp[element] -= 1
|
|
remaining -= 1
|
|
|
|
# For single element (non-Light/Dark), spend at least 1 of that element
|
|
elif elements.size() == 1:
|
|
var element = elements[0]
|
|
if not Enums.is_light_or_dark(element):
|
|
_cp[element] -= 1
|
|
remaining -= 1
|
|
|
|
# Spend remaining from any element
|
|
while remaining > 0:
|
|
var spent = false
|
|
for element in _cp:
|
|
if _cp[element] > 0:
|
|
_cp[element] -= 1
|
|
remaining -= 1
|
|
spent = true
|
|
break
|
|
if not spent:
|
|
push_error("Failed to spend remaining CP")
|
|
return false
|
|
|
|
return true
|
|
|
|
## Check if we can afford an ability cost
|
|
func can_afford_ability(cost: CardDatabase.CostData) -> bool:
|
|
if not cost:
|
|
return true # No cost means free
|
|
|
|
# Check element-specific requirements
|
|
if cost.fire > 0 and get_cp(Enums.Element.FIRE) < cost.fire:
|
|
return false
|
|
if cost.ice > 0 and get_cp(Enums.Element.ICE) < cost.ice:
|
|
return false
|
|
if cost.wind > 0 and get_cp(Enums.Element.WIND) < cost.wind:
|
|
return false
|
|
if cost.lightning > 0 and get_cp(Enums.Element.LIGHTNING) < cost.lightning:
|
|
return false
|
|
if cost.water > 0 and get_cp(Enums.Element.WATER) < cost.water:
|
|
return false
|
|
if cost.earth > 0 and get_cp(Enums.Element.EARTH) < cost.earth:
|
|
return false
|
|
if cost.light > 0 and get_cp(Enums.Element.LIGHT) < cost.light:
|
|
return false
|
|
if cost.dark > 0 and get_cp(Enums.Element.DARK) < cost.dark:
|
|
return false
|
|
|
|
# Check total
|
|
return get_total_cp() >= cost.get_total_cp()
|
|
|
|
## Spend CP to pay an ability cost
|
|
func spend_for_ability(cost: CardDatabase.CostData) -> bool:
|
|
if not can_afford_ability(cost):
|
|
return false
|
|
|
|
# Spend element-specific CP
|
|
if cost.fire > 0:
|
|
_cp[Enums.Element.FIRE] -= cost.fire
|
|
if cost.ice > 0:
|
|
_cp[Enums.Element.ICE] -= cost.ice
|
|
if cost.wind > 0:
|
|
_cp[Enums.Element.WIND] -= cost.wind
|
|
if cost.lightning > 0:
|
|
_cp[Enums.Element.LIGHTNING] -= cost.lightning
|
|
if cost.water > 0:
|
|
_cp[Enums.Element.WATER] -= cost.water
|
|
if cost.earth > 0:
|
|
_cp[Enums.Element.EARTH] -= cost.earth
|
|
if cost.light > 0:
|
|
_cp[Enums.Element.LIGHT] -= cost.light
|
|
if cost.dark > 0:
|
|
_cp[Enums.Element.DARK] -= cost.dark
|
|
|
|
# Spend generic from any element
|
|
var generic_remaining = cost.generic
|
|
while generic_remaining > 0:
|
|
for element in _cp:
|
|
if _cp[element] > 0:
|
|
_cp[element] -= 1
|
|
generic_remaining -= 1
|
|
break
|
|
|
|
return true
|
|
|
|
## Get a display-friendly dictionary of current CP
|
|
func get_display_data() -> Dictionary:
|
|
var data = {}
|
|
for element in _cp:
|
|
if _cp[element] > 0:
|
|
data[Enums.element_to_string(element)] = _cp[element]
|
|
return data
|
|
|
|
func _to_string() -> String:
|
|
var parts = []
|
|
for element in _cp:
|
|
if _cp[element] > 0:
|
|
parts.append("%s: %d" % [Enums.element_to_string(element), _cp[element]])
|
|
if parts.size() == 0:
|
|
return "[CPPool: empty]"
|
|
return "[CPPool: " + ", ".join(parts) + "]"
|