public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMRunTreeByNameOperand>(); string name; if (operand.StringScope == 1) {//global name = context.Global.Resource.Get<STR>(operand.StringTable).GetString(operand.StringID-1); } else {//local name = context.CodeOwner.Get<STR>(operand.StringTable).GetString(operand.StringID-1); } if (context.Callee.TreeByName.ContainsKey(name)) { var tree = context.Callee.TreeByName[name]; //found it! now lets call the tree ;) } else { return VMPrimitiveExitCode.GOTO_FALSE; } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMChangeSuitOrAccessoryOperand>(); var avatar = (VMAvatar)context.Caller; if ((operand.Flags & VMChangeSuitOrAccessoryFlags.Update) == VMChangeSuitOrAccessoryFlags.Update) { //update outfit with outfit in stringset 304 with index in temp 0 avatar.BodyOutfit = Convert.ToUInt64(context.Callee.Object.Resource.Get<STR>(304).GetString((context.Thread.TempRegisters[0])), 16); } else { var suit = VMMemory.GetSuit(context, operand.SuitScope, operand.SuitData); if(suit == null){ return VMPrimitiveExitCode.GOTO_TRUE; } if ((operand.Flags & VMChangeSuitOrAccessoryFlags.Remove) == VMChangeSuitOrAccessoryFlags.Remove) { avatar.Avatar.RemoveAccessory(suit); } else { avatar.Avatar.AddAccessory(suit); } } return VMPrimitiveExitCode.GOTO_TRUE; }
//TODO: Behaviour for being notified out of idle and interaction canceling public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMIdleForInputOperand>(); if (operand.AllowPush == 1 && context.Thread.Queue.Count > 1) { //if there are any more interactions, we have been interrupted return VMPrimitiveExitCode.INTERRUPT; } if (context.Thread.Queue[0].Cancelled) { context.Caller.SetFlag(VMEntityFlags.NotifiedByIdleForInput, true); return VMPrimitiveExitCode.GOTO_TRUE; } if (context.Caller.Interrupt) { context.Caller.Interrupt = false; return VMPrimitiveExitCode.GOTO_TRUE; } var ticks = VMMemory.GetVariable(context, TSO.Simantics.engine.scopes.VMVariableScope.Parameters, operand.StackVarToDec); ticks--; if (ticks < 0) { return VMPrimitiveExitCode.GOTO_TRUE; } else { VMMemory.SetVariable(context, TSO.Simantics.engine.scopes.VMVariableScope.Parameters, operand.StackVarToDec, ticks); return VMPrimitiveExitCode.CONTINUE_NEXT_TICK; } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMGotoRelativePositionOperand>(); var obj = (VMGameObject)context.Callee; var avatar = (VMAvatar)context.Caller; /** * 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.LeftFront: location += new Vector3(0.0f, 1.0f, 0.0f); break; case tso.world.model.Direction.LeftBack: location += new Vector3(-1.0f, 0.0f, 0.0f); break; case tso.world.model.Direction.RightFront: location += new Vector3(1.0f, 0.0f, 0.0f); break; case tso.world.model.Direction.RightBack: location += new Vector3(0.0f, -1.0f, 0.0f); break; } avatar.Position = location + new Vector3(0.5f, 0.5f, 0.0f); return VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK; } throw new Exception("Unknown goto relative"); }
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<VMRefreshOperand>(); VMEntity target = null; switch (operand.TargetObject) { case 0: target = context.Caller; break; case 1: target = context.StackObject; break; } switch (operand.RefreshType) { case 0: //graphic if (target.GetType() == typeof(VMGameObject)) { var TargObj = (VMGameObject)target; TargObj.RefreshGraphic(); } break; } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMPlaySoundOperand>(); FWAV fwav = context.CodeOwner.Get<FWAV>(operand.EventID); if (fwav == null) fwav = context.VM.Context.Globals.Resource.Get<FWAV>(operand.EventID); if (fwav != null) { var thread = HITVM.Get().PlaySoundEvent(fwav.Name); if (thread != null) { var owner = (operand.StackObjAsSource)?context.StackObject:context.Caller; if (!thread.AlreadyOwns(owner.ObjectID)) thread.AddOwner(owner.ObjectID); var entry = new VMSoundEntry() { Thread = thread, Pan = !operand.NoPan, Zoom = !operand.NoZoom, Loop = operand.Loop, Name = fwav.Name }; owner.SoundThreads.Add(entry); owner.TickSounds(); } } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMGenericTSOCallOperand>(); if ( operand.Call == VMGenericTSOCallMode.GetIsPendingDeletion || operand.Call == VMGenericTSOCallMode.IsTemp0AvatarIgnoringTemp1Avatar || operand.Call == VMGenericTSOCallMode.IsGlobalBroken ) return VMPrimitiveExitCode.GOTO_FALSE; else if (operand.Call == VMGenericTSOCallMode.SwapMyAndStackObjectsSlots) { int total = Math.Min(context.StackObject.TotalSlots(), context.Caller.TotalSlots()); for (int i = 0; i < total; i++) { VMEntity temp1 = context.Caller.GetSlot(i); VMEntity temp2 = context.StackObject.GetSlot(i); context.Caller.ClearSlot(i); context.StackObject.ClearSlot(i); context.Caller.PlaceInSlot(temp2, i); context.StackObject.PlaceInSlot(temp1, i); } } else if (operand.Call == VMGenericTSOCallMode.TestStackObject) return (context.StackObject != null) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE; 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) { var operand = context.GetCurrentOperand<VMTransferFundsOperand>(); /** Bit of a legacy thing going on here so there is a helper to translate old owner values into the new scope handler **/ var ammount = VMMemory.GetVariable(context, operand.GetAmmountOwner(), operand.AmmountData); return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMFindBestObjectForFunctionOperand>(); var entities = context.VM.Entities; int bestScore = int.MinValue; VMEntity bestObj = null; var entry = VMFindBestObjectForFunction.FunctionToEntryPoint[operand.Function]; for (int i=0; i<entities.Count; i++) { var ent = entities[i]; if (ent.ObjectData[(int)VMStackObjectVariable.LockoutCount] > 0) continue; //this object is not important!!! if (ent.EntryPoints[entry].ActionFunction != 0) { bool Execute; if (ent.EntryPoints[entry].ConditionFunction != 0) { var Behavior = ent.GetBHAVWithOwner(ent.EntryPoints[entry].ConditionFunction, context.VM.Context); var test = VMThread.EvaluateCheck(context.VM.Context, context.Caller, new VMQueuedAction(){ Callee = ent, CodeOwner = Behavior.owner, StackObject = ent, Routine = context.VM.Assemble(Behavior.bhav), }); Execute = (test == VMPrimitiveExitCode.RETURN_TRUE); } else { Execute = true; } if (Execute) { //calculate the score for this object. int score = 0; if (ScoreVar[operand.Function] != VMStackObjectVariable.Invalid) { score = ent.GetValue(ScoreVar[operand.Function]); } LotTilePos posDiff = ent.Position - context.Caller.Position; score -= (int)Math.Sqrt(posDiff.x*posDiff.x+posDiff.y*posDiff.y)/3; if (score > bestScore) { bestScore = score; bestObj = ent; } } } } if (bestObj != null) { context.StackObject = bestObj; return VMPrimitiveExitCode.GOTO_TRUE; } else return VMPrimitiveExitCode.GOTO_FALSE; //couldn't find an object! :'( }
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) { //TODO: Implement this. var operand = context.GetCurrentOperand<VMSetBalloonHeadlineOperand>(); if (operand.Duration == 0) { /** Clear **/ } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMRunFunctionalTreeOperand>(); var entry = VMFindBestObjectForFunction.FunctionToEntryPoint[operand.Function]; var ent = context.StackObject; if (ent.EntryPoints[entry].ActionFunction != 0) { bool Execute; if (ent.EntryPoints[entry].ConditionFunction != 0) //check if we can definitely execute this... { var Behavior = ent.GetBHAVWithOwner(ent.EntryPoints[entry].ConditionFunction, context.VM.Context); Execute = (VMThread.EvaluateCheck(context.VM.Context, context.Caller, new VMQueuedAction() { Callee = ent, CodeOwner = Behavior.owner, StackObject = ent, Routine = context.VM.Assemble(Behavior.bhav), }) == VMPrimitiveExitCode.RETURN_TRUE); } else { Execute = true; } if (Execute) { //push it onto our stack, except now the stack object owns our soul! var Behavior = ent.GetBHAVWithOwner(ent.EntryPoints[entry].ActionFunction, context.VM.Context); var routine = context.VM.Assemble(Behavior.bhav); var childFrame = new VMStackFrame { Routine = routine, Caller = context.Caller, Callee = ent, CodeOwner = Behavior.owner, StackObject = ent }; if (operand.Flags > 0) context.Thread.Queue[0].IconOwner = context.StackObject; childFrame.Args = new short[routine.Arguments]; context.Thread.Push(childFrame); return VMPrimitiveExitCode.CONTINUE; } else { return VMPrimitiveExitCode.GOTO_FALSE; } } else { return VMPrimitiveExitCode.GOTO_FALSE; } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMRandomNumberOperand>(); var rangeValue = (ushort)VMMemory.GetVariable(context, operand.RangeScope, operand.RangeData); var result = context.VM.Context.NextRandom(rangeValue); VMMemory.SetVariable(context, operand.DestinationScope, operand.DestinationData, (short)result); if (operand.RangeData == 8327) result = 0; return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { //TODO: Implement this. var operand = context.GetCurrentOperand <VMSetBalloonHeadlineOperand>(); if (operand.Duration == 0) { /** Clear **/ } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMSetToNextOperand>(); var targetValue = VMMemory.GetVariable(context, operand.GetTargetOwner(), operand.GetTargetData()); if (operand.SearchType == VMSetToNextSearchType.ObjectOfType){ //TODO: Implement! return VMPrimitiveExitCode.GOTO_FALSE; } throw new Exception("Unknown search type"); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMPushInteractionOperand>(); VMEntity interactionSource; if ((operand.Flags & (1 << 1)) > 0) interactionSource = context.VM.GetObjectById((short)context.Locals[operand.ObjectLocation]); else interactionSource = context.VM.GetObjectById((short)context.Args[operand.ObjectLocation]); VMQueuePriority priority; if (operand.Priority == 0) { priority = context.Thread.Queue[0].Priority; } else { priority = (VMQueuePriority)(operand.Priority - 1); } BHAV bhav; GameIffResource CodeOwner = null; var Action = interactionSource.TreeTable.InteractionByIndex[operand.Interaction]; ushort ActionID = Action.ActionFunction; CodeOwner = interactionSource.Object.Resource; if (ActionID < 4096) { //global bhav = null; //unimp as it has to access the context to get this. } else if (ActionID < 8192) { //local bhav = interactionSource.Object.Resource.Get<BHAV>(ActionID); } else { //semi-global bhav = interactionSource.SemiGlobal.Resource.Get<BHAV>(ActionID); } var routine = context.VM.Assemble(bhav); context.StackObject.Thread.EnqueueAction( new TSO.Simantics.engine.VMQueuedAction { Callee = interactionSource, CodeOwner = CodeOwner, Routine = routine, Name = interactionSource.TreeTableStrings.GetString((int)Action.TTAIndex), StackObject = interactionSource, InteractionNumber = operand.Interaction, Priority = priority } ); return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMSetToNextOperand>(); var targetValue = VMMemory.GetVariable(context, operand.GetTargetOwner(), operand.GetTargetData()); if (operand.SearchType == VMSetToNextSearchType.ObjectOfType) { //TODO: Implement! return(VMPrimitiveExitCode.GOTO_FALSE); } throw new Exception("Unknown search type"); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMRunFunctionalTreeOperand>(); var entry = VMFindBestObjectForFunction.FunctionToEntryPoint[operand.Function]; var ent = context.StackObject; if (ent.EntryPoints[entry].ActionFunction != 0) { bool Execute; if (ent.EntryPoints[entry].ConditionFunction != 0) //check if we can definitely execute this... { var Behavior = ent.GetBHAVWithOwner(ent.EntryPoints[entry].ConditionFunction, context.VM.Context); Execute = (VMThread.EvaluateCheck(context.VM.Context, context.Caller, new VMQueuedAction() { Callee = ent, CodeOwner = Behavior.owner, StackObject = ent, Routine = context.VM.Assemble(Behavior.bhav), }) == VMPrimitiveExitCode.RETURN_TRUE); } else { Execute = true; } if (Execute) { //push it onto our stack, except now the stack object owns our soul! var Behavior = ent.GetBHAVWithOwner(ent.EntryPoints[entry].ActionFunction, context.VM.Context); var routine = context.VM.Assemble(Behavior.bhav); var childFrame = new VMStackFrame { Routine = routine, Caller = context.Caller, Callee = ent, CodeOwner = Behavior.owner, StackObject = ent }; childFrame.Args = new short[routine.Arguments]; context.Thread.Push(childFrame); return(VMPrimitiveExitCode.CONTINUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } } else { return(VMPrimitiveExitCode.GOTO_FALSE); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMOnlineJobsCallOperand>(); switch (operand.Call) { case VMOnlineJobsCallMode.SetControllerID: context.VM.SetGlobalValue(21, (context.StackObject == null)?(short)0:context.StackObject.ObjectID); break; } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMRemoveObjectInstanceOperand>(); VMEntity obj; if (operand.Target == 0) obj = context.Caller; else obj = context.StackObject; obj.Delete(operand.CleanupAll, context.VM.Context); //if (obj == context.StackObject) context.StackObject = null; return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMTestObjectTypeOperand>(); var objectID = VMMemory.GetVariable(context, operand.IdOwner, operand.IdData); var obj = context.VM.GetObjectById(objectID); //var obj = context.StackObject; if (obj == null){ return VMPrimitiveExitCode.ERROR; } if (obj.Object.GUID == operand.GUID) return VMPrimitiveExitCode.GOTO_TRUE; //is my guid same? else if (obj.MasterDefinition != null && (obj.MasterDefinition.GUID == operand.GUID)) return VMPrimitiveExitCode.GOTO_TRUE; //is master guid same? else return VMPrimitiveExitCode.GOTO_FALSE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMStopAllSoundsOperand>(); var owner = (operand.Flags == 1)?context.StackObject:context.Caller; var threads = owner.SoundThreads; for (int i = 0; i < threads.Count; i++) { threads[i].Thread.RemoveOwner(owner.ObjectID); } threads.Clear(); return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMStopAllSoundsOperand>(); var owner = (operand.Flags == 1)?context.StackObject:context.Caller; var threads = owner.SoundThreads; for (int i = 0; i < threads.Count; i++) { threads[i].Thread.RemoveOwner(owner.ObjectID); } threads.Clear(); return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMRemoveObjectInstanceOperand>(); VMEntity obj; if (operand.Target == 0) obj = context.Caller; else obj = context.StackObject; if (operand.CleanupAll && obj.MultitileGroup != null) { for (int i = 0; i < obj.MultitileGroup.Objects.Count; i++) context.VM.Context.RemoveObjectInstance(obj.MultitileGroup.Objects[i]); //remove all multitile parts } else context.VM.Context.RemoveObjectInstance(obj); return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMRunTreeByNameOperand>(); string name; if (operand.StringScope == 1) {//global name = context.Global.Resource.Get <STR>(operand.StringTable).GetString(operand.StringID - 1); } else {//local name = context.CodeOwner.Get <STR>(operand.StringTable).GetString(operand.StringID - 1); } if (context.StackObject.TreeByName == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } if (context.StackObject.TreeByName.ContainsKey(name)) { var tree = context.StackObject.TreeByName[name]; if (operand.Destination == 2) { context.Thread.ExecuteSubRoutine(context, tree.bhav, tree.Owner, new VMSubRoutineOperand()); return(VMPrimitiveExitCode.CONTINUE); //push onto my stack - acts like a subroutine. } else if (operand.Destination == 0) { context.Caller.Thread.RunInMyStack(tree.bhav, tree.Owner); return(VMPrimitiveExitCode.GOTO_TRUE); //run in my stack } else { context.StackObject.Thread.RunInMyStack(tree.bhav, tree.Owner); return(VMPrimitiveExitCode.GOTO_TRUE); //run in stack obj's stack } //found it! now lets call the tree ;) } else { return(VMPrimitiveExitCode.GOTO_FALSE); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMFindBestObjectForFunctionOperand>(); var entities = context.VM.Entities; var entry = VMFindBestObjectForFunction.FunctionToEntryPoint[operand.Function]; for (int i = 0; i < entities.Count; i++) { var ent = entities[i]; if (ent.ObjectData[(int)VMStackObjectVariable.LockoutCount] > 0) { continue; //this object is not important!!! } if (ent.EntryPoints[entry].ActionFunction != 0) { bool Execute; if (ent.EntryPoints[entry].ConditionFunction != 0) { var Behavior = ent.GetBHAVWithOwner(ent.EntryPoints[entry].ConditionFunction, context.VM.Context); var test = VMThread.EvaluateCheck(context.VM.Context, context.Caller, new VMQueuedAction() { Callee = ent, CodeOwner = Behavior.owner, StackObject = ent, Routine = context.VM.Assemble(Behavior.bhav), }); Execute = (test == VMPrimitiveExitCode.RETURN_TRUE); } else { Execute = true; } if (Execute) { //we can run this, it's suitable, yes I'LL TAKE IT context.StackObject = ent; return(VMPrimitiveExitCode.GOTO_TRUE); } //if not just keep searching } } return(VMPrimitiveExitCode.GOTO_FALSE); //couldn't find an object! :'( }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMRunTreeByNameOperand>(); string name; STR res = null; if (operand.StringScope == 1) {//global res = context.Global.Resource.Get<STR>(operand.StringTable); } else {//local if (context.Routine.ID >= 8192 && context.CodeOwner.SemiGlobal != null) res = context.CodeOwner.SemiGlobal.Get<STR>(operand.StringTable); if (res == null) res = context.CodeOwner.Get<STR>(operand.StringTable); } if (res == null) return VMPrimitiveExitCode.GOTO_FALSE; name = res.GetString(operand.StringID-1); if (context.StackObject.TreeByName == null) return VMPrimitiveExitCode.GOTO_FALSE; if (context.StackObject.TreeByName.ContainsKey(name)) { var tree = context.StackObject.TreeByName[name]; if (operand.Destination == 2) { context.Thread.ExecuteSubRoutine(context, tree.bhav, tree.Owner, new VMSubRoutineOperand(context.Thread.TempRegisters)); return VMPrimitiveExitCode.CONTINUE; //push onto my stack - acts like a subroutine. } else if (operand.Destination == 0) { return context.Caller.Thread.RunInMyStack(tree.bhav, tree.Owner, context.Thread.TempRegisters, context.StackObject) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE; //run in my stack } else { return context.StackObject.Thread.RunInMyStack(tree.bhav, tree.Owner, context.Thread.TempRegisters, context.StackObject) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE; //run in stack obj's stack } //found it! now lets call the tree ;) } else { return VMPrimitiveExitCode.GOTO_FALSE; } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMFindLocationForOperand>(); var refObj = (operand.UseLocalAsRef) ? context.VM.GetObjectById((short)context.Locals[operand.Local]) : context.Caller; short container = context.StackObject.GetValue(VMStackObjectVariable.ContainerId); if (container != 0) context.VM.GetObjectById(container).ClearSlot(context.StackObject.GetValue(VMStackObjectVariable.SlotNumber)); //if object is in a slot, eject it if (operand.Mode == 0) //todo: detect collisions and place close to intended position if AllowIntersection is false. { //default //also todo.. a better way of moving objects lol (especially for multitile) context.StackObject.SetPosition((short)refObj.Position.X, (short)refObj.Position.Y, (sbyte)refObj.WorldUI.Level, context.StackObject.Direction, context.VM.Context); } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMRandomNumberOperand>(); var rangeValue = (ushort)VMMemory.GetVariable(context, operand.RangeScope, operand.RangeData); var result = context.VM.Context.NextRandom(rangeValue); VMMemory.SetVariable(context, operand.DestinationScope, operand.DestinationData, (short)result); if (operand.RangeData == 8327) { result = 0; } 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 = (VMGameObject)context.Callee; var avatar = (VMAvatar)context.Caller; //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 */ //Dont really know what 3 means, maybe relative to object? if (slot.Type == 3) { var tilePosition = new Vector2(obj.Position.X, obj.Position.Y); var min = slot.MinProximity; var max = slot.MaxProximity; var desired = slot.OptimalProximity; if (max == 0) { max = min; } if (desired == 0) { desired = min; } var possibleTargets = VMRouteFinder.FindAvaliableLocations(tilePosition, slot.Rsflags, min, max, desired); if (possibleTargets.Count == 0) { return(VMPrimitiveExitCode.GOTO_FALSE); } //TODO: Route finding and pick best route var target = possibleTargets[0]; 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) { var operand = context.GetCurrentOperand<VMRandomNumberOperand>(); var description = "random: less than " + VMMemory.DescribeVariable(context, operand.RangeScope, operand.RangeData); description += " written to " + VMMemory.DescribeVariable(context, operand.DestinationScope, operand.DestinationData); Trace(description); //TODO: Make this deterministic var rangeValue = VMMemory.GetVariable(context, operand.RangeScope, operand.RangeData); var rand = new Random(); var result = rand.Next(rangeValue); VMMemory.SetVariable(context, operand.DestinationScope, operand.DestinationData, (short)result); Trace("set " + operand.DestinationScope + " #" + operand.DestinationData + " to random " + result); return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMGetDistanceToOperand>(); var obj1 = context.StackObject; VMEntity obj2; if ((operand.Flags & 1) > 0) obj2 = context.Caller; else obj2 = context.VM.GetObjectById(VMMemory.GetVariable(context, (VMVariableScope)operand.ObjectScope, operand.OScopeData)); var pos1 = obj1.Position; var pos2 = obj2.Position; var result = (short)Math.Floor(Math.Sqrt(Math.Pow(Math.Floor(pos1.X) - Math.Floor(pos2.X), 2) + Math.Pow(Math.Floor(pos1.Y) - Math.Floor(pos2.Y), 2))); context.Thread.TempRegisters[operand.TempNum] = result; return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMGenericTSOCallOperand>(); if (operand.Call == 48 || operand.Call == 31) { return(VMPrimitiveExitCode.GOTO_FALSE); } else if (operand.Call == 40) { return((context.StackObject != null) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); } else { return(VMPrimitiveExitCode.GOTO_TRUE); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMSetMotiveChangeOperand>(); var avatar = ((VMAvatar)context.Caller); if ((operand.Flags & VMSetMotiveChangeFlags.ClearAll) > 0) { avatar.ClearMotiveChanges(); } else { var PerHourChange = VMMemory.GetVariable(context, (VMVariableScope)operand.DeltaOwner, (ushort)operand.DeltaData); var MaxValue = VMMemory.GetVariable(context, (VMVariableScope)operand.MaxOwner, (ushort)operand.MaxData); avatar.SetMotiveChange(operand.Motive, PerHourChange, MaxValue); } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMTestObjectTypeOperand>(); var objectID = VMMemory.GetVariable(context, operand.IdOwner, operand.IdData); var obj = context.VM.GetObjectById(objectID); if (obj == null){ return VMPrimitiveExitCode.ERROR; } //TODO: This should check if obj or masterID is type not just single tile if (obj.Object.GUID == operand.GUID) { return VMPrimitiveExitCode.GOTO_TRUE; }else{ return VMPrimitiveExitCode.GOTO_FALSE; } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand<VMSetMotiveChangeOperand>(); var avatar = ((VMAvatar)context.Caller); if ((operand.Flags & VMSetMotiveChangeFlags.ClearAll) > 0) { avatar.ClearMotiveChanges(); } else { var PerHourChange = VMMemory.GetVariable(context, (VMVariableScope)operand.DeltaOwner, (ushort)operand.DeltaData); var MaxValue = VMMemory.GetVariable(context, (VMVariableScope)operand.MaxOwner, (ushort)operand.MaxData); avatar.SetMotiveChange(operand.Motive, PerHourChange, MaxValue); } 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 = 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. * **/ //Routing slots must be type 3. if (slot.Type == 3){ 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) { var operand = context.GetCurrentOperand<VMSleepOperand>(); Trace("sleep: --(" + VMMemory.DescribeVariable(context, VMVariableScope.Local, operand.StackVarToDec) + ") != 0"); var ticks = VMMemory.GetVariable(context, tso.simantics.engine.scopes.VMVariableScope.Local, operand.StackVarToDec); ticks--; if (ticks <= 0) { return VMPrimitiveExitCode.GOTO_TRUE; } else { VMMemory.SetVariable(context, tso.simantics.engine.scopes.VMVariableScope.Local, operand.StackVarToDec, ticks); return VMPrimitiveExitCode.CONTINUE_NEXT_TICK; } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMFindLocationForOperand>(); var refObj = (operand.UseLocalAsRef) ? context.VM.GetObjectById((short)context.Locals[operand.Local]) : context.Caller; short container = context.StackObject.GetValue(VMStackObjectVariable.ContainerId); if (container != 0) { context.VM.GetObjectById(container).ClearSlot(context.StackObject.GetValue(VMStackObjectVariable.SlotNumber)); //if object is in a slot, eject it } if (operand.Mode == 0) //todo: detect collisions and place close to intended position if AllowIntersection is false. { //default //also todo.. a better way of moving objects lol (especially for multitile) context.StackObject.SetPosition((short)refObj.Position.X, (short)refObj.Position.Y, (sbyte)refObj.WorldUI.Level, context.StackObject.Direction, context.VM.Context); } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMSleepOperand>(); Trace("sleep: --(" + VMMemory.DescribeVariable(context, VMVariableScope.Local, operand.StackVarToDec) + ") != 0"); var ticks = VMMemory.GetVariable(context, tso.simantics.engine.scopes.VMVariableScope.Local, operand.StackVarToDec); ticks--; if (ticks < 0) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { VMMemory.SetVariable(context, tso.simantics.engine.scopes.VMVariableScope.Local, operand.StackVarToDec, ticks); return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMSleepOperand>(); var ticks = VMMemory.GetVariable(context, TSO.Simantics.engine.scopes.VMVariableScope.Parameters, operand.StackVarToDec); //if (ticks > 0) Trace("sleeping...") ; ticks--; if (ticks < 0) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { VMMemory.SetVariable(context, TSO.Simantics.engine.scopes.VMVariableScope.Parameters, operand.StackVarToDec, ticks); return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMRandomNumberOperand>(); var description = "random: less than " + VMMemory.DescribeVariable(context, operand.RangeScope, operand.RangeData); description += " written to " + VMMemory.DescribeVariable(context, operand.DestinationScope, operand.DestinationData); Trace(description); //TODO: Make this deterministic var rangeValue = VMMemory.GetVariable(context, operand.RangeScope, operand.RangeData); var rand = new Random(); var result = rand.Next(rangeValue); VMMemory.SetVariable(context, operand.DestinationScope, operand.DestinationData, (short)result); Trace("set " + operand.DestinationScope + " #" + operand.DestinationData + " to random " + result); return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMGotoRelativePositionOperand>(); var obj = (VMGameObject)context.Callee; var avatar = (VMAvatar)context.Caller; /** * 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.LeftFront: location += new Vector3(0.0f, 1.0f, 0.0f); break; case tso.world.model.Direction.LeftBack: location += new Vector3(-1.0f, 0.0f, 0.0f); break; case tso.world.model.Direction.RightFront: location += new Vector3(1.0f, 0.0f, 0.0f); break; case tso.world.model.Direction.RightBack: location += new Vector3(0.0f, -1.0f, 0.0f); break; } avatar.Position = location + new Vector3(0.5f, 0.5f, 0.0f); return(VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK); } throw new Exception("Unknown goto relative"); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMTestObjectTypeOperand>(); var objectID = VMMemory.GetVariable(context, operand.IdOwner, operand.IdData); var obj = context.VM.GetObjectById(objectID); if (obj == null) { return(VMPrimitiveExitCode.ERROR); } //TODO: This should check if obj or masterID is type not just single tile if (obj.Object.GUID == operand.GUID) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMChangeSuitOrAccessoryOperand>(); var suit = VMMemory.GetSuit(context, operand.SuitScope, operand.SuitData); var avatar = (VMAvatar)context.Caller; if (suit == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } if ((operand.Flags & VMChangeSuitOrAccessoryFlags.Remove) == VMChangeSuitOrAccessoryFlags.Remove) { avatar.Avatar.RemoveAccessory(suit); } else { avatar.Avatar.AddAccessory(suit); } return(VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMPlaySoundOperand>(); FWAV fwav = context.CodeOwner.Get <FWAV>(operand.EventID); if (fwav == null) { fwav = context.VM.Context.Globals.Resource.Get <FWAV>(operand.EventID); } if (fwav != null) { var thread = HITVM.Get().PlaySoundEvent(fwav.Name); if (thread != null) { var owner = (operand.StackObjAsSource)?context.StackObject:context.Caller; if (!thread.AlreadyOwns(owner.ObjectID)) { thread.AddOwner(owner.ObjectID); } var entry = new VMSoundEntry() { Thread = thread, Pan = !operand.NoPan, Zoom = !operand.NoZoom, Loop = operand.Loop, Name = fwav.Name }; owner.SoundThreads.Add(entry); owner.TickSounds(); } } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMGrabOperand>(); if (context.Caller.GetSlot(0) == null) { var prevContain = context.VM.GetObjectById(context.StackObject.GetValue(VMStackObjectVariable.ContainerId)); if (prevContain != null) { prevContain.ClearSlot(context.StackObject.GetValue(VMStackObjectVariable.SlotNumber)); } context.Caller.PlaceInSlot(context.StackObject, 0); var avatar = (VMAvatar)context.Caller; avatar.CarryAnimation = TSO.Content.Content.Get().AvatarAnimations.Get("a2o-rarm-carry-loop.anim"); avatar.CarryAnimationState = new VMAnimationState(); //set default carry animation } else { return(VMPrimitiveExitCode.GOTO_FALSE); } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMGetDistanceToOperand>(); var obj1 = context.StackObject; VMEntity obj2; if ((operand.Flags & 1) > 0) { obj2 = context.Caller; } else { obj2 = context.VM.GetObjectById(VMMemory.GetVariable(context, (VMVariableScope)operand.ObjectScope, operand.OScopeData)); } var pos1 = obj1.Position; var pos2 = obj2.Position; var result = (short)Math.Floor(Math.Sqrt(Math.Pow(Math.Floor(pos1.X) - Math.Floor(pos2.X), 2) + Math.Pow(Math.Floor(pos1.Y) - Math.Floor(pos2.Y), 2))); context.Thread.TempRegisters[operand.TempNum] = result; return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMRelationshipOperand>(); VMEntity obj1; VMEntity obj2; switch (operand.Mode) { case 0: //from me to stack object obj1 = context.Caller; obj2 = context.StackObject; break; case 1: //from stack object to me obj1 = context.StackObject; obj2 = context.Caller; break; case 2: //from stack object to object in local obj1 = context.StackObject; obj2 = context.VM.GetObjectById((short)context.Locals[operand.Local]); break; case 3: //from object in local to stack object obj1 = context.VM.GetObjectById((short)context.Locals[operand.Local]); obj2 = context.StackObject; break; default: throw new Exception("Invalid relationship type!"); } var rels = obj1.MeToObject; var targId = (ushort)obj2.ObjectID; //check if exists if (!rels.ContainsKey(targId)) { if (operand.FailIfTooSmall) { return(VMPrimitiveExitCode.GOTO_FALSE); } else { rels.Add(targId, new Dictionary <short, short>()); } } if (!rels[targId].ContainsKey(operand.RelVar)) { if (operand.FailIfTooSmall) { return(VMPrimitiveExitCode.GOTO_FALSE); } else { rels[targId].Add(operand.RelVar, 0); } } if (operand.SetMode == 1) { //todo, special system for server persistent avatars and pets var value = VMMemory.GetVariable(context, (VMVariableScope)operand.VarScope, operand.VarData); rels[targId][operand.RelVar] = value; } else if (operand.SetMode == 2) { var value = VMMemory.GetVariable(context, (VMVariableScope)operand.VarScope, operand.VarData); rels[targId][operand.RelVar] += value; } else if (operand.SetMode == 0) { VMMemory.SetVariable(context, (VMVariableScope)operand.VarScope, operand.VarData, rels[targId][operand.RelVar]); } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMReachOperand>(); int height; if (operand.Mode == 0) { //reach to stack object height = (int)Math.Round(context.StackObject.WorldUI.Position.Z * 4); //todo, factor in second floor by making height differential to sim height } else if (operand.Mode == 1) { var slotNum = context.Args[operand.SlotParam]; var slot = context.StackObject.Slots.Slots[0][slotNum]; if (slot != null) { height = (int)Math.Round((slot.Offset.Z == 0) ? slot.Height : slot.Offset.Z); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } } else { //reach to mouth is unimplemented so no, also none others exist after throw new Exception("Reach to mouth not implemented!"); } string animationName; if (height < 2) { animationName = "a2o-reach-floorht.anim"; } else if (height < 4) { animationName = "a2o-reach-seatht.anim"; } else { animationName = "a2o-reach-tableht.anim"; } var animation = TSO.Content.Content.Get().AvatarAnimations.Get(animationName); if (animation == null) { return(VMPrimitiveExitCode.ERROR); } var avatar = (VMAvatar)context.Caller; /** Are we starting the animation or progressing it? **/ if (avatar.CurrentAnimation == null || avatar.CurrentAnimation != animation) { //start the grab! /** Start it **/ avatar.CurrentAnimation = animation; avatar.CurrentAnimationState = new VMAnimationState(); avatar.Avatar.LeftHandGesture = SimHandGesture.Idle; avatar.Avatar.RightHandGesture = SimHandGesture.Idle; failed = false; foreach (var motion in animation.Motions) { if (motion.TimeProperties == null) { continue; } foreach (var tp in motion.TimeProperties) { foreach (var item in tp.Items) { avatar.CurrentAnimationState.TimePropertyLists.Add(item); } } } /** Sort time property lists by time **/ avatar.CurrentAnimationState.TimePropertyLists.Sort(new TimePropertyListItemSorter()); return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } else { if (avatar.CurrentAnimationState.EndReached) { avatar.CurrentAnimation = null; if (failed) { return(VMPrimitiveExitCode.GOTO_FALSE); } return(VMPrimitiveExitCode.GOTO_TRUE); } else if (avatar.CurrentAnimationState.EventFired) { if (avatar.CurrentAnimationState.EventCode == 0) { //do the grab/drop if (operand.Mode == 0) { //pick up stack object. no drop condition if (context.Caller.GetSlot(0) == null) { var prevContain = context.VM.GetObjectById(context.StackObject.GetValue(VMStackObjectVariable.ContainerId)); if (prevContain != null) { prevContain.ClearSlot(context.StackObject.GetValue(VMStackObjectVariable.SlotNumber)); } context.Caller.PlaceInSlot(context.StackObject, 0); avatar.CarryAnimation = TSO.Content.Content.Get().AvatarAnimations.Get("a2o-rarm-carry-loop.anim"); avatar.CarryAnimationState = new VMAnimationState(); //set default carry animation } else { failed = true; } } else if (operand.Mode == 1) { //grab or drop, depending on if we're holding something var holding = context.Caller.GetSlot(0); var slotNum = context.Args[operand.SlotParam]; if (holding == null) { //grab var item = context.StackObject.GetSlot(slotNum); if (item != null) { context.StackObject.ClearSlot(slotNum); context.Caller.PlaceInSlot(item, 0); avatar.CarryAnimation = TSO.Content.Content.Get().AvatarAnimations.Get("a2o-rarm-carry-loop.anim"); avatar.CarryAnimationState = new VMAnimationState(); //set default carry animation } else { failed = true; //can't grab from an empty space } } else //drop { var itemTest = context.StackObject.GetSlot(slotNum); if (itemTest == null) { context.Caller.ClearSlot(0); context.StackObject.PlaceInSlot(holding, slotNum); avatar.CarryAnimation = null; } else { failed = true; //can't drop in an occupied space } } } } avatar.CurrentAnimationState.EventFired = false; //clear fired flag return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } else { return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMExpressionOperand>(); var description = "expression: " + VMMemory.DescribeVariable(context, operand.LhsOwner, operand.LhsData); description += " "; description += OperatorToString(operand.Operator); description += " "; description += VMMemory.DescribeVariable(context, operand.RhsOwner, operand.RhsData); Trace(description); short rhsValue = 0; short lhsValue = 0; bool setResult = false; switch (operand.Operator) { /** Modifiers **/ case VMExpressionOperator.Assign: rhsValue = VMMemory.GetVariable(context, operand.RhsOwner, operand.RhsData); setResult = VMMemory.SetVariable(context, operand.LhsOwner, operand.LhsData, rhsValue); if (setResult) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } /** ++ and < **/ case VMExpressionOperator.IncAndLessThan: lhsValue = VMMemory.GetVariable(context, operand.LhsOwner, operand.LhsData); lhsValue++; VMMemory.SetVariable(context, operand.LhsOwner, operand.LhsData, lhsValue); rhsValue = VMMemory.GetVariable(context, operand.RhsOwner, operand.RhsData); if (lhsValue < rhsValue) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } case VMExpressionOperator.SetFlag: lhsValue = VMMemory.GetVariable(context, operand.LhsOwner, operand.LhsData); rhsValue = VMMemory.GetVariable(context, operand.RhsOwner, operand.RhsData); var bitval = 1 << (rhsValue - 1); lhsValue |= (short)bitval; if (VMMemory.SetVariable(context, operand.LhsOwner, operand.LhsData, lhsValue)) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } case VMExpressionOperator.ClearFlag: lhsValue = VMMemory.GetVariable(context, operand.LhsOwner, operand.LhsData); rhsValue = VMMemory.GetVariable(context, operand.RhsOwner, operand.RhsData); var clearBitval = ~(1 << (rhsValue - 1)); lhsValue &= (short)clearBitval; if (VMMemory.SetVariable(context, operand.LhsOwner, operand.LhsData, lhsValue)) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } /** %= **/ case VMExpressionOperator.PlusEquals: case VMExpressionOperator.ModEquals: case VMExpressionOperator.MinusEquals: case VMExpressionOperator.DivEquals: case VMExpressionOperator.MulEquals: case VMExpressionOperator.AndEquals: lhsValue = VMMemory.GetVariable(context, operand.LhsOwner, operand.LhsData); rhsValue = VMMemory.GetVariable(context, operand.RhsOwner, operand.RhsData); switch (operand.Operator) { case VMExpressionOperator.ModEquals: lhsValue %= rhsValue; break; case VMExpressionOperator.PlusEquals: lhsValue += rhsValue; break; case VMExpressionOperator.MinusEquals: lhsValue -= rhsValue; break; case VMExpressionOperator.DivEquals: lhsValue /= rhsValue; break; case VMExpressionOperator.MulEquals: lhsValue *= rhsValue; break; case VMExpressionOperator.AndEquals: lhsValue &= rhsValue; break; } VMMemory.SetVariable(context, operand.LhsOwner, operand.LhsData, lhsValue); return(VMPrimitiveExitCode.GOTO_TRUE); /** == **/ case VMExpressionOperator.Equals: case VMExpressionOperator.LessThan: case VMExpressionOperator.GreaterThan: case VMExpressionOperator.GreaterThanOrEqualTo: case VMExpressionOperator.NotEqualTo: case VMExpressionOperator.LessThanOrEqualTo: case VMExpressionOperator.IsFlagSet: lhsValue = VMMemory.GetVariable(context, operand.LhsOwner, operand.LhsData); rhsValue = VMMemory.GetVariable(context, operand.RhsOwner, operand.RhsData); bool result = false; switch (operand.Operator) { case VMExpressionOperator.Equals: result = lhsValue == rhsValue; break; case VMExpressionOperator.LessThan: result = lhsValue < rhsValue; break; case VMExpressionOperator.GreaterThan: result = lhsValue > rhsValue; break; case VMExpressionOperator.GreaterThanOrEqualTo: result = lhsValue >= rhsValue; break; case VMExpressionOperator.NotEqualTo: result = lhsValue != rhsValue; break; case VMExpressionOperator.LessThanOrEqualTo: result = lhsValue <= rhsValue; break; case VMExpressionOperator.IsFlagSet: result = ((lhsValue & (1 << (rhsValue - 1))) > 0); break; } if (result) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } default: throw new Exception("Unknown expression type"); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMAnimateSimOperand>(); var avatar = (VMAvatar)context.Caller; if (operand.AnimationID == 0) { //reset avatar.CurrentAnimation = null; if (avatar.GetSlot(0) != null) //if we're carrying something, set carry animation to default carry. { avatar.CarryAnimation = TSO.Content.Content.Get().AvatarAnimations.Get("a2o-rarm-carry-loop.anim"); avatar.CarryAnimationState = new VMAnimationState(); } else { avatar.CarryAnimation = null; } return(VMPrimitiveExitCode.GOTO_TRUE); } var animation = VMMemory.GetAnimation(context, operand.Source, operand.AnimationID); if (animation == null) { return(VMPrimitiveExitCode.ERROR); } if (operand.Mode == 3) //stop standard carry, then play and wait { avatar.CarryAnimation = null; } if (operand.Mode == 0 || operand.Mode == 3) //Play and Wait { /** Are we starting the animation or progressing it? **/ if (avatar.CurrentAnimation == null || avatar.CurrentAnimation != animation) { /** Start it **/ avatar.CurrentAnimation = animation; avatar.CurrentAnimationState = new VMAnimationState(); avatar.Avatar.LeftHandGesture = SimHandGesture.Idle; avatar.Avatar.RightHandGesture = SimHandGesture.Idle; if (operand.PlayBackwards) { avatar.CurrentAnimationState.PlayingBackwards = true; avatar.CurrentAnimationState.CurrentFrame = avatar.CurrentAnimation.NumFrames; } foreach (var motion in animation.Motions) { if (motion.TimeProperties == null) { continue; } foreach (var tp in motion.TimeProperties) { foreach (var item in tp.Items) { avatar.CurrentAnimationState.TimePropertyLists.Add(item); } } } /** Sort time property lists by time **/ avatar.CurrentAnimationState.TimePropertyLists.Sort(new TimePropertyListItemSorter()); return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } else { if (avatar.CurrentAnimationState.EndReached) { avatar.CurrentAnimation = null; return(VMPrimitiveExitCode.GOTO_TRUE); } else if (avatar.CurrentAnimationState.EventFired) { avatar.CurrentAnimationState.EventFired = false; //clear fired flag if (operand.StoreFrameInLocal) { VMMemory.SetVariable(context, VMVariableScope.Local, operand.LocalEventNumber, avatar.CurrentAnimationState.EventCode); } else { VMMemory.SetVariable(context, VMVariableScope.Parameters, 0, avatar.CurrentAnimationState.EventCode); } return(VMPrimitiveExitCode.GOTO_FALSE); } else { return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } } } else if (operand.Mode == 2) //set custom carry animation { avatar.CarryAnimation = animation; avatar.CarryAnimationState = new VMAnimationState(); return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_TRUE); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMCreateObjectInstanceOperand>(); short x = 0; short y = 0; sbyte level = 0; Direction dir; switch (operand.Position) { case VMCreateObjectPosition.UnderneathMe: case VMCreateObjectPosition.OnTopOfMe: var pos = context.Caller.Position; x = (short)pos.X; y = (short)pos.Y; level = 0; //for now.. dir = Direction.NORTH; break; case VMCreateObjectPosition.BelowObjectInLocal: var pos2 = context.VM.GetObjectById((short)context.Locals[operand.LocalToUse]).Position; x = (short)pos2.X; y = (short)pos2.Y; level = 0; //for now.. dir = Direction.NORTH; break; case VMCreateObjectPosition.OutOfWorld: x = 0; //need a system for out of world objects. y = 0; level = 0; //for now.. dir = Direction.NORTH; break; case VMCreateObjectPosition.InSlot0OfStackObject: case VMCreateObjectPosition.InMyHand: x = 0; //need a system for out of world objects. y = 0; level = 0; //for no.. 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; var location = objp.Position; switch (objp.Direction) { case tso.world.model.Direction.SOUTH: location += new Vector3(0.0f, 1.0f, 0.0f); break; case tso.world.model.Direction.WEST: location += new Vector3(-1.0f, 0.0f, 0.0f); break; case tso.world.model.Direction.EAST: location += new Vector3(1.0f, 0.0f, 0.0f); break; case tso.world.model.Direction.NORTH: location += new Vector3(0.0f, -1.0f, 0.0f); break; } x = (short)Math.Floor(location.X); y = (short)Math.Floor(location.Y); level = 0; dir = objp.Direction; break; default: throw new Exception("Where do I put this??"); } var obj = context.VM.Context.CreateObjectInstance(operand.GUID, x, y, level, dir); if (operand.PassObjectIds) { obj.MainStackOBJ = context.StackObject.ObjectID; obj.MainParam = context.Caller.ObjectID; } if (operand.PassTemp0) { obj.MainParam = context.Thread.TempRegisters[0]; } obj.Init(context.VM.Context); 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 Exception("Set callback as 'this interaction' when queue item has no interaction number!"); } 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); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMPlaySoundOperand>(); return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context) { var operand = context.GetCurrentOperand <VMSetToNextOperand>(); var targetValue = VMMemory.GetVariable(context, operand.GetTargetOwner(), operand.GetTargetData()); var entities = context.VM.Entities; bool foundCurrent = false; VMEntity FirstOfType = null; //used for looparound if no next VMEntity Pointer = context.VM.GetObjectById(targetValue); if (operand.SearchType == VMSetToNextSearchType.PartOfAMultipartTile) { if (context.Callee.MultitileGroup == null) { return(VMPrimitiveExitCode.GOTO_FALSE); //single part } else { var group = context.Callee.MultitileGroup.Objects; for (int i = 0; i < group.Count; i++) { var temp = group[i]; if (Pointer == null || context.SetToNextStart == null) { context.SetToNextStart = temp; VMMemory.SetVariable(context, operand.GetTargetOwner(), operand.GetTargetData(), temp.ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } else { if (foundCurrent) { if (temp == context.SetToNextStart) { return(VMPrimitiveExitCode.GOTO_FALSE); } else { VMMemory.SetVariable(context, operand.GetTargetOwner(), operand.GetTargetData(), temp.ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } } else { if (temp == Pointer) { foundCurrent = true; } else if (FirstOfType == null) { FirstOfType = temp; } } } } } } else { for (int i = 0; i < entities.Count; i++) //generic search through all objects { var temp = entities[i]; VMEntity temp2; //used in some places bool found = false; switch (operand.SearchType) //search types { case VMSetToNextSearchType.Object: found = true; break; case VMSetToNextSearchType.Person: found = (temp.GetType() == typeof(VMAvatar)); break; case VMSetToNextSearchType.NonPerson: found = (temp.GetType() == typeof(VMGameObject)); break; case VMSetToNextSearchType.ObjectOfType: found = (temp.Object.OBJ.GUID == operand.GUID); break; case VMSetToNextSearchType.NeighborId: throw new Exception("Not implemented!"); case VMSetToNextSearchType.ObjectWithCategoryEqualToSP0: found = (temp.Object.OBJ.FunctionFlags == context.Args[0]); //I'm assuming that means "Stack parameter 0", that category means function and that it needs to be exactly the same (no subsets) break; case VMSetToNextSearchType.NeighborOfType: throw new Exception("Not implemented!"); case VMSetToNextSearchType.ObjectOnSameTile: temp2 = context.Caller; //.VM.GetObjectById((short)context.Locals[operand.Local]); //sure, it doesn't have this in the name, but it seems like the object is chosen from a local. found = (Math.Round(temp.Position.X) == Math.Round(temp2.Position.X) && Math.Round(temp.Position.Y) == Math.Round(temp2.Position.Y)); break; case VMSetToNextSearchType.ObjectAdjacentToObjectInLocal: temp2 = context.VM.GetObjectById((short)context.Locals[operand.Local]); found = (Math.Abs(Math.Round(temp.Position.X) - Math.Round(temp2.Position.X)) < 2 && Math.Abs(Math.Round(temp.Position.Y) - Math.Round(temp2.Position.Y)) < 2); break; case VMSetToNextSearchType.Career: throw new Exception("Not implemented!"); case VMSetToNextSearchType.ClosestHouse: throw new Exception("Not implemented!"); } if (found) { if (Pointer == null || context.SetToNextStart == null) { context.SetToNextStart = temp; VMMemory.SetVariable(context, operand.GetTargetOwner(), operand.GetTargetData(), temp.ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } else { if (foundCurrent) { if (temp == context.SetToNextStart) { return(VMPrimitiveExitCode.GOTO_FALSE); } else { VMMemory.SetVariable(context, operand.GetTargetOwner(), operand.GetTargetData(), temp.ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } } else { if (temp == Pointer) { foundCurrent = true; } else if (FirstOfType == null) { FirstOfType = temp; } } } } } } //if we exit, we didn't find next. go for first of type if not where we started if (FirstOfType != null) { if (FirstOfType == context.SetToNextStart) { return(VMPrimitiveExitCode.GOTO_FALSE); } else { VMMemory.SetVariable(context, operand.GetTargetOwner(), operand.GetTargetData(), FirstOfType.ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } } return(VMPrimitiveExitCode.GOTO_FALSE); //no first, didn't find a next. }
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); }
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) { var operand = context.GetCurrentOperand <VMPushInteractionOperand>(); VMEntity interactionSource; if ((operand.Flags & (1 << 1)) > 0) { interactionSource = context.VM.GetObjectById((short)context.Locals[operand.ObjectLocation]); } else { interactionSource = context.VM.GetObjectById((short)context.Args[operand.ObjectLocation]); } VMQueuePriority priority; if (operand.Priority == 0) { priority = context.Thread.Queue[0].Priority; } else { priority = (VMQueuePriority)(operand.Priority - 1); } BHAV bhav; GameIffResource CodeOwner = null; var Action = interactionSource.TreeTable.InteractionByIndex[operand.Interaction]; ushort ActionID = Action.ActionFunction; if (ActionID < 4096) { //global bhav = null; //unimp as it has to access the context to get this. } else if (ActionID < 8192) { //local bhav = interactionSource.Object.Resource.Get <BHAV>(ActionID); CodeOwner = interactionSource.Object.Resource; } else { //semi-global bhav = interactionSource.SemiGlobal.Resource.Get <BHAV>(ActionID); CodeOwner = interactionSource.SemiGlobal.Resource; } var routine = context.VM.Assemble(bhav); context.StackObject.Thread.EnqueueAction( new TSO.Simantics.engine.VMQueuedAction { Callee = interactionSource, CodeOwner = CodeOwner, Routine = routine, Name = interactionSource.TreeTableStrings.GetString((int)Action.TTAIndex), StackObject = interactionSource, InteractionNumber = operand.Interaction, Priority = priority } ); return(VMPrimitiveExitCode.GOTO_TRUE); }