示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#6
0
        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++;
                }
            }
        }
示例#7
0
        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();
        }
示例#8
0
        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();
        }
示例#9
0
        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");
        }