187 lines
4.5 KiB
GDScript
187 lines
4.5 KiB
GDScript
class_name FishingShopStock
|
|
extends RefCounted
|
|
|
|
const ItemCatalogType = preload("res://items/item_catalog.gd")
|
|
const ItemDataType = preload("res://items/item_data.gd")
|
|
const FishingRodDataType = preload("res://items/fishing_rod_data.gd")
|
|
const PlayerBagType = preload("res://inventory/player_bag.gd")
|
|
const PlayerWalletType = preload("res://economy/player_wallet.gd")
|
|
const WORM_MAX_STACK: int = 10
|
|
const FISH_FINDER_ID: StringName = &"fish_finder"
|
|
const MAGNET_ID: StringName = &"magnet"
|
|
const BATTERIES_ID: StringName = &"batteries"
|
|
|
|
const ITEM_PRICES: Dictionary[StringName, int] = {
|
|
&"worms": 1,
|
|
&"snails": 3,
|
|
&"shrimp": 7,
|
|
&"squid_chunks": 15,
|
|
&"whole_anchovy": 60,
|
|
&"whole_sardine": 30,
|
|
&"luminous_roe": 125,
|
|
&"the_standby": 750,
|
|
&"coffee": 20,
|
|
&"energy_drink": 35,
|
|
&"snack": 30,
|
|
FISH_FINDER_ID: 500,
|
|
MAGNET_ID: 250,
|
|
BATTERIES_ID: 15,
|
|
}
|
|
const BAIT_UNLOCK_PRICES: Dictionary[StringName, int] = {
|
|
&"snails": 400,
|
|
&"shrimp": 1200,
|
|
&"squid_chunks": 3500,
|
|
&"whole_anchovy": 22000,
|
|
&"whole_sardine": 9000,
|
|
&"luminous_roe": 50000,
|
|
}
|
|
const ITEM_ORDER: Array[StringName] = [
|
|
&"worms",
|
|
&"snails",
|
|
&"shrimp",
|
|
&"squid_chunks",
|
|
&"whole_sardine",
|
|
&"whole_anchovy",
|
|
&"luminous_roe",
|
|
&"the_standby",
|
|
FISH_FINDER_ID,
|
|
MAGNET_ID,
|
|
&"coffee",
|
|
&"energy_drink",
|
|
&"snack",
|
|
BATTERIES_ID,
|
|
]
|
|
|
|
|
|
static func get_price(item_id: StringName) -> int:
|
|
return ITEM_PRICES.get(item_id, -1)
|
|
|
|
|
|
static func get_stock_item_ids() -> Array[StringName]:
|
|
return ITEM_ORDER.duplicate()
|
|
|
|
|
|
static func get_rod_stock(
|
|
catalog: ItemCatalogType,
|
|
) -> Array[FishingRodDataType]:
|
|
var rods: Array[FishingRodDataType] = []
|
|
if catalog == null:
|
|
return rods
|
|
for item: ItemDataType in catalog.get_available_items():
|
|
var rod := item as FishingRodDataType
|
|
if rod != null and rod.is_shop_available():
|
|
rods.append(rod)
|
|
rods.sort_custom(
|
|
func(left: FishingRodDataType, right: FishingRodDataType) -> bool:
|
|
if left.shop_order == right.shop_order:
|
|
return str(left.item_id) < str(right.item_id)
|
|
return left.shop_order < right.shop_order
|
|
)
|
|
return rods
|
|
|
|
|
|
static func get_unlock_price(item_id: StringName) -> int:
|
|
return BAIT_UNLOCK_PRICES.get(item_id, -1)
|
|
|
|
|
|
static func get_purchase_quantity(
|
|
item_id: StringName,
|
|
owned: int,
|
|
maximum_stack: int = WORM_MAX_STACK,
|
|
) -> int:
|
|
if is_bait_topoff(item_id):
|
|
return maxi(maximum_stack - owned, 0)
|
|
return 1
|
|
|
|
|
|
static func is_bait_topoff(item_id: StringName) -> bool:
|
|
return item_id == &"worms" or BAIT_UNLOCK_PRICES.has(item_id)
|
|
|
|
|
|
static func is_permanent_unlock(
|
|
item_id: StringName,
|
|
item: ItemDataType,
|
|
) -> bool:
|
|
return (
|
|
item != null
|
|
and (
|
|
item.is_lure()
|
|
or item_id == FISH_FINDER_ID
|
|
or item_id == MAGNET_ID
|
|
or item is FishingRodDataType
|
|
)
|
|
)
|
|
|
|
|
|
static func is_passive_supply(item_id: StringName) -> bool:
|
|
return item_id == BATTERIES_ID
|
|
|
|
|
|
static func get_purchase_cost(
|
|
item_id: StringName,
|
|
quantity: int,
|
|
bait_unlocked: bool,
|
|
) -> int:
|
|
if quantity <= 0:
|
|
return -1
|
|
if is_bait_topoff(item_id) and item_id != &"worms" and not bait_unlocked:
|
|
return get_unlock_price(item_id)
|
|
var unit_price: int = get_price(item_id)
|
|
return unit_price * quantity if unit_price >= 0 else -1
|
|
|
|
|
|
static func purchase_one(
|
|
item_id: StringName,
|
|
wallet: PlayerWalletType,
|
|
bag: PlayerBagType,
|
|
catalog: ItemCatalogType,
|
|
) -> bool:
|
|
if wallet == null or bag == null or catalog == null:
|
|
return false
|
|
var item: ItemDataType = catalog.get_item_by_id(item_id)
|
|
if item == null or not item.is_available():
|
|
return false
|
|
var bait_topoff: bool = is_bait_topoff(item_id)
|
|
var permanent_unlock: bool = is_permanent_unlock(item_id, item)
|
|
var quantity: int = get_purchase_quantity(
|
|
item_id,
|
|
bag.get_quantity(item_id),
|
|
item.max_stack if item != null else WORM_MAX_STACK,
|
|
)
|
|
var rod := item as FishingRodDataType
|
|
var price: int = (
|
|
rod.shop_price
|
|
if rod != null
|
|
else get_purchase_cost(
|
|
item_id,
|
|
quantity,
|
|
bag.is_bait_unlocked(item_id),
|
|
)
|
|
)
|
|
if (
|
|
price < 0
|
|
or not item.is_available()
|
|
or (rod != null and not rod.is_shop_available())
|
|
or (
|
|
item.category != ItemDataType.Category.CONSUMABLE
|
|
and not bait_topoff
|
|
and not permanent_unlock
|
|
)
|
|
or (not item.stackable and not permanent_unlock)
|
|
or (
|
|
not item.usable
|
|
and not bait_topoff
|
|
and not permanent_unlock
|
|
and not is_passive_supply(item_id)
|
|
)
|
|
or not bag.can_add_item(item_id, quantity)
|
|
or not wallet.can_afford(price)
|
|
):
|
|
return false
|
|
if not wallet.debit(price):
|
|
return false
|
|
if bag.add_item(item_id, quantity):
|
|
return true
|
|
if not wallet.credit(price):
|
|
push_error("Fishing Shop failed to roll back an item purchase.")
|
|
return false
|