public void Visit(CellCoord standing_cell, Visitor visitor, Map map, WorldObject obj, float radius) { //we should increase search radius by object's radius, otherwise //we could have problems with huge creatures, which won't attack nearest players etc Visit(standing_cell, visitor, map, obj.GetPositionX(), obj.GetPositionY(), radius + obj.GetObjectSize()); }
public void Visit(CellCoord standing_cell, Visitor visitor, Map map, float x_off, float y_off, float radius) { if (!standing_cell.IsCoordValid()) { return; } //no jokes here... Actually placing ASSERT() here was good idea, but //we had some problems with DynamicObjects, which pass radius = 0.0f (DB issue?) //maybe it is better to just return when radius <= 0.0f? if (radius <= 0.0f) { map.Visit(this, visitor); return; } //lets limit the upper value for search radius if (radius > MapConst.SizeofGrids) { radius = MapConst.SizeofGrids; } //lets calculate object coord offsets from cell borders. CellArea area = CalculateCellArea(x_off, y_off, radius); //if radius fits inside standing cell if (area == null) { map.Visit(this, visitor); return; } //visit all cells, found in CalculateCellArea() //if radius is known to reach cell area more than 4x4 then we should call optimized VisitCircle //currently this technique works with MAX_NUMBER_OF_CELLS 16 and higher, with lower values //there are nothing to optimize because SIZE_OF_GRID_CELL is too big... if ((area.high_bound.X_coord > (area.low_bound.X_coord + 4)) && (area.high_bound.Y_coord > (area.low_bound.Y_coord + 4))) { VisitCircle(visitor, map, area.low_bound, area.high_bound); return; } //ALWAYS visit standing cell first!!! Since we deal with small radiuses //it is very essential to call visitor for standing cell firstly... map.Visit(this, visitor); // loop the cell range for (uint x = area.low_bound.X_coord; x <= area.high_bound.X_coord; ++x) { for (uint y = area.low_bound.Y_coord; y <= area.high_bound.Y_coord; ++y) { CellCoord cellCoord = new CellCoord(x, y); //lets skip standing cell since we already visited it if (cellCoord != standing_cell) { Cell r_zone = new Cell(cellCoord); r_zone.data.nocreate = data.nocreate; map.Visit(r_zone, visitor); } } } }
public CellArea(CellCoord low, CellCoord high) { low_bound = low; high_bound = high; }
void LoadHelper <T>(SortedSet <ulong> guid_set, CellCoord cell, ref uint count, Map map) where T : WorldObject, new() { foreach (var guid in guid_set) { T obj = new T(); // Don't spawn at all if there's a respawn time if ((obj.IsTypeId(TypeId.Unit) && map.GetCreatureRespawnTime(guid) == 0) || (obj.IsTypeId(TypeId.GameObject) && map.GetGORespawnTime(guid) == 0)) { //TC_LOG_INFO("misc", "DEBUG: LoadHelper from table: %s for (guid: %u) Loading", table, guid); if (obj.IsTypeId(TypeId.Unit)) { CreatureData cdata = Global.ObjectMgr.GetCreatureData(guid); Cypher.Assert(cdata != null, $"Tried to load creature with spawnId {guid}, but no such creature exists."); SpawnGroupTemplateData group = cdata.spawnGroupData; // If creature in manual spawn group, don't spawn here, unless group is already active. if (!group.flags.HasAnyFlag(SpawnGroupFlags.System)) { if (!map.IsSpawnGroupActive(group.groupId)) { obj.Dispose(); continue; } } // If script is blocking spawn, don't spawn but queue for a re-check in a little bit if (!group.flags.HasFlag(SpawnGroupFlags.CompatibilityMode) && !Global.ScriptMgr.CanSpawn(guid, cdata.Id, cdata, map)) { map.SaveRespawnTime(SpawnObjectType.Creature, guid, cdata.Id, Time.UnixTime + RandomHelper.URand(4, 7), map.GetZoneId(PhasingHandler.EmptyPhaseShift, cdata.spawnPoint), GridDefines.ComputeGridCoord(cdata.spawnPoint.GetPositionX(), cdata.spawnPoint.GetPositionY()).GetId(), false); obj.Dispose(); continue; } } else if (obj.IsTypeId(TypeId.GameObject)) { // If gameobject in manual spawn group, don't spawn here, unless group is already active. GameObjectData godata = Global.ObjectMgr.GetGameObjectData(guid); Cypher.Assert(godata != null, $"Tried to load gameobject with spawnId {guid}, but no such object exists."); if (!godata.spawnGroupData.flags.HasAnyFlag(SpawnGroupFlags.System)) { if (!map.IsSpawnGroupActive(godata.spawnGroupData.groupId)) { obj.Dispose(); continue; } } } if (!obj.LoadFromDB(guid, map, false, false)) { obj.Dispose(); continue; } AddObjectHelper(cell, ref count, map, obj); } else { obj.Dispose(); } } }