You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

686 lines
21 KiB

#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];
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;
// Menu controlled by simulating a mouse.
bool InControlledMenu()
{
return invflag || spselflag || chrflag;
}
// 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(bool interact)
{
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 (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);
}
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 (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)
{
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 (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)
{
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++) {
int d_monster = dMonster[monster[i]._mx][monster[i]._my];
if (monster[i]._mFlags & MFLAG_HIDDEN || monster[i]._mhitpoints <= 0) // monster is hiding or dead, skip
continue;
if (d_monster && dFlags[monster[i]._mx][monster[i]._my] & BFLAG_LIT) { // is monster visible
if (monster[i].MData->mSelFlag & 1 || monster[i].MData->mSelFlag & 2 || monster[i].MData->mSelFlag & 3 || monster[i].MData->mSelFlag & 4) { // is monster selectable
coords objDist = checkNearbyObjs(monster[i]._mx, monster[i]._my, 6);
if (objDist.x > -1 && objDist.x <= objDistLast.x && objDist.y <= objDistLast.y) {
closest = i;
objDistLast = objDist;
}
}
}
}
if (closest > 0) { // did we find a monster
pcursmonst = closest;
//sprintf(tempstr, "NEARBY MONSTER WITH HP:%i", monster[closest]._mhitpoints);
//NetSendCmdString(1 << myplr, tempstr);
} else if (closest > 0) { // found monster, but we don't want to attack it
return true;
} else {
pcursmonst = -1;
return false;
}
if (attack) {
static DWORD attacktick = 0;
DWORD ticks = GetTickCount();
if (ticks - attacktick > 100) { // prevent accidental double attacks
attacktick = ticks;
LeftMouseCmd(false);
}
return true;
} else {
return true;
}
pcursmonst = -1;
return false;
}
// hide the cursor when we start walking via keyboard/controller
void HideCursor()
{
if (pcurs >= CURSOR_FIRSTITEM) // if we don't drop the item on cursor, it will be destroyed
DropItemBeforeTrig();
SetCursorPos(320, 180);
MouseX = 320;
MouseY = 180;
sgbControllerActive = true;
}
void attrIncBtnSnap(int key)
{
if (invflag || spselflag || !chrflag)
return;
if (chrbtnactive && !plr[myplr]._pStatPts)
return;
DWORD ticks = GetTickCount();
if (ticks - invmove < 80) {
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;
}
}
// set future location up or down
if (key == DVL_VK_UP) {
if (slot > 0)
--slot;
} else if (key == DVL_VK_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);
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)
{
if (!invflag)
return;
DWORD ticks = GetTickCount();
if (ticks - invmove < 80) {
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 (key == WALK_W) {
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 (key == WALK_E) {
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);
}
}
} else if (key == WALK_N) {
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 (key == WALK_S) {
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 (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);
}
} else {
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(int key)
{
if (!spselflag)
return;
int x = 0;
int y = 0;
if (!sgbControllerActive)
HideCursor();
DWORD ticks = GetTickCount();
if (ticks - invmove < 80) {
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 (key == DVL_VK_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 (key == DVL_VK_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;
}
}
} else if (key == DVL_VK_LEFT) {
if (spbslot >= speedspellcount - 1)
return;
spbslot++;
x = speedspellscoords[spbslot].x;
y = speedspellscoords[spbslot].y;
} else if (key == DVL_VK_RIGHT) {
if (spbslot <= 0)
return;
spbslot--;
x = speedspellscoords[spbslot].x;
y = speedspellscoords[spbslot].y;
}
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)];
}
void menuMoveX(MoveDirectionX dir)
{
if (dir == MoveDirectionX::NONE)
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);
}
void movement()
{
if (InGameMenu())
return;
MoveDirection move_dir = GetMoveDirection();
if (InControlledMenu()) {
menuMoveX(move_dir.x);
menuMoveY(move_dir.y);
} else {
walkInDir(move_dir);
}
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;
}
}
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
if (sgbControllerActive) {
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_game_logic()
{
// 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;
}
}
movement();
HandleRightStickMotionAt60Fps();
}
void plrctrls_event_loop()
{
HandleRightStickMotionAt60Fps();
}
void useBeltPotion(bool mana)
{
static DWORD menuopenslow = 0;
DWORD ticks = GetTickCount();
int invNum = 0;
if (ticks - menuopenslow < 300) {
return;
}
menuopenslow = ticks;
for (int i = 0; i < MAXBELTITEMS; i++) {
const auto id = AllItemsList[plr[myplr].SpdList[i].IDidx].iMiscId;
if ((!mana && (id == IMISC_HEAL || id == IMISC_FULLHEAL)) || (mana && (id == IMISC_MANA || id == IMISC_FULLMANA)) || id == IMISC_REJUV || id == IMISC_FULLREJUV) {
if (plr[myplr].SpdList[i]._itype > -1) {
invNum = i + INVITEM_BELT_FIRST;
UseInvItem(myplr, invNum);
break;
}
}
}
}
void performPrimaryAction()
{
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
CheckInvItem();
}
} else 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);
}
}
}
}
void performSecondaryAction()
{
if (invflag)
return;
static DWORD opentimer = 0;
HideCursor();
const DWORD ticks = GetTickCount();
if (ticks - opentimer > 500) {
opentimer = ticks;
checkItemsNearby(true);
}
}
} // namespace dvl