|
|
|
|
@ -2,14 +2,19 @@
|
|
|
|
|
|
|
|
|
|
#include <cstdint> |
|
|
|
|
#include <algorithm> |
|
|
|
|
#include <list> |
|
|
|
|
|
|
|
|
|
#include "controls/controller_motion.h" |
|
|
|
|
#include "controls/game_controls.h" |
|
|
|
|
|
|
|
|
|
// Based on the Nintendo Switch port by @lantus, @erfg12, @rsn8887.
|
|
|
|
|
|
|
|
|
|
namespace dvl { |
|
|
|
|
|
|
|
|
|
typedef struct bfsNode { |
|
|
|
|
int x; |
|
|
|
|
int y; |
|
|
|
|
int steps; |
|
|
|
|
} bfsNode; |
|
|
|
|
|
|
|
|
|
bool sgbControllerActive = false; |
|
|
|
|
coords speedspellscoords[50]; |
|
|
|
|
const int repeatRate = 100; |
|
|
|
|
@ -41,7 +46,7 @@ int spbslot = 0;
|
|
|
|
|
* @param y Tile coordinates |
|
|
|
|
* @return -1 == down |
|
|
|
|
*/ |
|
|
|
|
int GetRoteryDistance(int x, int y) |
|
|
|
|
int GetRotaryDistance(int x, int y) |
|
|
|
|
{ |
|
|
|
|
int d, d1, d2; |
|
|
|
|
|
|
|
|
|
@ -113,7 +118,7 @@ void FindItemOrObject()
|
|
|
|
|
if (item[i]._itype == ITYPE_NONE |
|
|
|
|
|| item[i]._iSelFlag == 0) |
|
|
|
|
continue; |
|
|
|
|
int newRotations = GetRoteryDistance(mx + xx, my + yy); |
|
|
|
|
int newRotations = GetRotaryDistance(mx + xx, my + yy); |
|
|
|
|
if (rotations < newRotations) |
|
|
|
|
continue; |
|
|
|
|
rotations = newRotations; |
|
|
|
|
@ -135,7 +140,7 @@ void FindItemOrObject()
|
|
|
|
|
int o = dObject[mx + xx][my + yy] > 0 ? dObject[mx + xx][my + yy] - 1 : -(dObject[mx + xx][my + yy] + 1); |
|
|
|
|
if (object[o]._oSelFlag == 0) |
|
|
|
|
continue; |
|
|
|
|
int newRotations = GetRoteryDistance(mx + xx, my + yy); |
|
|
|
|
int newRotations = GetRotaryDistance(mx + xx, my + yy); |
|
|
|
|
if (rotations < newRotations) |
|
|
|
|
continue; |
|
|
|
|
rotations = newRotations; |
|
|
|
|
@ -166,7 +171,26 @@ bool HasRangedSpell()
|
|
|
|
|
&& !spelldata[spl].sTownSpell; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CheckMonstersNearby() |
|
|
|
|
bool CanTargetMonster(int mi) |
|
|
|
|
{ |
|
|
|
|
const auto &monst = monster[mi]; |
|
|
|
|
|
|
|
|
|
if (monst._mFlags & (MFLAG_HIDDEN | MFLAG_GOLEM)) |
|
|
|
|
return false; |
|
|
|
|
if (monst._mhitpoints >> 6 <= 0) // dead
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
const int mx = monst._mx; |
|
|
|
|
const int my = monst._my; |
|
|
|
|
if (!(dFlags[mx][my] & BFLAG_LIT)) // not visable
|
|
|
|
|
return false; |
|
|
|
|
if (dMonster[mx][my] == 0) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FindRangedTarget() |
|
|
|
|
{ |
|
|
|
|
int newRotations, newDdistance; |
|
|
|
|
int distance = 2 * (MAXDUNX + MAXDUNY); |
|
|
|
|
@ -177,23 +201,15 @@ void CheckMonstersNearby()
|
|
|
|
|
const auto &monst = monster[i]; |
|
|
|
|
const int mx = monst._mx; |
|
|
|
|
const int my = monst._my; |
|
|
|
|
if (dMonster[mx][my] == 0 |
|
|
|
|
|| monst._mFlags & (MFLAG_HIDDEN | MFLAG_GOLEM) // hidden or golem
|
|
|
|
|
|| monst._mhitpoints >> 6 <= 0 // dead
|
|
|
|
|
|| !(dFlags[mx][my] & BFLAG_LIT) // not visable
|
|
|
|
|
|| !(monst.MData->mSelFlag & 7)) // selectable
|
|
|
|
|
if (!CanTargetMonster(i)) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
if (plr[myplr]._pwtype == WT_RANGED || HasRangedSpell()) |
|
|
|
|
newDdistance = GetDistanceRanged(mx, my); |
|
|
|
|
else |
|
|
|
|
newDdistance = GetDistance(mx, my, distance); |
|
|
|
|
|
|
|
|
|
if (newDdistance == 0 || distance < newDdistance || (pcursmonst != -1 && CanTalkToMonst(i))) { |
|
|
|
|
newDdistance = GetDistanceRanged(mx, my); |
|
|
|
|
if (distance < newDdistance || (pcursmonst != -1 && CanTalkToMonst(i))) { |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (distance == newDdistance) { |
|
|
|
|
newRotations = GetRoteryDistance(mx, my); |
|
|
|
|
newRotations = GetRotaryDistance(mx, my); |
|
|
|
|
if (rotations < newRotations) |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
@ -203,6 +219,75 @@ void CheckMonstersNearby()
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FindMeleeTarget() |
|
|
|
|
{ |
|
|
|
|
bool visited[MAXDUNX][MAXDUNY] = { 0 }; |
|
|
|
|
int maxSteps = 25; // Max steps for FindPath is 25
|
|
|
|
|
int rotations = 5; |
|
|
|
|
int x = plr[myplr]._px; |
|
|
|
|
int y = plr[myplr]._py; |
|
|
|
|
|
|
|
|
|
std::list<bfsNode> queue; |
|
|
|
|
|
|
|
|
|
visited[x][y] = true; |
|
|
|
|
queue.push_back({ x, y, 0 }); |
|
|
|
|
|
|
|
|
|
while (!queue.empty()) { |
|
|
|
|
bfsNode node = queue.front(); |
|
|
|
|
queue.pop_front(); |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 8; i++) { |
|
|
|
|
const int dx = node.x + pathxdir[i]; |
|
|
|
|
const int dy = node.y + pathydir[i]; |
|
|
|
|
|
|
|
|
|
if (visited[dx][dy]) |
|
|
|
|
continue; // already visisted
|
|
|
|
|
|
|
|
|
|
if (node.steps >= maxSteps) { |
|
|
|
|
visited[dx][dy] = true; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!PosOkPlayer(myplr, dx, dy)) { |
|
|
|
|
visited[dx][dy] = true; |
|
|
|
|
|
|
|
|
|
if (dMonster[dx][dy] != 0) { |
|
|
|
|
int mi = dMonster[dx][dy] > 0 ? dMonster[dx][dy] - 1 : -(dMonster[dx][dy] + 1); |
|
|
|
|
if (CanTargetMonster(mi)) { |
|
|
|
|
int newRotations = GetRotaryDistance(dx, dy); |
|
|
|
|
if (rotations < newRotations || (pcursmonst != -1 && CanTalkToMonst(i))) |
|
|
|
|
continue; |
|
|
|
|
rotations = newRotations; |
|
|
|
|
pcursmonst = mi; |
|
|
|
|
maxSteps = node.steps; // Monsters found, cap search to current steps
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PATHNODE pPath; |
|
|
|
|
pPath.x = node.x; |
|
|
|
|
pPath.y = node.y; |
|
|
|
|
|
|
|
|
|
if (path_solid_pieces(&pPath, dx, dy)) { |
|
|
|
|
queue.push_back({ dx, dy, node.steps + 1 }); |
|
|
|
|
visited[dx][dy] = true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CheckMonstersNearby() |
|
|
|
|
{ |
|
|
|
|
if (plr[myplr]._pwtype == WT_RANGED || HasRangedSpell()) { |
|
|
|
|
FindRangedTarget(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FindMeleeTarget(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void CheckPlayerNearby() |
|
|
|
|
{ |
|
|
|
|
int newRotations, newDdistance; |
|
|
|
|
@ -235,7 +320,7 @@ void CheckPlayerNearby()
|
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
if (distance == newDdistance) { |
|
|
|
|
newRotations = GetRoteryDistance(mx, my); |
|
|
|
|
newRotations = GetRotaryDistance(mx, my); |
|
|
|
|
if (rotations < newRotations) |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
@ -252,7 +337,8 @@ void FindActor()
|
|
|
|
|
else |
|
|
|
|
CheckTownersNearby(); |
|
|
|
|
|
|
|
|
|
CheckPlayerNearby(); |
|
|
|
|
if (gbMaxPlayers != 1) |
|
|
|
|
CheckPlayerNearby(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Interact() |
|
|
|
|
@ -794,7 +880,7 @@ void PerformSpellAction()
|
|
|
|
|
|
|
|
|
|
int spl = plr[myplr]._pRSpell; |
|
|
|
|
if ((pcursplr == -1 && (spl == SPL_RESURRECT || spl == SPL_HEALOTHER)) |
|
|
|
|
|| (pcursobj == -1 && spl == SPL_DISARM)) { |
|
|
|
|
|| (pcursobj == -1 && spl == SPL_DISARM)) { |
|
|
|
|
if (plr[myplr]._pClass == PC_WARRIOR) { |
|
|
|
|
PlaySFX(PS_WARR27); |
|
|
|
|
#ifndef SPAWN |
|
|
|
|
|