Browse Source

Make `Players` a vector

pull/5288/head
Gleb Mazovetskiy 4 years ago
parent
commit
188dc79f6e
  1. 2
      Source/automap.cpp
  2. 14
      Source/control.cpp
  3. 4
      Source/controls/game_controls.cpp
  4. 2
      Source/controls/plrctrls.cpp
  5. 142
      Source/cursor.cpp
  6. 2
      Source/debug.cpp
  7. 12
      Source/dvlnet/base.cpp
  8. 16
      Source/dvlnet/base_protocol.h
  9. 3
      Source/dvlnet/loopback.cpp
  10. 9
      Source/dvlnet/tcp_server.cpp
  11. 4
      Source/engine/render/scrollrt.cpp
  12. 2
      Source/items.cpp
  13. 4
      Source/monster.cpp
  14. 30
      Source/msg.cpp
  15. 40
      Source/multi.cpp
  16. 21
      Source/player.cpp
  17. 12
      Source/player.h
  18. 4
      Source/portal.cpp
  19. 2
      Source/portal.h
  20. 2
      Source/qol/monhealthbar.cpp
  21. 6
      Source/spells.cpp
  22. 2
      Source/spells.h
  23. 4
      Source/sync.cpp
  24. 2
      Source/towners.cpp
  25. 26
      test/drlg_l1_test.cpp
  26. 10
      test/effects_test.cpp
  27. 39
      test/inv_test.cpp
  28. 5
      test/missiles_test.cpp
  29. 33
      test/pack_test.cpp
  30. 2
      test/path_test.cpp
  31. 3
      test/player_test.cpp
  32. 5
      test/timedemo_test.cpp
  33. 1
      test/writehero_test.cpp

2
Source/automap.cpp

@ -715,7 +715,7 @@ void DrawAutomap(const Surface &out)
screen.y += AmLine(32);
}
for (int playerId = 0; playerId < MAX_PLRS; playerId++) {
for (size_t playerId = 0; playerId < Players.size(); playerId++) {
Player &player = Players[playerId];
if (player.isOnActiveLevel() && player.plractive && !player._pLvlChanging && (&player == MyPlayer || player.friendlyMode)) {
DrawAutomapPlr(out, myPlayerOffset, playerId);

14
Source/control.cpp

@ -328,7 +328,7 @@ void ResetTalkMsg()
uint32_t pmask = 0;
for (int i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
if (WhisperList[i])
pmask |= 1 << i;
}
@ -1154,7 +1154,7 @@ void DrawTalkPan(const Surface &out)
x += 46;
int talkBtn = 0;
for (int i = 0; i < 4; i++) {
for (size_t i = 0; i < Players.size(); i++) {
Player &player = Players[i];
if (&player == MyPlayer)
continue;
@ -1221,13 +1221,13 @@ void control_release_talk_btn()
int off = (MousePosition.y - (69 + mainPanelPosition.y)) / 18;
int p = 0;
for (; p < MAX_PLRS && off != -1; p++) {
if (p != MyPlayerId)
size_t playerId = 0;
for (; playerId < Players.size() && off != -1; ++playerId) {
if (playerId != MyPlayerId)
off--;
}
if (p <= MAX_PLRS)
WhisperList[p - 1] = !WhisperList[p - 1];
if (playerId > 0 && playerId <= Players.size())
WhisperList[playerId - 1] = !WhisperList[playerId - 1];
}
void control_type_message()

4
Source/controls/game_controls.cpp

@ -103,6 +103,10 @@ bool HandleStartAndSelect(const ControllerButtonEvent &ctrlEvent, GameAction *ac
bool GetGameAction(const SDL_Event &event, ControllerButtonEvent ctrlEvent, GameAction *action)
{
if (MyPlayer == nullptr) {
return false;
}
const bool inGameMenu = InGameMenu();
#ifndef USE_SDL1

2
Source/controls/plrctrls.cpp

@ -373,7 +373,7 @@ void CheckPlayerNearby()
if (myPlayer.friendlyMode && spl != SPL_RESURRECT && spl != SPL_HEALOTHER)
return;
for (int i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
const Player &player = Players[i];
if (&player == MyPlayer)
continue;

142
Source/cursor.cpp

@ -423,52 +423,52 @@ void CheckCursMove()
if (leveltype != DTYPE_TOWN) {
if (pcurstemp != -1) {
if (!flipflag && mx + 2 < MAXDUNX && my + 1 < MAXDUNY && dMonster[mx + 2][my + 1] != 0 && IsTileLit({ mx + 2, my + 1 })) {
int mi = abs(dMonster[mx + 2][my + 1]) - 1;
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 4) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 2][my + 1]) - 1;
if (monsterId == pcurstemp && Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 2, 1 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (flipflag && mx + 1 < MAXDUNX && my + 2 < MAXDUNY && dMonster[mx + 1][my + 2] != 0 && IsTileLit({ mx + 1, my + 2 })) {
int mi = abs(dMonster[mx + 1][my + 2]) - 1;
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 4) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 1][my + 2]) - 1;
if (monsterId == pcurstemp && Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 2 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (mx + 2 < MAXDUNX && my + 2 < MAXDUNY && dMonster[mx + 2][my + 2] != 0 && IsTileLit({ mx + 2, my + 2 })) {
int mi = abs(dMonster[mx + 2][my + 2]) - 1;
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 4) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 2][my + 2]) - 1;
if (monsterId == pcurstemp && Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 2, 2 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (mx + 1 < MAXDUNX && !flipflag && dMonster[mx + 1][my] != 0 && IsTileLit({ mx + 1, my })) {
int mi = abs(dMonster[mx + 1][my]) - 1;
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 2) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 1][my]) - 1;
if (monsterId == pcurstemp && Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 0 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (my + 1 < MAXDUNY && flipflag && dMonster[mx][my + 1] != 0 && IsTileLit({ mx, my + 1 })) {
int mi = abs(dMonster[mx][my + 1]) - 1;
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 2) != 0) {
const uint16_t monsterId = abs(dMonster[mx][my + 1]) - 1;
if (monsterId == pcurstemp && Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 0, 1 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (dMonster[mx][my] != 0 && IsTileLit({ mx, my })) {
int mi = abs(dMonster[mx][my]) - 1;
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 1) != 0) {
const uint16_t monsterId = abs(dMonster[mx][my]) - 1;
if (monsterId == pcurstemp && Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 1) != 0) {
cursPosition = { mx, my };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (mx + 1 < MAXDUNX && my + 1 < MAXDUNY && dMonster[mx + 1][my + 1] != 0 && IsTileLit({ mx + 1, my + 1 })) {
int mi = abs(dMonster[mx + 1][my + 1]) - 1;
if (mi == pcurstemp && Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 2) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 1][my + 1]) - 1;
if (monsterId == pcurstemp && Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 1 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (pcursmonst != -1 && (Monsters[pcursmonst].flags & MFLAG_HIDDEN) != 0) {
@ -483,52 +483,52 @@ void CheckCursMove()
}
}
if (!flipflag && mx + 2 < MAXDUNX && my + 1 < MAXDUNY && dMonster[mx + 2][my + 1] != 0 && IsTileLit({ mx + 2, my + 1 })) {
int mi = abs(dMonster[mx + 2][my + 1]) - 1;
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 4) != 0) {
int monsterId = abs(dMonster[mx + 2][my + 1]) - 1;
if (Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 2, 1 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (flipflag && mx + 1 < MAXDUNX && my + 2 < MAXDUNY && dMonster[mx + 1][my + 2] != 0 && IsTileLit({ mx + 1, my + 2 })) {
int mi = abs(dMonster[mx + 1][my + 2]) - 1;
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 4) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 1][my + 2]) - 1;
if (Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 2 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (mx + 2 < MAXDUNX && my + 2 < MAXDUNY && dMonster[mx + 2][my + 2] != 0 && IsTileLit({ mx + 2, my + 2 })) {
int mi = abs(dMonster[mx + 2][my + 2]) - 1;
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 4) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 2][my + 2]) - 1;
if (Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 4) != 0) {
cursPosition = Point { mx, my } + Displacement { 2, 2 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (!flipflag && mx + 1 < MAXDUNX && dMonster[mx + 1][my] != 0 && IsTileLit({ mx + 1, my })) {
int mi = abs(dMonster[mx + 1][my]) - 1;
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 2) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 1][my]) - 1;
if (Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 0 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (flipflag && my + 1 < MAXDUNY && dMonster[mx][my + 1] != 0 && IsTileLit({ mx, my + 1 })) {
int mi = abs(dMonster[mx][my + 1]) - 1;
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 2) != 0) {
const uint16_t monsterId = abs(dMonster[mx][my + 1]) - 1;
if (Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 0, 1 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (dMonster[mx][my] != 0 && IsTileLit({ mx, my })) {
int mi = abs(dMonster[mx][my]) - 1;
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 1) != 0) {
const uint16_t monsterId = abs(dMonster[mx][my]) - 1;
if (Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 1) != 0) {
cursPosition = { mx, my };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (mx + 1 < MAXDUNX && my + 1 < MAXDUNY && dMonster[mx + 1][my + 1] != 0 && IsTileLit({ mx + 1, my + 1 })) {
int mi = abs(dMonster[mx + 1][my + 1]) - 1;
if (Monsters[mi].hitPoints >> 6 > 0 && (Monsters[mi].data().selectionType & 2) != 0) {
const uint16_t monsterId = abs(dMonster[mx + 1][my + 1]) - 1;
if (Monsters[monsterId].hitPoints >> 6 > 0 && (Monsters[monsterId].data().selectionType & 2) != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 1 };
pcursmonst = mi;
pcursmonst = monsterId;
}
}
if (pcursmonst != -1 && (Monsters[pcursmonst].flags & MFLAG_HIDDEN) != 0) {
@ -559,34 +559,33 @@ void CheckCursMove()
if (pcursmonst == -1) {
if (!flipflag && mx + 1 < MAXDUNX && dPlayer[mx + 1][my] != 0) {
int8_t bv = abs(dPlayer[mx + 1][my]) - 1;
Player &player = Players[bv];
const uint8_t playerId = abs(dPlayer[mx + 1][my]) - 1;
Player &player = Players[playerId];
if (&player != MyPlayer && player._pHitPoints != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 0 };
pcursplr = bv;
pcursplr = static_cast<int8_t>(playerId);
}
}
if (flipflag && my + 1 < MAXDUNY && dPlayer[mx][my + 1] != 0) {
int8_t bv = abs(dPlayer[mx][my + 1]) - 1;
Player &player = Players[bv];
const uint8_t playerId = abs(dPlayer[mx][my + 1]) - 1;
Player &player = Players[playerId];
if (&player != MyPlayer && player._pHitPoints != 0) {
cursPosition = Point { mx, my } + Displacement { 0, 1 };
pcursplr = bv;
pcursplr = static_cast<int8_t>(playerId);
}
}
if (dPlayer[mx][my] != 0) {
int8_t bv = abs(dPlayer[mx][my]) - 1;
if (bv != MyPlayerId) {
const uint8_t playerId = abs(dPlayer[mx][my]) - 1;
if (playerId != MyPlayerId) {
cursPosition = { mx, my };
pcursplr = bv;
pcursplr = static_cast<int8_t>(playerId);
}
}
if (TileContainsDeadPlayer({ mx, my })) {
for (int i = 0; i < MAX_PLRS; i++) {
const Player &player = Players[i];
for (const Player &player : Players) {
if (player.position.tile == Point { mx, my } && &player != MyPlayer) {
cursPosition = { mx, my };
pcursplr = i;
pcursplr = static_cast<int8_t>(player.getId());
}
}
}
@ -594,11 +593,10 @@ void CheckCursMove()
for (int xx = -1; xx < 2; xx++) {
for (int yy = -1; yy < 2; yy++) {
if (TileContainsDeadPlayer({ mx + xx, my + yy })) {
for (int i = 0; i < MAX_PLRS; i++) {
const Player &player = Players[i];
for (const Player &player : Players) {
if (player.position.tile.x == mx + xx && player.position.tile.y == my + yy && &player != MyPlayer) {
cursPosition = Point { mx, my } + Displacement { xx, yy };
pcursplr = i;
pcursplr = static_cast<int8_t>(player.getId());
}
}
}
@ -606,11 +604,11 @@ void CheckCursMove()
}
}
if (mx + 1 < MAXDUNX && my + 1 < MAXDUNY && dPlayer[mx + 1][my + 1] != 0) {
int8_t bv = abs(dPlayer[mx + 1][my + 1]) - 1;
const Player &player = Players[bv];
const uint8_t playerId = abs(dPlayer[mx + 1][my + 1]) - 1;
const Player &player = Players[playerId];
if (&player != MyPlayer && player._pHitPoints != 0) {
cursPosition = Point { mx, my } + Displacement { 1, 1 };
pcursplr = bv;
pcursplr = static_cast<int8_t>(playerId);
}
}
}
@ -645,31 +643,31 @@ void CheckCursMove()
}
if (pcursplr == -1 && ObjectUnderCursor == nullptr && pcursmonst == -1) {
if (!flipflag && mx + 1 < MAXDUNX && dItem[mx + 1][my] > 0) {
int8_t bv = dItem[mx + 1][my] - 1;
if (Items[bv]._iSelFlag >= 2) {
const uint8_t itemId = dItem[mx + 1][my] - 1;
if (Items[itemId]._iSelFlag >= 2) {
cursPosition = Point { mx, my } + Displacement { 1, 0 };
pcursitem = bv;
pcursitem = static_cast<int8_t>(itemId);
}
}
if (flipflag && my + 1 < MAXDUNY && dItem[mx][my + 1] > 0) {
int8_t bv = dItem[mx][my + 1] - 1;
if (Items[bv]._iSelFlag >= 2) {
const uint8_t itemId = dItem[mx][my + 1] - 1;
if (Items[itemId]._iSelFlag >= 2) {
cursPosition = Point { mx, my } + Displacement { 0, 1 };
pcursitem = bv;
pcursitem = static_cast<int8_t>(itemId);
}
}
if (dItem[mx][my] > 0) {
int8_t bv = dItem[mx][my] - 1;
if (Items[bv]._iSelFlag == 1 || Items[bv]._iSelFlag == 3) {
const uint8_t itemId = dItem[mx][my] - 1;
if (Items[itemId]._iSelFlag == 1 || Items[itemId]._iSelFlag == 3) {
cursPosition = { mx, my };
pcursitem = bv;
pcursitem = static_cast<int8_t>(itemId);
}
}
if (mx + 1 < MAXDUNX && my + 1 < MAXDUNY && dItem[mx + 1][my + 1] > 0) {
int8_t bv = dItem[mx + 1][my + 1] - 1;
if (Items[bv]._iSelFlag >= 2) {
const uint8_t itemId = dItem[mx + 1][my + 1] - 1;
if (Items[itemId]._iSelFlag >= 2) {
cursPosition = Point { mx, my } + Displacement { 1, 1 };
pcursitem = bv;
pcursitem = static_cast<int8_t>(itemId);
}
}
if (pcursitem == -1) {

2
Source/debug.cpp

@ -935,7 +935,7 @@ std::string DebugCmdQuestInfo(const string_view parameter)
std::string DebugCmdPlayerInfo(const string_view parameter)
{
int playerId = atoi(parameter.data());
if (playerId < 0 || playerId >= MAX_PLRS)
if (static_cast<size_t>(playerId) >= Players.size())
return "My friend, we need a valid playerId.";
Player &player = Players[playerId];
if (!player.plractive)

12
Source/dvlnet/base.cpp

@ -4,6 +4,8 @@
#include <cstring>
#include <memory>
#include "player.h"
namespace devilution {
namespace net {
@ -218,7 +220,7 @@ bool base::SNetSendMessage(int playerId, void *data, unsigned int size)
bool base::AllTurnsArrived()
{
for (auto i = 0; i < MAX_PLRS; ++i) {
for (size_t i = 0; i < Players.size(); ++i) {
PlayerState &playerState = playerStateTable_[i];
if (!playerState.isConnected)
continue;
@ -237,7 +239,7 @@ bool base::SNetReceiveTurns(char **data, size_t *size, uint32_t *status)
{
poll();
for (auto i = 0; i < MAX_PLRS; ++i) {
for (size_t i = 0; i < Players.size(); ++i) {
status[i] = 0;
PlayerState &playerState = playerStateTable_[i];
@ -257,7 +259,7 @@ bool base::SNetReceiveTurns(char **data, size_t *size, uint32_t *status)
}
if (AllTurnsArrived()) {
for (auto i = 0; i < MAX_PLRS; ++i) {
for (size_t i = 0; i < Players.size(); ++i) {
PlayerState &playerState = playerStateTable_[i];
if (!playerState.isConnected)
continue;
@ -284,7 +286,7 @@ bool base::SNetReceiveTurns(char **data, size_t *size, uint32_t *status)
return true;
}
for (auto i = 0; i < MAX_PLRS; ++i) {
for (size_t i = 0; i < Players.size(); ++i) {
PlayerState &playerState = playerStateTable_[i];
if (!playerState.isConnected)
continue;
@ -414,7 +416,7 @@ bool base::SNetDropPlayer(int playerid, uint32_t flags)
plr_t base::GetOwner()
{
for (auto i = 0; i < MAX_PLRS; ++i) {
for (size_t i = 0; i < Players.size(); ++i) {
if (IsConnected(i)) {
return i;
}

16
Source/dvlnet/base_protocol.h

@ -68,7 +68,7 @@ template <class P>
plr_t base_protocol<P>::get_master()
{
plr_t ret = plr_self;
for (plr_t i = 0; i < MAX_PLRS; ++i)
for (plr_t i = 0; i < Players.size(); ++i)
if (peers[i].endpoint)
ret = std::min(ret, i);
return ret;
@ -195,7 +195,7 @@ void base_protocol<P>::send(packet &pkt)
return;
SendTo(destination, pkt);
} else if (destination == PLR_BROADCAST) {
for (plr_t player = 0; player < MAX_PLRS; player++)
for (plr_t player = 0; player < Players.size(); player++)
SendTo(player, pkt);
} else if (destination == PLR_MASTER) {
throw dvlnet_exception();
@ -236,7 +236,7 @@ void base_protocol<P>::recv()
}
}
while (proto.get_disconnected(sender)) {
for (plr_t i = 0; i < MAX_PLRS; ++i) {
for (plr_t i = 0; i < Players.size(); ++i) {
if (peers[i].endpoint == sender) {
DisconnectNet(i);
break;
@ -253,7 +253,7 @@ template <class P>
void base_protocol<P>::handle_join_request(packet &pkt, endpoint_t sender)
{
plr_t i;
for (i = 0; i < MAX_PLRS; ++i) {
for (i = 0; i < Players.size(); ++i) {
Peer &peer = peers[i];
if (i != plr_self && !peer.endpoint) {
peer.endpoint = sender;
@ -268,7 +268,7 @@ void base_protocol<P>::handle_join_request(packet &pkt, endpoint_t sender)
}
auto senderinfo = sender.serialize();
for (plr_t j = 0; j < MAX_PLRS; ++j) {
for (plr_t j = 0; j < Players.size(); ++j) {
endpoint_t peer = peers[j].endpoint;
if ((j != plr_self) && (j != i) && peer) {
auto peerpkt = pktfty->make_packet<PT_CONNECT>(PLR_MASTER, PLR_BROADCAST, i, senderinfo);
@ -297,7 +297,7 @@ void base_protocol<P>::recv_decrypted(packet &pkt, endpoint_t sender)
return;
const GameData *gameData = (const GameData *)pkt.Info().data();
std::vector<std::string> playerNames;
for (size_t i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
std::string playerName;
const char *playerNamePointer = (const char *)(pkt.Info().data() + sizeof(GameData) + (i * PlayerNameLength));
playerName.append(playerNamePointer, strnlen(playerNamePointer, PlayerNameLength));
@ -325,7 +325,7 @@ void base_protocol<P>::recv_ingame(packet &pkt, endpoint_t sender)
buffer_t buf;
buf.resize(game_init_info.size() + (PlayerNameLength * MAX_PLRS) + gamename.size());
std::memcpy(buf.data(), &game_init_info[0], game_init_info.size());
for (size_t i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
if (Players[i].plractive) {
std::memcpy(buf.data() + game_init_info.size() + (i * PlayerNameLength), &Players[i]._pName, PlayerNameLength);
} else {
@ -379,7 +379,7 @@ void base_protocol<P>::recv_ingame(packet &pkt, endpoint_t sender)
if (plr_self != PLR_BROADCAST) {
if (wasBroadcast) {
// Send a handshake to everyone just after PT_JOIN_ACCEPT
for (plr_t player = 0; player < MAX_PLRS; player++)
for (plr_t player = 0; player < Players.size(); player++)
InitiateHandshake(player);
}

3
Source/dvlnet/loopback.cpp

@ -1,6 +1,7 @@
#include "dvlnet/loopback.h"
#include "multi.h"
#include "player.h"
#include "utils/language.h"
#include "utils/stubs.h"
@ -41,7 +42,7 @@ bool loopback::SNetSendMessage(int dest, void *data, unsigned int size)
bool loopback::SNetReceiveTurns(char **data, size_t *size, uint32_t * /*status*/)
{
for (auto i = 0; i < MAX_PLRS; ++i) {
for (size_t i = 0; i < Players.size(); ++i) {
size[i] = 0;
data[i] = nullptr;
}

9
Source/dvlnet/tcp_server.cpp

@ -6,6 +6,7 @@
#include <utility>
#include "dvlnet/base.h"
#include "player.h"
#include "utils/log.hpp"
namespace devilution {
@ -44,7 +45,7 @@ tcp_server::scc tcp_server::MakeConnection()
plr_t tcp_server::NextFree()
{
for (plr_t i = 0; i < MAX_PLRS; ++i)
for (plr_t i = 0; i < Players.size(); ++i)
if (!connections[i])
return i;
return PLR_BROADCAST;
@ -52,7 +53,7 @@ plr_t tcp_server::NextFree()
bool tcp_server::Empty()
{
for (plr_t i = 0; i < MAX_PLRS; ++i)
for (plr_t i = 0; i < Players.size(); ++i)
if (connections[i])
return false;
return true;
@ -108,7 +109,7 @@ void tcp_server::HandleReceiveNewPlayer(const scc &con, packet &pkt)
if (Empty())
game_init_info = pkt.Info();
for (plr_t player = 0; player < MAX_PLRS; player++) {
for (plr_t player = 0; player < Players.size(); player++) {
if (connections[player]) {
auto playerPacket = pktfty.make_packet<PT_CONNECT>(PLR_MASTER, PLR_BROADCAST, newplr);
StartSend(connections[player], *playerPacket);
@ -135,7 +136,7 @@ void tcp_server::HandleReceivePacket(packet &pkt)
void tcp_server::SendPacket(packet &pkt)
{
if (pkt.Destination() == PLR_BROADCAST) {
for (auto i = 0; i < MAX_PLRS; ++i)
for (size_t i = 0; i < Players.size(); ++i)
if (i != pkt.Source() && connections[i])
StartSend(connections[i], pkt);
} else {

4
Source/engine/render/scrollrt.cpp

@ -496,7 +496,7 @@ void DrawPlayer(const Surface &out, const Player &player, Point tilePosition, Po
Point spriteBufferPosition = targetBufferPosition - Displacement { CalculateWidth2(sprite.width()), 0 };
if (pcursplr >= 0 && pcursplr < MAX_PLRS && &player == &Players[pcursplr])
if (static_cast<size_t>(pcursplr) < Players.size() && &player == &Players[pcursplr])
ClxDrawOutlineSkipColorZero(out, 165, spriteBufferPosition, sprite);
if (&player == MyPlayer) {
@ -799,7 +799,7 @@ void DrawDungeon(const Surface &out, Point tilePosition, Point targetBufferPosit
DrawDeadPlayer(out, tilePosition, targetBufferPosition);
}
int8_t playerId = dPlayer[tilePosition.x][tilePosition.y];
if (playerId > 0 && playerId <= MAX_PLRS) {
if (static_cast<size_t>(playerId - 1) < Players.size()) {
DrawPlayerHelper(out, Players[playerId - 1], tilePosition, targetBufferPosition);
}
if (dMonster[tilePosition.x][tilePosition.y] != 0) {

2
Source/items.cpp

@ -3020,7 +3020,7 @@ void GetItemAttrs(Item &item, int itemData, int lvl)
void SetupItem(Item &item)
{
item.setNewAnimation(MyPlayer->pLvlLoad == 0);
item.setNewAnimation(MyPlayer != nullptr && MyPlayer->pLvlLoad == 0);
item._iIdentified = false;
}

4
Source/monster.cpp

@ -624,7 +624,7 @@ void UpdateEnemy(Monster &monster)
bool bestsameroom = false;
const auto &position = monster.position.tile;
if ((monster.flags & MFLAG_BERSERK) != 0 || (monster.flags & MFLAG_GOLEM) == 0) {
for (int pnum = 0; pnum < MAX_PLRS; pnum++) {
for (size_t pnum = 0; pnum < Players.size(); pnum++) {
Player &player = Players[pnum];
if (!player.plractive || !player.isOnActiveLevel() || player._pLvlChanging
|| (((player._pHitPoints >> 6) == 0) && gbIsMultiplayer))
@ -635,7 +635,7 @@ void UpdateEnemy(Monster &monster)
|| ((sameroom || !bestsameroom) && dist < bestDist)
|| (menemy == -1)) {
monster.flags &= ~MFLAG_TARGETS_MONSTER;
menemy = pnum;
menemy = static_cast<int>(pnum);
target = player.position.future;
bestDist = dist;
bestsameroom = sameroom;

30
Source/msg.cpp

@ -237,7 +237,7 @@ void PrePacket()
continue;
}
if (playerId >= MAX_PLRS) {
if (playerId >= Players.size()) {
Log("Missing source of network message");
return;
}
@ -291,7 +291,7 @@ int WaitForTurns()
if (gbGameDestroyed)
return 100;
if (gbDeltaSender >= MAX_PLRS) {
if (gbDeltaSender >= Players.size()) {
sgbDeltaChunks = 0;
sgbRecvCmd = CMD_DLEVEL_END;
gbDeltaSender = MyPlayerId;
@ -820,9 +820,9 @@ size_t OnGotoGetItem(const TCmd *pCmd, Player &player)
bool IsGItemValid(const TCmdGItem &message)
{
if (message.bMaster >= MAX_PLRS)
if (message.bMaster >= Players.size())
return false;
if (message.bPnum >= MAX_PLRS)
if (message.bPnum >= Players.size())
return false;
if (message.bCursitem >= MAXITEMS + 1)
return false;
@ -1275,7 +1275,7 @@ size_t OnAttackPlayer(const TCmd *pCmd, Player &player)
{
const auto &message = *reinterpret_cast<const TCmdParam1 *>(pCmd);
if (gbBufferMsgs != 1 && player.isOnActiveLevel() && message.wParam1 < MAX_PLRS) {
if (gbBufferMsgs != 1 && player.isOnActiveLevel() && message.wParam1 < Players.size()) {
MakePlrPath(player, Players[message.wParam1].position.future, false);
player.destAction = ACTION_ATTACKPLR;
player.destParam1 = message.wParam1;
@ -1301,7 +1301,7 @@ size_t OnRangedAttackPlayer(const TCmd *pCmd, Player &player)
{
const auto &message = *reinterpret_cast<const TCmdParam1 *>(pCmd);
if (gbBufferMsgs != 1 && player.isOnActiveLevel() && message.wParam1 < MAX_PLRS) {
if (gbBufferMsgs != 1 && player.isOnActiveLevel() && message.wParam1 < Players.size()) {
ClrPlrPath(player);
player.destAction = ACTION_RATTACKPLR;
player.destParam1 = message.wParam1;
@ -1354,7 +1354,7 @@ size_t OnSpellPlayer(const TCmd *pCmd, Player &player)
return sizeof(message);
if (!player.isOnActiveLevel())
return sizeof(message);
if (message.wParam1 >= MAX_PLRS)
if (message.wParam1 >= Players.size())
return sizeof(message);
if (message.wParam2 > SPL_LAST)
return sizeof(message);
@ -1422,7 +1422,7 @@ size_t OnTargetSpellPlayer(const TCmd *pCmd, Player &player)
return sizeof(message);
if (!player.isOnActiveLevel())
return sizeof(message);
if (message.wParam1 >= MAX_PLRS)
if (message.wParam1 >= Players.size())
return sizeof(message);
if (message.wParam2 > SPL_LAST)
return sizeof(message);
@ -1467,9 +1467,9 @@ size_t OnResurrect(const TCmd *pCmd, int pnum)
if (gbBufferMsgs == 1) {
SendPacket(pnum, &message, sizeof(message));
} else if (message.wParam1 < MAX_PLRS) {
} else if (message.wParam1 < Players.size()) {
DoResurrect(pnum, Players[message.wParam1]);
if (pnum == MyPlayerId)
if (static_cast<size_t>(pnum) == MyPlayerId)
pfile_update(true);
}
@ -1481,7 +1481,7 @@ size_t OnHealOther(const TCmd *pCmd, const Player &caster)
const auto &message = *reinterpret_cast<const TCmdParam1 *>(pCmd);
if (gbBufferMsgs != 1) {
if (caster.isOnActiveLevel() && message.wParam1 < MAX_PLRS) {
if (caster.isOnActiveLevel() && message.wParam1 < Players.size()) {
DoHealOther(caster, Players[message.wParam1]);
}
}
@ -1509,7 +1509,7 @@ size_t OnNewLevel(const TCmd *pCmd, int pnum)
if (gbBufferMsgs == 1) {
SendPacket(pnum, &message, sizeof(message));
} else if (pnum != MyPlayerId) {
} else if (pnum != static_cast<int>(MyPlayerId)) {
if (message.wParam1 < WM_FIRST || message.wParam1 > WM_LAST)
return sizeof(message);
@ -1963,7 +1963,7 @@ size_t OnRestartTown(const TCmd *pCmd, int pnum)
if (gbBufferMsgs == 1) {
SendPacket(pnum, pCmd, sizeof(*pCmd));
} else {
if (pnum == MyPlayerId) {
if (pnum == static_cast<int>(MyPlayerId)) {
MyPlayerIsDead = false;
gamemenu_off();
}
@ -2058,7 +2058,7 @@ size_t OnSyncQuest(const TCmd *pCmd, int pnum)
if (gbBufferMsgs == 1) {
SendPacket(pnum, &message, sizeof(message));
} else {
if (pnum != MyPlayerId && message.q < MAXQUESTS && message.qstate <= QUEST_HIVE_DONE)
if (pnum != static_cast<int>(MyPlayerId) && message.q < MAXQUESTS && message.qstate <= QUEST_HIVE_DONE)
SetMultiQuest(message.q, message.qstate, message.qlog != 0, message.qvar1);
sgbDeltaChanged = true;
}
@ -2642,7 +2642,7 @@ void NetSendCmdGolem(uint8_t mx, uint8_t my, Direction dir, uint8_t menemy, int
void NetSendCmdLoc(int playerId, bool bHiPri, _cmd_id bCmd, Point position)
{
if (playerId == MyPlayerId && WasPlayerCmdAlreadyRequested(bCmd, position))
if (playerId == static_cast<int>(MyPlayerId) && WasPlayerCmdAlreadyRequested(bCmd, position))
return;
TCmdLoc cmd;

40
Source/multi.cpp

@ -12,6 +12,7 @@
#include "DiabloUI/diabloui.h"
#include "diablo.h"
#include "engine/demomode.h"
#include "engine/point.hpp"
#include "engine/random.hpp"
#include "engine/world_tile.hpp"
@ -150,7 +151,7 @@ bool IsNetPlayerValid(const Player &player)
void CheckPlayerInfoTimeouts()
{
for (int i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
Player &player = Players[i];
if (&player == MyPlayer) {
continue;
@ -198,11 +199,11 @@ void MonsterSeeds()
Monsters[i].aiSeed = seed + i;
}
void HandleTurnUpperBit(int pnum)
void HandleTurnUpperBit(size_t pnum)
{
int i;
size_t i;
for (i = 0; i < MAX_PLRS; i++) {
for (i = 0; i < Players.size(); i++) {
if ((player_state[i] & PS_CONNECTED) != 0 && i != pnum)
break;
}
@ -214,7 +215,7 @@ void HandleTurnUpperBit(int pnum)
}
}
void ParseTurn(int pnum, uint32_t turn)
void ParseTurn(size_t pnum, uint32_t turn)
{
if ((turn & 0x80000000) != 0)
HandleTurnUpperBit(pnum);
@ -262,7 +263,7 @@ void PlayerLeftMsg(int pnum, bool left)
void ClearPlayerLeftState()
{
for (int i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
if (sgbPlayerLeftGameTbl[i]) {
if (gbBufferMsgs == 1)
msg_send_drop_pkt(i, sgdwPlayerLeftReasonTbl[i]);
@ -277,7 +278,7 @@ void ClearPlayerLeftState()
void CheckDropPlayer()
{
for (int i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
if ((player_state[i] & PS_ACTIVE) == 0 && (player_state[i] & PS_CONNECTED) != 0) {
SNetDropPlayer(i, LEAVE_DROP);
}
@ -411,6 +412,8 @@ void UnregisterNetEventHandlers()
bool InitSingle(GameData *gameData)
{
Players.resize(1);
if (!SNetInitializeProvider(SELCONN_LOOPBACK, gameData)) {
return false;
}
@ -431,6 +434,8 @@ bool InitSingle(GameData *gameData)
bool InitMulti(GameData *gameData)
{
Players.resize(MAX_PLRS);
int playerId;
while (true) {
@ -445,7 +450,7 @@ bool InitMulti(GameData *gameData)
gbSelectProvider = true;
}
if (playerId < 0 || playerId >= MAX_PLRS) {
if (static_cast<size_t>(playerId) >= Players.size()) {
return false;
}
MyPlayerId = playerId;
@ -511,7 +516,7 @@ void multi_send_msg_packet(uint32_t pmask, const byte *data, size_t size)
pkt.hdr.wLen = static_cast<uint16_t>(len);
memcpy(pkt.body, data, size);
size_t playerID = 0;
for (size_t v = 1; playerID < MAX_PLRS; playerID++, v <<= 1) {
for (size_t v = 1; playerID < Players.size(); playerID++, v <<= 1) {
if ((v & pmask) != 0) {
if (!SNetSendMessage(playerID, &pkt.hdr, len) && SErrGetLastError() != STORM_ERROR_INVALID_PLAYER) {
nthread_terminate_game("SNetSendMessage");
@ -523,7 +528,7 @@ void multi_send_msg_packet(uint32_t pmask, const byte *data, size_t size)
void multi_msg_countdown()
{
for (int i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
if ((player_state[i] & PS_TURN_ARRIVED) != 0) {
if (gdwMsgLenTbl[i] == sizeof(int32_t))
ParseTurn(i, *(int32_t *)glpMsgTbl[i]);
@ -551,7 +556,7 @@ bool multi_handle_delta()
return false;
}
for (int i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
if (sgbSendDeltaTbl[i]) {
sgbSendDeltaTbl[i] = false;
DeltaExportData(i);
@ -594,7 +599,7 @@ void multi_process_network_packets()
ClearPlayerLeftState();
if (dwMsgSize < sizeof(TPktHdr))
continue;
if (dwID < 0 || dwID >= MAX_PLRS)
if (static_cast<size_t>(dwID) >= Players.size())
continue;
if (pkt->wCheck != LoadBE32("\0\0ip"))
continue;
@ -655,7 +660,7 @@ void multi_process_network_packets()
void multi_send_zero_packet(int pnum, _cmd_id bCmd, const byte *data, size_t size)
{
assert(pnum != MyPlayerId);
assert(pnum != static_cast<int>(MyPlayerId));
assert(data != nullptr);
assert(size <= 0x0ffff);
@ -700,6 +705,10 @@ void NetClose()
SNetLeaveGame(3);
if (gbIsMultiplayer)
SDL_Delay(2000);
if (!demo::IsRunning()) {
Players.clear();
MyPlayer = nullptr;
}
}
bool NetInit(bool bSinglePlayer)
@ -712,9 +721,8 @@ bool NetInit(bool bSinglePlayer)
memset(sgbPlayerLeftGameTbl, 0, sizeof(sgbPlayerLeftGameTbl));
memset(sgdwPlayerLeftReasonTbl, 0, sizeof(sgdwPlayerLeftReasonTbl));
memset(sgbSendDeltaTbl, 0, sizeof(sgbSendDeltaTbl));
for (Player &player : Players) {
player.Reset();
}
Players.clear();
MyPlayer = nullptr;
memset(sgwPackPlrOffsetTbl, 0, sizeof(sgwPackPlrOffsetTbl));
SNetSetBasePlayer(0);
if (bSinglePlayer) {

21
Source/player.cpp

@ -47,9 +47,9 @@
namespace devilution {
int MyPlayerId;
Player *MyPlayer = &Players[MyPlayerId];
Player Players[MAX_PLRS];
size_t MyPlayerId;
Player *MyPlayer;
std::vector<Player> Players;
bool MyPlayerIsDead;
/** Specifies the X-coordinate delta from the player start location in Tristram. */
@ -1933,13 +1933,6 @@ bool Player::IsWalking() const
return IsAnyOf(_pmode, PM_WALK_NORTHWARDS, PM_WALK_SOUTHWARDS, PM_WALK_SIDEWAYS);
}
void Player::Reset()
{
// Create empty default initialized Player on heap to avoid excessive stack usage
auto emptyPlayer = std::make_unique<Player>();
*this = std::move(*emptyPlayer);
}
int Player::GetManaShieldDamageReduction()
{
constexpr int8_t Max = 7;
@ -2421,7 +2414,7 @@ void SetPlrAnims(Player &player)
*/
void CreatePlayer(Player &player, HeroClass c)
{
player.Reset();
player = {};
SetRndSeed(SDL_GetTicks());
player._pClass = c;
@ -2674,7 +2667,7 @@ void AddPlrExperience(Player &player, int lvl, int exp)
void AddPlrMonstExper(int lvl, int exp, char pmask)
{
int totplrs = 0;
for (int i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
if (((1 << i) & pmask) != 0) {
totplrs++;
}
@ -3165,7 +3158,7 @@ void RestartTownLvl(Player &player)
}
}
void StartWarpLvl(Player &player, int pidx)
void StartWarpLvl(Player &player, size_t pidx)
{
InitLevelChange(player);
@ -3223,7 +3216,7 @@ void ProcessPlayers()
ValidatePlayer();
for (int pnum = 0; pnum < MAX_PLRS; pnum++) {
for (size_t pnum = 0; pnum < Players.size(); pnum++) {
Player &player = Players[pnum];
if (player.plractive && player.isOnActiveLevel() && (&player == MyPlayer || !player._pLvlChanging)) {
CheckCheatStats(player);

12
Source/player.h

@ -6,6 +6,7 @@
#pragma once
#include <cstdint>
#include <vector>
#include <algorithm>
#include <array>
@ -463,11 +464,6 @@ struct Player {
*/
bool IsWalking() const;
/**
* @brief Resets all Data of the current Player
*/
void Reset();
/**
* @brief Returns item location taking into consideration barbarian's ability to hold two-handed maces and clubs in one hand.
*/
@ -745,9 +741,9 @@ struct Player {
}
};
extern DVL_API_FOR_TEST int MyPlayerId;
extern DVL_API_FOR_TEST size_t MyPlayerId;
extern DVL_API_FOR_TEST Player *MyPlayer;
extern DVL_API_FOR_TEST Player Players[MAX_PLRS];
extern DVL_API_FOR_TEST std::vector<Player> Players;
extern bool MyPlayerIsDead;
extern const int BlockBonuses[enum_size<HeroClass>::value];
@ -797,7 +793,7 @@ void SyncPlrKill(Player &player, int earflag);
void RemovePlrMissiles(const Player &player);
void StartNewLvl(Player &player, interface_mode fom, int lvl);
void RestartTownLvl(Player &player);
void StartWarpLvl(Player &player, int pidx);
void StartWarpLvl(Player &player, size_t pidx);
void ProcessPlayers();
void ClrPlrPath(Player &player);
bool PosOkPlayer(const Player &player, Point position);

4
Source/portal.cpp

@ -19,7 +19,7 @@ Portal Portals[MAXPORTAL];
namespace {
/** Current portal number (a portal array index). */
int portalindex;
size_t portalindex;
/** Coordinate of each players portal in town. */
Point WarpDrop[MAXPORTAL] = {
@ -124,7 +124,7 @@ void RemovePortalMissile(int id)
});
}
void SetCurrentPortal(int p)
void SetCurrentPortal(size_t p)
{
portalindex = p;
}

2
Source/portal.h

@ -31,7 +31,7 @@ void ActivatePortal(int i, Point position, int lvl, dungeon_type lvltype, bool s
void DeactivatePortal(int i);
bool PortalOnLevel(int i);
void RemovePortalMissile(int id);
void SetCurrentPortal(int p);
void SetCurrentPortal(size_t p);
void GetPortalLevel();
void GetPortalLvlPos();
bool PosOkPortal(int lvl, int x, int y);

2
Source/qol/monhealthbar.cpp

@ -155,7 +155,7 @@ void DrawMonsterHealthBar(const Surface &out)
}
int tagOffset = 5;
for (size_t i = 0; i < MAX_PLRS; i++) {
for (size_t i = 0; i < Players.size(); i++) {
if (((1U << i) & monster.whoHit) != 0) {
RenderClxSprite(out, (*playerExpTags)[i + 1], position + Displacement { tagOffset, height - 31 });
} else if (Players[i].plractive) {

6
Source/spells.cpp

@ -252,8 +252,12 @@ void CastSpell(int id, spell_id spl, int sx, int sy, int dx, int dy, int spllvl)
}
}
void DoResurrect(int pnum, Player &target)
void DoResurrect(size_t pnum, Player &target)
{
if (pnum >= Players.size()) {
return;
}
AddMissile(target.position.tile, target.position.tile, Direction::South, MIS_RESURRECTBEAM, TARGET_MONSTERS, pnum, 0, 0);
if (target._pHitPoints != 0)

2
Source/spells.h

@ -37,7 +37,7 @@ void CastSpell(int id, spell_id spl, int sx, int sy, int dx, int dy, int spllvl)
* @param pnum player index
* @param rid target player index
*/
void DoResurrect(int pnum, Player &target);
void DoResurrect(size_t pnum, Player &target);
void DoHealOther(const Player &caster, Player &target);
int GetSpellBookLevel(spell_id s);
int GetSpellStaffLevel(spell_id s);

4
Source/sync.cpp

@ -295,7 +295,7 @@ uint32_t OnSyncData(const TCmd *pCmd, int pnum)
if (gbBufferMsgs == 1) {
return header.wLen + sizeof(header);
}
if (pnum == MyPlayerId) {
if (pnum == static_cast<int>(MyPlayerId)) {
return header.wLen + sizeof(header);
}
@ -312,7 +312,7 @@ uint32_t OnSyncData(const TCmd *pCmd, int pnum)
continue;
if (GetLevelForMultiplayer(*MyPlayer) == level) {
SyncMonster(pnum > MyPlayerId, monsterSyncs[i]);
SyncMonster(pnum > static_cast<int>(MyPlayerId), monsterSyncs[i]);
}
delta_sync_monster(monsterSyncs[i], level);

2
Source/towners.cpp

@ -810,7 +810,7 @@ bool IsTownerPresent(_talker_id npc)
case TOWN_COWFARM:
return gbIsHellfire && sgGameInitInfo.bCowQuest != 0;
case TOWN_GIRL:
return gbIsHellfire && sgGameInitInfo.bTheoQuest != 0 && Players->_pLvlVisited[17] && Quests[Q_GIRL]._qactive != QUEST_DONE;
return gbIsHellfire && sgGameInitInfo.bTheoQuest != 0 && MyPlayer->_pLvlVisited[17] && Quests[Q_GIRL]._qactive != QUEST_DONE;
default:
return true;
}

26
test/drlg_l1_test.cpp

@ -12,6 +12,8 @@ TEST(Drlg_l1, CreateL5Dungeon_diablo_1_2588)
{
LoadExpectedLevelData("diablo/1-2588.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = true;
TestCreateDungeon(1, 2588, ENTRY_MAIN);
@ -24,6 +26,8 @@ TEST(Drlg_l1, CreateL5Dungeon_diablo_1_743271966)
{
LoadExpectedLevelData("diablo/1-743271966.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = true;
TestCreateDungeon(1, 743271966, ENTRY_MAIN);
@ -36,6 +40,8 @@ TEST(Drlg_l1, CreateL5Dungeon_diablo_2_1383137027)
{
LoadExpectedLevelData("diablo/2-1383137027.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = true;
InitQuests();
@ -54,6 +60,8 @@ TEST(Drlg_l1, CreateL5Dungeon_diablo_3_844660068)
{
LoadExpectedLevelData("diablo/3-844660068.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = true;
Quests[Q_SKELKING]._qactive = QUEST_NOTAVAIL;
@ -67,6 +75,8 @@ TEST(Drlg_l1, CreateL5Dungeon_diablo_4_609325643)
{
LoadExpectedLevelData("diablo/4-609325643.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = true;
Quests[Q_LTBANNER]._qactive = QUEST_NOTAVAIL;
@ -80,6 +90,8 @@ TEST(Drlg_l1, CreateL5Dungeon_hellfire_1_401921334)
{
LoadExpectedLevelData("hellfire/1-401921334.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = false;
TestCreateDungeon(1, 401921334, ENTRY_MAIN);
@ -92,6 +104,8 @@ TEST(Drlg_l1, CreateL5Dungeon_hellfire_1_536340718)
{
LoadExpectedLevelData("hellfire/1-536340718.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = false;
TestCreateDungeon(1, 536340718, ENTRY_MAIN);
@ -104,6 +118,8 @@ TEST(Drlg_l1, CreateL5Dungeon_hellfire_2_128964898)
{
LoadExpectedLevelData("hellfire/2-128964898.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = false;
InitQuests();
Quests[Q_PWATER]._qactive = QUEST_NOTAVAIL;
@ -119,6 +135,8 @@ TEST(Drlg_l1, CreateL5Dungeon_hellfire_2_1180526547)
{
LoadExpectedLevelData("hellfire/2-1180526547.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = false;
InitQuests();
Quests[Q_PWATER]._qactive = QUEST_NOTAVAIL;
@ -134,6 +152,8 @@ TEST(Drlg_l1, CreateL5Dungeon_hellfire_3_1799396623)
{
LoadExpectedLevelData("hellfire/3-1799396623.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = false;
InitQuests();
Quests[Q_SKELKING]._qactive = QUEST_NOTAVAIL;
@ -148,6 +168,8 @@ TEST(Drlg_l1, CreateL5Dungeon_hellfire_3_1512491184)
{
LoadExpectedLevelData("hellfire/3-1512491184.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = false;
InitQuests();
Quests[Q_SKELKING]._qactive = QUEST_INIT;
@ -162,6 +184,8 @@ TEST(Drlg_l1, CreateL5Dungeon_hellfire_4_1190318991)
{
LoadExpectedLevelData("hellfire/4-1190318991.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = false;
InitQuests();
Quests[Q_LTBANNER]._qactive = QUEST_NOTAVAIL;
@ -176,6 +200,8 @@ TEST(Drlg_l1, CreateL5Dungeon_hellfire_4_1924296259)
{
LoadExpectedLevelData("hellfire/4-1924296259.dun");
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->pOriginalCathedral = false;
InitQuests();
Quests[Q_LTBANNER]._qactive = QUEST_INIT;

10
test/effects_test.cpp

@ -7,6 +7,8 @@ using namespace devilution;
TEST(Effects, CalculateSoundPosition_center)
{
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->position.tile = { 50, 50 };
int plVolume = 0;
int plPan = 0;
@ -17,6 +19,8 @@ TEST(Effects, CalculateSoundPosition_center)
TEST(Effects, CalculateSoundPosition_near)
{
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->position.tile = { 50, 50 };
int plVolume = 0;
int plPan = 0;
@ -27,6 +31,8 @@ TEST(Effects, CalculateSoundPosition_near)
TEST(Effects, CalculateSoundPosition_out_of_range)
{
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->position.tile = { 12, 12 };
int plVolume = 1234;
int plPan = 0;
@ -37,6 +43,8 @@ TEST(Effects, CalculateSoundPosition_out_of_range)
TEST(Effects, CalculateSoundPosition_extreme_right)
{
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->position.tile = { 50, 50 };
int plVolume = 0;
int plPan = 0;
@ -47,6 +55,8 @@ TEST(Effects, CalculateSoundPosition_extreme_right)
TEST(Effects, CalculateSoundPosition_extreme_left)
{
Players.resize(1);
MyPlayer = &Players[0];
MyPlayer->position.tile = { 50, 50 };
int plVolume = 0;
int plPan = 0;

39
test/inv_test.cpp

@ -5,7 +5,17 @@
#include "player.h"
#include "storm/storm_net.hpp"
using namespace devilution;
namespace devilution {
namespace {
class InvTest : public ::testing::Test {
public:
void SetUp() override
{
Players.resize(1);
MyPlayer = &Players[0];
}
};
/* Set up a given item as a spell scroll, allowing for its usage. */
void set_up_scroll(Item &item, spell_id spell)
@ -29,7 +39,7 @@ void clear_inventory()
}
// Test that the scroll is used in the inventory in correct conditions
TEST(Inv, UseScroll_from_inventory)
TEST_F(InvTest, UseScroll_from_inventory)
{
set_up_scroll(MyPlayer->InvList[2], SPL_FIREBOLT);
MyPlayer->_pNumInv = 5;
@ -37,14 +47,14 @@ TEST(Inv, UseScroll_from_inventory)
}
// Test that the scroll is used in the belt in correct conditions
TEST(Inv, UseScroll_from_belt)
TEST_F(InvTest, UseScroll_from_belt)
{
set_up_scroll(MyPlayer->SpdList[2], SPL_FIREBOLT);
EXPECT_TRUE(CanUseScroll(*MyPlayer, SPL_FIREBOLT));
}
// Test that the scroll is not used in the inventory for each invalid condition
TEST(Inv, UseScroll_from_inventory_invalid_conditions)
TEST_F(InvTest, UseScroll_from_inventory_invalid_conditions)
{
// Empty the belt to prevent using a scroll from the belt
for (int i = 0; i < MaxBeltItems; i++) {
@ -72,7 +82,7 @@ TEST(Inv, UseScroll_from_inventory_invalid_conditions)
}
// Test that the scroll is not used in the belt for each invalid condition
TEST(Inv, UseScroll_from_belt_invalid_conditions)
TEST_F(InvTest, UseScroll_from_belt_invalid_conditions)
{
// Disable the inventory to prevent using a scroll from the inventory
MyPlayer->_pNumInv = 0;
@ -95,7 +105,7 @@ TEST(Inv, UseScroll_from_belt_invalid_conditions)
}
// Test gold calculation
TEST(Inv, CalculateGold)
TEST_F(InvTest, CalculateGold)
{
MyPlayer->_pNumInv = 10;
// Set up 4 slots of gold in the inventory
@ -113,7 +123,7 @@ TEST(Inv, CalculateGold)
}
// Test automatic gold placing
TEST(Inv, GoldAutoPlace)
TEST_F(InvTest, GoldAutoPlace)
{
// Empty the inventory
clear_inventory();
@ -135,7 +145,7 @@ TEST(Inv, GoldAutoPlace)
}
// Test removing an item from inventory with no other items.
TEST(Inv, RemoveInvItem)
TEST_F(InvTest, RemoveInvItem)
{
SNetInitializeProvider(SELCONN_LOOPBACK, nullptr);
@ -154,7 +164,7 @@ TEST(Inv, RemoveInvItem)
}
// Test removing an item from inventory with other items in it.
TEST(Inv, RemoveInvItem_other_item)
TEST_F(InvTest, RemoveInvItem_other_item)
{
SNetInitializeProvider(SELCONN_LOOPBACK, nullptr);
@ -178,7 +188,7 @@ TEST(Inv, RemoveInvItem_other_item)
}
// Test removing an item from the belt
TEST(Inv, RemoveSpdBarItem)
TEST_F(InvTest, RemoveSpdBarItem)
{
SNetInitializeProvider(SELCONN_LOOPBACK, nullptr);
@ -194,7 +204,7 @@ TEST(Inv, RemoveSpdBarItem)
}
// Test removing a scroll from the inventory
TEST(Inv, RemoveCurrentSpellScroll_inventory)
TEST_F(InvTest, RemoveCurrentSpellScroll_inventory)
{
clear_inventory();
@ -211,7 +221,7 @@ TEST(Inv, RemoveCurrentSpellScroll_inventory)
}
// Test removing a scroll from the belt
TEST(Inv, RemoveCurrentSpellScroll_belt)
TEST_F(InvTest, RemoveCurrentSpellScroll_belt)
{
SNetInitializeProvider(SELCONN_LOOPBACK, nullptr);
@ -229,7 +239,7 @@ TEST(Inv, RemoveCurrentSpellScroll_belt)
EXPECT_TRUE(MyPlayer->SpdList[3].isEmpty());
}
TEST(Inv, ItemSize)
TEST_F(InvTest, ItemSize)
{
Item testItem {};
@ -250,3 +260,6 @@ TEST(Inv, ItemSize)
InitializeItem(testItem, IDI_GOLD);
EXPECT_EQ(GetInventorySize(testItem), Size(1, 1));
}
} // namespace
} // namespace devilution

5
test/missiles_test.cpp

@ -7,6 +7,11 @@ using namespace devilution;
TEST(Missiles, RotateBlockedMissileArrow)
{
Players.resize(1);
MyPlayerId = 0;
MyPlayer = &Players[MyPlayerId];
*MyPlayer = {};
Player &player = Players[0];
// missile can be a copy or a reference, there's no nullptr check and the functions that use it don't expect the instance to be part of a global structure so it doesn't really matter for this use.
Missile missile = *AddMissile({ 0, 0 }, { 0, 0 }, Direction::South, MIS_ARROW, TARGET_MONSTERS, player.getId(), 0, 0);

33
test/pack_test.cpp

@ -332,7 +332,16 @@ const TestItemStruct DiabloItems[] = {
// clang-format on
};
TEST(PackTest, UnPackItem_diablo)
class PackTest : public ::testing::Test {
public:
void SetUp() override
{
Players.resize(1);
MyPlayer = &Players[0];
}
};
TEST_F(PackTest, UnPackItem_diablo)
{
Item id;
ItemPack is;
@ -353,7 +362,7 @@ TEST(PackTest, UnPackItem_diablo)
}
}
TEST(PackTest, UnPackItem_diablo_unique_bug)
TEST_F(PackTest, UnPackItem_diablo_unique_bug)
{
ItemPack pkItemBug = { 6, 911, 14, 5, 60, 60, 0, 0, 0, 0 }; // Veil of Steel - with morph bug
ItemPack pkItem = { 6, 655, 14, 5, 60, 60, 0, 0, 0, 0 }; // Veil of Steel - fixed
@ -403,7 +412,7 @@ const TestItemStruct SpawnItems[] = {
// clang-format on
};
TEST(PackTest, UnPackItem_spawn)
TEST_F(PackTest, UnPackItem_spawn)
{
Item id;
ItemPack is;
@ -447,7 +456,7 @@ const TestItemStruct DiabloMPItems[] = {
// clang-format on
};
TEST(PackTest, UnPackItem_diablo_multiplayer)
TEST_F(PackTest, UnPackItem_diablo_multiplayer)
{
Item id;
ItemPack is;
@ -660,7 +669,7 @@ const TestItemStruct HellfireItems[] = {
// clang-format on
};
TEST(PackTest, UnPackItem_hellfire)
TEST_F(PackTest, UnPackItem_hellfire)
{
Item id;
ItemPack is;
@ -682,7 +691,7 @@ TEST(PackTest, UnPackItem_hellfire)
}
}
TEST(PackTest, UnPackItem_diablo_strip_hellfire_items)
TEST_F(PackTest, UnPackItem_diablo_strip_hellfire_items)
{
ItemPack is = { 1478792102, 259, 92, 0, 0, 0, 0, 0, 0, 0 }; // Scroll of Search
Item id;
@ -696,7 +705,7 @@ TEST(PackTest, UnPackItem_diablo_strip_hellfire_items)
ASSERT_EQ(id._itype, ItemType::None);
}
TEST(PackTest, UnPackItem_empty)
TEST_F(PackTest, UnPackItem_empty)
{
ItemPack is = { 0, 0, 0xFFFF, 0, 0, 0, 0, 0, 0, 0 };
Item id;
@ -706,7 +715,7 @@ TEST(PackTest, UnPackItem_empty)
ASSERT_EQ(id._itype, ItemType::None);
}
TEST(PackTest, PackItem_empty)
TEST_F(PackTest, PackItem_empty)
{
ItemPack is;
Item id = {};
@ -737,25 +746,25 @@ static void compareGold(const ItemPack &is, int iCurs)
ComparePackedItems(is, is2);
}
TEST(PackTest, UnPackItem_gold_small)
TEST_F(PackTest, UnPackItem_gold_small)
{
ItemPack is = { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 1000, 0 };
compareGold(is, ICURS_GOLD_SMALL);
}
TEST(PackTest, UnPackItem_gold_medium)
TEST_F(PackTest, UnPackItem_gold_medium)
{
ItemPack is = { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 1001, 0 };
compareGold(is, ICURS_GOLD_MEDIUM);
}
TEST(PackTest, UnPackItem_gold_large)
TEST_F(PackTest, UnPackItem_gold_large)
{
ItemPack is = { 0, 0, IDI_GOLD, 0, 0, 0, 0, 0, 2500, 0 };
compareGold(is, ICURS_GOLD_LARGE);
}
TEST(PackTest, UnPackItem_ear)
TEST_F(PackTest, UnPackItem_ear)
{
ItemPack is = { 1633955154, 17509, 23, 111, 103, 117, 101, 68, 19843, 0 };
Item id;

2
test/path_test.cpp

@ -110,7 +110,7 @@ void CheckPath(Point startPosition, Point destinationPosition, std::vector<int8_
// Die early if the wrong path length is returned as we don't want to read oob in expectedSteps
ASSERT_LE(pathLength, expectedSteps.size()) << "Path is longer than expected.";
for (auto i = 0; i < pathLength; i++) {
for (int i = 0; i < pathLength; i++) {
EXPECT_EQ(pathSteps[i], expectedSteps[i]) << "Path step " << i << " differs from expectation for a path from "
<< startPosition << " to " << destinationPosition; // this shouldn't be a requirement but...

3
test/player_test.cpp

@ -82,6 +82,8 @@ BlockTestCase BlockData[] = {
TEST(Player, PM_DoGotHit)
{
Players.resize(1);
MyPlayer = &Players[0];
for (size_t i = 0; i < sizeof(BlockData) / sizeof(*BlockData); i++) {
EXPECT_EQ(BlockData[i].expectedRecoveryFrame, RunBlockTest(BlockData[i].maxRecoveryFrame, BlockData[i].itemFlags));
}
@ -180,6 +182,7 @@ static void AssertPlayer(Player &player)
TEST(Player, CreatePlayer)
{
Players.resize(1);
CreatePlayer(Players[0], HeroClass::Rogue);
AssertPlayer(Players[0]);
}

5
test/timedemo_test.cpp

@ -35,6 +35,11 @@ void RunTimedemo(std::string timedemoFolderName)
const int demoNumber = 0;
Players.resize(1);
MyPlayerId = demoNumber;
MyPlayer = &Players[MyPlayerId];
*MyPlayer = {};
// Currently only spawn.mpq is present when building on github actions
gbIsSpawn = true;
gbIsHellfire = false;

1
test/writehero_test.cpp

@ -333,6 +333,7 @@ TEST(Writehero, pfile_write_hero)
leveltype = DTYPE_TOWN;
giNumberOfLevels = 17;
Players.resize(1);
MyPlayerId = 0;
MyPlayer = &Players[MyPlayerId];
*MyPlayer = {};

Loading…
Cancel
Save