public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand<VMLookTowardsOperand>();
            //TODO: primitive fails if object calls it
            VMAvatar sim = (VMAvatar)context.Caller;

            var result = new VMFindLocationResult();
            result.Position = new LotTilePos(sim.Position);

            switch (operand.Mode)
            {
                case VMLookTowardsMode.HeadTowardsObject:
                    return VMPrimitiveExitCode.GOTO_TRUE; //TODO: turning head towards things, with head seek timeout
                case VMLookTowardsMode.BodyTowardsCamera:
                    return VMPrimitiveExitCode.GOTO_TRUE; //does not work in TSO
                case VMLookTowardsMode.BodyTowardsStackObj:
                    result.RadianDirection = (float)GetDirectionTo(sim.Position, context.StackObject.Position);
                    result.Flags = RadianToFlags(result.RadianDirection);
                    break;
                case VMLookTowardsMode.BodyAwayFromStackObj:
                    result.RadianDirection = (float)GetDirectionTo(sim.Position, context.StackObject.Position);
                    result.RadianDirection = (float)((result.RadianDirection + Math.PI) % (Math.PI*2));
                    result.Flags = RadianToFlags(result.RadianDirection);
                    break;

            }

            var pathFinder = context.Thread.PushNewPathFinder(context, new List<VMFindLocationResult>() { result });
            if (pathFinder != null) return VMPrimitiveExitCode.CONTINUE;
            else return VMPrimitiveExitCode.GOTO_TRUE;
        }
        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;
        }
Пример #3
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args)
        {
            var operand = (VMLookTowardsOperand)args;
            //TODO: primitive fails if object calls it
            VMAvatar sim = (VMAvatar)context.Caller;

            var result = new VMFindLocationResult();

            result.Position = new LotTilePos(sim.Position);

            switch (operand.Mode)
            {
            case VMLookTowardsMode.HeadTowardsObject:
                return(VMPrimitiveExitCode.GOTO_TRUE);    //TODO: turning head towards things, with head seek timeout

            case VMLookTowardsMode.BodyTowardsCamera:
                return(VMPrimitiveExitCode.GOTO_TRUE);    //does not work in TSO

            case VMLookTowardsMode.BodyTowardsStackObj:
                result.RadianDirection = (float)GetDirectionTo(sim.Position, context.StackObject.Position);
                break;

            case VMLookTowardsMode.BodyAwayFromStackObj:
                result.RadianDirection = (float)GetDirectionTo(sim.Position, context.StackObject.Position);
                result.RadianDirection = (float)((result.RadianDirection + Math.PI) % (Math.PI * 2));
                break;
            }

            if (context.Thread.IsCheck)
            {
                return(VMPrimitiveExitCode.GOTO_FALSE);
            }
            var pathFinder = context.Thread.PushNewRoutingFrame(context, false); //use the path finder to do the turn animation.

            pathFinder.InitRoutes(new List <VMFindLocationResult>()
            {
                result
            });

            return(VMPrimitiveExitCode.CONTINUE);
        }
Пример #4
0
        private bool AttemptRoute(VMFindLocationResult route)
        {
            //returns false if there is no room portal route to the destination room.
            CurRoute = route;

            WalkTo = null; //reset routing state
            Walking = false;
            Turning = false;
            AttemptedChair = false;
            TurnTweak = 0;

            var avatar = (VMAvatar)Caller;

            //if we are routing to a chair, let it take over.
            if (route.Chair != null)
            {
                AttemptedChair = false;
                return true;
            }

            Rooms = new Stack<VMRoomPortal>();

            var DestRoom = VM.Context.GetRoomAt(route.Position);
            var MyRoom = VM.Context.GetRoomAt(avatar.Position);

            if (DestRoom == MyRoom || (route.Flags & SLOTFlags.IgnoreRooms) > 0) return true; //we don't have to do any room finding for this
            else {
                //find shortest room traversal to destination. Simple A* pathfind.
                //Portals are considered nodes to allow multiple portals between rooms to be considered.

                var openSet = new List<VMRoomPortal>(); //we use this like a queue, but we need certain functions for sorted queue that are only provided by list.
                var closedSet = new HashSet<VMRoomPortal>();

                var gScore = new Dictionary<VMRoomPortal, double>();
                var fScore = new Dictionary<VMRoomPortal, double>();
                var parents = new Dictionary<VMRoomPortal, VMRoomPortal>();

                var StartPortal = new VMRoomPortal(Caller.ObjectID, MyRoom); //consider the sim as a portal to this room (as a starting point)
                openSet.Add(StartPortal);
                gScore[StartPortal] = 0;
                fScore[StartPortal] = GetDist(Caller.Position, route.Position);

                while (openSet.Count != 0) {
                    var current = openSet[0];
                    openSet.RemoveAt(0);

                    if (current.TargetRoom == DestRoom) {
                        //this portal gets us to the room.
                        while (current != StartPortal) //push previous portals till we get to our first "portal", the sim in its current room (we have already "traversed" this portal)
                        {
                            Rooms.Push(current);
                            current = parents[current];
                        }
                        return true;
                    }

                    closedSet.Add(current);

                    var portals = VM.Context.RoomInfo[current.TargetRoom].Portals;

                    foreach (var portal in portals) { //evaluate all neighbor portals
                        if (closedSet.Contains(portal)) continue; //already evaluated!

                        var pos = VM.GetObjectById(portal.ObjectID).Position;
                        var gFromCurrent = gScore[current] + GetDist(VM.GetObjectById(current.ObjectID).Position, pos);
                        var newcomer = !openSet.Contains(portal);

                        if (newcomer || gFromCurrent < gScore[portal]) {
                            parents[portal] = current; //best parent for now
                            gScore[portal] = gFromCurrent;
                            fScore[portal] = gFromCurrent + GetDist(pos, route.Position);
                            if (newcomer) { //add and move to relevant position
                                OpenSetSortedInsert(openSet, fScore, portal);
                            } else { //remove and reinsert to refresh sort
                                openSet.Remove(portal);
                                OpenSetSortedInsert(openSet, fScore, portal);
                            }
                        }
                    }
                }

                return false;
            }
        }
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand <VMGotoRelativePositionOperand>();

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

            var result = new VMFindLocationResult();

            /**
             * Examples for reference
             * Fridge - Have Snack - In front of, facing
             */
            if (operand.Location == VMGotoRelativeLocation.InFrontOf)
            {
                /** Need to work out which side is in front? **/

                //TODO: My positions are wrong, what i call left front etc is wrong. Need to correct this eventually
                var location = obj.Position;
                switch (obj.Direction)
                {
                case tso.world.model.Direction.SOUTH:
                    location    += new Vector3(0.0f, 1.0f, 0.0f);
                    result.Flags = SLOTFlags.NORTH;
                    break;

                case tso.world.model.Direction.WEST:
                    location    += new Vector3(-1.0f, 0.0f, 0.0f);
                    result.Flags = SLOTFlags.EAST;
                    break;

                case tso.world.model.Direction.EAST:
                    location    += new Vector3(1.0f, 0.0f, 0.0f);
                    result.Flags = SLOTFlags.EAST;
                    break;

                case tso.world.model.Direction.NORTH:
                    location    += new Vector3(0.0f, -1.0f, 0.0f);
                    result.Flags = SLOTFlags.SOUTH;
                    break;
                }
                result.Position = location + new Vector3(0.5f, 0.5f, 0.0f);

                var pathFinder = context.Thread.PushNewPathFinder(context, new List <VMFindLocationResult>()
                {
                    result
                });
                if (pathFinder != null)
                {
                    return(VMPrimitiveExitCode.CONTINUE);
                }
                else
                {
                    return(VMPrimitiveExitCode.GOTO_FALSE);
                }
            }
            else if (operand.Location == VMGotoRelativeLocation.OnTopOf)
            {
                result.Position = obj.Position + new Vector3(0.5f, 0.5f, 0.0f);
                result.Flags    = (SLOTFlags)obj.Direction;

                var pathFinder = context.Thread.PushNewPathFinder(context, new List <VMFindLocationResult>()
                {
                    result
                });
                if (pathFinder != null)
                {
                    return(VMPrimitiveExitCode.CONTINUE);
                }
                else
                {
                    return(VMPrimitiveExitCode.GOTO_FALSE);
                }
            }
            //throw new Exception("Unknown goto relative");
            return(VMPrimitiveExitCode.GOTO_FALSE);
        }
Пример #6
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args)
        {
            var operand = (VMLookTowardsOperand)args;
            //TODO: primitive fails if object calls it
            VMAvatar sim = (VMAvatar)context.Caller;

            var result = new VMFindLocationResult();

            result.Position = new LotTilePos(sim.Position);

            LotTilePos pos = new LotTilePos();

            switch (operand.Mode)
            {
            case VMLookTowardsMode.HeadTowardsObject:
                //set default state
                sim.SetPersonData(VMPersonDataVariable.HeadSeekObject, context.StackObjectID);
                sim.SetPersonData(VMPersonDataVariable.HeadSeekState, 1);        //in progress flag only
                sim.SetPersonData(VMPersonDataVariable.HeadSeekLimitAction, 1);  //look back on limit?
                sim.SetPersonData(VMPersonDataVariable.HeadSeekFinishAction, 0); //unknown
                sim.SetPersonData(VMPersonDataVariable.HeadSeekTimeout, 0);      //forever
                return(VMPrimitiveExitCode.GOTO_TRUE);                           //TODO: turning head towards things, with head seek timeout

            case VMLookTowardsMode.BodyTowardsCamera:
                return(VMPrimitiveExitCode.GOTO_TRUE);    //does not work in TSO

            case VMLookTowardsMode.BodyTowardsStackObj:
                result.RadianDirection = (float)GetDirectionTo(sim.Position, context.StackObject.Position);
                break;

            case VMLookTowardsMode.BodyAwayFromStackObj:
                result.RadianDirection = (float)GetDirectionTo(sim.Position, context.StackObject.Position);
                result.RadianDirection = (float)((result.RadianDirection + Math.PI) % (Math.PI * 2));
                break;

            case VMLookTowardsMode.BodyTowardsAverageStackObj:
                foreach (var obj in context.StackObject.MultitileGroup.Objects)
                {
                    pos += obj.Position;
                }
                pos /= context.StackObject.MultitileGroup.Objects.Count;
                result.RadianDirection = (float)GetDirectionTo(sim.Position, pos);
                break;

            case VMLookTowardsMode.BodyAwayFromAverageStackObj:
                foreach (var obj in context.StackObject.MultitileGroup.Objects)
                {
                    pos += obj.Position;
                }
                pos /= context.StackObject.MultitileGroup.Objects.Count;
                result.RadianDirection = (float)GetDirectionTo(sim.Position, pos);
                result.RadianDirection = (float)((result.RadianDirection + Math.PI) % (Math.PI * 2));
                break;
            }

            if (context.Thread.IsCheck)
            {
                return(VMPrimitiveExitCode.GOTO_FALSE);
            }
            var pathFinder = context.Thread.PushNewRoutingFrame(context, false); //use the path finder to do the turn animation.

            pathFinder.InitRoutes(new List <VMFindLocationResult>()
            {
                result
            });

            return(VMPrimitiveExitCode.CONTINUE);
        }