Browse Source

[controller] Single BFS mele aim

pull/498/head
Anders Jenbo 6 years ago
parent
commit
dd0cd88eb8
  1. 128
      SourceX/controls/plrctrls.cpp

128
SourceX/controls/plrctrls.cpp

@ -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

Loading…
Cancel
Save