任务系统分为世界侧与玩家侧2个部分, 世界侧提供完整的多人游戏同步(跟随世界存档), 玩家提供可重复的个人体验(跟随玩家存档). 当前仅世界侧.

世界任务系统旨在通过以下几项核心功能提供结构化的静态体验.

(Types) 所有世界任务分为 3 类:主线剧情、支线剧情和传说任务. 主线任务是游戏的核心, 旨在引导玩家完成主线故事. 支线任务是可选的, 提供额外的内容和奖励. 传说任务是支线任务的一个特殊子集, 以独特的内容和专属奖励为特色, 使其有别于普通的支线任务.

(Features-Main) 在玩家达到特定的里程碑之前, 任务是锁定的, 但解锁条件是可见的. 某些任务只有在满足特定条件后才会显示. 部分任务具有时间限制, 一旦时限到期, 任务将变得不可用, 直到玩家选择重新开始.

(UI) 任务界面由两部分组成:任务列表和任务详情. 在任务列表中显示所有任务, 每个任务由一张卡片代表. 卡片显示任务名称、类型、状态和剩余时间(如果适用). 玩家可以点击卡片查看任务详情, 其中包括完整的描述、目标、奖励和其他信息. 如果任务是不可见的, 卡片会变灰并仅显示“???”作为名称, 且详情页面保持空白. 界面外观是可选的, 默认风格为大理石板技术风, 随着游戏进程的推进, 将解锁新的主题.

(Features-Sub) 每个任务都是由多个部分组成的组合, 包括任务名称、类型、状态、描述、目标、奖励和其他信息. 任务状态可以是以下之一:已锁定、可接取、已完成或已失败. 目标是玩家为了完成任务必须完成的任务. 奖励在任务完成时发放, 包括物品、世界状态变更或其他收益.

(Features-Objectives) 目标可以有多种类型, 包括但不限于:击杀 NPC、收集物品、消耗物品、到达特定地点、移动一定距离、与 NPC 对话、将物品交给 NPC 以及完成入侵. 系统还提供两种特殊结构:并行目标和分支目标. 一个目标也可以给予玩家完成后续目标所需的奖励, 但这些奖励可能会在目标完成后被移除.

世界侧任务系统

世界侧任务系统目标提供结构化的静态的任务流程

任务构成

  • 基础信息: 名称、描述、类型
  • 功能信息: 状态、目标、奖励

任务机制

  • 锁定与可见性: 任务在达到特定条件处于锁定状态, 详情内容不可见. 大部分任务解锁条件可见;隐藏任务解锁条件不可见, 仅显示"???"作为任务名
  • 限时任务: 部分任务有时间限制, 可无条件重试

任务类型

总共包含3个类型, 仅用作分类显示, 不影响游玩体验:

  • 主线任务: 游戏核心, 引导玩家推进主线剧情
  • 支线任务: 可选内容, 提供额外的剧情内容和奖励
  • 传说任务: 内容更为丰富的支线任务, 独特内容和高级奖励

任务状态 & 生命周期

锁定

大部分任务在初始状态下处于锁定状态, 需要达成特定条件后才能解锁 解锁后不会再次锁定

进行中

任务解锁后自动接取, 进入此状态

已完成

任务完成后进入此状态

失败

标记任务因为某种原因失败, 可无条件重试返回进行中状态 可能的原因有:任务计时结束、目标计时结束、任务限制等

任务目标

目标类型

  • 击杀NPC:击败一定数量的指定NPC, 多人游戏下计算所有玩家的击杀(未实现在特定条件下击杀, 因BOSS可能需要全伤害计算)
  • 收集物品: 在背包中拥有一定数量的指定物品, 多人游戏下计算所有玩家的仓库
  • 消耗物品: 消耗一定数量的指定物品, 多人游戏下由全体玩家贡献进度. 由客户端收集上传
  • 到达地点: 检测位置、环境、地层
  • 行走距离: 可附带条件
  • 对话NPC: 检测玩家对话NPC
  • 提交物品: 同上, 对话后自动提交. 由客户端收集上传
  • 完成事件: 略. 等待事件系统实现同步后启用

特殊结构

  • 分支目标: 完成其中一项后自动进入该分支
  • 并行目标: 完成任意/全部后可到达后继目标

注:特殊结构之间不可互相包含

目标限时

同任务限时, 可单独重试该目标

目标内奖励

完成某些目标可能获得奖励, 作为后续目标的前置条件. 这些奖励可能在完成目标后被移除, 类似天国魔力

任务奖励

完成任务后向全体玩家发放, 包含物品、世界状态变化等

网络同步

世界侧任务系统采用服务器权威模型, 核心逻辑均在主世界服务器完成, 部分信息由子世界服务器/客户端采集并上传, 在服务器端验证后生效. 由于子世界玩家的客户端无法直接连接至主世界服务器, 因此需要通过子世界服务器转发.

网络分层 (Send / Route)

任务系统通过 PacketResolver 统一管理网络数据包, 分为两层:

  • Send (原版 TML):
    仅在当前世界内广播, 不跨世界.
  • Route (跨世界):
    结合 TML 与 SubworldLibrary, 在主世界服务器、主世界客户端、子世界服务器、子世界客户端之间进行跨世界传输.
    Route 是任务系统跨世界同步的基础.

路由目标 (RouteDestination)

在 Route 层, 任务系统使用两种路由目标:

  • MainServer (上行)
    • 所有非主世界服务器 (子服务器、主客户端、子客户端) 均使用此路由.
    • 子世界服务器只负责识别并直接转发, 不执行任务逻辑.
    • 所有包最终到达主世界服务器, 由其验证并生效.
  • AllDownstream (下行)
    • 仅主世界服务器可发送.
    • 广播至所有主客户端与子世界服务器, 子世界服务器执行后再转发给其子客户端.

同步方式

  1. 全任务同步: 含所有任务的信息. 由 ModSystem.NetSend()ModSystem.NetReceive 触发. 与 Terraria 本体相同, 在特定时间点全量同步世界的信息.
    • 主世界服务器使用 AllDownstream 广播完整任务数据.
  2. 单任务同步: 含单个任务的信息. 一般由 数据上传 / 状态改变触发, 对所有客户端进行一次单任务同步.
    • 主世界服务器使用 AllDownstream 同步单个任务的最新状态.
  3. 数据上传: 含单个玩家的任务进度贡献量, 比如行走的距离, 消耗的物品等. 在客户端与子服务器上进行, 通过任务目标的 OnMPSync 方法, 发送数据到主服务器 (发送频率受限).
    • 客户端与子服务器均使用 MainServer 路由上行上传, 由主世界服务器验证后生效.

发送主体

  1. 主世界服务器 (广播至所有客户端和所有子世界及其客户端):
    主世界触发世界同步时 (全任务同步), 任务生命周期改变 (单任务同步), 差量数据上传后 (单任务同步).
    • 主世界服务器是唯一可使用 AllDownstream 的节点.
  2. 子世界服务器 (直接发送至主世界):
    上传子世界本地收集的玩家进度 (客户端收集内容除外).
    • 始终使用 MainServer 路由, 仅转发, 不执行任务逻辑.
  3. 客户端 (由子世界服务器转发至主世界):
    上传客户端本地收集的玩家进度、请求重试失败任务、请求发放奖励.
    • 始终使用 MainServer 路由; 若处于子世界, 则由子世界服务器转发.

任务提示

状态切换广播

  1. 正常更新: 需要
  2. 加载世界(Load/SaveData): 不需要
  3. 加载世界(NetSend/Receive): 不需要
  4. 强制同步(NetSend/Receive): 需要 (可以更换文本)

备注:

  1. 书写在State属性的get中, 会失去灵活性
  2. 在多人游戏下, 客户端调用NetSend/Receive加载世界时, Main.NewText会无效, 因此默认情况下不需要广播. 如果需要广播, 可以在ModPlayer.OnEnterWorld中广播

任务UI

监听任务系统更新, 刷新UI