Expert patterns for game economies including currency management (multi-currency, wallet system), shop systems (buy/sell prices, stock limits), dynamic pricing (supply/demand), loot tables (weighted drops, rarity tiers), and economic balance (inflation control, currency sinks). Use for RPGs, trading games, or resource management systems. Trigger keywords: EconomyManager, currency, shop_item, loot_table, dynamic_pricing, buy_sell_spread, currency_sink, inflation, item_rarity.
Expert guidance for designing balanced game economies with currency, shops, and loot.
Specialized data container for defining distinct denominations (Gold, Gems, XP) with UI metadata.
Centralized AutoLoad orchestrator for managing balances and processing secure transactions.
Resource-based definition for purchasables, including pricing, currency types, and stock limits.
Decoupled logic for handling buy/sell exchanges between the Wallet and Inventory systems.
Injection pattern for applying temporary discounts or markups based on world state (e.g. Sales).
Reactive UI hook for automatically updating currency displays when balances change.
Bridge node for capturing loot events and adding funds to the player's wallet.
Expert logic for serializing financial states into secure, loadable dictionaries.
Visual feedback controller that triggers particles or animations upon financial gain.
Advanced barter system definition for multi-item "Quid Pro Quo" transactions.
int for large-scale premium economies — Standard 32-bit integers cap at 2.1 billion. For massive quantities, use float or a custom BigInt structure [12].if current >= amount BEFORE subtracting. Negative gold can break logic and save files.WalletManager should decide if it's valid and update the state.0.1 + 0.2 might equal 0.30000000000000004, leading to discrepancies. Use int for cents/smallest units.# economy_manager.gd (AutoLoad)
extends Node
signal currency_changed(old_amount: int, new_amount: int)
var gold: int = 0
func add_currency(amount: int) -> void:
var old := gold
gold += amount
currency_changed.emit(old, gold)
func spend_currency(amount: int) -> bool:
if gold < amount:
return false
var old := gold
gold -= amount
currency_changed.emit(old, gold)
return true
func has_currency(amount: int) -> bool:
return gold >= amount
# shop_item.gd
class_name ShopItem
extends Resource
@export var item: Item
@export var buy_price: int
@export var sell_price: int
@export var stock: int = -1 # -1 = infinite
func can_buy() -> bool:
return stock != 0
# shop.gd
class_name Shop
extends Resource
@export var shop_name: String
@export var items: Array[ShopItem] = []
func buy_item(shop_item: ShopItem, inventory: Inventory) -> bool:
if not shop_item.can_buy():
return false
if not EconomyManager.has_currency(shop_item.buy_price):
return false
if not EconomyManager.spend_currency(shop_item.buy_price):
return false
inventory.add_item(shop_item.item, 1)
if shop_item.stock > 0:
shop_item.stock -= 1
return true
func sell_item(item: Item, inventory: Inventory) -> bool:
# Find matching shop item for sell price
var shop_item := get_shop_item_for(item)
if not shop_item:
return false
if not inventory.has_item(item, 1):
return false
inventory.remove_item(item, 1)
EconomyManager.add_currency(shop_item.sell_price)
return true
func get_shop_item_for(item: Item) -> ShopItem:
for shop_item in items:
if shop_item.item == item:
return shop_item
return null
func calculate_sell_price(buy_price: int, markup: float = 0.5) -> int:
# Sell for 50% of buy price
return int(buy_price * markup)
func calculate_dynamic_price(base_price: int, demand: float) -> int:
# Price increases with demand
return int(base_price * (1.0 + demand))
# loot_table.gd
class_name LootTable
extends Resource
@export var drops: Array[LootDrop] = []
func roll_loot() -> Array[Item]:
var items: Array[Item] = []
for drop in drops:
if randf() < drop.chance:
items.append(drop.item)
return items
# loot_drop.gd
class_name LootDrop
extends Resource
@export var item: Item
@export var chance: float = 0.5
@export var min_amount: int = 1
@export var max_amount: int = 1
godot-inventory-system, godot-save-load-systems