diff --git a/Source/controls/plrctrls.cpp b/Source/controls/plrctrls.cpp index 2b5055afb..9bb7cc006 100644 --- a/Source/controls/plrctrls.cpp +++ b/Source/controls/plrctrls.cpp @@ -1059,19 +1059,6 @@ bool IsPathBlocked(Point position, Direction dir) return !PosOkPlayer(myPlayer, leftStep) && !PosOkPlayer(myPlayer, rightStep); } -bool CanChangeDirection(const PlayerStruct &player) -{ - if (player._pmode == PM_STAND) - return true; - if (player._pmode == PM_ATTACK && player.AnimInfo.CurrentFrame > player._pAFNum) - return true; - if (player._pmode == PM_RATTACK && player.AnimInfo.CurrentFrame > player._pAFNum) - return true; - if (player._pmode == PM_SPELL && player.AnimInfo.CurrentFrame > player._pSFNum) - return true; - return false; -} - void WalkInDir(int playerId, AxisDirection dir) { auto &player = Players[playerId]; @@ -1085,7 +1072,7 @@ void WalkInDir(int playerId, AxisDirection dir) const Direction pdir = FaceDir[static_cast(dir.x)][static_cast(dir.y)]; const auto delta = player.position.future + pdir; - if (CanChangeDirection(player)) + if (!player.IsWalking() && player.CanChangeAction()) player._pdir = pdir; if (PosOkPlayer(player, delta) && IsPathBlocked(player.position.future, pdir)) @@ -1481,7 +1468,7 @@ void PerformSpellAction() } UpdateSpellTarget(); - CheckPlrSpell(false); + CheckPlrSpell(); } void CtrlUseInvItem() diff --git a/Source/cursor.cpp b/Source/cursor.cpp index 1bfbf07ee..70b12dc16 100644 --- a/Source/cursor.cpp +++ b/Source/cursor.cpp @@ -373,8 +373,8 @@ void CheckCursMove() my = MAXDUNY - 1; } - // While holding down left click we should retain target (but potentially lose it if it dies, goes out of view, etc) - if (sgbMouseDown == CLICK_LEFT && pcursinvitem == -1) { + // While holding the button down we should retain target (but potentially lose it if it dies, goes out of view, etc) + if (sgbMouseDown != CLICK_NONE && pcursinvitem == -1) { if (pcursmonst != -1) { if (Monsters[pcursmonst]._mDelFlag || Monsters[pcursmonst]._mhitpoints >> 6 <= 0 || ((dFlags[Monsters[pcursmonst].position.tile.x][Monsters[pcursmonst].position.tile.y] & BFLAG_VISIBLE) == 0)) diff --git a/Source/diablo.cpp b/Source/diablo.cpp index f23d77aec..9cafbf726 100644 --- a/Source/diablo.cpp +++ b/Source/diablo.cpp @@ -184,7 +184,7 @@ void StartGame(interface_mode uMsg) InitLevelCursor(); sgnTimeoutCurs = CURSOR_NONE; sgbMouseDown = CLICK_NONE; - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; } void FreeGame() @@ -225,13 +225,13 @@ bool ProcessInput() #endif CheckCursMove(); plrctrls_after_check_curs_move(); - track_process(); + RepeatMouseAction(); } return true; } -bool LeftMouseCmd(bool bShift) +void LeftMouseCmd(bool bShift) { bool bNear; @@ -242,94 +242,95 @@ bool LeftMouseCmd(bool bShift) NetSendCmdLocParam1(true, invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM, { cursmx, cursmy }, pcursitem); if (pcursmonst != -1) NetSendCmdLocParam1(true, CMD_TALKXY, { cursmx, cursmy }, pcursmonst); - if (pcursitem == -1 && pcursmonst == -1 && pcursplr == -1) - return true; + if (pcursitem == -1 && pcursmonst == -1 && pcursplr == -1) { + LastMouseButtonAction = MouseActionType::Walk; + } + return; + } + + auto &myPlayer = Players[MyPlayerId]; + bNear = myPlayer.position.tile.WalkingDistance({ cursmx, cursmy }) < 2; + if (pcursitem != -1 && pcurs == CURSOR_HAND && !bShift) { + NetSendCmdLocParam1(true, invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM, { cursmx, cursmy }, pcursitem); + } else if (pcursobj != -1 && (!objectIsDisabled(pcursobj)) && (!bShift || (bNear && Objects[pcursobj]._oBreak == 1))) { + LastMouseButtonAction = MouseActionType::OperateObject; + NetSendCmdLocParam1(true, pcurs == CURSOR_DISARM ? CMD_DISARMXY : CMD_OPOBJXY, { cursmx, cursmy }, pcursobj); + } else if (myPlayer.UsesRangedWeapon()) { + if (bShift) { + LastMouseButtonAction = MouseActionType::Attack; + NetSendCmdLoc(MyPlayerId, true, CMD_RATTACKXY, { cursmx, cursmy }); + } else if (pcursmonst != -1) { + if (CanTalkToMonst(Monsters[pcursmonst])) { + NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst); + } else { + LastMouseButtonAction = MouseActionType::AttackMonsterTarget; + NetSendCmdParam1(true, CMD_RATTACKID, pcursmonst); + } + } else if (pcursplr != -1 && !gbFriendlyMode) { + LastMouseButtonAction = MouseActionType::AttackPlayerTarget; + NetSendCmdParam1(true, CMD_RATTACKPID, pcursplr); + } } else { - auto &myPlayer = Players[MyPlayerId]; - bNear = myPlayer.position.tile.WalkingDistance({ cursmx, cursmy }) < 2; - if (pcursitem != -1 && pcurs == CURSOR_HAND && !bShift) { - NetSendCmdLocParam1(true, invflag ? CMD_GOTOGETITEM : CMD_GOTOAGETITEM, { cursmx, cursmy }, pcursitem); - } else if (pcursobj != -1 && (!objectIsDisabled(pcursobj)) && (!bShift || (bNear && Objects[pcursobj]._oBreak == 1))) { - LastMouseButtonAction = MouseActionType::OperateObject; - NetSendCmdLocParam1(true, pcurs == CURSOR_DISARM ? CMD_DISARMXY : CMD_OPOBJXY, { cursmx, cursmy }, pcursobj); - } else if (myPlayer.UsesRangedWeapon()) { - if (bShift) { - LastMouseButtonAction = MouseActionType::Attack; - NetSendCmdLoc(MyPlayerId, true, CMD_RATTACKXY, { cursmx, cursmy }); - } else if (pcursmonst != -1) { + if (bShift) { + if (pcursmonst != -1) { if (CanTalkToMonst(Monsters[pcursmonst])) { NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst); - } else { - LastMouseButtonAction = MouseActionType::AttackMonsterTarget; - NetSendCmdParam1(true, CMD_RATTACKID, pcursmonst); - } - } else if (pcursplr != -1 && !gbFriendlyMode) { - LastMouseButtonAction = MouseActionType::AttackPlayerTarget; - NetSendCmdParam1(true, CMD_RATTACKPID, pcursplr); - } - } else { - if (bShift) { - if (pcursmonst != -1) { - if (CanTalkToMonst(Monsters[pcursmonst])) { - NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst); - } else { - LastMouseButtonAction = MouseActionType::Attack; - NetSendCmdLoc(MyPlayerId, true, CMD_SATTACKXY, { cursmx, cursmy }); - } } else { LastMouseButtonAction = MouseActionType::Attack; NetSendCmdLoc(MyPlayerId, true, CMD_SATTACKXY, { cursmx, cursmy }); } - } else if (pcursmonst != -1) { - LastMouseButtonAction = MouseActionType::AttackMonsterTarget; - NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst); - } else if (pcursplr != -1 && !gbFriendlyMode) { - LastMouseButtonAction = MouseActionType::AttackPlayerTarget; - NetSendCmdParam1(true, CMD_ATTACKPID, pcursplr); + } else { + LastMouseButtonAction = MouseActionType::Attack; + NetSendCmdLoc(MyPlayerId, true, CMD_SATTACKXY, { cursmx, cursmy }); } + } else if (pcursmonst != -1) { + LastMouseButtonAction = MouseActionType::AttackMonsterTarget; + NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst); + } else if (pcursplr != -1 && !gbFriendlyMode) { + LastMouseButtonAction = MouseActionType::AttackPlayerTarget; + NetSendCmdParam1(true, CMD_ATTACKPID, pcursplr); } - if (!bShift && pcursitem == -1 && pcursobj == -1 && pcursmonst == -1 && pcursplr == -1) - return true; } - - return false; + if (!bShift && pcursitem == -1 && pcursobj == -1 && pcursmonst == -1 && pcursplr == -1) { + LastMouseButtonAction = MouseActionType::Walk; + } } -bool LeftMouseDown(int wParam) +void LeftMouseDown(int wParam) { - LastMouseButtonAction = MouseActionType::Other; + LastMouseButtonAction = MouseActionType::None; LastMouseButtonTime = SDL_GetTicks(); if (gmenu_left_mouse(true)) - return false; + return; if (control_check_talk_btn()) - return false; + return; if (sgnTimeoutCurs != CURSOR_NONE) - return false; + return; if (MyPlayerIsDead) { control_check_btn_press(); - return false; + return; } if (PauseMode == 2) { - return false; + return; } if (DoomFlag) { doom_close(); - return false; + return; } if (spselflag) { SetSpell(); - return false; + return; } if (stextflag != STORE_NONE) { CheckStoreBtn(); - return false; + return; } bool isShiftHeld = (wParam & DVL_MK_SHIFT) != 0; @@ -357,7 +358,7 @@ bool LeftMouseDown(int wParam) if (Players[MyPlayerId]._pStatPts != 0 && !spselflag) CheckLvlBtn(); if (!lvlbtndown) - return LeftMouseCmd(isShiftHeld); + LeftMouseCmd(isShiftHeld); } } } else { @@ -367,8 +368,6 @@ bool LeftMouseDown(int wParam) if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) NewCursor(CURSOR_HAND); } - - return false; } void LeftMouseUp(int wParam) @@ -388,7 +387,7 @@ void LeftMouseUp(int wParam) void RightMouseDown() { - LastMouseButtonAction = MouseActionType::Other; + LastMouseButtonAction = MouseActionType::None; LastMouseButtonTime = SDL_GetTicks(); if (gmenu_is_active() || sgnTimeoutCurs != CURSOR_NONE || PauseMode == 2 || Players[MyPlayerId]._pInvincible) { @@ -411,7 +410,7 @@ void RightMouseDown() && (pcursinvitem == -1 || !UseInvItem(MyPlayerId, pcursinvitem)))) { if (pcurs == CURSOR_HAND) { if (pcursinvitem == -1 || !UseInvItem(MyPlayerId, pcursinvitem)) - CheckPlrSpell(true); + CheckPlrSpell(); } else if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) { NewCursor(CURSOR_HAND); } @@ -488,7 +487,7 @@ void PressKey(int vkey) } if (vkey == DVL_VK_ESCAPE) { if (!PressEscKey()) { - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; gamemenu_on(); } return; @@ -734,7 +733,7 @@ void GameEventHandler(uint32_t uMsg, int32_t wParam, int32_t lParam) GetMousePos(lParam); if (sgbMouseDown == CLICK_NONE) { sgbMouseDown = CLICK_LEFT; - track_repeat_walk(LeftMouseDown(wParam)); + LeftMouseDown(wParam); } return; case DVL_WM_LBUTTONUP: @@ -743,7 +742,6 @@ void GameEventHandler(uint32_t uMsg, int32_t wParam, int32_t lParam) LastMouseButtonAction = MouseActionType::None; sgbMouseDown = CLICK_NONE; LeftMouseUp(wParam); - track_repeat_walk(false); } return; case DVL_WM_RBUTTONDOWN: @@ -762,7 +760,7 @@ void GameEventHandler(uint32_t uMsg, int32_t wParam, int32_t lParam) return; case DVL_WM_CAPTURECHANGED: sgbMouseDown = CLICK_NONE; - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; break; case WM_DIABNEXTLVL: case WM_DIABPREVLVL: @@ -778,7 +776,7 @@ void GameEventHandler(uint32_t uMsg, int32_t wParam, int32_t lParam) PaletteFadeOut(8); sound_stop(); music_stop(); - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; sgbMouseDown = CLICK_NONE; ShowProgress((interface_mode)uMsg); force_redraw = 255; @@ -1298,7 +1296,7 @@ void HelpKeyPressed() ClearPanel(); AddPanelString(_("No help available")); /// BUGFIX: message isn't displayed AddPanelString(_("while in stores")); - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; } else { invflag = false; chrflag = false; @@ -1408,7 +1406,7 @@ void DisplaySpellsKeyPressed() } else { spselflag = false; } - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; } void SpellBookKeyPressed() @@ -1757,7 +1755,7 @@ void diablo_pause_game() } else { PauseMode = 2; sound_stop(); - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; } force_redraw = 255; @@ -1778,7 +1776,7 @@ void diablo_focus_pause() if (!GameWasAlreadyPaused) { PauseMode = 2; sound_stop(); - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; } #ifndef NOSOUND diff --git a/Source/diablo.h b/Source/diablo.h index b97248cce..2fe9f62ac 100644 --- a/Source/diablo.h +++ b/Source/diablo.h @@ -45,8 +45,10 @@ enum class GameLogicStep { enum class MouseActionType : int { None, + Walk, Spell, - SpellOutOfMana, + SpellMonsterTarget, + SpellPlayerTarget, Attack, AttackMonsterTarget, AttackPlayerTarget, diff --git a/Source/objects.cpp b/Source/objects.cpp index 95b8a1287..56b6bccb5 100644 --- a/Source/objects.cpp +++ b/Source/objects.cpp @@ -1474,7 +1474,7 @@ void UpdateCircle(int i) if (Quests[Q_BETRAYER]._qactive == QUEST_ACTIVE && Quests[Q_BETRAYER]._qvar1 <= 4) // BUGFIX stepping on the circle again will break the quest state (fixed) Quests[Q_BETRAYER]._qvar1 = 4; AddMissile(myPlayer.position.tile, { 35, 46 }, myPlayer._pdir, MIS_RNDTELEPORT, TARGET_MONSTERS, MyPlayerId, 0, 0); - track_repeat_walk(false); + LastMouseButtonAction = MouseActionType::None; sgbMouseDown = CLICK_NONE; ClrPlrPath(myPlayer); StartStand(MyPlayerId, DIR_S); diff --git a/Source/player.cpp b/Source/player.cpp index b259f905a..7a7ffaec4 100644 --- a/Source/player.cpp +++ b/Source/player.cpp @@ -2167,14 +2167,7 @@ void PlayerStruct::Stop() bool PlayerStruct::IsWalking() const { - switch (_pmode) { - case PM_WALK: - case PM_WALK2: - case PM_WALK3: - return true; - default: - return false; - } + return IsAnyOf(_pmode, PM_WALK, PM_WALK2, PM_WALK3); } void PlayerStruct::Reset() @@ -3549,7 +3542,7 @@ void CalcPlrStaff(PlayerStruct &player) } } -void CheckPlrSpell(bool mouseClick) +void CheckPlrSpell() { bool addflag = false; int sl; @@ -3607,30 +3600,30 @@ void CheckPlrSpell(bool mouseClick) if (!addflag) { if (myPlayer._pRSplType == RSPLTYPE_SPELL) { - if (!mouseClick || LastMouseButtonAction != MouseActionType::SpellOutOfMana) - myPlayer.Say(HeroSpeech::NotEnoughMana); - if (mouseClick) - LastMouseButtonAction = MouseActionType::SpellOutOfMana; + myPlayer.Say(HeroSpeech::NotEnoughMana); + LastMouseButtonAction = MouseActionType::None; } return; } if (myPlayer._pRSpell == SPL_FIREWALL || myPlayer._pRSpell == SPL_LIGHTWALL) { + LastMouseButtonAction = MouseActionType::Spell; Direction sd = GetDirection(myPlayer.position.tile, { cursmx, cursmy }); sl = GetSpellLevel(MyPlayerId, myPlayer._pRSpell); NetSendCmdLocParam3(true, CMD_SPELLXYD, { cursmx, cursmy }, myPlayer._pRSpell, sd, sl); } else if (pcursmonst != -1) { + LastMouseButtonAction = MouseActionType::SpellMonsterTarget; sl = GetSpellLevel(MyPlayerId, myPlayer._pRSpell); NetSendCmdParam3(true, CMD_SPELLID, pcursmonst, myPlayer._pRSpell, sl); } else if (pcursplr != -1) { + LastMouseButtonAction = MouseActionType::SpellPlayerTarget; sl = GetSpellLevel(MyPlayerId, myPlayer._pRSpell); NetSendCmdParam3(true, CMD_SPELLPID, pcursplr, myPlayer._pRSpell, sl); - } else { //145 + } else { + LastMouseButtonAction = MouseActionType::Spell; sl = GetSpellLevel(MyPlayerId, myPlayer._pRSpell); NetSendCmdLocParam2(true, CMD_SPELLXY, { cursmx, cursmy }, myPlayer._pRSpell, sl); } - if (mouseClick) - LastMouseButtonAction = MouseActionType::Spell; } void SyncPlrAnim(int pnum) diff --git a/Source/player.h b/Source/player.h index 9b14df8fd..c3801ca20 100644 --- a/Source/player.h +++ b/Source/player.h @@ -433,7 +433,22 @@ struct PlayerStruct { bool UsesRangedWeapon() const { return static_cast(_pgfxnum & 0xF) == PlayerWeaponGraphic::Bow; - }; + } + + bool CanChangeAction() + { + if (_pmode == PM_STAND) + return true; + if (_pmode == PM_ATTACK && AnimInfo.CurrentFrame > _pAFNum) + return true; + if (_pmode == PM_RATTACK && AnimInfo.CurrentFrame > _pAFNum) + return true; + if (_pmode == PM_SPELL && AnimInfo.CurrentFrame > _pSFNum) + return true; + if (IsWalking() && AnimInfo.CurrentFrame == AnimInfo.NumberOfFrames) + return true; + return false; + } }; extern int MyPlayerId; @@ -488,7 +503,7 @@ void ClrPlrPath(PlayerStruct &player); bool PosOkPlayer(const PlayerStruct &player, Point position); void MakePlrPath(PlayerStruct &player, Point targetPosition, bool endspace); void CalcPlrStaff(PlayerStruct &player); -void CheckPlrSpell(bool mouseClick); +void CheckPlrSpell(); void SyncPlrAnim(int pnum); void SyncInitPlrPos(int pnum); void SyncInitPlr(int pnum); diff --git a/Source/track.cpp b/Source/track.cpp index 1b7a60f3b..6ca890f2b 100644 --- a/Source/track.cpp +++ b/Source/track.cpp @@ -15,28 +15,41 @@ namespace devilution { namespace { -bool sgbIsScrolling; -uint32_t sgdwLastWalk; -bool sgbIsWalking; +void RepeatWalk(PlayerStruct &player) +{ + if (cursmx < 0 || cursmx >= MAXDUNX - 1 || cursmy < 0 || cursmy >= MAXDUNY - 1) + return; + + if (player._pmode != PM_STAND && !(player.IsWalking() && player.AnimInfo.GetFrameToUseForRendering() > 6)) + return; + + const Point target = player.GetTargetPosition(); + if (cursmx == target.x && cursmy == target.y) + return; + + NetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, { cursmx, cursmy }); +} + +} // namespace -bool RepeatMouseAction() +void RepeatMouseAction() { if (pcurs != CURSOR_HAND) - return false; + return; if (sgbMouseDown == CLICK_NONE) - return false; + return; + + if (LastMouseButtonAction == MouseActionType::None) + return; auto &myPlayer = Players[MyPlayerId]; - if (myPlayer._pmode == PM_DEATH - || myPlayer._pmode == PM_QUIT - || myPlayer.destAction != ACTION_NONE - || SDL_GetTicks() - LastMouseButtonTime < gnTickDelay * 4) { - return true; - } + if (myPlayer.destAction != ACTION_NONE) + return; + if (!myPlayer.CanChangeAction()) + return; bool rangedAttack = myPlayer.UsesRangedWeapon(); - LastMouseButtonTime = SDL_GetTicks(); switch (LastMouseButtonAction) { case MouseActionType::Attack: if (cursmx >= 0 && cursmx < MAXDUNX && cursmy >= 0 && cursmy < MAXDUNY) @@ -51,8 +64,15 @@ bool RepeatMouseAction() NetSendCmdParam1(true, rangedAttack ? CMD_RATTACKPID : CMD_ATTACKPID, pcursplr); break; case MouseActionType::Spell: - case MouseActionType::SpellOutOfMana: - CheckPlrSpell(true); + CheckPlrSpell(); + break; + case MouseActionType::SpellMonsterTarget: + if (pcursmonst != -1) + CheckPlrSpell(); + break; + case MouseActionType::SpellPlayerTarget: + if (pcursplr != -1 && !gbFriendlyMode) + CheckPlrSpell(); break; case MouseActionType::OperateObject: if (pcursobj != -1) { @@ -62,65 +82,17 @@ bool RepeatMouseAction() NetSendCmdLocParam1(true, CMD_OPOBJXY, object.position, pcursobj); } break; - case MouseActionType::Other: + case MouseActionType::Walk: + RepeatWalk(myPlayer); + break; case MouseActionType::None: - return false; - } - - return true; -} - -} // namespace - -void track_process() -{ - if (RepeatMouseAction()) - return; - - if (!sgbIsWalking) - return; - - if (cursmx < 0 || cursmx >= MAXDUNX - 1 || cursmy < 0 || cursmy >= MAXDUNY - 1) - return; - - const auto &player = Players[MyPlayerId]; - - if (player._pmode != PM_STAND && !(player.IsWalking() && player.AnimInfo.GetFrameToUseForRendering() > 6)) - return; - - const Point target = player.GetTargetPosition(); - if (cursmx != target.x || cursmy != target.y) { - uint32_t tick = SDL_GetTicks(); - int tickMultiplier = 6; - if (currlevel == 0 && sgGameInitInfo.bRunInTown != 0) - tickMultiplier = 3; - if ((int)(tick - sgdwLastWalk) >= gnTickDelay * tickMultiplier) { - sgdwLastWalk = tick; - NetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, { cursmx, cursmy }); - if (!sgbIsScrolling) - sgbIsScrolling = true; - } - } -} - -void track_repeat_walk(bool rep) -{ - if (sgbIsWalking == rep) - return; - - sgbIsWalking = rep; - if (rep) { - sgbIsScrolling = false; - sgdwLastWalk = SDL_GetTicks() - gnTickDelay; - NetSendCmdLoc(MyPlayerId, true, CMD_WALKXY, { cursmx, cursmy }); - } else if (sgbIsScrolling) { - sgbIsScrolling = false; + break; } } bool track_isscrolling() { - return sgbIsScrolling; + return LastMouseButtonAction == MouseActionType::Walk; } } // namespace devilution diff --git a/Source/track.h b/Source/track.h index e83475002..3336b0dd7 100644 --- a/Source/track.h +++ b/Source/track.h @@ -7,8 +7,7 @@ namespace devilution { -void track_process(); -void track_repeat_walk(bool rep); +void RepeatMouseAction(); bool track_isscrolling(); } // namespace devilution