Skip to content

Commit

Permalink
Merge pull request #20 from dschu012/feature/drop-notification
Browse files Browse the repository at this point in the history
Use item name/color from BH.cfg when showing the drop notification
  • Loading branch information
planqi authored May 15, 2019
2 parents 3ec8fbe + f2deb2f commit 08dc318
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 19 deletions.
2 changes: 1 addition & 1 deletion BH/BH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void BH::Initialize()
SetWindowLong(D2GFX_GetHwnd(), GWL_WNDPROC, (LONG)GameWindowEvent);
});

settingsUI = new Drawing::UI(BH_VERSION, 400, 247);
settingsUI = new Drawing::UI(BH_VERSION, 400, 262);

Task::InitializeThreadPool(2);

Expand Down
60 changes: 60 additions & 0 deletions BH/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -1080,6 +1080,66 @@ enum QuestFlags {

#define ITEM_GROUP_GEM (ITEM_GROUP_AMETHYST|ITEM_GROUP_DIAMOND|ITEM_GROUP_EMERALD|ITEM_GROUP_RUBY|ITEM_GROUP_SAPPHIRE|ITEM_GROUP_TOPAZ|ITEM_GROUP_SKULL)

//https://d2mods.info/forum/viewtopic.php?p=487011#p487011
//UnitAny 0xC4
enum UNITFLAG
{
UNITFLAG_MODE = 0x00000001, // Sends mode updates via D2GAME.6FC4C520.
UNITFLAG_SELECTABLE = 0x00000002, // Unit is selectable.
UNITFLAG_ATTACKABLE = 0x00000004, // Unit is attackable.
UNITFLAG_SEARCHABLE = 0x00000008, // Unit can be seen by target searching functions (aura, curse).
UNITFLAG_NEW = 0x00000010, // Sends entire unit to the client.
UNITFLAG_NO_SHADOW = 0x00000020, // Unit doesn't have a shadow.
UNITFLAG_FINISHED = 0x00000040, // Unit has executed the current skill's 'do' function.
UNITFLAG_PREOPERATED = 0x00000080, // Tells the game that this object has been pre-operated (that is, it should not change its mode again during initialization).
UNITFLAG_CHATMESSAGE = 0x00000100, // Sends pUnit->pChatMessage (overlay text).
UNITFLAG_HIRELING = 0x00000200, // Unit is a hireling.
UNITFLAG_SOUND = 0x00000400, // Sends pUnit->eSoundMessage.
UNITFLAG_UMOD = 0x00000800, // Sends the monster's UMods to the client if MONSTERUPDATE_UMOD is set in pMonsterData->dwUpdateMask.
UNITFLAG_FLIPPY = 0x00001000, // When adding an item to a room this tells the game to send ITEMMODE_DROP instead of ITEMMODE_ROOM.
UNITFLAG_UPDATE = 0x00002000, // Set for units that're inside the pRoom->pUnitUpdateList update queue (which is the core controller for updates).
UNITFLAG_SEQUENCE_TRANSITION = 0x00004000, // Set when a animation sequence transitions from one mode to the next.
UNITFLAG_SOFTHIT = 0x00008000, // Sends the unit's current HP percent and hitclass (pUnit->dwHitClass) to the client.
UNITFLAG_DEAD = 0x00010000, // The unit is to be considered dead even if its mode is not DD or DT.
UNITFLAG_NO_TREASURE = 0x00020000, // This unit never drops items, even if it has a treasure class.
UNITFLAG_MONSTERMODE = 0x00080000, // Set when SMONSTER_SetMode successfully changes the monster's mode.
UNITFLAG_PREDRAW = 0x00100000, // Draw this unit as if it were a ground tile.
UNITFLAG_ASYNC = 0x00200000, // This unit exists only on the client (critters).
UNITFLAG_CLIENT = 0x00400000, // This is set for all units created on the client.
UNITFLAG_DELETE = 0x00800000, // When this is set CUNIT_DoFrame will not process this unit and delete it if it is an async unit.
UNITFLAG_PRESET = 0x01000000, // Set for units that're created through GAME_SpawnPresets. Some other places also set this, usually related to quest units.
UNITFLAG_RESTORE = 0x02000000, // Unit will always be saved by SUNIT_Deactivate even if it is a corpse or opened object.
UNITFLAG_NO_EXPERIENCE = 0x04000000, // This unit doesn't give experience when slain.
UNITFLAG_SEEN = 0x10000000, // This unit was drawn.
UNITFLAG_REVEALED = 0x20000000, // This unit was added to the automap (shrines).
UNITFLAG_PETIGNORE = 0x40000000, // This unit is ignored by pets.
UNITFLAG_PET = 0x80000000 // This unit is a pet.
};

//UnitAny 0xC8
enum UNITFLAGEX
{
UNITFLAGEX_INVENTORY = 0x00000001, // Dispatches hInventory->hUpdates. Objects also check this which will lead to undefined behavior when set because they don't have an inventory.
UNITFLAGEX_2 = 0x00000002, // Set by D2SetInventoryUpdateMessage alongside UNITFLAGEX_INVENTORY if the unit is a player.
UNITFLAGEX_MERCHANT_INVENTORY_PUT = 0x00000004, // Adds the item to an NPC's trade inventory (sell to NPC).
UNITFLAGEX_DISGUISED = 0x00000008, // This unit is using another unit's graphics (shapechange).
UNITFLAGEX_MERCHANT_INVENTORY_TAKE = 0x00000010, // Removes an item from an NPC's trade inventory (buy from NPC).
UNITFLAGEX_REMOVE = 0x00000020, // If this is set alongside UNITFLAG_DELETE the client will send CMESSAGE_TELEPORT which instructs the server to set UNITFLAGEX_TELEPORTED. Must be some legacy junk.
UNITFLAGEX_CONVERTING = 0x00000040, // Set while the cursor is in conversion mode (legacy).
UNITFLAGEX_VISIBLE = 0x00000080, // Unit is within line of sight of the player.
UNITFLAGEX_DEACTIVATED = 0x00000100, // Set for units that have been deactivated by SUNIT_Deactivate.
UNITFLAGEX_REACTIVATED = 0x00000200, // Set for units that have been reactivated by SUNIT_Reactivate.
UNITFLAGEX_OWNED = 0x00000400, // This unit has an owner stored at pUnit->dwOwnerID and pUnit->eOwnerTOU (usually used by missile, but also set for pets).
UNITFLAGEX_POSITIONED = 0x00000800, // SMESSAGE_SETUNITPOS, bFadeOutScreen = FALSE.
UNITFLAGEX_MOVING = 0x00002000, // Set for critters while they're moving on the client.
UNITFLAGEX_TEMPORARY = 0x00008000, // Items with this bit set are not saved to the D2S.
UNITFLAGEX_TELEPORTED = 0x00010000, // SMESSAGE_SETUNITPOS, bFadeOutScreen = TRUE.
UNITFLAGEX_ATTACKED = 0x00020000, // The unit has been attacked and is storing details of the attacker in pUnit->dwAttackerID and pUnit->eAttackerTOU.
UNITFLAGEX_INVISIBLE = 0x00040000, // The unit is invisible and will be ignored by the drawing code completely.
UNITFLAGEX_EXPANSION = 0x02000000, // This is a unit in an expansion game.
UNITFLAGEX_SERVER = 0x04000000, // This is set for all units created on the server.
};

#define MONSTAT_ALIGN_ENEMY 0x0
#define MONSTAT_ALIGN_ALLY 0x1
#define MONSTAT_ALIGN_NEUTRAL 0x2
Expand Down
17 changes: 17 additions & 0 deletions BH/D2Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,23 @@
#include "Common.h"
#include "Constants.h"

int quality_to_color[] = {
White, // none
White, // inferior
White, // normal
White, // superior
Blue, // magic
Green, // set
Yellow, // rare
Gold, // unique
Orange // craft
};

int ItemColorFromQuality(unsigned int quality) {
return quality_to_color[quality];
}


RosterUnit* FindPlayerRoster(DWORD unitId) {
for (RosterUnit* roster = (*p_D2CLIENT_PlayerUnitList); roster; roster = roster->pNext) {
if (roster->dwUnitId == unitId)
Expand Down
3 changes: 2 additions & 1 deletion BH/D2Helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ std::string GetItemName(UnitAny* item);
bool IsTown(DWORD levelId);

bool IsGameReady();
DWORD GetPlayerArea();
DWORD GetPlayerArea();
int ItemColorFromQuality(unsigned int quality);
5 changes: 5 additions & 0 deletions BH/Modules/Item/Item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ void Item::LoadConfig() {
BH::config->ReadToggle("Advanced Item Display", "None", false, Toggles["Advanced Item Display"]);
BH::config->ReadToggle("Item Drop Notifications", "None", false, Toggles["Item Drop Notifications"]);
BH::config->ReadToggle("Item Close Notifications", "None", false, Toggles["Item Close Notifications"]);
BH::config->ReadToggle("Item Detailed Notifications", "None", false, Toggles["Item Detailed Notifications"]);
BH::config->ReadToggle("Verbose Notifications", "None", false, Toggles["Verbose Notifications"]);
BH::config->ReadToggle("Allow Unknown Items", "None", false, Toggles["Allow Unknown Items"]);
BH::config->ReadToggle("Suppress Invalid Stats", "None", false, Toggles["Suppress Invalid Stats"]);
Expand Down Expand Up @@ -158,6 +159,10 @@ void Item::DrawSettings() {
new Keyhook(settingsTab, keyhook_x, y+2, &Toggles["Item Close Notifications"].toggle, "");
y += 15;

new Checkhook(settingsTab, 4, y, &Toggles["Item Detailed Notifications"].state, "Item Detailed Notifications");
new Keyhook(settingsTab, keyhook_x, y + 2, &Toggles["Item Detailed Notifications"].toggle, "");
y += 15;

new Checkhook(settingsTab, 4, y, &Toggles["Verbose Notifications"].state, "Verbose Notifications");
new Keyhook(settingsTab, keyhook_x, y+2, &Toggles["Verbose Notifications"].toggle, "");
y += 15;
Expand Down
18 changes: 3 additions & 15 deletions BH/Modules/ItemMover/ItemMover.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "../../BH.h"
#include "../../D2Ptrs.h"
#include "../../D2Stubs.h"
#include "../../D2Helpers.h"

// This module was inspired by the RedVex plugin "Item Mover", written by kaiks.
// Thanks to kaiks for sharing his code.
Expand All @@ -24,18 +25,6 @@ int CUBE_LEFT = 197;
int CUBE_TOP = 199;
int CELL_SIZE = 29;

int quality_to_color[] = {
White, // none
White, // inferior
White, // normal
White, // superior
Blue, // magic
Green, // set
Yellow, // rare
Gold, // unique
Orange // craft
};

DWORD idBookId;
DWORD unidItemId;

Expand Down Expand Up @@ -604,11 +593,10 @@ void ItemMover::OnGamePacketRecv(BYTE* packet, bool* block) {
/* break; */
}
}

//PrintText(1, "Item on ground: %s, %s, %s, %X", item.name.c_str(), item.code, item.attrs->category.c_str(), item.attrs->flags);
if(showOnMap) {
if(showOnMap && !(*BH::MiscToggles2)["Item Detailed Notifications"].state) {
if (color == UNDEFINED_COLOR) {
color = quality_to_color[item.quality];
color = ItemColorFromQuality(item.quality);
}
if ((*BH::MiscToggles2)["Item Drop Notifications"].state &&
item.action == ITEM_ACTION_NEW_GROUND &&
Expand Down
47 changes: 45 additions & 2 deletions BH/Modules/Maphack/Maphack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,50 @@ BYTE nChestClosedColour = 0x09;
BYTE nChestLockedColour = 0x09;

Act* lastAct = NULL;

void Maphack::OnDraw() {
UnitAny* player = D2CLIENT_GetPlayerUnit();

if (!player || !player->pAct || player->pPath->pRoom1->pRoom2->pLevel->dwLevelNo == 0)
return;
// We're looping over all items and setting 2 flags:
// UNITFLAG_NO_EXPERIENCE - Whether the item has been checked for a drop notification (to prevent checking it again)
// UNITFLAG_REVEALED - Whether the item should be notified and drawn on the automap
// To my knowledge these flags arent typically used on items. So we can abuse them for our own use.
for (Room1* room1 = player->pAct->pRoom1; room1; room1 = room1->pRoomNext) {
for (UnitAny* unit = room1->pUnitFirst; unit; unit = unit->pListNext) {
if (unit->dwType == UNIT_ITEM && (unit->dwFlags & UNITFLAG_NO_EXPERIENCE) == 0x0) {
UnitItemInfo uInfo;
uInfo.item = unit;
uInfo.itemCode[0] = D2COMMON_GetItemText(unit->dwTxtFileNo)->szCode[0];
uInfo.itemCode[1] = D2COMMON_GetItemText(unit->dwTxtFileNo)->szCode[1];
uInfo.itemCode[2] = D2COMMON_GetItemText(unit->dwTxtFileNo)->szCode[2];
uInfo.itemCode[3] = 0;
if (ItemAttributeMap.find(uInfo.itemCode) != ItemAttributeMap.end()) {
uInfo.attrs = ItemAttributeMap[uInfo.itemCode];
for (vector<Rule*>::iterator it = MapRuleList.begin(); it != MapRuleList.end(); it++) {
if ((*it)->Evaluate(&uInfo, NULL)) {
if ((unit->dwFlags & UNITFLAG_REVEALED) == 0x0
&& (*BH::MiscToggles2)["Item Detailed Notifications"].state) {
std::string itemName = GetItemName(unit);
size_t start_pos = 0;
while ((start_pos = itemName.find('\n', start_pos)) != std::string::npos) {
itemName.replace(start_pos, 1, " - ");
start_pos += 3;
}
PrintText(ItemColorFromQuality(unit->pItemData->dwQuality), "%s", itemName.c_str());
}
unit->dwFlags |= UNITFLAG_REVEALED;
break;
}
}
}
}
unit->dwFlags |= UNITFLAG_NO_EXPERIENCE;
}
}
}

void Maphack::OnAutomapDraw() {
UnitAny* player = D2CLIENT_GetPlayerUnit();

Expand Down Expand Up @@ -449,7 +493,7 @@ void Maphack::OnAutomapDraw() {
Drawing::Boxhook::Draw(automapLoc.x - 1, automapLoc.y - 1, 2, 2, color, Drawing::BTHighlight);
});
}
else if (unit->dwType == UNIT_ITEM) {
else if (unit->dwType == UNIT_ITEM && (unit->dwFlags & UNITFLAG_REVEALED) == UNITFLAG_REVEALED) {
UnitItemInfo uInfo;
uInfo.item = unit;
uInfo.itemCode[0] = D2COMMON_GetItemText(unit->dwTxtFileNo)->szCode[0];
Expand All @@ -465,7 +509,6 @@ void Maphack::OnAutomapDraw() {
auto dotColor = (*it)->action.dotColor;
auto pxColor = (*it)->action.pxColor;
auto lineColor = (*it)->action.lineColor;

xPos = unit->pItemPath->dwPosX;
yPos = unit->pItemPath->dwPosY;
automapBuffer.push_top_layer(
Expand Down
1 change: 1 addition & 0 deletions BH/Modules/Maphack/Maphack.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class Maphack : public Module {
void LoadConfig();

void OnLoop();
void OnDraw();
void OnAutomapDraw();
void OnGameJoin(const string& name, const string& pass, int diff);
void OnGamePacketRecv(BYTE* packet, bool *block);
Expand Down

0 comments on commit 08dc318

Please sign in to comment.