Commit c77fde8c authored by timel's avatar timel

feat: valtio store logic 70%

parent 6f35a67e
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
"antd": "^5.4.0", "antd": "^5.4.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"google-protobuf": "^3.21.2", "google-protobuf": "^3.21.2",
"lodash-es": "^4.17.21",
"react": "^18.2.0", "react": "^18.2.0",
"react-babylonjs": "^3.1.15", "react-babylonjs": "^3.1.15",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
...@@ -45,6 +46,7 @@ ...@@ -45,6 +46,7 @@
"@babylonjs/core": "^5.54.0", "@babylonjs/core": "^5.54.0",
"@babylonjs/gui": "^5.54.0", "@babylonjs/gui": "^5.54.0",
"@types/google-protobuf": "^3.15.6", "@types/google-protobuf": "^3.15.6",
"@types/lodash-es": "^4.17.7",
"@typescript-eslint/eslint-plugin": "^5.57.1", "@typescript-eslint/eslint-plugin": "^5.57.1",
"@typescript-eslint/parser": "^5.57.1", "@typescript-eslint/parser": "^5.57.1",
"@vitejs/plugin-react": "^3.1.0", "@vitejs/plugin-react": "^3.1.0",
...@@ -3656,6 +3658,21 @@ ...@@ -3656,6 +3658,21 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true "dev": true
}, },
"node_modules/@types/lodash": {
"version": "4.14.194",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz",
"integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==",
"dev": true
},
"node_modules/@types/lodash-es": {
"version": "4.17.7",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.7.tgz",
"integrity": "sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==",
"dev": true,
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "16.18.23", "version": "16.18.23",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.23.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.23.tgz",
...@@ -15348,6 +15365,11 @@ ...@@ -15348,6 +15365,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash._reinterpolate": { "node_modules/lodash._reinterpolate": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
...@@ -31242,6 +31264,21 @@ ...@@ -31242,6 +31264,21 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"dev": true "dev": true
}, },
"@types/lodash": {
"version": "4.14.194",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz",
"integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==",
"dev": true
},
"@types/lodash-es": {
"version": "4.17.7",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.7.tgz",
"integrity": "sha512-z0ptr6UI10VlU6l5MYhGwS4mC8DZyYer2mCoyysZtSF7p26zOX8UpbrV0YpNYLGS8K4PUFIyEr62IMFFjveSiQ==",
"dev": true,
"requires": {
"@types/lodash": "*"
}
},
"@types/node": { "@types/node": {
"version": "16.18.23", "version": "16.18.23",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.23.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.23.tgz",
...@@ -40451,6 +40488,11 @@ ...@@ -40451,6 +40488,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"lodash._reinterpolate": { "lodash._reinterpolate": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
import { ygopro } from "@/api"; import { ygopro, fetchCard, getCardStr } from "@/api";
import { setOptionModalIsOpen } from "@/reducers/duel/mod"; import { setOptionModalIsOpen } from "@/reducers/duel/mod";
import { fetchOptionMeta } from "@/reducers/duel/modal/mod"; import { fetchOptionMeta } from "@/reducers/duel/modal/mod";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import MsgSelectOption = ygopro.StocGameMessage.MsgSelectOption; import MsgSelectOption = ygopro.StocGameMessage.MsgSelectOption;
import { messageStore } from "@/valtioStores";
export default (selectOption: MsgSelectOption, dispatch: AppDispatch) => { export default async (selectOption: MsgSelectOption, dispatch: AppDispatch) => {
const player = selectOption.player; const player = selectOption.player;
const options = selectOption.options; const options = selectOption.options;
...@@ -13,4 +14,15 @@ export default (selectOption: MsgSelectOption, dispatch: AppDispatch) => { ...@@ -13,4 +14,15 @@ export default (selectOption: MsgSelectOption, dispatch: AppDispatch) => {
} }
dispatch(setOptionModalIsOpen(true)); dispatch(setOptionModalIsOpen(true));
await Promise.all(
options.map(async ({ code, response }) => {
const meta = await fetchCard(code >> 4);
const msg = getCardStr(meta, code & 0xf) || "[?]";
const newResponse = { msg, response };
messageStore.optionModal.options.push(newResponse);
})
);
messageStore.optionModal.isOpen = true;
}; };
...@@ -4,7 +4,7 @@ import { ...@@ -4,7 +4,7 @@ import {
setPositionModalPositions, setPositionModalPositions,
} from "@/reducers/duel/mod"; } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { matStore } from "@/valtioStores"; import { messageStore } from "@/valtioStores";
type MsgSelectPosition = ygopro.StocGameMessage.MsgSelectPosition; type MsgSelectPosition = ygopro.StocGameMessage.MsgSelectPosition;
...@@ -17,4 +17,9 @@ export default (selectPosition: MsgSelectPosition, dispatch: AppDispatch) => { ...@@ -17,4 +17,9 @@ export default (selectPosition: MsgSelectPosition, dispatch: AppDispatch) => {
); );
dispatch(setPositionModalIsOpen(true)); dispatch(setPositionModalIsOpen(true));
messageStore.positionModal.positions = positions.map(
(position) => position.position
);
messageStore.positionModal.isOpen = true;
}; };
...@@ -7,25 +7,43 @@ import { ...@@ -7,25 +7,43 @@ import {
} from "@/reducers/duel/mod"; } from "@/reducers/duel/mod";
import { fetchCheckCardMetasV3 } from "@/reducers/duel/modal/checkCardModalV3Slice"; import { fetchCheckCardMetasV3 } from "@/reducers/duel/modal/checkCardModalV3Slice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import MsgSelectSum = ygopro.StocGameMessage.MsgSelectSum; import {
messageStore,
fetchCheckCardMetasV3 as FIXME_fetchCheckCardMetasV3,
} from "@/valtioStores";
type MsgSelectSum = ygopro.StocGameMessage.MsgSelectSum;
export default (selectSum: MsgSelectSum, dispatch: AppDispatch) => { export default (selectSum: MsgSelectSum, dispatch: AppDispatch) => {
dispatch(setCheckCardModalV3OverFlow(selectSum.overflow != 0)); dispatch(setCheckCardModalV3OverFlow(selectSum.overflow != 0));
messageStore.checkCardModalV3.overflow = selectSum.overflow != 0;
dispatch(setCheckCardModalV3AllLevel(selectSum.level_sum)); dispatch(setCheckCardModalV3AllLevel(selectSum.level_sum));
messageStore.checkCardModalV3.allLevel = selectSum.level_sum;
dispatch( dispatch(
setCheckCardModalV3MinMax({ min: selectSum.min, max: selectSum.max }) setCheckCardModalV3MinMax({ min: selectSum.min, max: selectSum.max })
); );
messageStore.checkCardModalV3.selectMin = selectSum.min;
messageStore.checkCardModalV3.selectMax = selectSum.max;
dispatch( dispatch(
fetchCheckCardMetasV3({ fetchCheckCardMetasV3({
mustSelect: true, mustSelect: true,
options: selectSum.must_select_cards, options: selectSum.must_select_cards,
}) })
); );
FIXME_fetchCheckCardMetasV3({
mustSelect: true,
options: selectSum.must_select_cards,
});
dispatch( dispatch(
fetchCheckCardMetasV3({ fetchCheckCardMetasV3({
mustSelect: false, mustSelect: false,
options: selectSum.selectable_cards, options: selectSum.selectable_cards,
}) })
); );
FIXME_fetchCheckCardMetasV3({
mustSelect: false,
options: selectSum.selectable_cards,
});
dispatch(setCheckCardModalV3IsOpen(true)); dispatch(setCheckCardModalV3IsOpen(true));
messageStore.checkCardModalV3.isOpen = true;
}; };
...@@ -7,18 +7,28 @@ import { ...@@ -7,18 +7,28 @@ import {
} from "@/reducers/duel/mod"; } from "@/reducers/duel/mod";
import { fetchCheckCardMetasV3 } from "@/reducers/duel/modal/checkCardModalV3Slice"; import { fetchCheckCardMetasV3 } from "@/reducers/duel/modal/checkCardModalV3Slice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import MsgSelectTribute = ygopro.StocGameMessage.MsgSelectTribute;
import {
messageStore,
fetchCheckCardMetasV3 as FIXME_fetchCheckCardMetasV3,
} from "@/valtioStores";
type MsgSelectTribute = ygopro.StocGameMessage.MsgSelectTribute;
export default (selectTribute: MsgSelectTribute, dispatch: AppDispatch) => { export default (selectTribute: MsgSelectTribute, dispatch: AppDispatch) => {
// TODO: 当玩家选择卡数大于`max`时,是否也合法? // TODO: 当玩家选择卡数大于`max`时,是否也合法?
dispatch(setCheckCardModalV3OverFlow(true)); dispatch(setCheckCardModalV3OverFlow(true));
messageStore.checkCardModalV3.overflow = true;
dispatch(setCheckCardModalV3AllLevel(0)); dispatch(setCheckCardModalV3AllLevel(0));
messageStore.checkCardModalV3.allLevel = 0;
dispatch( dispatch(
setCheckCardModalV3MinMax({ setCheckCardModalV3MinMax({
min: selectTribute.min, min: selectTribute.min,
max: selectTribute.max, max: selectTribute.max,
}) })
); );
messageStore.checkCardModalV3.selectMin = selectTribute.min;
messageStore.checkCardModalV3.selectMax = selectTribute.max;
dispatch( dispatch(
fetchCheckCardMetasV3({ fetchCheckCardMetasV3({
mustSelect: false, mustSelect: false,
...@@ -33,5 +43,18 @@ export default (selectTribute: MsgSelectTribute, dispatch: AppDispatch) => { ...@@ -33,5 +43,18 @@ export default (selectTribute: MsgSelectTribute, dispatch: AppDispatch) => {
}), }),
}) })
); );
FIXME_fetchCheckCardMetasV3({
mustSelect: false,
options: selectTribute.selectable_cards.map((card) => {
return {
code: card.code,
location: card.location,
level1: card.level,
level2: card.level,
response: card.response,
};
}),
});
dispatch(setCheckCardModalV3IsOpen(true)); dispatch(setCheckCardModalV3IsOpen(true));
messageStore.checkCardModalV3.isOpen = true;
}; };
...@@ -8,24 +8,36 @@ import { ...@@ -8,24 +8,36 @@ import {
} from "@/reducers/duel/mod"; } from "@/reducers/duel/mod";
import { fetchCheckCardMetasV2 } from "@/reducers/duel/modal/checkCardModalV2Slice"; import { fetchCheckCardMetasV2 } from "@/reducers/duel/modal/checkCardModalV2Slice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import MsgSelectUnselectCard = ygopro.StocGameMessage.MsgSelectUnselectCard;
import {
messageStore,
fetchCheckCardMetasV2 as FIXME_fetchCheckCardMetasV2,
} from "@/valtioStores";
type MsgSelectUnselectCard = ygopro.StocGameMessage.MsgSelectUnselectCard;
export default ( export default (
selectUnselectCard: MsgSelectUnselectCard, {
finishable,
cancelable,
min,
max,
selectable_cards: selectableCards,
selected_cards: selectedCards,
}: MsgSelectUnselectCard,
dispatch: AppDispatch dispatch: AppDispatch
) => { ) => {
const finishable = selectUnselectCard.finishable;
const cancelable = selectUnselectCard.cancelable;
const min = selectUnselectCard.min;
const max = selectUnselectCard.max;
const selectableCards = selectUnselectCard.selectable_cards;
const selectedCards = selectUnselectCard.selected_cards;
dispatch(setCheckCardModalV2IsOpen(true)); dispatch(setCheckCardModalV2IsOpen(true));
dispatch(setCheckCardModalV2FinishAble(finishable)); dispatch(setCheckCardModalV2FinishAble(finishable));
dispatch(setCheckCardModalV2CancelAble(cancelable)); dispatch(setCheckCardModalV2CancelAble(cancelable));
dispatch(setCheckCardModalV2MinMax({ min, max })); dispatch(setCheckCardModalV2MinMax({ min, max }));
messageStore.checkCardModalV2.isOpen = true;
messageStore.checkCardModalV2.finishAble = finishable;
messageStore.checkCardModalV2.cancelAble = cancelable;
messageStore.checkCardModalV2.selectMin = min;
messageStore.checkCardModalV2.selectMax = max;
dispatch( dispatch(
fetchCheckCardMetasV2({ fetchCheckCardMetasV2({
selected: false, selected: false,
...@@ -39,6 +51,17 @@ export default ( ...@@ -39,6 +51,17 @@ export default (
}) })
); );
FIXME_fetchCheckCardMetasV2({
selected: false,
options: selectableCards.map((card) => {
return {
code: card.code,
location: card.location,
response: card.response,
};
}),
});
dispatch( dispatch(
fetchCheckCardMetasV2({ fetchCheckCardMetasV2({
selected: true, selected: true,
...@@ -52,5 +75,18 @@ export default ( ...@@ -52,5 +75,18 @@ export default (
}) })
); );
FIXME_fetchCheckCardMetasV2({
selected: true,
options: selectedCards.map((card) => {
return {
code: card.code,
location: card.location,
response: card.response,
};
}),
});
dispatch(setCheckCardModalV2ResponseAble(true)); dispatch(setCheckCardModalV2ResponseAble(true));
messageStore.checkCardModalV2.responseable = true;
}; };
...@@ -2,6 +2,9 @@ import { ygopro } from "@/api"; ...@@ -2,6 +2,9 @@ import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default (_set: ygopro.StocGameMessage.MsgSet, dispatch: AppDispatch) => { export default (_set: ygopro.StocGameMessage.MsgSet, dispatch: AppDispatch) => {
dispatch(fetchEsHintMeta({ originMsg: 1601 })); dispatch(fetchEsHintMeta({ originMsg: 1601 }));
FIXME_fetchEsHintMeta({ originMsg: 1601 });
}; };
...@@ -2,9 +2,12 @@ import { ygopro } from "@/api"; ...@@ -2,9 +2,12 @@ import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (
_: ygopro.StocGameMessage.MsgSpSummoned, _: ygopro.StocGameMessage.MsgSpSummoned,
dispatch: AppDispatch dispatch: AppDispatch
) => { ) => {
dispatch(fetchEsHintMeta({ originMsg: 1606 })); dispatch(fetchEsHintMeta({ originMsg: 1606 }));
FIXME_fetchEsHintMeta({ originMsg: 1606 });
}; };
...@@ -2,6 +2,7 @@ import { ygopro } from "@/api"; ...@@ -2,6 +2,7 @@ import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (
spSummoning: ygopro.StocGameMessage.MsgSpSummoning, spSummoning: ygopro.StocGameMessage.MsgSpSummoning,
dispatch: AppDispatch dispatch: AppDispatch
...@@ -12,4 +13,8 @@ export default ( ...@@ -12,4 +13,8 @@ export default (
cardID: spSummoning.code, cardID: spSummoning.code,
}) })
); );
FIXME_fetchEsHintMeta({
originMsg: "「[?]」特殊召唤宣言时",
cardID: spSummoning.code,
});
}; };
...@@ -2,9 +2,12 @@ import { ygopro } from "@/api"; ...@@ -2,9 +2,12 @@ import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (
_: ygopro.StocGameMessage.MsgSummoned, _: ygopro.StocGameMessage.MsgSummoned,
dispatch: AppDispatch dispatch: AppDispatch
) => { ) => {
dispatch(fetchEsHintMeta({ originMsg: 1604 })); dispatch(fetchEsHintMeta({ originMsg: 1604 }));
FIXME_fetchEsHintMeta({ originMsg: 1604 });
}; };
...@@ -2,6 +2,8 @@ import { ygopro } from "@/api"; ...@@ -2,6 +2,8 @@ import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (
summoning: ygopro.StocGameMessage.MsgSummoning, summoning: ygopro.StocGameMessage.MsgSummoning,
dispatch: AppDispatch dispatch: AppDispatch
...@@ -12,4 +14,8 @@ export default ( ...@@ -12,4 +14,8 @@ export default (
cardID: summoning.code, cardID: summoning.code,
}) })
); );
FIXME_fetchEsHintMeta({
originMsg: "「[?]」通常召唤宣言时",
cardID: summoning.code,
});
}; };
...@@ -2,9 +2,12 @@ import { ygopro } from "@/api"; ...@@ -2,9 +2,12 @@ import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { fetchEsHintMeta as FIXME_fetchEsHintMeta } from "@/valtioStores";
export default ( export default (
_swap: ygopro.StocGameMessage.MsgSwap, _swap: ygopro.StocGameMessage.MsgSwap,
dispatch: AppDispatch dispatch: AppDispatch
) => { ) => {
dispatch(fetchEsHintMeta({ originMsg: 1602 })); dispatch(fetchEsHintMeta({ originMsg: 1602 }));
FIXME_fetchEsHintMeta({ originMsg: 1602 });
}; };
...@@ -3,9 +3,14 @@ import { sendTimeConfirm } from "@/api/ocgcore/ocgHelper"; ...@@ -3,9 +3,14 @@ import { sendTimeConfirm } from "@/api/ocgcore/ocgHelper";
import { updateTimeLimit } from "@/reducers/duel/mod"; import { updateTimeLimit } from "@/reducers/duel/mod";
import { store } from "@/store"; import { store } from "@/store";
import { matStore } from "@/valtioStores";
export default function handleTimeLimit(timeLimit: ygopro.StocTimeLimit) { export default function handleTimeLimit(timeLimit: ygopro.StocTimeLimit) {
const dispatch = store.dispatch; const dispatch = store.dispatch;
dispatch(updateTimeLimit([timeLimit.player, timeLimit.left_time])); dispatch(updateTimeLimit([timeLimit.player, timeLimit.left_time]));
matStore.timeLimits.set(timeLimit.player, timeLimit.left_time);
sendTimeConfirm(); sendTimeConfirm();
} }
...@@ -3,6 +3,8 @@ import { useConfig } from "@/config"; ...@@ -3,6 +3,8 @@ import { useConfig } from "@/config";
import { setUnimplemented } from "@/reducers/duel/mod"; import { setUnimplemented } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { matStore } from "@/valtioStores";
const NeosConfig = useConfig(); const NeosConfig = useConfig();
export default ( export default (
...@@ -11,5 +13,6 @@ export default ( ...@@ -11,5 +13,6 @@ export default (
) => { ) => {
if (!NeosConfig.unimplementedWhiteList.includes(unimplemented.command)) { if (!NeosConfig.unimplementedWhiteList.includes(unimplemented.command)) {
dispatch(setUnimplemented(unimplemented.command)); dispatch(setUnimplemented(unimplemented.command));
matStore.unimplemented = unimplemented.command;
} }
}; };
import { ygopro } from "@/api"; import { ygopro } from "@/api";
import { updateMonsterCounters } from "@/reducers/duel/mod"; import { updateMonsterCounters } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import MsgUpdateCounter = ygopro.StocGameMessage.MsgUpdateCounter;
import { getCardByLocation } from "@/valtioStores";
type MsgUpdateCounter = ygopro.StocGameMessage.MsgUpdateCounter;
export default (updateCounter: MsgUpdateCounter, dispatch: AppDispatch) => { export default (updateCounter: MsgUpdateCounter, dispatch: AppDispatch) => {
dispatch(updateMonsterCounters(updateCounter.toObject())); dispatch(updateMonsterCounters(updateCounter.toObject()));
const { location, count, action_type: counterType } = updateCounter;
const target = getCardByLocation(location); // 不太确定这个后面能不能相应,我不好说
if (target) {
switch (counterType) {
case ygopro.StocGameMessage.MsgUpdateCounter.ActionType.ADD: {
if (counterType in target.counters) {
target.counters[counterType] += count;
} else {
target.counters[counterType] = count;
}
break;
}
case ygopro.StocGameMessage.MsgUpdateCounter.ActionType.REMOVE: {
if (counterType in target.counters) {
target.counters[counterType] -= count;
}
break;
}
default: {
break;
}
}
}
}; };
...@@ -2,14 +2,22 @@ import { ygopro } from "@/api"; ...@@ -2,14 +2,22 @@ import { ygopro } from "@/api";
import { fetchEsHintMeta } from "@/reducers/duel/hintSlice"; import { fetchEsHintMeta } from "@/reducers/duel/hintSlice";
import { updateHp } from "@/reducers/duel/mod"; import { updateHp } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import {
fetchEsHintMeta as FIXME_fetchEsHintMeta,
matStore,
} from "@/valtioStores";
import MsgUpdateHp = ygopro.StocGameMessage.MsgUpdateHp; import MsgUpdateHp = ygopro.StocGameMessage.MsgUpdateHp;
export default (msgUpdateHp: MsgUpdateHp, dispatch: AppDispatch) => { export default (msgUpdateHp: MsgUpdateHp, dispatch: AppDispatch) => {
if (msgUpdateHp.type_ == MsgUpdateHp.ActionType.DAMAGE) { if (msgUpdateHp.type_ == MsgUpdateHp.ActionType.DAMAGE) {
dispatch(fetchEsHintMeta({ originMsg: "玩家收到伤害时" })); // TODO: i18n dispatch(fetchEsHintMeta({ originMsg: "玩家收到伤害时" })); // TODO: i18n
FIXME_fetchEsHintMeta({ originMsg: "玩家收到伤害时" });
matStore.initInfo.at(msgUpdateHp.player).life -= msgUpdateHp.value;
} else if (msgUpdateHp.type_ == MsgUpdateHp.ActionType.RECOVER) { } else if (msgUpdateHp.type_ == MsgUpdateHp.ActionType.RECOVER) {
dispatch(fetchEsHintMeta({ originMsg: "玩家生命值回复时" })); // TODO: i18n dispatch(fetchEsHintMeta({ originMsg: "玩家生命值回复时" })); // TODO: i18n
FIXME_fetchEsHintMeta({ originMsg: "玩家生命值回复时" });
matStore.initInfo.at(msgUpdateHp.player).life += msgUpdateHp.value;
} }
dispatch(updateHp(msgUpdateHp)); dispatch(updateHp(msgUpdateHp)); // 可以删除了
}; };
...@@ -2,6 +2,11 @@ import { ygopro } from "@/api"; ...@@ -2,6 +2,11 @@ import { ygopro } from "@/api";
import { clearAllIdleInteractivities, setWaiting } from "@/reducers/duel/mod"; import { clearAllIdleInteractivities, setWaiting } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import {
matStore,
clearAllIdleInteractivities as FIXME_clearAllIdleInteractivities,
} from "@/valtioStores";
export default ( export default (
_wait: ygopro.StocGameMessage.MsgWait, _wait: ygopro.StocGameMessage.MsgWait,
dispatch: AppDispatch dispatch: AppDispatch
...@@ -9,4 +14,8 @@ export default ( ...@@ -9,4 +14,8 @@ export default (
dispatch(clearAllIdleInteractivities(0)); dispatch(clearAllIdleInteractivities(0));
dispatch(clearAllIdleInteractivities(1)); dispatch(clearAllIdleInteractivities(1));
dispatch(setWaiting(true)); dispatch(setWaiting(true));
FIXME_clearAllIdleInteractivities(0);
FIXME_clearAllIdleInteractivities(1);
matStore.waiting = true;
}; };
...@@ -2,6 +2,9 @@ import { ygopro } from "@/api"; ...@@ -2,6 +2,9 @@ import { ygopro } from "@/api";
import { setResult } from "@/reducers/duel/mod"; import { setResult } from "@/reducers/duel/mod";
import { AppDispatch } from "@/store"; import { AppDispatch } from "@/store";
import { matStore } from "@/valtioStores";
export default (win: ygopro.StocGameMessage.MsgWin, dispatch: AppDispatch) => { export default (win: ygopro.StocGameMessage.MsgWin, dispatch: AppDispatch) => {
dispatch(setResult(win.type_)); dispatch(setResult(win.type_));
matStore.result = win.type_;
}; };
import { proxy } from "valtio"; import { proxy } from "valtio";
import { cloneDeep } from "lodash-es";
import { fetchCard } from "@/api/cards"; import { fetchCard } from "@/api/cards";
import { ygopro } from "@/api"; import { ygopro } from "@/api";
...@@ -38,48 +38,36 @@ const isMe = (player: number): boolean => { ...@@ -38,48 +38,36 @@ const isMe = (player: number): boolean => {
} }
}; };
const genDuel = <T>(obj: T) => {
const res = proxy({
me: cloneDeep(obj),
op: cloneDeep(obj),
at: (controller: number) => res[getWhom(controller)],
});
return res;
};
/** /**
* 生成一个指定长度的卡片数组 * 生成一个指定长度的卡片数组
*/ */
const genBlock = ( const genBlock = (location: ygopro.CardZone, n: number): DuelFieldState =>
location: ygopro.CardZone, Array(n)
n: number .fill(null)
): BothSide<DuelFieldState> => { .map((_) => ({
return { location: {
me: Array(n) location,
.fill(null) },
.map((_) => ({ idleInteractivities: [],
location: { counters: {},
location, }));
},
idleInteractivities: [],
counters: {},
})),
op: Array(n)
.fill(null)
.map((_) => ({
location: {
location,
},
idleInteractivities: [],
counters: {},
})),
};
};
const initInfo: MatState["initInfo"] = proxy({ const initInfo: MatState["initInfo"] = proxy({
me: { ...genDuel({
masterRule: "UNKNOWN", masterRule: "UNKNOWN",
life: -1, // 特地设置一个不可能的值 life: -1, // 特地设置一个不可能的值
deckSize: 0, deckSize: 0,
extraSize: 0, extraSize: 0,
}, }),
op: {
masterRule: "UNKNOWN",
life: -1, // 特地设置一个不可能的值
deckSize: 0,
extraSize: 0,
},
set: (controller: number, obj: Partial<InitInfo>) => { set: (controller: number, obj: Partial<InitInfo>) => {
initInfo[getWhom(controller)] = { initInfo[getWhom(controller)] = {
...initInfo[getWhom(controller)], ...initInfo[getWhom(controller)],
...@@ -116,25 +104,18 @@ const wrap = <T extends DuelFieldState>( ...@@ -116,25 +104,18 @@ const wrap = <T extends DuelFieldState>(
const res: CardsBothSide<T> = proxy({ const res: CardsBothSide<T> = proxy({
...entity, ...entity,
at: (controller: number) => {
return res[getWhom(controller)];
},
remove: (controller: number, sequence: number) => { remove: (controller: number, sequence: number) => {
res[getWhom(controller)].splice(sequence, 1); res.at(controller).splice(sequence, 1);
}, },
insert: async (controller: number, sequence: number, id: number) => { insert: async (controller: number, sequence: number, id: number) => {
const card = await genCard(controller, id); const card = await genCard(controller, id);
res[getWhom(controller)].splice(sequence, 0, card); res.at(controller).splice(sequence, 0, card);
}, },
add: async (controller: number, ids: number[]) => { add: async (controller: number, ids: number[]) => {
const cards = await Promise.all( const cards = await Promise.all(
ids.map(async (id) => genCard(controller, id)) ids.map(async (id) => genCard(controller, id))
); );
res[getWhom(controller)].splice( res.at(controller).splice(res.at(controller).length, 0, ...cards);
res[getWhom(controller)].length,
0,
...cards
);
}, },
setOccupant: async ( setOccupant: async (
controller: number, controller: number,
...@@ -143,33 +124,31 @@ const wrap = <T extends DuelFieldState>( ...@@ -143,33 +124,31 @@ const wrap = <T extends DuelFieldState>(
position?: ygopro.CardPosition position?: ygopro.CardPosition
) => { ) => {
const meta = await fetchCard(id); const meta = await fetchCard(id);
const target = res[getWhom(controller)][sequence]; const target = res.at(controller)[sequence];
target.occupant = meta; target.occupant = meta;
if (position) { if (position) {
target.location.position = position; target.location.position = position;
} }
}, },
removeOccupant: (controller: number, sequence: number) => { removeOccupant: (controller: number, sequence: number) => {
res[getWhom(controller)][sequence].occupant = undefined; res.at(controller)[sequence].occupant = undefined;
}, },
addIdleInteractivity: ( addIdleInteractivity: (
controller: number, controller: number,
sequence: number, sequence: number,
interactivity: CardState["idleInteractivities"][number] interactivity: CardState["idleInteractivities"][number]
) => { ) => {
res[getWhom(controller)][sequence].idleInteractivities.push( res.at(controller)[sequence].idleInteractivities.push(interactivity);
interactivity
);
}, },
clearIdleInteractivities: (controller: number, sequence: number) => { clearIdleInteractivities: (controller: number) => {
res[getWhom(controller)][sequence].idleInteractivities = []; res.at(controller).forEach((card) => (card.idleInteractivities = []));
}, },
setPlaceInteractivityType: ( setPlaceInteractivityType: (
controller: number, controller: number,
sequence: number, sequence: number,
interactType: InteractType interactType: InteractType
) => { ) => {
res[getWhom(controller)][sequence].placeInteractivity = { res.at(controller)[sequence].placeInteractivity = {
interactType: interactType, interactType: interactType,
response: { response: {
controler: controller, controler: controller,
...@@ -178,8 +157,10 @@ const wrap = <T extends DuelFieldState>( ...@@ -178,8 +157,10 @@ const wrap = <T extends DuelFieldState>(
}, },
}; };
}, },
clearPlaceInteractivity: (controller: number, sequence: number) => { clearPlaceInteractivity: (controller: number) => {
res[getWhom(controller)][sequence].placeInteractivity = undefined; res
.at(controller)
.forEach((card) => (card.placeInteractivity = undefined));
}, },
}); });
return res; return res;
...@@ -209,23 +190,27 @@ const getZone = (zone: ygopro.CardZone) => { ...@@ -209,23 +190,27 @@ const getZone = (zone: ygopro.CardZone) => {
return matStore.extraDecks; return matStore.extraDecks;
} }
}; };
const { SZONE, MZONE, GRAVE, REMOVED, HAND, DECK, EXTRA } = ygopro.CardZone;
/** /**
* 💡 决斗盘状态仓库,本文件核心, * 💡 决斗盘状态仓库,本文件核心,
* 具体介绍可以点进`PlayMatState`去看 * 具体介绍可以点进`PlayMatState`去看
*/ */
export const matStore: MatState = proxy<MatState>({ export const matStore: MatState = proxy<MatState>({
magics: wrap(genBlock(ygopro.CardZone.SZONE, 6), ygopro.CardZone.SZONE), magics: wrap(genDuel(genBlock(SZONE, 6)), SZONE),
monsters: wrap(genBlock(ygopro.CardZone.MZONE, 7), ygopro.CardZone.MZONE), monsters: wrap(genDuel(genBlock(MZONE, 7)), MZONE),
graveyards: wrap({ me: [], op: [] }, ygopro.CardZone.GRAVE), graveyards: wrap(genDuel([]), GRAVE),
banishedZones: wrap({ me: [], op: [] }, ygopro.CardZone.REMOVED), banishedZones: wrap(genDuel([]), REMOVED),
hands: wrap({ me: [], op: [] }, ygopro.CardZone.HAND), hands: wrap(genDuel([]), HAND),
decks: wrap({ me: [], op: [] }, ygopro.CardZone.DECK), decks: wrap(genDuel([]), DECK),
extraDecks: wrap({ me: [], op: [] }, ygopro.CardZone.EXTRA), extraDecks: wrap(genDuel([]), EXTRA),
timeLimits: { timeLimits: {
// 时间限制 // 时间限制
me: 0, ...genDuel(-1),
op: 0, set: (controller: number, time: number) => {
matStore.timeLimits[getWhom(controller)] = time;
},
}, },
initInfo, initInfo,
......
...@@ -6,6 +6,7 @@ import type { ygopro } from "@/api"; ...@@ -6,6 +6,7 @@ import type { ygopro } from "@/api";
export interface BothSide<T> { export interface BothSide<T> {
me: T; me: T;
op: T; op: T;
at: (controller: number) => T;
} }
export interface CardsBothSide<T extends DuelFieldState> extends BothSide<T> { export interface CardsBothSide<T extends DuelFieldState> extends BothSide<T> {
...@@ -33,7 +34,7 @@ export interface CardsBothSide<T extends DuelFieldState> extends BothSide<T> { ...@@ -33,7 +34,7 @@ export interface CardsBothSide<T extends DuelFieldState> extends BothSide<T> {
interactivity: CardState["idleInteractivities"][number] interactivity: CardState["idleInteractivities"][number]
) => void; ) => void;
/** 移除 idle 的交互性 */ /** 移除 idle 的交互性 */
clearIdleInteractivities: (controller: number, sequence: number) => void; clearIdleInteractivities: (controller: number) => void;
/** 设置 place 的交互种类 */ /** 设置 place 的交互种类 */
setPlaceInteractivityType: ( setPlaceInteractivityType: (
controller: number, controller: number,
...@@ -41,7 +42,7 @@ export interface CardsBothSide<T extends DuelFieldState> extends BothSide<T> { ...@@ -41,7 +42,7 @@ export interface CardsBothSide<T extends DuelFieldState> extends BothSide<T> {
interactType: InteractType interactType: InteractType
) => void; ) => void;
/** 移除 place 的交互性 */ /** 移除 place 的交互性 */
clearPlaceInteractivity: (controller: number, sequence: number) => void; clearPlaceInteractivity: (controller: number) => void;
} }
export interface MatState { export interface MatState {
...@@ -65,7 +66,9 @@ export interface MatState { ...@@ -65,7 +66,9 @@ export interface MatState {
extraDecks: CardsBothSide<ExtraDeckState>; // 双方的额外卡组状态 extraDecks: CardsBothSide<ExtraDeckState>; // 双方的额外卡组状态
timeLimits: BothSide<number>; // 双方的时间限制 timeLimits: BothSide<number> & {
set: (controller: number, time: number) => void;
}; // 双方的时间限制
hint: HintState; hint: HintState;
......
import { proxy } from "valtio"; export * from "./store";
export * from "./methods";
import type { CardMeta } from "@/api/cards";
import { ygopro } from "@/api";
export const messageStore = proxy<ModalState>({
cardModal: { isOpen: false, interactivies: [], counters: {} },
cardListModal: { isOpen: false, list: [] },
checkCardModal: { isOpen: false, cancelAble: false, tags: [] },
yesNoModal: { isOpen: false },
positionModal: { isOpen: false, positions: [] },
optionModal: { isOpen: false, options: [] },
checkCardModalV2: {
isOpen: false,
cancelAble: false,
finishAble: false,
responseable: false,
selectableOptions: [],
selectedOptions: [],
},
checkCardModalV3: {
isOpen: false,
overflow: false,
allLevel: 0,
mustSelectList: [],
selectAbleList: [],
},
checkCounterModal: {
isOpen: false,
options: [],
},
sortCardModal: {
isOpen: false,
options: [],
},
});
// >>> modal types >>>
type CardLocation = ReturnType<typeof ygopro.CardLocation.prototype.toObject>;
export interface ModalState {
// 卡牌弹窗
cardModal: {
isOpen: boolean;
meta?: CardMeta;
interactivies: { desc: string; response: number }[];
counters: { [type: number]: number };
};
// 卡牌列表弹窗
cardListModal: {
isOpen: boolean;
list: {
meta?: CardMeta;
interactivies: { desc: string; response: number }[];
}[];
};
// 卡牌选择弹窗
checkCardModal: {
isOpen: boolean;
onSubmit?: string;
selectMin?: number;
selectMax?: number;
cancelAble: boolean;
cancelResponse?: number;
tags: {
tagName: string;
options: {
meta: CardMeta;
location?: CardLocation;
effectDescCode?: number;
effectDesc?: string;
response: number;
}[];
}[];
};
// Yes or No弹窗
yesNoModal: {
isOpen: boolean;
msg?: string;
};
// 表示形式选择弹窗
positionModal: {
isOpen: boolean;
positions: ygopro.CardPosition[];
};
// 选项选择弹窗
optionModal: {
isOpen: boolean;
options: { msg: string; response: number }[];
};
// 卡牌选择弹窗V2
checkCardModalV2: {
isOpen: boolean;
cancelAble: boolean;
finishAble: boolean;
selectMin?: number;
selectMax?: number;
responseable?: boolean;
selectableOptions: {
code: number;
name?: string;
desc?: string;
response: number;
}[];
selectedOptions: {
code: number;
name?: string;
desc?: string;
response: number;
}[];
};
// 卡牌选择弹窗V3
checkCardModalV3: {
isOpen: boolean;
overflow: boolean;
allLevel: number;
selectMin?: number;
selectMax?: number;
responseable?: boolean;
mustSelectList: {
meta: CardMeta;
level1: number;
level2: number;
response: number;
}[];
selectAbleList: {
meta: CardMeta;
level1: number;
level2: number;
response: number;
}[];
};
// 指示器选择弹窗
checkCounterModal: {
isOpen: boolean;
counterType?: number;
min?: number;
options: {
code: number;
max: number;
}[];
};
// 卡牌排序弹窗
sortCardModal: {
isOpen: boolean;
options: {
meta: CardMeta;
response: number;
}[];
};
}
// <<< modal types <<<
import { matStore } from "@/valtioStores";
export const clearAllIdleInteractivities = (controller: number) => {
matStore.banishedZones.clearIdleInteractivities(controller);
matStore.decks.clearIdleInteractivities(controller);
matStore.extraDecks.clearIdleInteractivities(controller);
matStore.graveyards.clearIdleInteractivities(controller);
matStore.hands.clearIdleInteractivities(controller);
matStore.magics.clearIdleInteractivities(controller);
matStore.monsters.clearIdleInteractivities(controller);
};
import { type ygopro, fetchCard } from "@/api";
import { getCardByLocation, messageStore } from "@/valtioStores";
export const fetchCheckCardMetasV2 = async ({
selected,
options,
}: {
selected: boolean;
options: {
code: number;
location: ygopro.CardLocation;
response: number;
name?: string;
desc?: string;
}[];
}) => {
const metas = await Promise.all(
options.map(async (option) => {
return await fetchCard(option.code, true);
})
);
for (const option of options) {
if (option.code == 0) {
const newCode = getCardByLocation(option.location)?.occupant?.id || 0;
option.code = newCode;
}
}
options.forEach((option) => {
metas.forEach((meta) => {
if (option.code == meta.id) {
option.name = meta.text.name;
option.desc = meta.text.desc;
}
});
});
if (selected) {
messageStore.checkCardModalV2.selectedOptions = options;
} else {
messageStore.checkCardModalV2.selectableOptions = options;
}
};
import { type ygopro, fetchCard } from "@/api";
import { getCardByLocation, messageStore } from "@/valtioStores";
export const fetchCheckCardMetasV3 = async ({
mustSelect,
options,
}: {
mustSelect: boolean;
options: {
code: number;
location: ygopro.CardLocation;
level1: number;
level2: number;
response: number;
}[];
}) => {
const metas = await Promise.all(
options.map(async (option) => {
return await fetchCard(option.code, true);
})
);
const newOptions = options.map((option) => {
if (option.code == 0) {
const newCode = getCardByLocation(option.location)?.occupant?.id || 0;
option.code = newCode;
}
return {
meta: { id: option.code, data: {}, text: {} },
level1: option.level1,
level2: option.level2,
response: option.response,
};
});
newOptions.forEach((option) => {
metas.forEach((meta) => {
if (option.meta.id == meta.id) {
option.meta = meta;
}
});
});
if (mustSelect) {
messageStore.checkCardModalV3.mustSelectList = newOptions;
} else {
messageStore.checkCardModalV3.selectAbleList = newOptions;
}
};
export * from "./fetchCheckCardMetasV2";
export * from "./fetchCheckCardMetasV3";
export * from "./clearAllIdleInteractivities";
import { proxy } from "valtio";
import type { ModalState } from "./types";
export const messageStore = proxy<ModalState>({
cardModal: { isOpen: false, interactivies: [], counters: {} },
cardListModal: { isOpen: false, list: [] },
checkCardModal: { isOpen: false, cancelAble: false, tags: [] },
yesNoModal: { isOpen: false },
positionModal: { isOpen: false, positions: [] },
optionModal: { isOpen: false, options: [] },
checkCardModalV2: {
isOpen: false,
cancelAble: false,
finishAble: false,
responseable: false,
selectableOptions: [],
selectedOptions: [],
},
checkCardModalV3: {
isOpen: false,
overflow: false,
allLevel: 0,
mustSelectList: [],
selectAbleList: [],
},
checkCounterModal: {
isOpen: false,
options: [],
},
sortCardModal: {
isOpen: false,
options: [],
},
});
// >>> modal types >>>
import type { CardMeta, ygopro } from "@/api";
type CardLocation = ygopro.CardLocation;
export interface ModalState {
// 卡牌弹窗
cardModal: {
isOpen: boolean;
meta?: CardMeta;
interactivies: { desc: string; response: number }[];
counters: { [type: number]: number };
};
// 卡牌列表弹窗
cardListModal: {
isOpen: boolean;
list: {
meta?: CardMeta;
interactivies: { desc: string; response: number }[];
}[];
};
// 卡牌选择弹窗
checkCardModal: {
isOpen: boolean;
onSubmit?: string;
selectMin?: number;
selectMax?: number;
cancelAble: boolean;
cancelResponse?: number;
tags: {
tagName: string;
options: {
meta: CardMeta;
location?: CardLocation;
effectDescCode?: number;
effectDesc?: string;
response: number;
}[];
}[];
};
// Yes or No弹窗
yesNoModal: {
isOpen: boolean;
msg?: string;
};
// 表示形式选择弹窗
positionModal: {
isOpen: boolean;
positions: ygopro.CardPosition[];
};
// 选项选择弹窗
optionModal: {
isOpen: boolean;
options: { msg: string; response: number }[];
};
// 卡牌选择弹窗V2
checkCardModalV2: {
isOpen: boolean;
cancelAble: boolean;
finishAble: boolean;
selectMin?: number;
selectMax?: number;
responseable?: boolean;
selectableOptions: {
code: number;
name?: string;
desc?: string;
response: number;
}[];
selectedOptions: {
code: number;
name?: string;
desc?: string;
response: number;
}[];
};
// 卡牌选择弹窗V3
checkCardModalV3: {
isOpen: boolean;
overflow: boolean;
allLevel: number;
selectMin?: number;
selectMax?: number;
responseable?: boolean;
mustSelectList: {
meta: CardMeta;
level1: number;
level2: number;
response: number;
}[];
selectAbleList: {
meta: CardMeta;
level1: number;
level2: number;
response: number;
}[];
};
// 指示器选择弹窗
checkCounterModal: {
isOpen: boolean;
counterType?: number;
min?: number;
options: {
code: number;
max: number;
}[];
};
// 卡牌排序弹窗
sortCardModal: {
isOpen: boolean;
options: {
meta: CardMeta;
response: number;
}[];
};
}
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