Pooling the party's juice and halving every reward in Godot
Juice stops belonging to each character and becomes one party pool, with every reward cut in half in a single place and a save migration to match.
Juice, the game’s experience points, used to belong to each of the four characters. Now the party has one pool of it, and every reward is half what it was. I changed it this afternoon, after I picked an answer on a question about the Juice Injector and decided it was really a question about the whole game.
Why did juice become one pool?
The Juice Injector had a row that said who pays for a heal or a raise, and that was awkward. I picked pooling the party’s juice for it, and then I wrote that juice should be purely party based and that every reward should be cut in half. That’s a core rule, so the pool had to reach everything that touches juice, not only the injector. Juice is still spent on one member’s stats and skills at a time, and it still buys ranks only at a safe house. The only thing that’s shared is the pile.
How can a pool go in without rewriting every price?
Every cost and refusal in the game already asks a member how much juice they have. So I didn’t change those. A JuicePool holds two numbers, what’s unspent and everything ever earned, and the party owns one. When the party is set up, each member gets a reference to it, and a member’s xp and spend_xp() now read and spend the pool. A member who isn’t in a party yet, like one on the creation screen, keeps a pool of their own and pours it into the party when they join.
The halving happens at the single place juice comes in. XpRules.reward() multiplies by 0.5, rounds, and pays at least 1 for any award. A monster’s value, a quest’s award and an ampoule’s juice are written in the content as they always were, and they all halve together. A meat sack kill pays 50 instead of 100, the three quests pay 40, 200 and 150, and a placed corpse pays 80.
A kill is paid as the party stands. The award is split by the party’s size, a member who’s down counts for half their share and a dead one for nothing, and the sum is rounded once. Rounding once matters because a kill with all four standing then pays exactly half its value, not a few points off from four separate roundings. The cheapest kill still pays 50, enough for a first skill rank.
On screen there’s a red JUICE readout next to the clock, and the floating number rises from it instead of over each card. At the injector, heal, raise and ranks come out of the pool. The “paid from” row is gone, a line at the top shows the party’s juice, and someone has to be standing to work the vat. When the whole party is wiped, it leaves the entire pool where it fell, and walking back picks up exactly that.
How do old saves cope?
The save version goes from 10 to 11. The party section now has one juice object with amount and earned, and the members’ own xp and xp_earned are no longer saved. A migration adds every member’s figures into that object, erases them from the members, and keeps earned at least as big as amount. It leaves a file alone if it already has a juice entry.
Why can’t killed monsters be eaten anymore?
When I added the injector, every killed monster’s body could be eaten for a quarter of the kill. I decided that was wrong, because the kill already paid. So I put the monster body script back the way it was before, deleted the class that made bodies edible and removed its key from the save schema. A killed body is searched, and when it’s empty it sinks away again. Corpses placed in the world as scenery, like the ones in the Breakout Site, still have Eat, and they pay half of what they used to into the pool.
Also done
- About twenty older tests changed from per-member, full-value numbers to the pool and half rewards, and a new
juice_pooltest has 43 checks. - The last full run of the branch had 59 tests with none failing.
- I replaced the old injector film with a new one, because the old script used the deleted eating class and the payer row.
The injector’s prices are still placeholders, so I haven’t decided whether they should drop with everything else.