Browse Source

Hold mouse button to keep attacking (Diablo 2-style) (#2349)

pull/2261/merge
FluffyQuack 5 years ago committed by GitHub
parent
commit
ba60907853
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      Source/controls/plrctrls.cpp
  2. 26
      Source/cursor.cpp
  3. 30
      Source/diablo.cpp
  4. 15
      Source/diablo.h
  5. 2
      Source/items.cpp
  6. 2
      Source/monster.cpp
  7. 2
      Source/objects.cpp
  8. 9
      Source/player.cpp
  9. 2
      Source/player.h
  10. 52
      Source/track.cpp

2
Source/controls/plrctrls.cpp

@ -1479,7 +1479,7 @@ void PerformSpellAction()
}
UpdateSpellTarget();
CheckPlrSpell();
CheckPlrSpell(false);
}
void CtrlUseInvItem()

26
Source/cursor.cpp

@ -373,6 +373,32 @@ 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) {
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))
pcursmonst = -1;
} else if (pcursobj != -1) {
if (Objects[pcursobj]._oSelFlag < 1)
pcursobj = -1;
} else if (pcursplr != -1) {
if (Players[pcursplr]._pmode == PM_DEATH || Players[pcursplr]._pmode == PM_QUIT || !Players[pcursplr].plractive
|| currlevel != Players[pcursplr].plrlevel || Players[pcursplr]._pHitPoints >> 6 <= 0
|| !(dFlags[Players[pcursplr].position.tile.x][Players[pcursplr].position.tile.y] & BFLAG_VISIBLE))
pcursplr = -1;
}
if (pcursmonst == -1 && pcursobj == -1 && pcursitem == -1 && pcursinvitem == -1 && pcursplr == -1) {
cursmx = mx;
cursmy = my;
CheckTrigForce();
CheckTown();
CheckRportal();
}
return;
}
bool flipflag = (flipy && flipx) || ((flipy || flipx) && px < TILE_WIDTH / 2);
pcurstemp = pcursmonst;

30
Source/diablo.cpp

@ -19,6 +19,7 @@
#endif
#include "DiabloUI/diabloui.h"
#include "controls/keymapper.hpp"
#include "diablo.h"
#include "doom.h"
#include "drlg_l1.h"
#include "drlg_l2.h"
@ -129,6 +130,11 @@ QuickMessage QuickMessages[QUICK_MESSAGE_OPTIONS] = {
{ "QuickMessage4", N_("Now you DIE!") }
};
MouseActionType lastLeftMouseButtonAction = MouseActionType::None; // This and the following mouse variables are for handling in-game click-and-hold actions
MouseActionType lastRightMouseButtonAction = MouseActionType::None;
Uint32 lastLeftMouseButtonTime = 0;
Uint32 lastRightMouseButtonTime = 0;
// Controller support: Actions to run after updating the cursor state.
// Defined in SourceX/controls/plctrls.cpp.
extern void finish_simulated_mouse_clicks(int currentMouseX, int currentMouseY);
@ -248,14 +254,17 @@ bool LeftMouseCmd(bool bShift)
NetSendCmdLocParam1(true, pcurs == CURSOR_DISARM ? CMD_DISARMXY : CMD_OPOBJXY, { cursmx, cursmy }, pcursobj);
} else if (myPlayer._pwtype == WT_RANGED) {
if (bShift) {
lastLeftMouseButtonAction = MouseActionType::Attack;
NetSendCmdLoc(MyPlayerId, true, CMD_RATTACKXY, { cursmx, cursmy });
} else if (pcursmonst != -1) {
if (CanTalkToMonst(Monsters[pcursmonst])) {
NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst);
} else {
lastLeftMouseButtonAction = MouseActionType::Attack_MonsterTarget;
NetSendCmdParam1(true, CMD_RATTACKID, pcursmonst);
}
} else if (pcursplr != -1 && !gbFriendlyMode) {
lastLeftMouseButtonAction = MouseActionType::Attack_PlayerTarget;
NetSendCmdParam1(true, CMD_RATTACKPID, pcursplr);
}
} else {
@ -264,14 +273,18 @@ bool LeftMouseCmd(bool bShift)
if (CanTalkToMonst(Monsters[pcursmonst])) {
NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst);
} else {
lastLeftMouseButtonAction = MouseActionType::Attack;
NetSendCmdLoc(MyPlayerId, true, CMD_SATTACKXY, { cursmx, cursmy });
}
} else {
lastLeftMouseButtonAction = MouseActionType::Attack;
NetSendCmdLoc(MyPlayerId, true, CMD_SATTACKXY, { cursmx, cursmy });
}
} else if (pcursmonst != -1) {
lastLeftMouseButtonAction = MouseActionType::Attack_MonsterTarget;
NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst);
} else if (pcursplr != -1 && !gbFriendlyMode) {
lastLeftMouseButtonAction = MouseActionType::Attack_PlayerTarget;
NetSendCmdParam1(true, CMD_ATTACKPID, pcursplr);
}
}
@ -284,6 +297,9 @@ bool LeftMouseCmd(bool bShift)
bool LeftMouseDown(int wParam)
{
lastLeftMouseButtonAction = MouseActionType::Other;
lastLeftMouseButtonTime = SDL_GetTicks();
if (gmenu_left_mouse(true))
return false;
@ -372,6 +388,9 @@ void LeftMouseUp(int wParam)
void RightMouseDown()
{
lastRightMouseButtonAction = MouseActionType::Other;
lastRightMouseButtonTime = SDL_GetTicks();
if (gmenu_is_active() || sgnTimeoutCurs != CURSOR_NONE || PauseMode == 2 || Players[MyPlayerId]._pInvincible) {
return;
}
@ -392,7 +411,7 @@ void RightMouseDown()
&& (pcursinvitem == -1 || !UseInvItem(MyPlayerId, pcursinvitem)))) {
if (pcurs == CURSOR_HAND) {
if (pcursinvitem == -1 || !UseInvItem(MyPlayerId, pcursinvitem))
CheckPlrSpell();
CheckPlrSpell(true);
} else if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) {
NewCursor(CURSOR_HAND);
}
@ -720,6 +739,7 @@ void GameEventHandler(uint32_t uMsg, int32_t wParam, int32_t lParam)
return;
case DVL_WM_LBUTTONUP:
GetMousePos(lParam);
lastLeftMouseButtonAction = MouseActionType::None;
if (sgbMouseDown == CLICK_LEFT) {
sgbMouseDown = CLICK_NONE;
LeftMouseUp(wParam);
@ -735,6 +755,7 @@ void GameEventHandler(uint32_t uMsg, int32_t wParam, int32_t lParam)
return;
case DVL_WM_RBUTTONUP:
GetMousePos(lParam);
lastRightMouseButtonAction = MouseActionType::None;
if (sgbMouseDown == CLICK_RIGHT) {
sgbMouseDown = CLICK_NONE;
}
@ -2118,6 +2139,13 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
if (!gbIsSpawn && setlevel && setlvlnum == SL_SKELKING && Quests[Q_SKELKING]._qactive == QUEST_ACTIVE)
PlaySFX(USFX_SKING1);
// Reset mouse selection of entities
pcursmonst = -1;
pcursobj = -1;
pcursitem = -1;
pcursinvitem = -1;
pcursplr = -1;
}
/**

15
Source/diablo.h

@ -43,6 +43,16 @@ enum class GameLogicStep {
ProcessMissilesTown,
};
enum class MouseActionType : int {
None,
Spell,
Spell_ComplainedAboutMana,
Attack,
Attack_MonsterTarget,
Attack_PlayerTarget,
Other,
};
extern SDL_Window *ghMainWnd;
extern DWORD glSeedTbl[NUMLEVELS];
extern dungeon_type gnLevelTypeTbl[NUMLEVELS];
@ -69,6 +79,11 @@ extern clicktype sgbMouseDown;
extern uint16_t gnTickDelay;
extern char gszProductName[64];
extern MouseActionType lastLeftMouseButtonAction;
extern MouseActionType lastRightMouseButtonAction;
extern Uint32 lastLeftMouseButtonTime;
extern Uint32 lastRightMouseButtonTime;
void FreeGameMem();
bool StartGame(bool bNewGame, bool bSinglePlayer);
[[noreturn]] void diablo_quit(int exitStatus);

2
Source/items.cpp

@ -3710,6 +3710,8 @@ void DeleteItem(int ii, int i)
ActiveItemCount--;
if (ActiveItemCount > 0 && i != ActiveItemCount)
ActiveItems[i] = ActiveItems[ActiveItemCount];
if (pcursitem == ii) // Unselect item if player has it highlighted
pcursitem = -1;
}
void ProcessItems()

2
Source/monster.cpp

@ -4446,6 +4446,8 @@ void DeleteMonsterList()
for (int i = MAX_PLRS; i < ActiveMonsterCount;) {
if (Monsters[ActiveMonsters[i]]._mDelFlag) {
if (pcursmonst == ActiveMonsters[i]) // Unselect monster if player highlighted it
pcursmonst = -1;
DeleteMonster(i);
} else {
i++;

2
Source/objects.cpp

@ -1212,6 +1212,8 @@ void DeleteObject(int oi, int i)
dObject[ox][oy] = 0;
AvailableObjects[-ActiveObjectCount + MAXOBJECTS] = oi;
ActiveObjectCount--;
if (pcursobj == oi) // Unselect object if this was highlighted by player
pcursobj = -1;
if (ActiveObjectCount > 0 && i != ActiveObjectCount)
ActiveObjects[i] = ActiveObjects[ActiveObjectCount];
}

9
Source/player.cpp

@ -3572,7 +3572,7 @@ void CalcPlrStaff(PlayerStruct &player)
}
}
void CheckPlrSpell()
void CheckPlrSpell(bool mouseClick)
{
bool addflag = false;
int sl;
@ -3643,11 +3643,16 @@ void CheckPlrSpell()
sl = GetSpellLevel(MyPlayerId, myPlayer._pRSpell);
NetSendCmdLocParam2(true, CMD_SPELLXY, { cursmx, cursmy }, myPlayer._pRSpell, sl);
}
if (mouseClick)
lastRightMouseButtonAction = MouseActionType::Spell;
return;
}
if (myPlayer._pRSplType == RSPLTYPE_SPELL) {
myPlayer.Say(HeroSpeech::NotEnoughMana);
if (!mouseClick || lastRightMouseButtonAction != MouseActionType::Spell_ComplainedAboutMana)
myPlayer.Say(HeroSpeech::NotEnoughMana);
if (mouseClick)
lastRightMouseButtonAction = MouseActionType::Spell_ComplainedAboutMana;
}
}

2
Source/player.h

@ -490,7 +490,7 @@ void ClrPlrPath(PlayerStruct &player);
bool PosOkPlayer(int pnum, Point position);
void MakePlrPath(int pnum, Point targetPosition, bool endspace);
void CalcPlrStaff(PlayerStruct &player);
void CheckPlrSpell();
void CheckPlrSpell(bool mouseClick);
void SyncPlrAnim(int pnum);
void SyncInitPlrPos(int pnum);
void SyncInitPlr(int pnum);

52
Source/track.cpp

@ -21,8 +21,60 @@ bool sgbIsWalking;
} // namespace
static bool RepeatMouseAttack(bool leftButton)
{
if (pcurs != CURSOR_HAND)
return false;
Uint32 *timePressed;
MouseActionType lastAction;
if (leftButton) {
if (sgbMouseDown != CLICK_LEFT)
return false;
timePressed = &lastLeftMouseButtonTime;
lastAction = lastLeftMouseButtonAction;
} else {
if (sgbMouseDown != CLICK_RIGHT)
return false;
timePressed = &lastRightMouseButtonTime;
lastAction = lastRightMouseButtonAction;
}
if (lastAction != MouseActionType::Attack && lastAction != MouseActionType::Attack_MonsterTarget && lastAction != MouseActionType::Attack_PlayerTarget && lastAction != MouseActionType::Spell && lastAction != MouseActionType::Spell_ComplainedAboutMana)
return false;
if (Players[MyPlayerId]._pmode != PM_DEATH && Players[MyPlayerId]._pmode != PM_QUIT &&
Players[MyPlayerId].destAction == ACTION_NONE && SDL_GetTicks() - *timePressed >= (Uint32)gnTickDelay * 4) {
bool rangedAttack = Players[MyPlayerId]._pwtype == WT_RANGED;
*timePressed = SDL_GetTicks();
switch (lastAction) {
case MouseActionType::Attack:
if (cursmx >= 0 && cursmx < MAXDUNX && cursmy >= 0 && cursmy < MAXDUNY)
NetSendCmdLoc(MyPlayerId, true, rangedAttack ? CMD_RATTACKXY : CMD_SATTACKXY, { cursmx, cursmy });
break;
case MouseActionType::Attack_MonsterTarget:
if (pcursmonst != -1)
NetSendCmdParam1(true, rangedAttack ? CMD_RATTACKID : CMD_ATTACKID, pcursmonst);
break;
case MouseActionType::Attack_PlayerTarget:
if (pcursplr != -1 && !gbFriendlyMode)
NetSendCmdParam1(true, rangedAttack ? CMD_RATTACKPID : CMD_ATTACKPID, pcursplr);
break;
case MouseActionType::Spell:
case MouseActionType::Spell_ComplainedAboutMana:
CheckPlrSpell(true);
break;
}
}
return true;
}
void track_process()
{
if (RepeatMouseAttack(true) || RepeatMouseAttack(false))
return;
if (!sgbIsWalking)
return;

Loading…
Cancel
Save