From dd0cd88eb8b9db2eece7d083db712126ec6a56fe Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Tue, 26 Nov 2019 00:31:37 +0100 Subject: [PATCH] [controller] Single BFS mele aim --- SourceX/controls/plrctrls.cpp | 128 ++++++++++++++++++++++++++++------ 1 file changed, 107 insertions(+), 21 deletions(-) diff --git a/SourceX/controls/plrctrls.cpp b/SourceX/controls/plrctrls.cpp index 58101d219..75d71e937 100644 --- a/SourceX/controls/plrctrls.cpp +++ b/SourceX/controls/plrctrls.cpp @@ -2,14 +2,19 @@ #include #include +#include #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 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