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.

814 lines
34 KiB

3 weeks ago
import { Button, color } from 'cc';
import { Label } from 'cc';
import { EventTouch } from 'cc';
import { instantiate } from 'cc';
import { EditBox } from 'cc';
import { _decorator, Component, Node } from 'cc';
import { isValid } from 'cc';
import { GBundle, GPath, UIID } from './ConfigRes';
import { UILayer } from '../../mx/module/ui/UIManager';
import { ItemNumType, OtherDataType, StatisticsType } from './GameData';
import { GEvent } from '../../mx/module/event/GEvent';
import { TableNames } from './ConfigTableData';
import MTools from '../../mx/tools/MTools';
import { sdkConfig } from '../sdk/sdkConfig';
import { parseGmBagWeapon2Filter } from '../battle/bag/BagWeaponPool';
import { parseGmAiBattleBuffIds } from '../battle/debug/GmBattlePreset';
import { BattleRuntime } from '../battle/runtime/BattleRuntime';
import { DailyShopDataManager } from '../manager/DailyShopDataManager';
import { HeadIconManager } from '../manager/HeadIconManager';
import { DailyShopKind } from '../manager/DailyShopTypes';
import { EmolumentDataManager } from '../manager/EmolumentDataManager';
import { RankBoardManager } from '../manager/RankBoardManager';
import { RankDataManager } from '../manager/RankDataManager';
const { ccclass, property } = _decorator;
/** GM「设置排行星级&胜场」:PopEmolument 待领星级 */
const GM_EMOLUMENT_SNAP_STARS = 50;
/** GM「设置排行星级&胜场」:PopEmolument 待领胜场 */
const GM_EMOLUMENT_SNAP_WINS = 50;
@ccclass('GM')
export class GM extends Component {
static Instance: GM;
static ShowGM = false;
static show() {
this.ShowGM = !this.ShowGM;
if (GM.Instance && isValid(GM.Instance.node)) {
GM.Instance.node.active = this.ShowGM;
return;
}
if (this.ShowGM) {
let res = gg.res.getNode(GPath.UIPrefab, "gm", GBundle.First);
gg.ui.showNode(res, UILayer.DeBug);
GM.Instance = res.getComponent(GM);
}
}
@property(EditBox)
eb_prama: EditBox;
@property(Node)
ui_quickBtns: Node;
@property(Node)
ui_paramBtns: Node;
@property(Node)
ui_help: Node;
@property(Label)
lb_help: Label;
content: Node;
btnGM: Node;
btnClear: Button;
btnClose: Button;
btnHelp: Button;
protected onLoad(): void {
this.content = this.node.find("content");
this.btnGM = this.node.find("btnGM");
this.btnClear = this.content.find("ui_content/ui_head/btnClear").getComponent(Button);
this.btnClose = this.content.find("ui_content/ui_head/btnClose").getComponent(Button);
this.btnHelp = this.content.find("ui_content/ui_head/btnHelp").getComponent(Button);
}
protected onEnable(): void {
this.btnGM.on(Button.EventType.CLICK, this.onOpenGM, this);
this.btnClear.node.on(Button.EventType.CLICK, this.onClear, this);
this.btnClose.node.on(Button.EventType.CLICK, this.onClose, this);
this.btnHelp.node.on(Button.EventType.CLICK, this.onHelp, this);
this.ui_help.on(Button.EventType.CLICK, this.onHelpUI, this);
this.btnGM.active = false;
this.onOpenGM();
this.initBtnEvents();
this.lb_help.string = this._helpStr;
this.ui_help.active = false;
}
protected onDisable(): void {
this.btnGM.off(Button.EventType.CLICK, this.onOpenGM, this);
this.btnClear.node.off(Button.EventType.CLICK, this.onClear, this);
this.btnClose.node.off(Button.EventType.CLICK, this.onClose, this);
this.btnHelp.node.off(Button.EventType.CLICK, this.onHelp, this);
this.ui_help.off(Button.EventType.CLICK, this.onHelpUI, this);
this.ui_quickBtns.children.map(x => x.off(Node.EventType.TOUCH_END, this.onQuickBtnClick, this));
this.ui_paramBtns.children.map(x => x.off(Node.EventType.TOUCH_END, this.onParamBtnClick, this));
}
initBtnEvents() {
for (let i = 0; i < this.quickBtns.length; i++) {
let btn: Node = null;
if (i < this.ui_quickBtns.children.length)
btn = this.ui_quickBtns.children[i];
else
btn = instantiate(this.ui_quickBtns.children[0]);
btn.active = true;
btn.name = this.quickBtns[i];
btn.setParent(this.ui_quickBtns);
btn.getComponentInChildren(Label).string = this.quickBtns[i];
btn.getComponentInChildren(Label).outlineColor = color().fromHEX(this.colors[i % this.colors.length]);
btn.on(Node.EventType.TOUCH_END, this.onQuickBtnClick, this);
}
for (let i = 0; i < this.paramBtns.length; i++) {
let btn = null;
if (i < this.ui_paramBtns.children.length)
btn = this.ui_paramBtns.children[i];
else
btn = instantiate(this.ui_paramBtns.children[0]);
btn.active = true;
let [name, desc] = this.paramBtns[i].split("|");
btn.name = name;
btn.setParent(this.ui_paramBtns);
btn.getChildByName("lb1").getComponent(Label).string = name;
btn.getChildByName("lb1").getComponent(Label).outlineColor = color().fromHEX(this.colors[i % this.colors.length]);
btn.getChildByName("lb2").getComponent(Label).string = "参数:" + desc;
btn.on(Node.EventType.TOUCH_END, this.onParamBtnClick, this);
}
this.scheduleOnce(() => {
this.refreshparamBtns()
}, 1)
}
refreshparamBtns() {
for (let i = 0; i < this.ui_paramBtns.children.length; i++) {
const btn = this.ui_paramBtns.children[i];
const lb2 = btn.getChildByName('lb2')?.getComponent(Label);
if (!lb2) continue;
switch (btn.name) {
case '设置金钱':
lb2.string = `参数:${gg.data.getItemNum(ItemNumType.money)}`;
break;
case '设置体力':
lb2.string = `参数:${gg.data.getItemNum(ItemNumType.vigour)}`;
break;
case '设置钻石':
lb2.string = `参数:${gg.data.getItemNum(ItemNumType.diamond)}`;
break;
case '设置关卡解锁':
lb2.string = `参数:${gg.data.doc.rankId}`;
break;
case '设置星数':
lb2.string = `参数:${RankDataManager.getPlayerRankStars()}`;
break;
case '设置玩家局内血量': {
const runtime = gg.battle.match;
const inBattleHp = runtime instanceof BattleRuntime ? runtime.WallMaxHp : 0;
const preset = gg.game.playerHp;
lb2.string = preset > 0
? `参数:${preset}(下局)${inBattleHp > 0 ? ` 当前${inBattleHp}` : ''}`
: `参数:0(默认)${inBattleHp > 0 ? ` 当前${inBattleHp}` : ''}`;
break;
}
case '设置玩家等级':
lb2.string = `参数:${gg.data.getPlayerLevel()}`;
break;
case '设置通关怪物数量': {
const n = sdkConfig.isDebugFastWinMonsterNum;
lb2.string = n > 0 ? `参数:${n}` : '参数:0(关闭)';
break;
}
case '指定背包文字': {
const cur = gg.game.gmBagWeapon2Ids;
lb2.string = cur?.length ? `参数:${cur.join(',')}` : '参数:未指定(正常随机)';
break;
}
case '设置AI主动BUFF': {
const cur = gg.game.gmAiActiveBuffIds;
lb2.string = cur?.length ? `参数:${cur.join(',')}(常驻)` : '参数:未指定(每局随机)';
break;
}
case '设置AI被动BUFF': {
const cur = gg.game.gmAiPassiveBuffIds;
lb2.string = cur?.length ? `参数:${cur.join(',')}(常驻)` : '参数:未指定(每局随机)';
break;
}
case '固定地图': {
const id = Math.floor(Number(gg.game.gmMapId) || 0);
lb2.string = this._formatFixedLevelParam(id);
break;
}
case '设置主动BUFF': {
const slotId = DailyShopDataManager.getActiveSlotIds()[0] ?? 0;
const parsed = slotId > 0 ? DailyShopDataManager.getParsed(slotId) : null;
lb2.string = parsed
? `参数:${parsed.id}(${parsed.name})`
: (slotId > 0 ? `参数:${slotId}` : '参数:空');
break;
}
case '设置被动BUFF': {
const slotId = DailyShopDataManager.getPassiveSlotIds()[0] ?? 0;
const parsed = slotId > 0 ? DailyShopDataManager.getParsed(slotId) : null;
lb2.string = parsed
? `参数:${parsed.id}(${parsed.name})`
: (slotId > 0 ? `参数:${slotId}` : '参数:空');
break;
}
}
}
}
onClear() {
gg.ui.closeAllPanel();
GEvent.Ins.emit(GEvent.GameRestart);
gg.game.reset('GM重置');
}
onOpenGM() {
this.content.active = true;
this.btnGM.active = false;
}
onHelp() {
this.ui_help.active = !this.ui_help.active;
}
onHelpUI() {
this.ui_help.active = false;
}
onClose() {
GM.show();
// this.content.active = false;
// this.btnGM.active = true;
}
colors = ["#21F018", "#05DBF8", "#EF9EFF", "#FFFF00", "#FFE09E", "#E8FF9E", "#47CA14", "#3CDCF1", "#E0FF00", "#20FA80"];
quickBtns = [
'清除副本次数难度全开',
'今日首次登录(每日重置)',
'复制存档',
'一键获取所有武器',
'一键添加所有宝石',
3 weeks ago
'设置武器等级',
'设置武器和技能',
'清除指定背包文字',
'快速胜利1怪',
'关闭快速胜利',
'关闭广告',
'显示广告',
'重置每日商店or抽奖',
'重置每日商店BUFF',
'打开每日商店无限次数',
'关闭每日商店无限次数',
'清除AI主动BUFF',
'清除AI被动BUFF',
'清除固定地图',
'测试七十二变→妙手神偷',
'关闭七十二变固定',
'设置排行星级&胜场',
'打开内购',
'关闭内购',
'开启己方营地不掉血',
'关闭己方营地不掉血',
'开启敌方营地不掉血',
'关闭敌方营地不掉血',
];
paramBtns = [
'设置道具数量|道具ID 数量(空格分隔)',
'设置武器数量|武器ID 数量(空格分隔)',
'设置主动BUFF|主动buffID(只设置第一个)',
'设置被动BUFF|被动buffID(只设置第一个)',
'设置金钱|金币数量',
'设置体力|体力数量',
'设置钻石|钻石数量',
'设置关卡解锁|段位id',
'设置星数|总星数(最低1)',
'设置玩家局内血量|城墙血量(下局生效,局内同步)',
'设置玩家等级|主角等级',
'设置玩家存档|JSON存档字符串',
'设置通关怪物数量|击杀N怪后通关,0关闭',
'指定背包文字|weapon2Id或名称,逗号分隔',
'设置AI主动BUFF|Battlebuff.id,逗号分隔(下局生效)',
'设置AI被动BUFF|Battlebuff.id,逗号分隔(下局生效)',
'固定地图|Level.id(关卡表),0关闭',
];
onQuickBtnClick(event: EventTouch) {
switch (event.target.name) {
case '关闭广告':
gg.sdk.showAd = false;
gg.ui.showToast('已关闭广告');
GM.show();
break;
case '显示广告':
gg.sdk.showAd = true;
gg.ui.showToast('已开启广告');
GM.show();
break;
case '打开内购':
sdkConfig.isIAPVersion = true;
gg.ui.showToast('已打开内购版本');
GM.show();
break;
case '关闭内购':
sdkConfig.isIAPVersion = false;
gg.ui.showToast('已关闭内购版本');
GM.show();
break;
case '清除副本次数难度全开':
gg.data.setStatistics(StatisticsType.BoxChallengeCount, 0);
gg.data.setStatistics(StatisticsType.gachaChallengeModeCount, 0);
gg.data.setStatistics(StatisticsType.InfiniteChallengeCount, 0);
gg.data.setStatistics(StatisticsType.PropChallengeCount, 0);
gg.data.setStatistics(StatisticsType.WeaponChallengeCount, 0);
gg.data.setStatistics(StatisticsType.BoxModelLevel, 5);
gg.data.setStatistics(StatisticsType.InfiniteModelLevel, 5);
gg.data.setStatistics(StatisticsType.PropModelLevel, 5);
gg.data.setStatistics(StatisticsType.WeaponModelLevel, 5);
gg.data.setStatistics(StatisticsType.GachaChallengeModeLevel, 5);
gg.data.setStatistics(StatisticsType.BossChallengeCount, 0);
gg.data.resetReplicaEnterAndSweepCountsToday();
gg.data.saveToServer();
gg.ui.showToast('副本次数已清零,难度已全开');
GM.show();
break;
case '今日首次登录(每日重置)':
gg.data.onFirstLoginToday();
gg.ui.showToast('今日首次登录(每日重置)成功');
GM.show();
break;
case '复制存档':
MTools.CopyTextEvent(JSON.stringify(gg.data.doc));
gg.ui.showToast('复制存档成功');
GM.show();
break;
case '一键获取所有武器': {
void (async () => {
const added = await gg.equip.gmGrantAllBagEquips();
gg.data.saveToServer();
GEvent.Ins.emit(GEvent.UpdateCombatPower);
gg.ui.showToast(added > 0 ? `已发放成品武器 ${added} 种(含新武器)` : 'Weapon 表成品已齐');
GM.show();
})();
break;
}
case '一键添加所有宝石': {
void (async () => {
const added = await gg.gem.gmGrantAllGems();
gg.data.saveToServer();
gg.ui.showToast(added > 0 ? `已再发宝石 ${added} 种` : 'Weapon 表无宝石');
GM.show();
})();
break;
}
3 weeks ago
case '设置武器和技能':
gg.ui.openPanel(UIID.PopGM, { data: 2 });
GM.show();
break;
case '设置武器等级':
gg.ui.openPanel(UIID.PopGM, { data: 1 });
GM.show();
break;
case '清除指定背包文字':
gg.game.gmBagWeapon2Ids = null;
gg.ui.showToast('已恢复背包正常刷新');
this._refreshBagIfPrep();
GM.show();
break;
case '快速胜利1怪':
sdkConfig.isDebugFastWinMonsterNum = 1;
gg.ui.showToast('快速胜利:击杀1怪后通关');
GM.show();
break;
case '关闭快速胜利':
sdkConfig.isDebugFastWinMonsterNum = 0;
gg.ui.showToast('已关闭快速胜利');
GM.show();
break;
case '重置每日商店or抽奖':
DailyShopDataManager.gmResetShopAndLotteryKeepCarry();
gg.ui.showToast('已重置每日商店/抽奖(保留携带道具)');
GM.show();
break;
case '重置每日商店BUFF':
DailyShopDataManager.gmClearCarriedBuffs();
gg.ui.showToast('已清空携带的每日商店BUFF');
GM.show();
break;
case '打开每日商店无限次数':
DailyShopDataManager.GM_UNLIMITED_DAILY_SHOP = true;
gg.ui.showToast('已打开每日商店无限次数');
GM.show();
break;
case '关闭每日商店无限次数':
DailyShopDataManager.GM_UNLIMITED_DAILY_SHOP = false;
DailyShopDataManager.gmResetShopAndLotteryKeepCarry();
gg.ui.showToast('已关闭每日商店无限次数并重置货架');
GM.show();
break;
case '清除AI主动BUFF':
gg.game.gmAiActiveBuffIds = null;
gg.ui.showToast('已恢复 AI 主动匹配随机');
GM.show();
break;
case '清除AI被动BUFF':
gg.game.gmAiPassiveBuffIds = null;
gg.ui.showToast('已恢复 AI 被动匹配随机');
GM.show();
break;
case '清除固定地图':
gg.game.gmMapId = 0;
gg.ui.showToast('已恢复地图随机');
GM.show();
break;
case '测试七十二变→妙手神偷': {
gg.game.gmRandomActiveFixBuffId = 16;
const result = DailyShopDataManager.gmSetFirstCarrySlot(DailyShopKind.Active, '20');
if (result.wrongKind) {
gg.ui.showToast('七十二变(id=20) 非主动 buff,请检查配表');
break;
}
if (!result.ok) {
gg.ui.showToast('写入七十二变失败,请检查 Battlebuff 表');
break;
}
gg.data.saveToServer();
gg.ui.showToast('已开启:七十二变 CD 结束固定→妙手神偷(id=16)');
GM.show();
break;
}
case '关闭七十二变固定':
gg.game.gmRandomActiveFixBuffId = null;
gg.ui.showToast('已关闭七十二变固定 roll,恢复随机');
GM.show();
break;
case '设置排行星级&胜场':
this._gmSetRankStarsAndDailyWins();
GM.show();
break;
case '开启己方营地不掉血':
this._setCampImmune(true, true);
break;
case '关闭己方营地不掉血':
this._setCampImmune(true, false);
break;
case '开启敌方营地不掉血':
this._setCampImmune(false, true);
break;
case '关闭敌方营地不掉血':
this._setCampImmune(false, false);
break;
}
this.refreshparamBtns();
}
onParamBtnClick(event: EventTouch) {
let needSaveServer = false;
switch (event.target.name) {
case '设置道具数量': {
const parts = this.eb_prama.string.trim().split(/\s+/);
const itemId = Number(parts[0]);
const num = Number(parts[1]);
if (!Number.isFinite(itemId) || !Number.isFinite(num)) {
gg.ui.showToast('格式:道具ID 数量');
break;
}
gg.data.setItemNum(itemId, num);
needSaveServer = true;
gg.ui.showToast(`道具 ${itemId} 已设为 ${num}`);
break;
}
case '设置武器数量': {
const parts = this.eb_prama.string.trim().split(/\s+/);
const equipId = Number(parts[0]);
const num = Number(parts[1]);
if (!Number.isFinite(equipId) || !Number.isFinite(num)) {
gg.ui.showToast('格式:武器ID 数量');
break;
}
const conf = gg.equip.getEquip(equipId);
if (!conf) {
gg.ui.showToast(`武器ID ${equipId} 无效`);
break;
}
gg.equip.setHaveEquipCount(equipId, num);
needSaveServer = true;
gg.ui.showToast(`武器 ${equipId} 已设为 ${gg.equip.getHaveEquipCount(equipId)}`);
break;
}
case '设置主动BUFF': {
const result = DailyShopDataManager.gmSetFirstCarrySlot(DailyShopKind.Active, this.eb_prama.string);
if (result.wrongKind) {
gg.ui.showToast('该 id 为被动 buff,不能写入主动第1槽');
break;
}
if (!result.ok) {
gg.ui.showToast('请填主动 Battlebuff.id(type=1) 或名称');
break;
}
needSaveServer = true;
if (result.parsed) {
gg.ui.showToast(`主动第1槽 → ${result.parsed.id}(${result.parsed.name})`);
} else {
gg.ui.showToast('已清空主动第1槽');
}
break;
}
case '设置被动BUFF': {
const result = DailyShopDataManager.gmSetFirstCarrySlot(DailyShopKind.Passive, this.eb_prama.string);
if (result.wrongKind) {
gg.ui.showToast('该 id 为主动 buff,不能写入被动第1槽');
break;
}
if (!result.ok) {
gg.ui.showToast('请填被动 Battlebuff.id(type=2) 或名称');
break;
}
needSaveServer = true;
if (result.parsed) {
gg.ui.showToast(`被动第1槽 → ${result.parsed.id}(${result.parsed.name})`);
} else {
gg.ui.showToast('已清空被动第1槽');
}
break;
}
case '设置金钱': {
const num = this._readParamInt();
if (num === null) break;
gg.data.setItemNum(ItemNumType.money, num);
needSaveServer = true;
break;
}
case '设置体力': {
const num = this._readParamInt();
if (num === null) break;
gg.data.setItemNum(ItemNumType.vigour, num);
needSaveServer = true;
break;
}
case '设置钻石': {
const num = this._readParamInt();
if (num === null) break;
gg.data.setItemNum(ItemNumType.diamond, num);
needSaveServer = true;
break;
}
case '设置关卡解锁': {
const rankId = this._readParamInt();
if (rankId === null || rankId < 1) {
gg.ui.showToast('请输入有效段位 id');
break;
}
gg.data.doc.rankId = rankId;
needSaveServer = true;
gg.ui.showToast(`段位已设为 ${gg.data.doc.rankId}`);
break;
}
case '设置星数': {
const stars = this._readParamInt();
if (stars === null || stars < 1) {
gg.ui.showToast('请输入有效星数(>=1)');
break;
}
gg.data.doc.rankStars = stars;
HeadIconManager.onRankStarsChanged();
needSaveServer = true;
void RankBoardManager.syncSelfScore();
GEvent.Ins.emit(GEvent.UpdateRankStars);
gg.ui.showToast(`星数已设为 ${gg.data.doc.rankStars}`);
break;
}
case '设置玩家局内血量': {
const hp = this._readParamInt();
if (hp === null || hp <= 0) {
gg.ui.showToast('请输入正整数血量');
break;
}
this._applyPlayerWallHp(hp);
gg.ui.showToast(`城墙血量 ${hp}${gg.battle.match ? '(局内已同步)' : '(下局生效)'}`);
break;
}
case '设置玩家等级': {
const level = this._readParamInt();
if (level === null || level < 0) {
gg.ui.showToast('请输入有效等级');
break;
}
this._applyUserLevel(level);
needSaveServer = true;
GEvent.Ins.emit(GEvent.UpdateCombatPower);
gg.ui.showToast(`主角等级已设为 ${gg.data.getPlayerLevel()}`);
break;
}
case '设置玩家存档':
try {
const doc = JSON.parse(this.eb_prama.string);
if (!doc || typeof doc !== 'object') {
gg.ui.showToast('存档格式错误');
break;
}
gg.data.doc = doc;
gg.data['_IsFirstLogin'] = false;
gg.game.init();
GEvent.Ins.emit(GEvent.UpdateItemNum);
gg.data.saveLocal();
gg.ui.showToast('设置成功');
GM.show();
} catch {
gg.ui.showToast('存档格式错误');
}
break;
case '设置通关怪物数量': {
const n = Math.floor(Number(this.eb_prama.string));
if (Number.isNaN(n) || n < 0) {
gg.ui.showToast('请输入非负整数,0=关闭');
break;
}
sdkConfig.isDebugFastWinMonsterNum = n;
gg.ui.showToast(n > 0 ? `快速胜利:击杀${n}怪后通关` : '已关闭快速胜利');
break;
}
case '指定背包文字':
gg.game.gmBagWeapon2Ids = parseGmBagWeapon2Filter(this.eb_prama.string);
if (gg.game.gmBagWeapon2Ids?.length) {
gg.ui.showToast(`背包仅刷: ${gg.game.gmBagWeapon2Ids.join(',')}`);
} else if (this.eb_prama.string.trim() === '' || this.eb_prama.string.trim() === '0') {
gg.ui.showToast('已关闭指定刷新');
} else {
gg.ui.showToast('未识别文字,请填 weapon2Id 或名称');
}
this._refreshBagIfPrep();
break;
case '设置AI主动BUFF': {
const ids = parseGmAiBattleBuffIds(this.eb_prama.string, 1);
gg.game.gmAiActiveBuffIds = ids;
if (ids?.length) {
gg.ui.showToast(`AI主动常驻: ${ids.join(',')}`);
} else if (this.eb_prama.string.trim() === '' || this.eb_prama.string.trim() === '0') {
gg.ui.showToast('已关闭 AI 主动覆盖(恢复每局随机)');
} else {
gg.ui.showToast('未识别主动 id,请填 Battlebuff.id(type=1)');
}
break;
}
case '设置AI被动BUFF': {
const ids = parseGmAiBattleBuffIds(this.eb_prama.string, 2);
gg.game.gmAiPassiveBuffIds = ids;
if (ids?.length) {
gg.ui.showToast(`AI被动常驻: ${ids.join(',')}`);
} else if (this.eb_prama.string.trim() === '' || this.eb_prama.string.trim() === '0') {
gg.ui.showToast('已关闭 AI 被动覆盖(恢复每局随机)');
} else {
gg.ui.showToast('未识别被动 id,请填 Battlebuff.id(type=2)');
}
break;
}
case '固定地图': {
const n = this._readParamInt();
if (n === null) break;
if (n <= 0) {
gg.game.gmMapId = 0;
gg.ui.showToast('已关闭固定地图(恢复随机)');
break;
}
const clamped = gg.data.project.clampBattleLevelId(n);
if (clamped !== n) {
console.log('[GM] 固定地图 id 不在 Level 表,已钳到', n, clamped);
}
gg.game.gmMapId = clamped;
gg.ui.showToast(this._formatFixedLevelToast(clamped));
break;
}
}
if (needSaveServer) {
gg.data.saveToServer();
} else {
gg.data.saveLocal();
}
this.refreshparamBtns();
}
/**
* GM:己方/敌方营地不掉血(仅本次登录内存)。
* @param local true=己方营地 false=敌方营地
* @param immune 是否免伤
*/
private _setCampImmune(local: boolean, immune: boolean): void {
if (local) {
gg.game.gmLocalCampImmune = immune;
} else {
gg.game.gmEnemyCampImmune = immune;
}
const runtime = gg.battle.match;
if (runtime instanceof BattleRuntime) {
runtime.syncGmCampImmune();
}
const side = local ? '己方' : '敌方';
gg.ui.showToast(immune ? `已开启${side}营地不掉血(本次登录)` : `已关闭${side}营地不掉血`);
GM.show();
}
/** GM:写入 PopEmolument 待领快照并标今日首次登录,重新进 Home 弹窗 */
private _gmSetRankStarsAndDailyWins(): void {
const ok = EmolumentDataManager.gmPrepareFirstLoginPopTest(
GM_EMOLUMENT_SNAP_STARS,
GM_EMOLUMENT_SNAP_WINS,
);
if (!ok) {
gg.ui.showToast('俸禄待领星级须 > 0');
return;
}
gg.data.saveToServer();
gg.ui.showToast(
`俸禄待领 星${GM_EMOLUMENT_SNAP_STARS} 胜${GM_EMOLUMENT_SNAP_WINS},请重新进 Home`,
);
}
private _readParamInt(): number | null {
const n = Math.floor(Number(this.eb_prama.string.trim()));
if (!Number.isFinite(n)) {
gg.ui.showToast('请输入有效数字');
return null;
}
return n;
}
private _refreshBagIfPrep(): void {
const runtime = gg.battle.match;
if (!(runtime instanceof BattleRuntime)) return;
const session = runtime.bagSession;
if (session?.merge.prepActive) {
session.refreshBag(runtime.LevelConfigId, false);
}
}
/** 预设下局城墙血量;局内则同步当前 slot */
private _applyPlayerWallHp(hp: number): void {
gg.game.playerHp = hp;
const runtime = gg.battle.match;
if (!(runtime instanceof BattleRuntime)) return;
const slot = runtime.localSlot;
if (!slot) return;
slot.wallMaxHp = hp;
slot.wallHp = hp;
}
/** 设置主角等级(Role 表已移除) */
private _applyUserLevel(_targetLevel: number): void {
}
private _helpStr = `GM 工具帮助
【快速按钮】
· 清除副本次数难度全开:重置各副本挑战次数,难度解锁到 5
· 今日首次登录:触发每日重置逻辑
· 复制存档:复制当前 doc JSON 到剪贴板
· 一键获取所有武器:Weapon 全表成品各发 1 把(含 isshow=1 与新增;新武器保留弹窗/角标)
· 一键添加所有宝石:Weapon 全表每颗再发 1 颗(每次点击叠加一套)
3 weeks ago
· 设置武器等级 / 设置武器和技能:打开 PopGM 面板
· 清除指定背包文字:恢复随机
· 快速胜利 / 关闭快速胜利:调试通关
· 重置每日商店or抽奖:重抽货架/抽奖池并清零购买次数,保留携带道具
· 重置每日商店BUFF:清空当前携带的主动/被动道具
· 打开/关闭每日商店无限次数:不限制货架购买和抽奖次数(关闭时自动重置货架)
· 清除AI主动/被动BUFF:恢复匹配随机抽取
· 清除固定地图:恢复关卡随机
· 测试七十二变→妙手神偷:主动第1槽=七十二变(id=20),CD 结束固定 roll 妙手神偷(id=16)
· 关闭七十二变固定:恢复七十二变正常随机
· 设置排行星级&胜场:俸禄待领星50胜50 + 标今日首次登录,重新进 Home 弹 PopEmolument
· 关闭/显示广告、打开/关闭内购:切换调试开关
· 开启/关闭己方或敌方营地不掉血:本次登录有效,不写档
【参数按钮】(先在输入框填参数再点按钮)
· 设置道具数量:道具ID 数量(空格分隔)
· 设置武器数量:武器ID 数量(空格分隔,写入成品库存)
· 设置主动BUFF:Battlebuff.id(type=1),只写携带第1槽(有则替换;0/空=清空)
· 设置被动BUFF:Battlebuff.id(type=2),只写携带第1槽(有则替换;0/空=清空)
· 设置金钱 / 体力 / 钻石:单个数字
· 设置关卡解锁:章节 id
· 设置星数:总星数(>=1)
· 设置玩家局内血量:城墙最大血量
· 设置玩家等级:主角总等级
· 设置玩家存档:粘贴 JSON 存档
· 设置通关怪物数量:N 或 0 关闭
· 指定背包文字:id 或名称,逗号分隔
· 设置AI主动BUFF:Battlebuff.id,逗号分隔(type=1,下局生效;空/0 关闭)
· 设置AI被动BUFF:Battlebuff.id,逗号分隔(type=2,下局生效;空/0 关闭)
· 固定地图:填 Level.id(关卡表 name 对应关卡);0 关闭随机
`;
/** GM 固定关卡:参数行展示 */
private _formatFixedLevelParam(levelId: number): string {
if (levelId <= 0) return '参数:0(随机)';
const row = gg.data.table.getTableData<ITableLevel>(TableNames.Level, levelId);
const name = typeof row?.name === 'string' ? row.name.trim() : '';
return name ? `参数:${levelId}(${name})` : `参数:${levelId}`;
}
/** GM 固定关卡:设置成功 toast */
private _formatFixedLevelToast(levelId: number): string {
const row = gg.data.table.getTableData<ITableLevel>(TableNames.Level, levelId);
const name = typeof row?.name === 'string' ? row.name.trim() : '';
return name ? `下局固定关卡${levelId}(${name})` : `下局固定关卡${levelId}`;
}
}