Browse Source

Manage friendly mode per player and sync state between clients

pull/4570/merge
obligaron 4 years ago committed by Anders Jenbo
parent
commit
2b0b944afb
  1. 9
      Source/control.cpp
  2. 4
      Source/controls/plrctrls.cpp
  3. 6
      Source/diablo.cpp
  4. 1
      Source/diablo.h
  5. 8
      Source/missiles.cpp
  6. 9
      Source/msg.cpp
  7. 4
      Source/msg.h
  8. 6
      Source/multi.cpp
  9. 4
      Source/pack.h
  10. 4
      Source/player.cpp
  11. 2
      Source/player.h
  12. 4
      Source/track.cpp

9
Source/control.cpp

@ -611,7 +611,8 @@ void DrawCtrlBtns(const Surface &out)
}
if (PanelButtonIndex == 8) {
CelDrawTo(out, { 87 + PANEL_X, 122 + PANEL_Y }, *multiButtons, PanelButtons[6] ? 1 : 0);
if (gbFriendlyMode)
auto &myPlayer = Players[MyPlayerId];
if (myPlayer.friendlyMode)
CelDrawTo(out, { 527 + PANEL_X, 122 + PANEL_Y }, *multiButtons, PanelButtons[7] ? 3 : 2);
else
CelDrawTo(out, { 527 + PANEL_X, 122 + PANEL_Y }, *multiButtons, PanelButtons[7] ? 5 : 4);
@ -699,7 +700,8 @@ void CheckPanelInfo()
if (i != 7) {
InfoString = _(PanBtnStr[i]);
} else {
if (gbFriendlyMode)
auto &myPlayer = Players[MyPlayerId];
if (myPlayer.friendlyMode)
InfoString = _("Player friendly");
else
InfoString = _("Player attack");
@ -824,7 +826,8 @@ void CheckBtnUp()
control_type_message();
break;
case PanelButtonFriendly:
gbFriendlyMode = !gbFriendlyMode;
// Toggle friendly Mode
NetSendCmd(true, CMD_FRIENDLYMODE);
break;
}
}

4
Source/controls/plrctrls.cpp

@ -365,7 +365,7 @@ void CheckPlayerNearby()
auto &myPlayer = Players[MyPlayerId];
int spl = myPlayer._pRSpell;
if (gbFriendlyMode && spl != SPL_RESURRECT && spl != SPL_HEALOTHER)
if (myPlayer.friendlyMode && spl != SPL_RESURRECT && spl != SPL_HEALOTHER)
return;
for (int i = 0; i < MAX_PLRS; i++) {
@ -512,7 +512,7 @@ void Interact()
return;
}
if (leveltype != DTYPE_TOWN && pcursplr != -1 && !gbFriendlyMode) {
if (leveltype != DTYPE_TOWN && pcursplr != -1 && !Players[MyPlayerId].friendlyMode) {
NetSendCmdParam1(true, Players[MyPlayerId].UsesRangedWeapon() ? CMD_RATTACKPID : CMD_ATTACKPID, pcursplr);
LastMouseButtonAction = MouseActionType::AttackPlayerTarget;
return;

6
Source/diablo.cpp

@ -113,8 +113,6 @@ char gszProductName[64] = "DevilutionX vUnknown";
bool DebugDisableNetworkTimeout = false;
std::vector<std::string> DebugCmdsFromCommandLine;
#endif
/** Specifies whether players are in non-PvP mode. */
bool gbFriendlyMode = true;
GameLogicStep gGameLogicStep = GameLogicStep::None;
QuickMessage QuickMessages[QUICK_MESSAGE_OPTIONS] = {
{ "QuickMessage1", N_("I need help! Come Here!") },
@ -254,7 +252,7 @@ void LeftMouseCmd(bool bShift)
LastMouseButtonAction = MouseActionType::AttackMonsterTarget;
NetSendCmdParam1(true, CMD_RATTACKID, pcursmonst);
}
} else if (pcursplr != -1 && !gbFriendlyMode) {
} else if (pcursplr != -1 && !myPlayer.friendlyMode) {
LastMouseButtonAction = MouseActionType::AttackPlayerTarget;
NetSendCmdParam1(true, CMD_RATTACKPID, pcursplr);
}
@ -274,7 +272,7 @@ void LeftMouseCmd(bool bShift)
} else if (pcursmonst != -1) {
LastMouseButtonAction = MouseActionType::AttackMonsterTarget;
NetSendCmdParam1(true, CMD_ATTACKID, pcursmonst);
} else if (pcursplr != -1 && !gbFriendlyMode) {
} else if (pcursplr != -1 && !myPlayer.friendlyMode) {
LastMouseButtonAction = MouseActionType::AttackPlayerTarget;
NetSendCmdParam1(true, CMD_ATTACKPID, pcursplr);
}

1
Source/diablo.h

@ -118,7 +118,6 @@ struct QuickMessage {
constexpr size_t QUICK_MESSAGE_OPTIONS = 4;
extern QuickMessage QuickMessages[QUICK_MESSAGE_OPTIONS];
extern bool gbFriendlyMode;
/**
* @brief Specifices what game logic step is currently executed
*/

8
Source/missiles.cpp

@ -309,14 +309,14 @@ bool MonsterMHit(int pnum, int m, int mindam, int maxdam, int dist, missile_id t
bool Plr2PlrMHit(int pnum, int p, int mindam, int maxdam, int dist, missile_id mtype, bool shift, bool *blocked)
{
if (sgGameInitInfo.bFriendlyFire == 0 && gbFriendlyMode)
auto &player = Players[pnum];
auto &target = Players[p];
if (sgGameInitInfo.bFriendlyFire == 0 && player.friendlyMode)
return false;
*blocked = false;
auto &player = Players[pnum];
auto &target = Players[p];
if (target._pInvincible) {
return false;
}

9
Source/msg.cpp

@ -1882,6 +1882,13 @@ DWORD OnString(const TCmd *pCmd, Player &player)
return len + 2; // length of string + nul terminator + sizeof(p->bCmd)
}
DWORD OnFriendlyMode(const TCmd *pCmd, Player &player) // NOLINT(misc-unused-parameters)
{
player.friendlyMode = !player.friendlyMode;
force_redraw = 255;
return sizeof(*pCmd);
}
DWORD OnSyncQuest(const TCmd *pCmd, int pnum)
{
const auto &message = *reinterpret_cast<const TCmdQuest *>(pCmd);
@ -2921,6 +2928,8 @@ uint32_t ParseCmd(int pnum, const TCmd *pCmd)
return OnSetVitality(pCmd, pnum);
case CMD_STRING:
return OnString(pCmd, player);
case CMD_FRIENDLYMODE:
return OnFriendlyMode(pCmd, player);
case CMD_SYNCQUEST:
return OnSyncQuest(pCmd, pnum);
case CMD_CHEAT_EXPERIENCE:

4
Source/msg.h

@ -372,6 +372,10 @@ enum _cmd_id : uint8_t {
//
// body (TCmdString)
CMD_STRING,
// Toggles friendly Mode
//
// body (TCmd)
CMD_FRIENDLYMODE,
// Set player strength.
//
// body (TCmdParam1):

6
Source/multi.cpp

@ -335,7 +335,10 @@ void SendPlayerInfo(int pnum, _cmd_id cmd)
static_assert(alignof(PlayerPack) == 1, "Fix pkplr alignment");
std::unique_ptr<byte[]> pkplr { new byte[sizeof(PlayerPack)] };
PackPlayer(reinterpret_cast<PlayerPack *>(pkplr.get()), Players[MyPlayerId], true, true);
PlayerPack *pPack = reinterpret_cast<PlayerPack *>(pkplr.get());
auto &myPlayer = Players[MyPlayerId];
PackPlayer(pPack, myPlayer, true, true);
pPack->friendlyMode = myPlayer.friendlyMode ? 1 : 0;
dthread_send_delta(pnum, cmd, std::move(pkplr), sizeof(PlayerPack));
}
@ -831,6 +834,7 @@ void recv_plrinfo(int pnum, const TCmdPlrInfoHdr &header, bool recv)
if (!UnPackPlayer(&packedPlayer, player, true)) {
return;
}
player.friendlyMode = packedPlayer.friendlyMode != 0;
if (!recv) {
return;

4
Source/pack.h

@ -75,7 +75,9 @@ struct PlayerPack {
uint32_t pDiabloKillLevel;
uint32_t pDifficulty;
ItemSpecialEffectHf pDamAcFlags;
int32_t dwReserved[5]; // For future use
/**@brief Only used in multiplayer sync (SendPlayerInfo/recv_plrinfo). Never used in save games (single- or multiplayer). */
uint8_t friendlyMode;
uint8_t dwReserved[19]; // For future use
};
#pragma pack(pop)

4
Source/player.cpp

@ -1148,7 +1148,7 @@ bool DoAttack(int pnum)
m = -(dMonster[dx][dy] + 1);
}
didhit = PlrHitMonst(pnum, m);
} else if (dPlayer[dx][dy] != 0 && !gbFriendlyMode) {
} else if (dPlayer[dx][dy] != 0 && !player.friendlyMode) {
BYTE p = dPlayer[dx][dy];
if (dPlayer[dx][dy] > 0) {
p = dPlayer[dx][dy] - 1;
@ -3627,7 +3627,7 @@ void CheckPlrSpell(bool isShiftHeld, spell_id spellID, spell_type spellType)
LastMouseButtonAction = MouseActionType::SpellMonsterTarget;
sl = GetSpellLevel(MyPlayerId, spellID);
NetSendCmdParam4(true, CMD_SPELLID, pcursmonst, spellID, spellType, sl);
} else if (pcursplr != -1 && !isShiftHeld && !gbFriendlyMode) {
} else if (pcursplr != -1 && !isShiftHeld && !myPlayer.friendlyMode) {
LastMouseButtonAction = MouseActionType::SpellPlayerTarget;
sl = GetSpellLevel(MyPlayerId, spellID);
NetSendCmdParam4(true, CMD_SPELLPID, pcursplr, spellID, spellType, sl);

2
Source/player.h

@ -347,6 +347,8 @@ struct Player {
uint8_t pDiabloKillLevel;
_difficulty pDifficulty;
ItemSpecialEffectHf pDamAcFlags;
/** @brief Specifies whether players are in non-PvP mode. */
bool friendlyMode = true;
void CalcScrolls();

4
Source/track.cpp

@ -93,7 +93,7 @@ void RepeatMouseAction()
NetSendCmdParam1(true, rangedAttack ? CMD_RATTACKID : CMD_ATTACKID, pcursmonst);
break;
case MouseActionType::AttackPlayerTarget:
if (pcursplr != -1 && !gbFriendlyMode)
if (pcursplr != -1 && !myPlayer.friendlyMode)
NetSendCmdParam1(true, rangedAttack ? CMD_RATTACKPID : CMD_ATTACKPID, pcursplr);
break;
case MouseActionType::Spell:
@ -107,7 +107,7 @@ void RepeatMouseAction()
CheckPlrSpell(false);
break;
case MouseActionType::SpellPlayerTarget:
if (pcursplr != -1 && !gbFriendlyMode)
if (pcursplr != -1 && !myPlayer.friendlyMode)
CheckPlrSpell(false);
break;
case MouseActionType::OperateObject:

Loading…
Cancel
Save