mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 08:32:41 +00:00
N6/C2: player-initiated duels — staked, no-death PvP
`!duel @user [stake]` (+ `!adventure duel`; accept/decline/status). A staked arena bout resolved through the auto-resolve combat engine. The engine is asymmetric — N player-seats vs one monster-shaped enemy, no seat for a second PC — so a duel builds each fighter as their real player Combatant and synthesises the opponent as an enemy stat block from their sheet. That is lopsided (player side = full kit, enemy = flat stat block), so the bout runs BOTH orientations and decides on aggregate remaining-HP fraction, cancelling the attacker-seat edge. To-hit stays faithful both ways (d20 + AttackBonus vs AC); damage folds into one enemy Attack (per-hit × swings + companion-proc expectation); DamageReduct ports over. Casters fight weapon-only in both orientations — accepted, PvP class balance is out of scope per the plan. Economics: both escrow the stake on accept (pool 2×stake); winner 70%, community pot rakes 30% (a sink); exact-HP-tie draw refunds both. Stake capped at level×€500. W/L reuses adventure_rival_records; shared 7-day pair cooldown. Terminal fate is serialised by an atomic claim (DELETE … WHERE id=? gated on RowsAffected==1, mirroring communityPotDebit): accept/decline/the expiry ticker all claim first, only the winner moves euros — no stake can be both resolved and refunded across the 24h boundary. issueDuel runs under advUserLock; accept re-checks the challenger and builds both fighters before debiting the challenged. Rides the 1-min eventTicker; combat golden byte-identical; suite green. Claude-Session: https://claude.ai/code/session_017mEwUmmS7aQTP2NQXj6rUa
This commit is contained in:
@@ -1610,6 +1610,20 @@ CREATE TABLE IF NOT EXISTS adventure_rival_challenges (
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_rival_challenges_user ON adventure_rival_challenges(challenged_id, expires_at);
|
||||
|
||||
-- Duels (N6/C2): player-initiated, staked, no-death combat bouts. Both stakes
|
||||
-- are escrowed while the row lives; expiry/decline refunds the challenger. W/L
|
||||
-- history reuses adventure_rival_records. No bootstrap — absent row == no duel.
|
||||
CREATE TABLE IF NOT EXISTS adventure_duel_challenges (
|
||||
challenge_id TEXT PRIMARY KEY,
|
||||
challenger_id TEXT NOT NULL,
|
||||
challenged_id TEXT NOT NULL,
|
||||
stake INTEGER NOT NULL,
|
||||
expires_at DATETIME NOT NULL,
|
||||
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_duel_challenges_user ON adventure_duel_challenges(challenged_id, expires_at);
|
||||
CREATE INDEX IF NOT EXISTS idx_duel_challenges_expiry ON adventure_duel_challenges(expires_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS community_pot (
|
||||
id INTEGER PRIMARY KEY DEFAULT 1,
|
||||
balance INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
Reference in New Issue
Block a user