@ -11,6 +11,7 @@ namespace dvl {
bool sgbControllerActive = false ;
coords speedspellscoords [ 50 ] ;
const int repeatRate = 100 ;
int speedspellcount = 0 ;
// Native game menu, controlled by simulating a keyboard.
@ -26,14 +27,8 @@ int hsr[3] = { 0, 0, 0 }; // hot spell row counts
int slot = SLOTXY_INV_FIRST ;
int spbslot = 0 ;
// Menu controlled by simulating a mouse.
bool InControlledMenu ( )
{
return invflag | | spselflag | | chrflag ;
}
// 0 = not near, >0 = distance related player 1 coordinates
coords c heckNearbyObjs( int x , int y , int diff )
coords CheckNearbyObjs ( int x , int y , int diff )
{
int diff_x = abs ( plr [ myplr ] . _px - x ) ;
int diff_y = abs ( plr [ myplr ] . _py - y ) ;
@ -47,119 +42,85 @@ coords checkNearbyObjs(int x, int y, int diff)
return { - 1 , - 1 } ;
}
void checkItemsNearby ( bool interact )
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 ) {
pcursitem = 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 ;
if ( interact ) {
//sprintf(tempstr, "FOUND NEARBY ITEM AT X:%i Y:%i SEL:%i", item[i]._ix, item[i]._iy, item[i]._iSelFlag);
//NetSendCmdString(1 << myplr, tempstr);
LeftMouseCmd ( false ) ;
}
pcursitem = i ;
return ; // item nearby, don't find objects
}
}
if ( sgbControllerActive )
pcursitem = - 1 ;
//sprintf(tempstr, "SCANNING FOR OBJECTS");
//NetSendCmdString(1 << myplr, tempstr);
for ( int i = 0 ; i < MAXOBJECTS ; i + + ) {
if ( c heckNearbyObjs( 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
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 ;
if ( interact ) {
LeftMouseCmd ( false ) ;
}
return ;
}
}
if ( sgbControllerActive )
pcursobj = - 1 ;
}
void checkTownersNearby ( bool interact )
void CheckTownersNearby ( )
{
if ( pcursitem ! = - 1 )
// Items take priority over towners because the player can move
// items but not towners.
return ;
for ( int i = 0 ; i < 16 ; i + + ) {
if ( c heckNearbyObjs( towner [ i ] . _tx , towner [ i ] . _ty , 2 ) . x ! = - 1 ) {
if ( CheckNearbyObjs ( towner [ i ] . _tx , towner [ i ] . _ty , 2 ) . x ! = - 1 ) {
if ( towner [ i ] . _ttype = = - 1 )
continue ;
pcursmonst = i ;
if ( interact ) {
TalkToTowner ( myplr , i ) ;
}
break ;
}
}
}
bool checkMonstersNearby ( bool attack )
void CheckMonstersNearby ( )
{
int closest = 0 ; // monster ID who is closest
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 ) ) // invisible
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 = c heckNearbyObjs( mx , my , 6 ) ;
coords objDist = C heckNearbyObjs( mx , my , 6 ) ;
if ( objDist . x > - 1 & & objDist . x < = objDistLast . x & & objDist . y < = objDistLast . y ) {
close st = i ;
pcursmon st = i ;
objDistLast = objDist ;
}
}
}
if ( closest < MAX_PLRS ) { // didn't find a monster
pcursmonst = - 1 ;
return false ;
}
pcursmonst = closest ;
//sprintf(tempstr, "NEARBY MONSTER WITH HP:%i", monster[closest]._mhitpoints);
//NetSendCmdString(1 << myplr, tempstr);
if ( attack ) {
static DWORD attacktick = 0 ;
DWORD ticks = GetTickCount ( ) ;
if ( ticks - attacktick > 100 ) { // prevent accidental double attacks
attacktick = ticks ;
LeftMouseCmd ( false ) ;
}
}
return true ;
}
// hide the cursor when we start walking via keyboard/controller
void HideCursor ( )
void Interact ( )
{
if ( pcurs > = CURSOR_FIRSTITEM ) // drop item to allow us to pick up other items
DropItemBeforeTrig ( ) ;
SetCursorPos ( SCREEN_WIDTH / 2 , PANEL_TOP / 2 ) ;
if ( pcurs = = CURSOR_REPAIR | | pcurs = = CURSOR_RECHARGE )
SetCursor_ ( CURSOR_HAND ) ;
sgbControllerActive = true ;
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 ( int key )
void AttrIncBtnSnap ( MoveDirectionY dir )
{
if ( invflag | | spselflag | | ! chrflag )
if ( dir = = MoveDirectionY : : NONE )
return ;
if ( chrbtnactive & & ! plr [ myplr ] . _pStatPts )
if ( chrbtnactive & & plr [ myplr ] . _pStatPts < = 0 )
return ;
DWORD ticks = GetTickCount ( ) ;
if ( ticks - invmove < 80 ) {
if ( ticks - invmove < repeatRate ) {
return ;
}
invmove = ticks ;
@ -176,11 +137,10 @@ void attrIncBtnSnap(int key)
}
}
// set future location up or down
if ( key = = DVL_VK_UP ) {
if ( dir = = MoveDirectionY : : UP ) {
if ( slot > 0 )
- - slot ;
} else if ( key = = DVL_VK_ DOWN) {
} else if ( dir = = MoveDirectionY : : DOWN ) {
if ( slot < 3 )
+ + slot ;
}
@ -189,20 +149,15 @@ void attrIncBtnSnap(int key)
int x = ChrBtnsRect [ slot ] . x + ( ChrBtnsRect [ slot ] . w / 2 ) ;
int y = ChrBtnsRect [ slot ] . y + ( ChrBtnsRect [ slot ] . h / 2 ) ;
SetCursorPos ( x , y ) ;
MouseX = x ;
MouseY = 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 ( int key )
void InvMove ( MoveDirection dir )
{
if ( ! invflag )
return ;
DWORD ticks = GetTickCount ( ) ;
if ( ticks - invmove < 80 ) {
if ( ticks - invmove < repeatRate ) {
return ;
}
invmove = ticks ;
@ -223,7 +178,7 @@ void invMove(int key)
slot = SLOTXY_BELT_LAST ;
// when item is on cursor, this is the real cursor XY
if ( key = = WALK_W ) {
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 ) ;
@ -251,7 +206,7 @@ void invMove(int key)
y = InvRect [ slot ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
}
}
} else if ( key = = WALK_E ) {
} 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 ) ;
@ -277,7 +232,8 @@ void invMove(int key)
y = InvRect [ slot ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
}
}
} else if ( key = = WALK_N ) {
}
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 ) ;
@ -311,7 +267,7 @@ void invMove(int key)
x = InvRect [ slot ] . X + ( INV_SLOT_SIZE_PX / 2 ) ;
y = InvRect [ slot ] . Y - ( INV_SLOT_SIZE_PX / 2 ) ;
}
} else if ( key = = WALK_S ) {
} 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 ) ;
@ -340,14 +296,17 @@ void invMove(int key)
}
}
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
{
SetCursorPos ( x - 10 , y - 10 ) ;
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 ;
}
} else {
SetCursorPos ( x , y ) ;
}
SetCursorPos ( x , y ) ;
}
// check if hot spell at X Y exists
@ -361,18 +320,13 @@ bool HSExists(int x, int y)
return false ;
}
void hotSpellMove ( int key )
void HotSpellMove ( MoveDirection dir )
{
if ( ! spselflag )
return ;
int x = 0 ;
int y = 0 ;
if ( ! sgbControllerActive )
HideCursor ( ) ;
DWORD ticks = GetTickCount ( ) ;
if ( ticks - invmove < 80 ) {
if ( ticks - invmove < repeatRate ) {
return ;
}
invmove = ticks ;
@ -392,7 +346,7 @@ void hotSpellMove(int key)
}
}
if ( key = = DVL_VK_ UP) {
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 ;
@ -404,7 +358,7 @@ void hotSpellMove(int key)
y = 195 ;
}
}
} else if ( key = = DVL_VK_ DOWN) {
} else if ( dir . y = = MoveDirectionY : : DOWN ) {
if ( speedspellscoords [ spbslot ] . y = = 251 ) { // we're in row 2
if ( HSExists ( MouseX , 307 ) ) {
x = MouseX ;
@ -416,13 +370,14 @@ void hotSpellMove(int key)
y = 251 ;
}
}
} else if ( key = = DVL_VK_LEFT ) {
}
if ( dir . x = = MoveDirectionX : : LEFT ) {
if ( spbslot > = speedspellcount - 1 )
return ;
spbslot + + ;
x = speedspellscoords [ spbslot ] . x ;
y = speedspellscoords [ spbslot ] . y ;
} else if ( key = = DVL_VK_ RIGHT) {
} else if ( dir . x = = MoveDirectionX : : RIGHT ) {
if ( spbslot < = 0 )
return ;
spbslot - - ;
@ -432,85 +387,54 @@ void hotSpellMove(int key)
if ( x > 0 & & y > 0 ) {
SetCursorPos ( x , y ) ;
MouseX = x ;
MouseY = y ;
}
}
void walkInDir ( MoveDirection dir )
{
if ( dir . x = = MoveDirectionX : : NONE & & dir . y = = MoveDirectionY : : NONE )
return ;
DWORD ticks = GetTickCount ( ) ;
if ( ticks - invmove < 370 ) {
return ;
}
invmove = ticks ;
ClrPlrPath ( myplr ) ; // clear nodes
plr [ myplr ] . destAction = ACTION_NONE ; // stop attacking, etc.
HideCursor ( ) ;
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
} ;
plr [ myplr ] . walkpath [ 0 ] = kMoveToWalkDir [ static_cast < std : : size_t > ( dir . x ) ] [ static_cast < std : : size_t > ( dir . 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 menuMoveX ( MoveDirectionX dir )
void WalkInDir ( MoveDirection dir )
{
if ( dir = = MoveDirectionX : : NONE )
if ( dir . x = = MoveDirectionX : : NONE & & dir . y = = MoveDirectionY : : NONE ) {
if ( sgbControllerActive & & plr [ myplr ] . destAction = = ACTION_NONE )
ClrPlrPath ( myplr ) ;
return ;
invMove ( dir = = MoveDirectionX : : LEFT ? WALK_W : WALK_E ) ;
hotSpellMove ( dir = = MoveDirectionX : : LEFT ? DVL_VK_LEFT : DVL_VK_RIGHT ) ;
}
}
void menuMoveY ( MoveDirectionY dir )
{
if ( dir = = MoveDirectionY : : NONE )
return ;
invMove ( dir = = MoveDirectionY : : UP ? WALK_N : WALK_S ) ;
const auto key = dir = = MoveDirectionY : : UP ? DVL_VK_UP : DVL_VK_DOWN ;
hotSpellMove ( key ) ;
attrIncBtnSnap ( key ) ;
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 m ovement( )
void Movement ( )
{
if ( InGameMenu ( ) )
return ;
MoveDirection move_dir = GetMoveDirection ( ) ;
if ( InControlledMenu ( ) ) {
menuMoveX ( move_dir . x ) ;
menuMoveY ( move_dir . y ) ;
} else {
walkInDir ( move_dir ) ;
if ( move_dir . x ! = MoveDirectionX : : NONE | | move_dir . y ! = MoveDirectionY : : NONE ) {
sgbControllerActive = true ;
}
if ( GetAsyncKeyState ( DVL_MK_LBUTTON ) & 0x8000 ) {
if ( sgbControllerActive ) { // show cursor first, before clicking
sgbControllerActive = false ;
} else if ( spselflag ) {
SetSpell ( ) ;
} else {
LeftMouseCmd ( false ) ;
}
}
}
// Move map or mouse no more than 60 times per second.
// This is called from both the game loop and the event loop for responsiveness.
void HandleRightStickMotionAt60Fps ( )
{
static std : : int64_t currentTime = 0 ;
static std : : int64_t lastTime = 0 ;
currentTime = SDL_GetTicks ( ) ;
if ( currentTime - lastTime > 15 ) {
HandleRightStickMotion ( ) ;
lastTime = currentTime ;
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 ) ;
}
}
@ -558,9 +482,7 @@ void HandleRightStickMotion()
AutomapLeft ( ) ;
acc . finish ( ) ;
} else { // move cursor
if ( sgbControllerActive ) {
sgbControllerActive = false ;
}
sgbControllerActive = false ;
static RightStickAccumulator acc = { /*slowdown=*/ ( 1 < < 13 ) + ( 1 < < 12 ) , 0 , 0 } ;
int x = MouseX ;
int y = MouseY ;
@ -576,32 +498,41 @@ void HandleRightStickMotion()
void plrctrls_after_check_curs_move ( )
{
HandleRightStickMotionAt60Fps ( ) ;
HandleRightStickMotion ( ) ;
// check for monsters first, then items, then towners.
if ( sgbControllerActive ) { // cursor should be missing
if ( ! checkMonstersNearby ( false ) ) {
pcursmonst = - 1 ;
checkItemsNearby ( false ) ;
checkTownersNearby ( false ) ;
} else {
pcursitem = - 1 ;
if ( sgbControllerActive ) {
// Clear focuse set by cursor
if ( ! invflag ) {
* infostr = ' \0 ' ;
ClearPanel ( ) ;
}
pcursplr = - 1 ;
pcursmonst = - 1 ;
pcursitem = - 1 ;
pcursobj = - 1 ;
// TODO target players if !FriendlyMode
if ( leveltype ! = DTYPE_TOWN )
CheckMonstersNearby ( ) ;
else
CheckTownersNearby ( ) ;
CheckItemsNearby ( ) ;
}
}
void plrctrls_after_game_logic ( )
{
movement ( ) ;
M ovement( ) ;
}
void useBeltPotion ( bool mana )
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 ( ( ! mana & & ( id = = IMISC_HEAL | | id = = IMISC_FULLHEAL | | ( id = = IMISC_SCROLL & & spellId = = SPL_HEAL ) ) )
| | ( mana & & ( id = = IMISC_MANA | | id = = IMISC_FULLMANA ) )
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 ) ;
@ -611,69 +542,52 @@ void useBeltPotion(bool mana)
}
}
void p erformPrimaryAction( )
void P erformPrimaryAction( )
{
const DWORD ticks = GetTickCount ( ) ;
if ( invflag ) { // inventory is open
static DWORD clickinvtimer ;
if ( ticks - clickinvtimer > = 300 ) {
clickinvtimer = ticks ;
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 ( ) ;
}
} else if ( spselflag ) {
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 ( ) ;
} else if ( chrflag ) {
static DWORD statuptimer ;
if ( ticks - statuptimer > = 400 ) {
statuptimer = ticks ;
if ( ! chrbtnactive & & plr [ myplr ] . _pStatPts ) {
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 ( ) ;
}
}
}
if ( plr [ myplr ] . _pStatPts = = 0 )
HideCursor ( ) ;
}
} else {
static DWORD talkwait ;
if ( stextflag )
talkwait = GetTickCount ( ) ; // Wait before we re-initiate talking
HideCursor ( ) ;
DWORD talktick = GetTickCount ( ) ;
if ( ! checkMonstersNearby ( true ) ) {
if ( talktick - talkwait > 600 ) { // prevent re-entering talk after finished
talkwait = talktick ;
checkTownersNearby ( true ) ;
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 p erformSecondaryAction( )
void PerformSecondaryAction ( )
{
if ( invflag )
return ;
static DWORD opentimer = 0 ;
HideCursor ( ) ;
const DWORD ticks = GetTickCount ( ) ;
if ( ticks - opentimer > 500 ) {
opentimer = ticks ;
checkItemsNearby ( true ) ;
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 ) ;
}
}