コード例 #1
0
        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);
        }
コード例 #2
0
ファイル: JitIdeas.cs プロジェクト: yuripourre-forks/FreeSO
        //the point:
        //a lot of execution time is spent on if statements and switches that check the operand
        //a way to remove that entirely would be to write and compile c# functions with those *static* operands in mind.
        //the compiler can also optimise multiple consecutive expression primitives. This can lead to orders of magnitude speedups for simantics.
        //(also a point of interest for generating readable simantics code... and perhaps writing our own text language!)

        //on platforms without JIT, we can still AOT simantics scripts that we expect to be there, then swap to interpreter when
        //hash functions do not match. we usually do one cs file per iff, and one assembly per iff - but with the AOT setup you would include ALL cs files
        //in the same fully inclusive assembly. (eg. TS1.Scripts or FSO.Scripts)

        //building the code
        // - we build separate inst
        // - anything that uses a temp variable must be enclosed in a scope (see refresh)

        //partial implementation and fallbacks
        // - instructions fall back on their interpreter primitives, pulling from private static operands baked into the class.
        // - scopes fall back on VMMemory

        //function modes:
        // - async function: sets up full vm stack frame system, can yield. exits this function to enter the next, essentially yielding.
        // - inline function: function is small and guaranteed not to yield (or change). however i would like to extend this to yielding functions somehow, specifically Idle.
        // - sync function: function is guaranteed to not yield. as a separate function.

        //structure detection:
        // - structure types: if/else, switch, loop
        // - a structure is broken when: structure from a non-nested struct jumps back into a branch, a instruction in the structure yields
        //   - broken structures only fully kill the loop primitive - for if/else and switch they will just return to the global switch statement.
        //   - loop primitives will have to break out eventually regardless - the breaking point is code that jumps *in*.

        public JitReturnData main(VMStackFrame context, byte instruction)
        {
            VMPrimitiveExitCode eResult;

            while (true)
            {
                switch (instruction)
                {
                case 0:
                    //0: expression
                    context.Thread.TempRegisters[0] = 1;
                    //1: set to next
                    eResult     = new VMSetToNext().Execute(context, context.Routine.Instructions[1].Operand);
                    instruction = (byte)((eResult == VMPrimitiveExitCode.GOTO_TRUE) ? 2 : 4);
                    break;

                case 2:
                    //2: expression
                    context.StackObject.SetValue(VMStackObjectVariable.BirthDay, VMMemory.GetVariable(context, Scopes.VMVariableScope.StackObjectList, 2));
                    //3: refresh
                    {
                        VMEntity target = context.Caller;
                        if (target is VMGameObject)
                        {
                            var TargObj = (VMGameObject)target;
                            TargObj.RefreshGraphic();
                        }
                    }
                    break;
                }
            }
        }
コード例 #3
0
ファイル: VMState.cs プロジェクト: lanicon/ctf-writeups
 public VMState()
 {
     InternalState1 = MainModule.GetOrCreateInternalState1();
     Memory1        = MainModule.GetOrCreateVMMemory();
     memory2        = MainModule.GetOrCreateMemory2();
     object_4       = MainModule.smethod_164();
 }
コード例 #4
0
        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);
        }
コード例 #5
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args)
        {
            var operand  = (VMTestObjectTypeOperand)args;
            var objectID = VMMemory.GetVariable(context, operand.IdOwner, operand.IdData);

            var obj = (operand.IdOwner == VMVariableScope.StackObjectID)?context.StackObject: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);
            }
        }
コード例 #6
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand <VMGetDirectionToOperand>();

            var      obj2 = context.StackObject;
            VMEntity obj1;

            if ((operand.Flags & 1) > 0)
            {
                obj1 = context.Caller;
            }
            else
            {
                obj1 = context.VM.GetObjectById(VMMemory.GetVariable(context, (VMVariableScope)operand.ObjectScope, operand.OScopeData));
            }


            //var pos1 = obj1.Position;
            var pos1 = context.Caller.Position;
            var pos2 = obj2.Position;

            var result = (Math.Round((Math.Atan2(Math.Floor(pos1.X) - Math.Floor(pos2.X), Math.Floor(pos2.Y) - Math.Floor(pos1.Y)) / (Math.PI * 2)) * 8) + 20) % 8;

            VMMemory.SetVariable(context, (VMVariableScope)operand.ResultOwner, operand.ResultData, (short)result);

            return(VMPrimitiveExitCode.GOTO_TRUE);
        }
コード例 #7
0
        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);
        }
コード例 #8
0
        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)
        }
コード例 #9
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context) //TODO: Behaviour for being notified out of idle and interaction canceling
        {
            var operand = context.GetCurrentOperand <VMIdleForInputOperand>();

            if (operand.AllowPush == 1 && context.Thread.Queue.Count > 1)
            { //if there are any more interactions, we have been interrupted
                return(VMPrimitiveExitCode.INTERRUPT);
            }

            if (context.Thread.Queue[0].Cancelled)
            {
                context.Caller.SetFlag(VMEntityFlags.NotifiedByIdleForInput, true);
                return(VMPrimitiveExitCode.GOTO_TRUE);
            }

            var ticks = VMMemory.GetVariable(context, TSO.Simantics.engine.scopes.VMVariableScope.Parameters, operand.StackVarToDec);

            ticks--;

            if (ticks < 0)
            {
                return(VMPrimitiveExitCode.GOTO_TRUE);
            }
            else
            {
                VMMemory.SetVariable(context, TSO.Simantics.engine.scopes.VMVariableScope.Parameters, operand.StackVarToDec, ticks);
                return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK);
            }
        }
コード例 #10
0
        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);
            }
        }
コード例 #11
0
        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);
            }

            if (operand.GUID == 0xDC6D7898)
            {
                operand = operand;
            }

            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);
            }
        }
コード例 #12
0
        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);
        }
コード例 #13
0
        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);
        }
コード例 #14
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand     = context.GetCurrentOperand <VMSetToNextOperand>();
            var targetValue = VMMemory.GetVariable(context, operand.GetTargetOwner(), operand.GetTargetData());

            if (operand.SearchType == VMSetToNextSearchType.ObjectOfType)
            {
                //TODO: Implement!
                return(VMPrimitiveExitCode.GOTO_FALSE);
            }
            throw new Exception("Unknown search type");
        }
コード例 #15
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand <VMRandomNumberOperand>();

            var rangeValue = (ushort)VMMemory.GetVariable(context, operand.RangeScope, operand.RangeData);


            var result = context.VM.Context.NextRandom(rangeValue);

            VMMemory.SetVariable(context, operand.DestinationScope, operand.DestinationData, (short)result);
            if (operand.RangeData == 8327)
            {
                result = 0;
            }
            return(VMPrimitiveExitCode.GOTO_TRUE);
        }
コード例 #16
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand <VMGotoRoutingSlotOperand>();
            var slot    = VMMemory.GetSlot(context, operand.Type, operand.Data);
            var obj     = (VMGameObject)context.Callee;
            var avatar  = (VMAvatar)context.Caller;

            //slot.Rsflags = tso.files.formats.iff.chunks.SLOTFlags.WEST;

            /**
             * Very little is kown about SLOTs so for now this is a place to dump comments
             *
             * Slots measure proximity in units of 16. 16 = 1 tile away from the object.
             * Global slots are in global.iff in a slot table with ID 100.
             * global.iff also has a string table #257 which provides labels for the SLOTs
             */

            //Dont really know what 3 means, maybe relative to object?
            if (slot.Type == 3)
            {
                var tilePosition = new Vector2(obj.Position.X, obj.Position.Y);
                var min          = slot.MinProximity;
                var max          = slot.MaxProximity;
                var desired      = slot.OptimalProximity;

                if (max == 0)
                {
                    max = min;
                }
                if (desired == 0)
                {
                    desired = min;
                }

                var possibleTargets = VMRouteFinder.FindAvaliableLocations(tilePosition, slot.Rsflags, min, max, desired);
                if (possibleTargets.Count == 0)
                {
                    return(VMPrimitiveExitCode.GOTO_FALSE);
                }

                //TODO: Route finding and pick best route
                var target = possibleTargets[0];
                avatar.Position = new Vector3(target.Position.X + 0.5f, target.Position.Y + 0.5f, 0.0f);
            }

            return(VMPrimitiveExitCode.GOTO_TRUE_NEXT_TICK);
        }
コード例 #17
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand <VMSetMotiveChangeOperand>();
            var avatar  = ((VMAvatar)context.Caller);

            if ((operand.Flags & VMSetMotiveChangeFlags.ClearAll) > 0)
            {
                avatar.ClearMotiveChanges();
            }
            else
            {
                var PerHourChange = VMMemory.GetVariable(context, (VMVariableScope)operand.DeltaOwner, (ushort)operand.DeltaData);
                var MaxValue      = VMMemory.GetVariable(context, (VMVariableScope)operand.MaxOwner, (ushort)operand.MaxData);
                avatar.SetMotiveChange(operand.Motive, PerHourChange, MaxValue);
            }

            return(VMPrimitiveExitCode.GOTO_TRUE);
        }
コード例 #18
0
        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);
        }
コード例 #19
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand <VMRandomNumberOperand>();

            var description = "random: less than " + VMMemory.DescribeVariable(context, operand.RangeScope, operand.RangeData);

            description += " written to " + VMMemory.DescribeVariable(context, operand.DestinationScope, operand.DestinationData);
            Trace(description);


            //TODO: Make this deterministic
            var rangeValue = VMMemory.GetVariable(context, operand.RangeScope, operand.RangeData);

            var rand   = new Random();
            var result = rand.Next(rangeValue);

            VMMemory.SetVariable(context, operand.DestinationScope, operand.DestinationData, (short)result);
            Trace("set " + operand.DestinationScope + " #" + operand.DestinationData + " to random " + result);
            return(VMPrimitiveExitCode.GOTO_TRUE);
        }
コード例 #20
0
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand <VMSleepOperand>();

            var ticks = VMMemory.GetVariable(context, TSO.Simantics.engine.scopes.VMVariableScope.Parameters, operand.StackVarToDec);

            //if (ticks > 0) Trace("sleeping...") ;

            ticks--;

            if (ticks < 0)
            {
                return(VMPrimitiveExitCode.GOTO_TRUE);
            }
            else
            {
                VMMemory.SetVariable(context, TSO.Simantics.engine.scopes.VMVariableScope.Parameters, operand.StackVarToDec, ticks);
                return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK);
            }
        }
コード例 #21
0
ファイル: VMSleep.cs プロジェクト: sector-c/Project-Dollhouse
        public override VMPrimitiveExitCode Execute(VMStackFrame context)
        {
            var operand = context.GetCurrentOperand <VMSleepOperand>();

            Trace("sleep: --(" + VMMemory.DescribeVariable(context, VMVariableScope.Local, operand.StackVarToDec) + ") != 0");

            var ticks = VMMemory.GetVariable(context, tso.simantics.engine.scopes.VMVariableScope.Local, operand.StackVarToDec);

            ticks--;

            if (ticks < 0)
            {
                return(VMPrimitiveExitCode.GOTO_TRUE);
            }
            else
            {
                VMMemory.SetVariable(context, tso.simantics.engine.scopes.VMVariableScope.Local, operand.StackVarToDec, ticks);
                return(VMPrimitiveExitCode.CONTINUE_NEXT_TICK);
            }
        }
コード例 #22
0
        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.Thread.Queue.Count > 0)
            {
                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);
            }
        }
コード例 #23
0
        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);
        }
コード例 #24
0
        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);
            }
        }
コード例 #25
0
        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);
        }
コード例 #26
0
        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);
        }
コード例 #27
0
        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);
            }
        }
コード例 #28
0
ファイル: VMRelationship.cs プロジェクト: RHY3756547/FreeSO
        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);
        }
コード例 #29
0
        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
        }
コード例 #30
0
ファイル: VMDialogHandler.cs プロジェクト: LinSianTing/FreeSO
        public static string ParseDialogString(VMStackFrame context, string input, STR source, int depth)
        {
            if (depth > 10)
            {
                return(input);
            }
            int           state   = 0;
            StringBuilder command = new StringBuilder();
            StringBuilder output  = new StringBuilder();

            if (input == null)
            {
                return("Missing String!!!");
            }

            for (int i = 0; i < input.Length; i++)
            {
                if (state == 0)
                {
                    if (input[i] == '$')
                    {
                        state = 1; //start parsing string
                        command.Clear();
                    }
                    else
                    {
                        output.Append(input[i]);
                    }
                }
                else
                {
                    command.Append(input[i]);
                    if (i == input.Length - 1 || !CommandSubstrValid(command.ToString()))
                    {
                        if (i != input.Length - 1 || char.IsDigit(input[i]))
                        {
                            command.Remove(command.Length - 1, 1);
                            i--;
                        }

                        var     cmdString = command.ToString();
                        short[] values    = new short[3];
                        if (cmdString.Length > 1 && cmdString[cmdString.Length - 1] == ':')
                        {
                            try
                            {
                                if (cmdString == "DynamicStringLocal:" || cmdString == "TimeLocal:" || cmdString == "JobOffer:" || cmdString == "Job:" || cmdString == "JobDesc:" || cmdString == "DateLocal:")
                                {
                                    values[1] = -1;
                                    values[2] = -1;
                                    for (int j = 0; j < 3; j++)
                                    {
                                        char   next = input[++i];
                                        string num  = "";
                                        while (char.IsDigit(next))
                                        {
                                            num += next;
                                            next = (++i == input.Length) ? '!': input[i];
                                        }
                                        if (num == "")
                                        {
                                            values[j] = -1;
                                            if (j == 1)
                                            {
                                                values[2] = -1;
                                            }
                                            break;
                                        }
                                        values[j] = short.Parse(num);
                                        if (i == input.Length || next != ':')
                                        {
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    char   next = input[++i];
                                    string num  = "";
                                    while (char.IsDigit(next))
                                    {
                                        num += next;
                                        next = (++i == input.Length) ? '!' : input[i];
                                    }
                                    values[0] = short.Parse(num);
                                }
                                i--;
                            }
                            catch (FormatException)
                            {
                            }
                        }
                        try
                        {
                            switch (cmdString)
                            {
                            case "Object":
                            case "DynamicObjectName":
                                //hack: if stack object doesn't exist and should contain owner's id,
                                //try output the callee's owner id instead for tip jar.
                                //special id for this is -1.
                                if (context.StackObjectID == -1 && !context.VM.TS1)
                                {
                                    //StackObjectOwnerID call sets the id to -1 if no owner found. (null is usually 0)
                                    output.Append(context.VM.TSOState.Names.GetNameForID(
                                                      context.VM,
                                                      (context.Callee.TSOState as VMTSOObjectState)?.OwnerID ?? 0
                                                      ));
                                }
                                else
                                {
                                    output.Append(context.StackObject.ToString());
                                }
                                break;

                            case "Me":
                                output.Append(context.Caller.ToString()); break;

                            case "TempXL:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.TempXL, values[0]).ToString()); break;

                            case "MoneyXL:":
                                output.Append("$" + VMMemory.GetBigVariable(context, Scopes.VMVariableScope.TempXL, values[0]).ToString("##,#0")); break;

                            case "Temp:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Temps, values[0]).ToString()); break;

                            case "$":
                                output.Append("$"); i--; break;

                            case "Attribute:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.MyObjectAttributes, values[0]).ToString()); break;

                            case "DynamicStringLocal:":
                                STR res = null;
                                if (values[2] != -1 && values[1] != -1)
                                {
                                    VMEntity obj = context.VM.GetObjectById((short)context.Locals[values[2]]);
                                    if (obj == null)
                                    {
                                        break;
                                    }
                                    ushort tableID = (ushort)context.Locals[values[1]];

                                    {    //local
                                        if (obj.SemiGlobal != null)
                                        {
                                            res = obj.SemiGlobal.Get <STR>(tableID);
                                        }
                                        if (res == null)
                                        {
                                            res = obj.Object.Resource.Get <STR>(tableID);
                                        }
                                        if (res == null)
                                        {
                                            res = context.Global.Resource.Get <STR>(tableID);
                                        }
                                    }
                                }
                                else if (values[1] != -1)
                                {
                                    //global table
                                    ushort tableID = (ushort)context.Locals[values[1]];
                                    res = context.Global.Resource.Get <STR>(tableID);
                                }
                                else
                                {
                                    res = source;
                                }

                                ushort index = (ushort)context.Locals[values[0]];
                                if (res != null)
                                {
                                    var str = res.GetString(index);
                                    output.Append(ParseDialogString(context, str, res, depth++));     // recursive command parsing!
                                    // this is needed for the crafting table.
                                    // though it is also, completely insane?
                                }
                                break;

                            case "Local:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]).ToString()); break;

                            case "FixedLocal:":
                                output.Append((VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]) / 100f).ToString("F2")); break;

                            case "TimeLocal:":
                                var hours  = VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]);
                                var mins   = (values[1] == -1)?0:VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[1]);
                                var suffix = (hours > 11) ? "pm" : "am";
                                if (hours > 12)
                                {
                                    hours -= 12;
                                }
                                output.Append(hours.ToString());
                                output.Append(":");
                                output.Append(mins.ToString().PadLeft(2, '0'));
                                output.Append(suffix);
                                break;

                            case "JobOffer:":
                                output.Append(Content.Content.Get().Jobs.JobOffer(
                                                  (short)VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]),
                                                  VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[1])));
                                break;

                            case "Job:":
                            case "JobDesc:":
                                var level  = VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[1]);
                                var jobStr = Content.Content.Get().Jobs.JobStrings(
                                    (short)VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Local, values[0]));
                                if (jobStr != null)
                                {
                                    output.Append(jobStr.GetString(level * 3 + ((cmdString == "JobDesc:")?3:4)));
                                }
                                break;

                            case "Param:":
                                output.Append(VMMemory.GetBigVariable(context, Scopes.VMVariableScope.Parameters, values[0]).ToString()); break;

                            case "NameLocal:":
                                output.Append(context.VM.GetObjectById(VMMemory.GetVariable(context, Scopes.VMVariableScope.Local, values[0])).ToString()); break;

                            case "Neighbor":
                                //neighbour in stack object id
                                if (!context.VM.TS1)
                                {
                                    break;
                                }
                                var guid = Content.Content.Get().Neighborhood.GetNeighborByID(context.StackObjectID)?.GUID ?? 0;
                                var gobj = Content.Content.Get().WorldObjects.Get(guid);
                                if (gobj == null)
                                {
                                    output.Append("Unknown");
                                }
                                else
                                {
                                    output.Append(gobj.Resource.Get <FSO.Files.Formats.IFF.Chunks.CTSS>(gobj.OBJ.CatalogStringsID)?.GetString(0) ?? "Unknown");
                                }
                                break;

                            case "ListObject":
                                output.Append(new string(context.StackObject.MyList.Select(x => (char)x).ToArray()));
                                break;

                            case "CatalogLocal:":
                                var catObj = context.VM.GetObjectById(VMMemory.GetVariable(context, Scopes.VMVariableScope.Local, values[0]));
                                var cat    = catObj.Object.Resource.Get <CTSS>(catObj.Object.OBJ.CatalogStringsID)?.GetString(1);
                                output.Append(cat ?? "");
                                break;

                            case "DateLocal:":
                                var date = new DateTime(context.Locals[values[2]], context.Locals[values[1]], context.Locals[values[0]]);
                                output.Append(date.ToLongDateString());
                                break;

                            case "\\n":
                                output.Append("\n");
                                break;

                            default:
                                output.Append(cmdString);
                                break;
                            }
                        } catch (Exception)
                        {
                            //something went wrong. just skip command
                        }
                        state = 0;
                    }
                }
            }
            output.Replace("\r\n", "\r\n\r\n");
            return(output.ToString());
        }