冒险系统

Adventure System Design

目标

让玩家派遣闲置的佣兵到 adventure_projects 中定义的项目中探险,获取奖励。

设计原则

  • 逻辑全部在 GDScript 中,读取数据库只做初始化
  • 所有结果(成功率、疲劳、奖励)都可导出为公式参数
  • 每日(游戏内时间)结算一次探险进度
  • UI 刷新延迟敏感,需要用信号驱动

数据模型(仅从数据库读取)

1. 佣兵属性(mercenaries 表)

字段 类型 备注
strength INT 影响成功率
vitality INT 影响疲劳/受伤容忍
agility INT 影响逃跑/额外奖励
fatigue INT 0-100,过高无法出战

2. 探险项目(adventure_projects 表)

字段 类型 备注
id INT 主键
name TEXT 项目名(如"荒芜矿洞")
base_difficulty INT 难度值
required_days INT 持续天数
max_team_size INT 最大人数限制
reward_table_id INT 奖励表外键

3. 队伍数据(仅存在于内存,可序列化保存)

class AdventureTeam:
    var team_id: int
    var project_id: int
    var member_ids: Array[int]
    var days_remaining: int
    var status: String  # "idle", "exploring", "returning", "complete"
    var daily_results: Array[Dictionary]

    func reset():
        member_ids = []
        days_remaining = 0
        status = "idle"
        daily_results = []

决策公式(GDScript 可调参数)

难度计算

func effective_difficulty(project: Project, team: AdventureTeam) -> float:
    var base = project.base_difficulty
    var team_power = sum([m.strength + m.vitality + m.agility for m in team.members])
    
    return base - team_power * POWER_COEFFICIENT

成功率

func success_rate(eff_diff: float) -> float:
    # 使用 atan 做平滑曲线
    var raw = 70 + atan(-eff_diff / 40.0) * 40
    return clamp(raw, MIN_SUCCESS_RATE, MAX_SUCCESS_RATE)

疲劳增加

func fatigue_gain(result: String, base_difficulty: int) -> int:
    match result:
        "crit_success":
            return randi_range(5, 10)
        "success":
            return randi_range(10, 20)
        "failure":
            return randi_range(25, 40)
        "crit_failure":
            return randi_range(50, 80)
    return 20

受伤判定

func take_damage(member, result: String) -> int:
    if result in ["failure", "crit_failure"]:
        var damage = randi_range(5, 20 + (20 if result == "crit_failure" else 0))
        damage = max(0, damage - member.vitality / 10)
        return damage
    return 0

流程(以三天项目为例)

Day 1

  1. 玩家选择项目,选择佣兵
  2. 创建 AdventureTeam,设置 days_remaining = 3status = "exploring"
  3. 发出 team_dispatched 信号

Day 2

  1. GameTimeManager 触发 day_passed
  2. AdventureManager 调用 tick_all_teams()
  3. 对每个 team:
    • 计算成功率
    • 掷骰判定本日结果
    • 累加疲劳、扣血、记录结果
    • days_remaining -= 1

Day 3

  1. 同上
  2. 如果 days_remaining == 0:
    • 计算总奖励(基于 daily_results 综合)
    • 设置 status = "complete"
    • 发出 adventure_complete 信号

可配置常量

const POWER_COEFFICIENT = 0.5
const MIN_SUCCESS_RATE = 5
const MAX_SUCCESS_RATE = 95
const FATIGUE_THRESHOLD = 80  # 超过这个值无法参加探险

奖励计算

基于每日结果综合计算:

  • 大成功天数 × 2 倍奖励系数
  • 成功天数 × 1 倍奖励系数
  • 失败天数 × 0.3 倍奖励系数
  • 大失败天数 × 0 倍奖励系数