public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMRefreshOperand)args; 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 is VMGameObject) { var TargObj = (VMGameObject)target; TargObj.RefreshGraphic(); } break; case 1: context.VM.Context.RefreshLighting(context.VM.Context.GetObjectRoom(target), true); if (target is VMGameObject) ((VMGameObject)target).RefreshLight(); break; } return VMPrimitiveExitCode.GOTO_TRUE; }
public ChangeBHAVCommand(BHAV target, EditorScope scope, VMStackFrame frame, BHAVPrimSelect callback) { Target = target; TargetScope = scope; Frame = frame; SelectCallback = callback; }
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; }
//TODO: Behaviour for being notified out of idle and interaction canceling public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMIdleForInputOperand)args; 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.Thread.Interrupt) { context.Thread.Interrupt = false; return VMPrimitiveExitCode.GOTO_TRUE; } var ticks = VMMemory.GetVariable(context, FSO.SimAntics.Engine.Scopes.VMVariableScope.Parameters, operand.StackVarToDec); ticks--; if (ticks < 0) { return VMPrimitiveExitCode.GOTO_TRUE; } else { VMMemory.SetVariable(context, FSO.SimAntics.Engine.Scopes.VMVariableScope.Parameters, operand.StackVarToDec, ticks); return VMPrimitiveExitCode.CONTINUE_NEXT_TICK; } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMSetBalloonHeadlineOperand)args; var obj = (operand.OfStackOBJ) ? context.StackObject : context.Caller; if (obj.HeadlineRenderer != null) obj.HeadlineRenderer.Dispose(); if (operand.Index == -1 || operand.Duration == 0) { obj.Headline = null; obj.HeadlineRenderer = null; } else { VMEntity icon = null; int index = operand.Index; if (operand.Group == VMSetBalloonHeadlineOperandGroup.Algorithmic) icon = (index < 2) ? context.StackObject : context.VM.GetObjectById(context.Locals[operand.Algorithmic]); else if (operand.Indexed) index += context.Thread.TempRegisters[0]; obj.Headline = new VMRuntimeHeadline(operand, obj, icon, (sbyte)index); obj.HeadlineRenderer = context.VM.Headline.Get(obj.Headline); } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMSetMotiveChangeOperand)args; var avatar = ((VMAvatar)context.Caller); if (operand.Once) { } if (operand.ClearAll) { avatar.ClearMotiveChanges(); } else { var rate = VMMemory.GetVariable(context, (VMVariableScope)operand.DeltaOwner, operand.DeltaData); var MaxValue = VMMemory.GetVariable(context, (VMVariableScope)operand.MaxOwner, operand.MaxData); if (operand.Once) { var motive = avatar.GetMotiveData(operand.Motive); if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { return VMPrimitiveExitCode.GOTO_TRUE; } // ^ we're already over, do nothing. (do NOT clamp) motive += rate; if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { motive = MaxValue; } avatar.SetMotiveData(operand.Motive, motive); } else avatar.SetMotiveChange(operand.Motive, rate, MaxValue); } 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<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, VMPrimitiveOperand args) { if (!VM.UseWorld) return VMPrimitiveExitCode.GOTO_TRUE; var operand = (VMPlaySoundOperand)args; FWAV fwav = context.ScopeResource.Get<FWAV>(operand.EventID); if (fwav == null) fwav = context.VM.Context.Globals.Resource.Get<FWAV>(operand.EventID); var owner = (operand.StackObjAsSource) ? context.StackObject : context.Caller; if (fwav != null && owner.SoundThreads.FirstOrDefault(x => x.Name == fwav.Name) == null) { var thread = HITVM.Get().PlaySoundEvent(fwav.Name); if (thread != null) { if (owner == null) return VMPrimitiveExitCode.GOTO_TRUE; if (!thread.AlreadyOwns(owner.ObjectID)) thread.AddOwner(owner.ObjectID); if (owner is VMAvatar && thread is HITThread) ((VMAvatar)owner).SubmitHITVars((HITThread)thread); var entry = new VMSoundEntry() { Sound = thread, Pan = !operand.NoPan, Zoom = !operand.NoZoom, Loop = operand.Loop, Name = fwav.Name }; owner.SoundThreads.Add(entry); if (owner.Thread != null) owner.TickSounds(); } } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMGotoRelativePositionOperand)args; var obj = context.StackObject; var avatar = (VMAvatar)context.Caller; if (obj.Position == LotTilePos.OUT_OF_WORLD) return VMPrimitiveExitCode.GOTO_FALSE; var slot = new SLOTItem { Type = 3, Standing = 1 }; if (operand.Location != VMGotoRelativeLocation.OnTopOf) { //default slot is on top of slot.MinProximity = 16; slot.MaxProximity = 24; if (operand.Location == VMGotoRelativeLocation.AnywhereNear) slot.Rsflags |= (SLOTFlags)255; else slot.Rsflags |= (SLOTFlags)(1 << (((int)operand.Location) % 8)); } if (operand.Direction == VMGotoRelativeDirection.AnyDirection) slot.Facing = SLOTFacing.FaceAnywhere; //TODO: verify. not sure where this came from? else slot.Facing = (SLOTFacing)operand.Direction; var pathFinder = context.Thread.PushNewRoutingFrame(context, !operand.NoFailureTrees); var success = pathFinder.InitRoutes(slot, context.StackObject); return VMPrimitiveExitCode.CONTINUE; }
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; } 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; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMChangeActionStringOperand)args; var table = context.ScopeResource.Get<STR>(operand.StringTable); if (table != null) context.Thread.Queue[0].Name = table.GetString(operand.StringID - 1); 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.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, VMPrimitiveOperand args) { //if caller's active interaction is with stack object, return true. var callerActive = context.Caller.Thread.Stack.LastOrDefault(); return (callerActive != null && callerActive.ActionTree && context.Caller.Thread.Queue[0].Callee == context.StackObject) ? VMPrimitiveExitCode.GOTO_TRUE:VMPrimitiveExitCode.GOTO_FALSE; }
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<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; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMChangeActionStringOperand)args; STR table = null; switch (operand.Scope) { case 0: table = context.ScopeResource.Get<STR>(operand.StringTable); break; case 1: table = context.Callee.SemiGlobal.Get<STR>(operand.StringTable); break; case 2: table = context.Global.Resource.Get<STR>(operand.StringTable); break; } if (table != null) { var newName = VMDialogHandler.ParseDialogString(context, table.GetString(operand.StringID - 1), table); if (context.Thread.IsCheck && context.Thread.ActionStrings != null) { context.Thread.ActionStrings.Add(new VMPieMenuInteraction() { Name = newName, Param0 = (context.StackObject == null) ? (short)0 : context.StackObject.ObjectID }); } else context.Thread.Queue[0].Name = newName; } 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) { /** * It seems as though dialogs might be sometimes blocking. This will need consideration when * a server is introduced */ return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMGrabOperand)args; return (context.Caller.PlaceInSlot(context.StackObject, 0, true, context.VM.Context)) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE; return VMPrimitiveExitCode.GOTO_TRUE; }
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, VMPrimitiveOperand args) { var operand = (VMRandomNumberOperand)args; 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); return VMPrimitiveExitCode.GOTO_TRUE; }
public override void Execute(BHAV bhav, UIBHAVEditor editor) { Old = editor.BHAVView.EditTarget; OldScope = editor.BHAVView.Scope; OldFrame = editor.DebugFrame; editor.BHAVView.OnSelectedChanged -= SelectCallback; editor.SwitchBHAV(Target, TargetScope, Frame); editor.BHAVView.OnSelectedChanged += SelectCallback; }
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) { /** Is my thread idle or active? **/ if (context.Thread.State == VMThreadState.Active){ context.VM.ThreadIdle(context.Thread); }else{ context.VM.ThreadActive(context.Thread); } return VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMTransferFundsOperand)args; return VMPrimitiveExitCode.GOTO_TRUE; //disable for now. /** 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) { //TODO: Implement this. var operand = context.GetCurrentOperand<VMSetBalloonHeadlineOperand>(); if (operand.Duration == 0) { /** Clear **/ } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { //TODO: Implement this. var operand = (VMSetBalloonHeadlineOperand)args; if (operand.Duration == 0) { /** Clear **/ } return VMPrimitiveExitCode.GOTO_TRUE; }
public void InitBHAV(BHAV bhav, EditorScope scope, VMEntity debugEnt, VMStackFrame debugFrame, BHAVPrimSelect callback) { if (FSOUI == null) { var mainCont = new UIExternalContainer(1024, 768); Editor = new UIBHAVEditor(bhav, scope, debugEnt); mainCont.Add(Editor); GameFacade.Screens.AddExternal(mainCont); SetUI(mainCont); Editor.BHAVView.OnSelectedChanged += callback; } else { //reuse existing lock (FSOUI) { Editor.QueueCommand(new ChangeBHAVCommand(bhav, scope, debugFrame, callback)); } } }
public static Appearance GetSuit(VMStackFrame context, VMSuitScope scope, ushort id) { switch (scope) { case VMSuitScope.Object: var suitTable = context.Callee.Object.Resource.Get <STR>(304); if (suitTable != null) { var suitFile = suitTable.GetString(id) + ".apr"; var apr = FSO.Content.Content.Get().AvatarAppearances.Get(suitFile); return(apr); } return(null); default: return(null); throw new VMSimanticsException("I dont know about this suit scope", context); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMRemoveObjectInstanceOperand)args; VMEntity obj; if (operand.Target == 0) { obj = context.Caller; } else { obj = context.StackObject; } //operand.CleanupAll; obj?.Delete(true, context.VM.Context); //if (obj == context.StackObject) context.StackObject = null; 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, VMPrimitiveOperand args) { var operand = (VMSetMotiveChangeOperand)args; var avatar = ((VMAvatar)context.Caller); if (operand.Once) { } if (operand.ClearAll) { avatar.ClearMotiveChanges(); } else { var PerHourChange = VMMemory.GetVariable(context, (VMVariableScope)operand.DeltaOwner, operand.DeltaData); var MaxValue = VMMemory.GetVariable(context, (VMVariableScope)operand.MaxOwner, operand.MaxData); avatar.SetMotiveChange(operand.Motive, PerHourChange, MaxValue); } return(VMPrimitiveExitCode.GOTO_TRUE); }
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 <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, VMPrimitiveOperand args) { var operand = (VMSetMotiveChangeOperand)args; var avatar = ((VMAvatar)context.Caller); if (operand.ClearAll) { avatar.ClearMotiveChanges(); } else { var rate = (short)VMMotiveChange.ScaleRate(context.VM, VMMemory.GetVariable(context, operand.DeltaOwner, operand.DeltaData), operand.Motive); var MaxValue = VMMotiveChange.ScaleMax(context.VM, VMMemory.GetVariable(context, operand.MaxOwner, operand.MaxData), operand.Motive); if (operand.Once) { var motive = avatar.GetMotiveData(operand.Motive); if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { return(VMPrimitiveExitCode.GOTO_TRUE); } // ^ we're already over, do nothing. (do NOT clamp) motive += rate; if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { motive = MaxValue; } avatar.SetMotiveData(operand.Motive, motive); } else { avatar.SetMotiveChange(operand.Motive, rate, MaxValue); } } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMRefreshOperand)args; 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 is VMGameObject) { var TargObj = (VMGameObject)target; TargObj.RefreshGraphic(); } break; case 1: //light case 2: //area contribution context.VM.Context.RefreshLighting(context.VM.Context.GetObjectRoom(target), true, new HashSet <ushort>()); if (target is VMGameObject) { ((VMGameObject)target).RefreshLight(); } break; } return(VMPrimitiveExitCode.GOTO_TRUE); }
public static short MultitilePart(VMStackFrame context, VMEntity pointer, short targetValue) { if (pointer == null || (!pointer.MultitileGroup.MultiTile)) { return(0); //single part } else { var group = pointer.MultitileGroup.Objects; bool found = false; short bestID = 0; short smallestID = 0; for (int i = 0; i < group.Count; i++) { var temp = group[i]; if (temp.ObjectID < smallestID || smallestID == 0) { smallestID = temp.ObjectID; } if (temp.ObjectID > targetValue) { if ((!found) || (temp.ObjectID < bestID)) { found = true; bestID = temp.ObjectID; } } } if (found) { return(bestID); } else { return(smallestID); } } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMChangeActionStringOperand)args; STR table = null; switch (operand.Scope) { case 0: table = context.ScopeResource.Get <STR>(operand.StringTable); break; case 1: table = context.Callee.SemiGlobal.Get <STR>(operand.StringTable); break; case 2: table = context.Global.Resource.Get <STR>(operand.StringTable); break; } if (table != null) { var newName = VMDialogHandler.ParseDialogString(context, table.GetString(operand.StringID - 1), table); if (context.Thread.IsCheck && context.Thread.ActionStrings != null) { context.Thread.ActionStrings.Add(new VMPieMenuInteraction() { Name = newName, Param0 = context.StackObjectID }); } else { context.Thread.ActiveAction.Name = newName; } } return(VMPrimitiveExitCode.GOTO_TRUE); }
public virtual VMPrimitiveExitCode Execute(VMStackFrame frame, out VMInstruction instruction) { instruction = frame.GetCurrentInstruction(); var opcode = instruction.Opcode; if (opcode >= 256) { frame.Thread.ExecuteSubRoutine(frame, opcode, (VMSubRoutineOperand)instruction.Operand); return(VMPrimitiveExitCode.CONTINUE); } var primitive = VMContext.Primitives[opcode]; if (primitive == null) { return(VMPrimitiveExitCode.GOTO_TRUE); } VMPrimitiveHandler handler = primitive.GetHandler(); return(handler.Execute(frame, instruction.Operand)); }
public void UpdateDebugPointer(VMStackFrame frame) { if (frame != null && BHAVView.EditTarget.ChunkID == frame.Routine.ID) { BHAVView.DebugPointer = BHAVView.RealPrim[frame.InstructionPointer]; GameThread.NextUpdate(x => { var location = GetCentralLocation(BHAVView.DebugPointer); GameFacade.Screens.Tween.To(BHAVView, 0.5f, new Dictionary <string, float>() { { "AnimScrollX", location.X }, { "AnimScrollY", location.Y }, }, TweenQuad.EaseOut); }); } else { BHAVView.DebugPointer = null; } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) //TODO: Behaviour for being notified out of idle and interaction canceling { var operand = (VMIdleForInputOperand)args; //if we're main, attempt to run a queued interaction. We just idle if this fails. if (operand.AllowPush == 1 && !context.ActionTree && context.Thread.AttemptPush()) { return(VMPrimitiveExitCode.CONTINUE); //control handover //TODO: does this forcefully end the rest of the idle? (force a true return, must loop back to run again) } if (context.ActionTree && context.Thread.Queue[0].Cancelled) { context.Caller.SetFlag(VMEntityFlags.NotifiedByIdleForInput, true); return(VMPrimitiveExitCode.GOTO_TRUE); } if (context.Thread.Interrupt) { context.Thread.Interrupt = false; return(VMPrimitiveExitCode.GOTO_TRUE); } var ticks = VMMemory.GetVariable(context, FSO.SimAntics.Engine.Scopes.VMVariableScope.Parameters, operand.StackVarToDec); ticks--; if (ticks < 0) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { VMMemory.SetVariable(context, FSO.SimAntics.Engine.Scopes.VMVariableScope.Parameters, operand.StackVarToDec, ticks); return(VMPrimitiveExitCode.CONTINUE_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, VMPrimitiveOperand args) { var operand = (VMSleepOperand)args; if (context.Thread.Interrupt) { context.Thread.Interrupt = false; return(VMPrimitiveExitCode.GOTO_TRUE); } var ticks = VMMemory.GetVariable(context, FSO.SimAntics.Engine.Scopes.VMVariableScope.Parameters, operand.StackVarToDec); ticks--; if (ticks < 0) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { VMMemory.SetVariable(context, FSO.SimAntics.Engine.Scopes.VMVariableScope.Parameters, operand.StackVarToDec, ticks); return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMGetDistanceToOperand)args; 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(pos1.x - pos2.x, 2) + Math.Pow(pos1.y - pos2.y, 2)) / 16.0); context.Thread.TempRegisters[operand.TempNum] = result; return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) //TODO: Behaviour for being notified out of idle and interaction canceling { var operand = (VMIdleForInputOperand)args; //TODO: wrong, breaks bbq 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.Thread.Interrupt) { context.Thread.Interrupt = false; return(VMPrimitiveExitCode.GOTO_TRUE); } var ticks = VMMemory.GetVariable(context, FSO.SimAntics.Engine.Scopes.VMVariableScope.Parameters, operand.StackVarToDec); ticks--; if (ticks < 0) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { VMMemory.SetVariable(context, FSO.SimAntics.Engine.Scopes.VMVariableScope.Parameters, operand.StackVarToDec, ticks); return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMRemoveObjectInstanceOperand)args; VMEntity obj; if (operand.Target == 0) { obj = context.Caller; } else { obj = context.StackObject; } //TODO: what do CleanupAll and ReturnImmediately do? //cleanup all likely resets all avatars using the object, though that should really happen regardless? //return immediately is an actual mystery obj?.Delete(true, context.VM.Context); //if (obj == context.StackObject) context.StackObject = null; // yield if we are going to delete return((obj == context.Caller) ? VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK : VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMSetBalloonHeadlineOperand)args; var obj = (operand.OfStackOBJ) ? context.StackObject : context.Caller; if (obj.HeadlineRenderer != null) { if (operand.Duration == 0 && obj.HeadlineRenderer.IsMoney) { return(VMPrimitiveExitCode.GOTO_TRUE); } obj.HeadlineRenderer.Dispose(); } if (operand.Index == -1 || operand.Duration == 0) { obj.Headline = null; obj.HeadlineRenderer = null; } else { VMEntity icon = null; int index = operand.Index; if (operand.Group == VMSetBalloonHeadlineOperandGroup.Algorithmic) { icon = (index < 2) ? context.StackObject : context.VM.GetObjectById(context.Locals[operand.Algorithmic]); } else if (operand.Indexed) { index += context.Thread.TempRegisters[0]; } obj.Headline = new VMRuntimeHeadline(operand, obj, icon, (sbyte)index); obj.HeadlineRenderer = context.VM.Headline.Get(obj.Headline); } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMGotoRoutingSlotOperand)args; if (context.Thread.IsCheck) { return(VMPrimitiveExitCode.GOTO_FALSE); } var slot = VMMemory.GetSlot(context, operand.Type, operand.Data); if (slot == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } var obj = context.StackObject; if (obj == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } var avatar = context.Caller; //Routing slots must be type 3. if (slot.Type == 3) { var pathFinder = context.Thread.PushNewRoutingFrame(context, !operand.NoFailureTrees); var success = pathFinder.InitRoutes(slot, context.StackObject); return(VMPrimitiveExitCode.CONTINUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { if (!VM.UseWorld) { return(VMPrimitiveExitCode.GOTO_TRUE); } var operand = (VMPlaySoundOperand)args; FWAV fwav = context.ScopeResource.Get <FWAV>(operand.EventID); if (fwav == null) { fwav = context.VM.Context.Globals.Resource.Get <FWAV>(operand.EventID); } var owner = (operand.StackObjAsSource) ? context.StackObject : context.Caller; var lastThread = owner.SoundThreads.FirstOrDefault(x => x?.Name == fwav?.Name); if ((lastThread?.Sound as HITThread)?.Interruptable == true) { lastThread = null; } if (fwav != null && lastThread == null) { var thread = HITVM.Get().PlaySoundEvent(fwav.Name); if (thread != null) { if (owner == null) { return(VMPrimitiveExitCode.GOTO_TRUE); } if (!thread.AlreadyOwns(owner.ObjectID)) { thread.AddOwner(owner.ObjectID); } if (owner is VMAvatar && thread is HITThread) { ((VMAvatar)owner).SubmitHITVars((HITThread)thread); } var entry = new VMSoundEntry() { Sound = thread, Pan = !operand.NoPan, Zoom = !operand.NoZoom, Loop = operand.Loop, Name = fwav.Name }; owner.SoundThreads.Add(entry); if (owner.Thread != null) { owner.TickSounds(); } } } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMRunTreeByNameOperand)args; if (context.StackObject == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } 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.ScopeResource.SemiGlobal != null) { res = context.ScopeResource.SemiGlobal.Get <STR>(operand.StringTable); } if (res == null) { res = context.ScopeResource.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, context.StackObject.Object, new VMSubRoutineOperand(context.Thread.TempRegisters)); return(VMPrimitiveExitCode.CONTINUE); //push onto my stack - acts like a subroutine. } else if (operand.Destination == 0) { var result = context.Thread.RunInMyStack(tree.bhav, context.StackObject.Object, context.Thread.TempRegisters, context.StackObject) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE; return((context.VM.Aborting) ? VMPrimitiveExitCode.ERROR : result); //run in my stack } else { var result = context.StackObject.Thread.RunInMyStack(tree.bhav, context.StackObject.Object, context.Thread.TempRegisters, context.StackObject) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE; return((context.VM.Aborting) ? VMPrimitiveExitCode.ERROR : result); //run in stack obj's stack } //found it! now lets call the tree ;) } else { return(VMPrimitiveExitCode.GOTO_FALSE); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMGenericTSOCallOperand)args; switch (operand.Call) { // 0. HOUSE TUTORIAL COMPLETE case VMGenericTSOCallMode.SwapMyAndStackObjectsSlots: //1 var cont1 = context.Caller.Container; var cont2 = context.StackObject.Container; var contS1 = context.Caller.ContainerSlot; var contS2 = context.StackObject.ContainerSlot; if (cont1 != null && cont2 != null) { context.Caller.PrePositionChange(context.VM.Context); context.StackObject.PrePositionChange(context.VM.Context); cont1.ClearSlot(contS1); cont2.ClearSlot(contS2); cont1.PlaceInSlot(context.StackObject, contS1, true, context.VM.Context); cont2.PlaceInSlot(context.Caller, contS2, true, context.VM.Context); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.SetActionIconToStackObject: //2 context.Thread.ActiveAction.IconOwner = context.StackObject; return(VMPrimitiveExitCode.GOTO_TRUE); // 3. DO NOT USE case VMGenericTSOCallMode.IsStackObjectARoommate: //4 return((context.StackObject is VMGameObject || ((VMAvatar)context.StackObject).AvatarState.Permissions < VMTSOAvatarPermissions.Roommate) ? VMPrimitiveExitCode.GOTO_FALSE : VMPrimitiveExitCode.GOTO_TRUE); // 5. Combine Assets of family in Temp0 // 6. Remove From Family // 7. Make New Neighbour // 8. Family Sims1 Tutorial Complete // 9. Architecture Sims1 Tutorial Complete // 10. Disable Build/Buy // 11. Enable Build/Buy // 12. Distance to camera in Temp0 // 13. Abort Interactions case VMGenericTSOCallMode.AbortInteractions: return(VMPrimitiveExitCode.GOTO_TRUE); // 14. House Radio Station equals Temp0 (TODO) case VMGenericTSOCallMode.HouseRadioStationEqualsTemp0: context.VM.SetGlobalValue(31, context.Thread.TempRegisters[0]); return(VMPrimitiveExitCode.GOTO_TRUE); // 15. My Routing Footprint equals Temp0 // 16. Change Normal Output case VMGenericTSOCallMode.GetInteractionResult: //17 //if our current interaction result is -1, then we need to start the process. if (context.ActionTree && context.Caller is VMAvatar && ((VMAvatar)context.Caller).PersistID != 0) { var interaction = context.Thread.ActiveAction; if (interaction.InteractionResult == -1) { interaction.InteractionResult = 0; } else { interaction.ResultCheckCounter++; } if (interaction.InteractionResult > 0 || interaction.ResultCheckCounter < 30 * 10) { context.Thread.TempRegisters[0] = interaction.InteractionResult; //0=waiting, 1=reject, 2=accept, 3=timeout } else { context.Thread.TempRegisters[0] = 3; } } else { context.Thread.TempRegisters[0] = 2; } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.SetInteractionResult: //18 //todo: set interaction result to value of temp 0. UNUSED. return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.DoIOwnThisObject: //19 uint ownerID = GetOwnerID(context.StackObject, context); context.Thread.TempRegisters[0] = (ownerID != context.Caller.PersistID) ? (short)0 : (short)1; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.DoesTheLocalMachineSimOwnMe: //20 context.Thread.TempRegisters[1] = 1; //TODO return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.MakeMeStackObjectsOwner: //21 if (context.StackObject is VMAvatar) { return(VMPrimitiveExitCode.GOTO_TRUE); } foreach (var owned in context.StackObject.MultitileGroup.Objects) { ((VMTSOObjectState)owned.TSOState).OwnerID = context.Caller.PersistID; } if (context.VM.IsServer) { context.VM.GlobalLink.UpdateObjectPersist(context.VM, context.StackObject.MultitileGroup, (worked, objid) => { }); } //TODO: immediately persist? what to do when new owner has hit their object limit? return(VMPrimitiveExitCode.GOTO_TRUE); //TODO: may need to update in global server // 22. Get Permissions (TODO) // 23. Set Permissions (TODO) case VMGenericTSOCallMode.AskStackObjectToBeRoommate: //24 //0 = initiate. 1 = accept. 2 = reject. if (context.VM.GlobalLink != null) { context.VM.GlobalLink.RequestRoommate(context.VM, context.StackObject.PersistID, context.Thread.TempRegisters[0], 0); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.LeaveLot: //25 //SPECIAL: cancel all interactions with us that have not been started. bool canLeave = true; var avaUs = ((VMAvatar)context.Caller); foreach (var ava2 in context.VM.Context.ObjectQueries.Avatars) { if (ava2 == avaUs) { continue; } var queueCopy = ava2.Thread.Queue.ToList(); foreach (var qitem in queueCopy) { //checking the icon owner is a bit of a hack, but it is a surefire way of detecting sim2sim interactions (callee for these is the interaction object) if (qitem.Callee == avaUs || qitem.IconOwner == avaUs) { ava2.Thread.CancelAction(qitem.UID); } } var action = ava2.Thread.ActiveAction; if (action != null) { //need to wait for this action to stop if (action.Callee == avaUs || action.IconOwner == avaUs) { canLeave = false; //already cancelled above, but we do need to wait for it to end. } else { //check the stack of this sim. ANY reference to us is dangerous, so get them to cancel their interactions gracefully. foreach (var frame in ava2.Thread.Stack) { if (frame.Callee == avaUs || frame.StackObject == avaUs) { ava2.Thread.CancelAction(action.UID); canLeave = false; } } } } } if (canLeave) { ((VMAvatar)context.Caller).UserLeaveLot(); if (context.VM.GlobalLink != null) { context.VM.GlobalLink.LeaveLot(context.VM, (VMAvatar)context.Caller); } else { // use our stub to remove the sim and potentially disconnect the client. context.VM.CheckGlobalLink.LeaveLot(context.VM, (VMAvatar)context.Caller); } return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK); } // 26. UNUSED case VMGenericTSOCallMode.KickoutRoommate: if (context.VM.TSOState.CommunityLot) { //remove their donator status. don't tell the database. context.VM.SendCommand(new VMChangePermissionsCmd() { TargetUID = context.StackObject.PersistID, Level = VMTSOAvatarPermissions.Visitor }); return(VMPrimitiveExitCode.GOTO_TRUE); } if (context.VM.GlobalLink != null) { context.VM.GlobalLink.RemoveRoommate(context.VM, (VMAvatar)context.StackObject); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.KickoutVisitor: if (context.VM.GlobalLink != null) { var server = (VMServerDriver)context.VM.Driver; server.DropAvatar(context.StackObject as VMAvatar); } ((VMAvatar)context.StackObject).UserLeaveLot(); return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.StackObjectOwnerID: //29 //attempt to find owner on lot. null stack object if not present if (context.StackObject is VMAvatar) { context.Thread.TempRegisters[0] = 0; } else { var ownerid = GetOwnerID(context.StackObject, context); var owner = context.VM.GetObjectByPersist(ownerid); context.Thread.TempRegisters[0] = (owner == null) ? (short)-1 : owner.ObjectID; } return(VMPrimitiveExitCode.GOTO_TRUE); //30. Create Cheat Neighbour case VMGenericTSOCallMode.IsTemp0AvatarIgnoringTemp1Avatar: //31 context.Thread.TempRegisters[0] = (short)(((VMTSOAvatarState)(context.VM.GetObjectById(context.Thread.TempRegisters[0]).TSOState)) .IgnoredAvatars.Contains(context.VM.GetObjectById(context.Thread.TempRegisters[1]).PersistID) ? 1 : 0); return(VMPrimitiveExitCode.GOTO_TRUE); //32. Play Next Song on Radio Station in Temp 0 (TODO) case VMGenericTSOCallMode.Temp0AvatarUnignoreTemp1Avatar: var avatar = context.VM.GetObjectById(context.Thread.TempRegisters[0]); if (avatar.PersistID == context.VM.MyUID) { context.VM.SignalGenericVMEvt(VMEventType.TSOUnignore, (uint)context.VM.GetObjectById(context.Thread.TempRegisters[1]).PersistID); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.GlobalRepairCostInTempXL0: //34 var mech = ((VMAvatar)context.Caller).GetPersonData(VMPersonDataVariable.MechanicalSkill); var discount = (Math.Min((int)mech, 1000) * 50) / 1000 + (Math.Max(0, mech - 1000) * 2 / 100); context.Thread.TempXL[0] = ((context.StackObject.MultitileGroup.InitialPrice / 10) * (100 - discount)) / 100; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.GlobalRepairObjectState: //35 //repairs the stack object if (context.StackObject is VMGameObject) { var state = (context.StackObject.MultitileGroup.BaseObject.TSOState as VMTSOObjectState); var wearRecovery = 0; //in quarter percents if (context.Caller is VMAvatar) { var rava = (VMAvatar)context.Caller; var logicFactor = Math.Min((ulong)rava.GetPersonData(VMPersonDataVariable.LogicSkill), 1000); if (context.Caller.PersistID > 0) { wearRecovery = (int)(((ulong)rava.GetPersonData(VMPersonDataVariable.MechanicalSkill) * (100 + (context.VM.Context.NextRandom(80) * (1000 - logicFactor) + 100 * logicFactor) / 1000)) / 2000); } else { wearRecovery = 40; //10% recovery for repairman } } state.QtrDaysSinceLastRepair = 0; foreach (var objr in context.StackObject.MultitileGroup.Objects) { ((VMGameObject)objr).DisableParticle(256); } state.Wear = (ushort)Math.Max(20 * 4, state.Wear - wearRecovery); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.IsGlobalBroken: //36 return(((context.StackObject.MultitileGroup.BaseObject.TSOState as VMTSOObjectState)?.Broken == true)?VMPrimitiveExitCode.GOTO_TRUE:VMPrimitiveExitCode.GOTO_FALSE); // 37. UNUSED case VMGenericTSOCallMode.MayAddRoommate: //38 // CONDITIONS, where stack object is desired roommate: (TODO: support extensions) // - Avatar we're asking must be resident of less lots than the maximum (currently 1) // - This lot must have less than (MAX_ROOMIES) roommates. (currently 8) // - Caller must be lot owner. // - This must not be a community lot. short result = 0; if (context.Caller is VMAvatar && context.Callee is VMAvatar) { var caller = (VMAvatar)context.Caller; var callee = (VMAvatar)context.Callee; if (caller.AvatarState.Permissions == VMTSOAvatarPermissions.Owner && !context.VM.TSOState.CommunityLot && context.VM.TSOState.Roommates.Count < 8 && (((VMTSOAvatarState)callee.TSOState).Flags & VMTSOAvatarFlags.CanBeRoommate) > 0) { result = 2; } } context.Thread.TempRegisters[0] = result; // 2 is "true". not sure what 1 is. (interaction shows up, but fails on trying to run it. likely "guessed" state for client) return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.ReturnLotCategory: //39 context.Thread.TempRegisters[0] = context.VM.TSOState.PropertyCategory; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.TestStackObject: //40 return((context.StackObject != null) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); case VMGenericTSOCallMode.GetCurrentValue: //41 //stack object price in TempXL 0 context.Thread.TempXL[0] = context.StackObject.MultitileGroup.Price; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.IsRegionEmpty: //42 //is temp0 radius (in full tiles) around stack object empty? //used for resurrect. TODO. return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.SetSpotlightStatus: if (context.VM.GlobalLink != null) { context.VM.GlobalLink.SetSpotlightStatus(context.VM, context.Thread.TempRegisters[0] == 1); } return(VMPrimitiveExitCode.GOTO_TRUE); //44. Is Full Refund (TODO: small grace period after purchase/until user exits buy mode) //45. Refresh buy/build (TODO? we probably don't need this) case VMGenericTSOCallMode.GetLotOwner: //46 context.Thread.TempRegisters[0] = context.VM.GetAvatarByPersist(context.VM.TSOState.OwnerID)?.ObjectID ?? 0; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.CopyDynObjNameFromTemp0ToTemp1: //47 var obj1 = context.VM.GetObjectById(context.Thread.TempRegisters[0]); var obj2 = context.VM.GetObjectById(context.Thread.TempRegisters[1]); obj2.Name = obj1.Name; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.GetIsPendingDeletion: //48 if (context.StackObject == null || context.StackObject.Dead) { return(VMPrimitiveExitCode.GOTO_TRUE); } return(VMPrimitiveExitCode.GOTO_FALSE); //49. Pet Ran Away //50. Set Original Purchase Price (TODO: parrot, snowman. should set to temp0) case VMGenericTSOCallMode.HasTemporaryID: //51 //persist ID should be 0 til we get one. return((context.StackObject.PersistID == 0 && context.StackObject.GetValue(VMStackObjectVariable.Reserved75) == 0)?VMPrimitiveExitCode.GOTO_TRUE:VMPrimitiveExitCode.GOTO_FALSE); case VMGenericTSOCallMode.SetStackObjOwnerToTemp0: //52 var obj = context.VM.GetObjectById(context.Thread.TempRegisters[0]); if (context.StackObject is VMAvatar || obj == null) { return(VMPrimitiveExitCode.GOTO_TRUE); } foreach (var owned in context.StackObject.MultitileGroup.Objects) { ((VMTSOObjectState)owned.TSOState).OwnerID = obj.PersistID; } if (context.VM.IsServer) { context.VM.GlobalLink.UpdateObjectPersist(context.VM, context.StackObject.MultitileGroup, (worked, objid) => { }); } return(VMPrimitiveExitCode.GOTO_TRUE); //53. Is On Editable Tile //54. Set Stack Object's Crafter Name To Avatar in Temp 0 case VMGenericTSOCallMode.CalcHarvestComponents: //55 { var tableq = Content.Content.Get().GlobalTuning?.EntriesByName["harvest component table"]; if (tableq == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } var table = tableq.Value; int[] componentTable = new int[] { 0, 0, 0 }; var objb = context.StackObject; uint guid = objb.Object.OBJ.GUID; if (objb.MasterDefinition != null) { guid = objb.MasterDefinition.GUID; } var catalog = Content.Content.Get().WorldCatalog; var item = catalog.GetItemByGUID(guid); if (item != null) { string compString = null; if (table.KeyValues.TryGetValue(item.Value.Category.ToString(), out compString)) { var commentInd = compString.IndexOf(';'); if (commentInd == -1) { commentInd = compString.Length; } var substr = compString.Substring(0, commentInd); componentTable = substr.Split(',').Select(x => int.Parse(x)).ToArray(); } } var value = context.StackObject.MultitileGroup.Price; //TODO: scale with wear, object age? var ava = (VMAvatar)context.Caller; float scale = 0.50f + ava.GetPersonData(VMPersonDataVariable.CreativitySkill) / 2000f + ava.GetPersonData(VMPersonDataVariable.MechanicalSkill) / 2000f; value = (int)(value * scale); context.Thread.TempRegisters[0] = (short)((7500 + context.VM.Context.NextRandom((ulong)(value * componentTable[0]))) / 10000); //wood context.Thread.TempRegisters[1] = (short)((7500 + context.VM.Context.NextRandom((ulong)(value * componentTable[1]))) / 10000); //cloth context.Thread.TempRegisters[2] = (short)((7500 + context.VM.Context.NextRandom((ulong)(value * componentTable[2]))) / 10000); //parts return(VMPrimitiveExitCode.GOTO_TRUE); } case VMGenericTSOCallMode.IsStackObjectForSale: //56. return((((context.StackObject as VMGameObject)?.Disabled)?.HasFlag(VMGameObjectDisableFlags.ForSale) ?? false) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); // === FREESO SPECIFIC === case VMGenericTSOCallMode.FSOLightRGBFromTemp012: //128 context.StackObject.LightColor = new Color((int)context.Thread.TempRegisters[0], (int)context.Thread.TempRegisters[1], (int)context.Thread.TempRegisters[2], (int)1); if (context.StackObject.GetValue(VMStackObjectVariable.LightingContribution) > 0) { context.VM.Context.RefreshLighting(context.VM.Context.GetObjectRoom(context.StackObject), true, new HashSet <ushort>()); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.FSOAbortAllInteractions: //129 //aborts all of the interactions of the stack object //a few rules: //if we're interacting with the go here object, set us as interruptable (since by default, go here is not) var sthread = context.StackObject.Thread; if (sthread.ActiveAction?.Callee?.Object?.GUID == 0x000007C4) { (context.StackObject as VMAvatar)?.SetPersonData(VMPersonDataVariable.NonInterruptable, 0); } //if we're in the idle interaction, END IT INSTANTLY. if (sthread.ActiveAction?.Mode == VMQueueMode.Idle) { sthread.AbortCurrentInteraction(); } var actionClone = new List <VMQueuedAction>(sthread.Queue); foreach (var action in actionClone) { sthread.CancelAction(action.UID); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.FSOClearStackObjRelationships: context.StackObject.MeToObject.Clear(); context.StackObject.MeToPersist.Clear(); return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.FSOMarkDonated: var ostate = (context.StackObject?.TSOState as VMTSOObjectState); if (ostate != null) { ostate.ObjectFlags |= VMTSOObjectFlags.FSODonated; } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.FSOAccurateDirectionInTemp0: var dir = (short)((context.StackObject.RadianDirection / Math.PI) * 32767); context.Thread.TempRegisters[0] = dir; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.FSOCanBreak: return((context.StackObject.TreeTable?.Interactions?.Any(x => (x.Flags & TTABFlags.TSOIsRepair) > 0) == true) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); case VMGenericTSOCallMode.FSOBreakObject: { var fobj = context.StackObject.MultitileGroup.BaseObject; (fobj.TSOState as VMTSOObjectState)?.Break(fobj); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.FSOSetWeatherTemp0: { // TSO only function that sets the active weather particle effect. // low byte: intensity in percent (0-255, 100% is "full blast") // high byte: weather flags. in order of lo to high // 9: manual. if not set and intensity is 0, weather is in "auto" mode. // 10/11: (rain, snow, hail?, ...) // 12: thunder (not impl yet) var data = context.Thread.TempRegisters[0]; context.VM.SetGlobalValue(18, data); if (VM.UseWorld) { context.VM.Context.Blueprint.Weather?.SetWeather(data); } return(VMPrimitiveExitCode.GOTO_TRUE); } case VMGenericTSOCallMode.FSOReturnNeighborhoodID: { context.Thread.TempRegisters[0] = (short)context.VM.TSOState.NhoodID; return(VMPrimitiveExitCode.GOTO_TRUE); } case VMGenericTSOCallMode.FSOGoToLotIDTemp01: { if (context.Caller.PersistID == context.VM.MyUID) { uint idLow = (uint)context.Thread.TempRegisters[0]; uint idHigh = (uint)context.Thread.TempRegisters[1] << 16; uint id = idLow | idHigh; if (id != ((VMTSOLotState)context.VM.PlatformState).LotID) { context.VM.SignalLotSwitch(id); } } return(VMPrimitiveExitCode.GOTO_TRUE); } case VMGenericTSOCallMode.FSOIsStackObjectTradable: { var ent = context.StackObject; var item = Content.Content.Get().WorldCatalog.GetItemByGUID((ent.MasterDefinition ?? ent.Object.OBJ).GUID); return((item == null || item.Value.DisableLevel < 2) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); } case VMGenericTSOCallMode.FSOSetStackObjectTransient: { var gobj = context.StackObject as VMGameObject; if (gobj != null) { if (context.Thread.TempRegisters[0] == 1) { gobj.Disabled |= VMGameObjectDisableFlags.Transient; } else { gobj.Disabled &= ~VMGameObjectDisableFlags.Transient; } return(VMPrimitiveExitCode.GOTO_TRUE); } return(VMPrimitiveExitCode.GOTO_FALSE); } default: return(VMPrimitiveExitCode.GOTO_TRUE); } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMRelationshipOperand)args; 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/stack param obj1 = context.StackObject; obj2 = context.VM.GetObjectById((operand is VMOldRelationshipOperand) ? context.Args[0] : context.Locals[operand.Local]); break; case 3: //from object in local/stack param to stack object obj1 = context.VM.GetObjectById((operand is VMOldRelationshipOperand) ? context.Args[0] : context.Locals[operand.Local]); obj2 = context.StackObject; break; default: throw new VMSimanticsException("Invalid relationship type!", context); } var ts1 = context.VM.TS1; if ((obj1 == null || obj2 == null) && !(ts1 && operand.UseNeighbor)) { return(VMPrimitiveExitCode.GOTO_TRUE); } List <short> relToTarg; var myNID = (obj1 as VMAvatar)?.GetPersonData(Model.VMPersonDataVariable.NeighborId) ?? 0; var targNID = (obj2 as VMAvatar)?.GetPersonData(Model.VMPersonDataVariable.NeighborId) ?? 0; if (!ts1 && obj2.PersistID > 0 && !operand.FSONeverPersist) { //use persist matrix whenever possible. //ignores use neighbour flag so we can use str/ltr. var rels = obj1.MeToPersist; var targId = obj2.PersistID; if (!rels.ContainsKey(targId)) { if (operand.FailIfTooSmall) { return(VMPrimitiveExitCode.GOTO_FALSE); } else { rels.Add(targId, new List <short>()); } } if (operand.SetMode > 0) { obj1.ChangedRels.Add(targId); } relToTarg = rels[targId]; } else if (ts1 && (operand.UseNeighbor || (myNID > 0 && targNID > 0))) { //ts1 neighbour matrix if (operand.UseNeighbor) { switch (operand.Mode) { case 0: //from me to stack object myNID = ((VMAvatar)context.Caller).GetPersonData(Model.VMPersonDataVariable.NeighborId); targNID = context.StackObjectID; break; case 1: //from stack object to me myNID = context.StackObjectID; targNID = ((VMAvatar)context.Caller).GetPersonData(Model.VMPersonDataVariable.NeighborId); break; case 2: //from stack object to object in local/stack param myNID = context.StackObjectID; targNID = (operand is VMOldRelationshipOperand) ? context.Args[0] : context.Locals[operand.Local]; break; case 3: //from object in local/stack param to stack object myNID = (operand is VMOldRelationshipOperand) ? context.Args[0] : context.Locals[operand.Local]; targNID = context.StackObjectID; break; default: throw new VMSimanticsException("Invalid relationship type!", context); } } var rels = Content.Content.Get().Neighborhood.GetNeighborByID(myNID).Relationships; if (!rels.ContainsKey(targNID)) { if (operand.FailIfTooSmall) { return(VMPrimitiveExitCode.GOTO_FALSE); } else { rels.Add(targNID, new List <short>()); } } relToTarg = rels[targNID]; } else { 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 List <short>()); } } relToTarg = rels[targId]; obj2.MayHaveRelToMe.Add((ushort)obj1.ObjectID); } if (relToTarg.Count <= operand.RelVar) { if (operand.FailIfTooSmall) { return(VMPrimitiveExitCode.GOTO_FALSE); } else { while (relToTarg.Count <= operand.RelVar) { relToTarg.Add(0); } } } //todo: move to tuning? var diffMultiplier = context.VM.Tuning?.GetTuning("category_mul", 0, context.VM.TSOState.PropertyCategory) ?? 1f; //0: relationship, 1: skill/money, 2: visitor hour scale if (operand.SetMode == 0) { VMMemory.SetVariable(context, operand.VarScope, operand.VarData, relToTarg[operand.RelVar]); } else if (operand.SetMode == 1) { var value = VMMemory.GetVariable(context, operand.VarScope, operand.VarData); relToTarg[operand.RelVar] = Math.Max((short)-100, Math.Min((short)100, value)); } else if (operand.SetMode == 2) { var value = VMMemory.GetVariable(context, operand.VarScope, operand.VarData); relToTarg[operand.RelVar] += (short)(value * diffMultiplier); relToTarg[operand.RelVar] = Math.Max((short)-100, Math.Min((short)100, relToTarg[operand.RelVar])); } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMSetToNextOperand)args; var targetValue = VMMemory.GetVariable(context, operand.TargetOwner, operand.TargetData); var entities = context.VM.Entities; VMEntity Pointer = context.VM.GetObjectById(targetValue); //re-evaluation of what this actually does: //tries to find the next object id (from the previous) that meets a specific condition. //the previous object id is supplied via the target variable // //we should take the first result with object id > targetValue. if (operand.SearchType == VMSetToNextSearchType.PartOfAMultipartTile) { var target = context.VM.GetObjectById(targetValue); if (target == null || (!target.MultitileGroup.MultiTile)) { return(VMPrimitiveExitCode.GOTO_FALSE); //single part } else { var group = target.MultitileGroup.Objects; bool found = false; short bestID = 0; short smallestID = 0; for (int i = 0; i < group.Count; i++) { var temp = group[i]; if (temp.ObjectID < smallestID || smallestID == 0) { smallestID = temp.ObjectID; } if (temp.ObjectID > targetValue) { if ((!found) || (temp.ObjectID < bestID)) { found = true; bestID = temp.ObjectID; } } } if (found) { VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, bestID); return(VMPrimitiveExitCode.GOTO_TRUE); } else { VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, smallestID); return(VMPrimitiveExitCode.GOTO_TRUE); } } } else if (operand.SearchType == VMSetToNextSearchType.ObjectAdjacentToObjectInLocal) { VMEntity anchor = context.VM.GetObjectById((short)context.Locals[operand.Local]); int ptrDir = -1; targetValue = 0; if (Pointer != null) { ptrDir = getAdjDir(anchor, Pointer); if (ptrDir == 3) { return(VMPrimitiveExitCode.GOTO_FALSE); //reached end } } //iterate through all following dirs til we find an object for (int i = ptrDir + 1; i < 4; i++) { var off = AdjStep[i]; var adj = context.VM.Context.ObjectQueries.GetObjectsAt(LotTilePos.FromBigTile( (short)(anchor.Position.TileX + off.X), (short)(anchor.Position.TileY + off.Y), anchor.Position.Level)); if (adj != null && adj.Count > 0) { //lists are ordered by object id. first is the smallest. VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, adj[0].ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } } return(VMPrimitiveExitCode.GOTO_FALSE); } else if (operand.SearchType == VMSetToNextSearchType.Career) { var next = Content.Content.Get().Jobs.SetToNext(targetValue); if (next < 0) { return(VMPrimitiveExitCode.GOTO_FALSE); } VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, next); return(VMPrimitiveExitCode.GOTO_TRUE); } else if (operand.SearchType == VMSetToNextSearchType.NeighborId) { var next = Content.Content.Get().Neighborhood.SetToNext(targetValue); if (next < 0) { return(VMPrimitiveExitCode.GOTO_FALSE); } VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, next); return(VMPrimitiveExitCode.GOTO_TRUE); } else if (operand.SearchType == VMSetToNextSearchType.NeighborOfType) { var next = Content.Content.Get().Neighborhood.SetToNext(targetValue, operand.GUID); if (next < 0) { return(VMPrimitiveExitCode.GOTO_FALSE); } VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, next); return(VMPrimitiveExitCode.GOTO_TRUE); } else { //if we've cached the search type, use that instead of all objects switch (operand.SearchType) { case VMSetToNextSearchType.ObjectOnSameTile: entities = context.VM.Context.ObjectQueries.GetObjectsAt(Pointer.Position); break; case VMSetToNextSearchType.Person: case VMSetToNextSearchType.FamilyMember: entities = context.VM.Context.ObjectQueries.Avatars; break; case VMSetToNextSearchType.ObjectOfType: entities = context.VM.Context.ObjectQueries.GetObjectsByGUID(operand.GUID); break; case VMSetToNextSearchType.ObjectWithCategoryEqualToSP0: entities = context.VM.Context.ObjectQueries.GetObjectsByCategory(context.Args[0]); break; default: break; } if (entities == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } bool loop = (operand.SearchType == VMSetToNextSearchType.ObjectOnSameTile); VMEntity first = null; for (int i = 0; i < entities.Count; i++) //generic search through all objects { var temp = entities[i]; bool found = false; if (temp.ObjectID > targetValue || loop) { switch (operand.SearchType) { //manual search types case VMSetToNextSearchType.NonPerson: found = (temp is VMGameObject); break; case VMSetToNextSearchType.ClosestHouse: return(VMPrimitiveExitCode.GOTO_FALSE); throw new VMSimanticsException("Not implemented!", context); case VMSetToNextSearchType.FamilyMember: found = context.VM.CurrentFamily?.FamilyGUIDs?.Contains(((VMAvatar)temp).Object.OBJ.GUID) ?? false; break; default: //set to next object, or cached search. found = true; break; } if (temp.ObjectID <= targetValue && found) { //remember the first element in case we need to loop back to it (set to next tile on same location) if (first == null) { first = temp; } found = false; } } if (found) { VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, temp.ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } } if (loop) { if (first == null) { return(VMPrimitiveExitCode.GOTO_FALSE); //no elements of this kind at all. } else { VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, first.ObjectID); //set to loop, so go back to lowest obj id. return(VMPrimitiveExitCode.GOTO_TRUE); } //loop around } } return(VMPrimitiveExitCode.GOTO_FALSE); //ran out of objects to test }
/// <summary> /// Set a variable /// </summary> /// <param name="context"></param> /// <param name="scope"></param> /// <param name="data"></param> /// <param name="value"></param> public static bool SetVariable(VMStackFrame context, VMVariableScope scope, short data, short value) { switch (scope) { case VMVariableScope.MyObjectAttributes: //0 context.Caller.SetAttribute((ushort)data, value); return(true); case VMVariableScope.StackObjectAttributes: //1 if (context.StackObject != null) { context.StackObject.SetAttribute((ushort)data, value); } return(true); case VMVariableScope.TargetObjectAttributes: //2 throw new VMSimanticsException("Target Object is Deprecated!", context); case VMVariableScope.MyObject: //3 return(context.Caller.SetValue((VMStackObjectVariable)data, value)); case VMVariableScope.StackObject: //4 if (context.StackObject != null) { return(context.StackObject.SetValue((VMStackObjectVariable)data, value)); } else { return(true); } case VMVariableScope.TargetObject: //5 throw new VMSimanticsException("Target Object is Deprecated!", context); case VMVariableScope.Global: //6 return(context.VM.SetGlobalValue((ushort)data, value)); case VMVariableScope.Literal: //7 /** Huh? **/ return(false); case VMVariableScope.Temps: //8 context.Thread.TempRegisters[data] = value; return(true); case VMVariableScope.Parameters: //9 /** Not too sure if this is illegal **/ context.Args[data] = value; return(true); case VMVariableScope.StackObjectID: //10 /** Change the stack object **/ context.StackObject = context.VM.GetObjectById(value); return(true); case VMVariableScope.TempByTemp: //11 context.Thread.TempRegisters[context.Thread.TempRegisters[data]] = value; return(true); case VMVariableScope.TreeAdRange: //12 return(false); //can't set this! case VMVariableScope.StackObjectTemp: //13 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.MyMotives: //14 if (context.Caller is VMAvatar) { return(((VMAvatar)context.Caller).SetMotiveData((VMMotive)data, value)); } return(false); case VMVariableScope.StackObjectMotives: //15 return(((VMAvatar)context.StackObject).SetMotiveData((VMMotive)data, value)); case VMVariableScope.StackObjectSlot: //16 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.StackObjectMotiveByTemp: //17 return(((VMAvatar)context.StackObject).SetMotiveData((VMMotive)context.Thread.TempRegisters[data], value)); case VMVariableScope.MyPersonData: //18 return(((VMAvatar)context.Caller).SetPersonData((VMPersonDataVariable)data, value)); case VMVariableScope.StackObjectPersonData: //19 return(((VMAvatar)context.StackObject).SetPersonData((VMPersonDataVariable)data, value)); case VMVariableScope.MySlot: //20 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.StackObjectDefinition: //21 return(false); //you can't set this! case VMVariableScope.StackObjectAttributeByParameter: //22 context.StackObject.SetAttribute((ushort)context.Args[data], value); return(true); case VMVariableScope.RoomByTemp0: //23 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.NeighborInStackObject: //24 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.Local: //25 context.Locals[data] = value; return(true); case VMVariableScope.Tuning: //26 return(false); //you can't set this! case VMVariableScope.DynSpriteFlagForTempOfStackObject: //27 context.StackObject.SetDynamicSpriteFlag((ushort)context.Thread.TempRegisters[data], value > 0); return(true); case VMVariableScope.TreeAdPersonalityVar: //28 return(false); //you can't set this! case VMVariableScope.TreeAdMin: //29 return(false); //you can't set this! case VMVariableScope.MyPersonDataByTemp: //30 return(((VMAvatar)context.Caller).SetPersonData((VMPersonDataVariable)context.Thread.TempRegisters[data], value)); case VMVariableScope.StackObjectPersonDataByTemp: //31 return(((VMAvatar)context.StackObject).SetPersonData((VMPersonDataVariable)context.Thread.TempRegisters[data], value)); case VMVariableScope.NeighborPersonData: //32 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.JobData: //33 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.NeighborhoodData: //34 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.StackObjectFunction: //35 return(false); //you can't set this! case VMVariableScope.MyTypeAttr: //36 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.StackObjectTypeAttr: //37 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.ThirtyEight: //38 return(false); //you can't set this! case VMVariableScope.LocalByTemp: //40 context.Locals[context.Thread.TempRegisters[data]] = value; return(true); case VMVariableScope.StackObjectAttributeByTemp: //41 context.StackObject.SetAttribute((ushort)context.Thread.TempRegisters[data], value); return(true); case VMVariableScope.TempXL: //42 throw new VMSimanticsException("Not implemented...", context); //this will need a special case for the expression primitive case VMVariableScope.CityTime: //43 case VMVariableScope.TSOStandardTime: //44 case VMVariableScope.GameTime: //45 return(false); //you can't set this! case VMVariableScope.MyList: //46 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.StackObjectList: //47 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.MoneyOverHead32Bit: //48 //throw new VMSimanticsException("Not implemented...", context); return(true); //needs special case like TempXL. case VMVariableScope.MyLeadTileAttribute: //49 context.Caller.MultitileGroup.BaseObject.SetAttribute((ushort)data, value); return(true); case VMVariableScope.StackObjectLeadTileAttribute: //50 context.StackObject.MultitileGroup.BaseObject.SetAttribute((ushort)data, value); return(true); case VMVariableScope.MyLeadTile: //51 case VMVariableScope.StackObjectLeadTile: //52 case VMVariableScope.StackObjectMasterDef: //53 return(false); case VMVariableScope.FeatureEnableLevel: //54 throw new VMSimanticsException("Not implemented...", context); case VMVariableScope.MyAvatarID: //59 return(false); //you can't set this! default: throw new VMSimanticsException("Unknown scope for set variable!", context); } }
//hilariously large switch case. there's got to be a better way public static short GetEntityDefinitionVar(OBJD objd, VMOBJDVariable var, VMStackFrame context) { switch (var) { case VMOBJDVariable.Version1: return((short)(objd.Version % 0xFFFF)); case VMOBJDVariable.Version2: return((short)(objd.Version >> 16)); case VMOBJDVariable.InitialStackSize: return((short)objd.StackSize); case VMOBJDVariable.BaseGraphic: return((short)objd.BaseGraphicID); case VMOBJDVariable.NumGraphics: return((short)objd.NumGraphics); case VMOBJDVariable.MainTreeID: return((short)objd.BHAV_MainID); // should this use OBJf functions? case VMOBJDVariable.GardeningTreeID: return((short)objd.BHAV_GardeningID); case VMOBJDVariable.TreeTableID: return((short)objd.TreeTableID); case VMOBJDVariable.InteractionGroup: return((short)objd.InteractionGroupID); case VMOBJDVariable.Type: return((short)objd.ObjectType); case VMOBJDVariable.MasterID: return((short)objd.MasterID); case VMOBJDVariable.SubIndex: return((short)objd.SubIndex); case VMOBJDVariable.WashHandsTreeID: return((short)objd.BHAV_WashHandsID); case VMOBJDVariable.AnimTableID: return((short)objd.AnimationTableID); case VMOBJDVariable.GUID1: return((short)(objd.GUID % 0xFFFF)); case VMOBJDVariable.GUID2: return((short)(objd.GUID >> 16)); case VMOBJDVariable.Disabled: return((short)objd.Disabled); case VMOBJDVariable.PortalTreeID: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.Price: return((short)objd.Price); case VMOBJDVariable.BodyStringsID: return((short)objd.BodyStringID); case VMOBJDVariable.SlotsID: return((short)objd.SlotID); case VMOBJDVariable.AllowIntersectionTreeID: return((short)objd.BHAV_AllowIntersectionID); case VMOBJDVariable.UsesFnTable: return((short)objd.UsesFnTable); case VMOBJDVariable.Bitfield1: return((short)objd.BitField1); case VMOBJDVariable.PrepareFoodTreeID: return((short)objd.BHAV_PrepareFoodID); case VMOBJDVariable.CookFoodTreeID: return((short)objd.BHAV_CookFoodID); case VMOBJDVariable.PlaceOnSurfaceTreeID: return((short)objd.BHAV_PlaceSurfaceID); case VMOBJDVariable.DisposeTreeID: return((short)objd.BHAV_DisposeID); case VMOBJDVariable.EatFoodTreeID: return((short)objd.BHAV_EatID); case VMOBJDVariable.PickupFromSlotTreeID: return((short)objd.BHAV_PickupFromSlotID); //uh case VMOBJDVariable.WashDishTreeID: return((short)objd.BHAV_WashDishID); case VMOBJDVariable.EatingSurfaceTreeID: return((short)objd.BHAV_EatSurfaceID); case VMOBJDVariable.SitTreeID: return((short)objd.BHAV_SitID); case VMOBJDVariable.StandTreeID: return((short)objd.BHAV_StandID); case VMOBJDVariable.SalePrice: return((short)objd.SalePrice); case VMOBJDVariable.Unused35: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.Unused36: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.BrokenBaseGraphicOffset: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.Unused38: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.HasCriticalAttributes: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.BuyModeType: return((short)objd.FunctionFlags); case VMOBJDVariable.CatalogStringsID: return((short)objd.CatalogStringsID); case VMOBJDVariable.IsGlobalSimObject: return((short)objd.Global); case VMOBJDVariable.InitTreeID: return((short)objd.BHAV_Init); case VMOBJDVariable.PlaceTreeID: return((short)objd.BHAV_Place); case VMOBJDVariable.UserPickupTreeID: return((short)objd.BHAV_UserPickup); case VMOBJDVariable.WallStyle: return((short)objd.WallStyle); case VMOBJDVariable.LoadTreeID: return((short)objd.BHAV_Load); case VMOBJDVariable.UserPlaceTreeID: return((short)objd.BHAV_UserPlace); case VMOBJDVariable.ObjectVersion: return((short)objd.ObjectVersion); case VMOBJDVariable.RoomChangedTreeID: return((short)objd.BHAV_RoomChange); case VMOBJDVariable.MotiveEffectsID: return((short)objd.MotiveEffectsID); case VMOBJDVariable.CleanupTreeID: return((short)objd.BHAV_Cleanup); case VMOBJDVariable.LevelInfoRequestTreeID: return((short)objd.BHAV_LevelInfo); case VMOBJDVariable.CatalogPopupID: return((short)objd.CatalogID); case VMOBJDVariable.ServingSurfaceTreeID: return((short)objd.CatalogID); case VMOBJDVariable.LevelOffset: return((short)objd.LevelOffset); case VMOBJDVariable.Shadow: return((short)objd.Shadow); case VMOBJDVariable.NumAttributes: return((short)objd.NumAttributes); case VMOBJDVariable.CleanTreeID: return((short)objd.BHAV_Clean); case VMOBJDVariable.QueueSkippedTreeID: return((short)objd.BHAV_QueueSkipped); case VMOBJDVariable.FrontDirection: return((short)objd.FrontDirection); case VMOBJDVariable.WallAdjacencyChangedTreeID: return((short)objd.BHAV_WallAdjacencyChanged); case VMOBJDVariable.MyLeadObject: return((short)objd.MyLeadObject); case VMOBJDVariable.DynamicSpritesBaseID: return((short)objd.DynamicSpriteBaseId); case VMOBJDVariable.NumDynamicSprites: return((short)objd.NumDynamicSprites); case VMOBJDVariable.ChairEntryFlags: return((short)objd.ChairEntryFlags); case VMOBJDVariable.TileWidth: return((short)objd.TileWidth); case VMOBJDVariable.LotCategories: return(0); //NOT IN OBJD RIGHT NOW! case VMOBJDVariable.BuildModeType: return((short)objd.BuildModeType); case VMOBJDVariable.OriginalGUID1: return((short)objd.OriginalGUID1); case VMOBJDVariable.OriginalGUID2: return((short)objd.OriginalGUID2); case VMOBJDVariable.SuitGUID1: return((short)objd.SuitGUID1); case VMOBJDVariable.SuitGUID2: return((short)objd.SuitGUID2); case VMOBJDVariable.PickupTreeID: return((short)objd.BHAV_Pickup); case VMOBJDVariable.ThumbnailGraphic: return((short)objd.ThumbnailGraphic); case VMOBJDVariable.ShadowFlags: return((short)objd.ShadowFlags); case VMOBJDVariable.FootprintMask: return((short)objd.FootprintMask); case VMOBJDVariable.DynamicMultiTileUpdateTreeID: return((short)objd.BHAV_DynamicMultiTileUpdate); case VMOBJDVariable.ShadowBrightness: return((short)objd.ShadowBrightness); case VMOBJDVariable.RepairTreeID: return((short)objd.BHAV_Repair); case VMOBJDVariable.WallStyleSpriteID: return((short)objd.WallStyleSpriteID); case VMOBJDVariable.RatingHunger: return((short)objd.RatingHunger); case VMOBJDVariable.RatingComfort: return((short)objd.CatalogID); case VMOBJDVariable.RatingHygiene: return((short)objd.RatingHygiene); case VMOBJDVariable.RatingBladder: return((short)objd.RatingBladder); case VMOBJDVariable.RatingEnergy: return((short)objd.RatingEnergy); case VMOBJDVariable.RatingFun: return((short)objd.RatingFun); case VMOBJDVariable.RatingRoom: return((short)objd.RatingRoom); case VMOBJDVariable.RatingSkillFlags: return((short)objd.RatingSkillFlags); case VMOBJDVariable.NumTypeAttributes: throw new VMSimanticsException("Not Implemented!", context); //?? case VMOBJDVariable.MiscFlags: throw new VMSimanticsException("Not Implemented!", context); //?? case VMOBJDVariable.TypeAttrGUID1: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.TypeAttrGUID2: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.InteractionResultStrings: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.ClientHouseJoinTreeID: throw new VMSimanticsException("Not Implemented!", context); case VMOBJDVariable.PrepareForSaleTreeID: throw new VMSimanticsException("Not Implemented!", context); default: throw new VMSimanticsException("Unknown definition var", context); } }
public static short GetTuningVariable(VMEntity entity, ushort data, VMStackFrame context) { var tableID = (ushort)(data >> 7); var keyID = (ushort)(data & 0x7F); int mode = 0; if (tableID < 64) { mode = 0; } else if (tableID < 128) { tableID = (ushort)((tableID - 64)); mode = 1; } else if (tableID < 192) { tableID = (ushort)((tableID - 128)); mode = 2; } BCON bcon; OTFTable tuning; /** This could be in a BCON or an OTF **/ switch (mode) { case 0: //local bcon = context.ScopeResource.Get <BCON>((ushort)(tableID + 4096)); if (bcon != null) { return((short)bcon.Constants[keyID]); } tuning = context.ScopeResource.Get <OTFTable>((ushort)(tableID + 4096)); if (tuning != null) { return((short)tuning.GetKey(keyID).Value); } break; case 1: //semi globals ushort testTab = (ushort)(tableID + 8192); bcon = context.ScopeResource.Get <BCON>(testTab); if (bcon != null && keyID < bcon.Constants.Length) { return((short)bcon.Constants[keyID]); } tuning = context.ScopeResource.Get <OTFTable>(testTab); if (tuning != null) { return((short)tuning.GetKey(keyID).Value); } if (context.ScopeResource.SemiGlobal != null) { bcon = context.ScopeResource.SemiGlobal.Get <BCON>(testTab); if (bcon != null && keyID < bcon.Constants.Length) { return((short)bcon.Constants[keyID]); } tuning = context.ScopeResource.SemiGlobal.Get <OTFTable>(testTab); if (tuning != null) { return((short)tuning.GetKey(keyID).Value); } } break; case 2: //global bcon = context.Global.Resource.Get <BCON>((ushort)(tableID + 256)); if (bcon != null && keyID < bcon.Constants.Length) { return((short)bcon.Constants[keyID]); } tuning = context.Global.Resource.Get <OTFTable>((ushort)(tableID + 256)); if (tuning != null) { return((short)tuning.GetKey(keyID).Value); } break; } //throw new Exception("Could not find tuning constant!"); return(0); }