コード例 #1
0
        public static bool FindLocationFor(VMEntity obj, VMEntity refObj, VMContext context, VMPlaceRequestFlags flags)
        {
            for (int i = 0; i < 10; i++)
            {
                if (i == 0)
                {
                    for (int j = 0; j < 4; j++)
                    {
                        if (obj.SetPosition(new LotTilePos(refObj.Position), (Direction)(1 << (j * 2)), context, flags).Status == VMPlacementError.Success)
                        {
                            return(true);
                        }
                    }
                }
                else
                {
                    LotTilePos bPos = refObj.Position;
                    for (int x = -i; x <= i; x++)
                    {
                        for (int j = 0; j < 8; j++)
                        {
                            if (obj.SetPosition(LotTilePos.FromBigTile((short)(bPos.TileX + x), (short)(bPos.TileY + ((j % 2) * 2 - 1) * i), bPos.Level),
                                                (Direction)(1 << ((j / 2) * 2)), context, flags).Status == VMPlacementError.Success)
                            {
                                return(true);
                            }
                        }
                    }

                    for (int y = 1 - i; y < i; y++)
                    {
                        for (int j = 0; j < 8; j++)
                        {
                            if (obj.SetPosition(LotTilePos.FromBigTile((short)(bPos.TileX + ((j % 2) * 2 - 1) * i), (short)(bPos.TileY + y), bPos.Level),
                                                (Direction)(1 << ((j / 2) * 2)), context, flags).Status == VMPlacementError.Success)
                            {
                                return(true);
                            }
                        }
                    }
                }
            }
            return(false);
        }
コード例 #2
0
        public static bool FindLocationVector(VMEntity obj, VMEntity refObj, VMContext context, int dir, VMPlaceRequestFlags flags)
        {
            LotTilePos step = DirectionVectors[dir];

            for (int i = 0; i < 32; i++)
            {
                if (obj.SetPosition(new LotTilePos(refObj.Position) + step * (i / 2),
                                    (Direction)(1 << (dir)), context, flags).Status == VMPlacementError.Success)
                {
                    return(true);
                }
                if (i % 2 != 0)
                {
                    if (obj.SetPosition(new LotTilePos(refObj.Position) - step * (i / 2),
                                        (Direction)(1 << (dir)), context, flags).Status == VMPlacementError.Success)
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
コード例 #3
0
        public VMPlacementResult ChangePosition(LotTilePos pos, Direction direction, VMContext context, VMPlaceRequestFlags flags)
        {
            if (pos.Level > context.Architecture.Stories)
            {
                return(new VMPlacementResult(VMPlacementError.NotAllowedOnFloor));
            }
            if (Objects.Count == 0)
            {
                return(new VMPlacementResult(VMPlacementError.Success));
            }

            var count = Objects.Count;

            VMEntity[]   OldContainers = new VMEntity[count];
            short[]      OldSlotNum    = new short[count];
            bool[]       RoomChange    = new bool[count];
            LotTilePos[] Targets       = new LotTilePos[count];
            for (int i = 0; i < count; i++)
            {
                OldContainers[i] = Objects[i].Container;
                OldSlotNum[i]    = Objects[i].ContainerSlot;
            }

            int Dir = 0;

            switch (direction)
            {
            case Direction.NORTH:
                Dir = 0; break;

            case Direction.EAST:
                Dir = 2; break;

            case Direction.SOUTH:
                Dir = 4; break;

            case Direction.WEST:
                Dir = 6; break;
            }

            Matrix rotMat = Matrix.CreateRotationZ((float)(Dir * Math.PI / 4.0));

            VMPlacementResult[] places = new VMPlacementResult[count];

            var bObj     = BaseObject;
            var bOff     = Offsets[Objects.IndexOf(BaseObject)];
            var leadOff  = new Vector3(bOff.x, bOff.y, 0);
            var offTotal = new Vector3();

            if (pos != LotTilePos.OUT_OF_WORLD)
            {
                for (int i = 0; i < count; i++)
                {
                    var sub = Objects[i];
                    var off = new Vector3(Offsets[i].x, Offsets[i].y, 0);
                    off       = Vector3.Transform(off - leadOff, rotMat);
                    offTotal += off;

                    var offPos = new LotTilePos((short)Math.Round(pos.x + off.X), (short)Math.Round(pos.y + off.Y), (sbyte)(pos.Level + Offsets[i].Level));
                    Targets[i] = offPos;
                    var roomChange = context.GetRoomAt(offPos) != context.GetObjectRoom(sub) || OldContainers[i] != null;
                    RoomChange[i] = roomChange;
                    sub.PrePositionChange(context, roomChange);
                    places[i] = sub.PositionValid(offPos, direction, context, flags);

                    if (places[i].Status != VMPlacementError.Success)
                    {
                        //go back to where we started: we're no longer out of world.
                        for (int j = 0; j <= i; j++)
                        {
                            //need to restore slot we were in
                            if (j < OldContainers.Length && OldContainers[j] != null)
                            {
                                OldContainers[j].PlaceInSlot(Objects[j], OldSlotNum[j], false, context);
                            }
                            Objects[j].PositionChange(context, false, RoomChange[j]);
                        }
                        return(places[i]);
                    }
                    else if (places[i].Object != null && !sub.StaticFootprint && !roomChange)
                    {
                        //edge case: we will be placed in a slot, but have a dynamic footprint still in the room.
                        //when placed in a slot, our collision footprint should become null.
                        //Static footprints are deleted before every move, but dynamic footprints are only removed when there is a room change.
                        //if the flag was not set, then we still need to remove the dynamic footprint for this object entering a slot.
                        sub.Footprint?.Unregister();
                    }
                }
            }
            else
            {
                for (int i = 0; i < count; i++)
                {
                    Objects[i].PrePositionChange(context, true);
                    RoomChange[i] = true;
                    var off = new Vector3(Offsets[i].x, Offsets[i].y, 0);
                    off       = Vector3.Transform(off - leadOff, rotMat);
                    offTotal += off;
                }
            }

            offTotal /= count; //this is now the average offset
            //verification success

            Matrix?groundAlign = null;

            //ground align
            if (VM.UseWorld && pos != LotTilePos.OUT_OF_WORLD && false) //wip ground alignment for carpool. currently disabled!
            {
                //find alignment
                var bp    = context.Blueprint;
                var spos  = (new Vector3(pos.x, pos.y, 0) + offTotal) / 16;
                var tBase = new Vector3(spos.X, bp.InterpAltitude(spos), spos.Y);
                var ty    = new Vector3(spos.X, bp.InterpAltitude(spos + new Vector3(0, 1 / 32f, 0)), spos.Y + 1 / 32f);
                var tx    = new Vector3(spos.X + 1 / 32f, bp.InterpAltitude(spos + new Vector3(1 / 32f, 0, 0)), spos.Y);

                var front = ty - tBase;
                front.Normalize();
                var side = tx - tBase;
                side.Normalize();
                var top = Vector3.Cross(front, side);
                groundAlign = Matrix.CreateLookAt(Vector3.Zero, new Vector3(front.X, front.Y, front.Z), top);
                //more direct coordinate creation - messes up with diagonally sloped tiles but could be useful for something else
                //groundAlign = new Matrix(new Vector4(side, 0), new Vector4(top, 0), new Vector4(front, 0), new Vector4(0, 0, 0, 1));
                if (pos != LotTilePos.OUT_OF_WORLD)
                {
                }
            }

            for (int i = 0; i < count; i++)
            {
                var sub = Objects[i];

                var offPos = (pos == LotTilePos.OUT_OF_WORLD) ?
                             LotTilePos.OUT_OF_WORLD :
                             Targets[i];

                if (VM.UseWorld)
                {
                    if (count > 0)
                    {
                        sub.WorldUI.MTOffset = Vector3.Transform(new Vector3(Offsets[i].x, Offsets[i].y, 0) - leadOff, rotMat) - offTotal;
                    }
                    if (groundAlign != null)
                    {
                        var mt = sub.WorldUI.MTOffset;
                        mt = new Vector3(mt.X / 16, mt.Z, mt.Y / 16);
                        mt = Vector3.Transform(mt, groundAlign.Value);
                        mt = new Vector3(mt.X, mt.Z, mt.Y) * 16;
                        sub.WorldUI.MTOffset = mt;
                    }
                    sub.WorldUI.GroundAlign = groundAlign;
                }
                sub.SetIndivPosition(offPos, direction, context, places[i]);
            }


            if (groundAlign != null)
            {
                //retarget floor
                var ctr = new Vector3(Offsets[0].x, Offsets[0].y, 0) - leadOff - offTotal;
                for (int i = 0; i < count; i++)
                {
                    var sub = Objects[i];
                    var mo  = Vector3.Transform(new Vector3(Offsets[i].x, Offsets[i].y, 0) - leadOff, rotMat) - offTotal;
                    var mo2 = sub.WorldUI.MTOffset;
                    if (mo != mo2)
                    {
                    }
                    mo2.Z = 0;
                    sub.VisualPosition = new Vector3(sub.VisualPosition.X, sub.VisualPosition.Y, 0) + (mo2 - mo) / 16;
                }
            }

            for (int i = 0; i < count; i++)
            {
                Objects[i].PositionChange(context, false, RoomChange[i]);
            }
            return(new VMPlacementResult(VMPlacementError.Success));
        }
コード例 #4
0
ファイル: VMMultitileGroup.cs プロジェクト: fourks/FreeSO
        public VMPlacementResult ChangePosition(LotTilePos pos, Direction direction, VMContext context, VMPlaceRequestFlags flags)
        {
            if (pos.Level > context.Architecture.Stories)
            {
                return(new VMPlacementResult(VMPlacementError.NotAllowedOnFloor));
            }
            if (Objects.Count == 0)
            {
                return(new VMPlacementResult(VMPlacementError.Success));
            }

            VMEntity[] OldContainers = new VMEntity[Objects.Count];
            short[]    OldSlotNum    = new short[Objects.Count];
            for (int i = 0; i < Objects.Count(); i++)
            {
                OldContainers[i] = Objects[i].Container;
                OldSlotNum[i]    = Objects[i].ContainerSlot;
                Objects[i].PrePositionChange(context);
            }

            int Dir = 0;

            switch (direction)
            {
            case Direction.NORTH:
                Dir = 0; break;

            case Direction.EAST:
                Dir = 2; break;

            case Direction.SOUTH:
                Dir = 4; break;

            case Direction.WEST:
                Dir = 6; break;
            }

            Matrix rotMat = Matrix.CreateRotationZ((float)(Dir * Math.PI / 4.0));

            VMPlacementResult[] places = new VMPlacementResult[Objects.Count];

            var bObj    = BaseObject;
            var bOff    = Offsets[Objects.IndexOf(BaseObject)];
            var leadOff = new Vector3(bOff.x, bOff.y, 0);

            //TODO: optimize so we don't have to recalculate all of this
            if (pos != LotTilePos.OUT_OF_WORLD)
            {
                for (int i = 0; i < Objects.Count(); i++)
                {
                    var sub = Objects[i];
                    var off = new Vector3(Offsets[i].x, Offsets[i].y, 0);
                    off = Vector3.Transform(off - leadOff, rotMat);

                    var offPos = new LotTilePos((short)Math.Round(pos.x + off.X), (short)Math.Round(pos.y + off.Y), (sbyte)(pos.Level + Offsets[i].Level));
                    places[i] = sub.PositionValid(offPos, direction, context, flags);
                    if (places[i].Status != VMPlacementError.Success)
                    {
                        //go back to where we started: we're no longer out of world.
                        for (int j = 0; j < Objects.Count(); j++)
                        {
                            //need to restore slot we were in
                            if (OldContainers[j] != null)
                            {
                                OldContainers[j].PlaceInSlot(Objects[j], OldSlotNum[j], false, context);
                            }
                            Objects[j].PositionChange(context, false);
                        }
                        return(places[i]);
                    }
                }
            }

            //verification success

            for (int i = 0; i < Objects.Count(); i++)
            {
                var sub = Objects[i];
                var off = new Vector3(Offsets[i].x, Offsets[i].y, 0);
                off = Vector3.Transform(off - leadOff, rotMat);

                var offPos = (pos == LotTilePos.OUT_OF_WORLD)?
                             LotTilePos.OUT_OF_WORLD :
                             new LotTilePos((short)Math.Round(pos.x + off.X), (short)Math.Round(pos.y + off.Y), (sbyte)(pos.Level + Offsets[i].Level));

                sub.SetIndivPosition(offPos, direction, context, places[i]);
            }
            for (int i = 0; i < Objects.Count(); i++)
            {
                Objects[i].PositionChange(context, false);
            }
            return(new VMPlacementResult(VMPlacementError.Success));
        }
コード例 #5
0
        public static bool FindLocationFor(VMEntity obj, VMEntity refObj, VMContext context, VMPlaceRequestFlags flags, bool preferNonEmpty = false)
        {
            var deferred = new List <Tuple <LotTilePos, Direction> >();

            Func <LotTilePos, Direction, bool> evaluate = (LotTilePos pos, Direction dir) =>
            {
                if (preferNonEmpty && TileOccupied(context, pos))
                {
                    deferred.Add(new Tuple <LotTilePos, Direction>(pos, dir));
                    return(false);
                }
                else
                {
                    return(obj.SetPosition(pos, dir, context, flags).Status == VMPlacementError.Success);
                }
            };

            for (int i = 0; i < 10; i++)
            {
                if (i == 0)
                {
                    var pos = new LotTilePos(refObj.Position);
                    for (int j = 0; j < 4; j++)
                    {
                        var dir = (Direction)(1 << (j * 2));
                        if (evaluate(pos, dir))
                        {
                            return(true);
                        }
                    }
                }
                else
                {
                    LotTilePos bPos = refObj.Position;
                    for (int x = -i; x <= i; x++)
                    {
                        for (int j = 0; j < 8; j++)
                        {
                            var pos = LotTilePos.FromBigTile((short)(bPos.TileX + x), (short)(bPos.TileY + ((j % 2) * 2 - 1) * i), bPos.Level);
                            var dir = (Direction)(1 << ((j / 2) * 2));
                            if (evaluate(pos, dir))
                            {
                                return(true);
                            }
                        }
                    }

                    for (int y = 1 - i; y < i; y++)
                    {
                        for (int j = 0; j < 8; j++)
                        {
                            var pos = LotTilePos.FromBigTile((short)(bPos.TileX + ((j % 2) * 2 - 1) * i), (short)(bPos.TileY + y), bPos.Level);
                            var dir = (Direction)(1 << ((j / 2) * 2));
                            if (evaluate(pos, dir))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            foreach (var tile in deferred)
            {
                if (obj.SetPosition(tile.Item1, tile.Item2, context, flags).Status == VMPlacementError.Success)
                {
                    return(true);
                }
            }
            return(false);
        }
コード例 #6
0
        public static bool FindLocationVector(VMEntity obj, VMEntity refObj, VMContext context, int dir, VMPlaceRequestFlags flags, bool preferNonEmpty = false)
        {
            LotTilePos step     = DirectionVectors[dir];
            var        dirf     = (Direction)(1 << (dir));
            var        deferred = new List <LotTilePos>();

            Func <LotTilePos, bool> evaluate = (LotTilePos pos) =>
            {
                if (preferNonEmpty && TileOccupied(context, pos))
                {
                    deferred.Add(pos);
                    return(false);
                }
                else
                {
                    return(obj.SetPosition(pos, dirf, context, flags).Status == VMPlacementError.Success);
                }
            };

            for (int i = 0; i < 32; i++)
            {
                if (evaluate(new LotTilePos(refObj.Position) + step * (i / 2)))
                {
                    return(true);
                }
                if (i % 2 != 0)
                {
                    if (evaluate(new LotTilePos(refObj.Position) - step * (i / 2)))
                    {
                        return(true);
                    }
                }
            }

            foreach (var tile in deferred)
            {
                if (obj.SetPosition(tile, dirf, context, flags).Status == VMPlacementError.Success)
                {
                    return(true);
                }
            }
            return(false);
        }