// szBuf must be a 4-character string void GetItemCode(UnitAny* pUnit, char* szBuf) { if(pUnit->dwType == UNIT_ITEM) { ItemTxt* pTxt = D2COMMON_GetItemText(pUnit->dwTxtFileNo); if(pTxt) { memcpy(szBuf, pTxt->szCode, 3); szBuf[3] = 0x00; } } }
void ItemMover::OnKey(bool up, BYTE key, LPARAM lParam, bool* block) { UnitAny *unit = D2CLIENT_GetPlayerUnit(); if (!unit) return; if (!up && (key == HealKey || key == ManaKey)) { char firstChar = key == HealKey ? 'h' : 'm'; char minPotion = 127; DWORD minItemId = 0; bool isBelt = false; for (UnitAny *pItem = unit->pInventory->pFirstItem; pItem; pItem = pItem->pItemData->pNextInvItem) { if (pItem->pItemData->ItemLocation == STORAGE_INVENTORY || pItem->pItemData->ItemLocation == STORAGE_NULL && pItem->pItemData->NodePage == NODEPAGE_BELTSLOTS) { char* code = D2COMMON_GetItemText(pItem->dwTxtFileNo)->szCode; if (code[0] == firstChar && code[1] == 'p' && code[2] < minPotion) { minPotion = code[2]; minItemId = pItem->dwUnitId; isBelt = pItem->pItemData->NodePage == NODEPAGE_BELTSLOTS; } } //char *code = D2COMMON_GetItemText(pItem->dwTxtFileNo)->szCode; //if (code[0] == 'b' && code[1] == 'o' && code[2] == 'x') { // // Hack to pick up cube to fix cube-in-cube problem // BYTE PacketDataCube[5] = {0x19,0,0,0,0}; // *reinterpret_cast<int*>(PacketDataCube + 1) = pItem->dwUnitId; // D2NET_SendPacket(5, 1, PacketDataCube); // break; //} } if (minItemId > 0) { if (isBelt){ BYTE PacketData[13] = { 0x26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; *reinterpret_cast<int*>(PacketData + 1) = minItemId; D2NET_SendPacket(13, 0, PacketData); } else{ //PrintText(1, "Sending packet %d, %d, %d", minItemId, unit->pPath->xPos, unit->pPath->yPos); BYTE PacketData[13] = { 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; *reinterpret_cast<int*>(PacketData + 1) = minItemId; *reinterpret_cast<WORD*>(PacketData + 5) = (WORD)unit->pPath->xPos; *reinterpret_cast<WORD*>(PacketData + 9) = (WORD)unit->pPath->yPos; D2NET_SendPacket(13, 0, PacketData); } *block = true; } } }
bool ItemMover::LoadInventory(UnitAny *unit, int xpac, int source, int sourceX, int sourceY, bool shiftState, bool ctrlState, int stashUI, int invUI) { bool returnValue = false; memset(InventoryItemIds, 0, INVENTORY_WIDTH * INVENTORY_HEIGHT * sizeof(int)); memset(StashItemIds, 0, STASH_WIDTH * LOD_STASH_HEIGHT * sizeof(int)); memset(CubeItemIds, 0, CUBE_WIDTH * CUBE_HEIGHT * sizeof(int)); if (!xpac) { for (int x = 0; x < STASH_WIDTH; x++) { for (int y = CLASSIC_STASH_HEIGHT; y < LOD_STASH_HEIGHT; y++) { StashItemIds[y*STASH_WIDTH + x] = -1; } } } unsigned int itemId = 0; BYTE itemXSize, itemYSize; bool cubeInInventory = false, cubeAnywhere = false; for (UnitAny *pItem = unit->pInventory->pFirstItem; pItem; pItem = pItem->pItemData->pNextInvItem) { int *p, width; if (pItem->pItemData->ItemLocation == STORAGE_INVENTORY) { p = InventoryItemIds; width = INVENTORY_WIDTH; } else if (pItem->pItemData->ItemLocation == STORAGE_STASH) { p = StashItemIds; width = STASH_WIDTH; } else if (pItem->pItemData->ItemLocation == STORAGE_CUBE) { p = CubeItemIds; width = CUBE_WIDTH; } else { continue; } bool box = false; char *code = D2COMMON_GetItemText(pItem->dwTxtFileNo)->szCode; if (code[0] == 'b' && code[1] == 'o' && code[2] == 'x') { if (pItem->pItemData->ItemLocation == STORAGE_INVENTORY) { cubeInInventory = true; cubeAnywhere = true; } if (pItem->pItemData->ItemLocation == STORAGE_STASH) { cubeAnywhere = true; } box = true; } int xStart = pItem->pObjectPath->dwPosX; int yStart = pItem->pObjectPath->dwPosY; BYTE xSize = D2COMMON_GetItemText(pItem->dwTxtFileNo)->xSize; BYTE ySize = D2COMMON_GetItemText(pItem->dwTxtFileNo)->ySize; for (int x = xStart; x < xStart + xSize; x++) { for (int y = yStart; y < yStart + ySize; y++) { p[y*width + x] = pItem->dwUnitId; // If you click to move the cube into itself, your character ends up in // the amusing (and apparently permanent) state where he has no visible // cube and yet is unable to pick one up. Logging out does not fix it. // So we disable all cube movements to be on the safe side. if (x == sourceX && y == sourceY && pItem->pItemData->ItemLocation == source && !box) { // This is the item we want to move itemId = pItem->dwUnitId; itemXSize = xSize; itemYSize = ySize; } } } } int destination; if (ctrlState && shiftState && ((stashUI && cubeAnywhere) || (invUI && cubeInInventory)) && source != STORAGE_CUBE) { destination = STORAGE_CUBE; } else if (ctrlState) { destination = STORAGE_NULL; // i.e. the ground } else if (source == STORAGE_STASH || source == STORAGE_CUBE) { destination = STORAGE_INVENTORY; } else if (source == STORAGE_INVENTORY && D2CLIENT_GetUIState(UI_STASH)) { destination = STORAGE_STASH; } else if (source == STORAGE_INVENTORY && D2CLIENT_GetUIState(UI_CUBE)) { destination = STORAGE_CUBE; } else { return false; } // Find a spot for the item in the destination container if (itemId > 0) { returnValue = FindDestination(xpac, destination, itemId, itemXSize, itemYSize); } FirstInit = true; return returnValue; }
UnitAny* FindItemByPosition(DWORD x, DWORD y, DWORD Location) { for(UnitAny* pItem = D2COMMON_GetItemFromInventory(D2CLIENT_GetPlayerUnit()->pInventory); pItem; pItem = D2COMMON_GetNextItemFromInventory(pItem)) { if((DWORD)GetItemLocation(pItem) == Location && InArea(x,y,pItem->pObjectPath->dwPosX,pItem->pObjectPath->dwPosY,D2COMMON_GetItemText(pItem->dwTxtFileNo)->xSize,D2COMMON_GetItemText(pItem->dwTxtFileNo)->ySize)) return pItem; } return NULL; }
INT unit_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) { CDebug cDbg("unit getProperty"); BnetData* pData = *p_D2LAUNCH_BnData; GameStructInfo* pInfo = *p_D2CLIENT_GameInfo; switch(JSVAL_TO_INT(id)) { case ME_ACCOUNT: if(!pData) return JS_TRUE; *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, pData->szAccountName)); break; case ME_CHARNAME: if(!pInfo) return JS_TRUE; *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, pInfo->szCharName)); break; case ME_CHICKENHP: *vp = INT_TO_JSVAL(Vars.nChickenHP); break; case ME_CHICKENMP: *vp = INT_TO_JSVAL(Vars.nChickenMP); break; case ME_DIFF: *vp = INT_TO_JSVAL(D2CLIENT_GetDifficulty()); break; case ME_GAMENAME: if(!pInfo) return JS_TRUE; *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, pInfo->szGameName)); break; case ME_GAMEPASSWORD: if(!pInfo) return JS_TRUE; *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, pInfo->szGamePassword)); break; case ME_GAMESERVERIP: if(!pInfo) return JS_TRUE; *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, pInfo->szGameServerIp)); break; case ME_GAMESTARTTIME: *vp = INT_TO_JSVAL(Vars.dwGameTime); break; case ME_GAMETYPE: *vp = INT_TO_JSVAL(*p_D2CLIENT_ExpCharFlag); break; case ME_ITEMONCURSOR: *vp = BOOLEAN_TO_JSVAL(!!D2CLIENT_GetCursorItem()); break; case ME_LADDER: if(pData) *vp = BOOLEAN_TO_JSVAL(((pData->nCharFlags & PLAYER_TYPE_LADDER) == TRUE)); break; case ME_QUITONHOSTILE: *vp = BOOLEAN_TO_JSVAL(Vars.bQuitOnHostile); break; case ME_REALM: *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, pData->szRealmName)); break; case ME_REALMSHORT: *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, pData->szRealmName2)); break; case OOG_SCREENSIZE: *vp = INT_TO_JSVAL(D2GFX_GetScreenSize()); break; case OOG_WINDOWTITLE: CHAR szTitle[128]; GetWindowText(D2WIN_GetHwnd(), szTitle, 128); *vp = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, szTitle)); break; case ME_PING: *vp = INT_TO_JSVAL(*p_D2CLIENT_Ping); break; case OOG_INGAME: *vp = BOOLEAN_TO_JSVAL(ClientState() == ClientStateMenu ? FALSE : TRUE); break; case OOG_QUITONERROR: *vp = BOOLEAN_TO_JSVAL(Vars.bQuitOnError); break; case OOG_MAXGAMETIME: *vp = INT_TO_JSVAL(Vars.dwMaxGameTime); break; case OOG_DEBUG: *vp = BOOLEAN_TO_JSVAL(Vars.bDebug); break; case ME_MERCREVIVECOST: *vp = INT_TO_JSVAL((*p_D2CLIENT_MercReviveCost)); break; case ME_BLOCKKEYS: *vp = BOOLEAN_TO_JSVAL(Vars.bBlockKeys); break; case ME_BLOCKMOUSE: *vp = BOOLEAN_TO_JSVAL(Vars.bBlockMouse); break; default: break; } /* // TODO: Properly fix this... if ((JSVAL_TO_INT(id) < OOG_WINDOWTITLE) && !GameReady()) return JS_TRUE; */ if(!GameReady()) return JS_TRUE; myUnit* lpUnit = (myUnit*)JS_GetPrivate(cx, obj); if(!lpUnit || IsBadReadPtr(lpUnit, sizeof(myUnit)) || lpUnit->_dwPrivateType != PRIVATE_UNIT) return JS_TRUE; UnitAny* pUnit = D2CLIENT_FindUnit(lpUnit->dwUnitId, lpUnit->dwType); if(!pUnit) return JS_TRUE; char* tmp = NULL; Room1* pRoom = NULL; switch(JSVAL_TO_INT(id)) { case UNIT_TYPE: *vp = INT_TO_JSVAL(pUnit->dwType); break; case UNIT_CLASSID: *vp = INT_TO_JSVAL(pUnit->dwTxtFileNo); break; case UNIT_MODE: *vp = INT_TO_JSVAL(pUnit->dwMode); break; case UNIT_NAME: tmp = new char[8192]; GetUnitName(pUnit, tmp, 8192); *vp = STRING_TO_JSVAL(JS_InternString(cx, tmp)); delete[] tmp; break; case UNIT_ACT: *vp = INT_TO_JSVAL(pUnit->dwAct + 1); break; case UNIT_AREA: pRoom = D2COMMON_GetRoomFromUnit(pUnit); if(pRoom && pRoom->pRoom2 && pRoom->pRoom2->pLevel) *vp = INT_TO_JSVAL(pRoom->pRoom2->pLevel->dwLevelNo); break; case UNIT_ID: *vp = INT_TO_JSVAL(pUnit->dwUnitId); break; case UNIT_XPOS: *vp = INT_TO_JSVAL(GetUnitX(pUnit)); break; case UNIT_YPOS: *vp = INT_TO_JSVAL(GetUnitY(pUnit)); break; case UNIT_HP: *vp = INT_TO_JSVAL(D2COMMON_GetUnitStat(pUnit, 6, 0) >> 8); break; case UNIT_HPMAX: *vp = INT_TO_JSVAL(D2COMMON_GetUnitStat(pUnit, 7, 0) >> 8); break; case UNIT_MP: *vp = INT_TO_JSVAL(D2COMMON_GetUnitStat(pUnit, 8, 0) >> 8); break; case UNIT_MPMAX: *vp = INT_TO_JSVAL(D2COMMON_GetUnitStat(pUnit, 9, 0) >> 8); break; case UNIT_STAMINA: *vp = INT_TO_JSVAL(D2COMMON_GetUnitStat(pUnit, 10, 0) >> 8); break; case UNIT_STAMINAMAX: *vp = INT_TO_JSVAL(D2COMMON_GetUnitStat(pUnit, 11, 0) >> 8); break; case UNIT_CHARLVL: *vp = INT_TO_JSVAL(D2COMMON_GetUnitStat(pUnit, 12, 0)); break; case ME_RUNWALK: *vp = INT_TO_JSVAL(*p_D2CLIENT_AlwaysRun); break; case UNIT_ADDRESS: *vp = INT_TO_JSVAL(pUnit); break; case UNIT_SPECTYPE: DWORD SpecType; SpecType = NULL; if(pUnit->dwType == UNIT_MONSTER && pUnit->pMonsterData) { if(pUnit->pMonsterData->fMinion & 1) SpecType |= 0x08; if(pUnit->pMonsterData->fBoss & 1) SpecType |= 0x04; if(pUnit->pMonsterData->fChamp & 1) SpecType |= 0x02; if((pUnit->pMonsterData->fBoss & 1)&& (pUnit->pMonsterData->fNormal & 1)) SpecType |= 0x01; if(pUnit->pMonsterData->fNormal & 1) SpecType |= 0x00; *vp = INT_TO_JSVAL(SpecType); return JS_TRUE; } break; case UNIT_UNIQUEID: if(pUnit->dwType == UNIT_MONSTER && pUnit->pMonsterData->fBoss && pUnit->pMonsterData->fNormal) *vp = INT_TO_JSVAL(pUnit->pMonsterData->wUniqueNo); else *vp = INT_TO_JSVAL(-1); break; case ITEM_CODE: // replace with better method if found if(!(pUnit->dwType == UNIT_ITEM) && pUnit->pItemData) break; ItemTxt* pTxt; pTxt = D2COMMON_GetItemText(pUnit->dwTxtFileNo); if(!pTxt) { *vp = STRING_TO_JSVAL(JS_InternString(cx, "Unknown")); return JS_TRUE; } CHAR szCode[4]; memcpy(szCode, pTxt->szCode, 3); szCode[3] = 0x00; *vp = STRING_TO_JSVAL(JS_InternString(cx, szCode)); break; case ITEM_PREFIX: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) if (D2COMMON_GetItemMagicalMods(pUnit->pItemData->wPrefix)) *vp = STRING_TO_JSVAL(JS_InternString(cx, D2COMMON_GetItemMagicalMods(pUnit->pItemData->wPrefix))); break; case ITEM_SUFFIX: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) if (D2COMMON_GetItemMagicalMods(pUnit->pItemData->wSuffix)) *vp = STRING_TO_JSVAL(JS_InternString(cx, D2COMMON_GetItemMagicalMods(pUnit->pItemData->wSuffix))); break; case ITEM_PREFIXNUM: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) *vp = INT_TO_JSVAL(pUnit->pItemData->wPrefix); break; case ITEM_SUFFIXNUM: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) *vp = INT_TO_JSVAL(pUnit->pItemData->wSuffix); break; case ITEM_FNAME: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) { wchar_t wszfname[256] = L""; D2CLIENT_GetItemName(pUnit, wszfname, sizeof(wszfname)); if(wszfname) { char* tmp = UnicodeToAnsi(wszfname); *vp = STRING_TO_JSVAL(JS_InternString(cx, tmp)); delete[] tmp; } } break; case ITEM_QUALITY: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) *vp = INT_TO_JSVAL(pUnit->pItemData->dwQuality); break; case ITEM_NODE: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) *vp = INT_TO_JSVAL(pUnit->pItemData->NodePage); break; case ITEM_LOC: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) *vp = INT_TO_JSVAL(pUnit->pItemData->ItemLocation); break; case ITEM_SIZEX: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) { if(!D2COMMON_GetItemText(pUnit->dwTxtFileNo)) break; *vp = INT_TO_JSVAL(D2COMMON_GetItemText(pUnit->dwTxtFileNo)->xSize); } break; case ITEM_SIZEY: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) { if(!D2COMMON_GetItemText(pUnit->dwTxtFileNo)) break; *vp = INT_TO_JSVAL(D2COMMON_GetItemText(pUnit->dwTxtFileNo)->ySize); } break; case ITEM_Type: if(pUnit->dwType == UNIT_ITEM && pUnit->pItemData) { if(!D2COMMON_GetItemText(pUnit->dwTxtFileNo)) break; *vp = INT_TO_JSVAL(D2COMMON_GetItemText(pUnit->dwTxtFileNo)->nType); } break; case ITEM_DESC: { if(pUnit->dwType != UNIT_ITEM) break; wchar_t wBuffer[8192] = L""; D2CLIENT_GetItemDesc(pUnit, wBuffer); tmp = UnicodeToAnsi(wBuffer); *vp = STRING_TO_JSVAL(JS_InternString(cx, tmp)); delete[] tmp; } break; case UNIT_ITEMCOUNT: if(pUnit->pInventory) *vp = INT_TO_JSVAL(pUnit->pInventory->dwItemCount); break; case ITEM_BODYLOCATION: if(pUnit->dwType != UNIT_ITEM) break; if(pUnit->pItemData) *vp = INT_TO_JSVAL(pUnit->pItemData->BodyLocation); break; case UNIT_OWNER: *vp = INT_TO_JSVAL(pUnit->dwOwnerId); break; case UNIT_OWNERTYPE: *vp = INT_TO_JSVAL(pUnit->dwOwnerType); break; case ITEM_LEVEL: if(pUnit->dwType != UNIT_ITEM) break; if(pUnit->pItemData) *vp = INT_TO_JSVAL(pUnit->pItemData->dwItemLevel); break; case ITEM_LEVELREQ: if(pUnit->dwType != UNIT_ITEM) break; *vp = INT_TO_JSVAL(D2COMMON_GetItemLevelRequirement(pUnit, D2CLIENT_GetPlayerUnit())); break; case UNIT_DIRECTION: if(pUnit->pPath) *vp = INT_TO_JSVAL(pUnit->pPath->bDirection); break; case OBJECT_TYPE: if(pUnit->dwType == UNIT_OBJECT) if(pUnit->pObjectData) { pRoom = D2COMMON_GetRoomFromUnit(pUnit); if(pRoom && pRoom->pRoom2 && pRoom->pRoom2->pLevel && IsTownLevel(pRoom->pRoom2->pLevel->dwLevelNo)) *vp = INT_TO_JSVAL(pUnit->pObjectData->Type & 255); else *vp = INT_TO_JSVAL(pUnit->pObjectData->Type); } break; case ME_WSWITCH: *vp = INT_TO_JSVAL(*p_D2CLIENT_bWeapSwitch); break; default: break; } return JS_TRUE; }