bool CChar::NPC_CheckWalkHere( const CPointBase & pt, const CRegionBase * pArea, WORD wBlockFlags ) const { ADDTOCALLSTACK("CChar::NPC_CheckWalkHere"); UNREFERENCED_PARAMETER(wBlockFlags); // Does the NPC want to walk here ? step on this item ? if ( !m_pNPC ) return false; if ( !pt.IsValidXY() ) return true; if ( m_pArea != NULL ) { if ( m_pNPC->m_Brain == NPCBRAIN_GUARD && !IsStatFlag(STATF_War) ) // guards will want to stay in guard range { if ( m_pArea->IsGuarded() && !pArea->IsGuarded() ) return false; } if ( Noto_IsCriminal() ) { if ( !m_pArea->IsGuarded() && pArea->IsGuarded() ) return false; } } // Is there a nasty object here that will hurt us ? CWorldSearch AreaItems(pt); for (;;) { CItem * pItem = AreaItems.GetItem(); if ( pItem == NULL ) break; if ( abs(pItem->GetTopZ() - pt.m_z) > 5 ) continue; switch ( pItem->GetType() ) { case IT_WEB: return (GetDispID() == CREID_GIANT_SPIDER) ? true : false; case IT_FIRE: return Can(CAN_C_FIRE_IMMUNE); case IT_TRAP: case IT_TRAP_ACTIVE: case IT_MOONGATE: case IT_TELEPAD: return false; default: break; } } return true; }
// timer expired, should I grow? bool CItem::Plant_OnTick() { ADDTOCALLSTACK("CItem::Plant_OnTick"); ASSERT(IsType(IT_CROPS) || IsType(IT_FOLIAGE)); // If it is in a container, kill it. if ( !IsTopLevel() ) return false; // Make sure the darn thing isn't moveable SetAttr(ATTR_MOVE_NEVER); Plant_SetTimer(); // No tree stuff below here if ( IsAttr(ATTR_INVIS) ) // if it's invis, take care of it here and return { SetHue(HUE_DEFAULT); ClrAttr(ATTR_INVIS); Update(); return true; } const CItemBase *pItemDef = Item_GetDef(); ITEMID_TYPE iGrowID = pItemDef->m_ttCrops.m_idGrow; if ( iGrowID == -1 ) { // Some plants generate a fruit on the ground when ripe. ITEMID_TYPE iFruitID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttCrops.m_idGrow)); if ( m_itCrop.m_ReapFruitID ) iFruitID = static_cast<ITEMID_TYPE>(RES_GET_INDEX(m_itCrop.m_ReapFruitID)); if ( !iFruitID ) return true; // Put a fruit on the ground if not already here. CWorldSearch AreaItems(GetTopPoint()); for (;;) { CItem *pItem = AreaItems.GetItem(); if ( !pItem ) { CItem *pItemFruit = CItem::CreateScript(iFruitID); ASSERT(pItemFruit); pItemFruit->MoveToDecay(GetTopPoint(), 10 * g_Cfg.m_iDecay_Item); break; } if ( pItem->IsType(IT_FRUIT) || pItem->IsType(IT_REAGENT_RAW) ) break; } // NOTE: ??? The plant should cycle here as well ! iGrowID = pItemDef->m_ttCrops.m_idReset; } if ( iGrowID ) { SetID(static_cast<ITEMID_TYPE>(RES_GET_INDEX(iGrowID))); Update(); return true; } // some plants go dormant again ? // m_itCrop.m_Fruit_ID = iTemp; return true; }
bool CChar::Use_Seed( CItem * pSeed, CPointMap * pPoint ) { ADDTOCALLSTACK("CChar::Use_Seed"); // Use the seed at the current point on the ground or some new point that i can touch. // IT_SEED from IT_FRUIT ASSERT(pSeed); CPointMap pt; if ( pPoint ) pt = *pPoint; else if ( pSeed->IsTopLevel() ) pt = pSeed->GetTopPoint(); else pt = GetTopPoint(); if ( !CanTouch(pt) ) { SysMessageDefault(DEFMSG_MSG_SEED_REACH); return false; } // is there soil here ? IT_DIRT if ( !IsPriv(PRIV_GM) && !g_World.IsItemTypeNear(pt, IT_DIRT, 0, false) ) { SysMessageDefault(DEFMSG_MSG_SEED_TARGSOIL); return(false); } const CItemBase *pItemDef = pSeed->Item_GetDef(); ITEMID_TYPE idReset = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttFruit.m_idReset)); if ( idReset == 0 ) { SysMessageDefault(DEFMSG_MSG_SEED_NOGOOD); return false; } // Already a plant here ? CWorldSearch AreaItems(pt); for (;;) { CItem *pItem = AreaItems.GetItem(); if ( !pItem ) break; if ( pItem->IsType(IT_TREE) || pItem->IsType(IT_FOLIAGE) ) // there's already a tree here { SysMessageDefault(DEFMSG_MSG_SEED_ATREE); return false; } if ( pItem->IsType(IT_CROPS) ) // there's already a plant here pItem->Delete(); } // plant it and consume the seed. CItem *pPlant = CItem::CreateScript(idReset, this); ASSERT(pPlant); pPlant->MoveToUpdate(pt); if ( pPlant->IsType(IT_CROPS) || pPlant->IsType(IT_FOLIAGE) ) { pPlant->m_itCrop.m_ReapFruitID = pSeed->GetID(); pPlant->Plant_CropReset(); } else { pPlant->SetDecayTime(10 * g_Cfg.m_iDecay_Item); } pSeed->ConsumeAmount(); return true; }
CItem * CWorld::CheckNaturalResource( const CPointMap & pt, IT_TYPE Type, bool fTest, CChar * pCharSrc ) { ADDTOCALLSTACK("CWorld::CheckNaturalResource"); // RETURN: // The resource tracking item. // NULL = nothing here. if ( !pt.IsValidPoint() ) return NULL; EXC_TRY("CheckNaturalResource"); // Check/Decrement natural resources at this location. // We create an invis object to time out and produce more. // RETURN: Quantity they wanted. 0 = none here. if ( fTest ) // Is the resource avail at all here ? { EXC_SET("is item near type"); if ((Type != IT_TREE) && (Type != IT_ROCK) ) { if ( !g_World.IsTypeNear_Top(pt, Type, 0) ) return NULL; } else { if ( !g_World.IsItemTypeNear(pt, Type, 0, false) ) //cannot be used, because it does no Z check... what if there is a static tile 70 tiles under me? return NULL; } } // Find the resource object. EXC_SET("find existant bit"); CItem * pResBit; CWorldSearch Area(pt); for (;;) { pResBit = Area.GetItem(); if ( !pResBit ) break; // NOTE: ??? Not all resource objects are world gems. should they be ? // I wanted to make tree stumps etc be the resource block some day. if ( pResBit->IsType(Type) && pResBit->GetID() == ITEMID_WorldGem ) break; } // If none then create one. if ( pResBit ) return pResBit; // What type of ore is here ? // NOTE: This is unrelated to the fact that we might not be skilled enough to find it. // Odds of a vein of ore being present are unrelated to my skill level. // Odds of my finding it are. // RES_REGIONRESOURCE from RES_REGIONTYPE linked to RES_AREA EXC_SET("get region"); CRegionWorld* pRegion = dynamic_cast<CRegionWorld*>( pt.GetRegion( REGION_TYPE_AREA )); if ( !pRegion ) return NULL; CWorldSearch AreaItems( pt ); AreaItems.SetAllShow(1); for (;;) { CItem *pItem = AreaItems.GetItem(); if ( !pItem ) break; if ( pItem->GetType() != Type ) return NULL; } // just use the background (default) region for this if ( pRegion->m_Events.GetCount() <= 0 ) { CPointMap ptZero(0,0,0,pt.m_map); pRegion = dynamic_cast<CRegionWorld*>(ptZero.GetRegion(REGION_TYPE_AREA)); } // Find RES_REGIONTYPE EXC_SET("resource group"); const CRandGroupDef * pResGroup = pRegion->FindNaturalResource(Type); if ( !pResGroup ) return NULL; // Find RES_REGIONRESOURCE EXC_SET("get random group element"); size_t id = pResGroup->GetRandMemberIndex(pCharSrc); CRegionResourceDef * pOreDef; if ( id == pResGroup->BadMemberIndex() ) { pOreDef = dynamic_cast <CRegionResourceDef *> (g_Cfg.ResourceGetDefByName(RES_REGIONRESOURCE, "mr_nothing")); } else { RESOURCE_ID rid = pResGroup->GetMemberID( id ); pOreDef = dynamic_cast <CRegionResourceDef *>( g_Cfg.ResourceGetDef( rid )); } if ( !pOreDef ) return NULL; EXC_SET("create bit"); pResBit = CItem::CreateScript(ITEMID_WorldGem, pCharSrc); if ( !pResBit ) return NULL; pResBit->SetType(Type); pResBit->SetAttr(ATTR_INVIS|ATTR_MOVE_NEVER); pResBit->m_itResource.m_rid_res = pOreDef->GetResourceID(); // Total amount of ore here. int amount = pOreDef->m_Amount.GetRandom(); if ( Type == IT_ROCK && g_Cfg.m_iFeatureML & FEATURE_ML_RACIAL_BONUS && pCharSrc->IsHuman() && pCharSrc->GetTopMap() == 0 ) amount += 1; // Workhorse racial bonus, giving +1 ore to humans in Felucca. if ( Type == IT_TREE && g_Cfg.m_iFeatureML & FEATURE_ML_RACIAL_BONUS && pCharSrc->IsHuman() && pCharSrc->GetTopMap() == 1 ) amount += 2; // Workhorse racial bonus, giving +2 logs to humans in Trammel. pResBit->SetAmount( amount ); pResBit->MoveToDecay(pt, pOreDef->m_iRegenerateTime.GetRandom() * TICK_PER_SEC); // Delete myself in this amount of time. EXC_SET("resourcefound"); if ( pCharSrc != NULL) { CScriptTriggerArgs Args(0, 0, pResBit); TRIGRET_TYPE tRet = TRIGRET_RET_DEFAULT; if ( IsTrigUsed(TRIGGER_REGIONRESOURCEFOUND) ) tRet = pCharSrc->OnTrigger(CTRIG_RegionResourceFound, pCharSrc, &Args); if ( IsTrigUsed(TRIGGER_RESOURCEFOUND) ) tRet = pOreDef->OnTrigger("@ResourceFound", pCharSrc, &Args); if (tRet == TRIGRET_RET_TRUE) { if ( pResBit->IsDisconnected() ) return NULL; pResBit->SetAmount(0); } } return pResBit; EXC_CATCH; EXC_DEBUG_START; g_Log.EventDebug("point '%d,%d,%d,%d' type '%d' [0%lx]\n", pt.m_x, pt.m_y, pt.m_z, pt.m_map, static_cast<int>(Type), pCharSrc ? static_cast<DWORD>(pCharSrc->GetUID()) : 0); EXC_DEBUG_END; return NULL; }
TRIGRET_TYPE CScriptObj::OnTriggerForLoop( CScript &s, int iType, CTextConsole * pSrc, CScriptTriggerArgs * pArgs, CGString * pResult ) { // loop from start here to the ENDFOR // See WebPageScriptList for dealing with Arrays. CScriptLineContext StartContext = s.GetContext(); CScriptLineContext EndContext = StartContext; int LoopsMade = 0; if ( iType & 8 ) // WHILE { TCHAR * pszCond; TCHAR *pszOrig = Str_GetTemp(); TCHAR *pszTemp = Str_GetTemp(); int iWhile = 0; strcpy( pszOrig, s.GetArgStr() ); while(true) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; pArgs->m_VarsLocal.SetNum( "_WHILE", iWhile, false ); iWhile++; strcpy( pszTemp, pszOrig ); pszCond = pszTemp; ParseText( pszCond, pSrc, 0, pArgs ); if ( !Exp_GetVal( pszCond ) ) break; TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } } else ParseText( s.GetArgStr(), pSrc, 0, pArgs ); if ( iType & 4 ) // FOR { int fCountDown = FALSE; int iMin = 0; int iMax = 0; int i; TCHAR * ppArgs[3]; int iQty = Str_ParseCmds( s.GetArgStr(), ppArgs, 3, ", " ); CGString sLoopVar = "_FOR"; switch( iQty ) { case 1: // FOR x iMin = 1; iMax = Exp_GetSingle( ppArgs[0] ); break; case 2: if ( isdigit( *ppArgs[0] ) ) { iMin = Exp_GetSingle( ppArgs[0] ); iMax = Exp_GetSingle( ppArgs[1] ); } else { iMin = 1; iMax = Exp_GetSingle( ppArgs[1] ); sLoopVar = ppArgs[0]; } break; case 3: sLoopVar = ppArgs[0]; iMin = Exp_GetSingle( ppArgs[1] );; iMax = Exp_GetSingle( ppArgs[2] ); break; default: iMin = iMax = 1; break; } if ( iMin > iMax ) fCountDown = true; if ( fCountDown ) for ( i = iMin; i >= iMax; --i ) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; pArgs->m_VarsLocal.SetNum( sLoopVar, i, false ); TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } else for ( i = iMin; i <= iMax; ++i ) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; pArgs->m_VarsLocal.SetNum( sLoopVar, i, false ); TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } } if ( (iType & 1) || (iType & 2) ) { int iDist; if ( s.HasArgs() ) iDist = s.GetArgVal(); else iDist = UO_MAP_VIEW_SIZE; CObjBaseTemplate * pObj = dynamic_cast <CObjBaseTemplate *>(this); if ( pObj == NULL ) { iType = 0; DEBUG_ERR(( "FOR Loop trigger on non-world object '%s'\n", GetName())); } CObjBaseTemplate * pObjTop = pObj->GetTopLevelObj(); CPointMap pt = pObjTop->GetTopPoint(); if ( iType & 1 ) // FORITEM, FOROBJ { CWorldSearch AreaItems( pt, iDist ); while(true) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; CItem * pItem = AreaItems.GetItem(); if ( pItem == NULL ) break; TRIGRET_TYPE iRet = pItem->OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } } if ( iType & 2 ) // FORCHAR, FOROBJ { CWorldSearch AreaChars( pt, iDist ); while(true) { LoopsMade++; if ( g_Cfg.m_iMaxLoopTimes && ( LoopsMade >= g_Cfg.m_iMaxLoopTimes )) goto toomanyloops; CChar * pChar = AreaChars.GetChar(); if ( pChar == NULL ) break; if ( ( iType & 0x10 ) && ( ! pChar->IsClient() ) ) // FORCLIENTS continue; if ( ( iType & 0x20 ) && ( pChar->m_pPlayer == NULL ) ) // FORPLAYERS continue; TRIGRET_TYPE iRet = pChar->OnTriggerRun( s, TRIGRUN_SECTION_TRUE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } EndContext = s.GetContext(); s.SeekContext( StartContext ); } } } if ( g_Cfg.m_iMaxLoopTimes ) { toomanyloops: if ( LoopsMade >= g_Cfg.m_iMaxLoopTimes ) { g_Log.EventError("Terminating loop cycle since it seems being dead-locked (%d iterations already passed)" DEBUG_CR, LoopsMade); } } if ( EndContext.m_lOffset <= StartContext.m_lOffset ) { // just skip to the end. TRIGRET_TYPE iRet = OnTriggerRun( s, TRIGRUN_SECTION_FALSE, pSrc, pArgs, pResult ); if ( iRet != TRIGRET_ENDIF ) { return( iRet ); } } else { s.SeekContext( EndContext ); } return( TRIGRET_ENDIF ); }
bool CChar::CanSeeLOS_New( const CPointMap &ptDst, CPointMap *pptBlock, int iMaxDist, word flags, bool bCombatCheck ) const { ADDTOCALLSTACK("CChar::CanSeeLOS_New"); // WARNING: CanSeeLOS is an expensive function (lot of calculations but most importantly it has to read the UO files, and file I/O is slow). if ( !bCombatCheck && IsPriv(PRIV_GM) ) // If i'm checking the LOS during a combat, i don't want to shoot through the walls even if i'm a GM { WARNLOS(("GM Pass\n")); return true; } CPointMap ptSrc = GetTopPoint(); CPointMap ptNow(ptSrc); if ( ptSrc.m_map != ptDst.m_map ) // Different map return this->CanSeeLOS_New_Failed(pptBlock, ptNow); if ( ptSrc == ptDst ) // Same point ^^ return true; short iTotalZ = ptSrc.m_z + GetHeightMount(true); ptSrc.m_z = (char)minimum(iTotalZ, UO_SIZE_Z); //true - substract one from the height because of eyes height WARNLOS(("Total Z: %d\n", ptSrc.m_z)); int dx, dy, dz; dx = ptDst.m_x - ptSrc.m_x; dy = ptDst.m_y - ptSrc.m_y; dz = ptDst.m_z - ptSrc.m_z; float dist2d, dist3d; dist2d = sqrt((float)(dx*dx + dy*dy)); if ( dz ) dist3d = sqrt((float)(dist2d*dist2d + dz*dz)); else dist3d = dist2d; if ( APPROX(dist2d) > (float)iMaxDist ) { WARNLOS(("( APPROX(dist2d)(%f) > ((double)iMaxDist)(%f) ) --> NOLOS\n", APPROX(dist2d), (float)iMaxDist)); return CanSeeLOS_New_Failed(pptBlock, ptNow); } float dFactorX, dFactorY, dFactorZ; dFactorX = dx / dist3d; dFactorY = dy / dist3d; dFactorZ = dz / dist3d; float nPx, nPy, nPz; nPx = ptSrc.m_x; nPy = ptSrc.m_y; nPz = ptSrc.m_z; std::vector<CPointMap> path; for (;;) { if ( BETWEENPOINT(nPx, ptDst.m_x, ptSrc.m_x) && BETWEENPOINT(nPy, ptDst.m_y, ptSrc.m_y) && BETWEENPOINT(nPz, ptDst.m_z, ptSrc.m_z) ) { dx = (int)APPROX(nPx); dy = (int)APPROX(nPy); dz = (int)APPROX(nPz); // Add point to vector if ( !path.empty() ) { CPointMap ptEnd = path[path.size() - 1]; if ( ptEnd.m_x != dx || ptEnd.m_y != dy || ptEnd.m_z != dz ) path.emplace_back((word)dx, (word)dy, (char)dz, ptSrc.m_map); } else { path.emplace_back((word)dx, (word)dy, (char)dz, ptSrc.m_map); } WARNLOS(("PATH X:%d Y:%d Z:%d\n", dx, dy, dz)); nPx += dFactorX; nPy += dFactorY; nPz += dFactorZ; } else break; } if ( !path.empty() ) { if ( path[path.size() - 1] != ptDst ) path.emplace_back(ptDst.m_x, ptDst.m_y, ptDst.m_z, ptDst.m_map); } else { path.clear(); return CanSeeLOS_New_Failed(pptBlock, ptNow); } WARNLOS(("Path calculated %" PRIuSIZE_T "\n", path.size())); // Ok now we should loop through all the points and checking for maptile, staticx, items, multis. // If something is in the way and it has the wrong flags LOS return false const CServerMapBlock *pBlock = nullptr; // Block of the map (for statics) const CUOStaticItemRec *pStatic = nullptr; // Statics iterator (based on SphereMapBlock) const CSphereMulti *pMulti = nullptr; // Multi Def (multi check) const CUOMultiItemRec_HS *pMultiItem = nullptr; // Multi item iterator CRegion *pRegion = nullptr; // Nulti regions CRegionLinks rlinks; // Links to multi regions CItem *pItem = nullptr; CItemBase *pItemDef = nullptr; CItemBaseDupe *pDupeDef = nullptr; dword wTFlags = 0; height_t Height = 0; word terrainid = 0; bool bPath = true; bool bNullTerrain = false; CRegion *pSrcRegion = ptSrc.GetRegion(REGION_TYPE_AREA|REGION_TYPE_ROOM|REGION_TYPE_MULTI); CRegion *pNowRegion = nullptr; int lp_x = 0, lp_y = 0; short min_z = 0, max_z = 0; for (uint i = 0, pathSize = uint(path.size()); i < pathSize; lp_x = ptNow.m_x, lp_y = ptNow.m_y, pItemDef = nullptr, pStatic = nullptr, pMulti = nullptr, pMultiItem = nullptr, min_z = 0, max_z = 0, ++i ) { ptNow = path[i]; WARNLOS(("---------------------------------------------\n")); WARNLOS(("Point %d,%d,%d \n", ptNow.m_x, ptNow.m_y, ptNow.m_z)); pNowRegion = ptNow.GetRegion(REGION_TYPE_AREA|REGION_TYPE_ROOM|REGION_TYPE_MULTI); if ( (flags & LOS_NO_OTHER_REGION) && (pSrcRegion != pNowRegion) ) { WARNLOS(("flags & 0200 and path is leaving my region - BLOCK\n")); bPath = false; break; } if ( (flags & LOS_NC_MULTI) && ptNow.GetRegion(REGION_TYPE_MULTI) && (ptNow.GetRegion(REGION_TYPE_MULTI) != ptSrc.GetRegion(REGION_TYPE_MULTI)) ) { WARNLOS(("flags & 0400 and path is crossing another multi - BLOCK\n")); bPath = false; break; } if ( (lp_x != ptNow.m_x) || (lp_y != ptNow.m_y) ) { WARNLOS(("\tLoading new map block.\n")); pBlock = g_World.GetMapBlock(ptNow); } if ( !pBlock ) // something is wrong { WARNLOS(("GetMapBlock Failed\n")); bPath = false; break; } if ( !(flags & LOS_NB_TERRAIN) ) { if ( !((flags & LOS_NB_LOCAL_TERRAIN) && (pSrcRegion == pNowRegion)) ) { // ------ MapX.mul Check ---------- terrainid = pBlock->GetTerrain(UO_BLOCK_OFFSET(ptNow.m_x), UO_BLOCK_OFFSET(ptNow.m_y))->m_wTerrainIndex; WARNLOS(("Terrain %d\n", terrainid)); if ( (flags & LOS_FISHING) && (ptSrc.GetDist(ptNow) >= 2) && (g_World.GetTerrainItemType(terrainid) != IT_WATER) && (g_World.GetTerrainItemType(terrainid) != IT_NORMAL) ) { WARNLOS(("Terrain %d blocked - flags & LOS_FISHING, distance >= 2 and type of pItemDef is not IT_WATER\n", terrainid)); WARNLOS(("ptSrc: %d,%d,%d; ptNow: %d,%d,%d; terrainid: %d; terrainid type: %d\n", ptSrc.m_x, ptSrc.m_y, ptSrc.m_z, ptNow.m_x, ptNow.m_y, ptNow.m_z, terrainid, g_World.GetTerrainItemType(terrainid))); bPath = false; break; } //#define MAPTILEMIN minimum(minimum(minimum(pBlock->GetTerrain(0,0)->m_z, pBlock->GetTerrain(0,1)->m_z), pBlock->GetTerrain(1,0)->m_z), pBlock->GetTerrain(1,1)->m_z) //#define MAPTILEMAX maximum(maximum(maximum(pBlock->GetTerrain(0,0)->m_z, pBlock->GetTerrain(0,1)->m_z), pBlock->GetTerrain(1,0)->m_z), pBlock->GetTerrain(1,1)->m_z); //#define MAPTILEZ pBlock->GetTerrain(UO_BLOCK_OFFSET(ptNow.m_x), UO_BLOCK_OFFSET(ptNow.m_y))->m_z; if ( (terrainid != TERRAIN_HOLE) && (terrainid != 475) ) { if ( terrainid < 430 || terrainid > 437 ) { /*this stuff should do some checking for surrounding items: aaa aXa aaa min_z is determined as a minimum of all a/X terrain, where X is ptNow */ byte pos_x = UO_BLOCK_OFFSET(ptNow.m_x) > 1 ? UO_BLOCK_OFFSET(ptNow.m_x - 1) : 0; byte pos_y = UO_BLOCK_OFFSET(ptNow.m_y) > 1 ? UO_BLOCK_OFFSET(ptNow.m_y - 1) : 0; const byte defx = UO_BLOCK_OFFSET(ptNow.m_x); const byte defy = UO_BLOCK_OFFSET(ptNow.m_y); min_z = pBlock->GetTerrain(pos_x, pos_y)->m_z; max_z = pBlock->GetTerrain(defx, defy)->m_z; for ( byte posy = pos_y; (abs(defx - UO_BLOCK_OFFSET(pos_x)) <= 1 && pos_x <= 7); ++pos_x ) { for ( pos_y = posy; (abs(defy - UO_BLOCK_OFFSET(pos_y)) <= 1 && pos_y <= 7); ++pos_y ) { char terrain_z = pBlock->GetTerrain(pos_x, pos_y)->m_z; min_z = minimum(min_z, terrain_z); } } //min_z = MAPTILEZ; //max_z = MAPTILEZ; WARNLOS(("Terrain %d - m:%d M:%d\n", terrainid, min_z, max_z)); if ( CUOMapMeter::IsTerrainNull(terrainid) ) bNullTerrain = true; //what if there are some items on that hole? if ( (min_z <= ptNow.m_z && max_z >= ptNow.m_z) && (ptNow.m_x != ptDst.m_x || ptNow.m_y != ptDst.m_y || min_z > ptDst.m_z || max_z < ptDst.m_z) ) { WARNLOS(("Terrain %d - m:%d M:%d - block\n", terrainid, min_z, max_z)); bPath = false; break; } CUOTerrainInfo land(terrainid); if ( (land.m_flags & UFLAG1_WATER) && (flags & LOS_NC_WATER) ) bNullTerrain = true; } } //#undef MAPTILEMIN //#undef MAPTILEMAX //#undef MAPTILEZ } } // ------ StaticsX.mul Check -------- if ( !(flags & LOS_NB_STATIC) ) { if ( !((flags & LOS_NB_LOCAL_STATIC) && (pSrcRegion == pNowRegion)) ) { uint uiStaticMaxQty = pBlock->m_Statics.GetStaticQty(); for ( uint s = 0; s < uiStaticMaxQty; pStatic = nullptr, pItemDef = nullptr, ++s ) { pStatic = pBlock->m_Statics.GetStatic(s); if ( (pStatic->m_x + pBlock->m_x != ptNow.m_x) || (pStatic->m_y + pBlock->m_y != ptNow.m_y) ) continue; //Fix for Stacked items blocking view if ( (pStatic->m_x == ptDst.m_x) && (pStatic->m_y == ptDst.m_y) && (pStatic->m_z >= GetTopZ()) && (pStatic->m_z <= ptSrc.m_z) ) continue; pItemDef = CItemBase::FindItemBase(pStatic->GetDispID()); wTFlags = 0; Height = 0; bNullTerrain = false; if ( !pItemDef ) { WARNLOS(("STATIC - Cannot get pItemDef for item (0%x)\n", pStatic->GetDispID())); } else { if (pItemDef->Can(CAN_I_BLOCKLOS)) { WARNLOS(("pStatic blocked by CAN_I_BLOCKLOS")); bPath = false; break; } if ( (flags & LOS_FISHING) && (ptSrc.GetDist(ptNow) >= 2) && (pItemDef->GetType() != IT_WATER) && ( pItemDef->Can(CAN_I_DOOR | CAN_I_PLATFORM | CAN_I_BLOCK | CAN_I_CLIMB | CAN_I_FIRE | CAN_I_ROOF | CAN_I_BLOCKLOS | CAN_I_BLOCKLOS_HEIGHT)) ) { WARNLOS(("pStatic blocked - flags & 0800, distance >= 2 and type of pItemDef is not IT_WATER\n")); bPath = false; break; } wTFlags = pItemDef->GetTFlags(); Height = pItemDef->GetHeight(); if ( pItemDef->GetID() != pStatic->GetDispID() ) //not a parent item { WARNLOS(("Not a parent item (STATIC)\n")); pDupeDef = CItemBaseDupe::GetDupeRef((ITEMID_TYPE)(pStatic->GetDispID())); if ( !pDupeDef ) { g_Log.EventDebug("AdvancedLoS: Failed to get non-parent reference (static) (DispID 0%x) (X: %d Y: %d Z: %hhd M: %hhu)\n", pStatic->GetDispID(), ptNow.m_x, ptNow.m_y, pStatic->m_z, ptNow.m_map); } else { wTFlags = pDupeDef->GetTFlags(); Height = pDupeDef->GetHeight(); } } else { WARNLOS(("Parent item (STATIC)\n")); } Height = (wTFlags & UFLAG2_CLIMBABLE) ? Height / 2 : Height; if ( ((wTFlags & (UFLAG1_WALL|UFLAG1_BLOCK|UFLAG2_PLATFORM)) || (pItemDef->Can(CAN_I_BLOCKLOS_HEIGHT))) && !((wTFlags & UFLAG2_WINDOW) && (flags & LOS_NB_WINDOWS)) ) { WARNLOS(("pStatic %0x %d,%d,%d - %d\n", pStatic->GetDispID(), pStatic->m_x, pStatic->m_y, pStatic->m_z, Height)); min_z = pStatic->m_z; max_z = minimum(Height + min_z, UO_SIZE_Z); WARNLOS(("wTFlags(0%x)\n", wTFlags)); WARNLOS(("pStatic %0x Z check: %d,%d (Now: %d) (Dest: %d).\n", pStatic->GetDispID(), min_z, max_z, ptNow.m_z, ptDst.m_z)); if ( (min_z <= ptNow.m_z) && (max_z >= ptNow.m_z) ) { if ( ptNow.m_x != ptDst.m_x || ptNow.m_y != ptDst.m_y || min_z > ptDst.m_z || max_z < ptDst.m_z ) { WARNLOS(("pStatic blocked - m:%d M:%d\n", min_z, max_z)); bPath = false; break; } } } } } } } if ( !bPath ) break; // --------- In game items ---------- if ( !(flags & LOS_NB_DYNAMIC) ) { if ( !((flags & LOS_NB_LOCAL_DYNAMIC) && (pSrcRegion == pNowRegion)) ) { CWorldSearch AreaItems(ptNow, 0); for (;;) { pItem = AreaItems.GetItem(); if ( !pItem ) break; if ( pItem->GetUnkPoint().m_x != ptNow.m_x || pItem->GetUnkPoint().m_y != ptNow.m_y ) continue; if ( !CanSeeItem(pItem) ) continue; //Fix for Stacked items blocking view if ( (pItem->GetUnkPoint().m_x == ptDst.m_x) && (pItem->GetUnkPoint().m_y == ptDst.m_y) && (pItem->GetUnkPoint().m_z >= GetTopZ()) && (pItem->GetUnkPoint().m_z <= ptSrc.m_z) ) continue; pItemDef = static_cast<CItemBase*>(pItem->Base_GetDef()); wTFlags = 0; Height = 0; bNullTerrain = false; if ( !pItemDef ) { WARNLOS(("DYNAMIC - Cannot get pItemDef for item (0%x)\n", pItem->GetDispID())); } else { if (pItem->Can(CAN_I_BLOCKLOS)) { WARNLOS(("pItem blocked by CAN_I_BLOCKLOS")); bPath = false; break; } if ( (flags & LOS_FISHING) && (ptSrc.GetDist(ptNow) >= 2) && (pItem->GetType() != IT_WATER) && ( pItem->Can(CAN_I_DOOR | CAN_I_PLATFORM | CAN_I_BLOCK | CAN_I_CLIMB | CAN_I_FIRE | CAN_I_ROOF | CAN_I_BLOCKLOS | CAN_I_BLOCKLOS_HEIGHT) ) ) { WARNLOS(("pItem blocked - flags & 0800, distance >= 2 and type of pItemDef is not IT_WATER\n")); bPath = false; break; //return CanSeeLOS_New_Failed(pptBlock, ptNow); } wTFlags = pItemDef->GetTFlags(); Height = pItemDef->GetHeight(); if ( pItemDef->GetID() != pItem->GetDispID() ) //not a parent item { WARNLOS(("Not a parent item (DYNAMIC)\n")); pDupeDef = CItemBaseDupe::GetDupeRef((ITEMID_TYPE)(pItem->GetDispID())); if ( !pDupeDef ) { // Not an error: i have changed the DISPID of the item. CItemBase* pParentDef = CItemBase::FindItemBase(pItem->GetDispID()); if (pParentDef) { wTFlags = pParentDef->GetTFlags(); Height = pParentDef->GetHeight(); } else g_Log.EventDebug("AdvancedLoS: Failed to get reference (dynamic): non-dupe, baseless dispid (DispID 0%x) (X: %d Y: %d Z: %hhd M: %hhu)\n", pItem->GetDispID(), ptNow.m_x, ptNow.m_y, pItem->GetUnkZ(), ptNow.m_map); } else { // It's a dupe item wTFlags = pDupeDef->GetTFlags(); Height = pDupeDef->GetHeight(); } } else { WARNLOS(("Parent item (DYNAMIC)\n")); } Height = (wTFlags & UFLAG2_CLIMBABLE) ? Height / 2 : Height; if ( ((wTFlags & (UFLAG1_WALL|UFLAG1_BLOCK|UFLAG2_PLATFORM)) || pItem->Can(CAN_I_BLOCKLOS_HEIGHT)) && !((wTFlags & UFLAG2_WINDOW) && (flags & LOS_NB_WINDOWS)) ) { WARNLOS(("pItem %0x(%0x) %d,%d,%d - %d\n", (dword)pItem->GetUID(), pItem->GetDispID(), pItem->GetUnkPoint().m_x, pItem->GetUnkPoint().m_y, pItem->GetUnkPoint().m_z, Height)); min_z = pItem->GetUnkPoint().m_z; max_z = minimum(Height + min_z, UO_SIZE_Z); WARNLOS(("wTFlags(0%x)\n", wTFlags)); WARNLOS(("pItem %0x(%0x) Z check: %d,%d (Now: %d) (Dest: %d).\n", (dword)pItem->GetUID(), pItem->GetDispID(), min_z, max_z, ptNow.m_z, ptDst.m_z)); if ( min_z <= ptNow.m_z && max_z >= ptNow.m_z ) { if ( ptNow.m_x != ptDst.m_x || ptNow.m_y != ptDst.m_y || min_z > ptDst.m_z || max_z < ptDst.m_z ) { WARNLOS(("pItem blocked - m:%d M:%d\n", min_z, max_z)); bPath = false; break; } } } } } } } if ( !bPath ) break; // ----------- Multis --------------- if ( !(flags & LOS_NB_MULTI) ) { if ( !((flags & LOS_NB_LOCAL_MULTI) && (pSrcRegion == pNowRegion)) ) { size_t iQtyr = ptNow.GetRegions(REGION_TYPE_MULTI, &rlinks); if ( iQtyr > 0 ) { for ( size_t ii = 0; ii < iQtyr; pMulti = nullptr, ++ii, pItem = nullptr, pRegion = nullptr ) { pRegion = rlinks[ii]; if ( pRegion ) pItem = pRegion->GetResourceID().ItemFindFromResource(); if ( !pItem ) continue; pMulti = g_Cfg.GetMultiItemDefs(pItem); if ( !pMulti ) continue; uint iQty = pMulti->GetItemCount(); for ( uint iii = 0; iii < iQty; pItemDef = nullptr, pMultiItem = nullptr, ++iii ) { pMultiItem = pMulti->GetItem(iii); if ( !pMultiItem ) break; if ( !pMultiItem->m_visible ) continue; if ( (pMultiItem->m_dx + pItem->GetTopPoint().m_x != ptNow.m_x) || (pMultiItem->m_dy + pItem->GetTopPoint().m_y != ptNow.m_y) ) continue; pItemDef = CItemBase::FindItemBase(pMultiItem->GetDispID()); wTFlags = 0; Height = 0; bNullTerrain = false; if ( !pItemDef ) { WARNLOS(("MULTI - Cannot get pItemDef for item (0%x)\n", pMultiItem->GetDispID())); } else { if (pItemDef->Can(CAN_I_BLOCKLOS)) { WARNLOS(("pMultiItem blocked by CAN_I_BLOCKLOS")); bPath = false; break; } if ( (flags & LOS_FISHING) && (ptSrc.GetDist(ptNow) >= 2) && (pItemDef->GetType() != IT_WATER) && ( pItemDef->Can(CAN_I_DOOR | CAN_I_PLATFORM | CAN_I_BLOCK | CAN_I_CLIMB | CAN_I_FIRE | CAN_I_ROOF | CAN_I_BLOCKLOS | CAN_I_BLOCKLOS_HEIGHT) ) ) { WARNLOS(("pMultiItem blocked - flags & 0800, distance >= 2 and type of pItemDef is not IT_WATER\n")); bPath = false; break; //return CanSeeLOS_New_Failed(pptBlock, ptNow); } wTFlags = pItemDef->GetTFlags(); Height = pItemDef->GetHeight(); if ( pItemDef->GetID() != pMultiItem->GetDispID() ) //not a parent item { WARNLOS(("Not a parent item (MULTI)\n")); pDupeDef = CItemBaseDupe::GetDupeRef((ITEMID_TYPE)(pMultiItem->GetDispID())); if ( !pDupeDef ) { g_Log.EventDebug("AdvancedLoS: Failed to get non-parent reference (multi) (DispID 0%x) (X: %d Y: %d Z: %hhd M: %hhu)\n", pMultiItem->GetDispID(), ptNow.m_x, ptNow.m_y, pMultiItem->m_dz + pItem->GetTopPoint().m_z, ptNow.m_map); } else { wTFlags = pDupeDef->GetTFlags(); Height = pDupeDef->GetHeight(); } } else { WARNLOS(("Parent item (MULTI)\n")); } Height = (wTFlags & UFLAG2_CLIMBABLE) ? Height / 2 : Height; if ( ((wTFlags & (UFLAG1_WALL|UFLAG1_BLOCK|UFLAG2_PLATFORM) || pItemDef->Can(CAN_I_BLOCKLOS_HEIGHT))) && !((wTFlags & UFLAG2_WINDOW) && (flags & LOS_NB_WINDOWS)) ) { WARNLOS(("pMultiItem %0x %d,%d,%d - %d\n", pMultiItem->GetDispID(), pMultiItem->m_dx, pMultiItem->m_dy, pMultiItem->m_dz, Height)); min_z = (char)(pMultiItem->m_dz) + pItem->GetTopPoint().m_z; max_z = minimum(Height + min_z, UO_SIZE_Z); WARNLOS(("wTFlags(0%x)\n", wTFlags)); if ( min_z <= ptNow.m_z && max_z >= ptNow.m_z ) { if ( ptNow.m_x != ptDst.m_x || ptNow.m_y != ptDst.m_y || min_z > ptDst.m_z || max_z < ptDst.m_z ) { WARNLOS(("pMultiItem blocked - m:%d M:%d\n", min_z, max_z)); bPath = false; break; } } } } } if ( !bPath ) break; } } } } if ( bNullTerrain ) bPath = false; if ( !bPath ) break; } path.clear(); if ( !bPath ) return CanSeeLOS_New_Failed(pptBlock, ptNow); return true; }
void CItem::Spawn_GenerateItem( CResourceDef * pDef ) { // Count how many items are here already. // This could be in a container. RESOURCE_ID_BASE rid = pDef->GetResourceID(); ITEMID_TYPE id = (ITEMID_TYPE) rid.GetResIndex(); int iDistMax = m_itSpawnItem.m_DistMax; int iAmountPile = m_itSpawnItem.m_pile; int iCount = 0; CItemContainer * pCont = dynamic_cast <CItemContainer *>( GetParent()); if ( pCont != NULL ) { iCount = pCont->ContentCount( rid ); } else { // If is equipped this will produce the item where you are standing. CPointMap pt = GetTopLevelObj()->GetTopPoint(); CWorldSearch AreaItems( pt, iDistMax ); while (true) { CItem * pItem = AreaItems.GetItem(); if ( pItem == NULL ) break; if ( pItem->IsType(IT_SPAWN_ITEM)) continue; if ( pItem->IsAttr( ATTR_INVIS )) continue; if ( pItem->GetID() != id ) continue; // if ( pItem->m_uidLink != GetUID()) continue; iCount += pItem->GetAmount(); } } if ( iCount >= GetAmount()) return; CItem * pItem = CreateTemplate( id ); if ( pItem == NULL ) return; pItem->SetAttr( m_Attr & ( ATTR_OWNED | ATTR_MOVE_ALWAYS )); if ( iAmountPile > 1 ) { CItemBase * pItemDef = pItem->Item_GetDef(); ASSERT(pItemDef); if ( pItemDef->IsStackableType()) { if ( iAmountPile == 0 || iAmountPile > GetAmount()) iAmountPile = GetAmount(); pItem->SetAmount( Calc_GetRandVal(iAmountPile) + 1 ); } } // pItem->m_uidLink = GetUID(); // This might be dangerous ? pItem->SetDecayTime( g_Cfg.m_iDecay_Item ); // It will decay eventually to be replaced later. pItem->MoveNearObj( this, iDistMax ); }
bool CWorld::Export( lpctstr pszFilename, const CChar * pSrc, word wModeFlags, int iDist, int dx, int dy ) { ADDTOCALLSTACK("CWorld::Export"); // wModeFlags = IMPFLAGS_TYPE // Just get the items in the local area to export. // dx = change in x from world to file. // dy = change in y if ( pSrc == NULL ) return false; size_t iLen = strlen( pszFilename ); if ( iLen <= 4 ) return false; CScript s; if ( ! s.Open( pszFilename, OF_WRITE|OF_TEXT|OF_DEFAULTMODE )) return false; if ( wModeFlags & IMPFLAGS_RELATIVE ) { dx -= pSrc->GetTopPoint().m_x; dy -= pSrc->GetTopPoint().m_y; } if ( ! strcmpi( pszFilename + (iLen - 4), ".WSC" )) { // Export as UOX format. for world forge stuff. int index = 0; CWorldSearch AreaItems( pSrc->GetTopPoint(), iDist ); AreaItems.SetSearchSquare(true); for (;;) { CItem * pItem = AreaItems.GetItem(); if ( pItem == NULL ) break; pItem->WriteUOX( s, index++ ); } return true; } // (???NPC) Chars and the stuff they are carrying. if ( wModeFlags & IMPFLAGS_CHARS ) { CWorldSearch AreaChars( pSrc->GetTopPoint(), iDist ); AreaChars.SetSearchSquare(true); AreaChars.SetAllShow( pSrc->IsPriv( PRIV_ALLSHOW )); // show logged out chars? for (;;) { CChar * pChar = AreaChars.GetChar(); if ( pChar == NULL ) break; pChar->r_WriteSafe( s ); } } if ( wModeFlags & IMPFLAGS_ITEMS ) { // Items on the ground. CWorldSearch AreaItems( pSrc->GetTopPoint(), iDist ); AreaItems.SetSearchSquare(true); AreaItems.SetAllShow( pSrc->IsPriv( PRIV_ALLSHOW )); // show logged out chars? for (;;) { CItem * pItem = AreaItems.GetItem(); if ( pItem == NULL ) break; pItem->r_WriteSafe( s ); } } return true; }
void CImportFile::ImportFix() { ADDTOCALLSTACK("CImportFile::ImportFix"); // adjust all the containered items and eliminate duplicates. CheckLast(); int iRemoved = 0; CImportSer * pSerNext; m_pCurSer = static_cast <CImportSer*> ( m_ListSer.GetHead()); for ( ; m_pCurSer != NULL; m_pCurSer = pSerNext ) { pSerNext = static_cast <CImportSer*> ( m_pCurSer->GetNext()); if ( m_pCurSer->m_pObj == NULL ) // NEver created correctly { delete m_pCurSer; continue; } // Make sure this item is not a dupe ? CItem * pItemTest; if ( m_pCurSer->IsTopLevel()) // top level only { if ( m_pCurSer->m_pObj->IsItem()) { CItem * pItemCheck = dynamic_cast <CItem*>( m_pCurSer->m_pObj ); ASSERT(pItemCheck); pItemCheck->SetAttr(ATTR_MOVE_NEVER); CWorldSearch AreaItems( m_pCurSer->m_pObj->GetTopPoint()); for (;;) { CItem * pItem = AreaItems.GetItem(); if ( pItem == NULL ) break; if ( ! pItem->IsSameType( m_pCurSer->m_pObj )) continue; pItem->SetName( m_pCurSer->m_pObj->GetName()); if ( ! ( m_pCurSer->m_pObj->GetTopZ() == pItem->GetTopZ())) continue; goto item_delete; } } else { // dupe char ? } // Make sure the top level object is placed correctly. m_pCurSer->m_pObj->MoveTo( m_pCurSer->m_pObj->GetTopPoint()); m_pCurSer->m_pObj->Update(); if ( ! m_pCurSer->m_pObj->IsContainer()) delete m_pCurSer; continue; } pItemTest = dynamic_cast <CItem*> (m_pCurSer->m_pObj); if ( pItemTest == NULL ) { item_delete: delete m_pCurSer->m_pObj; delete m_pCurSer; iRemoved ++; continue; } // Find it's container. CImportSer* pSerCont = static_cast <CImportSer*> ( m_ListSer.GetHead()); CObjBase * pObjCont = NULL; for ( ; pSerCont != NULL; pSerCont = static_cast <CImportSer*> ( pSerCont->GetNext())) { if ( pSerCont->m_pObj == NULL ) continue; if ( pSerCont->m_dwSer == m_pCurSer->m_dwContSer ) { pObjCont = pSerCont->m_pObj; if ( ! pItemTest->LoadSetContainer( pObjCont->GetUID(), m_pCurSer->m_layer )) { goto item_delete; // not in a cont ? } m_pCurSer->m_dwContSer = UID_UNUSED; // found it. break; } } if ( ! m_pCurSer->IsTopLevel() || pObjCont == NULL) { goto item_delete; } // Is it a dupe in the container or equipped ? for ( CItem *pItem = dynamic_cast<CContainer*>(pObjCont)->GetContentHead(); pItem != NULL; pItem = pItem->GetNext() ) { if ( pItemTest == pItem ) continue; if ( pItemTest->IsItemEquipped()) { if ( pItemTest->GetEquipLayer() != pItem->GetEquipLayer()) continue; } else { if ( ! pItemTest->GetContainedPoint().IsSame2D( pItem->GetContainedPoint())) continue; } if ( ! pItemTest->IsSameType( pItem )) continue; goto item_delete; } // done with it if not a container. if ( ! pItemTest->IsContainer()) delete m_pCurSer; } if ( iRemoved ) { DEBUG_ERR(( "Import: removed %d bad items\n", iRemoved )); } m_ListSer.DeleteAll(); // done with the list now. }
void CImportFile::MergeDupes() { ADDTOCALLSTACK("CImportFile::MergeDupes"); // place all items and eliminate duplicates. CheckLast(); int iRemoved = 0; CImportSer *pSerNext; m_pCurSer = static_cast<CImportSer *>(m_ListSer.GetHead()); for ( ; m_pCurSer != NULL; m_pCurSer = pSerNext ) { pSerNext = static_cast<CImportSer *>(m_pCurSer->GetNext()); if ( m_pCurSer->m_pObj == NULL ) // never created correctly { delete m_pCurSer; continue; } // Make sure this item is not a dupe ? CItem *pItemTest; if ( m_pCurSer->IsTopLevel() ) // top level only { if ( m_pCurSer->m_pObj->IsItem() ) { CItem *pItemCheck = dynamic_cast<CItem *>(m_pCurSer->m_pObj); ASSERT(pItemCheck); pItemCheck->SetAttr(ATTR_MOVE_NEVER); CWorldSearch AreaItems(m_pCurSer->m_pObj->GetTopPoint()); for (;;) { CItem *pItem = AreaItems.GetItem(); if ( pItem == NULL ) break; if ( !pItem->IsIdentical(m_pCurSer->m_pObj )) continue; pItem->SetName(m_pCurSer->m_pObj->GetName()); if ( !(m_pCurSer->m_pObj->GetTopZ() == pItem->GetTopZ()) ) continue; goto item_delete; } } // Make sure the top level object is placed correctly. m_pCurSer->m_pObj->MoveTo(m_pCurSer->m_pObj->GetTopPoint()); m_pCurSer->m_pObj->Update(); if ( !m_pCurSer->m_pObj->IsContainer() ) delete m_pCurSer; continue; } pItemTest = dynamic_cast <CItem*> (m_pCurSer->m_pObj); if ( pItemTest == NULL ) { item_delete: delete m_pCurSer->m_pObj; delete m_pCurSer; iRemoved ++; continue; } delete m_pCurSer; } if ( iRemoved ) { DEBUG_ERR(( "Import: removed %d bad items\n", iRemoved )); } m_ListSer.DeleteAll(); // done with the list now. }