Commit 71b4a5d1 authored by nanahira's avatar nanahira

rework random duel fleefree

parent 93745262
...@@ -222,6 +222,7 @@ export class Client { ...@@ -222,6 +222,7 @@ export class Client {
deck?: YGOProDeck; deck?: YGOProDeck;
@ClientRoomField() @ClientRoomField()
startDeck?: YGOProDeck; startDeck?: YGOProDeck;
fleeFree = false;
async sendTypeChange() { async sendTypeChange() {
return this.send( return this.send(
......
...@@ -70,6 +70,14 @@ export const TRANSLATIONS = { ...@@ -70,6 +70,14 @@ export const TRANSLATIONS = {
random_ban_reason_AFK: 'AFK', random_ban_reason_AFK: 'AFK',
random_ban_reason_abuse: 'Abusing', random_ban_reason_abuse: 'Abusing',
random_ban_reason_zombie: 'Zombie', random_ban_reason_zombie: 'Zombie',
random_score_part1: 'Record of ',
random_score_part2: ': ',
random_score_part3: '% WIN, ',
random_score_part4_combo: '% RAGE QUIT, WIN COMBO ',
random_score_part5_combo: ' !',
random_score_part4: '%',
random_score_blank: " didn't have enough duel record.",
random_score_not_enough: " didn't have enough duel record.",
unwelcome_warn_part1: 'If you keep doing ', unwelcome_warn_part1: 'If you keep doing ',
unwelcome_warn_part2: ', your opponent may leave you.', unwelcome_warn_part2: ', your opponent may leave you.',
unwelcome_tip_part1: 'Your opponent did ', unwelcome_tip_part1: 'Your opponent did ',
...@@ -160,6 +168,14 @@ export const TRANSLATIONS = { ...@@ -160,6 +168,14 @@ export const TRANSLATIONS = {
random_ban_reason_AFK: '挂机', random_ban_reason_AFK: '挂机',
random_ban_reason_abuse: '发言违规', random_ban_reason_abuse: '发言违规',
random_ban_reason_zombie: '挂房间', random_ban_reason_zombie: '挂房间',
random_score_part1: '',
random_score_part2: '的战绩:胜率',
random_score_part3: '%,逃跑率',
random_score_part4_combo: '%,',
random_score_part5_combo: '连胜中!',
random_score_part4: '%',
random_score_blank: '的战绩:正在统计中',
random_score_not_enough: '的战绩:正在统计中',
unwelcome_warn_part1: '如果您经常', unwelcome_warn_part1: '如果您经常',
unwelcome_warn_part2: ',您的对手可能会离你而去。', unwelcome_warn_part2: ',您的对手可能会离你而去。',
unwelcome_tip_part1: '因为您的对手有', unwelcome_tip_part1: '因为您的对手有',
......
...@@ -27,7 +27,6 @@ import { WaitForPlayerProvider } from '../wait-for-player-provider'; ...@@ -27,7 +27,6 @@ import { WaitForPlayerProvider } from '../wait-for-player-provider';
import { ClientKeyProvider } from '../client-key-provider'; import { ClientKeyProvider } from '../client-key-provider';
import { RandomDuelScore } from './score.entity'; import { RandomDuelScore } from './score.entity';
import { import {
buildFleeFreeKey,
formatRemainText, formatRemainText,
RandomDuelPunishReason, RandomDuelPunishReason,
renderReasonText, renderReasonText,
...@@ -73,13 +72,6 @@ class RandomDuelDisciplineCache { ...@@ -73,13 +72,6 @@ class RandomDuelDisciplineCache {
expireAt = 0; expireAt = 0;
} }
class RandomDuelFleeFreeCache {
@CacheKey()
key!: string;
enabled = false;
}
declare module '../../room' { declare module '../../room' {
interface Room { interface Room {
randomType?: string; randomType?: string;
...@@ -150,6 +142,9 @@ export class RandomDuelProvider { ...@@ -150,6 +142,9 @@ export class RandomDuelProvider {
await this.setAbuseCount(this.getClientKey(client), 0); await this.setAbuseCount(this.getClientKey(client), 0);
} }
await this.updateOpponentRelation(event.room, client); await this.updateOpponentRelation(event.room, client);
if (event.room.randomType === 'M') {
await this.sendMatchScoreTips(event.room, client);
}
return next(); return next();
}); });
...@@ -186,7 +181,7 @@ export class RandomDuelProvider { ...@@ -186,7 +181,7 @@ export class RandomDuelProvider {
if ( if (
room.turnCount >= RANDOM_DUEL_EARLY_SURRENDER_TURN || room.turnCount >= RANDOM_DUEL_EARLY_SURRENDER_TURN ||
(room.randomType === 'M' && this.recordMatchScoresEnabled) || (room.randomType === 'M' && this.recordMatchScoresEnabled) ||
(await this.isFleeFree(room.name, this.getClientKey(client))) client.fleeFree
) { ) {
return next(); return next();
} }
...@@ -428,7 +423,7 @@ export class RandomDuelProvider { ...@@ -428,7 +423,7 @@ export class RandomDuelProvider {
event.bySystem || event.bySystem ||
event.oldPos >= NetPlayerType.OBSERVER || event.oldPos >= NetPlayerType.OBSERVER ||
room.duelStage === DuelStage.Begin || room.duelStage === DuelStage.Begin ||
(await this.isFleeFree(room.name, this.getClientKey(client))) client.fleeFree
) { ) {
return; return;
} }
...@@ -505,7 +500,7 @@ export class RandomDuelProvider { ...@@ -505,7 +500,7 @@ export class RandomDuelProvider {
if (player.pos >= NetPlayerType.OBSERVER || player.isInternal) { if (player.pos >= NetPlayerType.OBSERVER || player.isInternal) {
return; return;
} }
await this.setFleeFree(room.name, this.getClientKey(player), true); player.fleeFree = true;
await player.sendChat( await player.sendChat(
'#{unwelcome_tip_part1}#{random_ban_reason_abuse}#{unwelcome_tip_part2}', '#{unwelcome_tip_part1}#{random_ban_reason_abuse}#{unwelcome_tip_part2}',
ChatColor.BABYBLUE, ChatColor.BABYBLUE,
...@@ -683,35 +678,61 @@ export class RandomDuelProvider { ...@@ -683,35 +678,61 @@ export class RandomDuelProvider {
await this.setDiscipline(clientKey, discipline); await this.setDiscipline(clientKey, discipline);
} }
private async isFleeFree(roomName: string, clientKey: string) { private async sendMatchScoreTips(room: Room, client: Client) {
if (!roomName || !clientKey) { if (!this.recordMatchScoresEnabled) {
return false; return;
} }
const key = buildFleeFreeKey(roomName, clientKey); const players = room.playingPlayers.filter(
const data = await this.ctx.aragami.get(RandomDuelFleeFreeCache, key); (player) => player.pos < NetPlayerType.OBSERVER,
return !!data?.enabled; );
} if (!players.length) {
private async setFleeFree(
roomName: string,
clientKey: string,
enabled: boolean,
) {
if (!roomName || !clientKey) {
return; return;
} }
const key = buildFleeFreeKey(roomName, clientKey);
await this.ctx.aragami.set( const clientScoreText = await this.getScoreDisplay(
RandomDuelFleeFreeCache, this.getClientKey(client),
{ client.name,
key,
enabled: !!enabled,
},
{
key,
ttl: RANDOM_DUEL_TTL,
},
); );
for (const player of players) {
if (clientScoreText) {
await player.sendChat(clientScoreText, ChatColor.GREEN);
}
if (player === client) {
continue;
}
const playerScoreText = await this.getScoreDisplay(
this.getClientKey(player),
player.name,
);
if (playerScoreText) {
await client.sendChat(playerScoreText, ChatColor.GREEN);
}
}
}
private async getScoreDisplay(name: string, displayName: string) {
const repo = this.ctx.database?.getRepository(RandomDuelScore);
if (!repo || !name) {
return '';
}
const score = await repo.findOneBy({ name });
if (!score) {
return `${displayName} #{random_score_blank}`;
}
const total = score.winCount + score.loseCount;
if (score.winCount < 2 && total < 3) {
return `${displayName} #{random_score_not_enough}`;
}
const safeTotal = total > 0 ? total : 1;
const winRate = Math.ceil((score.winCount / safeTotal) * 100);
const fleeRate = Math.ceil((score.fleeCount / safeTotal) * 100);
if (score.winCombo >= 2) {
return `#{random_score_part1}${displayName} #{random_score_part2} ${winRate}#{random_score_part3} ${fleeRate}#{random_score_part4_combo}${score.winCombo}#{random_score_part5_combo}`;
}
return `#{random_score_part1}${displayName} #{random_score_part2} ${winRate}#{random_score_part3} ${fleeRate}#{random_score_part4}`;
} }
private get recordMatchScoresEnabled() { private get recordMatchScoresEnabled() {
......
...@@ -36,6 +36,3 @@ export const formatRemainText = (expireAt: number) => { ...@@ -36,6 +36,3 @@ export const formatRemainText = (expireAt: number) => {
} }
return `${remainMinutes}m`; return `${remainMinutes}m`;
}; };
export const buildFleeFreeKey = (roomName: string, ip: string) =>
`${roomName}:${ip}`;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment