public VMArchitecture(int width, int height, Blueprint blueprint, VMContext context)
        {
            this.Context = context;
            this.Width = width;
            this.Height = height;

            var numTiles = width * height;
            this.WallsAt = new List<int>[Stories];
            this.Walls = new WallTile[Stories][];
            this.VisWalls = new WallTile[Stories][];

            this.Floors = new FloorTile[Stories][];
            this.VisFloors = new FloorTile[Stories][];

            this.ObjectSupport = new bool[Stories][]; //true if there's an object support in the specified position
            this.Supported = new bool[Stories-1][]; //no supported array for bottom floor. true if this tile is supported.
            blueprint.Supported = Supported;

            this.Rooms = new RoomMap[Stories];

            for (int i = 0; i < Stories; i++)
            {
                this.WallsAt[i] = new List<int>();
                this.Walls[i] = new WallTile[numTiles];
                this.VisWalls[i] = new WallTile[numTiles];

                this.Floors[i] = new FloorTile[numTiles];
                this.VisFloors[i] = new FloorTile[numTiles];
                this.ObjectSupport[i] = new bool[numTiles];

                if (i<Stories-1) this.Supported[i] = new bool[numTiles];

                this.Rooms[i] = new RoomMap();
            }

            this.RoomData = new List<BlueprintRoom>();
            this.WorldUI = blueprint;

            this.Commands = new List<VMArchitectureCommand>();
            this.Commands = new List<VMArchitectureCommand>();

            WallsDirty = true;
            FloorsDirty = true;
            RealMode = true;
            Redraw = true;
        }
예제 #2
0
        public virtual void SetIndivPosition(LotTilePos pos, Direction direction, VMContext context, VMPlacementResult info)
        {
            Direction = direction;

            //TODO: clean the f**k up out of OUT_OF_WORLD
            if (this is VMGameObject) context.Blueprint.ChangeObjectLocation((ObjectComponent)WorldUI, (pos==LotTilePos.OUT_OF_WORLD)?LotTilePos.FromBigTile(-1,-1,1):pos);
            Position = pos;
            if (info.Container != null) info.Container.PlaceInSlot(this, 0);
        }
예제 #3
0
 public virtual VMPlacementError SetPosition(LotTilePos pos, Direction direction, VMContext context)
 {
     return MultitileGroup.ChangePosition(pos, direction, context);
 }
예제 #4
0
        public virtual void PrePositionChange(VMContext context)
        {
            if (Container != null)
            {
                Container.ClearSlot(ContainerSlot);
                return;
            }
            if (Position == LotTilePos.OUT_OF_WORLD) return;

            var arch = context.Architecture;
            if (((VMEntityFlags2)ObjectData[(int)VMStackObjectVariable.FlagField2] & (VMEntityFlags2.ArchitectualWindow | VMEntityFlags2.ArchitectualDoor)) > 0)
            { //if wall or door, attempt to place style on wall
                var placeFlags = (WallPlacementFlags)ObjectData[(int)VMStackObjectVariable.WallPlacementFlags];
                var dir = DirectionToWallOff(Direction);
                if ((placeFlags & WallPlacementFlags.WallRequiredInFront) > 0) SetWallStyle((dir) % 4, arch, 0);
                if ((placeFlags & WallPlacementFlags.WallRequiredOnRight) > 0) SetWallStyle((dir+1) % 4, arch, 0);
                if ((placeFlags & WallPlacementFlags.WallRequiredBehind) > 0) SetWallStyle((dir+2) % 4, arch, 0);
                if ((placeFlags & WallPlacementFlags.WallRequiredOnLeft) > 0) SetWallStyle((dir+3) % 4, arch, 0);
            }
            SetWallUse(arch, false);
            if (GetValue(VMStackObjectVariable.Category) == 8) context.Architecture.SetObjectSupported(Position.TileX, Position.TileY, Position.Level, false);

            if (EntryPoints[15].ActionFunction != 0)
            { //portal
                context.RemoveRoomPortal(this);
            }
            context.UnregisterObjectPos(this);
        }
예제 #5
0
        public void PushUserInteraction(int interaction, VMEntity caller, VMContext context)
        {
            var Action = TreeTable.InteractionByIndex[(uint)interaction];
            ushort ActionID = Action.ActionFunction;

            var function = GetBHAVWithOwner(ActionID, context);

            VMEntity carriedObj = caller.GetSlot(0);

            var routine = context.VM.Assemble(function.bhav);
            caller.Thread.EnqueueAction(
                new TSO.Simantics.engine.VMQueuedAction
                {
                    Callee = this,
                    CodeOwner = function.owner,
                    Routine = routine,
                    Name = TreeTableStrings.GetString((int)Action.TTAIndex),
                    StackObject = this,
                    Args = ((Action.MaskFlags & InteractionMaskFlags.AvailableWhenCarrying) > 0)
                        ? new short[] { (carriedObj == null)?(short)0:carriedObj.ObjectID, 0, 0, 0 }:null,
                    InteractionNumber = interaction,
                    Priority = VMQueuePriority.UserDriven
                }
            );
        }
예제 #6
0
        public override void Init(VMContext context)
        {
            ((AvatarComponent)WorldUI).ObjectID = (ushort)ObjectID;

            base.Init(context);
            SetAvatarBodyStrings(Object.Resource.Get<STR>(Object.OBJ.BodyStringID), context);

            //init walking strings
            var GlobWalk = context.Globals.Resource.Get<STR>(150);
            for (int i = 0; i < GlobWalk.Length; i++)
            {
                WalkAnimations[i] = GlobWalk.GetString(i);
            }

            var SpecialWalk = Object.Resource.Get<STR>(150);
            if (SpecialWalk != null)
            {
                for (int i = 0; i < SpecialWalk.Length; i++)
                {
                    var str = SpecialWalk.GetString(i);
                    if (str != "") WalkAnimations[i] = str;
                }
            }

            SetMotiveData(VMMotive.Comfort, 100);
            SetPersonData(VMPersonDataVariable.NeatPersonality, 1000); //for testing wash hands after toilet
            SetPersonData(VMPersonDataVariable.OnlineJobID, 1); //for testing wash hands after toilet
            SetPersonData(VMPersonDataVariable.IsHousemate, 2);

            SetPersonData(VMPersonDataVariable.CreativitySkill, 15);
        }
예제 #7
0
        public virtual void PositionChange(VMContext context)
        {
            var blueprint = context.Blueprint;
            if (((VMEntityFlags2)ObjectData[(int)VMStackObjectVariable.FlagField2] & (VMEntityFlags2.ArchitectualWindow | VMEntityFlags2.ArchitectualDoor)) > 0)
            { //if wall or door, attempt to place style on wall

                if (Object.OBJ.WallStyle > 21 && Object.OBJ.WallStyle < 256)
                { //first thing's first, is the style between 22-255 inclusive? If it is, then the style is stored in the object. Need to load its sprites and change the id for the objd.
                    var id = Object.OBJ.WallStyleSpriteID;
                    var style = new WallStyle()
                    {
                        WallsUpFar = Object.Resource.Get<SPR>(id),
                        WallsUpMedium = Object.Resource.Get<SPR>((ushort)(id + 1)),
                        WallsUpNear = Object.Resource.Get<SPR>((ushort)(id + 2)),
                        WallsDownFar = Object.Resource.Get<SPR>((ushort)(id + 3)),
                        WallsDownMedium = Object.Resource.Get<SPR>((ushort)(id + 4)),
                        WallsDownNear = Object.Resource.Get<SPR>((ushort)(id + 5))
                    };
                    Object.OBJ.WallStyle = TSO.Content.Content.Get().WorldWalls.AddDynamicWallStyle(style);
                }

                var placeFlags = (WallPlacementFlags)ObjectData[(int)VMStackObjectVariable.WallPlacementFlags];
                var dir = DirectionToWallOff(Direction);
                if ((placeFlags & WallPlacementFlags.WallRequiredInFront) > 0) SetWallStyle((dir) % 4, blueprint, Object.OBJ.WallStyle);
                if ((placeFlags & WallPlacementFlags.WallRequiredOnRight) > 0) SetWallStyle((dir+1) % 4, blueprint, Object.OBJ.WallStyle);
                if ((placeFlags & WallPlacementFlags.WallRequiredBehind) > 0) SetWallStyle((dir+2) % 4, blueprint, Object.OBJ.WallStyle);
                if ((placeFlags & WallPlacementFlags.WallRequiredOnLeft) > 0) SetWallStyle((dir+3) % 4, blueprint, Object.OBJ.WallStyle);
            }

            if (EntryPoints[15].ActionFunction != 0)
            { //portal
                context.AddRoomPortal(this);
            }

            context.RegisterObjectPos(this);
        }
예제 #8
0
        public VMBHAVOwnerPair GetBHAVWithOwner(ushort ActionID, VMContext context)
        {
            BHAV bhav;
            GameIffResource CodeOwner;
            if (ActionID < 4096)
            { //global
                bhav = context.Globals.Resource.Get<BHAV>(ActionID);
                //CodeOwner = context.Globals.Resource;
            }
            else if (ActionID < 8192)
            { //local
                bhav = Object.Resource.Get<BHAV>(ActionID);

            }
            else
            { //semi-global
                bhav = SemiGlobal.Resource.Get<BHAV>(ActionID);
                //CodeOwner = SemiGlobal.Resource;
            }

            CodeOwner = Object.Resource;

            if (bhav == null) throw new Exception("Invalid BHAV call!");
            return new VMBHAVOwnerPair(bhav, CodeOwner);
        }
예제 #9
0
        public virtual void Init(VMContext context)
        {
            GenerateTreeByName(context);
            this.Thread = new VMThread(context, this, this.Object.OBJ.StackSize);

            ExecuteEntryPoint(0, context, true); //Init
            ExecuteEntryPoint(1, context, false); //Main
        }
예제 #10
0
        public void ExecuteEntryPoint(int entry, VMContext context, bool runImmediately)
        {
            if (entry == 11)
            {
                //user placement, hack to do auto floor removal/placement for stairs
                if (Object.OBJ.LevelOffset > 0 && Position != LotTilePos.OUT_OF_WORLD)
                {
                    var floor = context.Architecture.GetFloor(Position.TileX, Position.TileY, Position.Level);
                    var placeFlags = (VMPlacementFlags)ObjectData[(int)VMStackObjectVariable.PlacementFlags];
                    if ((placeFlags & VMPlacementFlags.InAir) > 0)
                        context.Architecture.SetFloor(Position.TileX, Position.TileY, Position.Level, new FloorTile(), true);
                    if ((placeFlags & VMPlacementFlags.OnFloor) > 0 && (floor.Pattern == 0))
                        context.Architecture.SetFloor(Position.TileX, Position.TileY, Position.Level, new FloorTile { Pattern = 1 } , true);
                }
            }
            if (EntryPoints[entry].ActionFunction > 255)
            {
                BHAV bhav;
                GameIffResource CodeOwner;
                ushort ActionID = EntryPoints[entry].ActionFunction;
                if (ActionID < 4096)
                { //global

                    bhav = context.Globals.Resource.Get<BHAV>(ActionID);
                }
                else if (ActionID < 8192)
                { //local
                    bhav = Object.Resource.Get<BHAV>(ActionID);
                }
                else
                { //semi-global
                    bhav = SemiGlobal.Resource.Get<BHAV>(ActionID);
                }

                CodeOwner = Object.Resource;

                var routine = context.VM.Assemble(bhav);
                if (bhav == null) return; //throw new Exception("Invalid BHAV call!");

                short[] Args = null;
                VMEntity StackOBJ = null;
                if (entry == 1)
                {
                    if (MainParam != 0)
                    {
                        Args = new short[4];
                        Args[0] = MainParam;
                        MainParam = 0;
                    }
                    if (MainStackOBJ != 0)
                    {
                        StackOBJ = context.VM.GetObjectById(MainStackOBJ);
                        MainStackOBJ = 0;
                    }
                }

                var action = new TSO.Simantics.engine.VMQueuedAction
                {
                    Callee = this,
                    CodeOwner = CodeOwner,
                    /** Main function **/
                    StackObject = StackOBJ,
                    Routine = routine,
                    Args = Args
                };

                if (runImmediately)
                    VMThread.EvaluateCheck(context, this, action);
                else
                    this.Thread.EnqueueAction(action);
            }
        }
예제 #11
0
        public void GenerateTreeByName(VMContext context)
        {
            TreeByName = new Dictionary<string, VMTreeByNameTableEntry>();

            var bhavs = Object.Resource.List<BHAV>();
            if (bhavs != null)
            {
                foreach (var bhav in bhavs)
                {
                    string name = bhav.ChunkLabel;
                    for (var i = 0; i < name.Length; i++)
                    {
                        if (name[i] == 0)
                        {
                            name = name.Substring(0, i);
                            break;
                        }
                    }
                    TreeByName.Add(name, new VMTreeByNameTableEntry(bhav, Object.Resource));
                }
            }
            //also add semiglobals

            if (SemiGlobal != null)
            {
                bhavs = SemiGlobal.Resource.List<BHAV>();
                if (bhavs != null)
                {
                    foreach (var bhav in bhavs)
                    {
                        string name = bhav.ChunkLabel;
                        for (var i = 0; i < name.Length; i++)
                        {
                            if (name[i] == 0)
                            {
                                name = name.Substring(0, i);
                                break;
                            }
                        }
                        if (!TreeByName.ContainsKey(name)) TreeByName.Add(name, new VMTreeByNameTableEntry(bhav, Object.Resource));
                    }
                }
            }
        }
예제 #12
0
 public void Delete(bool cleanupAll, VMContext context)
 {
     if (cleanupAll) MultitileGroup.Delete(context);
     else
     {
         PrePositionChange(context);
         context.RemoveObjectInstance(this);
         MultitileGroup.Objects.Remove(this); //we're no longer part of the multitile group
     }
 }
예제 #13
0
 public virtual void SetPosition(short x, short y, sbyte level, Direction direction, VMContext context)
 {
     if (MultitileGroup != null) MultitileGroup.ChangePosition(x, y, level, direction, context);
     else
     {
         Direction = direction;
         if (this is VMGameObject) context.Blueprint.ChangeObjectLocation((ObjectComponent)WorldUI, (short)x, (short)y, (sbyte)level);
         else Position = new Vector3(x+0.5f, y+0.5f, level * 3);
         PositionChange(context);
     }
 }
예제 #14
0
        public void PushUserInteraction(int interaction, VMEntity caller, VMContext context)
        {
            var Action = TreeTable.InteractionByIndex[(uint)interaction];
            ushort ActionID = Action.ActionFunction;

            var function = GetBHAVWithOwner(ActionID, context);

            var routine = context.VM.Assemble(function.bhav);
            caller.Thread.EnqueueAction(
                new TSO.Simantics.engine.VMQueuedAction
                {
                    Callee = this,
                    CodeOwner = function.owner,
                    Routine = routine,
                    Name = TreeTableStrings.GetString((int)Action.TTAIndex),
                    StackObject = this,
                    InteractionNumber = interaction,
                    Priority = VMQueuePriority.UserDriven
                }
            );
        }
예제 #15
0
 /// <summary>
 /// Constructs a new Virtual Machine instance.
 /// </summary>
 /// <param name="context">The VMContext instance to use.</param>
 public VM(VMContext context)
 {
     context.VM = this;
     ThreadLock = this;
     this.Context = context;
 }
예제 #16
0
        public virtual void PositionChange(VMContext context)
        {
            if (Container != null) return;
            if (Position == LotTilePos.OUT_OF_WORLD) return;

            var arch = context.Architecture;
            if (((VMEntityFlags2)ObjectData[(int)VMStackObjectVariable.FlagField2] & (VMEntityFlags2.ArchitectualWindow | VMEntityFlags2.ArchitectualDoor)) > 0)
            { //if wall or door, attempt to place style on wall

                if (Object.OBJ.WallStyle > 21 && Object.OBJ.WallStyle < 256)
                { //first thing's first, is the style between 22-255 inclusive? If it is, then the style is stored in the object. Need to load its sprites and change the id for the objd.
                    var id = Object.OBJ.WallStyleSpriteID;
                    var style = new WallStyle()
                    {
                        WallsUpFar = Object.Resource.Get<SPR>(id),
                        WallsUpMedium = Object.Resource.Get<SPR>((ushort)(id + 1)),
                        WallsUpNear = Object.Resource.Get<SPR>((ushort)(id + 2)),
                        WallsDownFar = Object.Resource.Get<SPR>((ushort)(id + 3)),
                        WallsDownMedium = Object.Resource.Get<SPR>((ushort)(id + 4)),
                        WallsDownNear = Object.Resource.Get<SPR>((ushort)(id + 5))
                    };
                    Object.OBJ.WallStyle = TSO.Content.Content.Get().WorldWalls.AddDynamicWallStyle(style);
                }

                var placeFlags = (WallPlacementFlags)ObjectData[(int)VMStackObjectVariable.WallPlacementFlags];
                var dir = DirectionToWallOff(Direction);
                if ((placeFlags & WallPlacementFlags.WallRequiredInFront) > 0) SetWallStyle((dir) % 4, arch, Object.OBJ.WallStyle);
                if ((placeFlags & WallPlacementFlags.WallRequiredOnRight) > 0) SetWallStyle((dir+1) % 4, arch, Object.OBJ.WallStyle);
                if ((placeFlags & WallPlacementFlags.WallRequiredBehind) > 0) SetWallStyle((dir+2) % 4, arch, Object.OBJ.WallStyle);
                if ((placeFlags & WallPlacementFlags.WallRequiredOnLeft) > 0) SetWallStyle((dir+3) % 4, arch, Object.OBJ.WallStyle);
            }
            SetWallUse(arch, true);
            if (GetValue(VMStackObjectVariable.Category) == 8) context.Architecture.SetObjectSupported(Position.TileX, Position.TileY, Position.Level, true);

            if (EntryPoints[15].ActionFunction != 0)
            { //portal
                context.AddRoomPortal(this);
            }

            context.RegisterObjectPos(this);

            ExecuteEntryPoint(9, context, true); //Placement
        }
예제 #17
0
        public override void Init(VMContext context)
        {
            base.Init(context);
            SetAvatarBodyStrings(Object.Resource.Get<STR>(Object.OBJ.BodyStringID), context);

            //init walking strings
            var GlobWalk = context.Globals.Resource.Get<STR>(150);
            for (int i = 0; i < GlobWalk.Length; i++)
            {
                WalkAnimations[i] = GlobWalk.GetString(i);
            }

            var SpecialWalk = Object.Resource.Get<STR>(150);
            if (SpecialWalk != null)
            {
                for (int i = 0; i < SpecialWalk.Length; i++)
                {
                    var str = SpecialWalk.GetString(i);
                    if (str != "") WalkAnimations[i] = str;
                }
            }

            SetMotiveData(VMMotive.Comfort, 100);
            SetPersonData(VMPersonDataVariable.NeatPersonality, 1000); //for testing wash hands after toilet
        }
예제 #18
0
        public VMPlacementResult PositionValid(LotTilePos pos, Direction direction, VMContext context)
        {
            if (pos == LotTilePos.OUT_OF_WORLD) return new VMPlacementResult();
            else if (context.IsOutOfBounds(pos)) return new VMPlacementResult { Status = VMPlacementError.LocationOutOfBounds };

            //TODO: speedup with exit early checks
            //TODO: corner checks (wtf uses this)

            var arch = context.Architecture;
            var wall = arch.GetWall(pos.TileX, pos.TileY, pos.Level); //todo: preprocess to check which walls are real solid walls.

            VMPlacementError wallValid = WallChangeValid(wall, direction, true);
            if (wallValid != VMPlacementError.Success) return new VMPlacementResult { Status = wallValid };

            var floor = arch.GetFloor(pos.TileX, pos.TileY, pos.Level); //todo: preprocess to check which walls are real solid walls.
            VMPlacementError floorValid = FloorChangeValid(floor, pos.Level);
            if (floorValid != VMPlacementError.Success) return new VMPlacementResult { Status = floorValid };

            //we've passed the wall test, now check if we intersect any objects.
            var valid = context.GetObjPlace(this, pos);
            return valid;
        }
예제 #19
0
        public void SetAvatarBodyStrings(STR data, VMContext context)
        {
            if (data == null) return;

            try
            {
                var body = data.GetString(1);
                var randBody = data.GetString(9);

                if (randBody != "")
                {
                    var bodySpl = randBody.Split(';');
                    BodyOutfit = Convert.ToUInt64(bodySpl[context.NextRandom((ulong)bodySpl.Length)], 16);
                }
                else if (body != "")
                {
                    BodyOutfit = Convert.ToUInt64(body, 16);
                }

                var head = data.GetString(2);
                var randHead = data.GetString(10);

                if (randHead != "")
                {
                    var headSpl = randHead.Split(';');
                    HeadOutfit = Convert.ToUInt64(headSpl[context.NextRandom((ulong)headSpl.Length)], 16);
                }
                else if (head != "")
                {
                    HeadOutfit = Convert.ToUInt64(head, 16);
                }
            }
            catch
            {
                //head or body invalid, resort to default.
            }

            var gender = data.GetString(12);
            var genVar = (int)VMPersonDataVariable.Gender;

            if (gender.Equals("male", StringComparison.InvariantCultureIgnoreCase)) PersonData[genVar] = 0;
            else if (gender.Equals("female", StringComparison.InvariantCultureIgnoreCase)) PersonData[genVar] = 1;
            else if (gender.Equals("dogmale", StringComparison.InvariantCultureIgnoreCase)) PersonData[genVar] = 8;
            else if (gender.Equals("dogfemale", StringComparison.InvariantCultureIgnoreCase)) PersonData[genVar] = 9;
            else if (gender.Equals("catmale", StringComparison.InvariantCultureIgnoreCase)) PersonData[genVar] = 16;
            else if (gender.Equals("catfemale", StringComparison.InvariantCultureIgnoreCase)) PersonData[genVar] = 17;

            var names = data.GetString(11);
            if (names != "")
            {
                var nameSpl = names.Split(';');
                Name = nameSpl[context.NextRandom((ulong)nameSpl.Length)];
            }

            PersonData[(int)VMPersonDataVariable.PersonsAge] = Convert.ToInt16(data.GetString(13));

            var skinTone = data.GetString(14);
            if (skinTone.Equals("lgt", StringComparison.InvariantCultureIgnoreCase)) SkinTone = AppearanceType.Light;
            else if (skinTone.Equals("med", StringComparison.InvariantCultureIgnoreCase)) SkinTone = AppearanceType.Medium;
            else if (skinTone.Equals("drk", StringComparison.InvariantCultureIgnoreCase)) SkinTone = AppearanceType.Dark;
        }
예제 #20
0
        public void ExecuteEntryPoint(int entry, VMContext context, bool runImmediately)
        {
            if (EntryPoints[entry].ActionFunction > 255)
            {
                BHAV bhav;
                GameIffResource CodeOwner;
                ushort ActionID = EntryPoints[entry].ActionFunction;
                if (ActionID < 4096)
                { //global

                    bhav = context.Globals.Resource.Get<BHAV>(ActionID);
                    CodeOwner = context.Globals.Resource;
                }
                else if (ActionID < 8192)
                { //local
                    bhav = Object.Resource.Get<BHAV>(ActionID);
                    CodeOwner = Object.Resource;
                }
                else
                { //semi-global
                    bhav = SemiGlobal.Resource.Get<BHAV>(ActionID);
                    CodeOwner = SemiGlobal.Resource;
                }

                var routine = context.VM.Assemble(bhav);
                if (bhav == null) return; //throw new Exception("Invalid BHAV call!");

                short[] Args = null;
                VMEntity StackOBJ = null;
                if (entry == 1)
                {
                    if (MainParam != 0)
                    {
                        Args = new short[4];
                        Args[0] = MainParam;
                        MainParam = 0;
                    }
                    if (MainStackOBJ != 0)
                    {
                        StackOBJ = context.VM.GetObjectById(MainStackOBJ);
                        MainStackOBJ = 0;
                    }
                }

                var action = new TSO.Simantics.engine.VMQueuedAction
                {
                    Callee = this,
                    CodeOwner = CodeOwner,
                    /** Main function **/
                    StackObject = StackOBJ,
                    Routine = routine,
                    Args = Args
                };

                if (runImmediately)
                    VMThread.EvaluateCheck(context, this, action);
                else
                    this.Thread.EnqueueAction(action);
            }
        }