507 lines
23 KiB
JavaScript
507 lines
23 KiB
JavaScript
// ============================================================================
|
||
// 02_SubGame_Input.js —— 平台输入/回调接口「转发壳」(框架维护,子游戏不碰)
|
||
// 平台按全局名调用 gameHallImport.* / Game_Modify.*;本文件统一转发到 SubGameHooks 同名 hook。
|
||
// 子游戏只需在 codes/ 的 SubGameHooks 里实现需要的接口(见 codes/SubGameHooks.js)。
|
||
// 严格 ES5。接口清单与默认值依据 spec §9。
|
||
// ============================================================================
|
||
|
||
var gameHallImport = gameHallImport || {};
|
||
var Game_Modify = Game_Modify || {};
|
||
|
||
// ============================================================================
|
||
// gameHallImport.* — 大厅接口(9 个)
|
||
// ============================================================================
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
// 注:与 Game_Modify.appStart 同名但语义不同(大厅启动 vs 游戏启动),故 hook 名加 hall 前缀区分
|
||
gameHallImport.appStart = function () {
|
||
if (window.SubGameHooks && SubGameHooks.hallAppStart) return SubGameHooks.hallAppStart();
|
||
};
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
gameHallImport.jumpMenuScene = function () {
|
||
if (window.SubGameHooks && SubGameHooks.jumpMenuScene) return SubGameHooks.jumpMenuScene();
|
||
};
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
gameHallImport.gameStart = function () {
|
||
if (window.SubGameHooks && SubGameHooks.gameStart) return SubGameHooks.gameStart();
|
||
};
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
gameHallImport.setGameList = function () {
|
||
if (window.SubGameHooks && SubGameHooks.setGameList) return SubGameHooks.setGameList();
|
||
};
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
gameHallImport.clearGameinfo = function () {
|
||
if (window.SubGameHooks && SubGameHooks.clearGameinfo) return SubGameHooks.clearGameinfo();
|
||
};
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
gameHallImport.getWebdata = function (data) {
|
||
if (window.SubGameHooks && SubGameHooks.getWebdata) return SubGameHooks.getWebdata(data);
|
||
};
|
||
|
||
// B 类:有平台默认返回值,无 hook 即返回默认
|
||
gameHallImport.isInstalled = function (data) {
|
||
if (window.SubGameHooks && SubGameHooks.isInstalled) return SubGameHooks.isInstalled(data);
|
||
return 1;
|
||
};
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
gameHallImport.up_imgurl = function (recid, photo) {
|
||
if (window.SubGameHooks && SubGameHooks.up_imgurl) return SubGameHooks.up_imgurl(recid, photo);
|
||
};
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
gameHallImport.getphoto = function (recid, photo) {
|
||
if (window.SubGameHooks && SubGameHooks.getphoto) return SubGameHooks.getphoto(recid, photo);
|
||
};
|
||
|
||
// ============================================================================
|
||
// Game_Modify.* — 生命周期/回调接口(来自 02,45 个)
|
||
// ============================================================================
|
||
|
||
// A 类:纯子游戏行为,无 hook 即 no-op
|
||
Game_Modify.appStart = function () {
|
||
if (window.SubGameHooks && SubGameHooks.appStart) return SubGameHooks.appStart();
|
||
};
|
||
|
||
// A 类:开战回调,无 hook 即 no-op
|
||
Game_Modify.StartWar = function (_msg) {
|
||
if (window.SubGameHooks && SubGameHooks.StartWar) return SubGameHooks.StartWar(_msg);
|
||
};
|
||
|
||
// A 类:接收数据包,无 hook 即 no-op
|
||
Game_Modify._ReceiveData = function (_msg) {
|
||
if (window.SubGameHooks && SubGameHooks._ReceiveData) return SubGameHooks._ReceiveData(_msg);
|
||
};
|
||
|
||
// A 类:创建房间,无 hook 即 no-op
|
||
Game_Modify.createRoom = function (_roomtype, _infinite) {
|
||
if (window.SubGameHooks && SubGameHooks.createRoom) return SubGameHooks.createRoom(_roomtype, _infinite);
|
||
};
|
||
|
||
// A 类:自己进入房间,无 hook 即 no-op
|
||
Game_Modify.myJoinRoom = function (_msg) {
|
||
if (window.SubGameHooks && SubGameHooks.myJoinRoom) return SubGameHooks.myJoinRoom(_msg);
|
||
};
|
||
|
||
// A 类:重连,无 hook 即 no-op
|
||
Game_Modify.Reconnect = function (_deskinfo) {
|
||
if (window.SubGameHooks && SubGameHooks.Reconnect) return SubGameHooks.Reconnect(_deskinfo);
|
||
};
|
||
|
||
// A 类:未开战重连,无 hook 即 no-op
|
||
Game_Modify.ReconnectNoMakewar = function () {
|
||
if (window.SubGameHooks && SubGameHooks.ReconnectNoMakewar) return SubGameHooks.ReconnectNoMakewar();
|
||
};
|
||
|
||
// A 类:关闭所有声音,无 hook 即 no-op
|
||
Game_Modify.stopAllSounds = function () {
|
||
if (window.SubGameHooks && SubGameHooks.stopAllSounds) return SubGameHooks.stopAllSounds();
|
||
};
|
||
|
||
// A 类:投票解散确认,无 hook 即 no-op
|
||
Game_Modify.Free = function (_msg) {
|
||
if (window.SubGameHooks && SubGameHooks.Free) return SubGameHooks.Free(_msg);
|
||
};
|
||
|
||
// A 类:未开战状态加入牌桌数据,无 hook 即 no-op
|
||
Game_Modify.DeskInfo = function (_msg) {
|
||
if (window.SubGameHooks && SubGameHooks.DeskInfo) return SubGameHooks.DeskInfo(_msg);
|
||
};
|
||
|
||
// A 类:开局后自己退出房间,无 hook 即 no-op
|
||
Game_Modify.breakRoom = function () {
|
||
if (window.SubGameHooks && SubGameHooks.breakRoom) return SubGameHooks.breakRoom();
|
||
};
|
||
|
||
// A 类:其他玩家加入房间,无 hook 即 no-op
|
||
Game_Modify.playerJoinRoom = function (seat) {
|
||
if (window.SubGameHooks && SubGameHooks.playerJoinRoom) return SubGameHooks.playerJoinRoom(seat);
|
||
};
|
||
|
||
// A 类:其他玩家离开房间,无 hook 即 no-op
|
||
Game_Modify.playerLeaveRoom = function (seat) {
|
||
if (window.SubGameHooks && SubGameHooks.playerLeaveRoom) return SubGameHooks.playerLeaveRoom(seat);
|
||
};
|
||
|
||
// A 类:更新游戏界面,无 hook 即 no-op
|
||
Game_Modify.updateScene = function () {
|
||
if (window.SubGameHooks && SubGameHooks.updateScene) return SubGameHooks.updateScene();
|
||
};
|
||
|
||
// A 类:关闭游戏界面,无 hook 即 no-op
|
||
Game_Modify.closeGameScene = function () {
|
||
if (window.SubGameHooks && SubGameHooks.closeGameScene) return SubGameHooks.closeGameScene();
|
||
};
|
||
|
||
// A 类:玩家离线,无 hook 即 no-op
|
||
Game_Modify.playerOffline = function (seat) {
|
||
if (window.SubGameHooks && SubGameHooks.playerOffline) return SubGameHooks.playerOffline(seat);
|
||
};
|
||
|
||
// A 类:玩家上线,无 hook 即 no-op
|
||
Game_Modify.playerOnline = function (seat) {
|
||
if (window.SubGameHooks && SubGameHooks.playerOnline) return SubGameHooks.playerOnline(seat);
|
||
};
|
||
|
||
// A 类:玩家电话状态,无 hook 即 no-op
|
||
Game_Modify.playerphonestate = function (seat, type) {
|
||
if (window.SubGameHooks && SubGameHooks.playerphonestate) return SubGameHooks.playerphonestate(seat, type);
|
||
};
|
||
|
||
// A 类:摇一摇事件,无 hook 即 no-op
|
||
Game_Modify.shakeEvent = function () {
|
||
if (window.SubGameHooks && SubGameHooks.shakeEvent) return SubGameHooks.shakeEvent();
|
||
};
|
||
|
||
// A 类:计算结果,无 hook 即 no-op
|
||
Game_Modify.calResult = function (inputArr) {
|
||
if (window.SubGameHooks && SubGameHooks.calResult) return SubGameHooks.calResult(inputArr);
|
||
};
|
||
|
||
// A 类:进入游戏主场景,无 hook 即 no-op
|
||
Game_Modify.onEnterMainScene = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.onEnterMainScene) return SubGameHooks.onEnterMainScene(roomtype);
|
||
};
|
||
|
||
// A 类:退出游戏主场景,无 hook 即 no-op
|
||
Game_Modify.onExitMainScene = function () {
|
||
if (window.SubGameHooks && SubGameHooks.onExitMainScene) return SubGameHooks.onExitMainScene();
|
||
};
|
||
|
||
// A 类:获取游戏配置时调用,无 hook 即 no-op
|
||
Game_Modify.onGameConfig = function (_gameConfig) {
|
||
if (window.SubGameHooks && SubGameHooks.onGameConfig) return SubGameHooks.onGameConfig(_gameConfig);
|
||
};
|
||
|
||
// A 类:进入牌局回放,无 hook 即 no-op
|
||
Game_Modify.onEnterVideo = function () {
|
||
if (window.SubGameHooks && SubGameHooks.onEnterVideo) return SubGameHooks.onEnterVideo();
|
||
};
|
||
|
||
// A 类:收到投降回包,无 hook 即 no-op
|
||
Game_Modify.onSurrender = function (_msg) {
|
||
if (window.SubGameHooks && SubGameHooks.onSurrender) return SubGameHooks.onSurrender(_msg);
|
||
};
|
||
|
||
// A 类:玩家准备触发,无 hook 即 no-op
|
||
Game_Modify.onReady = function (seat) {
|
||
if (window.SubGameHooks && SubGameHooks.onReady) return SubGameHooks.onReady(seat);
|
||
};
|
||
|
||
// B 类:获取房间描述,无 hook 返回默认文案
|
||
Game_Modify.getRoomInfo = function (roomtype, type, tea) {
|
||
if (window.SubGameHooks && SubGameHooks.getRoomInfo) return SubGameHooks.getRoomInfo(roomtype, type, tea);
|
||
return "房间描述" + roomtype;
|
||
};
|
||
|
||
// B 类:获取房间星星场下限,无 hook 返回默认值
|
||
Game_Modify.getStarLimit = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.getStarLimit) return SubGameHooks.getStarLimit(roomtype);
|
||
return 2001000;
|
||
};
|
||
|
||
// B 类:获取房间星星场倍数,无 hook 返回默认值
|
||
Game_Modify.getMult = function (roomtype, type) {
|
||
if (window.SubGameHooks && SubGameHooks.getMult) return SubGameHooks.getMult(roomtype, type);
|
||
return 10000;
|
||
};
|
||
|
||
// B 类:获取房间全部信息描述,无 hook 返回默认文案
|
||
Game_Modify.getFullRoomInfo = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.getFullRoomInfo) return SubGameHooks.getFullRoomInfo(roomtype);
|
||
return "房间描述" + roomtype;
|
||
};
|
||
|
||
// A 类:打开帮助页面,无 hook 即 no-op
|
||
Game_Modify.onOpenHelp = function (spid) {
|
||
if (window.SubGameHooks && SubGameHooks.onOpenHelp) return SubGameHooks.onOpenHelp(spid);
|
||
};
|
||
|
||
// A 类:显示大厅界面,无 hook 即 no-op
|
||
Game_Modify.onMainMenuScene = function () {
|
||
if (window.SubGameHooks && SubGameHooks.onMainMenuScene) return SubGameHooks.onMainMenuScene();
|
||
};
|
||
|
||
// A 类:数字输入框确认回调,无 hook 即 no-op
|
||
Game_Modify.onCheckInput = function (_result) {
|
||
if (window.SubGameHooks && SubGameHooks.onCheckInput) return SubGameHooks.onCheckInput(_result);
|
||
};
|
||
|
||
// A 类:创建房间成功后触发,无 hook 即 no-op
|
||
Game_Modify.onCreateRoom = function (_data) {
|
||
if (window.SubGameHooks && SubGameHooks.onCreateRoom) return SubGameHooks.onCreateRoom(_data);
|
||
};
|
||
|
||
// B 类:获取离场限制,无 hook 返回默认值
|
||
Game_Modify.getLeaveLimit = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.getLeaveLimit) return SubGameHooks.getLeaveLimit(roomtype);
|
||
return 10;
|
||
};
|
||
|
||
// A 类:成功获取定位信息,无 hook 即 no-op
|
||
Game_Modify.onLocationInfo = function (_locationInfo) {
|
||
if (window.SubGameHooks && SubGameHooks.onLocationInfo) return SubGameHooks.onLocationInfo(_locationInfo);
|
||
};
|
||
|
||
// A 类:进入游戏界面创建牌桌之前,无 hook 即 no-op
|
||
Game_Modify.onCreateDesk = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.onCreateDesk) return SubGameHooks.onCreateDesk(roomtype);
|
||
};
|
||
|
||
// B 类:获取是否开启视频功能,无 hook 返回默认值
|
||
Game_Modify.getVideoByRoomType = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.getVideoByRoomType) return SubGameHooks.getVideoByRoomType(roomtype);
|
||
return 1;
|
||
};
|
||
|
||
// B 类:获取房间顶部描述数组,无 hook 返回默认文案数组
|
||
Game_Modify.getRoomTopDescAry = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.getRoomTopDescAry) return SubGameHooks.getRoomTopDescAry(roomtype);
|
||
return ["" + roomtype];
|
||
};
|
||
|
||
// A 类:星星场房间列表,无 hook 即 no-op
|
||
Game_Modify.getShareRoom = function (_msg) {
|
||
if (window.SubGameHooks && SubGameHooks.getShareRoom) return SubGameHooks.getShareRoom(_msg);
|
||
};
|
||
|
||
// A 类:玩家自己退出房间,无 hook 即 no-op
|
||
Game_Modify.myExitRoom = function (seat) {
|
||
if (window.SubGameHooks && SubGameHooks.myExitRoom) return SubGameHooks.myExitRoom(seat);
|
||
};
|
||
|
||
// A 类:接收到换座包触发,无 hook 即 no-op
|
||
Game_Modify.changeSeat = function (seat1, seat2) {
|
||
if (window.SubGameHooks && SubGameHooks.changeSeat) return SubGameHooks.changeSeat(seat1, seat2);
|
||
};
|
||
|
||
// A 类:关闭 vip 选项时调用,无 hook 即 no-op
|
||
Game_Modify.onCloseVip = function () {
|
||
if (window.SubGameHooks && SubGameHooks.onCloseVip) return SubGameHooks.onCloseVip();
|
||
};
|
||
|
||
// B 类:判断房间是否为金币场,无 hook 返回默认值(0=非金币场)
|
||
Game_Modify.getRoomMode = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.getRoomMode) return SubGameHooks.getRoomMode(roomtype);
|
||
return 0;
|
||
};
|
||
|
||
// B 类:获取房间最大玩家数量,无 hook 返回默认值
|
||
Game_Modify.getMaxPlayerCount = function (roomtype) {
|
||
if (window.SubGameHooks && SubGameHooks.getMaxPlayerCount) return SubGameHooks.getMaxPlayerCount(roomtype);
|
||
// 默认值依赖全局 Game_Config(须在本模板之前加载);无则回退 4
|
||
return (Game_Config.Max && Game_Config.Max.PlayerCnt) || 4;
|
||
};
|
||
|
||
// 内部辅助(非平台接口):把相对显示位序 relPos 映射为 { ind:精灵槽, configIndex:物理布局位 }。
|
||
// 2/3 人时 ind≠configIndex;无效返回 null。updatePlayerInfoUI 与桌面气泡默认实现共用此映射,
|
||
// 保证头像面板与聊天/语音气泡落在同一玩家位。
|
||
Game_Modify._resolveDisplaySlot = function (relPos, playerCount) {
|
||
var ind = -1, configIndex = -1;
|
||
if (playerCount === 2) {
|
||
if (relPos === 0) { ind = 0; configIndex = 0; }
|
||
else if (relPos === 1) { ind = 1; configIndex = 2; }
|
||
} else if (playerCount === 3) {
|
||
if (relPos === 0) { ind = 0; configIndex = 0; }
|
||
else if (relPos === 1) { ind = 1; configIndex = 1; }
|
||
else if (relPos === 2) { ind = 2; configIndex = 3; }
|
||
} else {
|
||
if (relPos === 0) { ind = 0; configIndex = 0; }
|
||
else if (relPos === 1) { ind = 1; configIndex = 1; }
|
||
else if (relPos === 2) { ind = 2; configIndex = 2; }
|
||
else if (relPos === 3) { ind = 3; configIndex = 3; }
|
||
}
|
||
if (ind === -1) return null;
|
||
return { ind: ind, configIndex: configIndex };
|
||
};
|
||
|
||
// B 类:更新指定座位的玩家信息 UI(昵称/分数/头像)。
|
||
// 有 hook 则委托子游戏;无 hook 时由本模板提供默认头像等 UI 的显示逻辑,其逻辑与子游戏
|
||
// codes 内 GameView.updatePlayerInfoUI 保持一致,布局取自 Game_Modify.PLAYER_INFO_LAYOUT(见 01)。
|
||
// 精灵操作一律经框架 SpriteManager(setPosition/setSize/setText/show|hideGroup),不直接调
|
||
// set_self/set_group 等引擎原语;头像加载走平台 Func.up_imgurl(非精灵原语,SpriteManager 无对应能力)。
|
||
// 不引用任何 codes 模块。平台 GameUI.updatePlayerInfoUI 会对每个座位逐一调用本接口,故按单座位渲染。
|
||
Game_Modify.updatePlayerInfoUI = function (targetSeat) {
|
||
if (window.SubGameHooks && SubGameHooks.updatePlayerInfoUI) return SubGameHooks.updatePlayerInfoUI(targetSeat);
|
||
|
||
// ---- 模板默认:与 GameView.updatePlayerInfoUI 一致的单座位渲染 ----
|
||
if (typeof Desk === 'undefined' || typeof C_Player === 'undefined' || typeof SpriteManager === 'undefined') return false;
|
||
var layout = Game_Modify.PLAYER_INFO_LAYOUT;
|
||
if (!layout || !layout.POSITIONS) return false;
|
||
if (!Desk.PlayerList || targetSeat < 0 || targetSeat >= Desk.PlayerList.length) return false;
|
||
|
||
var selfSeat = (typeof C_Player.seat === 'number') ? C_Player.seat : 0;
|
||
var playerCount = (Game_Config.Max && Game_Config.Max.PlayerCnt) || 4;
|
||
var relPos = (targetSeat - selfSeat + playerCount) % playerCount;
|
||
|
||
// 显示槽 ind 与布局位 configIndex(2/3 人时两者不同)
|
||
var slot = Game_Modify._resolveDisplaySlot(relPos, playerCount);
|
||
if (!slot) return false;
|
||
var ind = slot.ind, configIndex = slot.configIndex;
|
||
|
||
var player = Desk.PlayerList[targetSeat];
|
||
// 空座位:隐藏该位玩家信息群组
|
||
if (!player || !player.playerid || player.playerid === -1) {
|
||
SpriteManager.hideGroup(43 + ind);
|
||
return true;
|
||
}
|
||
|
||
var posConfig = layout.POSITIONS[configIndex];
|
||
if (!posConfig) return false;
|
||
|
||
// 底框(346+ind)
|
||
if (posConfig.FRAME_X !== undefined) {
|
||
SpriteManager.setPosition(346 + ind, posConfig.FRAME_X, posConfig.FRAME_Y);
|
||
SpriteManager.setSize(346 + ind, posConfig.FRAME_WIDTH, posConfig.FRAME_HEIGHT);
|
||
}
|
||
|
||
// 头像框(376+ind):基于底框 + 相对偏移
|
||
var avatarX = posConfig.FRAME_X + posConfig.AVATAR.OFFSET_X;
|
||
var avatarY = posConfig.FRAME_Y + posConfig.AVATAR.OFFSET_Y;
|
||
var avatarWidth = posConfig.AVATAR.WIDTH;
|
||
var avatarHeight = posConfig.AVATAR.HEIGHT;
|
||
var nameOffsetX = posConfig.AVATAR.NAME_OFFSET_X || 0;
|
||
var nameOffsetY = posConfig.AVATAR.NAME_OFFSET_Y || 0;
|
||
var scoreOffsetX = posConfig.AVATAR.SCORE_OFFSET_X || 0;
|
||
var scoreOffsetY = posConfig.AVATAR.SCORE_OFFSET_Y || 0;
|
||
SpriteManager.setPosition(376 + ind, avatarX, avatarY);
|
||
SpriteManager.setSize(376 + ind, avatarWidth, avatarHeight);
|
||
|
||
var textStyle = layout.TEXT_STYLE || {};
|
||
var maxLen = textStyle.NAME_MAX_LENGTH || 8;
|
||
var charWidth = textStyle.CHAR_WIDTH || 7;
|
||
|
||
// 昵称(406+ind)
|
||
var nickname = Func.subString(player.nickname || '', maxLen, true);
|
||
SpriteManager.setText(406 + ind, nickname);
|
||
var nameX = avatarX + nameOffsetX;
|
||
if (posConfig.NAME_CENTER_ALIGN) {
|
||
var textWidth = (typeof nickname.gblen === 'function') ? nickname.gblen() * charWidth : nickname.length * charWidth;
|
||
nameX = avatarX + avatarWidth / 2 - textWidth / 2;
|
||
}
|
||
SpriteManager.setPosition(406 + ind, nameX, avatarY + nameOffsetY);
|
||
|
||
// 分数(436+ind)
|
||
var score = (typeof player.score === 'number') ? player.score : 0;
|
||
SpriteManager.setText(436 + ind, score);
|
||
var scoreX = avatarX + scoreOffsetX;
|
||
if (posConfig.NAME_CENTER_ALIGN) {
|
||
var scoreWidth = String(score).length * charWidth;
|
||
scoreX = avatarX + avatarWidth / 2 - scoreWidth / 2;
|
||
}
|
||
SpriteManager.setPosition(436 + ind, scoreX, avatarY + scoreOffsetY);
|
||
|
||
// 头像图(116+ind):Func.up_imgurl 为平台头像加载接口(非引擎精灵原语)
|
||
if (player.avatar && typeof Func !== 'undefined' && typeof Func.up_imgurl === 'function') {
|
||
Func.up_imgurl(116 + ind, player.avatar);
|
||
}
|
||
|
||
// 显示该座位玩家信息群组
|
||
SpriteManager.showGroup(43 + ind);
|
||
return true;
|
||
};
|
||
// 桌面文字聊天气泡:有 hook 委托子游戏;无 hook 时按【可变人数】默认渲染,使气泡贴合各玩家。
|
||
// seat 为绝对座位;经 SpriteManager 操作精灵(背景552+ind/文字582+ind),位置取自 Game_Modify.BUBBLE_LAYOUT
|
||
// 的物理位配置,尺寸(内边距/字宽/显示时长)复用 Game_Config.Chat/Max;不直接调引擎原语、不引用 codes。
|
||
Game_Modify.ShowChat = function (seat, text) {
|
||
if (window.SubGameHooks && SubGameHooks.ShowChat) return SubGameHooks.ShowChat(seat, text);
|
||
GameUI.CloseChat();
|
||
if (typeof Desk === 'undefined' || typeof C_Player === 'undefined' || typeof SpriteManager === 'undefined') return;
|
||
var layout = Game_Modify.BUBBLE_LAYOUT;
|
||
if (!layout || !layout.POSITIONS) return;
|
||
var playerCount = (Game_Config.Max && Game_Config.Max.PlayerCnt) || 4;
|
||
var relPos = (seat - C_Player.seat + playerCount) % playerCount;
|
||
var slot = Game_Modify._resolveDisplaySlot(relPos, playerCount);
|
||
if (!slot) return;
|
||
var pos = layout.POSITIONS[slot.configIndex];
|
||
if (!pos) return;
|
||
var ind = slot.ind;
|
||
|
||
text = String(text);
|
||
var chat = Game_Config.Chat || {};
|
||
var dis_x = (chat.ChatDis && chat.ChatDis[0]) || 0;
|
||
var dis_y = (chat.ChatDis && chat.ChatDis[1]) || 0;
|
||
var text_w = chat.textwidth || 14;
|
||
var text_len = (typeof text.gblen === 'function') ? text.gblen() : text.length;
|
||
var bgW = text_len * text_w + dis_x * 2;
|
||
|
||
SpriteManager.setText(582 + ind, text);
|
||
if (pos.IS_LEFT) {
|
||
SpriteManager.setPosition(552 + ind, pos.X, pos.Y);
|
||
SpriteManager.setPosition(582 + ind, pos.X + dis_x, pos.Y + dis_y);
|
||
SpriteManager.setImage(552 + ind, layout.IMG_LEFT);
|
||
} else {
|
||
SpriteManager.setPosition(552 + ind, pos.X - bgW, pos.Y);
|
||
SpriteManager.setPosition(582 + ind, pos.X - text_len * text_w - dis_x, pos.Y + dis_y);
|
||
SpriteManager.setImage(552 + ind, layout.IMG_RIGHT);
|
||
}
|
||
SpriteManager.setWidth(552 + ind, bgW);
|
||
SpriteManager.show(552 + ind);
|
||
SpriteManager.show(582 + ind);
|
||
|
||
// 自动隐藏:复用平台配置的显示时长(观感与固定人数版一致),按槽位去重定时器
|
||
var dur = (Game_Config.Max && Game_Config.Max.ShowChat) || 3000;
|
||
Game_Modify._chatHideTimers = Game_Modify._chatHideTimers || {};
|
||
if (Game_Modify._chatHideTimers[ind]) { clearTimeout(Game_Modify._chatHideTimers[ind]); }
|
||
Game_Modify._chatHideTimers[ind] = setTimeout(function () {
|
||
SpriteManager.hide(552 + ind);
|
||
SpriteManager.hide(582 + ind);
|
||
Game_Modify._chatHideTimers[ind] = null;
|
||
}, dur);
|
||
};
|
||
|
||
// 桌面语音气泡(播放):有 hook 委托子游戏;无 hook 时按【可变人数】默认渲染。
|
||
// uiIndex 已是相对显示位序(relPos);经 SpriteManager 操作精灵(背景612+ind/内容642+ind),
|
||
// 位置取自 Game_Modify.BUBBLE_LAYOUT,气泡宽度依据内容精灵当前宽度;尺寸复用 Game_Config.Voice。
|
||
Game_Modify.gameui_play_voice = function (uiIndex) {
|
||
if (window.SubGameHooks && SubGameHooks.gameui_play_voice) return SubGameHooks.gameui_play_voice(uiIndex);
|
||
if (typeof SpriteManager === 'undefined') return;
|
||
var layout = Game_Modify.BUBBLE_LAYOUT;
|
||
if (!layout || !layout.POSITIONS) return;
|
||
var playerCount = (Game_Config.Max && Game_Config.Max.PlayerCnt) || 4;
|
||
var relPos = ((Number(uiIndex) % playerCount) + playerCount) % playerCount;
|
||
var slot = Game_Modify._resolveDisplaySlot(relPos, playerCount);
|
||
if (!slot) return;
|
||
var pos = layout.POSITIONS[slot.configIndex];
|
||
if (!pos) return;
|
||
var ind = slot.ind;
|
||
|
||
var voice = Game_Config.Voice || {};
|
||
var dis_x = (voice.VoiceDis && voice.VoiceDis[0]) || 0;
|
||
var dis_y = (voice.VoiceDis && voice.VoiceDis[1]) || 0;
|
||
var contentSize = SpriteManager.getSize(642 + ind);
|
||
var text_len = (contentSize && typeof contentSize.width === 'number') ? contentSize.width : 0;
|
||
var bgW = text_len + dis_x * 2;
|
||
|
||
if (pos.IS_LEFT) {
|
||
SpriteManager.setPosition(612 + ind, pos.X, pos.Y);
|
||
SpriteManager.setPosition(642 + ind, pos.X + dis_x, pos.Y + dis_y);
|
||
SpriteManager.setImage(612 + ind, layout.IMG_LEFT);
|
||
} else {
|
||
SpriteManager.setPosition(612 + ind, pos.X - bgW, pos.Y);
|
||
SpriteManager.setPosition(642 + ind, pos.X - text_len - dis_x, pos.Y + dis_y);
|
||
SpriteManager.setImage(612 + ind, layout.IMG_RIGHT);
|
||
}
|
||
SpriteManager.setWidth(612 + ind, bgW);
|
||
SpriteManager.show(612 + ind);
|
||
SpriteManager.show(642 + ind);
|
||
play_ani(1, 642 + ind, 43, 1, 3, 0, Game_Config.Voice.VoiceTime, 0, 0, 0, 0, 0, 0);
|
||
};
|
||
|
||
// 桌面语音气泡(停止):有 hook 委托子游戏;无 hook 时隐藏对应槽位的语音气泡。
|
||
Game_Modify.gameui_stop_voice = function (uiIndex) {
|
||
if (window.SubGameHooks && SubGameHooks.gameui_stop_voice) return SubGameHooks.gameui_stop_voice(uiIndex);
|
||
if (typeof SpriteManager === 'undefined') return;
|
||
var playerCount = (Game_Config.Max && Game_Config.Max.PlayerCnt) || 4;
|
||
var relPos = ((Number(uiIndex) % playerCount) + playerCount) % playerCount;
|
||
var slot = Game_Modify._resolveDisplaySlot(relPos, playerCount);
|
||
if (!slot) return;
|
||
var ind = slot.ind;
|
||
SpriteManager.hide(612 + ind);
|
||
SpriteManager.hide(642 + ind);
|
||
}; |