void CPathFinder::Clear() { ADDTOCALLSTACK("CPathFinder::Clear"); m_Target = CPointMap(0,0); m_pChar = 0; m_Opened.clear(); m_Closed.clear(); m_RealX = 0; m_RealY = 0; }
CPointMap CWorld::FindTypeNear_Top( const CPointMap & pt, IT_TYPE iType, int iDistance ) { ADDTOCALLSTACK("CWorld::FindTypeNear_Top"); #define RESOURCE_Z_CHECK 8 CPointMap ptFound; CItemBase * pItemDef = NULL; CItem * pItem = NULL; CItemBaseDupe * pDupeDef = NULL; height_t Height = 0; BYTE z = 0; CPointMap ptTest; unsigned int iRetElem = 4; CPointMap ptElem[5]; memset(ptElem, 0, sizeof(ptElem)); //for ( iQty = 0; iQty < 4; ++iQty ) // ptElem[iQty].m_z = UO_SIZE_MIN_Z; ptElem[0].m_z = ptElem[1].m_z = ptElem[2].m_z = ptElem[3].m_z = UO_SIZE_MIN_Z; ptElem[4] = CPointMap(USHRT_MAX, USHRT_MAX, UO_SIZE_MIN_Z); bool fElem[4] = { false, false, false, false }; // Check dynamics CWorldSearch Area( pt, iDistance ); Area.SetAllShow( true ); for (;;) { z = 0; Height = 0; pItem = Area.GetItem(); if ( pItem == NULL ) break; if ( pt.GetDist( pItem->GetTopPoint() ) > iDistance ) continue; pItemDef = CItemBase::FindItemBase( pItem->GetDispID() ); if ( pItemDef == NULL ) continue; Height = pItemDef->GetHeight(); if ( pItemDef->GetID() != pItem->GetDispID() ) //not a parent item { pDupeDef = CItemBaseDupe::GetDupeRef(static_cast<ITEMID_TYPE>(pItem->GetDispID())); if ( ! pDupeDef ) { g_Log.EventDebug("Failed to get non-parent reference (dynamic) (DispID 0%x) (X: %d Y: %d Z: %d)\n",pItem->GetDispID(),ptTest.m_x,ptTest.m_y,ptTest.m_z); Height = pItemDef->GetHeight(); } else Height = pDupeDef->GetHeight(); } z = minimum( Height + pItem->GetTopPoint().m_z, UO_SIZE_Z ); //height + current position = the top point if ( ptElem[0].m_z > z ) //if ( ptElem[0].m_z > pItem->GetTopPoint().m_z ) continue; if ( ((( z - pt.m_z ) > 0) && ( z - pt.m_z ) > RESOURCE_Z_CHECK ) || ((( pt.m_z - z ) < 0) && (( pt.m_z - z ) < - RESOURCE_Z_CHECK ))) //if ( ((( pItem->GetTopPoint().m_z - pt.m_z ) > 0) && ( pItem->GetTopPoint().m_z - pt.m_z ) > RESOURCE_Z_CHECK ) || ((( pt.m_z - pItem->GetTopPoint().m_z ) < 0) && (( pt.m_z - pItem->GetTopPoint().m_z ) < - RESOURCE_Z_CHECK ))) continue; if (( z < ptElem[0].m_z ) || (( z == ptElem[0].m_z ) && ( fElem[0] ))) continue; ptElem[0] = pItem->GetTopPoint(); ptElem[0].m_z = z; fElem[0] = false; //DEBUG_ERR(("dynamic pItem->IsType( iType %d) %d\n",iType,pItem->IsType( iType ))); if ( pItem->IsType( iType ) ) //( pItem->Item_GetDef()->IsType(iType) ) ) { fElem[0] = true; iRetElem = 0; } } // Parts of multis ? const CGrayMulti * pMulti = NULL; // Multi Def (multi check) const CUOMultiItemRec2 * pMultiItem = NULL; // Multi item iterator CRegionBase * pRegion = NULL; CRegionLinks rlinks; size_t iRegionQty = pt.GetRegions( REGION_TYPE_MULTI, rlinks ); if ( iRegionQty > 0 ) { for ( size_t iRegion = 0; iRegion < iRegionQty; pMulti = NULL, ++iRegion) { pRegion = rlinks.GetAt(iRegion); pItem = pRegion->GetResourceID().ItemFind(); if ( !pItem ) continue; pMulti = g_Cfg.GetMultiItemDefs(pItem); if ( !pMulti ) continue; size_t iMultiQty = pMulti->GetItemCount(); for ( size_t iMulti = 0; iMulti < iMultiQty; pItemDef = NULL, pMultiItem = NULL, Height = 0, ++iMulti ) { pMultiItem = pMulti->GetItem(iMulti); if ( !pMultiItem ) break; //DEBUG_ERR(("abs( pMultiItem->m_dx ) %x, abs( pMultiItem->m_dy ) %x, abs( pMultiItem->m_dz ) %x,\n iDistance %x IF STATEMENT %x %x\n", abs( pMultiItem->m_dx ), abs( pMultiItem->m_dy ), abs( pMultiItem->m_dz ), iDistance, ( abs( pMultiItem->m_dx ) <= iDistance ), ( abs( pMultiItem->m_dy ) <= iDistance ) )); if ( !pMultiItem->m_visible ) continue; ptTest = CPointMap( pMultiItem->m_dx + pt.m_x, pMultiItem->m_dy + pt.m_y, static_cast<signed char>( pMultiItem->m_dz + pt.m_z ), pt.m_map ); pItemDef = CItemBase::FindItemBase( pMultiItem->GetDispID() ); if ( pItemDef == NULL ) continue; Height = pItemDef->GetHeight(); if ( pItemDef->GetID() != pMultiItem->GetDispID() ) //not a parent item { pDupeDef = CItemBaseDupe::GetDupeRef(static_cast<ITEMID_TYPE>(pMultiItem->GetDispID())); if ( ! pDupeDef ) { g_Log.EventDebug("Failed to get non-parent reference (multi) (DispID 0%x) (X: %d Y: %d Z: %d)\n",pMultiItem->GetDispID(),ptTest.m_x,ptTest.m_y,ptTest.m_z); Height = pItemDef->GetHeight(); } else Height = pDupeDef->GetHeight(); } ptTest.m_z = minimum(ptTest.m_z + Height, UO_SIZE_Z); //height + current position = the top point if ( pt.GetDist( ptTest ) > iDistance ) continue; if ( ptElem[1].m_z > ptTest.m_z ) continue; if ( ((( ptTest.m_z - pt.m_z ) > 0) && ( ptTest.m_z - pt.m_z ) > RESOURCE_Z_CHECK ) || ((( pt.m_z - ptTest.m_z ) < 0) && (( pt.m_z - ptTest.m_z ) < - RESOURCE_Z_CHECK ))) continue; if (( ptTest.m_z < ptElem[1].m_z ) || (( ptTest.m_z == ptElem[1].m_z ) && ( fElem[1] ))) continue; //DEBUG_ERR(("pMultiItem->GetDispID()%x\n",pMultiItem->GetDispID())); ptElem[1] = ptTest; fElem[1] = false; //DEBUG_ERR(("multi pItemDef->IsType( iType %d) %d\n",iType,pItemDef->IsType( iType ))); if ( pItemDef->IsType( iType ) ) { fElem[1] = true; //if ( ptElem[iRetElem].m_z > ptElem[1].m_z ) if ( ptElem[1].m_z > ptElem[iRetElem].m_z ) iRetElem = 1; } //DEBUG_ERR(( "DISPID: %x X %d Y %d Z %d\n", pMultiItem->GetDispID(), (pMultiItem->m_dx), (pMultiItem->m_dy), (pMultiItem->m_dz) )); } } } // STATIC - checks one 8x8 block const CGrayMapBlock * pMapBlock = GetMapBlock( pt ); ASSERT( pMapBlock ); size_t iStaticQty = pMapBlock->m_Statics.GetStaticQty(); if ( iStaticQty > 0 ) // no static items here. { const CUOStaticItemRec * pStatic = NULL; for ( size_t i = 0; i < iStaticQty; ++i, pStatic = NULL, Height = 0, pItemDef = NULL ) { pStatic = pMapBlock->m_Statics.GetStatic( i ); ptTest = CPointMap( pStatic->m_x + pMapBlock->m_x, pStatic->m_y + pMapBlock->m_y, pStatic->m_z, pt.m_map ); pItemDef = CItemBase::FindItemBase( pStatic->GetDispID() ); if ( pItemDef == NULL ) continue; //DEBUG_ERR(("pStatic->GetDispID() %d; name %s; pStatic->m_z %d\n",pStatic->GetDispID(),pItemDef->GetName(),pStatic->m_z)); Height = pItemDef->GetHeight(); if ( pItemDef->GetID() != pStatic->GetDispID() ) //not a parent item { pDupeDef = CItemBaseDupe::GetDupeRef(static_cast<ITEMID_TYPE>(pStatic->GetDispID())); if ( ! pDupeDef ) { g_Log.EventDebug("Failed to get non-parent reference (static) (DispID 0%x) (X: %d Y: %d Z: %d)\n",pStatic->GetDispID(),ptTest.m_x,ptTest.m_y,ptTest.m_z); Height = pItemDef->GetHeight(); } else Height = pDupeDef->GetHeight(); } ptTest.m_z = minimum(ptTest.m_z + Height, UO_SIZE_Z); //height + current position = the top point if ( pt.GetDist( ptTest ) > iDistance ) continue; if ( pt.GetDist( ptTest ) > iDistance ) continue; //if ( ptElem[2].m_z > pStatic->m_z ) if ( ptElem[2].m_z > ptTest.m_z ) continue; if ( ((( pStatic->m_z - pt.m_z ) > 0) && ( pStatic->m_z - pt.m_z ) > RESOURCE_Z_CHECK ) || ((( pt.m_z - pStatic->m_z ) < 0) && (( pt.m_z - pStatic->m_z ) < - RESOURCE_Z_CHECK ))) continue; if (( ptTest.m_z < ptElem[2].m_z ) || (( ptTest.m_z == ptElem[2].m_z ) && ( fElem[2] ))) continue; ptElem[2] = ptTest; fElem[2] = false; //DEBUG_ERR(("static pItemDef->IsType( iType %d) %d;pItemDef->GetType() %d;pItemDef->GetID() %d;pItemDef->GetDispID() %d\n",iType,pItemDef->IsType( iType ),pItemDef->GetType(),pItemDef->GetID(),pItemDef->GetDispID())); if ( pItemDef->IsType( iType ) ) { //DEBUG_ERR(("found %d; ptTest: %d,%d,%d\n",__LINE__,ptTest.m_x,ptTest.m_y,ptTest.m_z)); fElem[2] = true; //DEBUG_ERR(("ptElem[iRetElem].m_z %d, ptElem[2].m_z %d\n",ptElem[iRetElem].m_z,ptElem[2].m_z)); //if ( ptElem[iRetElem].m_z > ptElem[2].m_z ) if ( ptElem[2].m_z > ptElem[iRetElem].m_z ) iRetElem = 2; } } } // Check for appropriate terrain type CRectMap rect; rect.SetRect( pt.m_x - iDistance, pt.m_y - iDistance, pt.m_x + iDistance + 1, pt.m_y + iDistance + 1, pt.m_map); const CUOMapMeter * pMeter = NULL; for ( int x = rect.m_left; x < rect.m_right; ++x, pMeter = NULL ) { for ( int y = rect.m_top; y < rect.m_bottom; ++y, pMeter = NULL ) { ptTest = CPointMap(static_cast<WORD>(x), static_cast<WORD>(y), pt.m_z, pt.m_map); pMeter = GetMapMeter(ptTest); if ( !pMeter ) continue; if ( pt.GetDist( ptTest ) > iDistance ) continue; if ( ptElem[3].m_z > pMeter->m_z ) continue; //DEBUG_ERR(("(( pMeter->m_z (%d) - pt.m_z (%d) ) > 0) && ( pMeter->m_z (%d) - pt.m_z (%d) ) > RESOURCE_Z_CHECK (%d) >> %d\n",pMeter->m_z,pt.m_z,pMeter->m_z,pt.m_z,RESOURCE_Z_CHECK,(( pMeter->m_z - pt.m_z ) > 0) && ( pMeter->m_z - pt.m_z ) > RESOURCE_Z_CHECK)); //DEBUG_ERR(("(( pt.m_z (%d) - pMeter->m_z (%d) ) < 0) && (( pt.m_z (%d) - pMeter->m_z (%d) ) < - RESOURCE_Z_CHECK (%d) )) >> %d\n",pt.m_z,pMeter->m_z,pt.m_z,pMeter->m_z,- RESOURCE_Z_CHECK,((( pt.m_z - pMeter->m_z ) < 0) && (( pt.m_z - pMeter->m_z ) < - RESOURCE_Z_CHECK )))); if ( ((( pMeter->m_z - pt.m_z ) > 0) && ( pMeter->m_z - pt.m_z ) > RESOURCE_Z_CHECK ) || ((( pt.m_z - pMeter->m_z ) < 0) && (( pt.m_z - pMeter->m_z ) < - RESOURCE_Z_CHECK ))) continue; //DEBUG_ERR(("pMeter->m_z (%d) < ptElem[3].m_z (%d) >> %d\n",pMeter->m_z,ptElem[3].m_z,pMeter->m_z < ptElem[3].m_z)); if (( pMeter->m_z < ptElem[3].m_z ) || (( pMeter->m_z == ptElem[3].m_z ) && ( fElem[3] ))) continue; ptElem[3] = ptTest; fElem[3] = false; //DEBUG_ERR(("iType %x, TerrainType %x\n",iType,g_World.GetTerrainItemType( pMeter->m_wTerrainIndex ))); if ( iType == g_World.GetTerrainItemType( pMeter->m_wTerrainIndex ) ) { fElem[3] = true; //if ( ptElem[iRetElem].m_z > ptElem[3].m_z ) //DEBUG_ERR(("ptElem[3].m_z %d; ptElem[iRetElem].m_z %d\n",ptElem[3].m_z, ptElem[iRetElem].m_z)); if ( ptElem[3].m_z > ptElem[iRetElem].m_z ) iRetElem = 3; //DEBUG_ERR(("fElem3 %d %d\n",ptElem[3].m_z, fElem[3])); continue; } rect.SetRect( pt.m_x - iDistance, pt.m_y - iDistance, pt.m_x + iDistance + 1, pt.m_y + iDistance + 1, pt.m_map); } } /*CPointMap a; a.m_z = maximum( // priority dynamic->multi->static->terrain int iRetElem; if (( ptElem[0].m_z >= ptElem[1].m_z ) && ( fElem[0] )) iRetElem = 0; else if (( ptElem[1].m_z >= ptElem[2].m_z ) && ( fElem[1] )) iRetElem = 1; else if (( ptElem[2].m_z >= ptElem[3].m_z ) && ( fElem[2] )) iRetElem = 2; else if ( fElem[3] ) iRetElem = 3; else iRetElem = 4;*/ ASSERT(iRetElem < COUNTOF(ptElem)); if ( 0 != iRetElem && ptElem[0].m_z > ptElem[iRetElem].m_z ) iRetElem = 4; else if ( 1 != iRetElem && ptElem[1].m_z > ptElem[iRetElem].m_z ) iRetElem = 4; else if ( 2 != iRetElem && ptElem[2].m_z > ptElem[iRetElem].m_z ) iRetElem = 4; else if ( 3 != iRetElem && ptElem[3].m_z > ptElem[iRetElem].m_z ) iRetElem = 4; //DEBUG_ERR(("iRetElem %d; %d %d %d %d; %d %d %d ISVALID: %d\n",iRetElem,ptElem[1].m_z,ptElem[2].m_z,ptElem[3].m_z,ptElem[4].m_z,pt.m_x,pt.m_y,pt.m_z,ptElem[iRetElem].IsValidPoint())); //DEBUG_ERR(("X: %d Y: %d Z: %d\n",ptElem[iRetElem].m_x,ptElem[iRetElem].m_y,ptElem[iRetElem].m_z)); return ( ptElem[iRetElem] ); #undef RESOURCE_Z_CHECK }
int CPathFinder::FindPath() //A* algorithm { ADDTOCALLSTACK("CPathFinder::FindPath"); ASSERT(m_pChar != NULL); signed short X = m_pChar->GetTopPoint().m_x - m_RealX; signed short Y = m_pChar->GetTopPoint().m_y - m_RealY; if ( X < 0 || Y < 0 || X > 23 || Y > 23 ) { //Too far away Clear(); return PATH_NONEXISTENT; } CPathFinderPointRef Start(m_Points[X][Y]); //Start point CPathFinderPointRef End(m_Points[m_Target.m_x][m_Target.m_y]); //End Point ASSERT(Start.m_Point); ASSERT(End.m_Point); Start.m_Point->GValue = 0; Start.m_Point->HValue = Heuristic(Start, End); Start.m_Point->FValue = Start.m_Point->HValue; m_Opened.push_back( Start ); std::list<CPathFinderPointRef> Children; CPathFinderPointRef Child, Current; std::deque<CPathFinderPointRef>::iterator InOpened, InClosed; while ( !m_Opened.empty() ) { std::sort(m_Opened.begin(), m_Opened.end()); Current = *m_Opened.begin(); m_Opened.pop_front(); m_Closed.push_back( Current ); if ( Current == End ) { CPathFinderPointRef PathRef = Current; while ( PathRef.m_Point->GetParent() ) //Rebuild path + save { PathRef.m_Point = const_cast<CPathFinderPoint*>(PathRef.m_Point->GetParent()); m_LastPath.push_front(CPointMap(PathRef.m_Point->m_x + m_RealX, PathRef.m_Point->m_y + m_RealY, 0, PathRef.m_Point->m_map)); } Clear(); return PATH_FOUND; } else { Children.clear(); GetChildren( Current, Children ); while ( !Children.empty() ) { Child = Children.front(); Children.pop_front(); InClosed = std::find( m_Closed.begin(), m_Closed.end(), Child ); InOpened = std::find( m_Opened.begin(), m_Opened.end(), Child ); if ( InClosed != m_Closed.end() ) continue; if ( InOpened == m_Opened.end() ) { Child.m_Point->SetParent( Current ); Child.m_Point->GValue = Current.m_Point->GValue; if ( Child.m_Point->m_x == Current.m_Point->m_x || Child.m_Point->m_y == Current.m_Point->m_y ) Child.m_Point->GValue += 10; //Not diagonal else Child.m_Point->GValue += 14; //Diagonal Child.m_Point->HValue = Heuristic( Child, End ); Child.m_Point->FValue = Child.m_Point->GValue + Child.m_Point->HValue; m_Opened.push_back( Child ); //sort ( m_Opened.begin(), m_Opened.end() ); } else { if ( Child.m_Point->GValue < Current.m_Point->GValue ) { Child.m_Point->SetParent( Current ); if ( Child.m_Point->m_x == Current.m_Point->m_x || Child.m_Point->m_y == Current.m_Point->m_y ) Child.m_Point->GValue += 10; else Child.m_Point->GValue += 14; Child.m_Point->FValue = Child.m_Point->GValue + Child.m_Point->HValue; //sort ( m_Opened.begin(), m_Opened.end() ); } } } } } Clear(); return PATH_NONEXISTENT; }
CPointMap CItemContainer::GetRandContainerLoc() const { ADDTOCALLSTACK("CItemContainer::GetRandContainerLoc"); // Max/Min Container Sizes. static const struct // we can probably get this from MUL file some place. { GUMP_TYPE m_gump; WORD m_minx; WORD m_miny; WORD m_maxx; WORD m_maxy; } sm_ContSize[] = { { GUMP_RESERVED, 40, 50, 100, 100 }, // default. { GUMP_CORPSE, 20, 85, 80, 185 }, { GUMP_PACK, 44, 65, 142, 150 }, // Open backpack { GUMP_BAG, 29, 34, 93, 119 }, // Leather Bag { GUMP_BARREL, 33, 36, 98, 139 }, // Barrel { GUMP_BASKET_SQ, 19, 47, 138, 114 }, // Square picknick Basket { GUMP_BOX_WOOD, 16, 51, 140, 115 }, // small wood box with a lock { GUMP_BASKET_RO, 33, 36, 98, 134 }, // Round Basket { GUMP_CHEST_GO_SI, 18, 105, 118, 169 }, // Gold and Silver Chest. { GUMP_BOX_WOOD_OR, 16, 51, 140, 115 }, // Small wood box (ornate)(no lock) { GUMP_CRATE, 20, 10, 126, 91 }, // Wood Crate { GUMP_DRAWER_DK, 16, 17, 110, 85 }, { GUMP_CHEST_WO_GO, 18, 105, 118, 169 }, // Wood with gold trim. { GUMP_CHEST_SI, 18, 105, 118, 169 }, // silver chest. { GUMP_BOX_GO_LO, 16, 51, 140, 115 }, // Gold/Brass box with a lock. { GUMP_SHIP_HOLD, 46, 74, 152, 175 }, { GUMP_BOOK_SHELF, 76, 12, 96, 59 }, { GUMP_CABINET_DK, 24, 96, 91, 143 }, { GUMP_CABINET_LT, 24, 96, 91, 143 }, { GUMP_DRAWER_LT, 16, 17, 110, 85 }, { GUMP_GIFT_BOX, 35, 10, 155, 85 }, { GUMP_ARMOIRE_RED, 10, 10, 150, 95 }, { GUMP_ARMOIRE_MAPLE, 10, 10, 150, 95 }, { GUMP_ARMOIRE_CHERRY, 10, 10, 150, 95 }, { GUMP_BASKET_TALL, 10, 10, 116, 71 }, { GUMP_CHEST_WOOD_PLAIN, 10, 10, 150, 95 }, { GUMP_CHEST_WOOD_GILDED, 10, 10, 150, 95 }, { GUMP_CHEST_WOOD_ORNATE, 10, 10, 150, 95 }, { GUMP_TALL_CABINET, 10, 10, 150, 95 }, { GUMP_CHEST_WOOD_FINISH, 10, 10, 150, 95 }, { GUMP_HEART_SHAPED, 56, 30, 102, 74}, { GUMP_SECURE_TRADE, 1, 1, 66, 26 }, { GUMP_GAME_BOARD, 4, 10, 220, 185 }, // Chess or checker board. { GUMP_GAME_BACKGAM, 4, 10, 220, 185 }, }; // ??? pItemDef->m_ttContainer.m_dwMinXY to m_dwMaxXY // Get a random location in the container. CItemBase * pItemDef = Item_GetDef(); GUMP_TYPE gump = pItemDef->IsTypeContainer(); // check for custom values in TDATA3/TDATA4 if ( pItemDef->m_ttContainer.m_dwMaxXY ) { int tmp_MinX = (pItemDef->m_ttContainer.m_dwMinXY & 0xFFFF0000) >> 16; int tmp_MinY = (pItemDef->m_ttContainer.m_dwMinXY & 0xFFFF); int tmp_MaxX = (pItemDef->m_ttContainer.m_dwMaxXY & 0xFFFF0000) >> 16; int tmp_MaxY = (pItemDef->m_ttContainer.m_dwMaxXY & 0xFFFF); DEBUG_WARN(("Custom container gump id %d for 0%x\n", gump, GetDispID())); return( CPointMap( static_cast<WORD>(tmp_MinX + Calc_GetRandVal(tmp_MaxX - tmp_MinX)), static_cast<WORD>(tmp_MinY + Calc_GetRandVal(tmp_MaxY - tmp_MinY)), 0 )); }