Browse Source

Thumb stick / DPad repeating navigation in DiabloUI, gmenu, and quest log (#1206)

pull/1220/head
Gleb Mazovetskiy 5 years ago committed by GitHub
parent
commit
0f46e9c4c1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      CMakeLists.txt
  2. 60
      Source/gmenu.cpp
  3. 64
      SourceX/DiabloUI/diabloui.cpp
  4. 55
      SourceX/controls/axis_direction.cpp
  5. 48
      SourceX/controls/axis_direction.h
  6. 2
      SourceX/controls/controller.h
  7. 2
      SourceX/controls/controller_buttons.h
  8. 30
      SourceX/controls/controller_motion.cpp
  9. 9
      SourceX/controls/controller_motion.h
  10. 3
      SourceX/controls/devices/game_controller.cpp
  11. 3
      SourceX/controls/devices/joystick.cpp
  12. 55
      SourceX/controls/game_controls.cpp
  13. 25
      SourceX/controls/game_controls.h
  14. 25
      SourceX/controls/menu_controls.cpp
  15. 3
      SourceX/controls/menu_controls.h
  16. 138
      SourceX/controls/plrctrls.cpp

1
CMakeLists.txt

@ -283,6 +283,7 @@ set(devilutionx_SRCS
SourceX/controls/devices/game_controller.cpp
SourceX/controls/devices/joystick.cpp
SourceX/controls/devices/kbcontroller.cpp
SourceX/controls/axis_direction.cpp
SourceX/controls/controller.cpp
SourceX/controls/controller_motion.cpp
SourceX/controls/game_controls.cpp

60
Source/gmenu.cpp

@ -5,6 +5,9 @@
*/
#include "all.h"
#include "../SourceX/controls/axis_direction.h"
#include "../SourceX/controls/controller_motion.h"
DEVILUTION_BEGIN_NAMESPACE
BYTE *optbar_cel;
@ -133,6 +136,29 @@ static void gmenu_up_down(BOOL isDown)
}
}
static void gmenu_left_right(BOOL isRight)
{
int step, steps;
if (!(sgpCurrItem->dwFlags & GMENU_SLIDER))
return;
step = sgpCurrItem->dwFlags & 0xFFF;
steps = (int)(sgpCurrItem->dwFlags & 0xFFF000) >> 12;
if (isRight) {
if (step == steps)
return;
step++;
} else {
if (step == 0)
return;
step--;
}
sgpCurrItem->dwFlags &= 0xFFFFF000;
sgpCurrItem->dwFlags |= step;
sgpCurrItem->fnMenu(FALSE);
}
void gmenu_set_items(TMenuItem *pItem, void (*gmFunc)(TMenuItem *))
{
int i;
@ -206,6 +232,16 @@ static void gmenu_draw_menu_item(CelOutputBuffer out, TMenuItem *pItem, int y)
}
}
static void GameMenuMove()
{
static AxisDirectionRepeater repeater;
const AxisDirection move_dir = repeater.Get(GetLeftStickOrDpadDirection());
if (move_dir.x != AxisDirectionX_NONE)
gmenu_left_right(move_dir.x == AxisDirectionX_RIGHT);
if (move_dir.y != AxisDirectionY_NONE)
gmenu_up_down(move_dir.y == AxisDirectionY_DOWN);
}
void gmenu_draw(CelOutputBuffer out)
{
int y;
@ -213,6 +249,7 @@ void gmenu_draw(CelOutputBuffer out)
DWORD ticks;
if (sgpCurrentMenu) {
GameMenuMove();
if (gmenu_current_option)
gmenu_current_option(sgpCurrentMenu);
if (gbIsHellfire) {
@ -239,29 +276,6 @@ void gmenu_draw(CelOutputBuffer out)
}
}
static void gmenu_left_right(BOOL isRight)
{
int step, steps;
if (!(sgpCurrItem->dwFlags & GMENU_SLIDER))
return;
step = sgpCurrItem->dwFlags & 0xFFF;
steps = (int)(sgpCurrItem->dwFlags & 0xFFF000) >> 12;
if (isRight) {
if (step == steps)
return;
step++;
} else {
if (step == 0)
return;
step--;
}
sgpCurrItem->dwFlags &= 0xFFFFF000;
sgpCurrItem->dwFlags |= step;
sgpCurrItem->fnMenu(FALSE);
}
BOOL gmenu_presskeys(int vkey)
{
if (!sgpCurrentMenu)

64
SourceX/DiabloUI/diabloui.cpp

@ -145,6 +145,8 @@ void UiPlaySelectSound()
gfnSoundFunction("sfx\\items\\titlslct.wav");
}
namespace {
void UiFocus(std::size_t itemIndex)
{
if (SelectedItem == itemIndex)
@ -214,6 +216,39 @@ void selhero_CatToName(char *in_buf, char *out_buf, int cnt)
strncat(out_buf, output.c_str(), cnt - strlen(out_buf));
}
bool HandleMenuAction(MenuAction menu_action)
{
switch (menu_action) {
case MenuAction_SELECT:
UiFocusNavigationSelect();
return true;
case MenuAction_UP:
UiFocusUp();
return true;
case MenuAction_DOWN:
UiFocusDown();
return true;
case MenuAction_PAGE_UP:
UiFocusPageUp();
return true;
case MenuAction_PAGE_DOWN:
UiFocusPageDown();
return true;
case MenuAction_DELETE:
UiFocusNavigationYesNo();
return true;
case MenuAction_BACK:
if (!gfnListEsc)
return false;
UiFocusNavigationEsc();
return true;
default:
return false;
}
}
} // namespace
void UiFocusNavigation(SDL_Event *event)
{
switch (event->type) {
@ -239,33 +274,7 @@ void UiFocusNavigation(SDL_Event *event)
break;
}
switch (GetMenuAction(*event)) {
case MenuAction_SELECT:
UiFocusNavigationSelect();
return;
case MenuAction_UP:
UiFocusUp();
return;
case MenuAction_DOWN:
UiFocusDown();
return;
case MenuAction_PAGE_UP:
UiFocusPageUp();
return;
case MenuAction_PAGE_DOWN:
UiFocusPageDown();
return;
case MenuAction_DELETE:
UiFocusNavigationYesNo();
return;
case MenuAction_BACK:
if (!gfnListEsc)
break;
UiFocusNavigationEsc();
return;
default:
break;
}
if (HandleMenuAction(GetMenuAction(*event))) return;
#ifndef USE_SDL1
if (event->type == SDL_MOUSEWHEEL) {
@ -617,6 +626,7 @@ void UiPollAndRender()
UiFocusNavigation(&event);
UiHandleEvents(&event);
}
HandleMenuAction(GetMenuHeldUpDownAction());
UiRenderItems(gUiItems);
DrawMouse();
UiFadeIn();

55
SourceX/controls/axis_direction.cpp

@ -0,0 +1,55 @@
#include "axis_direction.h"
#include <SDL.h>
namespace dvl {
AxisDirection AxisDirectionRepeater::Get(AxisDirection axis_direction)
{
const int now = SDL_GetTicks();
switch (axis_direction.x) {
case AxisDirectionX_LEFT:
last_right_ = 0;
if (now - last_left_ < min_interval_ms_) {
axis_direction.x = AxisDirectionX_NONE;
} else {
last_left_ = now;
}
break;
case AxisDirectionX_RIGHT:
last_left_ = 0;
if (now - last_right_ < min_interval_ms_) {
axis_direction.x = AxisDirectionX_NONE;
} else {
last_right_ = now;
}
break;
case AxisDirectionX_NONE:
last_left_ = last_right_ = 0;
break;
}
switch (axis_direction.y) {
case AxisDirectionY_UP:
last_down_ = 0;
if (now - last_up_ < min_interval_ms_) {
axis_direction.y = AxisDirectionY_NONE;
} else {
last_up_ = now;
}
break;
case AxisDirectionY_DOWN:
last_up_ = 0;
if (now - last_down_ < min_interval_ms_) {
axis_direction.y = AxisDirectionY_NONE;
} else {
last_down_ = now;
}
break;
case AxisDirectionY_NONE:
last_up_ = last_down_ = 0;
break;
}
return axis_direction;
}
} // namespace

48
SourceX/controls/axis_direction.h

@ -0,0 +1,48 @@
#pragma once
namespace dvl {
enum AxisDirectionX {
AxisDirectionX_NONE = 0,
AxisDirectionX_LEFT,
AxisDirectionX_RIGHT
};
enum AxisDirectionY {
AxisDirectionY_NONE = 0,
AxisDirectionY_UP,
AxisDirectionY_DOWN
};
/**
* @brief 8-way direction of a D-Pad or a thumb stick.
*/
struct AxisDirection {
AxisDirectionX x;
AxisDirectionY y;
};
/**
* @brief Returns a non-empty AxisDirection at most once per the given time interval.
*/
class AxisDirectionRepeater {
public:
AxisDirectionRepeater(int min_interval_ms = 200)
: last_left_(0)
, last_right_(0)
, last_up_(0)
, last_down_(0)
, min_interval_ms_(min_interval_ms)
{
}
AxisDirection Get(AxisDirection axis_direction);
private:
int last_left_;
int last_right_;
int last_up_;
int last_down_;
int min_interval_ms_;
};
} // namespace dvl

2
SourceX/controls/controller.h

@ -2,7 +2,7 @@
#include <SDL.h>
#include "controls/controller_buttons.h"
#include "./controller_buttons.h"
namespace dvl {

2
SourceX/controls/controller_buttons.h

@ -1,8 +1,6 @@
#pragma once
// Unifies joystick, gamepad, and keyboard controller APIs.
#include "all.h"
namespace dvl {
// NOTE: A, B, X, Y refer to physical positions on an XBox 360 controller.

30
SourceX/controls/controller_motion.cpp

@ -1,5 +1,7 @@
#include "controls/controller_motion.h"
#include <cmath>
#include "controls/devices/game_controller.h"
#include "controls/devices/joystick.h"
#include "controls/devices/kbcontroller.h"
@ -30,7 +32,7 @@ void ScaleJoystickAxes(float *x, float *y, float deadzone)
float analog_y = *y;
float dead_zone = deadzone * maximum;
float magnitude = sqrtf(analog_x * analog_x + analog_y * analog_y);
float magnitude = std::sqrt(analog_x * analog_x + analog_y * analog_y);
if (magnitude >= dead_zone) {
// find scaled axis values with magnitudes between zero and maximum
float scalingFactor = 1.0 / magnitude * (magnitude - dead_zone) / (maximum - dead_zone);
@ -39,8 +41,8 @@ void ScaleJoystickAxes(float *x, float *y, float deadzone)
// clamp to ensure results will never exceed the max_axis value
float clamping_factor = 1.0f;
float abs_analog_x = fabs(analog_x);
float abs_analog_y = fabs(analog_y);
float abs_analog_x = std::fabs(analog_x);
float abs_analog_y = std::fabs(analog_y);
if (abs_analog_x > 1.0 || abs_analog_y > 1.0) {
if (abs_analog_x > abs_analog_y) {
clamping_factor = 1 / abs_analog_x;
@ -144,4 +146,26 @@ bool ProcessControllerMotion(const SDL_Event &event, ControllerButtonEvent ctrl_
return SimulateRightStickWithDpad(event, ctrl_event);
}
AxisDirection GetLeftStickOrDpadDirection(bool allow_dpad)
{
const float stickX = leftStickX;
const float stickY = leftStickY;
AxisDirection result { AxisDirectionX_NONE, AxisDirectionY_NONE };
if (stickY >= 0.5 || (allow_dpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_UP))) {
result.y = AxisDirectionY_UP;
} else if (stickY <= -0.5 || (allow_dpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_DOWN))) {
result.y = AxisDirectionY_DOWN;
}
if (stickX <= -0.5 || (allow_dpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_LEFT))) {
result.x = AxisDirectionX_LEFT;
} else if (stickX >= 0.5 || (allow_dpad && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_RIGHT))) {
result.x = AxisDirectionX_RIGHT;
}
return result;
}
} // namespace dvl

9
SourceX/controls/controller_motion.h

@ -2,8 +2,10 @@
// Processes and stores mouse and joystick motion.
#include "all.h"
#include "controls/controller.h"
#include <SDL.h>
#include "./axis_direction.h"
#include "./controller.h"
namespace dvl {
@ -19,4 +21,7 @@ extern bool leftStickNeedsScaling, rightStickNeedsScaling;
// Updates motion state for mouse and joystick sticks.
bool ProcessControllerMotion(const SDL_Event &event, ControllerButtonEvent ctrl_event);
// Returns direction of the left thumb stick or DPad (if allow_dpad = true).
AxisDirection GetLeftStickOrDpadDirection(bool allow_dpad = true);
} // namespace dvl

3
SourceX/controls/devices/game_controller.cpp

@ -8,6 +8,9 @@
#include "controls/devices/joystick.h"
#include "stubs.h"
// Defined in SourceX/controls/plctrls.cpp
extern "C" bool sgbControllerActive;
namespace dvl {
std::vector<GameController> *const GameController::controllers_ = new std::vector<GameController>;

3
SourceX/controls/devices/joystick.cpp

@ -6,6 +6,9 @@
#include "controls/controller_motion.h"
#include "stubs.h"
// Defined in SourceX/controls/plctrls.cpp
extern "C" bool sgbControllerActive;
namespace dvl {
std::vector<Joystick> *const Joystick::joysticks_ = new std::vector<Joystick>;

55
SourceX/controls/game_controls.cpp

@ -14,10 +14,10 @@ namespace dvl {
bool start_modifier_active = false;
bool select_modifier_active = false;
// gamepad dpad acts as hotkeys without holding "start"
/** Gamepad dpad acts as hotkeys without holding "start" */
bool dpad_hotkeys = false;
// shoulder gamepad buttons act as potions by default
/** Shoulder gamepad buttons act as potions by default */
bool switch_potions_and_clicks = false;
namespace {
@ -152,33 +152,33 @@ bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrl_event, Gam
case ControllerButton_BUTTON_DPAD_UP:
if (IsControllerButtonPressed(ControllerButton_BUTTON_BACK))
*action = GameActionSendKey{ DVL_VK_F6, ctrl_event.up };
else
else
*action = GameActionSendKey{ DVL_VK_ESCAPE, ctrl_event.up };
return true;
case ControllerButton_BUTTON_DPAD_RIGHT:
if (IsControllerButtonPressed(ControllerButton_BUTTON_BACK))
*action = GameActionSendKey{ DVL_VK_F8, ctrl_event.up };
else
else
if (!ctrl_event.up)
*action = GameAction(GameActionType_TOGGLE_INVENTORY);
return true;
case ControllerButton_BUTTON_DPAD_DOWN:
if (IsControllerButtonPressed(ControllerButton_BUTTON_BACK))
*action = GameActionSendKey{ DVL_VK_F7, ctrl_event.up };
else
else
*action = GameActionSendKey{ DVL_VK_TAB, ctrl_event.up };
return true;
case ControllerButton_BUTTON_DPAD_LEFT:
if (IsControllerButtonPressed(ControllerButton_BUTTON_BACK))
*action = GameActionSendKey{ DVL_VK_F5, ctrl_event.up };
else
else
if (!ctrl_event.up)
*action = GameAction(GameActionType_TOGGLE_CHARACTER_INFO);
return true;
default:
break;
default:
break;
}
}
}
if (start_modifier_active) {
switch (ctrl_event.button) {
case ControllerButton_BUTTON_DPAD_UP:
@ -308,6 +308,20 @@ bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrl_event, Gam
}
// DPad navigation is handled separately for these.
if (gmenu_is_active() || questlog)
{
switch (ctrl_event.button) {
case ControllerButton_BUTTON_DPAD_UP:
case ControllerButton_BUTTON_DPAD_DOWN:
case ControllerButton_BUTTON_DPAD_LEFT:
case ControllerButton_BUTTON_DPAD_RIGHT:
return true;
default:
break;
}
}
// By default, map to a keyboard key.
if (ctrl_event.button != ControllerButton_NONE) {
*action = GameActionSendKey{ translate_controller_button_to_key(ctrl_event.button),
@ -330,26 +344,9 @@ bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrl_event, Gam
return false;
}
MoveDirection GetMoveDirection()
AxisDirection GetMoveDirection()
{
const float stickX = leftStickX;
const float stickY = leftStickY;
MoveDirection result{ MoveDirectionX_NONE, MoveDirectionY_NONE };
if (stickY >= 0.5 || (!dpad_hotkeys && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_UP))) {
result.y = MoveDirectionY_UP;
} else if (stickY <= -0.5 || (!dpad_hotkeys && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_DOWN))) {
result.y = MoveDirectionY_DOWN;
}
if (stickX <= -0.5 || (!dpad_hotkeys && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_LEFT))) {
result.x = MoveDirectionX_LEFT;
} else if (stickX >= 0.5 || (!dpad_hotkeys && IsControllerButtonPressed(ControllerButton_BUTTON_DPAD_RIGHT))) {
result.x = MoveDirectionX_RIGHT;
}
return result;
return GetLeftStickOrDpadDirection(/*allow_dpad=*/!dpad_hotkeys);
}
} // namespace dvl

25
SourceX/controls/game_controls.h

@ -1,7 +1,10 @@
#pragma once
#include "all.h"
#include "controls/controller.h"
#include <cstdint>
#include <SDL.h>
#include "./axis_direction.h"
#include "./controller.h"
namespace dvl {
@ -22,7 +25,7 @@ enum GameActionType {
};
struct GameActionSendKey {
DWORD vk_code;
Uint32 vk_code;
bool up;
};
@ -68,21 +71,7 @@ struct GameAction {
bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrl_event, GameAction *action);
enum MoveDirectionX {
MoveDirectionX_NONE = 0,
MoveDirectionX_LEFT,
MoveDirectionX_RIGHT
};
enum MoveDirectionY {
MoveDirectionY_NONE = 0,
MoveDirectionY_UP,
MoveDirectionY_DOWN
};
struct MoveDirection {
MoveDirectionX x;
MoveDirectionY y;
};
MoveDirection GetMoveDirection();
AxisDirection GetMoveDirection();
extern bool start_modifier_active;
extern bool select_modifier_active;

25
SourceX/controls/menu_controls.cpp

@ -1,14 +1,36 @@
#include "controls/menu_controls.h"
#include "controls/axis_direction.h"
#include "controls/controller.h"
#include "controls/controller_motion.h"
#include "controls/remap_keyboard.h"
#include "DiabloUI/diabloui.h"
namespace dvl {
MenuAction GetMenuHeldUpDownAction()
{
static AxisDirectionRepeater repeater;
const AxisDirection dir = repeater.Get(GetLeftStickOrDpadDirection());
switch (dir.y) {
case AxisDirectionY_UP:
return MenuAction_UP;
case AxisDirectionY_DOWN:
return MenuAction_DOWN;
default:
return MenuAction_NONE;
}
}
MenuAction GetMenuAction(const SDL_Event &event)
{
const ControllerButtonEvent ctrl_event = ToControllerButtonEvent(event);
if (ProcessControllerMotion(event, ctrl_event)) {
sgbControllerActive = true;
return GetMenuHeldUpDownAction();
}
if (ctrl_event.button != ControllerButton_NONE)
sgbControllerActive = true;
@ -25,9 +47,8 @@ MenuAction GetMenuAction(const SDL_Event &event)
case ControllerButton_BUTTON_X: // Left button
return MenuAction_DELETE;
case ControllerButton_BUTTON_DPAD_UP:
return MenuAction_UP;
case ControllerButton_BUTTON_DPAD_DOWN:
return MenuAction_DOWN;
return GetMenuHeldUpDownAction();
case ControllerButton_BUTTON_DPAD_LEFT:
return MenuAction_LEFT;
case ControllerButton_BUTTON_DPAD_RIGHT:

3
SourceX/controls/menu_controls.h

@ -21,4 +21,7 @@ enum MenuAction {
MenuAction GetMenuAction(const SDL_Event &event);
/** Menu action from holding the left stick or DPad. */
MenuAction GetMenuHeldUpDownAction();
} // namespace dvl

138
SourceX/controls/plrctrls.cpp

@ -14,7 +14,6 @@ namespace dvl {
bool sgbControllerActive = false;
coords speedspellscoords[50];
const int repeatRate = 100;
int speedspellcount = 0;
/**
@ -33,7 +32,6 @@ bool InGameMenu()
namespace {
DWORD invmove = 0;
int slot = SLOTXY_INV_FIRST;
/**
@ -446,22 +444,16 @@ void Interact()
}
}
void AttrIncBtnSnap(MoveDirectionY dir)
void AttrIncBtnSnap(AxisDirection dir)
{
if (dir == MoveDirectionY_NONE) {
invmove = 0;
static AxisDirectionRepeater repeater;
dir = repeater.Get(dir);
if (dir.y == AxisDirectionY_NONE)
return;
}
if (chrbtnactive && plr[myplr]._pStatPts <= 0)
return;
DWORD ticks = SDL_GetTicks();
if (ticks - invmove < repeatRate) {
return;
}
invmove = ticks;
// first, find our cursor location
int slot = 0;
for (int i = 0; i < 4; i++) {
@ -474,10 +466,10 @@ void AttrIncBtnSnap(MoveDirectionY dir)
}
}
if (dir == MoveDirectionY_UP) {
if (dir.y == AxisDirectionY_UP) {
if (slot > 0)
--slot;
} else if (dir == MoveDirectionY_DOWN) {
} else if (dir.y == AxisDirectionY_DOWN) {
if (slot < 3)
++slot;
}
@ -493,18 +485,13 @@ void AttrIncBtnSnap(MoveDirectionY dir)
* If mouse coords are at SLOTXY_CHEST_LAST, consider this center of equipment
* small inventory squares are 29x29 (roughly)
*/
void InvMove(MoveDirection dir)
void InvMove(AxisDirection dir)
{
if (dir.x == MoveDirectionX_NONE && dir.y == MoveDirectionY_NONE) {
invmove = 0;
static AxisDirectionRepeater repeater(/*min_interval_ms=*/100);
dir = repeater.Get(dir);
if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE)
return;
}
DWORD ticks = SDL_GetTicks();
if (ticks - invmove < repeatRate) {
return;
}
invmove = ticks;
int x = MouseX;
int y = MouseY;
@ -529,7 +516,7 @@ void InvMove(MoveDirection dir)
slot = SLOTXY_BELT_LAST;
// when item is on cursor, this is the real cursor XY
if (dir.x == MoveDirectionX_LEFT) {
if (dir.x == AxisDirectionX_LEFT) {
if (slot >= SLOTXY_HAND_RIGHT_FIRST && slot <= SLOTXY_HAND_RIGHT_LAST) {
x = InvRect[SLOTXY_CHEST_FIRST].X + RIGHT_PANEL + (INV_SLOT_SIZE_PX / 2);
y = InvRect[SLOTXY_CHEST_FIRST].Y - (INV_SLOT_SIZE_PX / 2);
@ -561,7 +548,7 @@ void InvMove(MoveDirection dir)
x = InvRect[slot].X + PANEL_LEFT + (INV_SLOT_SIZE_PX / 2);
y = InvRect[slot].Y + PANEL_TOP - (INV_SLOT_SIZE_PX / 2);
}
} else if (dir.x == MoveDirectionX_RIGHT) {
} else if (dir.x == AxisDirectionX_RIGHT) {
if (slot == SLOTXY_RING_LEFT) {
x = InvRect[SLOTXY_RING_RIGHT].X + RIGHT_PANEL + (INV_SLOT_SIZE_PX / 2);
y = InvRect[SLOTXY_RING_RIGHT].Y - (INV_SLOT_SIZE_PX / 2);
@ -592,7 +579,7 @@ void InvMove(MoveDirection dir)
y = InvRect[slot].Y + PANEL_TOP - (INV_SLOT_SIZE_PX / 2);
}
}
if (dir.y == MoveDirectionY_UP) {
if (dir.y == AxisDirectionY_UP) {
if (slot > 24 && slot <= 27) { // first 3 general slots
x = InvRect[SLOTXY_RING_LEFT].X + RIGHT_PANEL + (INV_SLOT_SIZE_PX / 2);
y = InvRect[SLOTXY_RING_LEFT].Y - (INV_SLOT_SIZE_PX / 2);
@ -626,7 +613,7 @@ void InvMove(MoveDirection dir)
x = InvRect[slot].X + RIGHT_PANEL + (INV_SLOT_SIZE_PX / 2);
y = InvRect[slot].Y - (INV_SLOT_SIZE_PX / 2);
}
} else if (dir.y == MoveDirectionY_DOWN) {
} else if (dir.y == AxisDirectionY_DOWN) {
if (slot >= SLOTXY_HEAD_FIRST && slot <= SLOTXY_HEAD_LAST) {
x = InvRect[SLOTXY_CHEST_FIRST].X + RIGHT_PANEL + (INV_SLOT_SIZE_PX / 2);
y = InvRect[SLOTXY_CHEST_FIRST].Y - (INV_SLOT_SIZE_PX / 2);
@ -688,18 +675,12 @@ bool HSExists(int x, int y)
return false;
}
void HotSpellMove(MoveDirection dir)
void HotSpellMove(AxisDirection dir)
{
if (dir.x == MoveDirectionX_NONE && dir.y == MoveDirectionY_NONE) {
invmove = 0;
return;
}
DWORD ticks = SDL_GetTicks();
if (ticks - invmove < repeatRate) {
static AxisDirectionRepeater repeater;
dir = repeater.Get(dir);
if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE)
return;
}
invmove = ticks;
int spbslot = plr[myplr]._pRSpell;
for (int r = 0; r < speedspellcount; r++) {
@ -715,23 +696,23 @@ void HotSpellMove(MoveDirection dir)
int x = speedspellscoords[spbslot].x;
int y = speedspellscoords[spbslot].y;
if (dir.x == MoveDirectionX_LEFT) {
if (dir.x == AxisDirectionX_LEFT) {
if (spbslot < speedspellcount - 1) {
x = speedspellscoords[spbslot + 1].x;
y = speedspellscoords[spbslot + 1].y;
}
} else if (dir.x == MoveDirectionX_RIGHT) {
} else if (dir.x == AxisDirectionX_RIGHT) {
if (spbslot > 0) {
x = speedspellscoords[spbslot - 1].x;
y = speedspellscoords[spbslot - 1].y;
}
}
if (dir.y == MoveDirectionY_UP) {
if (dir.y == AxisDirectionY_UP) {
if (HSExists(x, y - SPLICONLENGTH)) {
y -= SPLICONLENGTH;
}
} else if (dir.y == MoveDirectionY_DOWN) {
} else if (dir.y == AxisDirectionY_DOWN) {
if (HSExists(x, y + SPLICONLENGTH)) {
y += SPLICONLENGTH;
}
@ -742,23 +723,15 @@ void HotSpellMove(MoveDirection dir)
}
}
void SpellBookMove(MoveDirection dir)
void SpellBookMove(AxisDirection dir)
{
if (dir.x == MoveDirectionX_NONE && dir.y == MoveDirectionY_NONE) {
invmove = 0;
return;
}
static AxisDirectionRepeater repeater;
dir = repeater.Get(dir);
DWORD ticks = SDL_GetTicks();
if (ticks - invmove < repeatRate) {
return;
}
invmove = ticks;
if (dir.x == MoveDirectionX_LEFT) {
if (dir.x == AxisDirectionX_LEFT) {
if (sbooktab > 0)
sbooktab--;
} else if (dir.x == MoveDirectionX_RIGHT) {
} else if (dir.x == AxisDirectionX_RIGHT) {
if ((gbIsHellfire && sbooktab < 4) || (!gbIsHellfire && sbooktab < 3))
sbooktab++;
}
@ -827,12 +800,12 @@ bool IsPathBlocked(int x, int y, int dir)
return !PosOkPlayer(myplr, d1x, d1y) && !PosOkPlayer(myplr, d2x, d2y);
}
void WalkInDir(MoveDirection dir)
void WalkInDir(AxisDirection dir)
{
const int x = plr[myplr]._pfutx;
const int y = plr[myplr]._pfuty;
if (dir.x == MoveDirectionX_NONE && dir.y == MoveDirectionY_NONE) {
if (dir.x == AxisDirectionX_NONE && dir.y == AxisDirectionY_NONE) {
if (sgbControllerActive && plr[myplr].walkpath[0] != WALK_NONE && plr[myplr].destAction == ACTION_NONE)
NetSendCmdLoc(true, CMD_WALKXY, x, y); // Stop walking
return;
@ -849,27 +822,56 @@ void WalkInDir(MoveDirection dir)
NetSendCmdLoc(true, CMD_WALKXY, dx, dy);
}
void QuestLogMove(AxisDirection move_dir)
{
static AxisDirectionRepeater repeater;
move_dir = repeater.Get(move_dir);
if (move_dir.y == AxisDirectionY_UP)
QuestlogUp();
else if (move_dir.y == AxisDirectionY_DOWN)
QuestlogDown();
}
typedef void (*HandleLeftStickOrDPadFn)(dvl::AxisDirection);
HandleLeftStickOrDPadFn GetLeftStickOrDPadGameUIHandler()
{
if (invflag) {
return &InvMove;
} else if (chrflag && plr[myplr]._pStatPts > 0) {
return &AttrIncBtnSnap;
} else if (spselflag) {
return &HotSpellMove;
} else if (sbookflag) {
return &SpellBookMove;
} else if (questlog) {
return &QuestLogMove;
}
return NULL;
}
void ProcessLeftStickOrDPadGameUI() {
HandleLeftStickOrDPadFn handler = GetLeftStickOrDPadGameUIHandler();
if (handler != NULL)
handler(GetLeftStickOrDpadDirection(true));
}
void Movement()
{
if (InGameMenu() || questlog
if (InGameMenu()
|| IsControllerButtonPressed(ControllerButton_BUTTON_START)
|| IsControllerButtonPressed(ControllerButton_BUTTON_BACK))
return;
MoveDirection move_dir = GetMoveDirection();
if (move_dir.x != MoveDirectionX_NONE || move_dir.y != MoveDirectionY_NONE) {
AxisDirection move_dir = GetMoveDirection();
if (move_dir.x != AxisDirectionX_NONE || move_dir.y != AxisDirectionY_NONE) {
sgbControllerActive = true;
}
if (invflag) {
InvMove(move_dir);
} else if (chrflag && plr[myplr]._pStatPts > 0) {
AttrIncBtnSnap(move_dir.y);
} else if (spselflag) {
HotSpellMove(move_dir);
} else if (sbookflag) {
SpellBookMove(move_dir);
} else {
// TODO: This should be called independently of game logic / tick rate.
ProcessLeftStickOrDPadGameUI();
if (GetLeftStickOrDPadGameUIHandler() == NULL) {
WalkInDir(move_dir);
}
}

Loading…
Cancel
Save