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; }
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); }
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); }
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); }