Browse Source

inspect players command

pull/5974/head
qndel 3 years ago committed by Anders Jenbo
parent
commit
ce2ce86070
  1. 40
      Source/control.cpp
  2. 2
      Source/controls/touch/renderers.cpp
  3. 2
      Source/cursor.cpp
  4. 8
      Source/diablo.cpp
  5. 17
      Source/inv.cpp
  6. 5
      Source/multi.cpp
  7. 90
      Source/panels/charpanel.cpp
  8. 14
      Source/panels/spell_book.cpp
  9. 1
      Source/player.cpp
  10. 7
      Source/player.h

40
Source/control.cpp

@ -407,10 +407,45 @@ std::string TextCmdArenaPot(const string_view parameter)
return ret; return ret;
} }
std::string TextCmdInspect(const string_view parameter)
{
std::string ret;
if (!gbIsMultiplayer) {
StrAppend(ret, _("Inspecting only supported in multiplayer."));
return ret;
}
if (parameter.empty()) {
StrAppend(ret, _("Stopped inspecting players."));
InspectPlayer = MyPlayer;
return ret;
}
std::string param { parameter.data() };
std::transform(param.begin(), param.end(), param.begin(), [](unsigned char c) { return std::tolower(c); });
for (auto &player : Players) {
std::string playerName { player._pName };
std::transform(playerName.begin(), playerName.end(), playerName.begin(), [](unsigned char c) { return std::tolower(c); });
if (playerName.find(param) != std::string::npos) {
InspectPlayer = &player;
StrAppend(ret, _("Inspecting player: "));
StrAppend(ret, player._pName);
OpenCharPanel();
if (!sbookflag)
invflag = true;
RedrawEverything();
return ret;
}
}
StrAppend(ret, _("No players found with such a name"));
return ret;
}
std::vector<TextCmdItem> TextCmdList = { std::vector<TextCmdItem> TextCmdList = {
{ N_("/help"), N_("Prints help overview or help for a specific command."), N_("({command})"), &TextCmdHelp }, { N_("/help"), N_("Prints help overview or help for a specific command."), N_("({command})"), &TextCmdHelp },
{ N_("/arena"), N_("Enter a PvP Arena."), N_("{arena-number}"), &TextCmdArena }, { N_("/arena"), N_("Enter a PvP Arena."), N_("{arena-number}"), &TextCmdArena },
{ N_("/arenapot"), N_("Gives Arena Potions."), N_("{number}"), &TextCmdArenaPot }, { N_("/arenapot"), N_("Gives Arena Potions."), N_("{number}"), &TextCmdArenaPot },
{ N_("/inspect"), N_("Inspects stats and equipment of another player."), N_("{player name}"), &TextCmdInspect },
}; };
bool CheckTextCommand(const string_view text) bool CheckTextCommand(const string_view text)
@ -609,6 +644,11 @@ void OpenCharPanel()
void CloseCharPanel() void CloseCharPanel()
{ {
chrflag = false; chrflag = false;
if (IsInspectingPlayer()) {
InspectPlayer = MyPlayer;
RedrawEverything();
InitDiabloMsg(_("Stopped inspecting players."));
}
} }
void ToggleCharPanel() void ToggleCharPanel()

2
Source/controls/touch/renderers.cpp

@ -376,7 +376,7 @@ void PotionButtonRenderer::RenderPotion(RenderFunction renderFunction, const But
std::optional<VirtualGamepadPotionType> PotionButtonRenderer::GetPotionType() std::optional<VirtualGamepadPotionType> PotionButtonRenderer::GetPotionType()
{ {
for (const Item &item : MyPlayer->SpdList) { for (const Item &item : InspectPlayer->SpdList) {
if (item.isEmpty()) { if (item.isEmpty()) {
continue; continue;
} }

2
Source/cursor.cpp

@ -243,7 +243,7 @@ void FreeHalfSizeItemSprites()
void DrawItem(const Item &item, const Surface &out, Point position, ClxSprite clx) void DrawItem(const Item &item, const Surface &out, Point position, ClxSprite clx)
{ {
const bool usable = item._iStatFlag; const bool usable = !IsInspectingPlayer() ? item._iStatFlag : InspectPlayer->CanUseItem(item);
if (usable) { if (usable) {
ClxDraw(out, position, clx); ClxDraw(out, position, clx);
} else { } else {

8
Source/diablo.cpp

@ -2461,7 +2461,7 @@ bool TryIconCurs()
Player &myPlayer = *MyPlayer; Player &myPlayer = *MyPlayer;
if (pcurs == CURSOR_IDENTIFY) { if (pcurs == CURSOR_IDENTIFY) {
if (pcursinvitem != -1) if (pcursinvitem != -1 && !IsInspectingPlayer())
CheckIdentify(myPlayer, pcursinvitem); CheckIdentify(myPlayer, pcursinvitem);
else if (pcursstashitem != StashStruct::EmptyCell) { else if (pcursstashitem != StashStruct::EmptyCell) {
Item &item = Stash.stashList[pcursstashitem]; Item &item = Stash.stashList[pcursstashitem];
@ -2472,7 +2472,7 @@ bool TryIconCurs()
} }
if (pcurs == CURSOR_REPAIR) { if (pcurs == CURSOR_REPAIR) {
if (pcursinvitem != -1) if (pcursinvitem != -1 && !IsInspectingPlayer())
DoRepair(myPlayer, pcursinvitem); DoRepair(myPlayer, pcursinvitem);
else if (pcursstashitem != StashStruct::EmptyCell) { else if (pcursstashitem != StashStruct::EmptyCell) {
Item &item = Stash.stashList[pcursstashitem]; Item &item = Stash.stashList[pcursstashitem];
@ -2483,7 +2483,7 @@ bool TryIconCurs()
} }
if (pcurs == CURSOR_RECHARGE) { if (pcurs == CURSOR_RECHARGE) {
if (pcursinvitem != -1) if (pcursinvitem != -1 && !IsInspectingPlayer())
DoRecharge(myPlayer, pcursinvitem); DoRecharge(myPlayer, pcursinvitem);
else if (pcursstashitem != StashStruct::EmptyCell) { else if (pcursstashitem != StashStruct::EmptyCell) {
Item &item = Stash.stashList[pcursstashitem]; Item &item = Stash.stashList[pcursstashitem];
@ -2495,7 +2495,7 @@ bool TryIconCurs()
if (pcurs == CURSOR_OIL) { if (pcurs == CURSOR_OIL) {
bool changeCursor = true; bool changeCursor = true;
if (pcursinvitem != -1) if (pcursinvitem != -1 && !IsInspectingPlayer())
changeCursor = DoOil(myPlayer, pcursinvitem); changeCursor = DoOil(myPlayer, pcursinvitem);
else if (pcursstashitem != StashStruct::EmptyCell) { else if (pcursstashitem != StashStruct::EmptyCell) {
Item &item = Stash.stashList[pcursstashitem]; Item &item = Stash.stashList[pcursstashitem];

17
Source/inv.cpp

@ -1015,13 +1015,13 @@ void InvDrawSlotBack(const Surface &out, Point targetPosition, Size size, item_q
if (pix >= PAL16_GRAY) { if (pix >= PAL16_GRAY) {
switch (itemQuality) { switch (itemQuality) {
case ITEM_QUALITY_MAGIC: case ITEM_QUALITY_MAGIC:
pix -= PAL16_GRAY - PAL16_BLUE - 1; pix -= PAL16_GRAY - (!IsInspectingPlayer() ? PAL16_BLUE : PAL16_ORANGE) - 1;
break; break;
case ITEM_QUALITY_UNIQUE: case ITEM_QUALITY_UNIQUE:
pix -= PAL16_GRAY - PAL16_YELLOW - 1; pix -= PAL16_GRAY - (!IsInspectingPlayer() ? PAL16_YELLOW : PAL16_ORANGE) - 1;
break; break;
default: default:
pix -= PAL16_GRAY - PAL16_BEIGE - 1; pix -= PAL16_GRAY - (!IsInspectingPlayer() ? PAL16_BEIGE : PAL16_ORANGE) - 1;
break; break;
} }
} }
@ -1087,7 +1087,7 @@ void DrawInv(const Surface &out)
{ 133, 160 }, // chest { 133, 160 }, // chest
}; };
Player &myPlayer = *MyPlayer; Player &myPlayer = *InspectPlayer;
for (int slot = INVLOC_HEAD; slot < NUM_INVLOC; slot++) { for (int slot = INVLOC_HEAD; slot < NUM_INVLOC; slot++) {
if (!myPlayer.InvBody[slot].isEmpty()) { if (!myPlayer.InvBody[slot].isEmpty()) {
@ -1163,7 +1163,7 @@ void DrawInvBelt(const Surface &out)
DrawPanelBox(out, { 205, 21, 232, 28 }, mainPanelPosition + Displacement { 205, 5 }); DrawPanelBox(out, { 205, 21, 232, 28 }, mainPanelPosition + Displacement { 205, 5 });
Player &myPlayer = *MyPlayer; Player &myPlayer = *InspectPlayer;
for (int i = 0; i < MaxBeltItems; i++) { for (int i = 0; i < MaxBeltItems; i++) {
if (myPlayer.SpdList[i].isEmpty()) { if (myPlayer.SpdList[i].isEmpty()) {
@ -1522,6 +1522,8 @@ void TransferItemToStash(Player &player, int location)
void CheckInvItem(bool isShiftHeld, bool isCtrlHeld) void CheckInvItem(bool isShiftHeld, bool isCtrlHeld)
{ {
if (IsInspectingPlayer())
return;
if (!MyPlayer->HoldItem.isEmpty()) { if (!MyPlayer->HoldItem.isEmpty()) {
CheckInvPaste(*MyPlayer, MousePosition); CheckInvPaste(*MyPlayer, MousePosition);
} else if (IsStashOpen && isCtrlHeld) { } else if (IsStashOpen && isCtrlHeld) {
@ -1843,7 +1845,7 @@ int8_t CheckInvHLight()
int8_t rv = -1; int8_t rv = -1;
InfoColor = UiFlags::ColorWhite; InfoColor = UiFlags::ColorWhite;
Item *pi = nullptr; Item *pi = nullptr;
Player &myPlayer = *MyPlayer; Player &myPlayer = *InspectPlayer;
if (r == SLOTXY_HEAD) { if (r == SLOTXY_HEAD) {
rv = INVLOC_HEAD; rv = INVLOC_HEAD;
@ -1978,6 +1980,9 @@ Item &GetInventoryItem(Player &player, int location)
bool UseInvItem(int cii) bool UseInvItem(int cii)
{ {
if (IsInspectingPlayer())
return false;
Player &player = *MyPlayer; Player &player = *MyPlayer;
if (player._pInvincible && player._pHitPoints == 0 && &player == MyPlayer) if (player._pInvincible && player._pHitPoints == 0 && &player == MyPlayer)

5
Source/multi.cpp

@ -244,6 +244,9 @@ void PlayerLeftMsg(int pnum, bool left)
{ {
Player &player = Players[pnum]; Player &player = Players[pnum];
if (&player == InspectPlayer)
InspectPlayer = MyPlayer;
if (&player == MyPlayer) if (&player == MyPlayer)
return; return;
if (!player.plractive) if (!player.plractive)
@ -437,6 +440,7 @@ bool InitSingle(GameData *gameData)
MyPlayerId = 0; MyPlayerId = 0;
MyPlayer = &Players[MyPlayerId]; MyPlayer = &Players[MyPlayerId];
InspectPlayer = MyPlayer;
gbIsMultiplayer = false; gbIsMultiplayer = false;
pfile_read_player_from_save(gSaveNumber, *MyPlayer); pfile_read_player_from_save(gSaveNumber, *MyPlayer);
@ -467,6 +471,7 @@ bool InitMulti(GameData *gameData)
} }
MyPlayerId = playerId; MyPlayerId = playerId;
MyPlayer = &Players[MyPlayerId]; MyPlayer = &Players[MyPlayerId];
InspectPlayer = MyPlayer;
gbIsMultiplayer = true; gbIsMultiplayer = true;
pfile_read_player_from_save(gSaveNumber, *MyPlayer); pfile_read_player_from_save(gSaveNumber, *MyPlayer);

90
Source/panels/charpanel.cpp

@ -41,7 +41,7 @@ struct PanelEntry {
UiFlags GetBaseStatColor(CharacterAttribute attr) UiFlags GetBaseStatColor(CharacterAttribute attr)
{ {
UiFlags style = UiFlags::ColorWhite; UiFlags style = UiFlags::ColorWhite;
if (MyPlayer->GetBaseAttributeValue(attr) == MyPlayer->GetMaximumAttributeValue(attr)) if (InspectPlayer->GetBaseAttributeValue(attr) == InspectPlayer->GetMaximumAttributeValue(attr))
style = UiFlags::ColorWhitegold; style = UiFlags::ColorWhitegold;
return style; return style;
} }
@ -49,8 +49,8 @@ UiFlags GetBaseStatColor(CharacterAttribute attr)
UiFlags GetCurrentStatColor(CharacterAttribute attr) UiFlags GetCurrentStatColor(CharacterAttribute attr)
{ {
UiFlags style = UiFlags::ColorWhite; UiFlags style = UiFlags::ColorWhite;
int current = MyPlayer->GetCurrentAttributeValue(attr); int current = InspectPlayer->GetCurrentAttributeValue(attr);
int base = MyPlayer->GetBaseAttributeValue(attr); int base = InspectPlayer->GetBaseAttributeValue(attr);
if (current > base) if (current > base)
style = UiFlags::ColorBlue; style = UiFlags::ColorBlue;
if (current < base) if (current < base)
@ -70,24 +70,24 @@ UiFlags GetValueColor(int value, bool flip = false)
UiFlags GetMaxManaColor() UiFlags GetMaxManaColor()
{ {
return MyPlayer->_pMaxMana > MyPlayer->_pMaxManaBase ? UiFlags::ColorBlue : UiFlags::ColorWhite; return InspectPlayer->_pMaxMana > InspectPlayer->_pMaxManaBase ? UiFlags::ColorBlue : UiFlags::ColorWhite;
} }
UiFlags GetMaxHealthColor() UiFlags GetMaxHealthColor()
{ {
return MyPlayer->_pMaxHP > MyPlayer->_pMaxHPBase ? UiFlags::ColorBlue : UiFlags::ColorWhite; return InspectPlayer->_pMaxHP > InspectPlayer->_pMaxHPBase ? UiFlags::ColorBlue : UiFlags::ColorWhite;
} }
std::pair<int, int> GetDamage() std::pair<int, int> GetDamage()
{ {
int damageMod = MyPlayer->_pIBonusDamMod; int damageMod = InspectPlayer->_pIBonusDamMod;
if (MyPlayer->InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Bow && MyPlayer->_pClass != HeroClass::Rogue) { if (InspectPlayer->InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Bow && InspectPlayer->_pClass != HeroClass::Rogue) {
damageMod += MyPlayer->_pDamageMod / 2; damageMod += InspectPlayer->_pDamageMod / 2;
} else { } else {
damageMod += MyPlayer->_pDamageMod; damageMod += InspectPlayer->_pDamageMod;
} }
int mindam = MyPlayer->_pIMinDam + MyPlayer->_pIBonusDam * MyPlayer->_pIMinDam / 100 + damageMod; int mindam = InspectPlayer->_pIMinDam + InspectPlayer->_pIBonusDam * InspectPlayer->_pIMinDam / 100 + damageMod;
int maxdam = MyPlayer->_pIMaxDam + MyPlayer->_pIBonusDam * MyPlayer->_pIMaxDam / 100 + damageMod; int maxdam = InspectPlayer->_pIMaxDam + InspectPlayer->_pIBonusDam * InspectPlayer->_pIMaxDam / 100 + damageMod;
return { mindam, maxdam }; return { mindam, maxdam };
} }
@ -117,78 +117,78 @@ constexpr unsigned GoldHeaderEntryIndex = 16;
PanelEntry panelEntries[] = { PanelEntry panelEntries[] = {
{ "", { 9, 14 }, 150, 0, { "", { 9, 14 }, 150, 0,
[]() { return StyledText { UiFlags::ColorWhite, MyPlayer->_pName }; } }, []() { return StyledText { UiFlags::ColorWhite, InspectPlayer->_pName }; } },
{ "", { 161, 14 }, 149, 0, { "", { 161, 14 }, 149, 0,
[]() { return StyledText { UiFlags::ColorWhite, std::string(_(PlayersData[static_cast<std::size_t>(MyPlayer->_pClass)].className)) }; } }, []() { return StyledText { UiFlags::ColorWhite, std::string(_(PlayersData[static_cast<std::size_t>(InspectPlayer->_pClass)].className)) }; } },
{ N_("Level"), { 57, 52 }, 57, 45, { N_("Level"), { 57, 52 }, 57, 45,
[]() { return StyledText { UiFlags::ColorWhite, StrCat(MyPlayer->_pLevel) }; } }, []() { return StyledText { UiFlags::ColorWhite, StrCat(InspectPlayer->_pLevel) }; } },
{ N_("Experience"), { TopRightLabelX, 52 }, 99, 91, { N_("Experience"), { TopRightLabelX, 52 }, 99, 91,
[]() { []() {
int spacing = ((MyPlayer->_pExperience >= 1000000000) ? 0 : 1); int spacing = ((InspectPlayer->_pExperience >= 1000000000) ? 0 : 1);
return StyledText { UiFlags::ColorWhite, FormatInteger(MyPlayer->_pExperience), spacing }; return StyledText { UiFlags::ColorWhite, FormatInteger(InspectPlayer->_pExperience), spacing };
} }, } },
{ N_("Next level"), { TopRightLabelX, 80 }, 99, 198, { N_("Next level"), { TopRightLabelX, 80 }, 99, 198,
[]() { []() {
if (MyPlayer->_pLevel == MaxCharacterLevel) { if (InspectPlayer->_pLevel == MaxCharacterLevel) {
return StyledText { UiFlags::ColorWhitegold, std::string(_("None")) }; return StyledText { UiFlags::ColorWhitegold, std::string(_("None")) };
} }
int spacing = ((MyPlayer->_pNextExper >= 1000000000) ? 0 : 1); int spacing = ((InspectPlayer->_pNextExper >= 1000000000) ? 0 : 1);
return StyledText { UiFlags::ColorWhite, FormatInteger(MyPlayer->_pNextExper), spacing }; return StyledText { UiFlags::ColorWhite, FormatInteger(InspectPlayer->_pNextExper), spacing };
} }, } },
{ N_("Base"), { LeftColumnLabelX, /* set dynamically */ 0 }, 0, 44, {} }, { N_("Base"), { LeftColumnLabelX, /* set dynamically */ 0 }, 0, 44, {} },
{ N_("Now"), { 135, /* set dynamically */ 0 }, 0, 44, {} }, { N_("Now"), { 135, /* set dynamically */ 0 }, 0, 44, {} },
{ N_("Strength"), { LeftColumnLabelX, 135 }, 45, LeftColumnLabelWidth, { N_("Strength"), { LeftColumnLabelX, 135 }, 45, LeftColumnLabelWidth,
[]() { return StyledText { GetBaseStatColor(CharacterAttribute::Strength), StrCat(MyPlayer->_pBaseStr) }; } }, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Strength), StrCat(InspectPlayer->_pBaseStr) }; } },
{ "", { 135, 135 }, 45, 0, { "", { 135, 135 }, 45, 0,
[]() { return StyledText { GetCurrentStatColor(CharacterAttribute::Strength), StrCat(MyPlayer->_pStrength) }; } }, []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Strength), StrCat(InspectPlayer->_pStrength) }; } },
{ N_("Magic"), { LeftColumnLabelX, 163 }, 45, LeftColumnLabelWidth, { N_("Magic"), { LeftColumnLabelX, 163 }, 45, LeftColumnLabelWidth,
[]() { return StyledText { GetBaseStatColor(CharacterAttribute::Magic), StrCat(MyPlayer->_pBaseMag) }; } }, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Magic), StrCat(InspectPlayer->_pBaseMag) }; } },
{ "", { 135, 163 }, 45, 0, { "", { 135, 163 }, 45, 0,
[]() { return StyledText { GetCurrentStatColor(CharacterAttribute::Magic), StrCat(MyPlayer->_pMagic) }; } }, []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Magic), StrCat(InspectPlayer->_pMagic) }; } },
{ N_("Dexterity"), { LeftColumnLabelX, 191 }, 45, LeftColumnLabelWidth, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Dexterity), StrCat(MyPlayer->_pBaseDex) }; } }, { N_("Dexterity"), { LeftColumnLabelX, 191 }, 45, LeftColumnLabelWidth, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Dexterity), StrCat(InspectPlayer->_pBaseDex) }; } },
{ "", { 135, 191 }, 45, 0, { "", { 135, 191 }, 45, 0,
[]() { return StyledText { GetCurrentStatColor(CharacterAttribute::Dexterity), StrCat(MyPlayer->_pDexterity) }; } }, []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Dexterity), StrCat(InspectPlayer->_pDexterity) }; } },
{ N_("Vitality"), { LeftColumnLabelX, 219 }, 45, LeftColumnLabelWidth, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Vitality), StrCat(MyPlayer->_pBaseVit) }; } }, { N_("Vitality"), { LeftColumnLabelX, 219 }, 45, LeftColumnLabelWidth, []() { return StyledText { GetBaseStatColor(CharacterAttribute::Vitality), StrCat(InspectPlayer->_pBaseVit) }; } },
{ "", { 135, 219 }, 45, 0, { "", { 135, 219 }, 45, 0,
[]() { return StyledText { GetCurrentStatColor(CharacterAttribute::Vitality), StrCat(MyPlayer->_pVitality) }; } }, []() { return StyledText { GetCurrentStatColor(CharacterAttribute::Vitality), StrCat(InspectPlayer->_pVitality) }; } },
{ N_("Points to distribute"), { LeftColumnLabelX, 248 }, 45, LeftColumnLabelWidth, { N_("Points to distribute"), { LeftColumnLabelX, 248 }, 45, LeftColumnLabelWidth,
[]() { []() {
MyPlayer->_pStatPts = std::min(CalcStatDiff(*MyPlayer), MyPlayer->_pStatPts); InspectPlayer->_pStatPts = std::min(CalcStatDiff(*InspectPlayer), InspectPlayer->_pStatPts);
return StyledText { UiFlags::ColorRed, (MyPlayer->_pStatPts > 0 ? StrCat(MyPlayer->_pStatPts) : "") }; return StyledText { UiFlags::ColorRed, (InspectPlayer->_pStatPts > 0 ? StrCat(InspectPlayer->_pStatPts) : "") };
} }, } },
{ N_("Gold"), { TopRightLabelX, /* set dynamically */ 0 }, 0, 98, {} }, { N_("Gold"), { TopRightLabelX, /* set dynamically */ 0 }, 0, 98, {} },
{ "", { TopRightLabelX, 127 }, 99, 0, { "", { TopRightLabelX, 127 }, 99, 0,
[]() { return StyledText { UiFlags::ColorWhite, FormatInteger(MyPlayer->_pGold) }; } }, []() { return StyledText { UiFlags::ColorWhite, FormatInteger(InspectPlayer->_pGold) }; } },
{ N_("Armor class"), { RightColumnLabelX, 163 }, 57, RightColumnLabelWidth, { N_("Armor class"), { RightColumnLabelX, 163 }, 57, RightColumnLabelWidth,
[]() { return StyledText { GetValueColor(MyPlayer->_pIBonusAC), StrCat(MyPlayer->GetArmor() + MyPlayer->_pLevel * 2) }; } }, []() { return StyledText { GetValueColor(InspectPlayer->_pIBonusAC), StrCat(InspectPlayer->GetArmor() + InspectPlayer->_pLevel * 2) }; } },
{ N_("To hit"), { RightColumnLabelX, 191 }, 57, RightColumnLabelWidth, { N_("To hit"), { RightColumnLabelX, 191 }, 57, RightColumnLabelWidth,
[]() { return StyledText { GetValueColor(MyPlayer->_pIBonusToHit), StrCat(MyPlayer->InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Bow ? MyPlayer->GetRangedToHit() : MyPlayer->GetMeleeToHit(), "%") }; } }, []() { return StyledText { GetValueColor(InspectPlayer->_pIBonusToHit), StrCat(InspectPlayer->InvBody[INVLOC_HAND_LEFT]._itype == ItemType::Bow ? InspectPlayer->GetRangedToHit() : InspectPlayer->GetMeleeToHit(), "%") }; } },
{ N_("Damage"), { RightColumnLabelX, 219 }, 57, RightColumnLabelWidth, { N_("Damage"), { RightColumnLabelX, 219 }, 57, RightColumnLabelWidth,
[]() { []() {
std::pair<int, int> dmg = GetDamage(); std::pair<int, int> dmg = GetDamage();
int spacing = ((dmg.first >= 100) ? -1 : 1); int spacing = ((dmg.first >= 100) ? -1 : 1);
return StyledText { GetValueColor(MyPlayer->_pIBonusDam), StrCat(dmg.first, "-", dmg.second), spacing }; return StyledText { GetValueColor(InspectPlayer->_pIBonusDam), StrCat(dmg.first, "-", dmg.second), spacing };
} }, } },
{ N_("Life"), { LeftColumnLabelX, 284 }, 45, LeftColumnLabelWidth, { N_("Life"), { LeftColumnLabelX, 284 }, 45, LeftColumnLabelWidth,
[]() { return StyledText { GetMaxHealthColor(), StrCat(MyPlayer->_pMaxHP >> 6) }; } }, []() { return StyledText { GetMaxHealthColor(), StrCat(InspectPlayer->_pMaxHP >> 6) }; } },
{ "", { 135, 284 }, 45, 0, { "", { 135, 284 }, 45, 0,
[]() { return StyledText { (MyPlayer->_pHitPoints != MyPlayer->_pMaxHP ? UiFlags::ColorRed : GetMaxHealthColor()), StrCat(MyPlayer->_pHitPoints >> 6) }; } }, []() { return StyledText { (InspectPlayer->_pHitPoints != InspectPlayer->_pMaxHP ? UiFlags::ColorRed : GetMaxHealthColor()), StrCat(InspectPlayer->_pHitPoints >> 6) }; } },
{ N_("Mana"), { LeftColumnLabelX, 312 }, 45, LeftColumnLabelWidth, { N_("Mana"), { LeftColumnLabelX, 312 }, 45, LeftColumnLabelWidth,
[]() { return StyledText { GetMaxManaColor(), StrCat(MyPlayer->_pMaxMana >> 6) }; } }, []() { return StyledText { GetMaxManaColor(), StrCat(InspectPlayer->_pMaxMana >> 6) }; } },
{ "", { 135, 312 }, 45, 0, { "", { 135, 312 }, 45, 0,
[]() { return StyledText { (MyPlayer->_pMana != MyPlayer->_pMaxMana ? UiFlags::ColorRed : GetMaxManaColor()), StrCat(MyPlayer->_pMana >> 6) }; } }, []() { return StyledText { (InspectPlayer->_pMana != InspectPlayer->_pMaxMana ? UiFlags::ColorRed : GetMaxManaColor()), StrCat(InspectPlayer->_pMana >> 6) }; } },
{ N_("Resist magic"), { RightColumnLabelX, 256 }, 57, RightColumnLabelWidth, { N_("Resist magic"), { RightColumnLabelX, 256 }, 57, RightColumnLabelWidth,
[]() { return GetResistInfo(MyPlayer->_pMagResist); } }, []() { return GetResistInfo(InspectPlayer->_pMagResist); } },
{ N_("Resist fire"), { RightColumnLabelX, 284 }, 57, RightColumnLabelWidth, { N_("Resist fire"), { RightColumnLabelX, 284 }, 57, RightColumnLabelWidth,
[]() { return GetResistInfo(MyPlayer->_pFireResist); } }, []() { return GetResistInfo(InspectPlayer->_pFireResist); } },
{ N_("Resist lightning"), { RightColumnLabelX, 313 }, 57, RightColumnLabelWidth, { N_("Resist lightning"), { RightColumnLabelX, 313 }, 57, RightColumnLabelWidth,
[]() { return GetResistInfo(MyPlayer->_pLghtResist); } }, []() { return GetResistInfo(InspectPlayer->_pLghtResist); } },
}; };
OptionalOwnedClxSpriteList Panel; OptionalOwnedClxSpriteList Panel;
@ -241,14 +241,14 @@ void DrawShadowString(const Surface &out, const PanelEntry &entry)
void DrawStatButtons(const Surface &out) void DrawStatButtons(const Surface &out)
{ {
if (MyPlayer->_pStatPts > 0) { if (InspectPlayer->_pStatPts > 0 && !IsInspectingPlayer()) {
if (MyPlayer->_pBaseStr < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Strength)) if (InspectPlayer->_pBaseStr < InspectPlayer->GetMaximumAttributeValue(CharacterAttribute::Strength))
ClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 157 }), (*pChrButtons)[chrbtn[static_cast<size_t>(CharacterAttribute::Strength)] ? 2 : 1]); ClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 157 }), (*pChrButtons)[chrbtn[static_cast<size_t>(CharacterAttribute::Strength)] ? 2 : 1]);
if (MyPlayer->_pBaseMag < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Magic)) if (InspectPlayer->_pBaseMag < InspectPlayer->GetMaximumAttributeValue(CharacterAttribute::Magic))
ClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 185 }), (*pChrButtons)[chrbtn[static_cast<size_t>(CharacterAttribute::Magic)] ? 4 : 3]); ClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 185 }), (*pChrButtons)[chrbtn[static_cast<size_t>(CharacterAttribute::Magic)] ? 4 : 3]);
if (MyPlayer->_pBaseDex < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Dexterity)) if (InspectPlayer->_pBaseDex < InspectPlayer->GetMaximumAttributeValue(CharacterAttribute::Dexterity))
ClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 214 }), (*pChrButtons)[chrbtn[static_cast<size_t>(CharacterAttribute::Dexterity)] ? 6 : 5]); ClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 214 }), (*pChrButtons)[chrbtn[static_cast<size_t>(CharacterAttribute::Dexterity)] ? 6 : 5]);
if (MyPlayer->_pBaseVit < MyPlayer->GetMaximumAttributeValue(CharacterAttribute::Vitality)) if (InspectPlayer->_pBaseVit < InspectPlayer->GetMaximumAttributeValue(CharacterAttribute::Vitality))
ClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 242 }), (*pChrButtons)[chrbtn[static_cast<size_t>(CharacterAttribute::Vitality)] ? 8 : 7]); ClxDraw(out, GetPanelPosition(UiPanels::Character, { 137, 242 }), (*pChrButtons)[chrbtn[static_cast<size_t>(CharacterAttribute::Vitality)] ? 8 : 7]);
} }
} }

14
Source/panels/spell_book.cpp

@ -43,7 +43,7 @@ SpellID GetSpellFromSpellPage(size_t page, size_t entry)
{ {
assert(page <= SpellBookPages && entry <= SpellBookPageEntries); assert(page <= SpellBookPages && entry <= SpellBookPageEntries);
if (page == 0 && entry == 0) { if (page == 0 && entry == 0) {
switch (MyPlayer->_pClass) { switch (InspectPlayer->_pClass) {
case HeroClass::Warrior: case HeroClass::Warrior:
return SpellID::ItemRepair; return SpellID::ItemRepair;
case HeroClass::Rogue: case HeroClass::Rogue:
@ -75,7 +75,7 @@ void PrintSBookStr(const Surface &out, Point position, string_view text, UiFlags
SpellType GetSBookTrans(SpellID ii, bool townok) SpellType GetSBookTrans(SpellID ii, bool townok)
{ {
Player &player = *MyPlayer; Player &player = *InspectPlayer;
if ((player._pClass == HeroClass::Monk) && (ii == SpellID::Search)) if ((player._pClass == HeroClass::Monk) && (ii == SpellID::Search))
return SpellType::Skill; return SpellType::Skill;
SpellType st = SpellType::Spell; SpellType st = SpellType::Spell;
@ -86,7 +86,7 @@ SpellType GetSBookTrans(SpellID ii, bool townok)
st = SpellType::Skill; st = SpellType::Skill;
} }
if (st == SpellType::Spell) { if (st == SpellType::Spell) {
if (CheckSpell(*MyPlayer, ii, st, true) != SpellCheckResult::Success) { if (CheckSpell(*InspectPlayer, ii, st, true) != SpellCheckResult::Success) {
st = SpellType::Invalid; st = SpellType::Invalid;
} }
if (player.GetSpellLevel(ii) == 0) { if (player.GetSpellLevel(ii) == 0) {
@ -129,7 +129,7 @@ void DrawSpellBook(const Surface &out)
} }
ClxDraw(out, GetPanelPosition(UiPanels::Spell, { sx, 348 }), (*pSBkBtnCel)[sbooktab]); ClxDraw(out, GetPanelPosition(UiPanels::Spell, { sx, 348 }), (*pSBkBtnCel)[sbooktab]);
} }
Player &player = *MyPlayer; Player &player = *InspectPlayer;
uint64_t spl = player._pMemSpells | player._pISpells | player._pAblSpells; uint64_t spl = player._pMemSpells | player._pISpells | player._pAblSpells;
const int lineHeight = 18; const int lineHeight = 18;
@ -143,7 +143,7 @@ void DrawSpellBook(const Surface &out)
SetSpellTrans(st); SetSpellTrans(st);
const Point spellCellPosition = GetPanelPosition(UiPanels::Spell, { 11, yp + SpellBookDescription.height }); const Point spellCellPosition = GetPanelPosition(UiPanels::Spell, { 11, yp + SpellBookDescription.height });
DrawSmallSpellIcon(out, spellCellPosition, sn); DrawSmallSpellIcon(out, spellCellPosition, sn);
if (sn == player._pRSpell && st == player._pRSplType) { if (sn == player._pRSpell && st == player._pRSplType && !IsInspectingPlayer()) {
SetSpellTrans(SpellType::Skill); SetSpellTrans(SpellType::Skill);
DrawSmallSpellIconBorder(out, spellCellPosition); DrawSmallSpellIconBorder(out, spellCellPosition);
} }
@ -196,9 +196,9 @@ void CheckSBook()
// enough to the height of the space given to spell descriptions that we can reuse that value and subtract the // enough to the height of the space given to spell descriptions that we can reuse that value and subtract the
// padding from the end of the area. // padding from the end of the area.
Rectangle iconArea = { GetPanelPosition(UiPanels::Spell, { 11, 18 }), Size { 37, SpellBookDescription.height * 7 - 5 } }; Rectangle iconArea = { GetPanelPosition(UiPanels::Spell, { 11, 18 }), Size { 37, SpellBookDescription.height * 7 - 5 } };
if (iconArea.contains(MousePosition)) { if (iconArea.contains(MousePosition) && !IsInspectingPlayer()) {
SpellID sn = GetSpellFromSpellPage(sbooktab, (MousePosition.y - iconArea.position.y) / SpellBookDescription.height); SpellID sn = GetSpellFromSpellPage(sbooktab, (MousePosition.y - iconArea.position.y) / SpellBookDescription.height);
Player &player = *MyPlayer; Player &player = *InspectPlayer;
uint64_t spl = player._pMemSpells | player._pISpells | player._pAblSpells; uint64_t spl = player._pMemSpells | player._pISpells | player._pAblSpells;
if (IsValidSpell(sn) && (spl & GetSpellBitmask(sn)) != 0) { if (IsValidSpell(sn) && (spl & GetSpellBitmask(sn)) != 0) {
SpellType st = SpellType::Spell; SpellType st = SpellType::Spell;

1
Source/player.cpp

@ -52,6 +52,7 @@ namespace devilution {
size_t MyPlayerId; size_t MyPlayerId;
Player *MyPlayer; Player *MyPlayer;
std::vector<Player> Players; std::vector<Player> Players;
Player *InspectPlayer;
bool MyPlayerIsDead; bool MyPlayerIsDead;
/** Specifies the X-coordinate delta from the player start location in Tristram. */ /** Specifies the X-coordinate delta from the player start location in Tristram. */

7
Source/player.h

@ -762,6 +762,13 @@ struct Player {
extern DVL_API_FOR_TEST size_t MyPlayerId; extern DVL_API_FOR_TEST size_t MyPlayerId;
extern DVL_API_FOR_TEST Player *MyPlayer; extern DVL_API_FOR_TEST Player *MyPlayer;
extern DVL_API_FOR_TEST std::vector<Player> Players; extern DVL_API_FOR_TEST std::vector<Player> Players;
/** @brief What Player items and stats should be displayed? Normally this is identical to MyPlayer but can differ when /inspect was used. */
extern Player *InspectPlayer;
/** @brief Do we currently inspect a remote player (/inspect was used)? In this case the (remote) players items and stats can't be modified. */
inline bool IsInspectingPlayer()
{
return MyPlayer != InspectPlayer;
}
extern bool MyPlayerIsDead; extern bool MyPlayerIsDead;
Player *PlayerAtPosition(Point position); Player *PlayerAtPosition(Point position);

Loading…
Cancel
Save