You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.4 KiB
8.4 KiB
方案-出怪逻辑实现
状态:出怪 + 到达扣营地血 + 营地血条 + 胜负已落地。审阅基线见 Cursor Plan v2。
1. 目标与范围
| 项 | 说明 |
|---|---|
| 对战 | PVE:玩家 vs AI(程序控制),双阵营地图对称出怪 |
| 进关 | 首页开始 → 按当天 Const 31~37 地图池随机 Level.id;GM「固定地图」可锁 id |
| 出怪 | Level.monster + Level.boss + Level.bosspro |
| 出怪口 | 玩家 port1,AI port2,同一套波次配置 |
| 队列 | 每波口内 顺序段:先小怪段,再 Boss 段(WaveSpawner segment 顺序) |
| 预制体 | Monster.icon → battleGameMonster/prefab/monster/{icon} |
| 本期不做 | 塔攻击 |
2. 配表
Level.monster(四列)
waveIndex,monsterId,count,spawnInterval
| 分隔 25 波。例:1,101,10,1.8
- 第 4 列:该波每只怪出现间隔(秒)
- Monster1 行 id = waveIndex(不是第 4 列)
Level.boss
waveIndex|monsterId,...
例:3|105,6|106 → 第 3 波排队出 105,第 6 波排队出 106(在小怪段之后)。
Level.bosspro(万分比)
- Boss 链未激活时,按
boss顺序在对应波次掷一次概率。 - 命中 → 该波出 Boss,链激活;之后所有 boss 配置波必出,不再掷概率。
- 未命中 → 该波不出 Boss,等下一条 boss 配置再掷。
实现:LevelWaveParser.resolveBossSpawns
掷点须无符号再 % 10000:JS 有符号 % 会得到负数,负数 < bosspro 恒成立,链会提前激活。
Monster / Monster1
- Monster:
icon为预制体名;speed寻路;hp参与血量公式;type:1 小怪 / 2 BOSS / 3 召唤。 - Monster1:行 =
waveIndex;列 =Rank.diffcult/ Level 难度组。 - 血量计算时机:出怪当下套公式
floor(Monster.hp × hp_multiple × port_hp × Monster1[波次] × 战力修正 × weapon_para),不以开局缓存为准。波次怪、营召唤、atk_type=8(含哮天犬)、万神幡 Boss 同一套;Monster1 行取当前波waveIndex。
表现皮肤(出怪口阵营)
| type | 预制体 | 己方口 port1(攻 AI) | 敌方口 port2(攻本机) |
|---|---|---|---|
| 1 小怪 | prefab/monster/{icon} |
Spine {icon}(如「猴」) |
Spine {icon}2(如「猴2」) |
| 2 Boss | prefab/monster/{icon} |
皮肤字1_1 |
皮肤字2_1 |
| 3 召唤 | prefab/monster/{icon} |
Spine {icon}(如「哮天犬」) |
Spine {icon}2(如「哮天犬2」) |
实现:MonsterDataManager.resolveBattleSpineSkin + CocosBattleMonsterPresenter._applyMonsterSpineSkin(优先 spawnPort===2 判敌方)。
营字强化出怪(Hero.id=5)
| 项 | 约定 |
|---|---|
| 触发 | 地图上每个激活的「营」独立计时、独立出怪 |
| 配表 | Skill.atk_para:怪物id,数量(如 -1,1);间隔用 Skill.cd(1~5 级 10/8/6/5/4 秒) |
-1 |
当前/最近一波小怪段 monsterId;准备期/Boss/波间仍按该 id 出小怪 |
| 出生 | 「攻击」0.5s 草字头打开后,怪出现在营格心上偏 30px(光的位置)、0.5 倍(相对落地)缩放,0.3s 放到 Monster.size×1.3;血条挂怪根上随身体放大;停 1s 再抛物线跳出 |
| 落点 | 同行最近可达进路格(出怪口格除外);与口同行或没有横向落点时,用普通怪出怪口跳跃落点(进路第一格)。出怪口不能作为跳跃目标 |
| 逻辑口 | UnitMetaComp.spawnPoint 仍记己方营 port1 / 敌方营 port2(皮肤、阵营、复活) |
| 表现 | 营预制体播「攻击」(开→持有→1.17s 合上)后回「待机」;无口特效、无冒怪 |
| 皮肤 | Monster.res[营等级-1];敌方阵营加后缀 2;预制体仍用 icon |
| 加成 | atk_buff1/2:type3 移速、type4 血量上限,均为 ×(1+万分比/10000)(如 1000=+10%)。上限变化后保持原血量比(100/70 → 120/84);出生时不播 怪物加血 |
| 实现 | YingCampSummonHost + WaveSpawner.spawnExtraEnemyAtCell + MovementSystem.assignPathVia;营不挂普攻 Ability |
Skill.atk_type=8 召唤
atk_para:怪物id,数量,间隔,出怪类型(1=施法处出现后跳入进路,2=自身周围出现)。非法第 4 段 warn,不猜默认。
| 出怪类型 | 逻辑 | 表现 |
|---|---|---|
| 1 施法处跳入 | spawnExtraEnemyAtCell:施法格出生,横向最近进路汇入(不含出怪口);与口同行或没有则用普通怪出怪口跳跃落点。逻辑口仍记己方 port1 / 敌方 port2 |
召唤哮天犬 播完后,在预兆点上偏 45px 出现,缩放 0→0.5,停 1s 再抛物线跳出,停顿+跳跃期间放到 1 倍 |
| 2 自身周围 | 施法者格及邻格生成,阵营与施法者一致 | unitSpawned.spawnPort=0,落在实体格,不出跳 |
杨戬主动(10176~10178)10001,1,0,1 → 施法处出 哮天犬(Monster.id=10001)再跳入进路。实现:SkillTableSummonExecutor。血量按召唤当时波次与波次怪同一公式,不锁开局第 1 波。
3. 代码结构
LevelWaveParser ← 解析 + bosspro + 生成 WaveDef(双口)
ChapterLevelBuilder ← 组装 LevelDef,wallHp 默认 3
WaveSpawner ← port.playerId,口内 segment 队列;spawnExtraEnemy / spawnExtraEnemyAtCell
YingCampSummonHost ← 营强化:营格水平进路出怪
SkillTableSummonExecutor ← atk_type=8(营地 / 自身周围)
UIBattleGame ← 地图 + 拓扑 + Presenter + startCombat
UIPanelHome ← pickRandomBattleLevelId 进关
数据流
UIPanelHome.click_btnStart→ 随机 LevelGameController.enterBattle→ 预载 →gg.battle.startChapterLevelBuilder.build→LevelWaveParser.toWaveDefsUIBattleGame→loadMap→applyMapTopologyToSession(..., 'pvp')CocosBattleMonsterPresenter.bind+startCombat→ 双口出怪 + 寻路表现
4. 默认参数
- 双方基地 HP:3(
DEFAULT_BATTLE_WALL_HP) - 中间波结波:
waveClearRequiresKillAll: false(出怪队列耗尽即下一波) - 最后一波:出完且场上进攻本机的怪清零 →
endBattle(true)→BattleRuntime.gameOver(true)弹BattleSuccess - 敌方营地
wallHp归零 → 胜利;己方归零 → 复活或失败 - 到达攻击点:
ReachGoalBaseDamageSystem对ownerId槽-1并 despawn(默认 3 血)
5. 营地血条与胜负
ReachGoalBaseDamageSystem(priority 55):reachedGoal && hasAttackGoal→PlayerSlot.damageWall(1)→lifecycle.despawn- 血条预制体
battleGame/prefab/营地血条:挂在地图根上,对齐该图spawnPoint_N(营地外观);己方在营下、敌方在营上,相对贴图 AABB 内收以免悬空;血量下格数=当前血,宽=60/maxHp,扣血渐隐回收;血格与根节点同样打 Sorting2D,避免被血量底盖成空槽 - spawnPoint_1 → 玩家 0(己营),spawnPoint_2 → 玩家 1(敌营)
- 胜负:
BattleRuntime听WallDamaged/BattleEnd;己方口怪不挡住最后一波清场胜利
6. 战斗预载(进关)
ResPkgBuilder 仅预载:
- 地图
mapLayerN、出怪口 - 本关怪物 + 状态特效 + 怪物血条
- 营地血条
营地血条 - battleHero 包全部英雄体(
prefab/hero/)+ 全部攻效(prefab/根目录;后续迁入prefab/skill/时在BattleHeroResCollector维护)
已移除老项目:芭蕉扇/围栏/机制包、局内飘字与受击特效 bulk 预载、按章节裁剪 HERO_ACTOR_RES。
7. 验收(出怪阶段)
- 首页多次进关按当天 Const 31~37 地图池随机 Level.id
- 玩家/AI 同时从出怪口 1/2 按表出怪
- Boss 概率链符合 bosspro 规则
- 同波小怪出完后排队出 Boss
- 怪物沿本阵营路径移动
- 皮肤来自 Monster.icon
- 双方营地血条贴营地:己方在下、敌方在上;进关即 3 格绿条、格宽=20
- 对方怪到达营地后消失且该营 -1 格(渐隐)
- 己方营地扣完失败(或复活);敌方扣完胜利
- 敌方波次怪全部击杀完胜利(己方口怪不挡住)