Commit 73760c2b authored by chechunchi's avatar chechunchi Committed by Chunchi Che

refactor fetchEsHintMeta

parent 128d5827
Pipeline #28466 passed with stages
in 9 minutes and 1 second
import { ygopro } from "@/api";
import { Container } from "@/container";
import { AudioActionType, playEffect } from "@/infra/audio";
import { cardStore, fetchEsHintMeta } from "@/stores";
import { callCardAttack } from "@/ui/Duel/PlayMat/Card";
export default async (attack: ygopro.StocGameMessage.MsgAttack) => {
import { fetchEsHintMeta } from "./util";
export default async (
container: Container,
attack: ygopro.StocGameMessage.MsgAttack,
) => {
const context = container.context;
fetchEsHintMeta({
context,
originMsg: "「[?]」攻击时",
location: attack.attacker_location,
});
const attacker = cardStore.at(
const attacker = context.cardStore.at(
attack.attacker_location.zone,
attack.attacker_location.controller,
attack.attacker_location.sequence,
......
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (_: ygopro.StocGameMessage.MsgAttackDisabled) => {
fetchEsHintMeta({ originMsg: "攻击被无效时" });
import { fetchEsHintMeta } from "./util";
export default (
container: Container,
_: ygopro.StocGameMessage.MsgAttackDisabled,
) => {
fetchEsHintMeta({ context: container.context, originMsg: "攻击被无效时" });
};
import { ygopro } from "@/api";
import { cardStore } from "@/stores";
import { Container } from "@/container";
export default (becomeTarget: ygopro.StocGameMessage.MsgBecomeTarget) => {
export default (
container: Container,
becomeTarget: ygopro.StocGameMessage.MsgBecomeTarget,
) => {
const context = container.context;
for (const location of becomeTarget.locations) {
const target = cardStore.at(
const target = context.cardStore.at(
location.zone,
location.controller,
location.sequence,
......
import { ygopro } from "@/api";
import { Container } from "@/container";
import { cardStore, matStore } from "@/stores";
export default (
container: Container,
......@@ -10,7 +9,7 @@ export default (
const context = container.context;
while (true) {
const chain = matStore.chains.pop();
const chain = context.matStore.chains.pop();
if (chain === undefined) {
break;
}
......@@ -27,7 +26,7 @@ export default (
// 因此在连锁结束的时候把selected标记清掉。
//
// TODO: 这里每次都要全部遍历一遍,后续可以优化下
for (const card of cardStore.inner) {
for (const card of context.cardStore.inner) {
card.targeted = false;
}
};
import { fetchCard, ygopro } from "@/api";
import { Container } from "@/container";
import { AudioActionType, playEffect } from "@/infra/audio";
import { cardStore, fetchEsHintMeta, matStore } from "@/stores";
import { callCardFocus } from "@/ui/Duel/PlayMat/Card";
import { fetchEsHintMeta } from "./util";
export default async (
container: Container,
chaining: ygopro.StocGameMessage.MsgChaining,
) => {
playEffect(AudioActionType.SOUND_ACTIVATE);
const context = container.context;
fetchEsHintMeta({
context,
originMsg: "「[?]」被发动时",
cardID: chaining.code,
});
const context = container.context;
const location = chaining.location;
// 将`location`添加到连锁栈
matStore.chains.push(location);
context.matStore.chains.push(location);
const target = cardStore.find(location);
const target = context.cardStore.find(location);
if (target) {
// 设置连锁序号
const block = context.placeStore.of(context, location);
if (block) {
block.chainIndex.push(matStore.chains.length);
block.chainIndex.push(context.matStore.chains.length);
} else {
console.warn(`<Chaining>block from ${location} is null`);
}
......@@ -45,7 +47,9 @@ export default async (
// 发动效果动画
await callCardFocus(target.uuid);
console.color("blue")(`${target.meta.text.name} chaining`);
console.info(`<Chaining>chain stack length = ${matStore.chains.length}`);
console.info(
`<Chaining>chain stack length = ${context.matStore.chains.length}`,
);
} else {
console.warn(`<Chaining>target from ${location} is null`);
}
......
import { fetchCard, ygopro } from "@/api";
import { Container } from "@/container";
import { sleep } from "@/infra";
import { AudioActionType, playEffect } from "@/infra/audio";
import { cardStore } from "@/stores";
import { callCardFocus, callCardMove } from "@/ui/Duel/PlayMat/Card";
const { MZONE, SZONE } = ygopro.CardZone;
......@@ -10,13 +10,21 @@ const { FACEUP_ATTACK, FACEDOWN_ATTACK, FACEDOWN_DEFENSE, FACEDOWN } =
const WAIT_TIME = 100;
export default async (confirmCards: ygopro.StocGameMessage.MsgConfirmCards) => {
export default async (
container: Container,
confirmCards: ygopro.StocGameMessage.MsgConfirmCards,
) => {
playEffect(AudioActionType.SOUND_REVEAL);
const context = container.context;
const cards = confirmCards.cards;
console.color("pink")(`confirmCards: ${cards}`);
for (const card of cards) {
const target = cardStore.at(card.location, card.controller, card.sequence);
const target = context.cardStore.at(
card.location,
card.controller,
card.sequence,
);
if (target) {
// 设置`occupant`
......
import { fetchCard, ygopro } from "@/api";
import { Container } from "@/container";
import { AudioActionType, playEffect } from "@/infra/audio";
import { cardStore, fetchEsHintMeta } from "@/stores";
import { callCardMove } from "@/ui/Duel/PlayMat/Card";
export default async (draw: ygopro.StocGameMessage.MsgDraw) => {
fetchEsHintMeta({ originMsg: "玩家抽卡时" });
import { fetchEsHintMeta } from "./util";
export default async (
container: Container,
draw: ygopro.StocGameMessage.MsgDraw,
) => {
const context = container.context;
fetchEsHintMeta({ context, originMsg: "玩家抽卡时" });
const drawLength = draw.cards.length;
// 将卡从卡组移到手牌:设置zone、occupant、sequence
const handsLength = cardStore.at(ygopro.CardZone.HAND, draw.player).length;
const newHands = cardStore
const handsLength = context.cardStore.at(
ygopro.CardZone.HAND,
draw.player,
).length;
const newHands = context.cardStore
.at(ygopro.CardZone.DECK, draw.player)
.sort((a, b) => a.location.sequence - b.location.sequence)
.slice(-drawLength);
......@@ -29,7 +38,7 @@ export default async (draw: ygopro.StocGameMessage.MsgDraw) => {
// 抽卡动画
await Promise.all(
cardStore
context.cardStore
.at(ygopro.CardZone.HAND, draw.player)
.map((card) => callCardMove(card.uuid)),
);
......
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (_: ygopro.StocGameMessage.MsgFlipSummoned) => {
fetchEsHintMeta({ originMsg: 1608 });
import { fetchEsHintMeta } from "./util";
export default (
container: Container,
_: ygopro.StocGameMessage.MsgFlipSummoned,
) => {
fetchEsHintMeta({ context: container.context, originMsg: 1608 });
};
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (flipSummoning: ygopro.StocGameMessage.MsgFlipSummoning) => {
import { fetchEsHintMeta } from "./util";
export default (
container: Container,
flipSummoning: ygopro.StocGameMessage.MsgFlipSummoning,
) => {
// playEffect(AudioActionType.SOUND_FILP);
fetchEsHintMeta({
context: container.context,
originMsg: "「[?]」反转召唤宣言时",
cardID: flipSummoning.code,
});
......
......@@ -119,7 +119,7 @@ export default async function handleGameMsg(
break;
}
case "draw": {
await onMsgDraw(msg.draw);
await onMsgDraw(container, msg.draw);
break;
}
......@@ -134,12 +134,12 @@ export default async function handleGameMsg(
break;
}
case "hint": {
await onMsgHint(msg.hint);
await onMsgHint(container, msg.hint);
break;
}
case "select_idle_cmd": {
onMsgSelectIdleCmd(msg.select_idle_cmd);
onMsgSelectIdleCmd(container, msg.select_idle_cmd);
break;
}
......@@ -149,7 +149,7 @@ export default async function handleGameMsg(
break;
}
case "move": {
await onMsgMove(msg.move);
await onMsgMove(container, msg.move);
break;
}
case "select_card": {
......@@ -178,22 +178,22 @@ export default async function handleGameMsg(
break;
}
case "shuffle_hand_extra": {
await onMsgShuffleHandExtra(msg.shuffle_hand_extra);
await onMsgShuffleHandExtra(container, msg.shuffle_hand_extra);
break;
}
case "select_battle_cmd": {
onMsgSelectBattleCmd(msg.select_battle_cmd);
onMsgSelectBattleCmd(container, msg.select_battle_cmd);
break;
}
case "pos_change": {
await onMsgPosChange(msg.pos_change);
await onMsgPosChange(container, msg.pos_change);
break;
}
case "select_unselect_card": {
await onMsgSelectUnselectCard(msg.select_unselect_card);
await onMsgSelectUnselectCard(container, msg.select_unselect_card);
break;
}
......@@ -203,7 +203,7 @@ export default async function handleGameMsg(
break;
}
case "update_hp": {
onMsgUpdateHp(msg.update_hp);
onMsgUpdateHp(container, msg.update_hp);
break;
}
......@@ -213,37 +213,37 @@ export default async function handleGameMsg(
break;
}
case "wait": {
onMsgWait(msg.wait);
onMsgWait(container, msg.wait);
break;
}
case "update_data": {
await onMsgUpdateData(msg.update_data);
await onMsgUpdateData(container, msg.update_data);
break;
}
case "reload_field": {
onMsgReloadField(msg.reload_field);
onMsgReloadField(container, msg.reload_field);
break;
}
case "select_sum": {
onMsgSelectSum(msg.select_sum);
onMsgSelectSum(container, msg.select_sum);
break;
}
case "select_tribute": {
onMsgSelectTribute(msg.select_tribute);
onMsgSelectTribute(container, msg.select_tribute);
break;
}
case "update_counter": {
onMsgUpdateCounter(msg.update_counter);
onMsgUpdateCounter(container, msg.update_counter);
break;
}
case "select_counter": {
await onMsgSelectCounter(msg.select_counter);
await onMsgSelectCounter(container, msg.select_counter);
break;
}
......@@ -253,22 +253,22 @@ export default async function handleGameMsg(
break;
}
case "set": {
onMsgSet(msg.set);
onMsgSet(container, msg.set);
break;
}
case "swap": {
onMsgSwap(msg.swap);
onMsgSwap(container, msg.swap);
break;
}
case "attack": {
await onMsgAttack(msg.attack);
await onMsgAttack(container, msg.attack);
break;
}
case "attack_disable": {
onMsgAttackDisable(msg.attack_disable);
onMsgAttackDisable(container, msg.attack_disable);
break;
}
......@@ -287,32 +287,32 @@ export default async function handleGameMsg(
break;
}
case "summoning": {
onMsgSummoning(msg.summoning);
onMsgSummoning(container, msg.summoning);
break;
}
case "summoned": {
onMsgSummoned(msg.summoned);
onMsgSummoned(container, msg.summoned);
break;
}
case "flip_summoning": {
onMsgFlipSummoning(msg.flip_summoning);
onMsgFlipSummoning(container, msg.flip_summoning);
break;
}
case "flip_summoned": {
onMsgFilpSummoned(msg.flip_summoned);
onMsgFilpSummoned(container, msg.flip_summoned);
break;
}
case "sp_summoning": {
onMsgSpSummoning(msg.sp_summoning);
onMsgSpSummoning(container, msg.sp_summoning);
break;
}
case "sp_summoned": {
onMsgSpSummoned(msg.sp_summoned);
onMsgSpSummoned(container, msg.sp_summoned);
break;
}
......@@ -327,11 +327,11 @@ export default async function handleGameMsg(
break;
}
case "confirm_cards": {
await onConfirmCards(msg.confirm_cards);
await onConfirmCards(container, msg.confirm_cards);
break;
}
case "become_target": {
onMsgBecomeTarget(msg.become_target);
onMsgBecomeTarget(container, msg.become_target);
break;
}
......@@ -341,7 +341,7 @@ export default async function handleGameMsg(
break;
}
case "shuffle_set_card": {
await onMsgShuffleSetCard(msg.shuffle_set_card);
await onMsgShuffleSetCard(container, msg.shuffle_set_card);
break;
}
......@@ -351,7 +351,7 @@ export default async function handleGameMsg(
break;
}
case "shuffle_deck": {
onMsgShuffleDeck(msg.shuffle_deck);
onMsgShuffleDeck(container, msg.shuffle_deck);
break;
}
......@@ -366,7 +366,7 @@ export default async function handleGameMsg(
break;
}
case "swap_grave_deck": {
await onMsgSwapGraveDeck(msg.swap_grave_deck);
await onMsgSwapGraveDeck(container, msg.swap_grave_deck);
break;
}
......
import { ygopro } from "@/api";
import {
fetchCommonHintMeta,
fetchEsHintMeta,
fetchSelectHintMeta,
} from "@/stores";
import { fetchCommonHintMeta, fetchSelectHintMeta } from "@/stores";
import MsgHint = ygopro.StocGameMessage.MsgHint;
import { Container } from "@/container";
export default async (hint: MsgHint) => {
import { fetchEsHintMeta } from "./util";
export default async (container: Container, hint: MsgHint) => {
switch (hint.hint_type) {
case MsgHint.HintType.HINT_EVENT: {
await fetchEsHintMeta({ originMsg: hint.hint_data });
await fetchEsHintMeta({
context: container.context,
originMsg: hint.hint_data,
});
break;
}
case MsgHint.HintType.HINT_MESSAGE: {
......
import { fetchCard, ygopro } from "@/api";
import { Container } from "@/container";
import { AudioActionType, playEffect } from "@/infra/audio";
import { cardStore, CardType } from "@/stores";
import { CardType } from "@/stores";
import { callCardMove } from "@/ui/Duel/PlayMat/Card";
import { REASON_DESTROY, REASON_MATERIAL, TYPE_TOKEN } from "../../common";
......@@ -31,7 +32,8 @@ const overlayStack: ygopro.CardLocation[] = [];
* - 通过`meta.data.type`判断一张卡是否是衍生物。
*
* */
export default async (move: MsgMove) => {
export default async (container: Container, move: MsgMove) => {
const context = container.context;
const code = move.code;
const from = move.from;
const to = move.to;
......@@ -63,7 +65,7 @@ export default async (move: MsgMove) => {
if (from.is_overlay) {
// 超量素材的去除
const overlayMaterial = cardStore.at(
const overlayMaterial = context.cardStore.at(
from.zone,
from.controller,
from.sequence,
......@@ -79,14 +81,18 @@ export default async (move: MsgMove) => {
return;
}
} else {
const card = cardStore.at(from.zone, from.controller, from.sequence);
const card = context.cardStore.at(
from.zone,
from.controller,
from.sequence,
);
if (card) {
target = card;
} else {
console.warn(
`<Move>card from zone=${from.zone}, controller=${from.controller} sequence=${from.sequence} is null`,
);
console.info(cardStore.at(from.zone, from.controller));
console.info(context.cardStore.at(from.zone, from.controller));
return;
}
}
......@@ -105,7 +111,7 @@ export default async (move: MsgMove) => {
// 超量素材出栈
const xyzLocations = overlayStack.splice(0, overlayStack.length);
for (const location of xyzLocations) {
const overlayMaterial = cardStore.at(
const overlayMaterial = context.cardStore.at(
location.zone,
location.controller,
location.sequence,
......@@ -132,8 +138,8 @@ export default async (move: MsgMove) => {
}
// 维护sequence
const fromCards = cardStore.at(from.zone, from.controller);
const toCards = cardStore.at(to.zone, to.controller);
const fromCards = context.cardStore.at(from.zone, from.controller);
const toCards = context.cardStore.at(to.zone, to.controller);
if (
[HAND, GRAVE, REMOVED, DECK, EXTRA, TZONE].includes(from.zone) &&
......@@ -149,7 +155,7 @@ export default async (move: MsgMove) => {
if (from.is_overlay) {
// 超量素材的序号也需要维护
const overlay_sequence = from.overlay_sequence;
for (const overlay of cardStore.findOverlay(
for (const overlay of context.cardStore.findOverlay(
from.zone,
from.controller,
from.sequence,
......@@ -182,7 +188,7 @@ export default async (move: MsgMove) => {
const p = callCardMove(target.uuid, { fromZone: from.zone });
// 如果from或者to是手卡,那么需要刷新除了这张卡之外,这个玩家的所有手卡
if ([from.zone, to.zone].includes(HAND)) {
const pHands = cardStore
const pHands = context.cardStore
.at(HAND, target.location.controller)
.filter((c) => c.uuid !== target.uuid)
.map(async (c) => await callCardMove(c.uuid));
......@@ -193,7 +199,7 @@ export default async (move: MsgMove) => {
// 超量素材位置跟随超量怪兽移动
if (from.zone === MZONE && !from.is_overlay) {
for (const overlay of cardStore.findOverlay(
for (const overlay of context.cardStore.findOverlay(
from.zone,
from.controller,
from.sequence,
......
import { ygopro } from "@/api";
import MsgPosChange = ygopro.StocGameMessage.MsgPosChange;
import { cardStore, fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
import { callCardMove } from "@/ui/Duel/PlayMat/Card";
export default async (posChange: MsgPosChange) => {
import { fetchEsHintMeta } from "./util";
export default async (container: Container, posChange: MsgPosChange) => {
const context = container.context;
const { location, controller, sequence } = posChange.card_info;
const target = cardStore.at(location, controller, sequence);
const target = context.cardStore.at(location, controller, sequence);
if (target) {
target.location.position = posChange.cur_position;
......@@ -17,6 +20,7 @@ export default async (posChange: MsgPosChange) => {
}
fetchEsHintMeta({
context,
originMsg: 1600,
});
};
import { v4 as v4uuid } from "uuid";
import { ygopro } from "@/api";
import { cardStore, matStore } from "@/stores";
import { Container } from "@/container";
import { genCard } from "../utils";
type MsgReloadField = ygopro.StocGameMessage.MsgReloadField;
export default (field: MsgReloadField) => {
export default (container: Container, field: MsgReloadField) => {
const context = container.context;
// 重置
cardStore.reset();
context.cardStore.reset();
const actions = field.actions;
actions.forEach((action) => {
const controller = action.player;
// 更新生命值
matStore.initInfo.of(controller).life = action.lp;
context.matStore.initInfo.of(controller).life = action.lp;
// 更新卡片集合
const cards = action.zone_actions
.map((zoneAction) =>
......@@ -44,6 +45,6 @@ export default (field: MsgReloadField) => {
),
)
.flat();
cardStore.inner.push(...cards);
context.cardStore.inner.push(...cards);
});
};
import { ygopro } from "@/api";
import {
cardStore,
type Interactivity,
InteractType,
matStore,
} from "@/stores";
import { type Interactivity, InteractType } from "@/stores";
import MsgSelectBattleCmd = ygopro.StocGameMessage.MsgSelectBattleCmd;
import { Container } from "@/container";
export default async (selectBattleCmd: MsgSelectBattleCmd) => {
export default async (
container: Container,
selectBattleCmd: MsgSelectBattleCmd,
) => {
const context = container.context;
const player = selectBattleCmd.player;
const cmds = selectBattleCmd.battle_cmds;
// 先清掉之前的互动性
// TODO: 确认这里在AI托管的模式下是否需要
cardStore.inner.forEach((card) => {
context.cardStore.inner.forEach((card) => {
card.idleInteractivities = [];
});
......@@ -33,7 +33,7 @@ export default async (selectBattleCmd: MsgSelectBattleCmd) => {
[InteractType.ATTACK]: { directAttackAble: data.direct_attackable },
};
const tmp = map[interactType]; // 添加额外信息
const target = cardStore.at(location, player, sequence);
const target = context.cardStore.at(location, player, sequence);
if (target) {
target.idleInteractivities.push({
...tmp,
......@@ -50,8 +50,8 @@ export default async (selectBattleCmd: MsgSelectBattleCmd) => {
}
});
});
matStore.phase.enableM2 = selectBattleCmd.enable_m2;
matStore.phase.enableEp = selectBattleCmd.enable_ep;
context.matStore.phase.enableM2 = selectBattleCmd.enable_m2;
context.matStore.phase.enableEp = selectBattleCmd.enable_ep;
};
function battleTypeToInteracType(
......
......@@ -9,6 +9,7 @@ import { fetchCheckCardMeta } from "../utils";
export default async (container: Container, selectCard: MsgSelectCard) => {
const { cancelable, min, max, cards } = selectCard;
const conn = container.conn;
const context = container.context;
// TODO: handle release_param
......@@ -19,6 +20,7 @@ export default async (container: Container, selectCard: MsgSelectCard) => {
}
const { selecteds, mustSelects, selectables } = await fetchCheckCardMeta(
context,
cards,
);
await displaySelectActionsModal({
......
......@@ -8,6 +8,7 @@ import { fetchCheckCardMeta } from "../utils";
type MsgSelectChain = ygopro.StocGameMessage.MsgSelectChain;
export default async (container: Container, selectChain: MsgSelectChain) => {
const conn = container.conn;
const context = container.context;
const spCount = selectChain.special_count;
const forced = selectChain.forced;
const _hint0 = selectChain.hint0;
......@@ -73,6 +74,7 @@ export default async (container: Container, selectChain: MsgSelectChain) => {
selectHintData: 203,
});
const { selecteds, mustSelects, selectables } = await fetchCheckCardMeta(
context,
chains,
);
await displaySelectActionsModal({
......
import { ygopro } from "@/api";
import { cardStore } from "@/stores";
import { Container } from "@/container";
import { displayCheckCounterModal } from "@/ui/Duel/Message";
type MsgSelectCounter = ygopro.StocGameMessage.MsgSelectCounter;
export default async (selectCounter: MsgSelectCounter) => {
export default async (
container: Container,
selectCounter: MsgSelectCounter,
) => {
const context = container.context;
await displayCheckCounterModal({
counterType: selectCounter.counter_type,
min: selectCounter.min,
options: selectCounter.options!.map(({ location, code, counter_count }) => {
const id = cardStore.find(location)?.code;
const id = context.cardStore.find(location)?.code;
const newCode = code ? code : id || 0;
return {
......
import { ygopro } from "@/api";
import {
cardStore,
type Interactivity,
InteractType,
matStore,
} from "@/stores";
import { type Interactivity, InteractType } from "@/stores";
import MsgSelectIdleCmd = ygopro.StocGameMessage.MsgSelectIdleCmd;
import { Container } from "@/container";
export default async (selectIdleCmd: MsgSelectIdleCmd) => {
export default async (
container: Container,
selectIdleCmd: MsgSelectIdleCmd,
) => {
const context = container.context;
const player = selectIdleCmd.player;
const cmds = selectIdleCmd.idle_cmds;
// 先清掉之前的互动性
// TODO: 确认这里是否需要在AI托管的时候调用
cardStore.inner.forEach((card) => {
context.cardStore.inner.forEach((card) => {
card.idleInteractivities = [];
});
......@@ -32,7 +32,7 @@ export default async (selectIdleCmd: MsgSelectIdleCmd) => {
[InteractType.ACTIVATE]: { activateIndex: data.effect_description },
};
const tmp = map[interactType];
const target = cardStore.at(location, player, sequence);
const target = context.cardStore.at(location, player, sequence);
if (target) {
target.idleInteractivities.push({
...tmp,
......@@ -50,8 +50,8 @@ export default async (selectIdleCmd: MsgSelectIdleCmd) => {
});
});
matStore.phase.enableBp = selectIdleCmd.enable_bp;
matStore.phase.enableEp = selectIdleCmd.enable_ep;
context.matStore.phase.enableBp = selectIdleCmd.enable_bp;
context.matStore.phase.enableEp = selectIdleCmd.enable_ep;
};
function idleTypeToInteractType(
......
import { ygopro } from "@/api";
import { Container } from "@/container";
import { displaySelectActionsModal } from "@/ui/Duel/Message/SelectActionsModal";
import { fetchCheckCardMeta } from "../utils";
type MsgSelectSum = ygopro.StocGameMessage.MsgSelectSum;
export default async (selectSum: MsgSelectSum) => {
export default async (container: Container, selectSum: MsgSelectSum) => {
const context = container.context;
const {
selecteds: selecteds1,
mustSelects: mustSelect1,
selectables: selectable1,
} = await fetchCheckCardMeta(selectSum.must_select_cards, false, true);
} = await fetchCheckCardMeta(
context,
selectSum.must_select_cards,
false,
true,
);
const {
selecteds: selecteds2,
mustSelects: mustSelect2,
selectables: selectable2,
} = await fetchCheckCardMeta(selectSum.selectable_cards);
} = await fetchCheckCardMeta(context, selectSum.selectable_cards);
await displaySelectActionsModal({
overflow: selectSum.overflow !== 0,
totalLevels: selectSum.level_sum,
......
import { ygopro } from "@/api";
import { Container } from "@/container";
import { displaySelectActionsModal } from "@/ui/Duel/Message/SelectActionsModal";
import { fetchCheckCardMeta } from "../utils";
type MsgSelectTribute = ygopro.StocGameMessage.MsgSelectTribute;
export default async (selectTribute: MsgSelectTribute) => {
export default async (
container: Container,
selectTribute: MsgSelectTribute,
) => {
const { selecteds, mustSelects, selectables } = await fetchCheckCardMeta(
container.context,
selectTribute.selectable_cards,
);
// TODO: 当玩家选择卡数大于`max`时,是否也合法?
......
import { ygopro } from "@/api";
import { cardStore, matStore } from "@/stores";
import { Container } from "@/container";
import { displaySelectActionsModal } from "@/ui/Duel/Message/SelectActionsModal";
import { fetchCheckCardMeta } from "../utils";
import { isAllOnField } from "./util";
type MsgSelectUnselectCard = ygopro.StocGameMessage.MsgSelectUnselectCard;
export default async (selectUnselectCards: MsgSelectUnselectCard) => {
export default async (
container: Container,
selectUnselectCards: MsgSelectUnselectCard,
) => {
const context = container.context;
const cardStore = context.cardStore;
const matStore = context.matStore;
const {
finishable,
cancelable,
......@@ -48,12 +54,12 @@ export default async (selectUnselectCards: MsgSelectUnselectCard) => {
selecteds: selecteds1,
mustSelects: mustSelect1,
selectables: selectable1,
} = await fetchCheckCardMeta(selectableCards);
} = await fetchCheckCardMeta(context, selectableCards);
const {
selecteds: selecteds2,
mustSelects: mustSelect2,
selectables: selectable2,
} = await fetchCheckCardMeta(selectedCards, true);
} = await fetchCheckCardMeta(context, selectedCards, true);
await displaySelectActionsModal({
finishable,
cancelable,
......
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (_set: ygopro.StocGameMessage.MsgSet) => {
fetchEsHintMeta({ originMsg: 1601 });
import { fetchEsHintMeta } from "./util";
export default (container: Container, _set: ygopro.StocGameMessage.MsgSet) => {
fetchEsHintMeta({ context: container.context, originMsg: 1601 });
};
import { ygopro } from "@/api";
import { Container } from "@/container";
import { AudioActionType, playEffect } from "@/infra/audio";
import { cardStore } from "@/stores";
export default (shuffleDeck: ygopro.StocGameMessage.MsgShuffleDeck) => {
export default (
container: Container,
shuffleDeck: ygopro.StocGameMessage.MsgShuffleDeck,
) => {
const context = container.context;
playEffect(AudioActionType.SOUND_SHUFFLE);
const player = shuffleDeck.player;
for (const card of cardStore.at(ygopro.CardZone.DECK, player)) {
for (const card of context.cardStore.at(ygopro.CardZone.DECK, player)) {
// 把数据抹掉就好了
card.code = 0;
card.meta = { id: 0, data: {}, text: {} };
......
import { ygopro } from "@/api";
import { Container } from "@/container";
import { AudioActionType, playEffect } from "@/infra/audio";
import { cardStore } from "@/stores";
import { callCardMove } from "@/ui/Duel/PlayMat/Card";
type MsgShuffleHandExtra = ygopro.StocGameMessage.MsgShuffleHandExtra;
export default async (shuffleHandExtra: MsgShuffleHandExtra) => {
export default async (
container: Container,
shuffleHandExtra: MsgShuffleHandExtra,
) => {
const context = container.context;
playEffect(AudioActionType.SOUND_SHUFFLE);
const { cards: codes, player: controller, zone } = shuffleHandExtra;
// 本质上是要将手卡/额外卡组的sequence变成和codes一样的顺序
const cards = cardStore.at(zone, controller);
const cards = context.cardStore.at(zone, controller);
const hash = new Map(codes.map((code) => [code, new Array()]));
codes.forEach((code, sequence) => {
hash.get(code)?.push(sequence);
......
import { ygopro } from "@/api";
import { cardStore } from "@/stores";
import { callCardMove } from "@/ui/Duel/PlayMat/Card";
import MsgShuffleSetCard = ygopro.StocGameMessage.MsgShuffleSetCard;
import { Container } from "@/container";
import { AudioActionType, playEffect } from "@/infra/audio";
// 后端传过来的`from_locations`的列表是切洗前场上卡的location,它们在列表里面按照切洗后的顺序排列
export default async (shuffleSetCard: MsgShuffleSetCard) => {
export default async (
container: Container,
shuffleSetCard: MsgShuffleSetCard,
) => {
playEffect(AudioActionType.SOUND_SHUFFLE);
const context = container.context;
const from_locations = shuffleSetCard.from_locations;
const overlay_locations = shuffleSetCard.overlay_locations;
if (from_locations.length === 0) {
......@@ -24,7 +28,11 @@ export default async (shuffleSetCard: MsgShuffleSetCard) => {
Promise.all(
Array.from({ length: count }).map(async (_, i) => {
const from = from_locations[i];
const target = cardStore.at(from.zone, from.controller, from.sequence);
const target = context.cardStore.at(
from.zone,
from.controller,
from.sequence,
);
if (target) {
// 设置code为0,洗切后的code会由`UpdateData`指定
target.code = 0;
......@@ -38,7 +46,7 @@ export default async (shuffleSetCard: MsgShuffleSetCard) => {
const overlay_location = overlay_locations[i];
if (overlay_location.zone > 0) {
// 如果没有超量素材,后端会全传0
for (const overlay of cardStore.findOverlay(
for (const overlay of context.cardStore.findOverlay(
from.zone,
from.controller,
from.sequence,
......
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (_: ygopro.StocGameMessage.MsgSpSummoned) => {
fetchEsHintMeta({ originMsg: 1606 });
import { fetchEsHintMeta } from "./util";
export default (
container: Container,
_: ygopro.StocGameMessage.MsgSpSummoned,
) => {
fetchEsHintMeta({ context: container.context, originMsg: 1606 });
};
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (spSummoning: ygopro.StocGameMessage.MsgSpSummoning) => {
import { fetchEsHintMeta } from "./util";
export default (
container: Container,
spSummoning: ygopro.StocGameMessage.MsgSpSummoning,
) => {
// const card = fetchCard(spSummoning.code);
// if (card.data.type && card.data.type & TYPE_TOKEN) {
// playEffect(AudioActionType.SOUND_TOKEN);
......@@ -9,6 +14,7 @@ export default (spSummoning: ygopro.StocGameMessage.MsgSpSummoning) => {
// playEffect(AudioActionType.SOUND_SPECIAL_SUMMON);
// }
fetchEsHintMeta({
context: container.context,
originMsg: "「[?]」特殊召唤宣言时",
cardID: spSummoning.code,
});
......
......@@ -5,13 +5,7 @@ import { ygopro } from "@/api";
import { useConfig } from "@/config";
import { Container } from "@/container";
import { sleep } from "@/infra";
import {
cardStore,
matStore,
replayStore,
RoomStage,
SideStage,
} from "@/stores";
import { replayStore, RoomStage, SideStage } from "@/stores";
import { replayStart } from "@/ui/Match/ReplayModal";
import { genCard } from "../utils";
......@@ -23,7 +17,7 @@ export default async (
) => {
const context = container.context;
// 先初始化`matStore`
matStore.selfType = start.playerType;
context.matStore.selfType = start.playerType;
if (context.sideStore.stage !== SideStage.NONE) {
// 更新Side状态
......@@ -34,12 +28,12 @@ export default async (
context.roomStore.stage = RoomStage.DUEL_START;
}
matStore.initInfo.set(0, {
context.matStore.initInfo.set(0, {
life: start.life1,
deckSize: start.deckSize1,
extraSize: start.extraSize1,
});
matStore.initInfo.set(1, {
context.matStore.initInfo.set(1, {
life: start.life2,
deckSize: start.deckSize2,
extraSize: start.extraSize2,
......@@ -88,7 +82,7 @@ export default async (
),
);
cardStore.inner.push(...cards);
context.cardStore.inner.push(...cards);
// note: 额外卡组的卡会在对局开始后通过`UpdateData` msg更新
......
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (_: ygopro.StocGameMessage.MsgSummoned) => {
fetchEsHintMeta({ originMsg: 1604 });
import { fetchEsHintMeta } from "./util";
export default (
container: Container,
_: ygopro.StocGameMessage.MsgSummoned,
) => {
fetchEsHintMeta({ context: container.context, originMsg: 1604 });
};
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (summoning: ygopro.StocGameMessage.MsgSummoning) => {
import { fetchEsHintMeta } from "./util";
export default (
container: Container,
summoning: ygopro.StocGameMessage.MsgSummoning,
) => {
/* 因为现在Neos动画架构的问题,这里播放音效的话会滞后于移动动画,
* 因此这里先注释掉,等解决掉上述问题后再加上召唤的音效。
* */
// playEffect(AudioActionType.SOUND_SUMMON);
fetchEsHintMeta({
context: container.context,
originMsg: "「[?]」通常召唤宣言时",
cardID: summoning.code,
});
......
import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/stores";
import { Container } from "@/container";
export default (_swap: ygopro.StocGameMessage.MsgSwap) => {
fetchEsHintMeta({ originMsg: 1602 });
import { fetchEsHintMeta } from "./util";
export default (
container: Container,
_swap: ygopro.StocGameMessage.MsgSwap,
) => {
fetchEsHintMeta({ context: container.context, originMsg: 1602 });
};
import { ygopro } from "@/api";
import { cardStore } from "@/stores";
import { callCardMove } from "@/ui/Duel/PlayMat/Card";
import MsgSwapGraveDeck = ygopro.StocGameMessage.MsgSwapGraveDeck;
import { Container } from "@/container";
const { DECK, GRAVE } = ygopro.CardZone;
export default async (swapGraveDeck: MsgSwapGraveDeck) => {
export default async (
container: Container,
swapGraveDeck: MsgSwapGraveDeck,
) => {
const context = container.context;
const player = swapGraveDeck.player;
const deck = cardStore.at(DECK, player);
const grave = cardStore.at(GRAVE, player);
const deck = context.cardStore.at(DECK, player);
const grave = context.cardStore.at(GRAVE, player);
for (const card of deck) {
card.location.zone = GRAVE;
......
import { ygopro } from "@/api";
import { Container } from "@/container";
import { AudioActionType, playEffect } from "@/infra/audio";
import { cardStore } from "@/stores";
type MsgUpdateCounter = ygopro.StocGameMessage.MsgUpdateCounter;
export default (updateCounter: MsgUpdateCounter) => {
export default (container: Container, updateCounter: MsgUpdateCounter) => {
const context = container.context;
const { location, count, action_type: counterType } = updateCounter;
const target = cardStore.find(location); // 不太确定这个后面能不能相应,我不好说
const target = context.cardStore.find(location); // 不太确定这个后面能不能相应,我不好说
if (target) {
switch (counterType) {
case ygopro.StocGameMessage.MsgUpdateCounter.ActionType.ADD: {
......
import { fetchCard, ygopro } from "@/api";
import { cardStore } from "@/stores";
import { callCardMove } from "@/ui/Duel/PlayMat/Card";
import MsgUpdateData = ygopro.StocGameMessage.MsgUpdateData;
import { TYPE_TOKEN } from "@/common";
import { Container } from "@/container";
export default async (updateData: MsgUpdateData) => {
export default async (container: Container, updateData: MsgUpdateData) => {
const { player: controller, zone, actions } = updateData;
if (controller !== undefined && zone !== undefined && actions !== undefined) {
const field = cardStore.at(zone, controller);
const field = container.context.cardStore.at(zone, controller);
for (const action of actions) {
const sequence = action.location?.sequence;
if (typeof sequence !== "undefined") {
......
import { ygopro } from "@/api";
import { fetchEsHintMeta, matStore } from "@/stores";
import { matStore } from "@/stores";
import MsgUpdateHp = ygopro.StocGameMessage.MsgUpdateHp;
import { Container } from "@/container";
import { AudioActionType, changeScene, playEffect } from "@/infra/audio";
export default (msgUpdateHp: MsgUpdateHp) => {
import { fetchEsHintMeta } from "./util";
export default (container: Container, msgUpdateHp: MsgUpdateHp) => {
const context = container.context;
if (msgUpdateHp.type_ === MsgUpdateHp.ActionType.DAMAGE) {
playEffect(AudioActionType.SOUND_DAMAGE);
fetchEsHintMeta({ originMsg: "玩家收到伤害时" }); // TODO: i18n
fetchEsHintMeta({ context, originMsg: "玩家收到伤害时" }); // TODO: i18n
matStore.initInfo.of(msgUpdateHp.player).life -= msgUpdateHp.value;
} else if (msgUpdateHp.type_ === MsgUpdateHp.ActionType.RECOVER) {
playEffect(AudioActionType.SOUND_RECOVER);
fetchEsHintMeta({ originMsg: "玩家生命值回复时" }); // TODO: i18n
fetchEsHintMeta({ context, originMsg: "玩家生命值回复时" }); // TODO: i18n
matStore.initInfo.of(msgUpdateHp.player).life += msgUpdateHp.value;
}
if (matStore.initInfo.me.life > matStore.initInfo.op.life * 2) {
......
import { ygopro } from "@/api";
const { MZONE, SZONE, HAND } = ygopro.CardZone;
import { fetchStrings } from "@/api";
import { Region } from "@/api";
import { fetchCard } from "@/api/cards";
import { Context } from "@/container";
export function isAllOnField(locations: ygopro.CardLocation[]): boolean {
const isOnField = (location: ygopro.CardLocation) => {
......@@ -53,3 +57,41 @@ export function argmax<T>(arr: T[], getValue: (item: T) => number): number {
return maxIndex;
}
export const fetchEsHintMeta = async ({
context,
originMsg,
location,
cardID,
}: {
context: Context;
originMsg: string | number;
location?: ygopro.CardLocation;
cardID?: number;
}) => {
const newOriginMsg =
typeof originMsg === "string"
? originMsg
: fetchStrings(Region.System, originMsg);
const cardMeta = cardID ? fetchCard(cardID) : undefined;
let esHint = newOriginMsg;
if (cardMeta?.text.name) {
esHint = esHint.replace("[?]", cardMeta.text.name);
}
if (location) {
const fieldMeta = context.cardStore.at(
location.zone,
location.controller,
location.sequence,
);
if (fieldMeta?.meta.text.name) {
esHint = esHint.replace("[?]", fieldMeta.meta.text.name);
}
}
context.matStore.hint.esHint = esHint;
};
import { ygopro } from "@/api";
import { cardStore } from "@/stores";
import { Container } from "@/container";
import { showWaiting } from "@/ui/Duel/Message";
export default (_wait: ygopro.StocGameMessage.MsgWait) => {
for (const card of cardStore.inner) {
export default (
container: Container,
_wait: ygopro.StocGameMessage.MsgWait,
) => {
for (const card of container.context.cardStore.inner) {
card.idleInteractivities = [];
}
showWaiting(true);
......
import type { ygopro } from "@/api";
import { fetchCard, getCardStr } from "@/api/cards";
import { cardStore } from "@/stores";
import { Context } from "@/container";
import type { Option } from "@/ui/Duel/Message";
const helper = async (
context: Context,
{
code,
location,
......@@ -26,7 +27,7 @@ const helper = async (
mustSelect?: boolean,
) => {
const { controller, zone, sequence } = location;
const target = cardStore.at(zone, controller, sequence);
const target = context.cardStore.at(zone, controller, sequence);
// 这里可能直接用target.meta即可,不用再查一遍DB
// 但是ygopro后端传回来了code,感觉这里会有些坑,因此求稳这样写
......@@ -63,6 +64,7 @@ const helper = async (
};
export const fetchCheckCardMeta = async (
context: Context,
cards: {
code: number;
location: ygopro.CardLocation;
......@@ -79,6 +81,7 @@ export const fetchCheckCardMeta = async (
const selectables: Option[] = [];
for (const card of cards) {
await helper(
context,
card,
selecteds,
mustSelects,
......
......@@ -94,6 +94,3 @@ export class CardStore implements NeosStore {
}
export const cardStore = proxy(new CardStore());
// @ts-ignore
window.cardStore = cardStore;
import { Region, type ygopro } from "@/api";
import { Region } from "@/api";
import { DESCRIPTION_LIMIT, fetchStrings, getStrings } from "@/api";
import { fetchCard } from "@/api/cards";
import { cardStore } from "@/stores/cardStore";
import { matStore } from "../store";
......@@ -38,39 +37,3 @@ export const fetchSelectHintMeta = ({
matStore.hint.esHint = esHint;
}
};
export const fetchEsHintMeta = async ({
originMsg,
location,
cardID,
}: {
originMsg: string | number;
location?: ygopro.CardLocation;
cardID?: number;
}) => {
const newOriginMsg =
typeof originMsg === "string"
? originMsg
: fetchStrings(Region.System, originMsg);
const cardMeta = cardID ? fetchCard(cardID) : undefined;
let esHint = newOriginMsg;
if (cardMeta?.text.name) {
esHint = esHint.replace("[?]", cardMeta.text.name);
}
if (location) {
const fieldMeta = cardStore.at(
location.zone,
location.controller,
location.sequence,
);
if (fieldMeta?.meta.text.name) {
esHint = esHint.replace("[?]", fieldMeta.meta.text.name);
}
}
matStore.hint.esHint = esHint;
};
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