public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMSnapOperand)args; var avatar = context.Caller; //todo, can sometimes be an object?? see roaches object tile movement, snaps to its own routing slot var obj = context.StackObject; if (obj == context.Caller) { foreach (var objSub in obj.MultitileGroup.Objects) { objSub.MovedSelf = true; } if (obj is VMGameObject) { if (VM.UseWorld) { // the object moving this object may not be the caller... // for instance, we can be moved with a call tree. // we want to use the idle timings for that thread rather than our own. var idleObjID = context.VM.Scheduler.CurrentObjectID; var idleObj = context.VM.GetObjectById(idleObjID) ?? obj; foreach (var obj2 in obj.MultitileGroup.Objects) { obj2.WorldUI.PrepareSnapInterpolation(idleObj.WorldUI); } } } } if (operand.OriginOnly) { } //origin only. unused? SLOTItem slot = null; switch (operand.Mode) { case VMSnapSlotScope.StackVariable: slot = VMMemory.GetSlot(context, VMSlotScope.StackVariable, operand.Index); break; case VMSnapSlotScope.BeContained: return((context.StackObject.PlaceInSlot(context.Caller, 0, true, context.VM.Context)) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); case VMSnapSlotScope.InFront: slot = new SLOTItem { Type = 3, Standing = 1, MinProximity = 16, Rsflags = SLOTFlags.NORTH }; break; case VMSnapSlotScope.Literal: slot = VMMemory.GetSlot(context, VMSlotScope.Literal, operand.Index); break; case VMSnapSlotScope.Global: slot = VMMemory.GetSlot(context, VMSlotScope.Global, operand.Index); break; } if (slot == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } var dirSnap = (slot.Rsflags & SLOTFlags.SnapToDirection) > 0; if (operand.Mode != VMSnapSlotScope.BeContained) { var parser = new VMSlotParser(slot); var locations = parser.FindAvaliableLocations(obj, context.VM.Context, avatar); if (slot.SnapTargetSlot > -1) { if (!context.StackObject.PlaceInSlot(context.Caller, slot.SnapTargetSlot, true, context.VM.Context)) { return(VMPrimitiveExitCode.GOTO_FALSE); } if (locations.Count > 0) { avatar.RadianDirection = ((slot.Rsflags & SLOTFlags.SnapToDirection) > 0) ? locations[0].RadianDirection: avatar.RadianDirection; } } else { if (locations.Count > 0) { if (!SetPosition(avatar, locations[0].Position, (dirSnap) ? locations[0].RadianDirection : avatar.RadianDirection, operand.Shoo, context.VM.Context)) { //set direction regardless. TS1, experimental, breaks chairs snapping onto avatars. if this were correct, it also needs to be in the false branch. //if (dirSnap) avatar.RadianDirection = locations[0].RadianDirection; return(VMPrimitiveExitCode.GOTO_FALSE); } } else { if (parser.FailCode == Model.Routing.VMRouteFailCode.NoValidGoals) { avatar.SetValue(VMStackObjectVariable.PrimitiveResult, 2); } avatar.SetValue(VMStackObjectVariable.PrimitiveResultID, (parser.Blocker == null) ? (short)0 : parser.Blocker.ObjectID); return(VMPrimitiveExitCode.GOTO_FALSE); } } } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMGotoRoutingSlotOperand>(); var slot = VMMemory.GetSlot(context, operand.Type, operand.Data); var obj = context.StackObject; var avatar = (VMAvatar)context.Caller; /** * How we should be going about this: * * Step 1: Evaluate possible positons for sim to route to * Step 2: Eliminate all positions intersected by an object that does not allow person intersection * Step 3: Evaluate routes to all positions, choose shortest route and eliminate all positions that we cannot route to (ignoring people). * Step 4: Route to position. Stop when the next tile has a person in it and ask them to move if possible. * **/ //slot.Rsflags = TSO.Files.formats.iff.chunks.SLOTFlags.WEST; /** * Very little is kown about SLOTs so for now this is a place to dump comments * * Slots measure proximity in units of 16. 16 = 1 tile away from the object. * Global slots are in global.iff in a slot table with ID 100. * global.iff also has a string table #257 which provides labels for the SLOTs */ //Routing slots must be type 3. if (slot.Type == 3) { var tilePosition = new Vector2(obj.Position.X, obj.Position.Y); var possibleTargets = VMSlotParser.FindAvaliableLocations(obj, slot, context.VM.Context); if (possibleTargets.Count == 0) { return(VMPrimitiveExitCode.GOTO_FALSE); } //TODO: Route finding and pick best route var target = possibleTargets[0]; var pathFinder = context.Thread.PushNewPathFinder(context, possibleTargets); if (pathFinder != null) { return(VMPrimitiveExitCode.CONTINUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } //var test = new VMPathFinder(); //test.Caller = context.Caller; //test.Routine = context.Routine; //test.InitRoutes(possibleTargets); //avatar.SetPersonData(TSO.Simantics.model.VMPersonDataVariable.RouteEntryFlags, (short)target.Flags); //avatar.Direction = (Direction)target.Flags; //avatar.Position = new Vector3(target.Position.X + 0.5f, target.Position.Y + 0.5f, 0.0f); } return(VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMSnapOperand)args; var avatar = context.Caller; //todo, can sometimes be an object?? see roaches object tile movement, snaps to its own routing slot var obj = context.StackObject; SLOTItem slot = null; switch (operand.Mode) { case VMSnapSlotScope.StackVariable: slot = VMMemory.GetSlot(context, VMSlotScope.StackVariable, operand.Index); break; case VMSnapSlotScope.BeContained: return((context.StackObject.PlaceInSlot(context.Caller, 0, true, context.VM.Context)) ? VMPrimitiveExitCode.GOTO_TRUE:VMPrimitiveExitCode.GOTO_FALSE); case VMSnapSlotScope.InFront: slot = new SLOTItem { Type = 3, Standing = 1, MinProximity = 16, Rsflags = SLOTFlags.NORTH }; break; case VMSnapSlotScope.Literal: slot = VMMemory.GetSlot(context, VMSlotScope.Literal, operand.Index); break; case VMSnapSlotScope.Global: slot = VMMemory.GetSlot(context, VMSlotScope.Global, operand.Index); break; } if (operand.Mode != VMSnapSlotScope.BeContained) { var parser = new VMSlotParser(slot); var locations = parser.FindAvaliableLocations(obj, context.VM.Context, avatar); if (slot.SnapTargetSlot > -1) { if (!context.StackObject.PlaceInSlot(context.Caller, slot.SnapTargetSlot, true, context.VM.Context)) { return(VMPrimitiveExitCode.GOTO_FALSE); } if (locations.Count > 0) { avatar.RadianDirection = ((slot.Rsflags & SLOTFlags.SnapToDirection) > 0) ? locations[0].RadianDirection: avatar.RadianDirection; } } else { if (locations.Count > 0) { if (!SetPosition(avatar, locations[0].Position, ((slot.Rsflags & SLOTFlags.SnapToDirection) > 0) ? locations[0].RadianDirection : avatar.RadianDirection, context.VM.Context)) { return(VMPrimitiveExitCode.GOTO_FALSE); } } else { avatar.SetValue(VMStackObjectVariable.PrimitiveResultID, (parser.Blocker == null) ? (short)0 : parser.Blocker.ObjectID); return(VMPrimitiveExitCode.GOTO_FALSE); } } } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMSnapOperand>(); var avatar = (VMAvatar)context.Caller; //todo, can sometimes be an object?? see roaches object tile movement, snaps to its own routing slot var obj = context.StackObject; var prevContain = context.VM.GetObjectById(avatar.GetValue(VMStackObjectVariable.ContainerId)); if (prevContain != null) //if we are contained in an object, drop out of it. { prevContain.ClearSlot(avatar.GetValue(VMStackObjectVariable.SlotNumber)); } SLOTItem slot; VMFindLocationResult location; switch (operand.Mode) { case 0: slot = VMMemory.GetSlot(context, VMSlotScope.StackVariable, operand.Index); location = VMSlotParser.FindAvaliableLocations(obj, slot, context.VM.Context)[0]; avatar.Position = location.Position; avatar.Direction = (Direction)location.Flags; break; case 1: //be contained on stack object context.StackObject.PlaceInSlot(context.Caller, 0); break; case 2: var pos = obj.Position; switch (obj.Direction) { case tso.world.model.Direction.SOUTH: pos += new Vector3(0.0f, 1.0f, 0.0f); break; case tso.world.model.Direction.WEST: pos += new Vector3(-1.0f, 0.0f, 0.0f); break; case tso.world.model.Direction.EAST: pos += new Vector3(1.0f, 0.0f, 0.0f); break; case tso.world.model.Direction.NORTH: pos += new Vector3(0.0f, -1.0f, 0.0f); break; } avatar.Position = pos + new Vector3(0.5f, 0.5f, 0); break; case 3: slot = VMMemory.GetSlot(context, VMSlotScope.Literal, operand.Index); location = VMSlotParser.FindAvaliableLocations(obj, slot, context.VM.Context)[0]; avatar.Position = location.Position; avatar.Direction = (Direction)location.Flags; if (slot.SnapTargetSlot != -1) { context.StackObject.PlaceInSlot(context.Caller, slot.SnapTargetSlot); } break; case 4: slot = VMMemory.GetSlot(context, VMSlotScope.Global, operand.Index); location = VMSlotParser.FindAvaliableLocations(obj, slot, context.VM.Context)[0]; avatar.Position = location.Position; avatar.Direction = (Direction)location.Flags; break; } return(VMPrimitiveExitCode.GOTO_TRUE); }