public VMPlacementError ChangePosition(LotTilePos pos, Direction direction, VMContext context)
        {
            if (pos.Level > context.Architecture.Stories) return VMPlacementError.NotAllowedOnFloor;
            for (int i = 0; i < Objects.Count(); i++) 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 leadOff = new Vector3(((sbyte)(((ushort)bObj.Object.OBJ.SubIndex) >> 8) * 16), ((sbyte)(((ushort)bObj.Object.OBJ.SubIndex) & 0xFF) * 16), 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((sbyte)(((ushort)sub.Object.OBJ.SubIndex) >> 8) * 16, (sbyte)(((ushort)sub.Object.OBJ.SubIndex) & 0xFF) * 16, 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 + sub.Object.OBJ.LevelOffset));
                    places[i] = sub.PositionValid(offPos, direction, context);
                    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++) Objects[j].PositionChange(context);
                        return places[i].Status;
                    }
                }
            }

            //verification success

            for (int i = 0; i < Objects.Count(); i++)
            {
                var sub = Objects[i];
                var off = new Vector3((sbyte)(((ushort)sub.Object.OBJ.SubIndex) >> 8) * 16, (sbyte)(((ushort)sub.Object.OBJ.SubIndex) & 0xFF)*16, 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+sub.Object.OBJ.LevelOffset));

                sub.SetIndivPosition(offPos, direction, context, places[i]);
            }
            for (int i = 0; i < Objects.Count(); i++) Objects[i].PositionChange(context);
            return VMPlacementError.Success;
        }
Ejemplo n.º 2
0
 public bool CheckFloorValid(LotTilePos pos, FloorTile floor)
 {
     if (pos.Level < 1 || pos.Level > ObjectsAt.Count || !ObjectsAt[pos.Level - 1].ContainsKey(pos.TileID)) return true;
     var objs = ObjectsAt[pos.Level - 1][pos.TileID];
     foreach (var id in objs)
     {
         var obj = VM.GetObjectById(id);
         if (obj.FloorChangeValid(floor, pos.Level) != VMPlacementError.Success) return false;
     }
     return true;
 }
Ejemplo n.º 3
0
 private bool SetPosition(VMEntity entity, LotTilePos pos, Direction dir, VMContext context)
 {
     return SetPosition(entity, pos, (float)(Math.Round(Math.Log((double)dir, 2))*(Math.PI/4)), context);
 }
Ejemplo n.º 4
0
 public virtual VMPlacementError SetPosition(LotTilePos pos, Direction direction, VMContext context)
 {
     return MultitileGroup.ChangePosition(pos, direction, context);
 }
Ejemplo n.º 5
0
 public ushort GetRoomAt(LotTilePos pos)
 {
     if (pos.TileX < 0 || pos.TileX >= _Arch.Width) return 0;
     else if (pos.TileY < 0 || pos.TileY >= _Arch.Height) return 0;
     else if (pos.Level < 1 || pos.Level > _Arch.Stories) return 0;
     else return Architecture.Rooms[pos.Level-1].Map[pos.TileX + pos.TileY * _Arch.Width];
 }
Ejemplo n.º 6
0
 public VMSolidResult SolidToAvatars(LotTilePos pos)
 {
     if (pos.Level < 1 || pos.Level > ObjectsAt.Count || !ObjectsAt[pos.Level - 1].ContainsKey(pos.TileID)) return new VMSolidResult();
     var objs = ObjectsAt[pos.Level - 1][pos.TileID];
     foreach (var id in objs)
     {
         var obj = VM.GetObjectById(id);
         if (obj == null) continue;
         var flags = (VMEntityFlags)obj.GetValue(VMStackObjectVariable.Flags);
         if (((flags & VMEntityFlags.DisallowPersonIntersection) > 0) || (flags & (VMEntityFlags.AllowPersonIntersection | VMEntityFlags.HasZeroExtent)) == 0)
             return new VMSolidResult {
                 Solid = true,
                 Chair = (obj.EntryPoints[26].ActionFunction != 0)?obj:null
             }; //solid to people
     }
     return new VMSolidResult();
 }
Ejemplo n.º 7
0
 public LotTilePos(LotTilePos pos)
 {
     x = pos.x;
     y = pos.y;
     Level = pos.Level;
 }
Ejemplo n.º 8
0
        public VMMultitileGroup CreateObjectInstance(UInt32 GUID, LotTilePos pos, Direction direction, short MainStackOBJ, short MainParam)
        {
            VMMultitileGroup group = new VMMultitileGroup();
            var objDefinition = TSO.Content.Content.Get().WorldObjects.Get(GUID);
            if (objDefinition == null)
            {
                return null;
            }

            var master = objDefinition.OBJ.MasterID;
            if (master != 0)
            {
                group.MultiTile = true;
                var objd = objDefinition.Resource.List<OBJD>();

                for (int i = 0; i < objd.Count; i++)
                {
                    if (objd[i].MasterID == master && objd[i].SubIndex != -1) //if sub-part of this object, make it!
                    {
                        var subObjDefinition = TSO.Content.Content.Get().WorldObjects.Get(objd[i].GUID);
                        if (subObjDefinition != null)
                        {
                            var worldObject = new ObjectComponent(subObjDefinition);
                            var vmObject = new VMGameObject(subObjDefinition, worldObject);
                            vmObject.MasterDefinition = objDefinition.OBJ;
                            vmObject.UseTreeTableOf(objDefinition);

                            vmObject.MainParam = MainParam;
                            vmObject.MainStackOBJ = MainStackOBJ;
                            group.Objects.Add(vmObject);

                            vmObject.MultitileGroup = group;
                            VM.AddEntity(vmObject);

                        }
                    }
                }

                group.Init(this);
                VMPlacementError couldPlace = group.ChangePosition(pos, direction, this);
                if (couldPlace != VMPlacementError.Success);
                return group;
            }
            else
            {
                if (objDefinition.OBJ.ObjectType == OBJDType.Person) //person
                {
                    var vmObject = new VMAvatar(objDefinition);
                    vmObject.MultitileGroup = group;
                    group.Objects.Add(vmObject);
                    VM.AddEntity(vmObject);

                    Blueprint.AddAvatar((AvatarComponent)vmObject.WorldUI);

                    vmObject.MainParam = MainParam;
                    vmObject.MainStackOBJ = MainStackOBJ;

                    group.Init(this);
                    vmObject.SetPosition(pos, direction, this);

                    return group;
                }
                else
                {
                    var worldObject = new ObjectComponent(objDefinition);
                    var vmObject = new VMGameObject(objDefinition, worldObject);

                    vmObject.MultitileGroup = group;
                    group.Objects.Add(vmObject);

                    VM.AddEntity(vmObject);

                    vmObject.MainParam = MainParam;
                    vmObject.MainStackOBJ = MainStackOBJ;

                    group.Init(this);
                    vmObject.SetPosition(pos, direction, this);

                    return group;
                }
            }
        }
Ejemplo n.º 9
0
 private double GetDirectionTo(LotTilePos pos1, LotTilePos pos2)
 {
     return Math.Atan2(pos2.x - pos1.x, -(pos2.y - pos1.y));
 }
Ejemplo n.º 10
0
 private static bool equals(LotTilePos c1, LotTilePos c2)
 {
     return c1.x == c2.x && c1.y == c2.y && c1.Level == c2.Level;
 }
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand<VMGotoRelativePositionOperand>();

            var obj = context.StackObject;
            var avatar = (VMAvatar)context.Caller;

            if (obj.Position == LotTilePos.OUT_OF_WORLD) return VMPrimitiveExitCode.GOTO_FALSE;

            var result = new VMFindLocationResult();
            LotTilePos relative;
            int intDir = (int)Math.Round(Math.Log((double)obj.Direction, 2));

            /**
             * Examples for reference
             * Fridge - Have Snack - In front of, facing
             */
            if (operand.Location == VMGotoRelativeLocation.OnTopOf)
            {
                relative = new LotTilePos(0, 0, obj.Position.Level);
                result.Position = new LotTilePos(obj.Position);
                //result.Flags = (SLOTFlags)obj.Direction;
            }
            else
            {
                int dir;
                if (operand.Location == VMGotoRelativeLocation.AnywhereNear) dir = (int)context.VM.Context.NextRandom(8);
                else dir = ((int)operand.Location + intDir) % 8;

                relative = Positions[dir];

                var location = obj.Position;
                location += relative;
                result.Position = location;
            }
            //throw new Exception("Unknown goto relative");

            if (operand.Direction == VMGotoRelativeDirection.Facing)
            {
                result.RadianDirection = (float)GetDirectionTo(relative, new LotTilePos(0, 0, relative.Level));
                result.Flags = RadianToFlags(result.RadianDirection);
            }
            else if (operand.Direction == VMGotoRelativeDirection.AnyDirection)
            {
                result.RadianDirection = 0;
                result.Flags = SLOTFlags.NORTH;
            }
            else
            {
                var dir = ((int)operand.Direction + intDir) % 8;
                result.RadianDirection = (float)dir*(float)(Math.PI/4.0);
                if (result.RadianDirection > Math.PI) result.RadianDirection -= (float)(Math.PI * 2.0);
                result.Flags = (SLOTFlags)(1<<(int)dir);
            }

            var pathFinder = context.Thread.PushNewPathFinder(context, new List<VMFindLocationResult>() { result });
            if (pathFinder != null) return VMPrimitiveExitCode.CONTINUE;
            else return VMPrimitiveExitCode.GOTO_FALSE;
        }
Ejemplo n.º 12
0
 private double GetDist(LotTilePos pos1, LotTilePos pos2)
 {
     return Math.Sqrt(Math.Pow(pos1.x - pos2.x, 2) + Math.Pow(pos1.y - pos2.y, 2))/16.0 + Math.Abs(pos1.Level-pos2.Level)*10;
 }
Ejemplo n.º 13
0
        private bool AdvanceWaypoint()
        {
            if (WalkTo.Count == 0) return false;
            var point = WalkTo.First.Value;
            WalkTo.RemoveFirst();
            if (WalkTo.Count > 0)
            {
                CurrentWaypoint = LotTilePos.FromBigTile((short)point.X, (short)point.Y, Caller.Position.Level);
            }
            else CurrentWaypoint = CurRoute.Position; //go directly to position at last

            WalkDirection = TargetDirection;
            TargetDirection = Math.Atan2(CurrentWaypoint.x - Caller.Position.x, Caller.Position.y - CurrentWaypoint.y); //y+ as north. x+ is -90 degrees.
            TurnFrames = 10;
            return true;
        }
Ejemplo n.º 14
0
 public bool CheckWallValid(LotTilePos pos, WallTile wall)
 {
     if (pos.Level < 1 || pos.Level > ObjectsAt.Count || !ObjectsAt[pos.Level - 1].ContainsKey(pos.TileID)) return true;
     var objs = ObjectsAt[pos.Level - 1][pos.TileID];
     foreach (var id in objs)
     {
         var obj = VM.GetObjectById(id);
         if (obj.WallChangeValid(wall, obj.Direction, false) != VMPlacementError.Success) return false;
     }
     return true;
 }
Ejemplo n.º 15
0
 public static int Distance(LotTilePos a, LotTilePos b)
 {
     return (int)Math.Sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
     //TODO: consider level? does anything need this?
 }
Ejemplo n.º 16
0
 public VMMultitileGroup CreateObjectInstance(UInt32 GUID, LotTilePos pos, Direction direction)
 {
     return CreateObjectInstance(GUID, pos, direction, 0, 0);
 }
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand<VMCreateObjectInstanceOperand>();
            LotTilePos tpos = new LotTilePos(LotTilePos.OUT_OF_WORLD);
            Direction dir;

            switch (operand.Position)
            {
                case VMCreateObjectPosition.UnderneathMe:
                case VMCreateObjectPosition.OnTopOfMe:
                    tpos = new LotTilePos(context.Caller.Position);
                    dir = Direction.NORTH;
                    break;
                case VMCreateObjectPosition.BelowObjectInLocal:
                    tpos = new LotTilePos(context.VM.GetObjectById((short)context.Locals[operand.LocalToUse]).Position);
                    dir = Direction.NORTH;
                    break;
                case VMCreateObjectPosition.BelowObjectInStackParam0:
                    tpos = new LotTilePos(context.VM.GetObjectById((short)context.Args[0]).Position);
                    dir = Direction.NORTH;
                    break;
                case VMCreateObjectPosition.OutOfWorld:
                    dir = Direction.NORTH;
                    break;
                case VMCreateObjectPosition.InSlot0OfStackObject:
                case VMCreateObjectPosition.InMyHand:
                    dir = Direction.NORTH;
                    //this object should start in slot 0 of the stack object!
                    //we have to create it first tho so hold your horses
                    break;
                case VMCreateObjectPosition.InFrontOfStackObject:
                case VMCreateObjectPosition.InFrontOfMe:
                    var objp = (operand.Position == VMCreateObjectPosition.InFrontOfStackObject)?context.StackObject:context.Caller;
                    tpos = new LotTilePos(objp.Position);
                    switch (objp.Direction)
                    {
                        case tso.world.model.Direction.SOUTH:
                            tpos.y += 16;
                            break;
                        case tso.world.model.Direction.WEST:
                            tpos.x -= 16;
                            break;
                        case tso.world.model.Direction.EAST:
                            tpos.x += 16;
                            break;
                        case tso.world.model.Direction.NORTH:
                            tpos.y -= 16;
                            break;
                    }
                    dir = objp.Direction;
                    break;
                default:
                    throw new VMSimanticsException("Where do I put this??", context);
            }

            var obj = context.VM.Context.CreateObjectInstance(operand.GUID, tpos, dir,
                (operand.PassObjectIds && context.StackObject != null) ? (context.StackObject.ObjectID) : (short)0,
                (operand.PassTemp0) ? (context.Thread.TempRegisters[0]) : (operand.PassObjectIds ? context.Caller.ObjectID : (short)0) ).Objects[0];

            if (operand.Position == VMCreateObjectPosition.InSlot0OfStackObject) context.StackObject.PlaceInSlot(obj, 0);
            else if (operand.Position == VMCreateObjectPosition.InMyHand) context.Caller.PlaceInSlot(obj, 0);

            if ((operand.Flags & (1 << 6)) > 0)
            {
                var interaction = operand.InteractionCallback;
                if (interaction == 254)
                {
                    var temp = context.Caller.Thread.Queue[0].InteractionNumber;
                    if (temp == -1) throw new VMSimanticsException("Set callback as 'this interaction' when queue item has no interaction number!", context);
                    interaction = (byte)temp;
                }
                var callback = new VMActionCallback(context.VM, interaction, context.Callee, context.StackObject, context.Caller, true);
                callback.Run(obj);
            }
            else context.StackObject = obj;

            return VMPrimitiveExitCode.GOTO_TRUE;
        }
Ejemplo n.º 18
0
        public VMPlacementResult GetObjPlace(VMEntity target, LotTilePos pos)
        {
            //ok, this might be confusing...
            short allowedHeights = target.GetValue(VMStackObjectVariable.AllowedHeightFlags);
            short weight = target.GetValue(VMStackObjectVariable.Weight);
            var tflags = (VMEntityFlags)target.GetValue(VMStackObjectVariable.Flags);
            bool noFloor = (allowedHeights&1)==0;

            VMPlacementError status = (noFloor)?VMPlacementError.HeightNotAllowed:VMPlacementError.Success;

            if ((tflags & VMEntityFlags.HasZeroExtent) > 0 ||
                pos.Level < 1 || pos.Level > ObjectsAt.Count || (!ObjectsAt[pos.Level - 1].ContainsKey(pos.TileID)))
            {
                return new VMPlacementResult { Status = status };
            }
            var objs = ObjectsAt[pos.Level - 1][pos.TileID];
            foreach (var id in objs)
            {
                var obj = VM.GetObjectById(id);
                if (obj == null || obj.MultitileGroup == target.MultitileGroup) continue;
                var flags = (VMEntityFlags)obj.GetValue(VMStackObjectVariable.Flags);
                if ((flags & VMEntityFlags.HasZeroExtent) == 0)
                {
                    status = VMPlacementError.CantIntersectOtherObjects;

                    //this object is technically solid. Check if we can place on top of it
                    if (allowedHeights>1 && obj.TotalSlots() > 0 && (obj.GetSlot(0) == null || obj.GetSlot(0) == target))
                    {
                        //first check if we have a slot 0, which is what we place onto. then check if it's empty,
                        //then check if the object can support this one's weight.
                        //we also need to make sure that the height of this specific slot is allowed.

                        if (((1 << (obj.GetSlotHeight(0) - 1)) & allowedHeights) > 0)
                        {
                            if (weight < obj.GetValue(VMStackObjectVariable.SupportStrength))
                            {
                                return new VMPlacementResult
                                {
                                    Status = VMPlacementError.Success,
                                    Container = obj
                                };
                            }
                            else
                            {
                                status = VMPlacementError.CantSupportWeight;
                            }
                        }
                        else
                        {
                            if (noFloor)
                            {
                                if ((allowedHeights & (1 << 3)) > 0) status = VMPlacementError.CounterHeight;
                                else status = (obj.GetSlotHeight(0) == 8) ? VMPlacementError.CannotPlaceComputerOnEndTable : VMPlacementError.HeightNotAllowed;
                            }
                        }
                    }
                }
            }
            return new VMPlacementResult
            {
                Status = status
            };
        }
Ejemplo n.º 19
0
        public VMPlacementResult PositionValid(LotTilePos pos, Direction direction, VMContext context)
        {
            if (pos == LotTilePos.OUT_OF_WORLD) return new VMPlacementResult();
            else if (context.IsOutOfBounds(pos)) return new VMPlacementResult { Status = VMPlacementError.LocationOutOfBounds };

            //TODO: speedup with exit early checks
            //TODO: corner checks (wtf uses this)

            var arch = context.Architecture;
            var wall = arch.GetWall(pos.TileX, pos.TileY, pos.Level); //todo: preprocess to check which walls are real solid walls.

            VMPlacementError wallValid = WallChangeValid(wall, direction, true);
            if (wallValid != VMPlacementError.Success) return new VMPlacementResult { Status = wallValid };

            var floor = arch.GetFloor(pos.TileX, pos.TileY, pos.Level); //todo: preprocess to check which walls are real solid walls.
            VMPlacementError floorValid = FloorChangeValid(floor, pos.Level);
            if (floorValid != VMPlacementError.Success) return new VMPlacementResult { Status = floorValid };

            //we've passed the wall test, now check if we intersect any objects.
            var valid = context.GetObjPlace(this, pos);
            return valid;
        }
Ejemplo n.º 20
0
 public bool IsOutOfBounds(LotTilePos pos)
 {
     return (pos.x < 0 || pos.y < 0 || pos.TileX >= _Arch.Width || pos.TileY >= _Arch.Height);
 }
Ejemplo n.º 21
0
        public virtual void SetIndivPosition(LotTilePos pos, Direction direction, VMContext context, VMPlacementResult info)
        {
            Direction = direction;

            //TODO: clean the f**k up out of OUT_OF_WORLD
            if (this is VMGameObject) context.Blueprint.ChangeObjectLocation((ObjectComponent)WorldUI, (pos==LotTilePos.OUT_OF_WORLD)?LotTilePos.FromBigTile(-1,-1,1):pos);
            Position = pos;
            if (info.Container != null) info.Container.PlaceInSlot(this, 0);
        }
Ejemplo n.º 22
0
        public void ChangeObjectLocation(ObjectComponent component, LotTilePos pos)
        {
            short tileX = (pos.x < 0) ? (short)0 : pos.TileX;
            short tileY = (pos.y < 0) ? (short)0 : pos.TileY;
            sbyte level = pos.Level;
            /** It has never been placed before if tileX == -2 **/

            if (component.TileX != -2){
                var currentOffset = GetOffset(component.TileX, component.TileY);
                var currentList = Objects[currentOffset];
                if (currentList != null){
                    currentList.RemoveObject(component);
                }
            }

            if (tileX != -2)
            {
                var newOffset = GetOffset(tileX, tileY);
                var newList = Objects[newOffset];
                if (newList == null)
                {
                    newList = Objects[newOffset] = new BlueprintObjectList();
                }
                newList.AddObject(component);
                if (!All.Contains(component))
                {
                    All.Add(component);
                }
            }
            else if (All.Contains(component))
            {
                All.Remove(component);
            }

            Damage.Add(new BlueprintDamage(BlueprintDamageType.OBJECT_MOVE, tileX, tileY, level) { Component = component });
            OccupiedTilesDirty = true;

            component.blueprint = this;
            component.TileX = tileX;
            component.TileY = tileY;
            component.Level = level;
            component.Position = new Microsoft.Xna.Framework.Vector3(pos.x / 16.0f, pos.y / 16.0f, (level - 1) * 3.0f);
        }
Ejemplo n.º 23
0
 private bool SetPosition(VMEntity entity, LotTilePos pos, float radDir, VMContext context)
 {
     if (entity is VMGameObject)
     {
         var posChange = entity.SetPosition(pos, (Direction)(1 << (int)(Math.Round(DirectionUtils.PosMod(radDir, (float)Math.PI * 2) / (Math.PI/4)) % 8)), context);
         if (posChange != VMPlacementError.Success) return false;
     }
     else
     {
         entity.Position = pos;
         entity.RadianDirection = radDir;
     }
     return true;
 }