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; 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) { 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) { //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, VMPrimitiveOperand args) { var operand = (VMDropOntoOperand)args; var src = (operand.SrcSlotMode == 1) ? (ushort)context.Args[operand.SrcSlotNum] : operand.SrcSlotNum; var dest = (operand.DestSlotMode == 1) ? (ushort)context.Args[operand.DestSlotNum] : operand.DestSlotNum; var item = context.Caller.GetSlot(src); if (item != null) { var itemTest = context.StackObject.GetSlot(dest); if (itemTest == null) { return((context.StackObject.PlaceInSlot(item, dest, true, context.VM.Context)) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); //cannot replace items currently in slots } } else { return(VMPrimitiveExitCode.GOTO_FALSE); } }
//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 = (VMSleepOperand)args; var idleStart = context.Thread.ScheduleIdleStart; context.Args[operand.StackVarToDec] -= (short)((idleStart != 0 && idleStart < context.VM.Scheduler.CurrentTickID) ? (context.VM.Scheduler.CurrentTickID - idleStart) : 1); if (context.Thread.Interrupt) { context.Thread.ScheduleIdleStart = 0; context.Thread.Interrupt = false; return(VMPrimitiveExitCode.GOTO_TRUE); } if (context.Args[operand.StackVarToDec] <= -1) { context.Thread.ScheduleIdleStart = 0; context.VM.Context.NextRandom(1); //rng cycle - for desync detect return((context.Caller.Dead)?VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK:VMPrimitiveExitCode.GOTO_TRUE); } else { context.Thread.ScheduleIdleStart = context.VM.Scheduler.CurrentTickID; context.VM.Scheduler.ScheduleTickIn(context.Caller, (uint)context.Args[operand.StackVarToDec] + 1); return(VMPrimitiveExitCode.CONTINUE_FUTURE_TICK); } }
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, VMPrimitiveOperand args) { var operand = (VMSpecialEffectOperand)args; //TODO: Implement this, fridge has one when u have no money return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var obj = context.Caller; if (context.Caller.TotalSlots() == 0) { return(VMPrimitiveExitCode.GOTO_FALSE); } var drop = context.Caller.GetSlot(0); if (drop == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } int intDir = (int)Math.Round(Math.Log((double)obj.Direction, 2)); LotTilePos basePos = LotTilePos.FromBigTile(obj.Position.TileX, obj.Position.TileY, obj.Position.Level); for (int i = 0; i < Positions.Length; i++) { int j = (i % 2 == 1) ? ((Positions.Length - 1) - i / 2) : i / 2; var posChange = drop.MultitileGroup.ChangePosition(basePos + Positions[(j + intDir) % 8], obj.Direction, context.VM.Context); if (posChange.Status == VMPlacementError.Success) { return(VMPrimitiveExitCode.GOTO_TRUE); } } return(VMPrimitiveExitCode.GOTO_FALSE); }
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, 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 OpLabelControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, OpTextProvider textP) : this() { Scope = scope; Operand = operand; TextProvider = textP; OperandUpdated(); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMGetDirectionToOperand)args; var obj2 = context.StackObject; VMEntity obj1; //todo: wrong flag below? if ((operand.Flags & 1) == 0) { obj1 = context.Caller; } else { obj1 = context.VM.GetObjectById(VMMemory.GetVariable(context, operand.ObjectScope, operand.OScopeData)); } var pos1 = obj1.Position; var pos2 = obj2.Position; var direction = DirectionUtils.Normalize(Math.Atan2(pos2.x - pos1.x, pos1.y - pos2.y)); var result = Math.Round((DirectionUtils.PosMod(direction, Math.PI * 2) / Math.PI) * 4); VMMemory.SetVariable(context, operand.ResultOwner, operand.ResultData, (short)result); return(VMPrimitiveExitCode.GOTO_TRUE); }
public override Dictionary<int, string> GetNamedProperties(EditorScope scope, VMPrimitiveOperand operand) { var map = new Dictionary<int, string>(); var op = (VMGotoRoutingSlotOperand)operand; switch (op.Type) { case VMSlotScope.Global: var gslots = scope.GetResource<STR>(257, ScopeSource.Global); for (int i = 0; i < gslots.Length; i++) map.Add(i, gslots.GetString(i)); return map; case VMSlotScope.Literal: var slotNs = scope.GetResource<STR>(257, ScopeSource.Private); var slotRes = scope.GetResource<SLOT>(scope.GetOBJD().SlotID, ScopeSource.Private); if (slotRes == null) return map; var slots = slotRes.Slots[3]; for (int i = 0; i < slots.Count; i++) map.Add(i, (slotNs != null && slotNs.GetString(i) != null)?slotNs.GetString(i):"slot "+i); return map; case VMSlotScope.StackVariable: var str = scope.GetVarScopeDataNames(VMVariableScope.Parameters); for (int i = 0; i < str.Count; i++) map.Add(str[i].Value, str[i].Name); return map; default: return map; } }
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 = (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 OpFlagsControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, OpFlag[] flags) { InitializeComponent(); this.FlagsPanel.Controls.Clear(); Master = master; Scope = scope; Operand = operand; Flags = flags; FlagChecks = new CheckBox[flags.Length]; int i = 0; foreach (var flag in flags) { var check = new CheckBox(); check.AutoSize = true; check.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); check.Size = new System.Drawing.Size(195, 17); check.Text = flag.Title; check.UseVisualStyleBackColor = true; check.CheckedChanged += Check_CheckedChanged; FlagChecks[i++] = check; CheckToFlag.Add(check, flag); this.FlagsPanel.Controls.Add(check); } OperandUpdated(); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { if (context.StackObject is VMGameObject) { return(VMPrimitiveExitCode.GOTO_TRUE); } var operand = (VMShowStringOperand)args; var table = context.ScopeResource.Get <STR>(operand.StringTable); var avatar = context.StackObject as VMAvatar; if (table != null) { var message = VMDialogHandler.ParseDialogString(context, table.GetString(operand.StringID - 1), table); var vm = context.VM; var channelID = 0; if (!operand.NoHistory) { vm.SignalChatEvent(new VMChatEvent(avatar, VMChatEventType.Message, (byte)(channelID & 0x7f), avatar.Name, message)); } if ((channelID & 0x80) == 0) { avatar.Message = message; } } return(VMPrimitiveExitCode.GOTO_TRUE); }
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, 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 = (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.GetType() == typeof(VMGameObject)) { var TargObj = (VMGameObject)target; TargObj.RefreshGraphic(); } break; } return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMTransferFundsOperand)args; var amount = VMMemory.GetBigVariable(context, operand.GetAmountOwner(), (short)operand.AmountData); if ((operand.Flags & VMTransferFundsFlags.Subtract) > 0) { amount = -amount; //instead of subtracting, we're adding } //weird terms for the flags here but ts1 is inverted //amount contains the amount we are subtracting from the budget. var oldBudget = context.VM.TS1State.CurrentFamily?.Budget ?? 0; var newBudget = oldBudget - amount; if (oldBudget < 0) { return(VMPrimitiveExitCode.GOTO_FALSE); } if ((operand.Flags & VMTransferFundsFlags.JustTest) == 0 && context.VM.TS1State.CurrentFamily != null) { context.VM.TS1State.CurrentFamily.Budget = newBudget; } return(VMPrimitiveExitCode.GOTO_TRUE); //ts1 does have expense types, which could be used for expenses monitoring (i do not think ts1 had this) }
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 OpFlagsControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, OpFlag[] flags) { InitializeComponent(); this.FlagsPanel.Controls.Clear(); Master = master; Scope = scope; Operand = operand; Flags = flags; FlagChecks = new CheckBox[flags.Length]; int i = 0; foreach (var flag in flags) { var check = new CheckBox(); check.AutoSize = true; check.Margin = new System.Windows.Forms.Padding(3, 0, 3, 0); check.Size = new System.Drawing.Size(195, 17); check.Text = flag.Title; check.UseVisualStyleBackColor = true; check.CheckedChanged += Check_CheckedChanged; FlagChecks[i++] = check; CheckToFlag.Add(check, flag); this.FlagsPanel.Controls.Add(check); } OperandUpdated(); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMGetTerrainInfoOperand)args; var obj = (operand.UseMe)?context.Caller:context.StackObject; if (obj.Position == LotTilePos.OUT_OF_WORLD) { return(VMPrimitiveExitCode.GOTO_FALSE); } for (int i = 0; i < 5; i++) { if (operand.Unknown[i] != 0) { } } //TODO: all. switch (operand.Mode) { case 0: //four altitudes around stack object //3 is flat in pre-alpha. TODO when terrain is in progress. context.Thread.TempRegisters[0] = 3; context.Thread.TempRegisters[1] = 3; context.Thread.TempRegisters[2] = 3; context.Thread.TempRegisters[3] = 3; break; case 1: //slope at stack object //unverifiable since terrain tool is a little broken in pre-alpha //most likely altitude difference. +x slope down towards positive x, -x slope down towards -x. context.Thread.TempRegisters[0] = 0; context.Thread.TempRegisters[1] = 0; break; case 2: //fixed coordinates of stack object //VERIFIED var pos = obj.Position; context.Thread.TempRegisters[0] = pos.TileX; //tile x context.Thread.TempRegisters[1] = (short)(pos.x % 16); //sub-tile x context.Thread.TempRegisters[2] = pos.TileY; //tile y context.Thread.TempRegisters[3] = (short)(pos.y % 16); //sub-tile y context.Thread.TempRegisters[4] = pos.Level; //level break; case 3: //grass height under stack object // 0-255, depending on terrain colour. (dead-alive) context.Thread.TempRegisters[0] = 0; //used for extra ball friction on (short) grass. break; case 4: //ceiling or roof exists above stack object. unused. context.Thread.TempRegisters[0] = 0; break; } return(VMPrimitiveExitCode.GOTO_TRUE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMTestObjectTypeOperand)args; 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, 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); var levelDiff = Math.Abs(pos2.Level - pos1.Level); if (context.VM.TS1) { context.Thread.TempRegisters[operand.TempNum] = (short)Math.Max(20 * levelDiff, result + 5 * levelDiff); } else { context.Thread.TempRegisters[operand.TempNum] = (short)(result + 20 * levelDiff); //FreeSO behaviour. consistently allows us to remove the level factor. } 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, 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 OpLabelControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, OpTextProvider textP) : this() { Scope = scope; Operand = operand; TextProvider = textP; OperandUpdated(); }
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.ActiveAction.Callee == context.StackObject) ? VMPrimitiveExitCode.GOTO_TRUE:VMPrimitiveExitCode.GOTO_FALSE); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMFindBestObjectForFunctionOperand)args; 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+(posDiff.Level*posDiff.Level*900*256))/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 = (VMGotoRelativePositionOperand)args; if (context.Thread.IsCheck) { return(VMPrimitiveExitCode.GOTO_FALSE); } var obj = context.StackObject; if (obj == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } 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 { if (operand.Location == VMGotoRelativeLocation.AnywhereNear) { slot.MinProximity = 16; slot.MaxProximity = 32; //diamond shaped slot.OptimalProximity = 16; slot.Rsflags |= (SLOTFlags)255; } else { slot.MinProximity = 16; slot.MaxProximity = 24; 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 = (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 VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMRunFunctionalTreeOperand)args; 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, VMPrimitiveOperand args) { if (context.StackObject?.Thread != null) { context.VM.Scheduler.RescheduleInterrupt(context.StackObject); context.StackObject.Thread.Interrupt = true; } return(VMPrimitiveExitCode.GOTO_TRUE); }
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 Dictionary<int, string> GetNamedProperties(EditorScope scope, VMPrimitiveOperand operand) { var map = new Dictionary<int, string>(); var evts = scope.GetAllResource<FWAV>(ScopeSource.Private); foreach (var evt in evts) { map.Add(evt.ChunkID, evt.Name); } return map; }
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 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 static VMRoutine Assemble(VM vm, BHAV bhav) { var context = vm.Context; var routine = new VMRoutine(); routine.Locals = bhav.Locals; routine.Arguments = bhav.Args; routine.Type = bhav.Type; routine.ID = bhav.ChunkID; routine.Chunk = bhav; routine.VM = vm; routine.Rti = new VMFunctionRTI { Name = bhav.ChunkLabel }; VMInstruction[] instructions = new VMInstruction[bhav.Instructions.Length]; for (var i = 0; i < bhav.Instructions.Length; i++) { var bhavInstruction = bhav.Instructions[i]; var instruction = new VMInstruction(); instruction.Index = (byte)i; instruction.Opcode = bhavInstruction.Opcode; instruction.Operand = null; instruction.FalsePointer = bhavInstruction.FalsePointer; instruction.TruePointer = bhavInstruction.TruePointer; instruction.Breakpoint = bhavInstruction.Breakpoint; instruction.Function = routine; /** Routine call **/ if (instruction.Opcode >= 256) { var operand = new VMSubRoutineOperand(); operand.Read(bhavInstruction.Operand); instruction.Operand = operand; } else { var primitive = context.Primitives[instruction.Opcode]; if (primitive != null) { if (primitive.OperandModel != null) { VMPrimitiveOperand operand = (VMPrimitiveOperand)Activator.CreateInstance(primitive.OperandModel); operand.Read(bhavInstruction.Operand); instruction.Operand = operand; } } } instructions[i] = instruction; } routine.Instructions = instructions; return(routine); }
public OpAnimControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title) { InitializeComponent(); this.Dock = DockStyle.Fill; Master = master; Scope = scope; Operand = (VMAnimateSimOperand)operand; TitleLabel.Text = title; OperandUpdated(); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMRunFunctionalTreeOperand)args; 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 OpSoundControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title) { InitializeComponent(); this.Dock = DockStyle.Fill; Master = master; Scope = scope; Operand = (VMPlaySoundOperand)operand; TitleLabel.Text = title; OperandUpdated(); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMFindLocationForOperand)args; var refObj = (operand.UseLocalAsRef) ? context.VM.GetObjectById((short)context.Locals[operand.Local]) : context.Caller; var obj = context.StackObject; switch (operand.Mode) { case 0: //default if (FindLocationFor(obj, refObj, context.VM.Context)) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } case 1: //out of world obj.SetPosition(LotTilePos.OUT_OF_WORLD, Direction.NORTH, context.VM.Context); return(VMPrimitiveExitCode.GOTO_TRUE); case 2: //"smoke cloud" - halfway between callee and caller (is "caller" actually reference object?) var smokePos = context.Callee.Position; smokePos += context.Caller.Position; smokePos /= 2; smokePos -= new LotTilePos(8, 8, 0); //smoke is 2x2... offset to center it. return((obj.SetPosition(smokePos, Direction.NORTH, context.VM.Context).Status == VMPlacementError.Success)? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); case 3: case 4: //along object vector var intDir = (int)Math.Round(Math.Log((double)refObj.Direction, 2)); if (operand.Mode == 4) { intDir = (intDir + 2) % 8; //lateral to object vector } if (FindLocationVector(obj, refObj, context.VM.Context, intDir)) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } } 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; 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 = (VMSnapOperand)args; var avatar = context.Caller; //todo, can sometimes be an object?? see roaches object tile movement, snaps to its own routing slot var obj = context.StackObject; SLOTItem slot = null; switch (operand.Mode) { case VMSnapSlotScope.StackVariable: slot = VMMemory.GetSlot(context, VMSlotScope.StackVariable, operand.Index); break; case VMSnapSlotScope.BeContained: return (context.StackObject.PlaceInSlot(context.Caller, 0, true, context.VM.Context)) ? VMPrimitiveExitCode.GOTO_TRUE:VMPrimitiveExitCode.GOTO_FALSE; case VMSnapSlotScope.InFront: slot = new SLOTItem { Type = 3, Standing = 1, MinProximity = 16, Rsflags = SLOTFlags.NORTH }; break; case VMSnapSlotScope.Literal: slot = VMMemory.GetSlot(context, VMSlotScope.Literal, operand.Index); break; case VMSnapSlotScope.Global: slot = VMMemory.GetSlot(context, VMSlotScope.Global, operand.Index); break; } if (operand.Mode != VMSnapSlotScope.BeContained) { var parser = new VMSlotParser(slot); var locations = parser.FindAvaliableLocations(obj, context.VM.Context, avatar); if (slot.SnapTargetSlot > -1) { if (!context.StackObject.PlaceInSlot(context.Caller, slot.SnapTargetSlot, true, context.VM.Context)) return VMPrimitiveExitCode.GOTO_FALSE; if (locations.Count > 0) avatar.RadianDirection = ((slot.Rsflags & SLOTFlags.SnapToDirection) > 0) ? locations[0].RadianDirection: avatar.RadianDirection; } else { if (locations.Count > 0) { if (!SetPosition(avatar, locations[0].Position, ((slot.Rsflags & SLOTFlags.SnapToDirection) > 0) ? locations[0].RadianDirection : avatar.RadianDirection, context.VM.Context)) return VMPrimitiveExitCode.GOTO_FALSE; } else { avatar.SetValue(VMStackObjectVariable.PrimitiveResultID, (parser.Blocker == null) ? (short)0 : parser.Blocker.ObjectID); return VMPrimitiveExitCode.GOTO_FALSE; } } } return VMPrimitiveExitCode.GOTO_TRUE; }
public OpComboControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, string property, OpNamedPropertyProvider valueProvider) { InitializeComponent(); this.Dock = DockStyle.Fill; Master = master; Scope = scope; Operand = operand; TitleLabel.Text = title; Property = property; ValueProvider = valueProvider; OperandUpdated(); }
public OpValueControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, string property, OpValueBoundsProvider bounds) { InitializeComponent(); Master = master; Scope = scope; Operand = operand; TitleLabel.Text = title; Property = property; BoundsProvider = bounds; this.Dock = DockStyle.Fill; OperandUpdated(); }
public OpComboControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, string property, OpNamedPropertyProvider valueProvider) { InitializeComponent(); this.Dock = DockStyle.Fill; Master = master; Scope = scope; Operand = operand; TitleLabel.Text = title; Property = property; ValueProvider = valueProvider; OperandUpdated(); }
public OpObjectControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, string guidProperty) { InitializeComponent(); this.Dock = DockStyle.Fill; Master = master; Scope = scope; Operand = operand; TitleLabel.Text = title; GUIDProperty = guidProperty; OperandUpdated(); }
public OpObjectControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, string guidProperty) { InitializeComponent(); this.Dock = DockStyle.Fill; Master = master; Scope = scope; Operand = operand; TitleLabel.Text = title; GUIDProperty = guidProperty; OperandUpdated(); }
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 OpValueControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, string property, OpValueBoundsProvider bounds) { InitializeComponent(); Master = master; Scope = scope; Operand = operand; TitleLabel.Text = title; Property = property; BoundsProvider = bounds; this.Dock = DockStyle.Fill; OperandUpdated(); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMGenericTSOCallOperand)args; switch (operand.Call) { case VMGenericTSOCallMode.GetIsPendingDeletion: return(VMPrimitiveExitCode.GOTO_FALSE); case VMGenericTSOCallMode.IsTemp0AvatarIgnoringTemp1Avatar: context.Thread.TempRegisters[0] = 0; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.IsGlobalBroken: return(VMPrimitiveExitCode.GOTO_FALSE); case VMGenericTSOCallMode.GetLotOwner: case VMGenericTSOCallMode.StackObjectOwnerID: context.Thread.TempRegisters[0] = context.Caller.ObjectID; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.SetActionIconToStackObject: context.Thread.Queue[0].IconOwner = context.StackObject; return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.HasTemporaryID: return(VMPrimitiveExitCode.GOTO_FALSE); //used by real game to check if object is persistently tracked probably. case 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, false, context.VM.Context); //slot to slot needs no cleanup context.StackObject.PlaceInSlot(temp1, i, false, context.VM.Context); } return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.ReturnLotCategory: context.Thread.TempRegisters[0] = 6; //skills lot. see #Lot Types in global.iff return(VMPrimitiveExitCode.GOTO_TRUE); case VMGenericTSOCallMode.TestStackObject: return((context.StackObject != null) ? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); default: return(VMPrimitiveExitCode.GOTO_TRUE); } }
public OpScopeControl(BHAVEditor master, EditorScope scope, VMPrimitiveOperand operand, string title, string sourceProperty, string dataProperty) { InitializeComponent(); this.Dock = DockStyle.Fill; Master = master; Scope = scope; Operand = operand; TitleLabel.Text = title; SourceProperty = sourceProperty; DataProperty = dataProperty; OperandUpdated(); }
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; obj.Delete(operand.CleanupAll, context.VM.Context); //if (obj == context.StackObject) context.StackObject = null; return VMPrimitiveExitCode.GOTO_TRUE; }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMOnlineJobsCallOperand)args; 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, VMPrimitiveOperand args) { var operand = (VMOnlineJobsCallOperand)args; 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, VMPrimitiveOperand args) { var operand = (VMGetTerrainInfoOperand)args; var obj = (operand.UseMe)?context.Caller:context.StackObject; if (obj.Position == LotTilePos.OUT_OF_WORLD) return VMPrimitiveExitCode.GOTO_FALSE; for (int i = 0; i < 5; i++) { if (operand.Unknown[i] != 0) { } } //TODO: all. switch (operand.Mode) { case 0: //four altitudes around stack object //3 is flat in pre-alpha. TODO when terrain is in progress. context.Thread.TempRegisters[0] = 3; context.Thread.TempRegisters[1] = 3; context.Thread.TempRegisters[2] = 3; context.Thread.TempRegisters[3] = 3; break; case 1: //slope at stack object //unverifiable since terrain tool is a little broken in pre-alpha //most likely altitude difference. +x slope down towards positive x, -x slope down towards -x. context.Thread.TempRegisters[0] = 0; context.Thread.TempRegisters[1] = 0; break; case 2: //fixed coordinates of stack object //VERIFIED var pos = obj.Position; context.Thread.TempRegisters[0] = pos.TileX; //tile x context.Thread.TempRegisters[1] = (short)(pos.x%16); //sub-tile x context.Thread.TempRegisters[2] = pos.TileY; //tile y context.Thread.TempRegisters[3] = (short)(pos.y%16); //sub-tile y context.Thread.TempRegisters[4] = pos.Level; //level break; case 3: //grass height under stack object // 0-255, depending on terrain colour. (dead-alive) context.Thread.TempRegisters[0] = 0; //used for extra ball friction on (short) grass. break; case 4: //ceiling or roof exists above stack object. unused. context.Thread.TempRegisters[0] = 0; break; } return VMPrimitiveExitCode.GOTO_TRUE; }