Level* GetLevel(DWORD dwLevelNo) { for(Level* pLevel = D2CLIENT_GetPlayerUnit()->pAct->pMisc->pLevelFirst; pLevel; pLevel = pLevel->pNextLevel) if(pLevel->dwLevelNo == dwLevelNo) return pLevel; return D2COMMON_GetLevel(D2CLIENT_GetPlayerUnit()->pAct->pMisc, dwLevelNo); }
INT GetSkill(WORD wSkillId) { if(!D2CLIENT_GetPlayerUnit()) return 0; for(Skill* pSkill = D2CLIENT_GetPlayerUnit()->pInfo->pFirstSkill; pSkill; pSkill = pSkill->pNextSkill) if(pSkill->pSkillInfo->wSkillId == wSkillId) return D2COMMON_GetSkillLevel(D2CLIENT_GetPlayerUnit(), pSkill, TRUE); return 0; }
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; }
ClientGameState ClientState(void) { ClientGameState state = ClientStateNull; UnitAny* player = D2CLIENT_GetPlayerUnit(); if(player != NULL) { if(player != NULL && player->pUpdateUnit != NULL) { state = ClientStateBusy; return state; } if (player->pInventory != NULL && player->pPath != NULL && player->pPath->pRoom1 != NULL && player->pPath->pRoom1->pRoom2 != NULL && player->pPath->pRoom1->pRoom2->pLevel != NULL && player->pPath->pRoom1->pRoom2->pLevel->dwLevelNo != NULL) state = ClientStateInGame; else state = ClientStateBusy; } else if(player == NULL) state = ClientStateMenu; return state; }
BOOL CPathFinder::Search() { UnitAny *pPlayer = D2CLIENT_GetPlayerUnit(); if(!pPlayer) return FALSE; Room *pRoom1 = D2COMMON_GetRoomFromUnit(pPlayer); if(!pRoom1) return FALSE; RoomOther *pRoom2 = pRoom1->ptRoomOther; if(!pRoom2) return FALSE; DrlgLevel *pLevel = pRoom2->ptDrlgLevel; if(!pLevel) return FALSE; Reset(); m_ptLevelLeftTop.x = pLevel->LevelX; m_ptLevelLeftTop.y = pLevel->LevelY; POINT ptPlayer = MapPos2Point(GetPosition()); MapToGraph(ptPlayer); Search(pRoom2, ptPlayer); return TRUE; }
void BH::Initialize() { moduleManager = new ModuleManager(); config = new Config("BH.cfg"); config->Parse(); if (D2GFX_GetHwnd()) { BH::OldWNDPROC = (WNDPROC)GetWindowLong(D2GFX_GetHwnd(), GWL_WNDPROC); SetWindowLong(D2GFX_GetHwnd(), GWL_WNDPROC, (LONG)GameWindowEvent); } settingsUI = new Drawing::UI("Settings", 350, 200); Task::InitializeThreadPool(2); // Read the MPQ Data asynchronously //CreateThread(0, 0, LoadMPQData, 0, 0, 0); Task::Enqueue([]() -> void { LoadMPQData(NULL); }); new ScreenInfo(); new Gamefilter(); new Bnet(); new Item(); new SpamFilter(); new AutoTele(); new Party(); new ItemMover(); new StashExport(); new Maphack(); moduleManager->LoadModules(); statsDisplay = new Drawing::StatsDisplay("Stats"); MiscToggles = ((AutoTele*)moduleManager->Get("autotele"))->GetToggles(); MiscToggles2 = ((Item*)moduleManager->Get("item"))->GetToggles(); // Injection would occasionally deadlock (I only ever saw it when using Tabbed Diablo // but theoretically it could happen during regular injection): // Worker thread in DllMain->LoadModules->AutoTele::OnLoad->UITab->SetCurrentTab->Lock() // Main thread in GameDraw->UI::OnDraw->D2WIN_SetTextSize->GetDllOffset->GetModuleHandle() // GetModuleHandle can invoke the loader lock which causes the deadlock, so delay patch // installation until after all startup initialization is done. for (int n = 0; n < (sizeof(patches) / sizeof(Patch*)); n++) { patches[n]->Install(); } if (!D2CLIENT_GetPlayerUnit()) oogDraw->Install(); // GameThread can potentially run oogDraw->Install, so create the thread after all // loading/installation finishes. CreateThread(0, 0, GameThread, 0, 0, 0); initialized = true; }
BOOL RevealRoom(Room2* pRoom2, BOOL revealPresets) { bool bAdded = false; bool bInit = false; DWORD dwLevelNo = D2CLIENT_GetPlayerUnit()->pPath->pRoom1->pRoom2->pLevel->dwLevelNo; // Make sure we have the room. if (!pRoom2) return false; AutoCriticalRoom* cRoom = new AutoCriticalRoom; UnitAny* player = D2CLIENT_GetPlayerUnit(); // Check if we have Room1(Needed in order to reveal) if (!(pRoom2 && pRoom2->pLevel && pRoom2->pRoom1)) { D2COMMON_AddRoomData(pRoom2->pLevel->pMisc->pAct, pRoom2->pLevel->dwLevelNo, pRoom2->dwPosX, pRoom2->dwPosY, NULL); bAdded = true; } if (!(pRoom2 && pRoom2->pRoom1)) { // second check added to see if we DID indeed init the room! delete cRoom; return false; } // If we are somewhere other then the given area, init automap layer to be drawn to. if (!(pRoom2 && pRoom2->pLevel && pRoom2->pLevel->dwLevelNo && player->pPath && player->pPath->pRoom1 && player->pPath->pRoom1->pRoom2 && player->pPath->pRoom1->pRoom2->pLevel && player->pPath->pRoom1->pRoom2->pLevel->dwLevelNo == pRoom2->pLevel->dwLevelNo)) { InitAutomapLayer(pRoom2->pLevel->dwLevelNo); bInit = true; } // Reveal this room! D2CLIENT_RevealAutomapRoom(pRoom2->pRoom1, TRUE, (*p_D2CLIENT_AutomapLayer)); if (revealPresets) DrawPresets(pRoom2); // Remove room data if we have added. if (bAdded) D2COMMON_RemoveRoomData(pRoom2->pLevel->pMisc->pAct, pRoom2->pLevel->dwLevelNo, pRoom2->dwPosX, pRoom2->dwPosY, NULL); if (bInit) InitAutomapLayer(dwLevelNo); delete cRoom; return true; }
BOOL CCollisionMap::BuildMapData(DWORD AreaIds[], int nSize) { UnitAny* pUnit = D2CLIENT_GetPlayerUnit (); if (m_map.IsCreated()) return TRUE; if(!pUnit) return FALSE; //Get the most left-top level for the base and the size of the entire wanted map Level* pBestLevel = GetLevel(AreaIds[0]); DWORD dwXSize = 0; DWORD dwYSize = 0; m_ptLevelOrigin.x = pBestLevel->dwPosX * 5; m_ptLevelOrigin.y = pBestLevel->dwPosY * 5; dwLevelId = AreaIds[0]; //Loop all the given areas for (int n = 0; n < nSize; n++) { //Get the level struct for given id Level* pLevel = GetLevel(AreaIds[n]); //Make sure we have pLevel if (!pLevel) continue; //Check if this level is even more top-left then the current one if((m_ptLevelOrigin.x / 5) > (int)pLevel->dwPosX) m_ptLevelOrigin.x = pLevel->dwPosX * 5; if((m_ptLevelOrigin.y / 5) > (int)pLevel->dwPosY) m_ptLevelOrigin.y = pLevel->dwPosY * 5; //Add the size of the levels. dwXSize += pLevel->dwSizeX * 5; dwYSize += pLevel->dwSizeY * 5; } if (!m_map.Create(dwXSize, dwYSize, (WORD)MAP_DATA_INVALID)) return FALSE; DwordArray aSkip; for (int n = 0; n < nSize; n++) { Level* pLevel = GetLevel(AreaIds[n]); if (!pLevel) continue; Search(pLevel->pRoom2First, pUnit, aSkip, AreaIds[n]); } FillGaps(); FillGaps(); return TRUE; }
bool BH::ReloadConfig() { if (initialized){ if (D2CLIENT_GetPlayerUnit()) { PrintText(0, "Reloading config: %s", config->GetConfigName().c_str()); } config->Parse(); moduleManager->ReloadConfig(); statsDisplay->LoadConfig(); } return true; }
void ItemMover::OnRightClick(bool up, int x, int y, bool* block) { BnetData* pData = (*p_D2LAUNCH_BnData); UnitAny *unit = D2CLIENT_GetPlayerUnit(); bool shiftState = ((GetKeyState(VK_LSHIFT) & 0x80) || (GetKeyState(VK_RSHIFT) & 0x80)); bool ctrlState = ((GetKeyState(VK_LCONTROL) & 0x80) || (GetKeyState(VK_RCONTROL) & 0x80)); if (up || !pData || !unit || !(shiftState || ctrlState)) { return; } Init(); int xpac = pData->nCharFlags & PLAYER_TYPE_EXPANSION; int inventoryRight = INVENTORY_LEFT + (CELL_SIZE * INVENTORY_WIDTH); int inventoryBottom = INVENTORY_TOP + (CELL_SIZE * INVENTORY_HEIGHT); int stashRight = STASH_LEFT + (CELL_SIZE * STASH_WIDTH); int stashTop = xpac ? LOD_STASH_TOP : CLASSIC_STASH_TOP; int stashHeight = xpac ? LOD_STASH_HEIGHT : CLASSIC_STASH_HEIGHT; int stashBottom = stashTop + (CELL_SIZE * stashHeight); int cubeRight = CUBE_LEFT + (CELL_SIZE * CUBE_WIDTH); int cubeBottom = CUBE_TOP + (CELL_SIZE * CUBE_HEIGHT); int source, sourceX, sourceY; int invUI = D2CLIENT_GetUIState(UI_INVENTORY); int stashUI = D2CLIENT_GetUIState(UI_STASH); int cubeUI = D2CLIENT_GetUIState(UI_CUBE); if ((invUI || stashUI || cubeUI) && x >= INVENTORY_LEFT && x <= inventoryRight && y >= INVENTORY_TOP && y <= inventoryBottom) { source = STORAGE_INVENTORY; sourceX = (x - INVENTORY_LEFT) / CELL_SIZE; sourceY = (y - INVENTORY_TOP) / CELL_SIZE; } else if (stashUI && x >= STASH_LEFT && x <= stashRight && y >= stashTop && y <= stashBottom) { source = STORAGE_STASH; sourceX = (x - STASH_LEFT) / CELL_SIZE; sourceY = (y - stashTop) / CELL_SIZE; } else if (cubeUI && x >= CUBE_LEFT && x <= cubeRight && y >= CUBE_TOP && y <= cubeBottom) { source = STORAGE_CUBE; sourceX = (x - CUBE_LEFT) / CELL_SIZE; sourceY = (y - CUBE_TOP) / CELL_SIZE; } else { return; } bool moveItem = LoadInventory(unit, xpac, source, sourceX, sourceY, shiftState, ctrlState, stashUI, invUI); if (moveItem) { PickUpItem(); } *block = true; }
BOOL ExecuteEnchantQueue(LPENCHANTINFO EnchInfo) { if (!GameReady() || !EnchInfo) return FALSE; UnitAny* pPlayer = D2CLIENT_GetPlayerUnit(); if (EnchInfo->dwPlayerId == pPlayer->dwUnitId) return FALSE; if (EnchInfo->nEnchantType == ENCHANT_ME) { for(Room1* pRoom1 = pPlayer->pAct->pRoom1; pRoom1; pRoom1 = pRoom1->pRoomNext) for (UnitAny* pUnit = pRoom1->pFirstUnit; pUnit; pUnit = pUnit->pListNext) if (pUnit->dwType == UNIT_PLAYER && pUnit->dwUnitId == EnchInfo->dwPlayerId) { CastOnUnit(D2S_ENCHANT, pUnit, FALSE); return TRUE; } if (!bSilentBots) Say("You're out of range!"); return FALSE; } if(EnchInfo->nEnchantType == ENCHANT_MERC) { for (Room1* pRoom1 = pPlayer->pAct->pRoom1; pRoom1; pRoom1 = pRoom1->pRoomNext) for (UnitAny* pUnit = pRoom1->pFirstUnit; pUnit; pUnit = pUnit->pListNext) if (pUnit->dwType == UNIT_NPC && IsMercClassId(pUnit->dwTxtFileNo)) { DWORD dwOwner = D2CLIENT_GetMonsterOwner(pUnit->dwUnitId); if (dwOwner == EnchInfo->dwPlayerId) { CastOnUnit(D2S_ENCHANT, pUnit, FALSE); return TRUE; } } if (!bSilentBots) Say("Couldn't find your mercenary!"); return FALSE; } return FALSE; }
int GetRelation(UnitAny* unit) { UnitAny* player = D2CLIENT_GetPlayerUnit(); RosterUnit* roster; RosterUnit* playerRoster = FindPlayerRoster(player->dwUnitId); //Neutral = 2, Partied = 3, You = 1, Hostile = 4 if (!unit || !player) return 2; switch(unit->dwType) { case UNIT_PLAYER://Player // Check if we are the unit. if (unit->dwUnitId == player->dwUnitId) return 1;//You // Check if we are in a party with unit. roster = FindPlayerRoster(unit->dwUnitId); if (playerRoster && roster && playerRoster->wPartyId == roster->wPartyId && roster->wPartyId != INVALID_PARTY_ID) return 3;//Partied // Check if unit is hostile towards us if (TestPvpFlag_STUB(unit->dwUnitId, player->dwUnitId, 8)) return 4; return 2; break; case UNIT_MONSTER://Monster or NPC or Summon case UNIT_MISSILE://Missile if (unit->dwOwnerId < 0 || unit->dwOwnerType < 0 || unit->dwOwnerType > 5) return 4; if (unit->dwType == UNIT_MONSTER && unit->dwOwnerType == UNIT_MONSTER) return 4; // Find the owner of the unit. UnitAny* owner = D2CLIENT_FindServerSideUnit(unit->dwOwnerId, unit->dwOwnerType); if (!owner || owner->dwType != unit->dwOwnerType || owner->dwUnitId != unit->dwOwnerId) return 4; return GetRelation(owner); break; } return 2;//Neutral }
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; } } }
void CPathFinder::Search(RoomOther *ro, POINT ptPlayer) { if (!ro) return; if(ro->ptDrlgLevel->LevelNo != GetCurrentMapID()) return; if (m_aSearched.Find(ro) != -1) return; UnitPlayer* pPlayer = D2CLIENT_GetPlayerUnit(); if (pPlayer == NULL) return; BOOL add_room=FALSE; if(!ro->pRoom) { add_room=TRUE; D2COMMON_AddRoomData(pPlayer->ptAct, GetCurrentMapID(), ro->xPos, ro->yPos, pPlayer); } m_aSearched.Add(ro); m_aSearched.Sort(); if (ro->pRoom) AddCollisionData((LPVOID)ro->pRoom->pColl, ptPlayer); //DumpCollisionMap((LPVOID)ro->pRoom->pColl); RoomOther **n = ro->ptList; for(int i=0;i<ro->nRoomList;i++) { Search(n[i], ptPlayer); } if(add_room) { D2COMMON_RemoveRoomData(pPlayer->ptAct, GetCurrentMapID(), ro->xPos, ro->yPos, pPlayer); } }
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; }
INT unit_interact(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { CDebug cDbg("unit interact"); if(!GameReady()) return JS_TRUE; myUnit* lpUnit = (myUnit*)JS_GetPrivate(cx, obj); *rval = JSVAL_FALSE; 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; if(pUnit->dwType == UNIT_ITEM && pUnit->dwMode != ITEM_MODE_ON_GROUND && pUnit->dwMode != ITEM_MODE_BEING_DROPPED) { INT nLocation = GetItemLocation(pUnit); BYTE aPacket[13] = {NULL}; if(nLocation == STORAGE_INVENTORY) { aPacket[0] = 0x20; *(DWORD*)&aPacket[1] = pUnit->dwUnitId; *(DWORD*)&aPacket[5] = D2CLIENT_GetPlayerUnit()->pPath->xPos; *(DWORD*)&aPacket[9] = D2CLIENT_GetPlayerUnit()->pPath->yPos; D2NET_SendPacket(13, 1, aPacket); return JS_TRUE; } else if(nLocation == STORAGE_BELT) { aPacket[0] = 0x26; *(DWORD*)&aPacket[1] = pUnit->dwUnitId; *(DWORD*)&aPacket[5] = 0; *(DWORD*)&aPacket[9] = 0; D2NET_SendPacket(13, 1, aPacket); return JS_TRUE; } } if(pUnit->dwType == UNIT_OBJECT && argc == 1 && JSVAL_IS_INT(argv[0])) { // TODO: check the range on argv[0] to make sure it won't crash the game D2CLIENT_TakeWaypoint(pUnit->dwUnitId, JSVAL_TO_INT(argv[0])); // D2CLIENT_TakeWP(pUnit->dwUnitId, JSVAL_TO_INT(argv[0])); *rval = JSVAL_TRUE; return JS_TRUE; } else if(pUnit->dwType == UNIT_PLAYER && argc == 1 && JSVAL_IS_INT(argv[0]) && JSVAL_TO_INT(argv[0]) == 1) { // Accept Trade } else { *rval = JSVAL_TRUE; ClickMap(0, GetUnitX(pUnit), GetUnitY(pUnit), FALSE, pUnit); //D2CLIENT_Interact(pUnit, 0x45); } return JS_TRUE; }
BOOL CCollisionMap::DumpMap(LPCSTR lpszFilePath, const LPPOINT lpPath, DWORD dwCount) const { if (lpszFilePath == NULL) return FALSE; FILE *fp = NULL; fopen_s(&fp, lpszFilePath, "w+"); if(fp == NULL ) return FALSE; if (!m_map.IsCreated()) return FALSE; //m_map.Lock(); char szMapName[256] = ""; fprintf(fp, "%s (Size: %d * %d)\nKnown Collision Types: ", szMapName, m_map.GetCX(), m_map.GetCY()); for (int i = 0; i < m_aCollisionTypes.GetSize(); i++) { fprintf(fp, "%d, ", m_aCollisionTypes[i]); } fprintf(fp, "\n\n"); POINT* pPath = NULL; if (lpPath && dwCount) { pPath = new POINT[dwCount]; ::memcpy(pPath, lpPath, dwCount * sizeof(POINT)); for (DWORD i = 0; i < dwCount; i++) AbsToRelative(pPath[i]); } UnitAny* Me = D2CLIENT_GetPlayerUnit(); POINT ptPlayer = {Me->pPath->xPos,Me->pPath->yPos}; AbsToRelative(ptPlayer); const int CX = m_map.GetCX(); const int CY = m_map.GetCY(); for (int y = 0; y < CY; y++) { for (int x = 0; x < CX; x++) { char ch = IsMarkPoint(ptPlayer, x, y, pPath, dwCount); if (!ch) ch = (m_map[x][y] % 2) ? 'X' : ' '; fprintf(fp, "%C", ch); // X - unreachable } fprintf(fp, "%c", '\n'); } if (pPath) delete [] pPath; //m_map.Unlock(); fclose(fp); return TRUE; }
INT CCollisionMap::GetLevelExits(LPLevelExit* lpLevel) { POINT ptExitPoints[0x40][2]; INT nTotalPoints = 0, nCurrentExit = 0; INT nMaxExits = 0x40; UnitAny* Me = D2CLIENT_GetPlayerUnit(); CriticalRoom myRoom; myRoom.EnterSection(); for(INT i = 0; i < m_map.GetCX(); i++) { if(!(m_map[i][0] % 2)) { ptExitPoints[nTotalPoints][0].x = i; ptExitPoints[nTotalPoints][0].y = 0; for(i++; i < m_map.GetCX(); i++) { if(m_map[i][0] % 2) { ptExitPoints[nTotalPoints][1].x = i - 1; ptExitPoints[nTotalPoints][1].y = 0; break; } } nTotalPoints++; break; } } for(INT i = 0; i < m_map.GetCX(); i++) { if(!(m_map[i][m_map.GetCY() - 1] % 2)) { ptExitPoints[nTotalPoints][0].x = i; ptExitPoints[nTotalPoints][0].y = m_map.GetCY() - 1; for(i++; i < m_map.GetCX(); i++) { if((m_map[i][m_map.GetCY() - 1] % 2)) { ptExitPoints[nTotalPoints][1].x = i - 1; ptExitPoints[nTotalPoints][1].y = m_map.GetCY() - 1; break; } } nTotalPoints++; break; } } for(INT i = 0; i < m_map.GetCY(); i++) { if(!(m_map[0][i] % 2)) { ptExitPoints[nTotalPoints][0].x = 0; ptExitPoints[nTotalPoints][0].y = i; for(i++; i < m_map.GetCY(); i++) { if((m_map[0][i] % 2)) { ptExitPoints[nTotalPoints][1].x = 0; ptExitPoints[nTotalPoints][1].y = i - 1; break; } } nTotalPoints++; break; } } for(INT i = 0; i < m_map.GetCY(); i++) { if(!(m_map[m_map.GetCX() - 1][i] % 2)) { ptExitPoints[nTotalPoints][0].x = m_map.GetCX() - 1; ptExitPoints[nTotalPoints][0].y = i; for(i++; i < m_map.GetCY(); i++) { if((m_map[m_map.GetCX() - 1][i] % 2)) { ptExitPoints[nTotalPoints][1].x = m_map.GetCX() - 1; ptExitPoints[nTotalPoints][1].y = i - 1; break; } } nTotalPoints++; break; } } LPPOINT ptCenters = new POINT[nTotalPoints]; for(INT i = 0; i < nTotalPoints; i++) { INT nXDiff = ptExitPoints[i][1].x - ptExitPoints[i][0].x; INT nYDiff = ptExitPoints[i][1].y - ptExitPoints[i][0].y; INT nXCenter = 0, nYCenter = 0; if(nXDiff > 0) { if(nXDiff % 2) nXCenter = ptExitPoints[i][0].x + ((nXDiff - (nXDiff % 2)) / 2); else nXCenter = ptExitPoints[i][0].x + (nXDiff / 2); } if(nYDiff > 0) { if(nYDiff % 2) nYCenter = ptExitPoints[i][0].y + ((nYDiff - (nYDiff % 2)) / 2); else nYCenter = ptExitPoints[i][0].y + (nYDiff / 2); } ptCenters[i].x = nXCenter ? nXCenter : ptExitPoints[i][0].x; ptCenters[i].y = nYCenter ? nYCenter : ptExitPoints[i][0].y; } for(Room2* pRoom = GetLevel(dwLevelId)->pRoom2First; pRoom; pRoom = pRoom->pRoom2Next) { Room2* *pNear = pRoom->pRoom2Near; for(DWORD i = 0; i < pRoom->dwRoomsNear; i++) { if(pNear[i]->pLevel->dwLevelNo != dwLevelId) { INT nRoomX = pRoom->dwPosX * 5; INT nRoomY = pRoom->dwPosY * 5; for(INT j = 0; j < nTotalPoints; j++) { if((ptCenters[j].x + m_ptLevelOrigin.x) >= (WORD)nRoomX && (ptCenters[j].x + m_ptLevelOrigin.x) <= (WORD)(nRoomX + (pRoom->dwSizeX * 5))) { if((ptCenters[j].y + m_ptLevelOrigin.y) >= (WORD)nRoomY && (ptCenters[j].y + m_ptLevelOrigin.y) <= (WORD)(nRoomY + (pRoom->dwSizeY * 5))) { if(nCurrentExit >= nMaxExits) { // LeaveCriticalSection(&CriticalSection); return FALSE; } lpLevel[nCurrentExit] = new LevelExit; lpLevel[nCurrentExit]->dwTargetLevel = pNear[i]->pLevel->dwLevelNo; lpLevel[nCurrentExit]->ptPos.x = ptCenters[j].x + m_ptLevelOrigin.x; lpLevel[nCurrentExit]->ptPos.y = ptCenters[j].y + m_ptLevelOrigin.y; lpLevel[nCurrentExit]->dwType = EXIT_LEVEL; lpLevel[nCurrentExit]->dwId = 0; nCurrentExit++; } } } break; } } BOOL bAdded = FALSE; if(!pRoom->pRoom1) { D2COMMON_AddRoomData(Me->pAct, pRoom->pLevel->dwLevelNo, pRoom->dwPosX, pRoom->dwPosY, Me->pPath->pRoom1); bAdded = TRUE; } for(PresetUnit* pUnit = pRoom->pPreset; pUnit; pUnit = pUnit->pPresetNext) { if(nCurrentExit >= nMaxExits) { if(bAdded) D2COMMON_RemoveRoomData(Me->pAct, pRoom->pLevel->dwLevelNo, pRoom->dwPosX, pRoom->dwPosY, Me->pPath->pRoom1); // LeaveCriticalSection(&CriticalSection); return FALSE; } if(pUnit->dwType == UNIT_TILE) { DWORD dwTargetLevel = GetTileLevelNo(pRoom, pUnit->dwTxtFileNo); if(dwTargetLevel) { BOOL bExists = FALSE; for(INT i = 0; i < nCurrentExit; i++) { if(((DWORD)lpLevel[i]->ptPos.x == (pRoom->dwPosX * 5) + pUnit->dwPosX) && ((DWORD)lpLevel[i]->ptPos.y == (pRoom->dwPosY * 5) + pUnit->dwPosY)) bExists = TRUE; } if(!bExists) { lpLevel[nCurrentExit] = new LevelExit; lpLevel[nCurrentExit]->dwTargetLevel = dwTargetLevel; lpLevel[nCurrentExit]->ptPos.x = (pRoom->dwPosX * 5) + pUnit->dwPosX; lpLevel[nCurrentExit]->ptPos.y = (pRoom->dwPosY * 5) + pUnit->dwPosY; lpLevel[nCurrentExit]->dwType = EXIT_TILE; lpLevel[nCurrentExit]->dwId = pUnit->dwTxtFileNo; nCurrentExit++; } } } } if(bAdded) D2COMMON_RemoveRoomData(Me->pAct, pRoom->pLevel->dwLevelNo, pRoom->dwPosX, pRoom->dwPosY, Me->pPath->pRoom1); } // LeaveCriticalSection(&CriticalSection); return nCurrentExit; }