public static float GetTerrainZ(this Position p) { var landblock = LScape.get_landblock(p.LandblockId.Raw); var cellID = GetOutdoorCell(p); var landcell = (LandCell)LScape.get_landcell(cellID); if (landcell == null) { return(p.Pos.Z); } Physics.Polygon walkable = null; if (!landcell.find_terrain_poly(p.Pos, ref walkable)) { return(p.Pos.Z); } Vector3 terrainPos = p.Pos; walkable.Plane.set_height(ref terrainPos); return(terrainPos.Z); }
public Landblock(LandblockId id) { //Console.WriteLine($"Loading landblock {(id.Raw | 0xFFFF):X8}"); Id = id; CellLandblock = DatManager.CellDat.ReadFromDat <CellLandblock>(Id.Raw >> 16 | 0xFFFF); LandblockInfo = DatManager.CellDat.ReadFromDat <LandblockInfo>((uint)Id.Landblock << 16 | 0xFFFE); lastActiveTime = DateTime.UtcNow; Task.Run(() => { _landblock = LScape.get_landblock(Id.Raw); CreateWorldObjects(); SpawnDynamicShardObjects(); SpawnEncounters(); }); //LoadMeshes(objects); }
public Landblock(LandblockId id) { Id = id; UpdateStatus(LandBlockStatusFlag.IdleUnloaded); // initialize adjacency array adjacencies.Add(Adjacency.North, null); adjacencies.Add(Adjacency.NorthEast, null); adjacencies.Add(Adjacency.East, null); adjacencies.Add(Adjacency.SouthEast, null); adjacencies.Add(Adjacency.South, null); adjacencies.Add(Adjacency.SouthWest, null); adjacencies.Add(Adjacency.West, null); adjacencies.Add(Adjacency.NorthWest, null); UpdateStatus(LandBlockStatusFlag.IdleLoading); actionQueue = new NestedActionQueue(WorldManager.ActionQueue); var objects = DatabaseManager.World.GetCachedInstancesByLandblock(Id.Landblock); // Instances var factoryObjects = WorldObjectFactory.CreateNewWorldObjects(objects); factoryObjects.ForEach(fo => { AddWorldObject(fo); fo.ActivateLinks(); }); _landblock = LScape.get_landblock(Id.Raw); // Many thanks for GDL cache and GDL coding for loading into landblock and gmriggs assistance with taking the byte arrays and turning them in to more easy to follow (for me) data structures var encounters = DatabaseManager.World.GetCachedEncountersByLandblock(Id.Landblock); encounters.ForEach(encounter => { var wo = WorldObjectFactory.CreateNewWorldObject(encounter.WeenieClassId); if (wo != null) { float x_shift = 24.0f * encounter.CellX; float y_shift = 24.0f * encounter.CellY; var pos = new Physics.Common.Position(); pos.ObjCellID = (uint)(id.Landblock << 16) | 1; pos.Frame = new Physics.Animation.AFrame(new Vector3(x_shift, y_shift, 0), new Quaternion(0, 0, 0, 1)); pos.adjust_to_outside(); pos.Frame.Origin.Z = _landblock.GetZ(pos.Frame.Origin); wo.Location = new Position(pos.ObjCellID, pos.Frame.Origin.X, pos.Frame.Origin.Y, pos.Frame.Origin.Z, pos.Frame.Orientation.X, pos.Frame.Orientation.Y, pos.Frame.Orientation.Z, pos.Frame.Orientation.W); if (!worldObjects.ContainsKey(wo.Guid)) { AddWorldObject(wo); } } }); //LoadMeshes(objects); UpdateStatus(LandBlockStatusFlag.IdleLoaded); // FIXME(ddevec): Goal: get rid of UseTime() function... actionQueue.EnqueueAction(new ActionEventDelegate(() => UseTimeWrapper())); motionQueue = new NestedActionQueue(WorldManager.MotionQueue); }
public static void TryFindObject(Vector3 dir) { Dir = dir; LastPickResult = PickResult; ClearSelection(); PickResult = new PickResult(); // first try using physics engine for this // try spawning a tiny 'projectile' object at the camera position // if successfully spawned, simulate proceeding in that direction until something is hit var startPos = Camera.GetPosition(); if (startPos == null) { Console.WriteLine($"Couldn't find current camera position in world!"); return; } var maxSteps = 500; var stepSize = 1.0f; var i = 0; var stepDir = (dir * stepSize).ToNumerics(); var singleBlock = WorldViewer.Instance.SingleBlock; if (singleBlock != uint.MaxValue) { var landblock = LScape.get_landblock(singleBlock); // custom for single landblock IsDungeon if (landblock.IsDungeon) { if (startPos.Landblock != singleBlock >> 16) { startPos.Reframe(singleBlock); } var adjustCell = AdjustCell.Get(startPos.Landblock); for ( ; i < maxSteps; i++) { var foundCell = adjustCell.GetCell(startPos.Frame.Origin); if (foundCell != null) { startPos.ObjCellID = foundCell.Value; break; } startPos.Frame.Origin += stepDir; } } } // todo: make this static var pickerObj = PhysicsObj.makeObject(setupId, pickerGuid.Full, true); pickerObj.State |= PhysicsState.PathClipped; pickerObj.State &= ~PhysicsState.Gravity; pickerObj.set_object_guid(pickerGuid); var worldObj = new WorldObject(); //worldObj.Name = "Picker"; var weenie = new WeenieObject(worldObj); pickerObj.set_weenie_obj(weenie); // perform transition PhysicsObj.IsPicking = true; var showedMsg = false; var spawned = false; for ( ; i < maxSteps; i++) { if (!spawned) { var success = pickerObj.enter_world(startPos); if (!success) { startPos.Frame.Origin += stepDir; continue; } else { //Console.WriteLine($"Successfully spawned picker @ {startPos}"); spawned = true; } } var nextPos = new ACE.Server.Physics.Common.Position(pickerObj.Position); nextPos.Frame.Origin += stepDir; var transition = pickerObj.transition(pickerObj.Position, nextPos, false); // debug collision info if (transition == null) { Console.WriteLine($"Null transition result!"); showedMsg = true; break; } else if (transition.CollisionInfo.CollidedWithEnvironment || transition.CollisionInfo.CollideObject.Count > 0) { /*if (transition.CollisionInfo.CollidedWithEnvironment) * Console.WriteLine($"CollidedWithEnvironment"); * * if (transition.CollisionInfo.CollideObject.Count > 0) * { * Console.WriteLine($"CollideObjs:"); * foreach (var collideObj in transition.CollisionInfo.CollideObject) * Console.WriteLine($"{collideObj.PartArray.Setup._dat.Id:X8} @ {collideObj.Position.ShortLoc()}"); * }*/ BuildHitPolys(); showedMsg = true; break; } else { pickerObj.SetPositionInternal(transition); } } PhysicsObj.IsPicking = false; if (!spawned) { Console.WriteLine($"Failed to spawn picker @ {Camera.GetPosition()}"); } else if (!showedMsg) { Console.WriteLine($"No collisions"); } // cleanup pickerObj.DestroyObject(); }
/// <summary> /// Gets the cell ID for a position within a landblock /// </summary> public static uint GetCell(this Position p) { var landblock = LScape.get_landblock(p.LongObjCellID); // dungeons // TODO: investigate dungeons that are below actual traversable overworld terrain // ex., 010AFFFF //if (landblock.IsDungeon) if (p.Indoors) { return(GetIndoorCell(p)); } // outside - could be on landscape, in building, or underground cave var cellID = GetOutdoorCell(p); var longcellID = ((ulong)p.Instance << 32) | cellID; var landcell = LScape.get_landcell(longcellID) as LandCell; if (landcell == null) { return(cellID); } if (landcell.has_building()) { var envCells = landcell.Building.get_building_cells(); foreach (var envCell in envCells) { if (envCell.point_in_cell(p.Pos)) { return(envCell.ID); } } } // handle underground areas ie. caves // get the terrain Z-height for this X/Y Physics.Polygon walkable = null; var terrainPoly = landcell.find_terrain_poly(p.Pos, ref walkable); if (walkable != null) { Vector3 terrainPos = p.Pos; walkable.Plane.set_height(ref terrainPos); // are we below ground? if so, search all of the indoor cells for this landblock if (terrainPos.Z > p.Pos.Z) { var envCells = landblock.get_envcells(); foreach (var envCell in envCells) { if (envCell.point_in_cell(p.Pos)) { return(envCell.ID); } } } } return(cellID); }
public void ProcessGeneratorQueue() { var index = 0; while (index < GeneratorQueue.Count) { double ts = Common.Time.GetTimestamp(); if (ts >= GeneratorQueue[index].When) { if (GeneratorRegistry.Count >= MaxGeneratedObjects) { // System.Diagnostics.Debug.WriteLine($"GeneratorRegistry for {Guid.Full} is at MaxGeneratedObjects {MaxGeneratedObjects}"); // System.Diagnostics.Debug.WriteLine($"Removing {GeneratorQueue[index].Slot} from GeneratorQueue for {Guid.Full}"); GeneratorQueue.RemoveAt(index); index++; continue; } var profile = GeneratorProfiles[(int)GeneratorQueue[index].Slot]; var rNode = new GeneratorRegistryNode(); rNode.WeenieClassId = profile.WeenieClassId; rNode.Timestamp = Common.Time.GetTimestamp(); rNode.Slot = GeneratorQueue[index].Slot; var wo = WorldObjectFactory.CreateNewWorldObject(profile.WeenieClassId); if (wo != null) { switch ((RegenLocationType)profile.WhereCreate) { case RegenLocationType.SpecificTreasure: case RegenLocationType.Specific: if ((profile.ObjCellId ?? 0) > 0) { wo.Location = new ACE.Entity.Position(profile.ObjCellId ?? 0, profile.OriginX ?? 0, profile.OriginY ?? 0, profile.OriginZ ?? 0, profile.AnglesX ?? 0, profile.AnglesY ?? 0, profile.AnglesZ ?? 0, profile.AnglesW ?? 0); } else { wo.Location = new ACE.Entity.Position(Location.Cell, Location.PositionX + profile.OriginX ?? 0, Location.PositionY + profile.OriginY ?? 0, Location.PositionZ + profile.OriginZ ?? 0, profile.AnglesX ?? 0, profile.AnglesY ?? 0, profile.AnglesZ ?? 0, profile.AnglesW ?? 0); } break; case RegenLocationType.ScatterTreasure: case RegenLocationType.Scatter: float genRadius = (float)(GetProperty(PropertyFloat.GeneratorRadius) ?? 0f); var random_x = Physics.Common.Random.RollDice(genRadius * -1, genRadius); var random_y = Physics.Common.Random.RollDice(genRadius * -1, genRadius); var pos = new Physics.Common.Position(Location); wo.Location = new ACE.Entity.Position(pos.ObjCellID, pos.Frame.Origin.X, pos.Frame.Origin.Y, pos.Frame.Origin.Z, pos.Frame.Orientation.X, pos.Frame.Orientation.Y, pos.Frame.Orientation.Z, pos.Frame.Orientation.W); var newPos = wo.Location.Pos + new Vector3(random_x, random_y, 0.0f); if (!Location.Indoors) { // Based on GDL scatter newPos.X = Math.Clamp(newPos.X, 0.5f, 191.5f); newPos.Y = Math.Clamp(newPos.Y, 0.5f, 191.5f); wo.Location.SetPosition(newPos); newPos.Z = LScape.get_landblock(wo.Location.Cell).GetZ(newPos); } wo.Location.SetPosition(newPos); break; default: wo.Location = Location; break; } wo.Generator = this; wo.GeneratorId = Guid.Full; // System.Diagnostics.Debug.WriteLine($"Adding {wo.Guid.Full} | {rNode.Slot} in GeneratorRegistry for {Guid.Full}"); GeneratorRegistry.Add(wo.Guid.Full, rNode); GeneratorCache.Add(wo.Guid.Full, wo); // System.Diagnostics.Debug.WriteLine($"Spawning {GeneratorQueue[index].Slot} in GeneratorQueue for {Guid.Full}"); wo.EnterWorld(); // System.Diagnostics.Debug.WriteLine($"Removing {GeneratorQueue[index].Slot} from GeneratorQueue for {Guid.Full}"); GeneratorQueue.RemoveAt(index); } else { // System.Diagnostics.Debug.WriteLine($"Removing {GeneratorQueue[index].Slot} from GeneratorQueue for {Guid.Full} because wcid {rNode.WeenieClassId} is not in the database"); GeneratorQueue.RemoveAt(index); } } else { index++; } } }
public void LoadLandblock(uint landblockID, uint radius = 1) { if (PlayerMode) { ExitPlayerMode(); InitPlayerMode = true; } Render.Buffer.ClearBuffer(); Server.Init(); TextureCache.Init(); LScape.unload_landblocks_all(); var landblock = LScape.get_landblock(landblockID); if (landblock.HasDungeon) { radius = 0; } DungeonMode = landblock.HasDungeon; var center_lbx = landblockID >> 24; var center_lby = landblockID >> 16 & 0xFF; //Landblocks = new Dictionary<uint, R_Landblock>(); R_Landblock r_landblock = null; R_Landblock centerBlock = null; for (var lbx = (int)(center_lbx - radius); lbx <= center_lbx + radius; lbx++) { if (lbx < 0 || lbx > 254) { continue; } for (var lby = (int)(center_lby - radius); lby <= center_lby + radius; lby++) { if (lby < 0 || lby > 254) { continue; } var lbid = (uint)(lbx << 24 | lby << 16 | 0xFFFF); var timer = Stopwatch.StartNew(); landblock = LScape.get_landblock(lbid); timer.Stop(); r_landblock = new R_Landblock(landblock); //LScape.unload_landblock(lbid); if (landblockID == lbid) { centerBlock = r_landblock; } MainWindow.Status.WriteLine($"Loaded {lbid:X8} in {timer.Elapsed.TotalMilliseconds}ms"); //Landblocks.Add(lbid, new R_Landblock(landblock)); } } Render.Buffer.BuildBuffers(); Render.InitEmitters(); if (FileExplorer.Instance.TeleportMode) { var zBump = DungeonMode ? 1.775f : 2.775f; if (InitPlayerMode) { zBump = 0.0f; } Camera.InitTeleport(centerBlock, zBump); FileExplorer.Instance.TeleportMode = false; } else if (DungeonMode) { BoundingBox = new Model.BoundingBox(Render.Buffer.RB_EnvCell); Camera.InitDungeon(r_landblock, BoundingBox); } else { Camera.InitLandblock(r_landblock); } SingleBlock = landblock.ID; FreeResources(); Server.OnLoadWorld(); }
public async void LoadLandblocks(Vector2 startBlock, Vector2 endBlock) { //Console.WriteLine($"LoadLandblocks({startBlock}, {endBlock})"); if (PlayerMode) { ExitPlayerMode(); InitPlayerMode = true; } Render.Buffer.ClearBuffer(); Server.Init(); TextureCache.Init(); LScape.unload_landblocks_all(); DungeonMode = false; var dx = (int)(endBlock.X - startBlock.X) + 1; var dy = (int)(startBlock.Y - endBlock.Y) + 1; var numBlocks = dx * dy; var size = endBlock - startBlock; var center = startBlock + size / 2; var centerX = (uint)Math.Round(center.X); var centerY = (uint)Math.Round(center.Y); var landblockID = centerX << 24 | centerY << 16 | 0xFFFF; MainWindow.Status.WriteLine($"Loading {numBlocks} landblocks"); await Task.Delay(1); //Landblocks = new Dictionary<uint, R_Landblock>(); R_Landblock r_landblock = null; R_Landblock centerBlock = null; for (var lbx = (uint)startBlock.X; lbx <= endBlock.X; lbx++) { if (lbx < 0 || lbx > 254) { continue; } for (var lby = (uint)endBlock.Y; lby <= startBlock.Y; lby++) { if (lby < 0 || lby > 254) { continue; } var lbid = lbx << 24 | lby << 16 | 0xFFFF; var timer = Stopwatch.StartNew(); var landblock = LScape.get_landblock(lbid); timer.Stop(); r_landblock = new R_Landblock(landblock); //LScape.unload_landblock(lbid); if (lbid == landblockID) { centerBlock = r_landblock; } MainWindow.Status.WriteLine($"Loaded {lbid:X8} in {timer.Elapsed.TotalMilliseconds}ms"); //Landblocks.Add(lbid, new R_Landblock(landblock)); } } Render.Buffer.BuildBuffers(); Render.InitEmitters(); Camera.InitLandblock(centerBlock); GameView.ViewMode = ViewMode.World; SingleBlock = uint.MaxValue; FreeResources(); Server.OnLoadWorld(); }
public static void LoadEncounters() { Initting = true; MainWindow.Instance.SuppressStatusText = true; SetDatabaseConfig(); Encounters = new List <WorldObject>(); var timer = Stopwatch.StartNew(); // get the list of loaded landblocks foreach (var lbid in LScape.Landblocks.Keys) { var encounters = DatabaseManager.World.GetCachedEncountersByLandblock((ushort)(lbid >> 16)); Console.WriteLine($"Found {encounters.Count:N0} encounters for {lbid:X8}"); var landblock = LScape.get_landblock(lbid); foreach (var encounter in encounters) { var wo = WorldObjectFactory.CreateNewWorldObject(encounter.WeenieClassId); if (wo == null) { continue; } wo.InitPhysicsObj(); var xPos = Math.Clamp(encounter.CellX * 24.0f, 0.5f, 191.5f); var yPos = Math.Clamp(encounter.CellY * 24.0f, 0.5f, 191.5f); var pos = new Position(); pos.ObjCellID = lbid & 0xFFFF0000 | 1; pos.Frame = new AFrame(new Vector3(xPos, yPos, 0), Quaternion.Identity); pos.adjust_to_outside(); pos.Frame.Origin.Z = landblock.GetZ(pos.Frame.Origin); wo.Location = new ACE.Entity.Position(pos.ObjCellID, pos.Frame.Origin, pos.Frame.Orientation); var sortCell = LScape.get_landcell(pos.ObjCellID) as SortCell; if (sortCell != null && sortCell.has_building()) { continue; } var success = wo.AddPhysicsObj(pos); if (!success) { Console.WriteLine($"LoadEncounters({lbid:X8}).AddPhysicsObj({wo.Name}, {pos}) - failed to spawn"); continue; } Console.WriteLine($"Spawned {encounter.WeenieClassId} - {wo.Name} @ {pos}"); AddEncounter(wo); } } TickGenerators(GeneratorTickMode.Encounters); timer.Stop(); Console.WriteLine($"Completed in {timer.Elapsed.TotalSeconds}s"); }