# 沙盒地图 ## Actor分类 - logic actor: 驱动整个地图的业务逻辑,管理 map table 对象的更新 - aoi actor: 管理地图 AOI,根据对象类型分层 - pathfind actor: 地图寻路处理,构造多对象并发处理寻路 - pusher actor: 推送地图数据给客户端 - player actor: 处理玩家在地图上的业务数据与逻辑请求 - league actor: 处理联盟在地图上的业务数据与逻辑请求 - ops actor: 对外 API 接口 ## 服务启动数据加载思路 - 创建各层 actor 前把所有的 map table 加载到内存 - 各层 actor 通过 map table 构造自己的副本数据 - map table 只在 logic actor 管理,数据变更时通知其它各层 actor 更新数据 ## AOI分层思路 - 把不同类型的对象分为多层管理,它们独立运行各自actor上,每层有专属的AOI同步 - 当玩家登录游戏时,传入玩家的坐标到各层,并进行AOI的enter()操作 - 当玩家拖动屏幕时,传入玩家的坐标到各层,并进行AOI的move()操作 - 当玩家退出下线时,传入玩家的坐标到各层,并进行AOI的leave()操作 - 行军层用于军队的寻路,当玩家坐标在当前灯塔范围内时进行AOI对象同步 ## 地图对象分类 - 地图建筑:城池,关卡,码头 - 玩家建筑:联盟驻地,主城,其它玩家建筑 - 资源点 - 怪物 - 行军对象 ## A星寻路思路 - 大地图分区域,区域之间只有少数连接点 - 分层寻路 - 区域之间寻路:找到区域之间的连接点 - 区域内部寻路:起点 -> 连接点A, 连接点A -> 连接点B, 连接点B -> ... 连接点N, 连接点N -> 终点 - 不规则区域表示法:使用多边则,保存多边形的所有顶点坐标 ## 行军对象状态梳理 - 0 - 空闲状态 - 1 - 停留状态 - 2 - 撤退状态 - 3 - 占领状态 - 4 - 采集状态 - 5 - 驻守状态 - 6 - 攻城状态 - 7 - 调动状态 - 8 - 集结状态 - 9 - 征兵状态 - 10 - 到达状态 - 100 - 行军状态 - 101 - 调动行军状态 - 102 - 集结行军状态 - 103 - 运输回城状态 - 200 - 战斗状态 - 201 - 战斗等待状态 ## 行军碰撞业务梳理 ### 行军碰撞列表 1. 攻击列表 1. 进攻列表 - 进入地块的部队在与 `防守队列` 的 `敌对部队` 相交时进入 (PVP) 2. 攻占列表 - 通过 `行军-攻占` 指令进入, 会参与子地块的碰撞 (PVP) 3. 掠夺列表 4. 攻城列表 2. 防守列表 1. 驻守列表 - 通过 `行军-驻守` 指令进入, 会参与子地块的碰撞 2. 城防部队 - 大型城池特有的配置 (PVE) 3. 占领列表 - 通过 `行军-占领` 指令进入 (PVP) 4. 攻城列表 - 通过 `行军-攻城` 指令进入 (PVP) 5. 行军列表 - 通过 `行军` 指令在到达目标点之前经过的地块上 (PVP) 6. 停留列表 - 通过 `行军` 指令到达目标点之后停在地块上 (PVP) 7. 调动列表 - 通过 `行军-调动` 指令进入 (PVP) 8. 采集列表 - 通过 `行军-采集` 或者 `行军-占领` 完成后进入,只有资源点才有,并且只有单个部队的列表 (PVP) 9. 城防守军 - 建筑耐久守军通用配置,`攻城` 指令时拆除耐久 (PVE) 10. 地块守军 - 地图对象通用配置, `行军-占领` 攻打之后进入 `占领列表` (PVE) ### 行军碰撞顺序 1. 以进入地块的行军对象为参照,部队进入 `进攻列表` ,依次碰撞本地块上的 `驻守`、`占领`、`攻城`、`行军`、`停留`、`调动`、`征兵`、`采集` 列表(驻守方为防守方) 2. 当 `驻守列表` 有范围时,会扫描周围地块,不会碰撞进入 `进攻列表` 的队伍,只有 `进攻列表` 的队伍进入 `防守列表` 后,`驻守列表` 才会碰撞(驻守方为进攻方) 3. 当攻城或者掠夺的时候(打玩家建筑或者主城),扫描主城军列表和调动列表 ### 行军碰撞流程 1. 行军碰撞检测 1. 部队发起 `行军` 指令进行移动 2. 每进入一个地块,先检查 `进攻队列` 中是否有 `同盟部队`,如果有,则进入 `进攻队列`,并设置 `进攻状态` 3. 否则,依次检查 PVP 防守队列中是否有 `敌对部队`,如果有,则进入 `进攻队列` 4. 如果 `进攻队列` 不为空,且 `防守队列` 有友军部队,则进入 `防守队列` 5. 当 `进攻队列` 为空,且不与 `防过队列` 碰撞时,进入 `行军队列`,或者执行行军到达逻辑 2. 行军碰撞过程 1. 每个 ticker 分别从 `攻击队列` 和 `防守队列` 中弹出 5 个部队,分别构建战斗保存到提交队列,并发送验证 2. 战斗返回之后,败方加入 `撤退队列` 走 `撤退` 逻辑,胜方 Push 回原来的队列 3. 如果 `进攻队列` 为空,则碰撞过程结束 4. 如果 `进攻队列` 不为空,但是 `防守队列` 为空,检查 `进攻队列`,把同盟部队加入 `防守队列`,其它继续留在 `进攻队列`, 再次交战 3. 行军碰撞细节 1. 只要进入 `进攻队列` 就设置 `战斗(等待?)状态`, 不可操作 2. `防守队列` 中的部队可以进行各自的逻辑 ## 城战玩法梳理 ### 攻城模式参考 - 三谋:城池四面城墙单独配置守军、耐久,每面城墙对应一座攻城大营。占领大营可宣战,部队集结后自动列队,然后加入攻城队列。 - 三战:城池自成一体,守军与耐久共享,攻城开启后,所有部队选择攻城次数后,行军到城池中心点加入攻城队列。 ### 攻城设计 - 宣战模式参考三谋,攻城模式参考三战 - 宣战阶段:城池四面配置攻城大营,占领可宣战,部队集结后自动列队。 - 攻城阶段:所有部队行军到城墙位置,加入先城池中心地块的行军对象发生碰撞,再加入攻城队列(这个过程所有攻城联盟共享)。 ### 技术设计 #### 配置 - 城池与攻城大营之间的关联关系 - 城池每一面城墙可攻打的坐标点 - 攻城大营的主力部队与拆迁部队的坐标点,与城墙攻打点的关联 - 主力部队与拆迁部队的出兵时间 #### 逻辑 1. 攻打攻城大营 1. 点击 `攻城大营` 发送 `攻城` 指令 2. 部队行军到 `攻城大营` 墙上 (非 `攻城` 指令不可行军,寻路要特殊处理,方法 `TODO`),先碰撞再加入 `攻城队列` 3. 走 `攻城` 和 `攻城结束` 逻辑(会根据建筑类型走不同的逻辑) 4. 攻城大营攻城结束的逻辑为:修改攻城大营所属为我方联盟ID 2. 攻城大营建造 1. 占领 `攻城大营` 后才能修建,需要做权限判断,和数量限制 2. `攻城大营` 修建完成时,做法一是替换 `攻城大营` 为另一个不同配置的 `攻城大营`, 需要在 AOI 做一次 `enter` 和 `leave`; 做法二是用同一个 `攻城大营` 配置,只记录一个 `是否修建` 的状态,只在 AOI 做一个 `update`, 但是需要配置两套属性 3. 宣战 1. 点击 `城池` 选择 `宣战` 指令,并选择 `宣战时间`, 此时需要判断是否满足条件 2. 把 `宣战` 的联盟和状态记录到 `城池` 或者 `攻城大营` 上? 3. 设置 `宣战阶段` 并开始 ticker 检查,如果时间到了,进入 `攻城阶段`,开始 `出兵` 和 `攻城` 逻辑 4. 任务阶段只要 `攻城大营` 被攻破,进入 `攻城失败` 流程 4. 集结 1. 点击 `攻城大营` 发送 `集结` 指令,部队通过 `行军-集结` 指令进入 `行军` 状态,并设置子状态为 `集结`;或者分为两个一级状态 `集结中` 和 `集结` 2. 行军到 `攻城大营` 后,设置为 `集结` 状态,并加入地块的 `集结队列`, 同时把集结点加入回城点选项并设置为默认回城点 5. 出兵 1. `宣战阶段` 结束,进入 `攻城阶段`, 未 `集结` 的部队可以手动请求 `攻城` 指令 2. 每个 ticker 选择获取地块上的 `集结队列` 并弹出一批主力部队,行军到前排点; 3. 主力部队出完后,每个 ticker 选择获取地块上的 `集结队列` 并弹出一批拆迁部队,行军到后排点; 4. 经过一段时间后,每个 ticker 把前排主力行军到城墙点进入 `攻城队列`,进行 `攻城` 逻辑 5. 每次驻城部队的战斗返回,检查驻城部队数量是否为 0,每个 ticker 把后排拆迁行军到城墙点进入 `攻城队列`,进行 `攻城` 逻辑 6. 以上出兵逻辑只会做一次,在 `攻城大营` 记录状态 7. 如果 `主力部队` 和 `拆迁部队` 数量极度不均衡,甚至某一个为空,策划分配逻辑感觉有点问题(如何均匀排列,主力为0拆迁不动) 6. 攻城 1. 以城池中心坐标的地块作为锚点,遍历所有子地块,分别处理地块的逻辑 2. 碰撞的驻守队列会额外检查父地块 3. 如果碰撞完成了,就会构造 `驻城部队` 的战斗,战斗验证成功 `驻城部队` 减一,并且进攻方增加 2 秒 CD 4. `驻地部队` 为空时,先增加 3 分钟 CD(需要状态记录),再构建 `守军部队` 战斗,战斗验证成功扣除耐久,并设置 3 分钟 CD 5. 过程中记录部队攻城数据 6. 城池耐久和驻城部队受损,触发 `回复`,每过 30 分钟恢复驻城部队数量和耐久(走通用建筑回复逻辑) 7. 攻城成功 1. 耐久为 0 时,攻城成功,把城池所属设置最后一击的玩家联盟ID 2. 如果首次攻占的,发奖励,记排行榜 3. 所有部队退回集结点 4. 如果城池有守军,退回各自的主城 5. 如果有其它攻城同盟,执行 `攻城失败` 逻辑 8. 攻城失败 1. `攻城` 过程中,检查是否超时,超时则失败 2. 部队回到集结点 3. 等待 CD 后可以再次 `宣战` 4. 不会影响其它联盟的 `攻城` 逻辑