跳到主要内容

PRD-010 抽奖与寻宝

文档编号:PRD-010
版本:v1.0
状态:已通过
适用端:服务端 / 客户端
关联模块:SessionServer/Lottery.cpp、BillServer、tbl/LotteryPool.xml

1. 背景与目标​

抽奖是主要的付费/消耗玩法,必须保证概率透明、结果可审计、保底可复现。当前存在十连结果与单抽概率不一致、保底计数丢失、客户端可预知结果等问题。本 PRD 统一种奖池、概率、保底、十连与公示。

2. 核心规则​

2.1 奖池​

类型消耗保底说明
普通寻宝金币无材料/消耗品
高级寻宝元宝30 抽必出稀有时装/坐骑碎片
限定寻宝限定道具90 抽必出大奖活动期限
  • 奖池分权重组,组内按权重随机。
  • 十连至少 1 个稀有(按配置保底)。
  • 限定奖池结束,保底次数按配置继承/清零。

2.2 概率与保底​

  • 单抽概率公示在抽奖界面,可展开查看完整列表。
  • 保底计数按角色 + 奖池记录,跨天不清空。
  • 出大奖后保底计数重置。
  • 十连按 10 次独立随机 + 保底修正,不是一次随机。

2.3 结果与发放​

  • 结果由服务端生成并落库,客户端只播放动画。
  • 物品直接入包,背包满转邮件。
  • 抽奖记录保留 180 天,可按角色/时间查询。
  • 抽奖动画不提前暴露结果,避免抓包/改包。

3. 服务端设计​

3.1 数据结构​

struct LotteryPool {
uint32_t pool_id;
std::vector<LotteryItem> items; // item_id, weight, rare_level
uint32_t pity_threshold;
uint32_t ten_pull_guarantee;
};

struct LotteryState {
uint64_t role_id;
uint32_t pool_id;
uint32_t pity_count;
uint32_t total_count;
};

3.2 协议​

方向协议说明
C→SCS_LotteryDraw单抽/十连
C→SCS_LotteryInfo奖池/概率/保底
S→CSC_LotteryResult结果列表(全部生成后下发)
S→CSC_LotteryInfo保底/剩余次数

3.3 抽奖流程​

CS_LotteryDraw(pool_id, count)
→ 校验活动时间/消耗/次数
→ 扣货币(事务)
→ 循环 count 次:按权重随机 → 更新保底
→ 十连保底修正
→ 生成结果列表 → 发放物品/邮件
→ 写 lottery_log(种子、结果、保底前后)
→ 返回 SC_LotteryResult

3.4 审计与风控​

  • 记录随机种子、奖池版本、概率表版本。
  • 同一 request_id 幂等,不重复扣费/发奖。
  • 异常高频抽奖触发风控,人工复核。
  • 概率表变更需版本号,历史记录可追溯。

4. 客户端设计​

  • 抽奖界面:奖池展示、单抽/十连按钮、消耗、保底进度。
  • 概率公示:可展开完整概率表,支持搜索。
  • 动画:翻牌/开箱,十连逐个展示,可跳过。
  • 结果汇总:稀有物品高亮,可分享到聊天。
  • 保底提示:剩余 N 抽必出。

5. 配置​

LotteryPool.xml:pool_id、item_id、weight、rare_level、pity_threshold、ten_pull_guarantee、start_time、end_time、cost_type、cost_value。

6. 边界与异常​

场景处理
货币不足拒绝,不扣费
背包满物品转邮件
十连中服务器断线结果已落库,重连补发/查询
保底计数异常以 DB 为准,修正内存
奖池结束瞬间请求以服务端时间校验,拒绝越界
重复请求幂等

7. 验收标准​

  • 单抽/十连概率、保底、稀有保底符合配置。
  • 结果与扣费事务一致,无扣费不发奖。
  • 断线/重复请求不重复扣费/发奖。
  • 概率公示与实际一致。
  • 抽奖日志可按 request_id 审计。