Allow late Mentat bribes and retain turn-end promises

This commit is contained in:
Quintine committed 2026-10-26 15:41:10 +11:00
1 parent f5ae61f382
commit c81e00e6dd
19 files changed
+590 -51

No files matched your search

+2 -1
View File
@@ -41,7 +41,8 @@ export function BribeClaimFields(props: {
{error && <p role="alert">{error}</p>}
<p className="fine" id="truth-bribe-help">
Count cumulative future ordinary bribe payments to this recipient after the answer; smaller payments add together.
Earlier payments, gifts and ally aid do not count. The sender pays now; the recipient can spend the payment at Mentat Pause.
Earlier payments, gifts and ally aid do not count. The sender pays now; the recipient collects the payment at the start of Mentat Pause.
Payments made during Mentat Pause wait until the start of next turn&apos;s Mentat Pause.
</p>
</fieldset>;
}
+5 -3
View File
@@ -12,14 +12,15 @@ type BribePromiseProps = { game: GameView; busy: boolean; send: (action: Action)
export function BribePromiseGuideButton(props: BribePromiseProps) {
const game = props.game, guide = game.bribePromiseGuide;
if (!guide) return null;
const actor = game.me, turn = game.turn, action = guide.action;
const actor = game.me, turn = game.turn, phase = game.phase, action = guide.action;
const event = action.bribePromiseEvent, signature = JSON.stringify(action);
const canAct = () => {
const current = props.game, me = current.players.find(player => player.id === current.me), options = current.bribeOptions;
const target = typeof action.target === 'string' ? current.players.find(player => player.id === action.target) : undefined;
const limit = options.targets.find(recipient => recipient.id === action.target);
return !props.busy && current === game && bribePromiseModeSupported(current) && current.status === 'playing' &&
Number.isSafeInteger(current.phase) && current.phase >= 0 && current.phase <= 7 && current.turn === turn && current.me === actor &&
Number.isSafeInteger(current.phase) && current.phase >= 0 && current.phase <= 8 && current.phase === phase &&
current.turn === turn && current.me === actor &&
current.bribePromiseGuide === guide && current.bribePromiseGuide.action === action && JSON.stringify(action) === signature &&
action.type === 'bribe' && typeof event === 'string' &&
liveBribePromises(current.bribePromises, actor, turn).some(promise => promise.event === event) &&
@@ -56,7 +57,8 @@ export function BribePromises(props: BribePromiseProps) {
Prior payments, gifts and ally aid do not count.
</p>
<p className="fine">
The sender pays immediately. The recipient can spend the payment only at Mentat Pause.
The sender pays immediately. The recipient collects the payment at the start of Mentat Pause.
Payments made during Mentat Pause wait until the start of next turn&apos;s Mentat Pause.
Ordinary bribes can be paid out of turn when the current bribe controls permit them; original timing and payment rules still apply.
{' '}<a href="/rules#truthtrance-bribe">Bribe promise rules</a>.
</p>
+1 -1
View File
@@ -19,7 +19,7 @@ export function Bribes({ game: g, act, busy }: {
return (
<details className="notice bribe-panel">
<summary>Bribes{options.incoming > 0 ? ` · ${options.incoming} spice awaiting Mentat` : ''}</summary>
<p id={description}>Pay another non-allied faction now. The amount is public; the recipient can spend their share only from the next Mentat Pause. A message or promise alone does not pay spice.</p>
<p id={description}>Pay another non-allied faction now. The amount is public; the recipient collects their share at the start of Mentat Pause. Payments made during Mentat Pause wait until the start of next turn&apos;s Mentat Pause. A message or promise alone does not pay spice.</p>
<p>Your incoming bribes: <strong>{options.incoming} spice</strong>, separate from your spendable supply.</p>
{options.blocked ? <output className="bribe-status">{options.blocked}</output> : null}
{options.targets.length === 0 ? <p>No non-allied recipient is available.</p> : (
+2 -2
View File
@@ -266,7 +266,7 @@ export function Truthtrance({
</>
) : w.question!.kind === 'bribe' ? (
<>
<p className="notice">Yes requires cumulative ordinary bribe payments to this named recipient while possible. No keeps all later payments below the minimum. Earlier payments, gifts and allied aid do not count. You pay now; the recipient spends the receipt at Mentat Pause.</p>
<p className="notice">Yes requires cumulative ordinary bribe payments to this named recipient while possible. No keeps all later payments below the minimum. Earlier payments, gifts and allied aid do not count. You pay now; the recipient collects at the next Mentat opening. Payments during Mentat wait until next turn&apos;s opening.</p>
{(g.truthBribeAnswers ?? []).map(answer => <div key={answer}>
{button(`Answer ${answer === 'yes' ? 'Yes' : answer === 'no' ? 'No' : 'I don’t know'}`, { type: 'truthAnswer', answer })}
</div>)}
@@ -453,7 +453,7 @@ export function Truthtrance({
<BribeClaimFields value={bribeClaim} recipients={bribeRecipients} disabled={busy || !g.truthBribeTargets.includes(target)}
onChange={claim => setBribeSelection({ recipient: claim.recipient, minimum: claim.minimum })} />
<p className="fine">Count cumulative ordinary payer payments after this answer, before this turn ends. Keep the current spendable spice needed by every Yes. Actual bribe timing and deferred recipient receipts remain; optional modules and future-income preparation remain unfinished.</p>
{!g.truthBribeTargets.includes(target) && <p className="notice">Choose a supported participant before Mentat Pause and finish pending decisions.</p>}
{!g.truthBribeTargets.includes(target) && <p className="notice">Choose a supported participant before this turn ends and finish pending decisions.</p>}
<p className="notice" aria-label="Public bribe question preview">{truthQuestionText(question, leaderName, locationName, name)}</p>
</>
) : kind === 'revival' ? (