Commit de2c697f authored by Chunchi Che's avatar Chunchi Che

Merge branch 'dev' into 'main'

Dev

See merge request mycard/Neos!33
parents 4d9570c2 236f0a84
......@@ -19,27 +19,6 @@ export interface CardMeta {
};
}
interface CardTransform {
position?: {
x: number;
y: number;
z: number;
};
rotation?: {
x: number;
y: number;
z: number;
};
}
/*
* `Neos`中表示卡牌的通用结构
* */
export interface Card {
meta: CardMeta;
transform: CardTransform;
}
/*
* 返回卡片元数据
*
......
......@@ -18,7 +18,7 @@ export default (data: Uint8Array) => {
const msg = new MsgSelectIdleCmd({});
msg.player = reader.readUint8();
// summon
// 通常召唤
const summonCmd = new MsgSelectIdleCmd.IdleCmd({
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.SUMMON,
idle_datas: [],
......@@ -31,7 +31,7 @@ export default (data: Uint8Array) => {
summonCmd.idle_datas.push(idleData);
}
// spsummon
// 特殊召唤
const spSummonCmd = new MsgSelectIdleCmd.IdleCmd({
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.SPSUMMON,
idle_datas: [],
......@@ -44,7 +44,7 @@ export default (data: Uint8Array) => {
spSummonCmd.idle_datas.push(idleData);
}
// pos change
// 表示形式改变
const posChangeCmd = new MsgSelectIdleCmd.IdleCmd({
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.POS_CHANGE,
idle_datas: [],
......@@ -57,7 +57,7 @@ export default (data: Uint8Array) => {
posChangeCmd.idle_datas.push(idleData);
}
// mset
// 前场放置
const mSetCmd = new MsgSelectIdleCmd.IdleCmd({
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.MSET,
idle_datas: [],
......@@ -70,7 +70,7 @@ export default (data: Uint8Array) => {
mSetCmd.idle_datas.push(idleData);
}
// sset
// 后场放置
const sSetCmd = new MsgSelectIdleCmd.IdleCmd({
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.SSET,
idle_datas: [],
......@@ -83,7 +83,7 @@ export default (data: Uint8Array) => {
sSetCmd.idle_datas.push(idleData);
}
// activate
// 发动效果/灵摆发动
const activateCmd = new MsgSelectIdleCmd.IdleCmd({
idle_type: MsgSelectIdleCmd.IdleCmd.IdleType.ACTIVATE,
idle_datas: [],
......@@ -106,8 +106,11 @@ export default (data: Uint8Array) => {
activateCmd,
];
// 进入战斗阶段
msg.enable_bp = reader.readUint8() === 1;
// 结束回合
msg.enable_ep = reader.readUint8() === 1;
// 切洗手牌
msg.enable_shuffle = reader.readUint8() === 1;
return msg;
......
import { createAsyncThunk, ActionReducerMapBuilder } from "@reduxjs/toolkit";
import {
createAsyncThunk,
ActionReducerMapBuilder,
CaseReducer,
PayloadAction,
} from "@reduxjs/toolkit";
import { DuelState } from "./mod";
import { RootState } from "../../store";
import { Card, fetchCard, CardMeta } from "../../api/cards";
import { judgeSelf } from "./util";
import { fetchCard, CardMeta } from "../../api/cards";
import { judgeSelf, Card, Interactivity } from "./util";
import * as UICONFIG from "../../config/ui";
export interface Hands {
// 注意:手牌的位置顺序是有约束的
cards: Card[];
}
......@@ -35,12 +41,11 @@ export const handsCase = (builder: ActionReducerMapBuilder<DuelState>) => {
builder.addCase(fetchHandsMeta.fulfilled, (state, action) => {
const player = action.payload[0];
const hands = action.payload[1];
const selfType = state.selfType;
const cards = hands.map((meta) => {
return { meta, transform: {} };
return { meta, transform: {}, interactivities: [] };
});
if (judgeSelf(player, selfType)) {
if (judgeSelf(player, state)) {
if (state.meHands) {
state.meHands.cards = state.meHands.cards.concat(cards);
} else {
......@@ -78,6 +83,42 @@ function setHandsTransform(hands: Card[]): void {
});
}
// 清空手牌互动性
export const clearHandsInteractivityImpl: CaseReducer<
DuelState,
PayloadAction<number>
> = (state, action) => {
const player = action.payload;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
if (hands) {
for (let hand of hands.cards) {
hand.interactivities = [];
}
}
};
// 添加手牌互动性
export const addHandsInteractivityImpl: CaseReducer<
DuelState,
PayloadAction<{
player: number;
index: number;
interactivity: Interactivity;
}>
> = (state, action) => {
const player = action.payload.player;
const hands = judgeSelf(player, state) ? state.meHands : state.opHands;
if (hands) {
const index = action.payload.index;
const interactivity = action.payload.interactivity;
hands.cards[index].interactivities.push(interactivity);
}
};
export const selectMeHands = (state: RootState) =>
state.duel.meHands || { cards: [] };
export const selectOpHands = (state: RootState) =>
......
......@@ -16,9 +16,8 @@ export const infoInitImpl: CaseReducer<
> = (state, action) => {
const player = action.payload[0];
const initInfo = action.payload[1];
const selfType = state.selfType;
if (judgeSelf(player, selfType)) {
if (judgeSelf(player, state)) {
state.meInitInfo = initInfo;
} else {
state.opInitInfo = initInfo;
......
......@@ -5,7 +5,12 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { InitInfo, infoInitImpl } from "./initInfoSlice";
import { Hands, handsCase } from "./handsSlice";
import {
Hands,
handsCase,
clearHandsInteractivityImpl,
addHandsInteractivityImpl,
} from "./handsSlice";
import { newTurnImpl } from "./turnSlice";
import { newPhaseImpl } from "./phaseSlice";
import { RootState } from "../../store";
......@@ -32,14 +37,24 @@ const duelSlice = createSlice({
infoInit: infoInitImpl,
updateTurn: newTurnImpl,
updatePhase: newPhaseImpl,
// 手牌相关`Reducer`
clearHandsInteractivity: clearHandsInteractivityImpl,
addHandsInteractivity: addHandsInteractivityImpl,
},
extraReducers(builder) {
handsCase(builder);
},
});
export const { setSelfType, infoInit, updateTurn, updatePhase } =
duelSlice.actions;
export const {
setSelfType,
infoInit,
updateTurn,
updatePhase,
clearHandsInteractivity,
addHandsInteractivity,
} = duelSlice.actions;
export const selectDuelHsStart = (state: RootState) => {
return state.duel.meInitInfo != null;
};
......
/*
* 对局内状态更新逻辑的一些共用函数
* 对局内状态更新逻辑的一些共用函数和数据结构
*
* */
import { CardMeta } from "../../api/cards";
import { DuelState } from "./mod";
import { Draft } from "@reduxjs/toolkit";
/*
* 通过`player`和`selfType`判断是应该处理自己还是对手
* */
export function judgeSelf(
player: number,
selfType: number | undefined
): boolean {
export function judgeSelf(player: number, state: Draft<DuelState>): boolean {
const selfType = state.selfType;
if (selfType === 1) {
// 自己是先攻
return player === 0;
......@@ -21,3 +23,46 @@ export function judgeSelf(
return false;
}
}
/*
* `Neos`中表示卡牌的通用结构
* */
export interface Card {
meta: CardMeta;
transform: CardTransform;
interactivities: Interactivity[];
}
interface CardTransform {
position?: {
x: number;
y: number;
z: number;
};
rotation?: {
x: number;
y: number;
z: number;
};
}
export enum InteractType {
// 可普通召唤
SUMMON,
// 可特殊召唤
SP_SUMMON,
// 可改变表示形式
POS_CHANGE,
// 可前场放置
MSET,
// 可后场放置
SSET,
// 可发动效果
ACTIVATE,
}
export interface Interactivity {
interactType: InteractType;
// 如果`interactType`是`ACTIVATE`,这个字段是对应的效果编号
activateIndex?: number;
}
import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { AppDispatch } from "../../store";
import { InteractType } from "../../reducers/duel/util";
import {
clearHandsInteractivity,
addHandsInteractivity,
} from "../../reducers/duel/mod";
import MsgSelectIdleCmd = ygopro.StocGameMessage.MsgSelectIdleCmd;
export default (
selectIdleCmd: ygopro.StocGameMessage.MsgSelectIdleCmd,
dispatch: AppDispatch
) => {
// TODO
console.log(selectIdleCmd);
export default (selectIdleCmd: MsgSelectIdleCmd, dispatch: AppDispatch) => {
const player = selectIdleCmd.player;
const cmds = selectIdleCmd.idle_cmds;
// 先清掉之前的手牌互动性
dispatch(clearHandsInteractivity(player));
for (let cmd of cmds) {
let interactType;
switch (cmd.idle_type) {
case MsgSelectIdleCmd.IdleCmd.IdleType.SUMMON: {
interactType = InteractType.SUMMON;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.SPSUMMON: {
interactType = InteractType.SP_SUMMON;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.POS_CHANGE: {
interactType = InteractType.POS_CHANGE;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.MSET: {
interactType = InteractType.MSET;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.SSET: {
interactType = InteractType.SSET;
break;
}
case MsgSelectIdleCmd.IdleCmd.IdleType.ACTIVATE: {
interactType = InteractType.ACTIVATE;
break;
}
}
for (let data of cmd.idle_datas) {
const card_info = data.card_info;
if (card_info.location === 2) {
// 目前只处理手牌场景
if (interactType === InteractType.ACTIVATE) {
// 发动效果会多一个字段
dispatch(
addHandsInteractivity({
player,
index: card_info.sequence,
interactivity: {
interactType,
activateIndex: data.effect_description,
},
})
);
} else if (interactType) {
dispatch(
addHandsInteractivity({
player,
index: card_info.sequence,
interactivity: { interactType },
})
);
}
}
}
}
};
......@@ -16,7 +16,7 @@
import React from "react";
import type { RootState } from "../../store";
import { Card } from "../../api/cards";
import { Card } from "../../reducers/duel/util";
/*
* 通用的决斗界面抽象接口
......
import * as BABYLON from "@babylonjs/core";
import * as CONFIG from "../../../config/ui";
import { Card } from "../../../api/cards";
import { Card } from "../../../reducers/duel/util";
export default (hands: Card[], scene: BABYLON.Scene) => {
const handShape = CONFIG.HandShape();
......
......@@ -17,7 +17,7 @@ import renderCemetery from "./cemetery";
import renderExclusion from "./exclusion";
import renderField from "./field";
import * as CONFIG from "../../../config/ui";
import { Card } from "../../../api/cards";
import { Card } from "../../../reducers/duel/util";
import { selectCurrentPlayer } from "../../../reducers/duel/turnSlice";
import { selectCurrentPhase } from "../../../reducers/duel/phaseSlice";
......
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