Commit b15537c1 authored by Chunchi Che's avatar Chunchi Che

add attack effect

parent 247ad7f3
Pipeline #21665 passed with stages
in 11 minutes and 2 seconds
...@@ -56,3 +56,4 @@ export const MSG_ADD_COUNTER = 101; ...@@ -56,3 +56,4 @@ export const MSG_ADD_COUNTER = 101;
export const MSG_REMOVE_COUNTER = 102; export const MSG_REMOVE_COUNTER = 102;
export const MSG_SELECT_COUNTER = 22; export const MSG_SELECT_COUNTER = 22;
export const MSG_SORT_CARD = 25; export const MSG_SORT_CARD = 25;
export const MSG_ATTACK = 110;
import { ygopro } from "@/api/ocgcore/idl/ocgcore";
import { BufferReaderExt } from "../../bufferIO";
import MsgAttack = ygopro.StocGameMessage.MsgAttack;
/*
* Msg Attack
*
* @param attacker_location - 攻击者位置
* @param target_location - 攻击目标位置,可能为空
* @param direct_attack - 是否直接攻击玩家
* */
export default (data: Uint8Array) => {
const reader = new BufferReaderExt(data);
const attacker_location = reader.readCardLocation();
const target_location = reader.readCardLocation();
if (
target_location.controler == 0 &&
target_location.location == 0 &&
target_location.sequence == 0
) {
// 全零表示直接攻击玩家
return new MsgAttack({
attacker_location,
direct_attack: true,
});
} else {
return new MsgAttack({
attacker_location,
target_location,
direct_attack: false,
});
}
};
...@@ -7,6 +7,7 @@ import { ygopro } from "../../../idl/ocgcore"; ...@@ -7,6 +7,7 @@ import { ygopro } from "../../../idl/ocgcore";
import { StocAdapter, YgoProPacket } from "../../packet"; import { StocAdapter, YgoProPacket } from "../../packet";
import * as GAME_MSG from "../../protoDecl"; import * as GAME_MSG from "../../protoDecl";
import MsgAddCounter from "./addCounter"; import MsgAddCounter from "./addCounter";
import MsgAttack from "./attack";
import MsgDamage from "./damage"; import MsgDamage from "./damage";
import MsgDrawAdapter from "./draw"; import MsgDrawAdapter from "./draw";
import MsgHintAdapter from "./hint"; import MsgHintAdapter from "./hint";
...@@ -190,6 +191,11 @@ export default class GameMsgAdapter implements StocAdapter { ...@@ -190,6 +191,11 @@ export default class GameMsgAdapter implements StocAdapter {
break; break;
} }
case GAME_MSG.MSG_ATTACK: {
gameMsg.attack = MsgAttack(gameData);
break;
}
default: { default: {
gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({ gameMsg.unimplemented = new ygopro.StocGameMessage.MsgUnimplemented({
command: func, command: func,
......
...@@ -106,12 +106,6 @@ ...@@ -106,12 +106,6 @@
{ "fieldName": "location", "fieldType": "CardLocation" } { "fieldName": "location", "fieldType": "CardLocation" }
] ]
}, },
"110": {
"protoType": "attack",
"fields": [
{ "fieldName": "location", "fieldType": "CardLocation" }
]
},
"112": { "112": {
"protoType": "attack_disable", "protoType": "attack_disable",
"fields": [] "fields": []
......
...@@ -29,7 +29,6 @@ const MsgConstructorMap: Map<string, Constructor> = new Map([ ...@@ -29,7 +29,6 @@ const MsgConstructorMap: Map<string, Constructor> = new Map([
["sp_summoning", ygopro.StocGameMessage.MsgSpSummoning], ["sp_summoning", ygopro.StocGameMessage.MsgSpSummoning],
["sp_summoned", ygopro.StocGameMessage.MsgSpSummoned], ["sp_summoned", ygopro.StocGameMessage.MsgSpSummoned],
["chaining", ygopro.StocGameMessage.MsgChaining], ["chaining", ygopro.StocGameMessage.MsgChaining],
["attack", ygopro.StocGameMessage.MsgAttack],
["attack_disable", ygopro.StocGameMessage.MsgAttackDisabled], ["attack_disable", ygopro.StocGameMessage.MsgAttackDisabled],
["chain_solved", ygopro.StocGameMessage.MsgChainSolved], ["chain_solved", ygopro.StocGameMessage.MsgChainSolved],
]); ]);
......
...@@ -24,7 +24,11 @@ export default (attack: ygopro.StocGameMessage.MsgAttack) => { ...@@ -24,7 +24,11 @@ export default (attack: ygopro.StocGameMessage.MsgAttack) => {
.at(attack.target_location.sequence); .at(attack.target_location.sequence);
if (target) { if (target) {
attacker.attackTarget = target; attacker.attackTarget = {
sequence: attack.target_location.sequence,
opponent: matStore.isMe(attack.target_location.controler),
...target,
};
setTimeout(() => (attacker.attackTarget = undefined), 500); setTimeout(() => (attacker.attackTarget = undefined), 500);
} }
......
...@@ -126,6 +126,8 @@ function handleDelay(stoc: ygopro.YgoStocMsg): number { ...@@ -126,6 +126,8 @@ function handleDelay(stoc: ygopro.YgoStocMsg): number {
matStore.delay = NeosConfig.ui.moveDelay + 500; matStore.delay = NeosConfig.ui.moveDelay + 500;
} else if (stoc.stoc_game_msg.gameMsg == "chaining") { } else if (stoc.stoc_game_msg.gameMsg == "chaining") {
matStore.delay = NeosConfig.ui.chainingDelay; matStore.delay = NeosConfig.ui.chainingDelay;
} else if (stoc.stoc_game_msg.gameMsg == "attack") {
matStore.delay = 500 + 500;
} }
} }
......
...@@ -133,7 +133,7 @@ export interface CardState { ...@@ -133,7 +133,7 @@ export interface CardState {
focus: boolean; // 用于实现动画效果,当这个字段为true时,该张卡片会被放大并在屏幕中央展示 focus: boolean; // 用于实现动画效果,当这个字段为true时,该张卡片会被放大并在屏幕中央展示
chaining: boolean; // 是否在连锁中 chaining: boolean; // 是否在连锁中
directAttack: boolean; // 是否正在直接攻击为玩家 directAttack: boolean; // 是否正在直接攻击为玩家
attackTarget?: CardState; // 攻击目标。(嵌套结构可行么?) attackTarget?: CardState & { sequence: number; opponent: boolean }; // 攻击目标。(嵌套结构可行么?)
idleInteractivities: Interactivity<number>[]; // IDLE状态下的互动信息 idleInteractivities: Interactivity<number>[]; // IDLE状态下的互动信息
placeInteractivity?: Interactivity<{ placeInteractivity?: Interactivity<{
controler: number; controler: number;
......
...@@ -107,7 +107,11 @@ export const Mat = () => { ...@@ -107,7 +107,11 @@ export const Mat = () => {
card.focus || card.focus ||
(card.chaining && card.location.zone == YgoZone.HAND) (card.chaining && card.location.zone == YgoZone.HAND)
} }
fly={card.chaining && card.location.zone != YgoZone.HAND} fly={
(card.chaining && card.location.zone != YgoZone.HAND) ||
card.attackTarget !== undefined ||
card.directAttack
}
opponent={card.opponent} opponent={card.opponent}
onClick={ onClick={
card.location.zone == YgoZone.SZONE || card.location.zone == YgoZone.SZONE ||
...@@ -128,6 +132,18 @@ export const Mat = () => { ...@@ -128,6 +132,18 @@ export const Mat = () => {
function cardStateToRow(state: RenderCard): number { function cardStateToRow(state: RenderCard): number {
if (state.focus) return 2; if (state.focus) return 2;
if (state.directAttack) {
// 正在直接攻击玩家
if (state.opponent) {
return 4.5;
} else {
return -0.5;
}
}
if (state.attackTarget) {
// 正在攻击怪兽
return cardStateToRow(state.attackTarget) - 0.5 * (state.opponent ? 1 : -1);
}
if (state.opponent) { if (state.opponent) {
switch (state.location.zone) { switch (state.location.zone) {
case YgoZone.EXTRA: case YgoZone.EXTRA:
......
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