Money and shops
Usage guide of economy.money and trade.shop: the balance and its rules, shops, offers, stock and restock, settings and defaults, verbs, hooks (money.earn, money.spend, shop.open, shop.buy, shop.sell), engines.
Money and shops (economy.money, trade.shop) #
The player's balance and the merchants that exchange it for items. Readable offline: gripforge docs economy, or the MCP tool gripforge_docs (topic economy).
What it is for #
| Kit | What it adds |
|---|---|
economy.money | the balance as the game variable economy.money: earn and spend with an optional debt, a transaction event for every change, mission rewards paid through it, verbs for scripts |
trade.shop | merchants as data: offers with price and stock, what a merchant buys, a sell rate, restocking, interaction prompt, buy and sell rules |
The rules live in the kits; the counter itself (the screen) is drawn by the interface layer from the events and services.
Turn it on #
gripforge_gamekit_install { project_id: "gkp_…", id: "economy.money" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "economy.money", config: { "startingMoney": 100, "currency": "gold" } }
gripforge_gamekit_install { project_id: "gkp_…", id: "trade.shop" }
economy.money requires only game.engine. trade.shop requires economy.money and inventory.basic (see the Inventory guide), so installing a shop brings both.
Settings and defaults #
| Kit | Key | Default | Meaning |
|---|---|---|---|
economy.money | startingMoney | 0 | balance at the start, when the project does not seed one |
economy.money | currency | $ | symbol shown by the HUD (economy.currency) |
economy.money | allowDebt | false | let a spend go below zero |
trade.shop | buyRate | 0.5 | share of an item's price paid when the player sells it |
trade.shop | buysAnything | true | a merchant buys any item that has a price in any shop |
trade.shop | restockMinutes | 0 | minutes before a sold-out offer comes back (0: never) |
trade.shop | interactLabel | Trade with {name} | the prompt on a merchant; {name} is the shop name |
A project may also seed the balance in its variables ({ "economy.money": 250 } wins over startingMoney); a set_var on it is simply the new balance.
Money rules #
add(amount, reason)credits a finite amount of 0 or more; 0 or an invalid amount changes nothing and emits nothing.spend(amount, reason)debits when the balance covers it, or always withallowDebt; otherwise it answersfalseand the balance is untouched. Amounts are rounded to cents.- Mission
rewards.moneyis paid throughadd(money, "mission:<id>"), once, just beforemission.completed. - Service
economy.money:balance(),currency(),canAfford(amount),add(amount, reason?)(the new balance),spend(amount, reason?). Verbsadd_money,spend_money, conditionmoney_at_least; in a script:{ "add_money": 50 }. - Events:
economy.transaction { amount, balance, reason }(signed: plus is a credit),economy.refused(a spend that could not be paid). Variables:economy.money,economy.currency. The balance is part of the saved game state.
Shops #
{ "shops": [{ "id": "blacksmith", "name": "Blacksmith", "greeting": "Steel for the road?",
"offers": [{ "item": "iron_helmet", "price": 120, "stock": 1 }, { "item": "arrow", "price": 2 }] }] }
An offer with no stock is unlimited. A shop may also list the items the merchant buys (an id, or { item, price } with its own base price) and its own sell rate. A merchant in the world is an entity with the component shop: { id }: interacting opens the shop; open_shop does the same from a script.
buy(shop, item, n)checks the stock and the balance, takes the money and gives the units; a full inventory refuses withno_room.sell(shop, item, n)pays price timesbuyRatefor items the merchant offers or buys, or any priced item whenbuysAnything.- Service
trade.shop:shops(),open(id),close(),current(),offers(id)(with price, stock, affordable, sell price),priceOf,sellPriceOf,buy(...)andsell(...)answering{ ok, reason?, paid? / earned? }. - Verbs
open_shop { shop },close_shop, conditionshop_open { shop? }. Variableshop.open. Eventsshop.opened,shop.closed,shop.bought,shop.sold,shop.refused. The stock is saved.
Hooks and modding #
| Hook | Payload | What a tap may do |
|---|---|---|
money.earn | { amount, reason, balance } | change amount, cancel (nothing is credited) |
money.spend | { amount, reason, balance } | change amount (before the balance check), cancel (refused like a short balance) |
shop.open | { shop } | cancel (a closed shop; shop.refused carries the reason) |
shop.buy | { shop, item, count, price } | change the total price (a discount, a tax), cancel; asked after the stock check and before the balance check |
shop.sell | { shop, item, count, price } | change the total price the merchant pays, cancel |
{ "id": "half_rent", "hook": "money.spend", "match": { "reason": "rent" }, "mul": { "amount": 0.5 } }
Moddable: every setting above, and the shops collection (a registry: { "id": "new", "extends": "blacksmith" } inherits an entry, keys merged, the child wins). Quests and missions pay and check money through the same service (see the Quests guide).
Engines #
economy.money is the same Rust logic on the web and in the native player, and is delivered to Godot and Unity as files and to Unreal through the shared kit library. trade.shop runs on the web and in the native player. The hooks run in those two.
When it does not do what you expect #
| Symptom | Cause and fix |
|---|---|
| A purchase is refused | read the reason: no_room (inventory full), not enough money, or sold out |
spend_money fails at zero | allowDebt is false |
| A reward is not paid | the mission or quest was not completed through the kit, or a money.earn tap cancelled it |
| Selling pays little | buyRate is 0.5 by default; raise it or set a rate on the shop |
| The HUD shows the wrong symbol | set currency (or seed economy.currency) |