adventure: let a player leave town from the web, not only read about it
W5a gave the web two verbs that cost nothing. These are the three that take arguments and spend coins: set out for a zone with a supply loadout, walk back into the run you extracted from, hire the pet sitter for a week or a month. Between them they cover the most common thing anybody does in the game, which until now could only be typed into Matrix. Arguments are the new surface, so they are the thing to be careful with. Nothing in a request is trusted: every zone, loadout and duration is looked up in the offer list gogobee pushed onto that owner's own private row, and the order stores what was found there rather than what was sent. A forged zone resolves to nothing and never becomes an order. gogobee then re-resolves all of it anyway, because an offer is a quote and a quote is not a permission. The money confirm is the equip panel's, lifted: cost, balance, and the balance it leaves. When it does not cover, it says so instead of printing a negative. Verified in a browser rather than only in tests, which is where both real defects came from: the confirm box was appending to the whole panel and so appeared at the bottom of the section instead of under the button that raised it, and button prices printed as EUR45000 above a dialog reading EUR45,000. Claude-Session: https://claude.ai/code/session_012bxpQQJDjC1mTtLN3VVtBQ
This commit is contained in:
@@ -25,6 +25,59 @@ type PlayerDetail struct {
|
||||
Slots []EquipSlotView `json:"slots,omitempty"`
|
||||
// Balance is the owner's euro balance, for the upgrade/repair confirm dialogs.
|
||||
Balance float64 `json:"balance,omitempty"`
|
||||
// Zones / Resume / Babysit are the W5b action offers: what this owner may ask
|
||||
// for from the web right now, priced by gogobee. Pete renders these and does no
|
||||
// arithmetic — every price and every gate is the game's, quoted at push time.
|
||||
//
|
||||
// An offer is NOT a permission. It is up to two minutes stale, so gogobee
|
||||
// re-resolves the zone, the price and the fee when the order lands. What the
|
||||
// list buys is a page that does not offer a button certain to be refused.
|
||||
Zones []ZoneOffer `json:"zones,omitempty"`
|
||||
Resume *ResumeOffer `json:"resume,omitempty"`
|
||||
Babysit *BabysitOffer `json:"babysit,omitempty"`
|
||||
}
|
||||
|
||||
// ZoneOffer is one place the owner may set out for. Absent entirely while they
|
||||
// are already out, so an empty list means "not right now" rather than "nowhere".
|
||||
type ZoneOffer struct {
|
||||
ID string `json:"id"`
|
||||
Display string `json:"display"`
|
||||
Tier int `json:"tier"`
|
||||
Hook string `json:"hook,omitempty"`
|
||||
Postgame bool `json:"postgame,omitempty"`
|
||||
Loadouts []LoadoutOffer `json:"loadouts,omitempty"`
|
||||
}
|
||||
|
||||
// LoadoutOffer is one supply preset: what it is called, what it costs, and how
|
||||
// many days of provisions it buys. Key is what the order carries back.
|
||||
type LoadoutOffer struct {
|
||||
Key string `json:"key"` // lean|balanced|heavy
|
||||
Name string `json:"name"`
|
||||
Blurb string `json:"blurb,omitempty"`
|
||||
Cost int `json:"cost"`
|
||||
Days int `json:"days"`
|
||||
}
|
||||
|
||||
// ResumeOffer is the extracted expedition still waiting to be walked back into.
|
||||
// ExpiresAt is the end of the seven-day window, so the page can say how long is
|
||||
// left rather than only that there is a way back.
|
||||
type ResumeOffer struct {
|
||||
ZoneID string `json:"zone_id"`
|
||||
Display string `json:"display"`
|
||||
Tier int `json:"tier"`
|
||||
Day int `json:"day"`
|
||||
ExpiresAt int64 `json:"expires_at,omitempty"`
|
||||
Loadouts []LoadoutOffer `json:"loadouts,omitempty"`
|
||||
}
|
||||
|
||||
// BabysitOffer is the pet sitter's standing and the two prices they charge. It
|
||||
// is pushed even when a sitter is engaged: "looked after until Tuesday" is what
|
||||
// the page should say instead of a buy button.
|
||||
type BabysitOffer struct {
|
||||
Active bool `json:"active"`
|
||||
ExpiresAt int64 `json:"expires_at,omitempty"`
|
||||
WeekCost int `json:"week_cost"`
|
||||
MonthCost int `json:"month_cost"`
|
||||
}
|
||||
|
||||
// EquipSlotView is one of the 5 standard equipment slots as gogobee pushed it,
|
||||
|
||||
Reference in New Issue
Block a user