|
|
|
|
@ -1,14 +1,14 @@
|
|
|
|
|
#include "controls/plrctrls.h" |
|
|
|
|
|
|
|
|
|
#include <algorithm> |
|
|
|
|
#include <cmath> |
|
|
|
|
#include <cstdint> |
|
|
|
|
#include <list> |
|
|
|
|
#include <string> |
|
|
|
|
|
|
|
|
|
#ifdef USE_SDL3 |
|
|
|
|
#include <SDL3/SDL_events.h> |
|
|
|
|
#include <SDL3/SDL_gamepad.h> |
|
|
|
|
#include <algorithm> |
|
|
|
|
#include <cmath> |
|
|
|
|
#include <cstdint> |
|
|
|
|
#include <list> |
|
|
|
|
#include <string> |
|
|
|
|
|
|
|
|
|
#ifdef USE_SDL3 |
|
|
|
|
#include <SDL3/SDL_events.h> |
|
|
|
|
#include <SDL3/SDL_gamepad.h> |
|
|
|
|
#include <SDL3/SDL_timer.h> |
|
|
|
|
#else |
|
|
|
|
#include <SDL.h> |
|
|
|
|
@ -16,20 +16,21 @@
|
|
|
|
|
#ifdef USE_SDL1 |
|
|
|
|
#include "utils/sdl2_to_1_2_backports.h" |
|
|
|
|
#endif |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#include <fmt/format.h> |
|
|
|
|
|
|
|
|
|
#include "automap.h" |
|
|
|
|
#include "control/control.hpp" |
|
|
|
|
#include "controls/controller_motion.h" |
|
|
|
|
#ifndef USE_SDL1 |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#include <fmt/format.h> |
|
|
|
|
|
|
|
|
|
#include "automap.h" |
|
|
|
|
#include "control/control.hpp" |
|
|
|
|
#include "controls/controller_motion.h" |
|
|
|
|
#ifndef USE_SDL1 |
|
|
|
|
#include "controls/devices/game_controller.h" |
|
|
|
|
#endif |
|
|
|
|
#include "controls/control_mode.hpp" |
|
|
|
|
#include "controls/game_controls.h" |
|
|
|
|
#include "controls/touch/gamepad.h" |
|
|
|
|
#include "cursor.h" |
|
|
|
|
#include "diablo.h" |
|
|
|
|
#include "doom.h" |
|
|
|
|
#include "engine/point.hpp" |
|
|
|
|
#include "engine/points_in_rectangle_range.hpp" |
|
|
|
|
@ -49,16 +50,16 @@
|
|
|
|
|
#include "panels/ui_panels.hpp" |
|
|
|
|
#include "qol/chatlog.h" |
|
|
|
|
#include "qol/stash.h" |
|
|
|
|
#include "stores.h" |
|
|
|
|
#include "towners.h" |
|
|
|
|
#include "track.h" |
|
|
|
|
#include "utils/format_int.hpp" |
|
|
|
|
#include "utils/is_of.hpp" |
|
|
|
|
#include "utils/language.h" |
|
|
|
|
#include "utils/log.hpp" |
|
|
|
|
#include "utils/screen_reader.hpp" |
|
|
|
|
#include "utils/sdl_compat.h" |
|
|
|
|
#include "utils/str_cat.hpp" |
|
|
|
|
#include "stores.h" |
|
|
|
|
#include "towners.h" |
|
|
|
|
#include "track.h" |
|
|
|
|
#include "utils/format_int.hpp" |
|
|
|
|
#include "utils/is_of.hpp" |
|
|
|
|
#include "utils/language.h" |
|
|
|
|
#include "utils/log.hpp" |
|
|
|
|
#include "utils/screen_reader.hpp" |
|
|
|
|
#include "utils/sdl_compat.h" |
|
|
|
|
#include "utils/str_cat.hpp" |
|
|
|
|
|
|
|
|
|
namespace devilution { |
|
|
|
|
|
|
|
|
|
@ -675,104 +676,104 @@ Point GetSlotCoord(int slot)
|
|
|
|
|
/**
|
|
|
|
|
* Return the item id of the current slot |
|
|
|
|
*/ |
|
|
|
|
int GetItemIdOnSlot(int slot) |
|
|
|
|
{ |
|
|
|
|
if (slot >= SLOTXY_INV_FIRST && slot <= SLOTXY_INV_LAST) { |
|
|
|
|
return std::abs(MyPlayer->InvGrid[slot - SLOTXY_INV_FIRST]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
StringOrView GetInventorySlotNameForSpeech(int slot) |
|
|
|
|
{ |
|
|
|
|
switch (slot) { |
|
|
|
|
case SLOTXY_HEAD: |
|
|
|
|
return _("Head"); |
|
|
|
|
case SLOTXY_RING_LEFT: |
|
|
|
|
return _("Left ring"); |
|
|
|
|
case SLOTXY_RING_RIGHT: |
|
|
|
|
return _("Right ring"); |
|
|
|
|
case SLOTXY_AMULET: |
|
|
|
|
return _("Amulet"); |
|
|
|
|
case SLOTXY_HAND_LEFT: |
|
|
|
|
return _("Left hand"); |
|
|
|
|
case SLOTXY_HAND_RIGHT: |
|
|
|
|
return _("Right hand"); |
|
|
|
|
case SLOTXY_CHEST: |
|
|
|
|
return _("Chest"); |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (slot >= SLOTXY_BELT_FIRST && slot <= SLOTXY_BELT_LAST) |
|
|
|
|
return StrCat(_("Belt"), " ", slot - SLOTXY_BELT_FIRST + 1); |
|
|
|
|
|
|
|
|
|
return _("Inventory"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SpeakInventorySlotForAccessibility() |
|
|
|
|
{ |
|
|
|
|
if (MyPlayer == nullptr) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
const Player &player = *MyPlayer; |
|
|
|
|
const Item *item = nullptr; |
|
|
|
|
|
|
|
|
|
if (Slot >= SLOTXY_BELT_FIRST && Slot <= SLOTXY_BELT_LAST) { |
|
|
|
|
item = &player.SpdList[Slot - SLOTXY_BELT_FIRST]; |
|
|
|
|
} else if (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_INV_LAST) { |
|
|
|
|
const int invId = GetItemIdOnSlot(Slot); |
|
|
|
|
if (invId != 0) |
|
|
|
|
item = &player.InvList[invId - 1]; |
|
|
|
|
} else { |
|
|
|
|
switch (Slot) { |
|
|
|
|
case SLOTXY_HEAD: |
|
|
|
|
item = &player.InvBody[INVLOC_HEAD]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_RING_LEFT: |
|
|
|
|
item = &player.InvBody[INVLOC_RING_LEFT]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_RING_RIGHT: |
|
|
|
|
item = &player.InvBody[INVLOC_RING_RIGHT]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_AMULET: |
|
|
|
|
item = &player.InvBody[INVLOC_AMULET]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_HAND_LEFT: |
|
|
|
|
item = &player.InvBody[INVLOC_HAND_LEFT]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_HAND_RIGHT: { |
|
|
|
|
const Item &left = player.InvBody[INVLOC_HAND_LEFT]; |
|
|
|
|
if (!left.isEmpty() && player.GetItemLocation(left) == ILOC_TWOHAND) |
|
|
|
|
item = &left; |
|
|
|
|
else |
|
|
|
|
item = &player.InvBody[INVLOC_HAND_RIGHT]; |
|
|
|
|
} break; |
|
|
|
|
case SLOTXY_CHEST: |
|
|
|
|
item = &player.InvBody[INVLOC_CHEST]; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (item != nullptr && !item->isEmpty()) { |
|
|
|
|
if (item->_itype == ItemType::Gold) { |
|
|
|
|
const int nGold = item->_ivalue; |
|
|
|
|
SpeakText(fmt::format(fmt::runtime(ngettext("{:s} gold piece", "{:s} gold pieces", nGold)), FormatInteger(nGold)), /*force=*/true); |
|
|
|
|
} else { |
|
|
|
|
SpeakText(item->getName(), /*force=*/true); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SpeakText(StrCat(GetInventorySlotNameForSpeech(Slot), ": ", _("empty")), /*force=*/true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get item size (grid size) on the slot specified. Returns 1x1 if none exists. |
|
|
|
|
*/ |
|
|
|
|
int GetItemIdOnSlot(int slot) |
|
|
|
|
{ |
|
|
|
|
if (slot >= SLOTXY_INV_FIRST && slot <= SLOTXY_INV_LAST) { |
|
|
|
|
return std::abs(MyPlayer->InvGrid[slot - SLOTXY_INV_FIRST]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
StringOrView GetInventorySlotNameForSpeech(int slot) |
|
|
|
|
{ |
|
|
|
|
switch (slot) { |
|
|
|
|
case SLOTXY_HEAD: |
|
|
|
|
return _("Head"); |
|
|
|
|
case SLOTXY_RING_LEFT: |
|
|
|
|
return _("Left ring"); |
|
|
|
|
case SLOTXY_RING_RIGHT: |
|
|
|
|
return _("Right ring"); |
|
|
|
|
case SLOTXY_AMULET: |
|
|
|
|
return _("Amulet"); |
|
|
|
|
case SLOTXY_HAND_LEFT: |
|
|
|
|
return _("Left hand"); |
|
|
|
|
case SLOTXY_HAND_RIGHT: |
|
|
|
|
return _("Right hand"); |
|
|
|
|
case SLOTXY_CHEST: |
|
|
|
|
return _("Chest"); |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (slot >= SLOTXY_BELT_FIRST && slot <= SLOTXY_BELT_LAST) |
|
|
|
|
return StrCat(_("Belt"), " ", slot - SLOTXY_BELT_FIRST + 1); |
|
|
|
|
|
|
|
|
|
return _("Inventory"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void SpeakInventorySlotForAccessibility() |
|
|
|
|
{ |
|
|
|
|
if (MyPlayer == nullptr) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
const Player &player = *MyPlayer; |
|
|
|
|
const Item *item = nullptr; |
|
|
|
|
|
|
|
|
|
if (Slot >= SLOTXY_BELT_FIRST && Slot <= SLOTXY_BELT_LAST) { |
|
|
|
|
item = &player.SpdList[Slot - SLOTXY_BELT_FIRST]; |
|
|
|
|
} else if (Slot >= SLOTXY_INV_FIRST && Slot <= SLOTXY_INV_LAST) { |
|
|
|
|
const int invId = GetItemIdOnSlot(Slot); |
|
|
|
|
if (invId != 0) |
|
|
|
|
item = &player.InvList[invId - 1]; |
|
|
|
|
} else { |
|
|
|
|
switch (Slot) { |
|
|
|
|
case SLOTXY_HEAD: |
|
|
|
|
item = &player.InvBody[INVLOC_HEAD]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_RING_LEFT: |
|
|
|
|
item = &player.InvBody[INVLOC_RING_LEFT]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_RING_RIGHT: |
|
|
|
|
item = &player.InvBody[INVLOC_RING_RIGHT]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_AMULET: |
|
|
|
|
item = &player.InvBody[INVLOC_AMULET]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_HAND_LEFT: |
|
|
|
|
item = &player.InvBody[INVLOC_HAND_LEFT]; |
|
|
|
|
break; |
|
|
|
|
case SLOTXY_HAND_RIGHT: { |
|
|
|
|
const Item &left = player.InvBody[INVLOC_HAND_LEFT]; |
|
|
|
|
if (!left.isEmpty() && player.GetItemLocation(left) == ILOC_TWOHAND) |
|
|
|
|
item = &left; |
|
|
|
|
else |
|
|
|
|
item = &player.InvBody[INVLOC_HAND_RIGHT]; |
|
|
|
|
} break; |
|
|
|
|
case SLOTXY_CHEST: |
|
|
|
|
item = &player.InvBody[INVLOC_CHEST]; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (item != nullptr && !item->isEmpty()) { |
|
|
|
|
if (item->_itype == ItemType::Gold) { |
|
|
|
|
const int nGold = item->_ivalue; |
|
|
|
|
SpeakText(fmt::format(fmt::runtime(ngettext("{:s} gold piece", "{:s} gold pieces", nGold)), FormatInteger(nGold)), /*force=*/true); |
|
|
|
|
} else { |
|
|
|
|
SpeakText(item->getName(), /*force=*/true); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SpeakText(StrCat(GetInventorySlotNameForSpeech(Slot), ": ", _("empty")), /*force=*/true); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get item size (grid size) on the slot specified. Returns 1x1 if none exists. |
|
|
|
|
*/ |
|
|
|
|
Size GetItemSizeOnSlot(int slot) |
|
|
|
|
{ |
|
|
|
|
if (slot >= SLOTXY_INV_FIRST && slot <= SLOTXY_INV_LAST) { |
|
|
|
|
@ -1238,14 +1239,14 @@ void InventoryMove(AxisDirection dir)
|
|
|
|
|
mousePos.y += ((itemSize.height - 1) * InventorySlotSizeInPixels.height) / 2; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (mousePos == MousePosition) { |
|
|
|
|
SpeakInventorySlotForAccessibility(); |
|
|
|
|
return; // Avoid wobbling when scaled
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SetCursorPos(mousePos); |
|
|
|
|
SpeakInventorySlotForAccessibility(); |
|
|
|
|
} |
|
|
|
|
if (mousePos == MousePosition) { |
|
|
|
|
SpeakInventorySlotForAccessibility(); |
|
|
|
|
return; // Avoid wobbling when scaled
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SetCursorPos(mousePos); |
|
|
|
|
SpeakInventorySlotForAccessibility(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Move the cursor around in the inventory |
|
|
|
|
@ -1443,12 +1444,12 @@ void StashMove(AxisDirection dir)
|
|
|
|
|
FocusOnInventory(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void HotSpellMoveInternal(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
static AxisDirectionRepeater repeater; |
|
|
|
|
dir = repeater.Get(dir); |
|
|
|
|
if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE) |
|
|
|
|
return; |
|
|
|
|
void HotSpellMoveInternal(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
static AxisDirectionRepeater repeater; |
|
|
|
|
dir = repeater.Get(dir); |
|
|
|
|
if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
auto spellListItems = GetSpellListItems(); |
|
|
|
|
|
|
|
|
|
@ -1591,14 +1592,14 @@ void StoreMove(AxisDirection moveDir)
|
|
|
|
|
|
|
|
|
|
using HandleLeftStickOrDPadFn = void (*)(devilution::AxisDirection); |
|
|
|
|
|
|
|
|
|
HandleLeftStickOrDPadFn GetLeftStickOrDPadGameUIHandler() |
|
|
|
|
{ |
|
|
|
|
if (SpellSelectFlag) { |
|
|
|
|
return &HotSpellMoveInternal; |
|
|
|
|
} |
|
|
|
|
if (IsStashOpen) { |
|
|
|
|
return &StashMove; |
|
|
|
|
} |
|
|
|
|
HandleLeftStickOrDPadFn GetLeftStickOrDPadGameUIHandler() |
|
|
|
|
{ |
|
|
|
|
if (SpellSelectFlag) { |
|
|
|
|
return &HotSpellMoveInternal; |
|
|
|
|
} |
|
|
|
|
if (IsStashOpen) { |
|
|
|
|
return &StashMove; |
|
|
|
|
} |
|
|
|
|
if (invflag) { |
|
|
|
|
return &CheckInventoryMove; |
|
|
|
|
} |
|
|
|
|
@ -1826,16 +1827,16 @@ void LogGamepadChange(GamepadLayout newGamepad)
|
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void HotSpellMove(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
HotSpellMoveInternal(dir); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent) |
|
|
|
|
{ |
|
|
|
|
ControlTypes inputType = GetInputTypeFromEvent(event); |
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void HotSpellMove(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
HotSpellMoveInternal(dir); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void DetectInputMethod(const SDL_Event &event, const ControllerButtonEvent &gamepadEvent) |
|
|
|
|
{ |
|
|
|
|
ControlTypes inputType = GetInputTypeFromEvent(event); |
|
|
|
|
|
|
|
|
|
if (inputType == ControlTypes::None) |
|
|
|
|
return; |
|
|
|
|
@ -2005,20 +2006,20 @@ void InvalidateInventorySlot()
|
|
|
|
|
/**
|
|
|
|
|
* @brief Moves the mouse to the first inventory slot. |
|
|
|
|
*/ |
|
|
|
|
void FocusOnInventory() |
|
|
|
|
{ |
|
|
|
|
Slot = SLOTXY_INV_FIRST; |
|
|
|
|
ResetInvCursorPosition(); |
|
|
|
|
SpeakInventorySlotForAccessibility(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void InventoryMoveFromKeyboard(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
if (!invflag) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
CheckInventoryMove(dir); |
|
|
|
|
} |
|
|
|
|
void FocusOnInventory() |
|
|
|
|
{ |
|
|
|
|
Slot = SLOTXY_INV_FIRST; |
|
|
|
|
ResetInvCursorPosition(); |
|
|
|
|
SpeakInventorySlotForAccessibility(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void InventoryMoveFromKeyboard(AxisDirection dir) |
|
|
|
|
{ |
|
|
|
|
if (!invflag) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
CheckInventoryMove(dir); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool PointAndClickState = false; |
|
|
|
|
|
|
|
|
|
@ -2090,10 +2091,10 @@ void plrctrls_after_game_logic()
|
|
|
|
|
Movement(*MyPlayer); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void UseBeltItem(BeltItemType type) |
|
|
|
|
{ |
|
|
|
|
for (int i = 0; i < MaxBeltItems; i++) { |
|
|
|
|
const Item &item = MyPlayer->SpdList[i]; |
|
|
|
|
void UseBeltItem(BeltItemType type) |
|
|
|
|
{ |
|
|
|
|
for (int i = 0; i < MaxBeltItems; i++) { |
|
|
|
|
const Item &item = MyPlayer->SpdList[i]; |
|
|
|
|
if (item.isEmpty()) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
@ -2105,55 +2106,56 @@ void UseBeltItem(BeltItemType type)
|
|
|
|
|
if ((type == BeltItemType::Healing && isHealing) || (type == BeltItemType::Mana && isMana)) { |
|
|
|
|
UseInvItem(INVITEM_BELT_FIRST + i); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
void UpdateTargetsForKeyboardAction() |
|
|
|
|
{ |
|
|
|
|
// Clear focus set by cursor.
|
|
|
|
|
PlayerUnderCursor = nullptr; |
|
|
|
|
pcursmonst = -1; |
|
|
|
|
pcursitem = -1; |
|
|
|
|
ObjectUnderCursor = nullptr; |
|
|
|
|
|
|
|
|
|
pcursmissile = nullptr; |
|
|
|
|
pcurstrig = -1; |
|
|
|
|
pcursquest = Q_INVALID; |
|
|
|
|
cursPosition = { -1, -1 }; |
|
|
|
|
|
|
|
|
|
if (MyPlayer == nullptr) |
|
|
|
|
return; |
|
|
|
|
if (MyPlayer->_pInvincible) |
|
|
|
|
return; |
|
|
|
|
if (DoomFlag) |
|
|
|
|
return; |
|
|
|
|
if (invflag) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
InfoString = StringOrView {}; |
|
|
|
|
FindActor(); |
|
|
|
|
FindItemOrObject(); |
|
|
|
|
FindTrigger(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void PerformPrimaryActionAutoTarget() |
|
|
|
|
{ |
|
|
|
|
if (ControlMode == ControlTypes::KeyboardAndMouse && !IsPointAndClick()) { |
|
|
|
|
UpdateTargetsForKeyboardAction(); |
|
|
|
|
} |
|
|
|
|
PerformPrimaryAction(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PerformPrimaryAction() |
|
|
|
|
{ |
|
|
|
|
if (SpellSelectFlag) { |
|
|
|
|
SetSpell(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
namespace { |
|
|
|
|
|
|
|
|
|
void UpdateTargetsForKeyboardAction() |
|
|
|
|
{ |
|
|
|
|
// Clear focus set by cursor.
|
|
|
|
|
PlayerUnderCursor = nullptr; |
|
|
|
|
pcursmonst = -1; |
|
|
|
|
pcursitem = -1; |
|
|
|
|
ObjectUnderCursor = nullptr; |
|
|
|
|
|
|
|
|
|
pcursmissile = nullptr; |
|
|
|
|
pcurstrig = -1; |
|
|
|
|
pcursquest = Q_INVALID; |
|
|
|
|
cursPosition = { -1, -1 }; |
|
|
|
|
|
|
|
|
|
if (MyPlayer == nullptr) |
|
|
|
|
return; |
|
|
|
|
if (MyPlayer->_pInvincible) |
|
|
|
|
return; |
|
|
|
|
if (DoomFlag) |
|
|
|
|
return; |
|
|
|
|
if (invflag) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
InfoString = StringOrView {}; |
|
|
|
|
FindActor(); |
|
|
|
|
FindItemOrObject(); |
|
|
|
|
FindTrigger(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void PerformPrimaryActionAutoTarget() |
|
|
|
|
{ |
|
|
|
|
CancelAutoWalk(); |
|
|
|
|
if (ControlMode == ControlTypes::KeyboardAndMouse && !IsPointAndClick()) { |
|
|
|
|
UpdateTargetsForKeyboardAction(); |
|
|
|
|
} |
|
|
|
|
PerformPrimaryAction(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PerformPrimaryAction() |
|
|
|
|
{ |
|
|
|
|
if (SpellSelectFlag) { |
|
|
|
|
SetSpell(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (invflag) { // inventory is open
|
|
|
|
|
@ -2176,9 +2178,9 @@ void PerformPrimaryAction()
|
|
|
|
|
ReleaseChrBtns(false); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Interact(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Interact(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool SpellHasActorTarget() |
|
|
|
|
{ |
|
|
|
|
@ -2322,11 +2324,11 @@ void CtrlUseInvItem()
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CtrlUseStashItem() |
|
|
|
|
{ |
|
|
|
|
if (pcursstashitem == StashStruct::EmptyCell) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
void CtrlUseStashItem() |
|
|
|
|
{ |
|
|
|
|
if (pcursstashitem == StashStruct::EmptyCell) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const Item &item = Stash.stashList[pcursstashitem]; |
|
|
|
|
if (item.isScroll()) { |
|
|
|
|
@ -2342,31 +2344,33 @@ void CtrlUseStashItem()
|
|
|
|
|
CheckStashItem(MousePosition, true, false); // Auto-equip if it's equipment
|
|
|
|
|
} else { |
|
|
|
|
UseStashItem(pcursstashitem); |
|
|
|
|
} |
|
|
|
|
// Todo reset cursor position if item is moved
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PerformSecondaryActionAutoTarget() |
|
|
|
|
{ |
|
|
|
|
if (ControlMode == ControlTypes::KeyboardAndMouse && !IsPointAndClick()) { |
|
|
|
|
UpdateTargetsForKeyboardAction(); |
|
|
|
|
} |
|
|
|
|
PerformSecondaryAction(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PerformSpellActionAutoTarget() |
|
|
|
|
{ |
|
|
|
|
if (ControlMode == ControlTypes::KeyboardAndMouse && !IsPointAndClick()) { |
|
|
|
|
UpdateTargetsForKeyboardAction(); |
|
|
|
|
} |
|
|
|
|
PerformSpellAction(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PerformSecondaryAction() |
|
|
|
|
{ |
|
|
|
|
Player &myPlayer = *MyPlayer; |
|
|
|
|
if (invflag) { |
|
|
|
|
if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) { |
|
|
|
|
} |
|
|
|
|
// Todo reset cursor position if item is moved
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PerformSecondaryActionAutoTarget() |
|
|
|
|
{ |
|
|
|
|
CancelAutoWalk(); |
|
|
|
|
if (ControlMode == ControlTypes::KeyboardAndMouse && !IsPointAndClick()) { |
|
|
|
|
UpdateTargetsForKeyboardAction(); |
|
|
|
|
} |
|
|
|
|
PerformSecondaryAction(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PerformSpellActionAutoTarget() |
|
|
|
|
{ |
|
|
|
|
CancelAutoWalk(); |
|
|
|
|
if (ControlMode == ControlTypes::KeyboardAndMouse && !IsPointAndClick()) { |
|
|
|
|
UpdateTargetsForKeyboardAction(); |
|
|
|
|
} |
|
|
|
|
PerformSpellAction(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void PerformSecondaryAction() |
|
|
|
|
{ |
|
|
|
|
Player &myPlayer = *MyPlayer; |
|
|
|
|
if (invflag) { |
|
|
|
|
if (pcurs > CURSOR_HAND && pcurs < CURSOR_FIRSTITEM) { |
|
|
|
|
TryIconCurs(); |
|
|
|
|
NewCursor(CURSOR_HAND); |
|
|
|
|
} else if (IsStashOpen) { |
|
|
|
|
|