Compare commits

..

2 Commits

  1. 10
      assets/script/battle/ai/runtime/AiHeadlessBagHost.ts
  2. 59
      assets/script/battle/bag/BattleBagSession.ts
  3. 9
      assets/script/battle/view/CocosBagBoardView.ts
  4. 57
      assets/script/battle/view/TextListLandHost.ts
  5. 2
      assets/script/game/GameDataEnums.ts

@ -146,12 +146,10 @@ export class AiHeadlessBagHost {
const bag = this._bagSession;
if (!bag) return;
if (this._land.stateOf(slotIndex) !== TextListCellState.OpenNoDrag) return;
const born = this._land.promoteAround(slotIndex);
for (let i = 0; i < born.length; i++) {
bag.fillGateUnlockSlot(born[i]);
}
if (born.length > 0) {
aiOp(`AI 待开启推进 slot=${slotIndex} born=${born.join(',')}`);
const promoted = this._land.promoteAround(slotIndex);
bag.fillGateUnlockSlots(promoted.born, promoted.levelAdd);
if (promoted.born.length > 0) {
aiOp(`AI 待开启推进 slot=${slotIndex} born=${promoted.born.join(',')}`);
this._logBagSlots('gateUnlock');
}
}

@ -341,21 +341,68 @@ export class BattleBagSession {
/**
* 新的待开启格补一个五行随机字(不广播整包刷新)。
* 显示等级 = 抽取等级 + 本次解锁加值,不超过该五行上限。
* @param slotIndex 待开启槽下标
* @returns 是否写入成功
* @param levelAdd 本次解锁的等级加值(Const 39);0 不加
* @returns 随机出来的显示等级;未写入返回 null
*/
fillGateUnlockSlot(slotIndex: number): boolean {
fillGateUnlockSlot(slotIndex: number, levelAdd: number): number | null {
if (this.landStateOf?.(slotIndex) !== TextListCellState.OpenNoDrag) {
console.log('[BattleBagSession] 非待开启格不出字', slotIndex);
return false;
return null;
}
const roll = this._textPool.rollOneForLand(true);
if (roll == null) {
console.log('[BattleBagSession] 待开启格字池抽空', slotIndex);
return false;
return null;
}
this.merge.bag.setSlot(slotIndex, { weapon2Id: roll.weapon2Id, level: roll.level });
return true;
const level = this._gateLevel(roll.weapon2Id, roll.level, levelAdd);
this.merge.bag.setSlot(slotIndex, { weapon2Id: roll.weapon2Id, level });
return Math.floor(roll.level);
}
/**
* 给本次解锁新生的待开启格出字。
* @param slotIndices 新生槽
* @param levelAdd 本次解锁的等级加值
* @returns 各格随机等级,形如「槽:等级」
*/
fillGateUnlockSlots(slotIndices: readonly number[], levelAdd: number): string[] {
const rolls: string[] = [];
for (let i = 0; i < slotIndices.length; i++) {
const slot = slotIndices[i];
const rolled = this.fillGateUnlockSlot(slot, levelAdd);
rolls.push(rolled == null ? `${slot}:无` : `${slot}:${rolled}`);
}
return rolls;
}
/**
* 待开启出字等级:抽取等级加上解锁加值,不超过该五行上限。
* @param weapon2Id Text.id
* @param level 抽取显示等级
* @param levelAdd Const 39 加值
*/
private _gateLevel(weapon2Id: number, level: number, levelAdd: number): number {
const base = Math.floor(level);
const add = Math.floor(Number(levelAdd));
if (!Number.isFinite(add) || add < 0) {
console.log('[BattleBagSession] 解锁等级加值非法', weapon2Id, levelAdd);
return base;
}
if (add === 0) return base;
const w2Type = Math.floor(WeaponComposeConfigProvider.instance.getWeapon2Type(weapon2Id));
if (w2Type < 1 || w2Type > 5) {
console.log('[BattleBagSession] 解锁加值目标非五行', weapon2Id, w2Type);
return base;
}
const maxLv = WeaponComposeConfigProvider.instance.getElementMaxLevel(w2Type);
const sum = base + add;
if (sum > maxLv) {
console.log('[BattleBagSession] 解锁加值超过五行上限', weapon2Id, base, add, maxLv);
return maxLv;
}
return sum;
}
/** 两个字是否五行类型相同且显示等级相同 */

@ -4409,10 +4409,11 @@ export class CocosBagBoardView {
case MergeEventType.BagMerged:
// 待开启格吃到同类型同等级:自身变开启,四周未解锁格变待开启并各生成一个字
if (this._land.stateOf(event.slotIndex) === TextListCellState.OpenNoDrag) {
const born = this._land.promoteAround(event.slotIndex);
for (let i = 0; i < born.length; i++) {
this._bagSession?.fillGateUnlockSlot(born[i]);
}
const promoted = this._land.promoteAround(event.slotIndex);
const rolls = this._bagSession
? this._bagSession.fillGateUnlockSlots(promoted.born, promoted.levelAdd)
: [];
this._land.printUnlock(rolls);
this._fillMissingBagSlotGrids();
}
this._reportMergeUpgraded(event.weapon1Id, event.level);

@ -1,5 +1,6 @@
import { Node } from 'cc';
import { TableNames } from '../../game/ConfigTableData';
import { ConstNumType } from '../../game/GameDataEnums';
/** ui_textList 格子状态 */
export enum TextListCellState {
@ -25,10 +26,20 @@ const TEMP_NODE = 'temp';
/** 空装饰格下标(grid17):预制体底图保持关闭,逻辑不处理 */
const BLANK_INDEX = 17;
/** 一次待开启推进:新生待解锁格,以及本次要累加到这些格子数字上的等级 */
export interface TextListPromoteResult {
/** 新变成待开启、需要出字的格子 */
readonly born: readonly number[];
/** 本次解锁对应的显示等级加值(Const 39);无加值为 0 */
readonly levelAdd: number;
}
/**
* 按关卡 normalland / tolockland 管理 ui_textList 格子状态与拖入解锁。
* normalland 为开启且开局不放字;tolockland 为待开启(有字、不能拖、靠同类型同等级合成打开)。
* 待开启被合成后自身变为开启,上下左右的未解锁格变为待开启。其余为未解锁。
* 每局记录解锁次数,bind 时清零。第 1 次读 Const 39 的 index 0,依次类推;超出则用最后一项。
* 该加值累加到本次上下左右新待解锁格的数字等级上。
* grid17 是空装饰格,不刷底、不出字、不可拖放。名为 temp 的节点跳过。
* 格子上的字块是背包槽位数据(BattleBagSession),由视图按槽位记录生成标准 TextGrid;
* 拖拽预览、合成解锁走既有背包管线,本类只负责格子底图状态与解锁规则。
@ -44,6 +55,10 @@ export class TextListLandHost {
private readonly _open: number[] = [];
/** 待解锁下标(开启但不能拖) */
private readonly _gate: number[] = [];
/** 本局已解锁次数;bind / clear 清零。下次解锁用这个下标读 Const 39 */
private _unlockCount = 0;
/** 最近一次解锁的邻格等级加值,供本条解锁日志使用 */
private _lastLevelAdd = 0;
/**
* 读取关卡并刷新格子底图。
@ -111,6 +126,8 @@ export class TextListLandHost {
this._headless = false;
this._open.length = 0;
this._gate.length = 0;
this._unlockCount = 0;
this._lastLevelAdd = 0;
}
/**
@ -164,13 +181,13 @@ export class TextListLandHost {
/**
* 待开启格被同类型同等级合成:自身改为开启,上下左右的未解锁格改为待开启。
* 成功解锁计一次,并按本局次数取 Const 39 等级加值。
* @param gateIndex 待开启格下标
* @returns 新变成待开启、需要生成文字的格子
*/
promoteAround(gateIndex: number): number[] {
promoteAround(gateIndex: number): TextListPromoteResult {
if (this.isBlank(gateIndex) || this.stateOf(gateIndex) !== TextListCellState.OpenNoDrag) {
console.log('[TextListLand] 非待开启格', gateIndex);
return [];
return { born: [], levelAdd: 0 };
}
const gateAt = this._gate.indexOf(gateIndex);
if (gateAt >= 0) this._gate.splice(gateAt, 1);
@ -192,7 +209,39 @@ export class TextListLandHost {
}
born.push(index);
}
return born;
const levelAdd = this._unlockLevelAdd(this._unlockCount);
this._lastLevelAdd = levelAdd;
this._unlockCount++;
return { born, levelAdd };
}
/**
* 玩家本次解锁只打一条:解锁次数、上下左右累加等级、各新生格随机等级。AI 不打印。
* @param rolls 各格随机等级,形如「槽:等级」;没有新生格传空数组
*/
printUnlock(rolls: readonly string[]): void {
if (this._headless) return;
const randomText = rolls.length > 0 ? rolls.join(',') : '无';
console.log('[TextListLand] 玩家 解锁次数', this._unlockCount, '上下左右累加等级', this._lastLevelAdd, '随机等级', randomText);
}
/**
* Const 39:第 1 次解锁读 index 0,依次类推;下标超出数组则读最后一项。
* @param unlockIndex 本次解锁前已解锁次数
*/
private _unlockLevelAdd(unlockIndex: number): number {
const list = gg.data.table.getConstArray(ConstNumType.UnlockLandLevelAdd);
if (!list.length) {
console.log('[TextListLand] Const 解锁格子等级加值为空', ConstNumType.UnlockLandLevelAdd);
return 0;
}
const index = unlockIndex >= 0 && unlockIndex < list.length ? unlockIndex : list.length - 1;
const value = Math.floor(Number(list[index]));
if (!Number.isFinite(value) || value < 0) {
console.log('[TextListLand] 解锁格子等级加值非法', unlockIndex, list[index]);
return 0;
}
return value;
}
/**

@ -552,6 +552,8 @@ export enum ConstNumType {
WeekMapSun = 37,
/** 战斗中看视频加金币:para1 为每次奖励数量,次数=数组长度 */
BattleCoinAdRewards = 38,
/** 解锁格子次数等级加值 para1:第1次起按下标,越界读最后一项 */
UnlockLandLevelAdd = 39,
}
export enum TaskType {

Loading…
Cancel
Save