Browse Source

Always spawn players in a valid location

pull/6066/head
Anders Jenbo 3 years ago committed by Stephen C. Wills
parent
commit
5a12f7b0d5
  1. 5
      Source/diablo.cpp
  2. 7
      Source/multi.cpp
  3. 36
      Source/player.cpp
  4. 7
      Source/player.h
  5. 41
      Source/spells.cpp

5
Source/diablo.cpp

@ -2916,10 +2916,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
for (Player &player : Players) {
if (player.plractive && player.isOnActiveLevel() && (!player._pLvlChanging || &player == MyPlayer)) {
if (player._pHitPoints > 0) {
if (!gbIsMultiplayer)
dPlayer[player.position.tile.x][player.position.tile.y] = player.getId() + 1;
else
SyncInitPlrPos(player);
SyncInitPlrPos(player);
} else {
dFlags[player.position.tile.x][player.position.tile.y] |= DungeonFlag::DeadPlayer;
}

7
Source/multi.cpp

@ -362,13 +362,12 @@ void SetupLocalPositions()
leveltype = DTYPE_TOWN;
setlevel = false;
const auto x = static_cast<WorldTileCoord>(75 + plrxoff[MyPlayerId]);
const auto y = static_cast<WorldTileCoord>(68 + plryoff[MyPlayerId]);
const WorldTilePosition spawns[9] = { { 75, 68 }, { 77, 70 }, { 75, 70 }, { 77, 68 }, { 76, 69 }, { 75, 69 }, { 76, 68 }, { 77, 69 }, { 76, 70 } };
Player &myPlayer = *MyPlayer;
myPlayer.position.tile = WorldTilePosition { x, y };
myPlayer.position.future = WorldTilePosition { x, y };
myPlayer.position.tile = spawns[MyPlayerId];
myPlayer.position.future = myPlayer.position.tile;
myPlayer.setLevel(currlevel);
myPlayer._pLvlChanging = true;
myPlayer.pLvlLoad = 0;

36
Source/player.cpp

@ -27,6 +27,7 @@
#include "help.h"
#include "init.h"
#include "inv_iterators.hpp"
#include "levels/trigs.h"
#include "lighting.h"
#include "loadsave.h"
#include "minitext.h"
@ -55,15 +56,6 @@ std::vector<Player> Players;
Player *InspectPlayer;
bool MyPlayerIsDead;
/** Specifies the X-coordinate delta from the player start location in Tristram. */
const int8_t plrxoff[9] = { 0, 2, 0, 2, 1, 0, 1, 2, 1 };
/** Specifies the Y-coordinate delta from the player start location in Tristram. */
const int8_t plryoff[9] = { 0, 2, 2, 0, 1, 1, 0, 1, 2 };
/** Specifies the X-coordinate delta from a player, used for instance when casting resurrect. */
const int8_t plrxoff2[9] = { 0, 1, 0, 1, 2, 0, 1, 2, 2 };
/** Specifies the Y-coordinate delta from a player, used for instance when casting resurrect. */
const int8_t plryoff2[9] = { 0, 0, 1, 1, 0, 2, 2, 1, 2 };
namespace {
struct DirectionSettings {
@ -2558,19 +2550,10 @@ void InitPlayer(Player &player, bool firstTime)
player._pdir = Direction::South;
if (&player == MyPlayer) {
if (!firstTime || leveltype != DTYPE_TOWN) {
player.position.tile = ViewPosition;
}
} else {
unsigned i;
for (i = 0; i < 8 && !PosOkPlayer(player, player.position.tile + Displacement { plrxoff2[i], plryoff2[i] }); i++)
;
player.position.tile.x += plrxoff2[i];
player.position.tile.y += plryoff2[i];
if (&player == MyPlayer && (!firstTime || leveltype != DTYPE_TOWN)) {
player.position.tile = ViewPosition;
}
player.position.future = player.position.tile;
SetPlayerOld(player);
player.walkpath[0] = WALK_NONE;
player.destAction = ACTION_NONE;
@ -3293,19 +3276,24 @@ void SyncPlrAnim(Player &player)
void SyncInitPlrPos(Player &player)
{
if (!gbIsMultiplayer || !player.isOnActiveLevel()) {
if (!player.isOnActiveLevel())
return;
}
const WorldTileDisplacement offset[9] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 }, { 2, 0 }, { 0, 2 }, { 1, 2 }, { 2, 1 }, { 2, 2 } };
Point position = [&]() {
for (int i = 0; i < 8; i++) {
Point position = player.position.tile + Displacement { plrxoff2[i], plryoff2[i] };
Point position = player.position.tile + offset[i];
if (PosOkPlayer(player, position))
return position;
}
std::optional<Point> nearPosition = FindClosestValidPosition(
[&player](Point testPosition) {
for (int i = 0; i < numtrigs; i++) {
if (trigs[i].position == testPosition)
return false;
}
return PosOkPlayer(player, testPosition) && !PosOkPortal(currlevel, testPosition);
},
player.position.tile,
@ -3317,9 +3305,9 @@ void SyncInitPlrPos(Player &player)
player.position.tile = position;
dPlayer[position.x][position.y] = player.getId() + 1;
player.position.future = position;
if (&player == MyPlayer) {
player.position.future = position;
ViewPosition = position;
}
}

7
Source/player.h

@ -852,11 +852,4 @@ void SetPlrVit(Player &player, int v);
void InitDungMsgs(Player &player);
void PlayDungMsgs();
/* data */
extern const int8_t plrxoff[9];
extern const int8_t plryoff[9];
extern const int8_t plrxoff2[9];
extern const int8_t plryoff2[9];
} // namespace devilution

41
Source/spells.cpp

@ -65,45 +65,6 @@ void ClearReadiedSpell(Player &player)
}
}
void PlacePlayer(Player &player)
{
if (!player.isOnActiveLevel())
return;
Point newPosition = [&]() {
Point okPosition = {};
for (int i = 0; i < 8; i++) {
okPosition = player.position.tile + Displacement { plrxoff2[i], plryoff2[i] };
if (PosOkPlayer(player, okPosition))
return okPosition;
}
for (int max = 1, min = -1; min > -50; max++, min--) {
for (int y = min; y <= max; y++) {
okPosition.y = player.position.tile.y + y;
for (int x = min; x <= max; x++) {
okPosition.x = player.position.tile.x + x;
if (PosOkPlayer(player, okPosition))
return okPosition;
}
}
}
return okPosition;
}();
player.position.tile = newPosition;
dPlayer[newPosition.x][newPosition.y] = player.getId() + 1;
if (&player == MyPlayer) {
ViewPosition = newPosition;
}
}
} // namespace
bool IsValidSpell(SpellID spl)
@ -293,7 +254,7 @@ void DoResurrect(size_t pnum, Player &target)
ClrPlrPath(target);
target.destAction = ACTION_NONE;
target._pInvincible = false;
PlacePlayer(target);
SyncInitPlrPos(target);
int hp = 10 << 6;
if (target._pMaxHPBase < (10 << 6)) {

Loading…
Cancel
Save