diff --git a/client/src/hero.cpp b/client/src/hero.cpp index 778692b34..4ac522d43 100644 --- a/client/src/hero.cpp +++ b/client/src/hero.cpp @@ -345,13 +345,10 @@ bool Hero::motionValid(const std::unique_ptr &motionPtr) const case MOTION_HITTED: case MOTION_WHEELWIND: case MOTION_RANDSWING: + case MOTION_SPINKICK: { return !onHorse() && (nLDistance2 == 0); } - case MOTION_BACKDROPKICK: - { - return false; - } case MOTION_DIE: { return !onHorse() && (nLDistance2 == 0); @@ -430,6 +427,7 @@ bool Hero::parseAction(const ActionNode &action) case ACTION_STAND: case ACTION_SPELL: case ACTION_ATTACK: + case ACTION_SPINKICK: { m_motionQueue = makeWalkMotionQueue(endX, endY, action.x, action.y, SYS_MAXSPEED); break; @@ -465,6 +463,27 @@ bool Hero::parseAction(const ActionNode &action) })); break; } + case ACTION_SPINKICK: + { + m_motionQueue.push_back(std::unique_ptr(new MotionNode + { + .type = MOTION_SPINKICK, + .direction = [&action, this]() -> int + { + if(action.aimUID){ + if(auto coPtr = m_processRun->findUID(action.aimUID)){ + if(mathf::CDistance(coPtr->x(), coPtr->y(), x(), y()) == 1){ + return PathFind::GetDirection(coPtr->x(), coPtr->y(), x(), y()); + } + } + } + return m_currMotion->direction; + }(), + .x = action.x, + .y = action.y, + })); + break; + } case ACTION_MOVE: { if(auto moveNode = makeWalkMotion(action.x, action.y, action.aimX, action.aimY, action.speed)){ @@ -1040,7 +1059,7 @@ HeroFrameGfxSeq Hero::getFrameGfxSeq(int motion, int direction) const case MOTION_HITTED : return {.count = 3}; case MOTION_WHEELWIND : return {.count = 10}; case MOTION_RANDSWING : return {.count = 10}; - case MOTION_BACKDROPKICK : return {.count = 10}; + case MOTION_SPINKICK : return {.count = 10}; case MOTION_DIE : return {.count = 10}; case MOTION_ONHORSEDIE : return {.count = 10}; case MOTION_WALK : return {.count = 6}; diff --git a/client/src/motionnode.hpp b/client/src/motionnode.hpp index 29cd685b5..d0ae65b74 100644 --- a/client/src/motionnode.hpp +++ b/client/src/motionnode.hpp @@ -132,7 +132,7 @@ inline const char *motionName(int type) _add_motion_type_case(MOTION_HITTED ) _add_motion_type_case(MOTION_WHEELWIND ) _add_motion_type_case(MOTION_RANDSWING ) - _add_motion_type_case(MOTION_BACKDROPKICK ) + _add_motion_type_case(MOTION_SPINKICK ) _add_motion_type_case(MOTION_DIE ) _add_motion_type_case(MOTION_ONHORSEDIE ) _add_motion_type_case(MOTION_WALK ) diff --git a/client/src/processrun.cpp b/client/src/processrun.cpp index 24cdc59fa..4c6b0e200 100644 --- a/client/src/processrun.cpp +++ b/client/src/processrun.cpp @@ -1930,6 +1930,32 @@ void ProcessRun::checkMagicSpell(const SDL_Event &event) } switch(magicID){ + case DBCOM_MAGICID(u8"空拳刀法"): + { + getMyHero()->brakeMove(); + if(const auto uid = focusUID(FOCUS_MAGIC)){ + getMyHero()->emplaceAction(ActionSpinKick + { + .x = getMyHero()->currMotion()->endX, + .y = getMyHero()->currMotion()->endY, + .aimUID = uid, + }); + } + else{ + // even there is no target UID + // we still cast the magic to show gfx + + const auto [aimX, aimY] = getMouseGLoc(); + getMyHero()->emplaceAction(ActionSpinKick + { + .x = getMyHero()->currMotion()->endX, + .y = getMyHero()->currMotion()->endY, + .aimX = aimX, + .aimY = aimY, + }); + } + break; + } case DBCOM_MAGICID(u8"烈火剑法"): case DBCOM_MAGICID(u8"翔空剑法"): case DBCOM_MAGICID(u8"莲月剑法"): diff --git a/common/src/actionnode.hpp b/common/src/actionnode.hpp index 555699025..b81caae68 100644 --- a/common/src/actionnode.hpp +++ b/common/src/actionnode.hpp @@ -38,6 +38,7 @@ enum ActionType: int ACTION_SPELL, ACTION_TRANSF, ACTION_HITTED, + ACTION_SPINKICK, ACTION_DIE, ACTION_END, }; @@ -214,6 +215,36 @@ struct ActionNode }; #pragma pack(pop) +struct ActionSpinKick +{ + const int speed = SYS_DEFSPEED; + + const int x = -1; + const int y = -1; + + const int aimX = x; + const int aimY = y; + + const uint64_t aimUID = 0; + + operator ActionNode () const + { + ActionNode node; + std::memset(&node, 0, sizeof(node)); + + node.type = ACTION_SPINKICK; + node.speed = speed; + + node.x = x; + node.y = y; + + node.aimX = aimX; + node.aimY = aimY; + node.aimUID = aimUID; + return node; + } +}; + struct ActionDie { const int x = -1; @@ -506,6 +537,7 @@ inline const char *actionName(int type) _add_action_type_case(ACTION_SPELL ) _add_action_type_case(ACTION_TRANSF ) _add_action_type_case(ACTION_HITTED ) + _add_action_type_case(ACTION_SPINKICK ) _add_action_type_case(ACTION_DIE ) default: return "ACTION_UNKNOWN"; } diff --git a/common/src/magicrecord.inc b/common/src/magicrecord.inc index 4b0a6c41b..5f51f5e94 100644 --- a/common/src/magicrecord.inc +++ b/common/src/magicrecord.inc @@ -2010,7 +2010,7 @@ .type = u8"附着", .gfxID = 0X020001AE, .frameCount = 7, - .motion = MOTION_SPELL1, + .motion = MOTION_ATTACKMODE, }, }, }, diff --git a/common/src/motion.hpp b/common/src/motion.hpp index 62a6eeafa..f60929b1d 100644 --- a/common/src/motion.hpp +++ b/common/src/motion.hpp @@ -41,7 +41,7 @@ enum MotionType: int MOTION_HITTED, MOTION_WHEELWIND, MOTION_RANDSWING, - MOTION_BACKDROPKICK, + MOTION_SPINKICK, MOTION_DIE, MOTION_ONHORSEDIE, MOTION_WALK, diff --git a/server/src/player.cpp b/server/src/player.cpp index 23eedd09e..559da7e51 100644 --- a/server/src/player.cpp +++ b/server/src/player.cpp @@ -686,6 +686,12 @@ void Player::onCMActionAttack(CMAction stCMA) }); } +void Player::onCMActionSpinKick(CMAction cmA) +{ + fflassert(cmA.action.type == ACTION_SPINKICK); + dispatchAction(cmA.action); +} + void Player::onCMActionSpell(CMAction cmA) { fflassert(cmA.action.type == ACTION_SPELL); diff --git a/server/src/player.hpp b/server/src/player.hpp index 9a130d37a..83ec54143 100644 --- a/server/src/player.hpp +++ b/server/src/player.hpp @@ -187,10 +187,11 @@ class Player final: public CharObject bool MotionValid(const ActionNode &); protected: - void onCMActionMove (CMAction); - void onCMActionStand (CMAction); - void onCMActionSpell (CMAction); - void onCMActionAttack(CMAction); + void onCMActionMove (CMAction); + void onCMActionStand (CMAction); + void onCMActionSpell (CMAction); + void onCMActionSpinKick(CMAction); + void onCMActionAttack (CMAction); private: bool postNetMessage(uint8_t, const void *, size_t); diff --git a/server/src/playernet.cpp b/server/src/playernet.cpp index d5f151b92..f47fc4598 100644 --- a/server/src/playernet.cpp +++ b/server/src/playernet.cpp @@ -37,11 +37,12 @@ void Player::net_CM_ACTION(uint8_t, const uint8_t *pBuf, size_t) // we may need to filter some actions to anti-cheat, dispatch in onCMActionXXXX(cmA) if legeal switch(to_d(cmA.action.type)){ - case ACTION_STAND : onCMActionStand (cmA); return; - case ACTION_MOVE : onCMActionMove (cmA); return; - case ACTION_ATTACK: onCMActionAttack(cmA); return; - case ACTION_SPELL : onCMActionSpell (cmA); return; - default : return; + case ACTION_STAND : onCMActionStand (cmA); return; + case ACTION_MOVE : onCMActionMove (cmA); return; + case ACTION_ATTACK : onCMActionAttack (cmA); return; + case ACTION_SPELL : onCMActionSpell (cmA); return; + case ACTION_SPINKICK: onCMActionSpinKick(cmA); return; + default : return; } } }