# include "controls/plrctrls.h"
# include <cstdint>
# include "controls/controller_motion.h"
# include "controls/game_controls.h"
// Based on the Nintendo Switch port by @lantus, @erfg12, @rsn8887.
namespace dvl {
bool sgbControllerActive = false ;
coords speedspellscoords [ 50 ] ;
const int repeatRate = 100 ;
int speedspellcount = 0 ;
// Native game menu, controlled by simulating a keyboard.
bool InGameMenu ( )
{
return stextflag > 0 | | questlog | | helpflag | | talkflag | | qtextflag | | sgpCurrentMenu ;
}
namespace {
DWORD invmove = 0 ;
int hsr [ 3 ] = { 0 , 0 , 0 } ; // hot spell row counts
int slot = SLOTXY_INV_FIRST ;
int spbslot = 0 ;
// 0 = not near, >0 = distance related player 1 coordinates
coords CheckNearbyObjs ( int x , int y , int diff )
{
int diff_x = abs ( plr [ myplr ] . _px - x ) ;
int diff_y = abs ( plr [ myplr ] . _py - y ) ;
if ( diff_x < = diff & & diff_y < = diff ) {
coords cm = { diff_x , diff_y } ;
//sprintf(tempstr, "N-DIFF X:%i Y:%i", diff_x, diff_y);
//NetSendCmdString(1 << myplr, tempstr);
return cm ;
}
return { - 1 , - 1 } ;
}
void CheckItemsNearby ( )
{
for ( int i = 0 ; i < MAXITEMS ; i + + ) {
if ( CheckNearbyObjs ( item [ i ] . _ix , item [ i ] . _iy , 1 ) . x ! = - 1 & & item [ i ] . _iSelFlag > 0 & & item [ i ] . _itype > - 1 ) {
if ( dItem [ item [ i ] . _ix ] [ item [ i ] . _iy ] < = 0 )
continue ;
pcursitem = i ;
return ; // item nearby, don't find objects
}
}
for ( int i = 0 ; i < MAXOBJECTS ; i + + ) {
if ( CheckNearbyObjs ( object [ i ] . _ox , object [ i ] . _oy , 1 ) . x ! = - 1 & & object [ i ] . _oSelFlag > 0 & & object [ i ] . _otype > - 1 & & currlevel ) { // make sure we're in the dungeon to scan for objs
pcursobj = i ;
return ;
}
}
}
void CheckTownersNearby ( )
{
for ( int i = 0 ; i < 16 ; i + + ) {
if ( CheckNearbyObjs ( towner [ i ] . _tx , towner [ i ] . _ty , 2 ) . x ! = - 1 ) {
if ( towner [ i ] . _ttype = = - 1 )
continue ;
pcursmonst = i ;
break ;
}
}
}
void CheckMonstersNearby ( )
{
coords objDistLast = { 99 , 99 } ; // previous obj distance
// The first MAX_PLRS monsters are reserved for players' golems.
for ( int i = MAX_PLRS ; i < MAXMONSTERS ; i + + ) {
const auto & monst = monster [ i ] ;
const int mx = monst . _mx ;
const int my = monst . _my ;
if ( dMonster [ mx ] [ my ] = = 0 | | ( monst . _mFlags & MFLAG_HIDDEN ) | | // hidden
monst . _mhitpoints < = 0 | | // dead
! ( ( dFlags [ mx ] [ my ] & BFLAG_LIT ) | | plr [ myplr ] . _pInfraFlag ) ) // not visable
continue ;
const char mSelFlag = monst . MData - > mSelFlag ;
if ( mSelFlag & 1 | | mSelFlag & 2 | | mSelFlag & 3 | | mSelFlag & 4 ) { // is monster selectable
coords objDist = CheckNearbyObjs ( mx , my , 6 ) ;
if ( objDist . x > - 1 & & objDist . x < = objDistLast . x & & objDist . y < = objDistLast . y ) {
pcursmonst = i ;
objDistLast = objDist ;
}
}
}
}
void Interact ( )
{
if ( leveltype = = DTYPE_TOWN & & pcursmonst ! = - 1 ) {
NetSendCmdLocParam1 ( true , CMD_TALKXY , towner [ pcursmonst ] . _tx , towner [ pcursmonst ] . _ty , pcursmonst ) ;
} else if ( pcursmonst ! = - 1 ) {
if ( plr [ myplr ] . _pwtype ! = WT_RANGED | | CanTalkToMonst ( pcursmonst ) ) {
NetSendCmdParam1 ( true , CMD_ATTACKID , pcursmonst ) ;
} else {
NetSendCmdParam1 ( true , CMD_RATTACKID , pcursmonst ) ;
}
} else if ( pcursplr ! = - 1 & & ! FriendlyMode ) {
NetSendCmdParam1 ( true , plr [ myplr ] . _pwtype = = WT_RANGED ? CMD_RATTACKPID : CMD_ATTACKPID , pcursplr ) ;
}
}
void AttrIncBtnSnap ( MoveDirectionY dir )
{
if ( dir = = MoveDirectionY : : NONE )
return ;
if ( chrbtnactive & & plr [ myplr ] . _pStatPts < = 0 )
return ;
DWORD ticks = GetTickCount ( ) ;
if ( ticks - invmove < repeatRate ) {
return ;
}
invmove = ticks ;
// first, find our cursor location
int slot = 0 ;
for ( int i = 0 ; i < 4 ; i + + ) {
if ( MouseX > = ChrBtnsRect [ i ] . x
& & MouseX < = ChrBtnsRect [ i ] . x + ChrBtnsRect [ i ] . w
& & MouseY > = ChrBtnsRect [ i ] . y
& & MouseY < = ChrBtnsRect [ i ] . h + ChrBtnsRect [ i ] . y ) {
slot = i ;
break ;
}
}
if ( dir = = MoveDirectionY : : UP ) {
if ( slot > 0 )
- - slot ;
} else if ( dir = = MoveDirectionY : : DOWN ) {
if ( slot < 3 )
+ + slot ;
}
// move cursor to our new location
int x = ChrBtnsRect [ slot ] . x + ( ChrBtnsRect [ slot ] . w / 2 ) ;
int y = ChrBtnsRect [ slot ] . y + ( ChrBtnsRect [ slot ] . h / 2 ) ;
SetCursorPos ( x , y ) ;
}
// move the cursor around in our inventory
// if mouse coords are at SLOTXY_CHEST_LAST, consider this center of equipment
// small inventory squares are 29x29 (roughly)
void InvMove ( MoveDirection dir )
{
DWORD ticks = GetTickCount ( ) ;
if ( ticks - invmove < repeatRate ) {
return ;
}
invmove = ticks ;
int x = MouseX ;
int y = MouseY ;
// check which inventory rectangle the mouse is in, if any
for ( int r = 0 ; ( DWORD ) r < NUM_XY_SLOTS ; r + + ) {
if ( x > = InvRect [ r ] . X & & x < InvRect [ r ] . X + ( INV_SLOT_SIZE_PX + 1 ) & & y > = InvRect [ r ] . Y - ( INV_SLOT_SIZE_PX + 1 ) & & y < InvRect [ r ] . Y ) {
slot = r ;
break ;
}
}
if ( slot < 0 )
slot = 0 ;
if ( slot > SLOTXY_BELT_LAST )
slot = SLOTXY_BELT_LAST ;
// when item is on cursor, this is the real cursor XY
if ( dir . x = = MoveDirectionX : : LEFT ) {
if ( slot > = SLOTXY_HAND_RIGHT_FIRST & & slot < = SLOTXY_HAND_RIGHT_LAST ) {
x = InvRect [ SLOTXY_CHEST_FIRST ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_CHEST_FIRST ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_CHEST_FIRST & & slot < = SLOTXY_CHEST_LAST ) {
x = InvRect [ SLOTXY_HAND_LEFT_FIRST + 2 ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_HAND_LEFT_FIRST + 2 ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_AMULET ) {
x = InvRect [ SLOTXY_HEAD_FIRST ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_HEAD_FIRST ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_RING_RIGHT ) {
x = InvRect [ SLOTXY_RING_LEFT ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_RING_LEFT ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_BELT_FIRST ) {
// do nothing
} else if ( slot = = SLOTXY_RING_LEFT ) { // left ring
// do nothing
} else if ( slot > = SLOTXY_HAND_LEFT_FIRST & & slot < = SLOTXY_HAND_LEFT_LAST ) { // left hand
// do nothing
} else if ( slot > = SLOTXY_HEAD_FIRST & & slot < = SLOTXY_HEAD_LAST ) { // head
// do nothing
} else if ( slot > SLOTXY_INV_FIRST ) { // general inventory
if ( slot ! = SLOTXY_INV_FIRST & & slot ! = 35 & & slot ! = 45 & & slot ! = 55 ) { // left bounds
slot - = 1 ;
x = InvRect [ slot ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ slot ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
}
}
} else if ( dir . x = = MoveDirectionX : : RIGHT ) {
if ( slot = = SLOTXY_RING_LEFT ) {
x = InvRect [ SLOTXY_RING_RIGHT ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_RING_RIGHT ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_HAND_LEFT_FIRST & & slot < = SLOTXY_HAND_LEFT_LAST ) {
x = InvRect [ SLOTXY_CHEST_FIRST ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_CHEST_FIRST ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_CHEST_FIRST & & slot < = SLOTXY_CHEST_LAST ) {
x = InvRect [ SLOTXY_HAND_RIGHT_FIRST + 2 ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_HAND_RIGHT_FIRST + 2 ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_HEAD_FIRST & & slot < = SLOTXY_HEAD_LAST ) { // head to amulet
x = InvRect [ SLOTXY_AMULET ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_AMULET ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_HAND_RIGHT_FIRST & & slot < = SLOTXY_HAND_RIGHT_LAST ) { // right hand
// do nothing
} else if ( slot = = SLOTXY_AMULET ) {
// do nothing
} else if ( slot = = SLOTXY_RING_RIGHT ) {
// do nothing
} else if ( slot < SLOTXY_BELT_LAST & & slot > = SLOTXY_INV_FIRST ) { // general inventory
if ( slot ! = 34 & & slot ! = 44 & & slot ! = 54 & & slot ! = SLOTXY_INV_LAST ) { // right bounds
slot + = 1 ;
x = InvRect [ slot ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ slot ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
}
}
}
if ( dir . y = = MoveDirectionY : : UP ) {
if ( slot > 24 & & slot < = 27 ) { // first 3 general slots
x = InvRect [ SLOTXY_RING_LEFT ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_RING_LEFT ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = 28 & & slot < = 32 ) { // middle 4 general slots
x = InvRect [ SLOTXY_CHEST_FIRST ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_CHEST_FIRST ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = 33 & & slot < 35 ) { // last 3 general slots
x = InvRect [ SLOTXY_RING_RIGHT ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_RING_RIGHT ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_CHEST_FIRST & & slot < = SLOTXY_CHEST_LAST ) { // chest to head
x = InvRect [ SLOTXY_HEAD_FIRST ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_HEAD_FIRST ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_RING_LEFT ) { // left ring to left hand
x = InvRect [ SLOTXY_HAND_LEFT_FIRST + 2 ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_HAND_LEFT_FIRST + 2 ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_RING_RIGHT ) { // right ring to right hand
x = InvRect [ SLOTXY_HAND_RIGHT_FIRST + 2 ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_HAND_RIGHT_FIRST + 2 ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_HAND_RIGHT_FIRST & & slot < = SLOTXY_HAND_RIGHT_LAST ) { // right hand to amulet
x = InvRect [ SLOTXY_AMULET ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_AMULET ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_HEAD_FIRST & & slot < = SLOTXY_HEAD_LAST ) {
// do nothing
} else if ( slot > = SLOTXY_HAND_LEFT_FIRST & & slot < = SLOTXY_HAND_LEFT_LAST ) { // left hand to head
x = InvRect [ SLOTXY_HEAD_FIRST ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_HEAD_FIRST ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_AMULET ) {
// do nothing
} else if ( slot > = ( SLOTXY_INV_FIRST + 10 ) ) { // general inventory
slot - = 10 ;
x = InvRect [ slot ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ slot ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
}
} else if ( dir . y = = MoveDirectionY : : DOWN ) {
if ( slot > = SLOTXY_HEAD_FIRST & & slot < = SLOTXY_HEAD_LAST ) {
x = InvRect [ SLOTXY_CHEST_FIRST ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_CHEST_FIRST ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_CHEST_FIRST & & slot < = SLOTXY_CHEST_LAST ) {
x = InvRect [ 30 ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ 30 ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_HAND_LEFT_FIRST & & slot < = SLOTXY_HAND_LEFT_LAST ) {
x = InvRect [ SLOTXY_RING_LEFT ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_RING_LEFT ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_RING_LEFT ) {
x = InvRect [ 26 ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ 26 ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_RING_RIGHT ) {
x = InvRect [ 34 ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ 34 ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot = = SLOTXY_AMULET ) {
x = InvRect [ SLOTXY_HAND_RIGHT_FIRST + 2 ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_HAND_RIGHT_FIRST + 2 ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot > = SLOTXY_HAND_RIGHT_FIRST & & slot < = SLOTXY_HAND_RIGHT_LAST ) {
x = InvRect [ SLOTXY_RING_RIGHT ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ SLOTXY_RING_RIGHT ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
} else if ( slot < ( SLOTXY_BELT_LAST - 10 ) ) { // general inventory
slot + = 10 ;
x = InvRect [ slot ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ slot ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
}
}
if ( x = = MouseX & & y = = MouseY ) {
return ; // Avoid wobeling when scalled
}
if ( pcurs > 1 ) { // [3] Keep item in the same slot, don't jump it up
if ( x ! = MouseX ) { // without this, the cursor keeps moving -10
x - = 10 ;
y - = 10 ;
}
}
SetCursorPos ( x , y ) ;
}
// check if hot spell at X Y exists
bool HSExists ( int x , int y )
{
for ( int r = 0 ; r < speedspellcount ; r + + ) { // speedbook cells are 56x56
if ( MouseX > = speedspellscoords [ r ] . x - 28 & & MouseX < speedspellscoords [ r ] . x + ( 28 ) & & MouseY > = speedspellscoords [ r ] . y - ( 28 ) & & MouseY < speedspellscoords [ r ] . y + 28 ) {
return true ;
}
}
return false ;
}
void HotSpellMove ( MoveDirection dir )
{
int x = 0 ;
int y = 0 ;
DWORD ticks = GetTickCount ( ) ;
if ( ticks - invmove < repeatRate ) {
return ;
}
invmove = ticks ;
for ( int r = 0 ; r < speedspellcount ; r + + ) { // speedbook cells are 56x56
// our 3 rows by y axis
if ( speedspellscoords [ r ] . y = = 307 )
hsr [ 0 ] + + ;
if ( speedspellscoords [ r ] . y = = 251 )
hsr [ 1 ] + + ;
if ( speedspellscoords [ r ] . y = = 195 )
hsr [ 2 ] + + ;
if ( MouseX > = speedspellscoords [ r ] . x - 28 & & MouseX < speedspellscoords [ r ] . x + ( 28 ) & & MouseY > = speedspellscoords [ r ] . y - ( 28 ) & & MouseY < speedspellscoords [ r ] . y + 28 ) {
spbslot = r ;
//sprintf(tempstr, "IN HOT SPELL CELL NUM:%i", r);
//NetSendCmdString(1 << myplr, tempstr);
}
}
if ( dir . y = = MoveDirectionY : : UP ) {
if ( speedspellscoords [ spbslot ] . y = = 307 & & hsr [ 1 ] > 0 ) { // we're in row 1, check if row 2 has spells
if ( HSExists ( MouseX , 251 ) ) {
x = MouseX ;
y = 251 ;
}
} else if ( speedspellscoords [ spbslot ] . y = = 251 & & hsr [ 2 ] > 0 ) { // we're in row 2, check if row 3 has spells
if ( HSExists ( MouseX , 195 ) ) {
x = MouseX ;
y = 195 ;
}
}
} else if ( dir . y = = MoveDirectionY : : DOWN ) {
if ( speedspellscoords [ spbslot ] . y = = 251 ) { // we're in row 2
if ( HSExists ( MouseX , 307 ) ) {
x = MouseX ;
y = 307 ;
}
} else if ( speedspellscoords [ spbslot ] . y = = 195 ) { // we're in row 3
if ( HSExists ( MouseX , 251 ) ) {
x = MouseX ;
y = 251 ;
}
}
}
if ( dir . x = = MoveDirectionX : : LEFT ) {
if ( spbslot > = speedspellcount - 1 )
return ;
spbslot + + ;
x = speedspellscoords [ spbslot ] . x ;
y = speedspellscoords [ spbslot ] . y ;
} else if ( dir . x = = MoveDirectionX : : RIGHT ) {
if ( spbslot < = 0 )
return ;
spbslot - - ;
x = speedspellscoords [ spbslot ] . x ;
y = speedspellscoords [ spbslot ] . y ;
}
if ( x > 0 & & y > 0 ) {
SetCursorPos ( x , y ) ;
}
}
static const _walk_path kMoveToWalkDir [ 3 ] [ 3 ] = {
// NONE UP DOWN
{ WALK_NONE , WALK_N , WALK_S } , // NONE
{ WALK_W , WALK_NW , WALK_SW } , // LEFT
{ WALK_E , WALK_NE , WALK_SE } , // RIGHT
} ;
static const direction kFaceDir [ 3 ] [ 3 ] = {
// NONE UP DOWN
{ DIR_OMNI , DIR_N , DIR_S } , // NONE
{ DIR_W , DIR_NW , DIR_SW } , // LEFT
{ DIR_E , DIR_NE , DIR_SE } , // RIGHT
} ;
void WalkInDir ( MoveDirection dir )
{
if ( dir . x = = MoveDirectionX : : NONE & & dir . y = = MoveDirectionY : : NONE ) {
if ( sgbControllerActive & & plr [ myplr ] . destAction = = ACTION_NONE )
ClrPlrPath ( myplr ) ;
return ;
}
ClrPlrPath ( myplr ) ;
plr [ myplr ] . walkpath [ 0 ] = kMoveToWalkDir [ static_cast < std : : size_t > ( dir . x ) ] [ static_cast < std : : size_t > ( dir . y ) ] ;
plr [ myplr ] . destAction = ACTION_NONE ; // stop attacking, etc.
plr [ myplr ] . _pdir = kFaceDir [ static_cast < std : : size_t > ( dir . x ) ] [ static_cast < std : : size_t > ( dir . y ) ] ;
}
void Movement ( )
{
if ( InGameMenu ( ) )
return ;
MoveDirection move_dir = GetMoveDirection ( ) ;
if ( move_dir . x ! = MoveDirectionX : : NONE | | move_dir . y ! = MoveDirectionY : : 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 {
WalkInDir ( move_dir ) ;
}
}
struct RightStickAccumulator {
void start ( int * x , int * y )
{
hiresDX + = rightStickX * kGranularity ;
hiresDY + = rightStickY * kGranularity ;
* x + = hiresDX / slowdown ;
* y + = - hiresDY / slowdown ;
}
void finish ( )
{
// keep track of remainder for sub-pixel motion
hiresDX % = slowdown ;
hiresDY % = slowdown ;
}
static const int kGranularity = ( 1 < < 15 ) - 1 ;
int slowdown ; // < kGranularity
int hiresDX ;
int hiresDY ;
} ;
} // namespace
void HandleRightStickMotion ( )
{
// deadzone is handled in ScaleJoystickAxes() already
if ( rightStickX = = 0 & & rightStickY = = 0 )
return ;
if ( automapflag ) { // move map
static RightStickAccumulator acc = { /*slowdown=*/ ( 1 < < 14 ) + ( 1 < < 13 ) , 0 , 0 } ;
int dx = 0 , dy = 0 ;
acc . start ( & dx , & dy ) ;
if ( dy > 1 )
AutomapUp ( ) ;
else if ( dy < - 1 )
AutomapDown ( ) ;
else if ( dx < - 1 )
AutomapRight ( ) ;
else if ( dx > 1 )
AutomapLeft ( ) ;
acc . finish ( ) ;
} else { // move cursor
sgbControllerActive = false ;
static RightStickAccumulator acc = { /*slowdown=*/ ( 1 < < 13 ) + ( 1 < < 12 ) , 0 , 0 } ;
int x = MouseX ;
int y = MouseY ;
acc . start ( & x , & y ) ;
if ( x < 0 )
x = 0 ;
if ( y < 0 )
y = 0 ;
SetCursorPos ( x , y ) ;
acc . finish ( ) ;
}
}
void plrctrls_after_check_curs_move ( )
{
HandleRightStickMotion ( ) ;
// check for monsters first, then items, then towners.
if ( sgbControllerActive ) {
// Clear focuse set by cursor
pcursplr = - 1 ;
pcursmonst = - 1 ;
pcursitem = - 1 ;
pcursobj = - 1 ;
if ( ! invflag ) {
* infostr = ' \0 ' ;
ClearPanel ( ) ;
// TODO target players if !FriendlyMode
if ( leveltype ! = DTYPE_TOWN )
CheckMonstersNearby ( ) ;
else
CheckTownersNearby ( ) ;
CheckItemsNearby ( ) ;
}
}
}
void plrctrls_after_game_logic ( )
{
Movement ( ) ;
}
void UseBeltItem ( int type )
{
for ( int i = 0 ; i < MAXBELTITEMS ; i + + ) {
const auto id = AllItemsList [ plr [ myplr ] . SpdList [ i ] . IDidx ] . iMiscId ;
const auto spellId = AllItemsList [ plr [ myplr ] . SpdList [ i ] . IDidx ] . iSpell ;
if ( ( type = = BLT_HEALING & & ( id = = IMISC_HEAL | | id = = IMISC_FULLHEAL | | ( id = = IMISC_SCROLL & & spellId = = SPL_HEAL ) ) )
| | ( type = = BLT_MANA & & ( id = = IMISC_MANA | | id = = IMISC_FULLMANA ) )
| | id = = IMISC_REJUV | | id = = IMISC_FULLREJUV ) {
if ( plr [ myplr ] . SpdList [ i ] . _itype > - 1 ) {
UseInvItem ( myplr , INVITEM_BELT_FIRST + i ) ;
break ;
}
}
}
}
void PerformPrimaryAction ( )
{
if ( invflag ) { // inventory is open
if ( pcurs = = CURSOR_IDENTIFY )
CheckIdentify ( myplr , pcursinvitem ) ;
else if ( pcurs = = CURSOR_REPAIR )
DoRepair ( myplr , pcursinvitem ) ;
else if ( pcurs = = CURSOR_RECHARGE )
DoRecharge ( myplr , pcursinvitem ) ;
else
CheckInvItem ( ) ;
return ;
}
if ( spselflag ) {
SetSpell ( ) ;
return ;
}
if ( chrflag & & ! chrbtnactive & & plr [ myplr ] . _pStatPts > 0 ) {
CheckChrBtns ( ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
if ( MouseX > = ChrBtnsRect [ i ] . x
& & MouseX < = ChrBtnsRect [ i ] . x + ChrBtnsRect [ i ] . w
& & MouseY > = ChrBtnsRect [ i ] . y
& & MouseY < = ChrBtnsRect [ i ] . h + ChrBtnsRect [ i ] . y ) {
chrbtn [ i ] = 1 ;
chrbtnactive = true ;
ReleaseChrBtns ( ) ;
}
}
return ;
}
Interact ( ) ;
}
void PerformSecondaryAction ( )
{
if ( invflag )
return ;
if ( pcursitem ! = - 1 & & pcurs = = CURSOR_HAND ) {
NetSendCmdLocParam1 ( pcurs , CMD_GOTOAGETITEM , item [ pcursitem ] . _ix , item [ pcursitem ] . _iy , pcursitem ) ;
} else if ( pcursobj ! = - 1 ) {
NetSendCmdLocParam1 ( true , pcurs = = CURSOR_DISARM ? CMD_DISARMXY : CMD_OPOBJXY , object [ pcursobj ] . _ox , object [ pcursobj ] . _oy , pcursobj ) ;
}
}
} // namespace dvl