Commit 57e5a7ba authored by Chunchi Che's avatar Chunchi Che

Merge branch 'feat/ui/select_battle_cmd' into 'main'

Feat/ui/select battle cmd

See merge request mycard/Neos!82
parents dd528e77 d9ee1160
Pipeline #19625 passed with stages
in 3 minutes and 37 seconds
...@@ -28,7 +28,7 @@ export default (data: Uint8Array) => { ...@@ -28,7 +28,7 @@ export default (data: Uint8Array) => {
const activateData = new MsgSelectBattleCmd.BattleCmd.BattleData({ const activateData = new MsgSelectBattleCmd.BattleCmd.BattleData({
card_info: cardInfo, card_info: cardInfo,
effect_description: effectDescription, effect_description: effectDescription,
response: i << (16 + 0), response: (i << 16) + 0,
}); });
activateCmd.battle_datas.push(activateData); activateCmd.battle_datas.push(activateData);
} }
...@@ -45,7 +45,7 @@ export default (data: Uint8Array) => { ...@@ -45,7 +45,7 @@ export default (data: Uint8Array) => {
const attackData = new MsgSelectBattleCmd.BattleCmd.BattleData({ const attackData = new MsgSelectBattleCmd.BattleCmd.BattleData({
card_info: cardInfo, card_info: cardInfo,
direct_attackable: directAttackAble == 1, direct_attackable: directAttackAble == 1,
response: i << (16 + 1), response: (i << 16) + 1,
}); });
attackCmd.battle_datas.push(attackData); attackCmd.battle_datas.push(attackData);
} }
......
...@@ -38,12 +38,16 @@ export enum InteractType { ...@@ -38,12 +38,16 @@ export enum InteractType {
ACTIVATE = 6, ACTIVATE = 6,
// 可作为位置选择 // 可作为位置选择
PLACE_SELECTABLE = 7, PLACE_SELECTABLE = 7,
// 可攻击
ATTACK = 8,
} }
export interface Interactivity<T> { export interface Interactivity<T> {
interactType: InteractType; interactType: InteractType;
// 如果`interactType`是`ACTIVATE`,这个字段是对应的效果编号 // 如果`interactType`是`ACTIVATE`,这个字段是对应的效果编号
activateIndex?: number; activateIndex?: number;
// 如果`interactType`是`ATTACK`,这个字段表示是否可以直接攻击
directAttackAble?: boolean;
// 用户点击后,需要回传给服务端的`response` // 用户点击后,需要回传给服务端的`response`
response: T; response: T;
} }
......
...@@ -18,6 +18,7 @@ import { ...@@ -18,6 +18,7 @@ import {
newPhaseImpl, newPhaseImpl,
PhaseState, PhaseState,
setEnableBpImpl, setEnableBpImpl,
setEnableM2Impl,
setEnableEpImpl, setEnableEpImpl,
} from "./phaseSlice"; } from "./phaseSlice";
import { RootState } from "../../store"; import { RootState } from "../../store";
...@@ -184,6 +185,7 @@ const duelSlice = createSlice({ ...@@ -184,6 +185,7 @@ const duelSlice = createSlice({
// 阶段相关 // 阶段相关
updatePhase: newPhaseImpl, updatePhase: newPhaseImpl,
setEnableBp: setEnableBpImpl, setEnableBp: setEnableBpImpl,
setEnableM2: setEnableM2Impl,
setEnableEp: setEnableEpImpl, setEnableEp: setEnableEpImpl,
// UI相关`Reducer` // UI相关`Reducer`
...@@ -225,6 +227,7 @@ export const { ...@@ -225,6 +227,7 @@ export const {
updateTurn, updateTurn,
updatePhase, updatePhase,
setEnableBp, setEnableBp,
setEnableM2,
setEnableEp, setEnableEp,
clearHandsIdleInteractivity, clearHandsIdleInteractivity,
addHandsIdleInteractivity, addHandsIdleInteractivity,
......
...@@ -5,6 +5,7 @@ import { DuelState } from "./mod"; ...@@ -5,6 +5,7 @@ import { DuelState } from "./mod";
export interface PhaseState { export interface PhaseState {
currentPhase: string; // 当前的阶段 currentPhase: string; // 当前的阶段
enableBp: boolean; // 允许进入战斗阶段 enableBp: boolean; // 允许进入战斗阶段
enableM2: boolean; // 允许进入M2阶段
enableEp: boolean; // 允许回合结束 enableEp: boolean; // 允许回合结束
} }
export const newPhaseImpl: CaseReducer<DuelState, PayloadAction<string>> = ( export const newPhaseImpl: CaseReducer<DuelState, PayloadAction<string>> = (
...@@ -17,6 +18,7 @@ export const newPhaseImpl: CaseReducer<DuelState, PayloadAction<string>> = ( ...@@ -17,6 +18,7 @@ export const newPhaseImpl: CaseReducer<DuelState, PayloadAction<string>> = (
state.phase = { state.phase = {
currentPhase: action.payload, currentPhase: action.payload,
enableBp: false, enableBp: false,
enableM2: false,
enableEp: false, enableEp: false,
}; };
} }
...@@ -31,6 +33,15 @@ export const setEnableBpImpl: CaseReducer<DuelState, PayloadAction<boolean>> = ( ...@@ -31,6 +33,15 @@ export const setEnableBpImpl: CaseReducer<DuelState, PayloadAction<boolean>> = (
} }
}; };
export const setEnableM2Impl: CaseReducer<DuelState, PayloadAction<boolean>> = (
state,
action
) => {
if (state.phase) {
state.phase.enableM2 = action.payload;
}
};
export const setEnableEpImpl: CaseReducer<DuelState, PayloadAction<boolean>> = ( export const setEnableEpImpl: CaseReducer<DuelState, PayloadAction<boolean>> = (
state, state,
action action
...@@ -44,5 +55,7 @@ export const selectCurrentPhase = (state: RootState) => ...@@ -44,5 +55,7 @@ export const selectCurrentPhase = (state: RootState) =>
state.duel.phase?.currentPhase; state.duel.phase?.currentPhase;
export const selectEnableBp = (state: RootState) => export const selectEnableBp = (state: RootState) =>
state.duel.phase?.enableBp || false; state.duel.phase?.enableBp || false;
export const selectEnableM2 = (state: RootState) =>
state.duel.phase?.enableBp || false;
export const selectEnableEp = (state: RootState) => export const selectEnableEp = (state: RootState) =>
state.duel.phase?.enableEp || false; state.duel.phase?.enableEp || false;
import { ActionCreatorWithPayload } from "@reduxjs/toolkit";
import { ygopro } from "../../api/ocgcore/idl/ocgcore"; import { ygopro } from "../../api/ocgcore/idl/ocgcore";
import { Interactivity, InteractType } from "../../reducers/duel/generic";
import {
addFieldIdleInteractivities,
addHandsIdleInteractivity,
addMagicIdleInteractivities,
addMonsterIdleInteractivities,
clearFieldIdleInteractivities,
clearHandsIdleInteractivity,
clearMagicIdleInteractivities,
clearMonsterIdleInteractivities,
setEnableEp,
setEnableM2,
} from "../../reducers/duel/mod";
import { AppDispatch } from "../../store"; import { AppDispatch } from "../../store";
import MsgSelectBattleCmd = ygopro.StocGameMessage.MsgSelectBattleCmd; import MsgSelectBattleCmd = ygopro.StocGameMessage.MsgSelectBattleCmd;
export default (selectBattleCmd: MsgSelectBattleCmd, dispatch: AppDispatch) => { export default (selectBattleCmd: MsgSelectBattleCmd, dispatch: AppDispatch) => {
console.log(selectBattleCmd); const player = selectBattleCmd.player;
const cmds = selectBattleCmd.battle_cmds;
// 先清掉之前的互动性
dispatch(clearHandsIdleInteractivity(player));
dispatch(clearMonsterIdleInteractivities(player));
dispatch(clearMagicIdleInteractivities(player));
dispatch(clearFieldIdleInteractivities(player));
const dispatcher = (
battleData: MsgSelectBattleCmd.BattleCmd.BattleData,
interactType: InteractType | undefined,
actionCreator: ActionCreatorWithPayload<
{
player: number;
sequence: number;
interactivity: Interactivity<number>;
},
string
>
) => {
const cardInfo = battleData.card_info;
if (interactType === InteractType.ACTIVATE) {
dispatch(
actionCreator({
player,
sequence: cardInfo.sequence,
interactivity: {
interactType,
activateIndex: battleData.effect_description,
response: battleData.response,
},
})
);
} else if (interactType === InteractType.ATTACK) {
dispatch(
actionCreator({
player,
sequence: cardInfo.sequence,
interactivity: {
interactType,
directAttackAble: battleData.direct_attackable,
response: battleData.response,
},
})
);
} else {
console.log(`Unhandled InteractType`);
}
};
cmds.forEach((cmd) => {
const interactType = battleTypeToInteracType(cmd.battle_type);
cmd.battle_datas.forEach((data) => {
const cardInfo = data.card_info;
switch (cardInfo.location) {
case ygopro.CardZone.HAND: {
dispatcher(data, interactType, addHandsIdleInteractivity);
break;
}
case ygopro.CardZone.MZONE: {
dispatcher(data, interactType, addMonsterIdleInteractivities);
break;
}
case ygopro.CardZone.SZONE: {
dispatcher(data, interactType, addMagicIdleInteractivities);
break;
}
case ygopro.CardZone.ONFIELD: {
dispatcher(data, interactType, addFieldIdleInteractivities);
break;
}
default: {
}
}
});
});
dispatch(setEnableM2(selectBattleCmd.enable_m2));
dispatch(setEnableEp(selectBattleCmd.enable_ep));
}; };
function battleTypeToInteracType(
battleType: MsgSelectBattleCmd.BattleCmd.BattleType
): InteractType | undefined {
switch (battleType) {
case MsgSelectBattleCmd.BattleCmd.BattleType.ATTACK: {
return InteractType.ATTACK;
}
case MsgSelectBattleCmd.BattleCmd.BattleType.ACTIVATE: {
return InteractType.ACTIVATE;
}
default: {
return undefined;
}
}
}
...@@ -54,19 +54,6 @@ const Monsters = () => { ...@@ -54,19 +54,6 @@ const Monsters = () => {
} }
)} )}
<ExtraMonsters /> <ExtraMonsters />
<adtFullscreenUi name="ui">
<rectangle name="rect" height="20px" width="60px">
<babylon-button name="close-icon">
<textBlock
text="bp"
fontFamily="FontAwesome"
fontStyle="bold"
fontSize={15}
color="white"
/>
</babylon-button>
</rectangle>
</adtFullscreenUi>
<ExtraMonsters /> <ExtraMonsters />
</> </>
); );
......
import React from "react"; import React from "react";
import { store } from "../../store"; import { store } from "../../store";
import { useAppSelector } from "../../hook"; import { useAppSelector } from "../../hook";
import { selectEnableBp, selectEnableEp } from "../../reducers/duel/phaseSlice"; import {
import { sendSelectIdleCmdResponse } from "../../api/ocgcore/ocgHelper"; selectCurrentPhase,
selectEnableBp,
selectEnableEp,
selectEnableM2,
} from "../../reducers/duel/phaseSlice";
import {
sendSelectBattleCmdResponse,
sendSelectIdleCmdResponse,
} from "../../api/ocgcore/ocgHelper";
import { import {
clearFieldIdleInteractivities, clearFieldIdleInteractivities,
clearHandsIdleInteractivity, clearHandsIdleInteractivity,
...@@ -10,6 +18,7 @@ import { ...@@ -10,6 +18,7 @@ import {
clearMonsterIdleInteractivities, clearMonsterIdleInteractivities,
setEnableBp, setEnableBp,
setEnableEp, setEnableEp,
setEnableM2,
} from "../../reducers/duel/mod"; } from "../../reducers/duel/mod";
import { Button2D } from "./2d"; import { Button2D } from "./2d";
...@@ -31,13 +40,45 @@ const Bp = () => { ...@@ -31,13 +40,45 @@ const Bp = () => {
dispatch(setEnableBp(false)); dispatch(setEnableBp(false));
}; };
return <Button2D text="bp" left={0} enable={enable} onClick={onClick} />; return <Button2D text="bp" left={-200} enable={enable} onClick={onClick} />;
};
const M2 = () => {
const dispatch = store.dispatch;
const enable = useAppSelector(selectEnableM2);
const onClick = () => {
// 清除一堆东西的互动性
dispatch(clearHandsIdleInteractivity(0));
dispatch(clearHandsIdleInteractivity(1));
dispatch(clearMonsterIdleInteractivities(0));
dispatch(clearMonsterIdleInteractivities(1));
dispatch(clearMagicIdleInteractivities(0));
dispatch(clearMagicIdleInteractivities(1));
dispatch(clearFieldIdleInteractivities(0));
dispatch(clearFieldIdleInteractivities(1));
sendSelectBattleCmdResponse(2);
dispatch(setEnableM2(false));
};
return <Button2D text="m2" left={0} enable={enable} onClick={onClick} />;
}; };
const Ep = () => { const Ep = () => {
const dispatch = store.dispatch; const dispatch = store.dispatch;
const enable = useAppSelector(selectEnableEp); const enable = useAppSelector(selectEnableEp);
const onClick = () => { const currentPhase = useAppSelector(selectCurrentPhase);
const response =
currentPhase === "BATTLE_START" ||
currentPhase === "BATTLE_STEP" ||
currentPhase === "DAMAGE" ||
currentPhase === "DAMAGE_GAL" ||
currentPhase === "BATTLE"
? 3
: 7;
const onClick = (response: number) => () => {
// 清除一堆东西的互动性 // 清除一堆东西的互动性
dispatch(clearHandsIdleInteractivity(0)); dispatch(clearHandsIdleInteractivity(0));
dispatch(clearHandsIdleInteractivity(1)); dispatch(clearHandsIdleInteractivity(1));
...@@ -48,16 +89,24 @@ const Ep = () => { ...@@ -48,16 +89,24 @@ const Ep = () => {
dispatch(clearFieldIdleInteractivities(0)); dispatch(clearFieldIdleInteractivities(0));
dispatch(clearFieldIdleInteractivities(1)); dispatch(clearFieldIdleInteractivities(1));
sendSelectIdleCmdResponse(7); sendSelectIdleCmdResponse(response);
dispatch(setEnableEp(false)); dispatch(setEnableEp(false));
}; };
return <Button2D text="ep" left={200} enable={enable} onClick={onClick} />; return (
<Button2D
text="ep"
left={200}
enable={enable}
onClick={onClick(response)}
/>
);
}; };
const Phase = () => ( const Phase = () => (
<> <>
<Bp /> <Bp />
<M2 />
<Ep /> <Ep />
</> </>
); );
......
...@@ -34,6 +34,9 @@ export function interactTypeToString(t: InteractType): string { ...@@ -34,6 +34,9 @@ export function interactTypeToString(t: InteractType): string {
case InteractType.ACTIVATE: { case InteractType.ACTIVATE: {
return "发动效果"; return "发动效果";
} }
case InteractType.ATTACK: {
return "攻击";
}
default: { default: {
return "未知选项"; return "未知选项";
} }
......
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