update:新增乱斗语音,排位赛界面新增统计
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
export const MELEE_FIRST_HALF_COMPLETE_AUDIO =
|
||||
"上半场6箭已射完,请等待他人完成射箭";
|
||||
export const MELEE_SECOND_HALF_COMPLETE_AUDIO =
|
||||
"下半场6箭已射完,请等待最终排名";
|
||||
|
||||
// 独立于页面和连接生命周期,避免切回页面、同场重连后重复提示。
|
||||
export function createMeleeCompletionTracker() {
|
||||
let contextKey = "";
|
||||
let completedHalves = new Set();
|
||||
let closedThrough = 0;
|
||||
|
||||
function prepare(info, userId) {
|
||||
if (!info?.matchId || userId === undefined || userId === null) return false;
|
||||
const key = JSON.stringify([String(info.matchId), String(userId)]);
|
||||
if (contextKey !== key) {
|
||||
contextKey = key;
|
||||
completedHalves = new Set();
|
||||
closedThrough = 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function observe(info, userId) {
|
||||
if (!prepare(info, userId)) return;
|
||||
const rounds = Array.isArray(info.rounds) ? info.rounds : [];
|
||||
rounds.slice(0, 2).forEach((round, index) => {
|
||||
if ((round.shoots?.[userId]?.length || 0) >= 6) {
|
||||
completedHalves.add(index + 1);
|
||||
}
|
||||
});
|
||||
if (rounds.length === 2 || Number(info.status) === 3) {
|
||||
closedThrough = Math.max(closedThrough, 1);
|
||||
}
|
||||
if ([2, 4].includes(Number(info.status))) closedThrough = 2;
|
||||
}
|
||||
|
||||
function getShotAudio(info, userId) {
|
||||
if (!prepare(info, userId)) return "";
|
||||
const mode = Number(info.mode);
|
||||
const rounds = Array.isArray(info.rounds) ? info.rounds : [];
|
||||
const half = rounds.length;
|
||||
const roster = info.teams?.[0]?.players;
|
||||
const expectedPlayers = mode === 4 ? 5 : mode === 5 ? 10 : 0;
|
||||
const shoots = rounds[half - 1]?.shoots;
|
||||
const ownShots = shoots?.[userId];
|
||||
const eligible =
|
||||
expectedPlayers > 0 &&
|
||||
[1, 2].includes(half) &&
|
||||
half > closedThrough &&
|
||||
!completedHalves.has(half) &&
|
||||
![2, 3, 4].includes(Number(info.status)) &&
|
||||
String(info.shootData?.playerId) === String(userId) &&
|
||||
Array.isArray(ownShots) && ownShots.length === 6 &&
|
||||
Array.isArray(roster) && roster.length === expectedPlayers &&
|
||||
new Set(roster.map((player) => String(player.id))).size === expectedPlayers &&
|
||||
roster.some((player) => String(player.id) === String(userId)) &&
|
||||
roster.every((player) => {
|
||||
// protobuf map 可以省略零箭用户;缺失项按零箭处理,异常项不参与推断。
|
||||
const list = shoots[player.id];
|
||||
return list === undefined || Array.isArray(list);
|
||||
}) &&
|
||||
roster.some((player) =>
|
||||
String(player.id) !== String(userId) &&
|
||||
(shoots[player.id]?.length || 0) < 6
|
||||
);
|
||||
|
||||
// 包括最后完成者在内,完成状态只消费一次;恢复快照也走同一入口。
|
||||
observe(info, userId);
|
||||
if (!eligible) return "";
|
||||
return half === 1
|
||||
? MELEE_FIRST_HALF_COMPLETE_AUDIO
|
||||
: MELEE_SECOND_HALF_COMPLETE_AUDIO;
|
||||
}
|
||||
|
||||
return { observe, getShotAudio };
|
||||
}
|
||||
|
||||
export default createMeleeCompletionTracker();
|
||||
Reference in New Issue
Block a user