Ejemplo n.º 1
0
        public void AddObject(IffFile iff, OBJD obj)
        {
            lock (Entries)
            {
                GameObjectSource source;
                switch (iff.RuntimeInfo.State)
                {
                case IffRuntimeState.PIFFClone:
                    source = GameObjectSource.PIFFClone;
                    break;

                case IffRuntimeState.Standalone:
                    source = GameObjectSource.Standalone;
                    break;

                default:
                    source = GameObjectSource.Far;
                    break;
                }

                Entries.Add(obj.GUID, new GameObjectReference(this)
                {
                    ID       = obj.GUID,
                    FileName = iff.RuntimeInfo.Path,
                    Source   = source,
                    Name     = obj.ChunkLabel,
                    Group    = (short)obj.MasterID,
                    SubIndex = obj.SubIndex
                });
            }
        }
Ejemplo n.º 2
0
        private void PrintOBJD(OBJD item)
        {
            string[] fieldLabels = null;
            switch (item.Version)
            {
            case 142:
                fieldLabels = OBJD.VERSION_142_Fields;
                break;
            }

            Printer.H1(item.ChunkID + " (" + item.ChunkLabel + ") GUID = " + item.GUID.ToString("x") + " Version = " + item.Version);
            var table = Printer.CreateTable(new string[] { "Field", "Value" });

            for (var i = 0; i < item.RawData.Length; i++)
            {
                if (fieldLabels != null && i < fieldLabels.Length)
                {
                    table.AddRow(new object[] { i.ToString() + " (" + fieldLabels[i] + ")", item.RawData[i].ToString() });
                }
                else
                {
                    table.AddRow(new object[] { i.ToString(), item.RawData[i].ToString() });
                }
            }
            Printer.Add(table);
        }
Ejemplo n.º 3
0
        public void DisableIfTSOCategoryWrong(VMContext context)
        {
            //if (context.VM.TS1) return;
            OBJD obj = Object.OBJ;

            if (MasterDefinition != null)
            {
                obj = MasterDefinition;
            }
            var category = context.VM.TSOState.PropertyCategory;
            var flag     = (1 << category);

            if (category == 7)
            {
                flag |= 2;                //money objects are allowed on welcome lots too. (fso change, disabling this is todo)
            }
            if (category != 255 && obj.LotCategories > 0 && (obj.LotCategories & flag) == 0)
            {
                Disabled |= VMGameObjectDisableFlags.LotCategoryWrong;
            }
            else
            {
                Disabled &= ~VMGameObjectDisableFlags.LotCategoryWrong;
            }
        }
Ejemplo n.º 4
0
 /// <summary>
 /// Tests the FAR1Archive class.
 /// </summary>
 private static void FAR1Test()
 {
     Console.WriteLine("Attempting to parse IFF...");
     //Testcases: djbooth.iff, trashcanvacation.iff, stair2.iff, stereos.iff, maid.iff, mask.iff, medicinecabinet.iff
     Iff  IffObject = FileManager.GetIFF("medicinecabinet.iff");
     OBJD Master    = IffObject.Master;
 }
Ejemplo n.º 5
0
        public DGRP3DMesh Get(DGRP dgrp, OBJD obj)
        {
            DGRP3DMesh result  = null;
            var        repldir = Path.Combine(FSOEnvironment.ContentDir, "MeshReplace/");
            var        dir     = Path.Combine(FSOEnvironment.UserDir, "MeshCache/");

            if (!Cache.TryGetValue(dgrp, out result))
            {
                //does it exist in replacements
                var name = obj.ChunkParent.Filename.Replace('.', '_') + "_" + dgrp.ChunkID + ".fsom";
                try
                {
                    using (var file = File.OpenRead(Path.Combine(repldir, name)))
                    {
                        result = new DGRP3DMesh(dgrp, file, GD);
                    }
                }
                catch (Exception)
                {
                    result = null;
                }

                if (result == null)
                {
                    //does it exist in iff
                    try
                    {
                        result = dgrp.ChunkParent.Get <FSOM>(dgrp.ChunkID)?.Get(dgrp, GD);
                    }
                    catch (Exception)
                    {
                        result = null;
                    }
                }

                if (result == null && !IgnoreRCCache.Contains(dgrp))
                {
                    //does it exist in rc cache
                    try
                    {
                        using (var file = File.OpenRead(Path.Combine(dir, name)))
                        {
                            result = new DGRP3DMesh(dgrp, file, GD);
                        }
                    }
                    catch (Exception)
                    {
                        result = null;
                    }
                }

                //create it anew
                if (result == null)
                {
                    result = new DGRP3DMesh(dgrp, obj, GD, dir);
                }
                Cache[dgrp] = result;
            }
            return(result);
        }
Ejemplo n.º 6
0
        //hilariously large switch case. there's got to be a better way
        public static short GetEntityDefinitionVar(OBJD objd, VMOBJDVariable var, VMStackFrame context)
        {
            switch (var)
            {
            case VMOBJDVariable.Version1:
                return((short)(objd.Version % 0xFFFF));

            case VMOBJDVariable.Version2:
                return((short)(objd.Version >> 16));

            default:
                return((short)objd.RawData[((int)var) - 2]);
            }
        }
Ejemplo n.º 7
0
 public void SetSelectors(OBJD objd, IffChunk active, OBJDSelector[] selectors)
 {
     Active               = active;
     Definition           = objd;
     SelectButton.Dock    = DockStyle.Fill;
     SelectCombo.Dock     = DockStyle.Fill;
     SelectButton.Visible = selectors.Length == 1;
     SelectCombo.Visible  = selectors.Length > 1;
     Selectors            = selectors;
     if (selectors.Length > 1)
     {
         SelectCombo.Items.Clear();
         SelectCombo.Items.Add("-- Not Selected --");
         int i = 1;
         OwnChange = true;
         SelectCombo.SelectedIndex = 0;
         foreach (var sel in selectors)
         {
             SelectCombo.Items.Add(sel);
             if (sel.FieldName != null && objd.GetPropertyByName <ushort>(sel.FieldName) == active.ChunkID)
             {
                 SelectCombo.SelectedIndex = i;
             }
             i++;
         }
         OwnChange = false;
     }
     else if (selectors.Length > 0)
     {
         var sel = selectors[0];
         if (sel.FieldName != null && objd.GetPropertyByName <ushort>(sel.FieldName) == active.ChunkID)
         {
             SelectButton.Text    = "Selected as " + sel.Name;
             SelectButton.Enabled = false;
         }
         else
         {
             SelectButton.Text    = "Select as " + sel.Name;
             SelectButton.Enabled = true;
         }
     }
     else
     {
         Enabled = false;
         Visible = false;
     }
 }
Ejemplo n.º 8
0
        public void DisableIfTSOCategoryWrong(VMContext context)
        {
            OBJD obj = Object.OBJ;

            if (MasterDefinition != null)
            {
                obj = MasterDefinition;
            }
            var category = context.VM.TSOState.PropertyCategory;

            if (category != 255 && obj.LotCategories > 0 && (obj.LotCategories & (1 << category)) == 0)
            {
                Disabled |= VMGameObjectDisableFlags.LotCategoryWrong;
            }
            else
            {
                Disabled &= ~VMGameObjectDisableFlags.LotCategoryWrong;
            }
        }
        /// <summary>
        /// Creates a new SimulationObject instance.
        /// </summary>
        /// <param name="Obj">The OBJD for this object. Assumed to be the master OBJD if the object is multi-tile.</param>
        /// <param name="Container">The IFF archive where the OBJD resides.</param>
        public SimulationObject(OBJD Obj, Iff Container, string GUID)
        {
            m_GUID = GUID;

            if (!Obj.IsMultiTile)
            {
                m_MasterOBJD      = Obj;
                m_ObjectContainer = Container;
            }
            else //Load the OBJDs for the other tiles...
            {
                foreach (OBJD O in m_ObjectContainer.OBJDs)
                {
                    if (O.MasterID == Obj.MasterID)
                    {
                        m_Slaves.Add(O);
                    }
                }
            }
        }
Ejemplo n.º 10
0
        public OBJfFunctionEntry[] GenerateFunctionTable(OBJD obj)
        {
            OBJfFunctionEntry[] result = new OBJfFunctionEntry[33];

            result[0].ActionFunction  = obj.BHAV_Init;
            result[1].ActionFunction  = obj.BHAV_MainID;
            result[2].ActionFunction  = obj.BHAV_Load;
            result[3].ActionFunction  = obj.BHAV_Cleanup;
            result[4].ActionFunction  = obj.BHAV_QueueSkipped;
            result[5].ActionFunction  = obj.BHAV_AllowIntersectionID;
            result[6].ActionFunction  = obj.BHAV_WallAdjacencyChanged;
            result[7].ActionFunction  = obj.BHAV_RoomChange;
            result[8].ActionFunction  = obj.BHAV_DynamicMultiTileUpdate;
            result[9].ActionFunction  = obj.BHAV_Place;
            result[10].ActionFunction = obj.BHAV_Pickup;
            result[11].ActionFunction = obj.BHAV_UserPlace;
            result[12].ActionFunction = obj.BHAV_UserPickup;
            result[13].ActionFunction = obj.BHAV_LevelInfo;
            result[14].ActionFunction = obj.BHAV_ServingSurface;
            result[15].ActionFunction = obj.BHAV_Portal; //portal
            result[16].ActionFunction = obj.BHAV_GardeningID;
            result[17].ActionFunction = obj.BHAV_WashHandsID;
            result[18].ActionFunction = obj.BHAV_PrepareFoodID;
            result[19].ActionFunction = obj.BHAV_CookFoodID;
            result[20].ActionFunction = obj.BHAV_PlaceSurfaceID;
            result[21].ActionFunction = obj.BHAV_DisposeID;
            result[22].ActionFunction = obj.BHAV_EatID;
            result[23].ActionFunction = obj.BHAV_PickupFromSlotID; //pickup from slot
            result[24].ActionFunction = obj.BHAV_WashDishID;
            result[25].ActionFunction = obj.BHAV_EatSurfaceID;
            result[26].ActionFunction = obj.BHAV_SitID;
            result[27].ActionFunction = obj.BHAV_StandID;
            result[28].ActionFunction = obj.BHAV_Clean;
            result[29].ActionFunction = obj.BHAV_Repair; //repair
            result[30].ActionFunction = 0;               //client house join
            result[31].ActionFunction = 0;               //prepare for sale
            result[32].ActionFunction = 0;               //house unload

            return(result);
        }
Ejemplo n.º 11
0
        public virtual void Load(VMEntityMarshal input)
        {
            ObjectID   = input.ObjectID;
            PersistID  = input.PersistID;
            ObjectData = input.ObjectData;
            MyList     = new LinkedList <short>(input.MyList);

            MainParam    = input.MainParam; //parameters passed to main on creation.
            MainStackOBJ = input.MainStackOBJ;

            if (input.MasterGUID != 0)
            {
                var masterDef = FSO.Content.Content.Get().WorldObjects.Get(input.MasterGUID);
                MasterDefinition = masterDef.OBJ;
                UseTreeTableOf(masterDef);
            }

            else
            {
                MasterDefinition = null;
            }

            ContainerSlot = input.ContainerSlot;

            Attributes = new List <short>(input.Attributes);
            MeToObject = new Dictionary <ushort,List <short> >();
            foreach (var obj in input.MeToObject)
            {
                MeToObject[obj.Target] = new List <short>(obj.Values);
            }

            DynamicSpriteFlags = input.DynamicSpriteFlags;
            Position           = input.Position;

            if (UseWorld)
            {
                WorldUI.Visible = GetValue(VMStackObjectVariable.Hidden) == 0;
            }
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Adds an object that will be run by this virtual machine.
        /// </summary>
        /// <param name="Obj">The object to run.</param>
        /// <param name="ObjectContainer">The object's container.</param>
        public void AddObject(OBJD Obj, Iff ObjectContainer, string GUID)
        {
            VirtualThread VThread = new VirtualThread(new SimulationObject(Obj, ObjectContainer, GUID));

            m_Threads.Add(VThread);
        }
Ejemplo n.º 13
0
 public DGRPRenderer(DGRP group, OBJD source)
 {
     this.DrawGroup = group;
     this.Source    = source;
 }
Ejemplo n.º 14
0
        public PackageType getType(Database db, bool loopAll)
        {
            // Do some quick sanity checks
            switch (db.dbpf.packageType)
            {
            case PackageTypes.genericPackage:
                break;

            case PackageTypes.corruptBadDownload:
            case PackageTypes.corruptChaavik:
            case PackageTypes.corruptIndex:
            case PackageTypes.corruptPeggy:
            case PackageTypes.corruptNotADBPF:
            case PackageTypes.corruptTXTC:
                this.isCorrupt      = true;
                this.pType.SubType  = "";
                this.pType.MainType = db.dbpf.packageType;
                return(this.pType);

            case PackageTypes.sims3Store:
            case PackageTypes.sims2Package:
            case PackageTypes.pngThumbnail:
                this.pType.SubType  = "";
                this.pType.MainType = db.dbpf.packageType;
                return(this.pType);
            }

            rc.Clear();
            this.pType = new PackageType();

            //print(db.dbpf.Entries.Count + " entries found");
            for (int i = 0; i < db.dbpf.Entries.Count; i++)
            {
                DatabasePackedFile.Entry entry = db.dbpf.Entries[i];

                if ((entry.Key.typeId == (uint)ResourceTypes.NULL) && (entry.Key.groupId == (uint)ResourceTypes.NULL) && (entry.Key.instanceId == (uint)ResourceTypes.NULL))
                {
                    // Check the first 4 bytes of the stream
                    Stream checkDbpf = db.GetResourceStream(entry.Key);
                    string magic     = MadScience.StreamHelpers.ReadStringASCII(checkDbpf, 4);
                    if (magic == "DBPF" || magic == "DBBF")                     // DBPF & DBBF
                    {
                        this.isCorrupt      = true;
                        this.pType.MainType = PackageTypes.corruptRecursive;
                        this.pType.SubType  = "This package contains another package inside it.";
                        if (!loopAll)
                        {
                            return(this.pType);
                        }
                    }
                    checkDbpf.Close();
                }

                if (entry.Key.typeId == (uint)ResourceTypes.TXTC)
                {
                    int isValid = checkValidEntry(entry, db);
                    if (isValid > 0)
                    {
                        if (isValid == 2)
                        {
                            this.isCorrupt      = true;
                            this.pType.MainType = PackageTypes.corruptTXTC;
                            if (!loopAll)
                            {
                                return(this.pType);
                            }
                        }
                    }
                }

                if (entry.Key.typeId == (uint)ResourceTypes.PTRN)
                {
                    if (this.pType.MainType == PackageTypes.genericPackage)
                    {
                        this.pType.MainType = PackageTypes.patternGeneric;
                    }
                    if (!loopAll)
                    {
                        return(this.pType);
                    }
                }

                if (Enum.IsDefined(typeof(ResourceTypes), entry.Key.typeId))
                {
                    if (rc.ContainsKey(Enum.GetName(typeof(ResourceTypes), entry.Key.typeId)))
                    {
                        rc[Enum.GetName(typeof(ResourceTypes), entry.Key.typeId)]++;
                    }
                    else
                    {
                        rc.Add(Enum.GetName(typeof(ResourceTypes), entry.Key.typeId), 1);
                    }
                }
            }

            //print("Done");

            if (rc.ContainsKey("WLOT") && rc.ContainsKey("UNKW1"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage)
                {
                    this.pType.MainType = PackageTypes.neighbourhood;
                }
                this.isCorrupt = true;
                return(this.pType);
            }

            if (rc.ContainsKey("WLTL") && rc.ContainsKey("ARY2"))
            {
                this.pType.MainType = PackageTypes.lot;
                return(this.pType);
            }

            if (rc.ContainsKey("SIMO") && rc.ContainsKey("SIME") && rc.ContainsKey("SNAP") && rc.ContainsKey("SNAPL"))
            {
                this.pType.MainType = PackageTypes.sim;
                return(this.pType);
            }

            //this.pType.MainType = PackageTypes.genericPackage;
            // Check Objects
            if (rc.ContainsKey("OBJD"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage)
                {
                    this.pType.MainType = PackageTypes.objectGeneric;
                }
                Stream objStream = MadScience.Package.Search.getStream(db, 0x319E4F1D, -1, -1);
                if (StreamHelpers.isValidStream(objStream))
                {
                    OBJD objd = new OBJD(objStream);
                    this.pType.SubType = objd.ToString();
                    objd = null;
                }
                return(this.pType);
            }
            if (rc.ContainsKey("S3SA"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage)
                {
                    this.pType.MainType = PackageTypes.coremod;
                }
            }

            if (rc.ContainsKey("CASP"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage)
                {
                    this.pType.MainType = PackageTypes.casPartGeneric;
                }

                Stream casStream = MadScience.Package.Search.getStream(db, 0x034AEECB, -1, -1);
                if (StreamHelpers.isValidStream(casStream))
                {
                    casPartFile cFile = new casPartFile();
                    cFile.Load(casStream);

                    this.pType.SubType = cFile.clothingType();

                    switch (cFile.casType())
                    {
                    case "Hair":
                        this.pType.MainType = PackageTypes.casPartHair;
                        break;

                    case "Scalp":
                        break;

                    case "Face Overlay":
                        switch (cFile.clothingType())
                        {
                        case "Lipstick":
                        case "Eyeshadow":
                        case "Eyeliner":
                        case "Blush":
                        case "Makeup":
                        case "Mascara":
                            this.pType.MainType = PackageTypes.casPartMakeup;
                            break;

                        default:
                            this.pType.MainType = PackageTypes.casPartFaceOverlay;
                            break;
                        }
                        break;

                    case "Body":
                        this.pType.MainType = PackageTypes.casPartClothing;
                        this.pType.SubType  = cFile.clothingCategory();

                        // Check the TYPE of clothing we have
                        switch (cFile.clothingType())
                        {
                        case "Body":
                        case "Top":
                        case "Bottom":
                        case "Shoes":
                            // Check the age too
                            // If we have Toddler OR Child OR Teen, plus other ages
                            bool ageCorrupt = false;
                            //if ((cFile.cFile.ageGender.baby || cFile.cFile.ageGender.toddler || cFile.cFile.ageGender.child || cFile.cFile.ageGender.teen) && (cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                            //{
                            //	ageCorrupt = true;
                            //}
                            // If we have Baby AND any other age...
                            if (cFile.cFile.ageGender.baby && (cFile.cFile.ageGender.toddler || cFile.cFile.ageGender.child || cFile.cFile.ageGender.teen || cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                            {
                                ageCorrupt = true;
                            }
                            // If we have Toddler AND any other age...
                            if (cFile.cFile.ageGender.toddler && (cFile.cFile.ageGender.child || cFile.cFile.ageGender.teen || cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                            {
                                ageCorrupt = true;
                            }
                            // If we have Child AND any other age
                            if (cFile.cFile.ageGender.child && (cFile.cFile.ageGender.teen || cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                            {
                                ageCorrupt = true;
                            }
                            // If we have Teen AND any other age
                            if (cFile.cFile.ageGender.teen && (cFile.cFile.ageGender.youngAdult || cFile.cFile.ageGender.adult || cFile.cFile.ageGender.elder))
                            {
                                ageCorrupt = true;
                            }

                            if (ageCorrupt)
                            {
                                this.isCorrupt      = true;
                                this.pType.MainType = PackageTypes.corruptBadAges;
                                if (!loopAll)
                                {
                                    return(this.pType);
                                }
                            }
                            break;

                        default:
                            break;
                        }

                        break;

                    case "Accessory":
                        this.pType.MainType = PackageTypes.casPartAccessory;
                        break;
                    }
                    this.pType.SubType += " (" + cFile.ageGender() + ")";
                }
                return(this.pType);
            }

            if (rc.ContainsKey("FBLN") && rc.ContainsKey("FACE") && rc.ContainsKey("BOND"))
            {
                if (this.pType.MainType == PackageTypes.genericPackage)
                {
                    this.pType.MainType = PackageTypes.casSlider;
                }
                return(this.pType);
            }

            if (rc.ContainsKey("_IMG") && rc.Count == 1)
            {
                if (this.pType.MainType == PackageTypes.genericPackage)
                {
                    this.pType.MainType = PackageTypes.textureReplacement;
                }
            }

            if (rc.Count == 1 && (rc.ContainsKey("_XML") || rc.ContainsKey("_XML2")))
            {
                if (this.pType.MainType == PackageTypes.genericPackage)
                {
                    this.pType.MainType = PackageTypes.xmltuningmod;
                }
            }

            return(this.pType);
        }
Ejemplo n.º 15
0
 public DGRPRendererRC(DGRP group, OBJD source) : base(group)
 {
     Source = source;
 }
Ejemplo n.º 16
0
        private void OKButton_Click(object sender, EventArgs e)
        {
            var  name  = ChunkLabelEntry.Text;
            var  guidT = GUIDEntry.Text;
            uint guid;
            var  objProvider = Content.Content.Get().WorldObjects;

            if (name == "")
            {
                MessageBox.Show("Name cannot be empty!", "Invalid Object Name");
            }
            else if (guidT == "")
            {
                MessageBox.Show("GUID cannot be empty!", "Invalid GUID");
            }
            else if (!uint.TryParse(guidT, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out guid))
            {
                MessageBox.Show("GUID is invalid! Make sure it is a hex string of size 8. (eg. 6789ABCD)", "Invalid GUID");
            }
            else
            {
                lock (objProvider.Entries)
                {
                    if (objProvider.Entries.ContainsKey(guid))
                    {
                        MessageBox.Show("This GUID is already being used!", "GUID is Taken!");
                        return;
                    }

                    //OK, it's valid. Now to add it to the objects system...
                    //This is a little tricky because we want to add an object that does not exist yet.
                    //There's a special function just for this! But first, we need an OBJD...

                    var obj = new OBJD()
                    {
                        GUID             = guid,
                        ObjectType       = OBJDType.Normal,
                        ChunkLabel       = name,
                        ChunkID          = 1,
                        ChunkProcessed   = true,
                        ChunkType        = "OBJD",
                        ChunkParent      = TargetIff,
                        AnimationTableID = 128,
                        AddedByPatch     = true
                    };

                    Content.Content.Get().Changes.BlockingResMod(new ResAction(() =>
                    {
                        //find a free space to place the object
                        ushort id = 16807; //todo: why???
                        var list  = TargetIff.List <OBJD>();
                        if (list != null)
                        {
                            foreach (var chk in list.OrderBy(x => x.ChunkID))
                            {
                                if (chk.ChunkID == id)
                                {
                                    id++;
                                }
                            }
                        }
                        obj.ChunkID = id;
                        //add it to the iff file
                        TargetIff.AddChunk(obj);
                    }, obj));

                    if (IsNew)
                    {
                        //add a default animation table, for quality of life reasons

                        var anim = new STR()
                        {
                            ChunkLabel     = name,
                            ChunkID        = 128,
                            ChunkProcessed = true,
                            ChunkType      = "STR#",
                            ChunkParent    = TargetIff,
                        };

                        anim.InsertString(0, new STRItem {
                            Value = "", Comment = ""
                        });
                        TargetIff.AddChunk(anim);

                        var filename = TargetIff.RuntimeInfo.Path;
                        Directory.CreateDirectory(Path.GetDirectoryName(filename));
                        using (var stream = new FileStream(filename, FileMode.Create))
                            TargetIff.Write(stream);
                    }

                    //add it to the provider
                    objProvider.AddObject(TargetIff, obj);

                    DialogResult = DialogResult.OK;
                    ResultGUID   = guid;
                    Close();
                }
            }
        }
Ejemplo n.º 17
0
        //hilariously large switch case. there's got to be a better way
        public static short GetEntityDefinitionVar(OBJD objd, VMOBJDVariable var, VMStackFrame context)
        {
            switch (var)
            {
            case VMOBJDVariable.Version1:
                return((short)(objd.Version % 0xFFFF));

            case VMOBJDVariable.Version2:
                return((short)(objd.Version >> 16));

            case VMOBJDVariable.InitialStackSize:
                return((short)objd.StackSize);

            case VMOBJDVariable.BaseGraphic:
                return((short)objd.BaseGraphicID);

            case VMOBJDVariable.NumGraphics:
                return((short)objd.NumGraphics);

            case VMOBJDVariable.MainTreeID:
                return((short)objd.BHAV_MainID);    // should this use OBJf functions?

            case VMOBJDVariable.GardeningTreeID:
                return((short)objd.BHAV_GardeningID);

            case VMOBJDVariable.TreeTableID:
                return((short)objd.TreeTableID);

            case VMOBJDVariable.InteractionGroup:
                return((short)objd.InteractionGroupID);

            case VMOBJDVariable.Type:
                return((short)objd.ObjectType);

            case VMOBJDVariable.MasterID:
                return((short)objd.MasterID);

            case VMOBJDVariable.SubIndex:
                return((short)objd.SubIndex);

            case VMOBJDVariable.WashHandsTreeID:
                return((short)objd.BHAV_WashHandsID);

            case VMOBJDVariable.AnimTableID:
                return((short)objd.AnimationTableID);

            case VMOBJDVariable.GUID1:
                return((short)(objd.GUID % 0xFFFF));

            case VMOBJDVariable.GUID2:
                return((short)(objd.GUID >> 16));

            case VMOBJDVariable.Disabled:
                return((short)objd.Disabled);

            case VMOBJDVariable.PortalTreeID:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.Price:
                return((short)objd.Price);

            case VMOBJDVariable.BodyStringsID:
                return((short)objd.BodyStringID);

            case VMOBJDVariable.SlotsID:
                return((short)objd.SlotID);

            case VMOBJDVariable.AllowIntersectionTreeID:
                return((short)objd.BHAV_AllowIntersectionID);

            case VMOBJDVariable.UsesFnTable:
                return((short)objd.UsesFnTable);

            case VMOBJDVariable.Bitfield1:
                return((short)objd.BitField1);

            case VMOBJDVariable.PrepareFoodTreeID:
                return((short)objd.BHAV_PrepareFoodID);

            case VMOBJDVariable.CookFoodTreeID:
                return((short)objd.BHAV_CookFoodID);

            case VMOBJDVariable.PlaceOnSurfaceTreeID:
                return((short)objd.BHAV_PlaceSurfaceID);

            case VMOBJDVariable.DisposeTreeID:
                return((short)objd.BHAV_DisposeID);

            case VMOBJDVariable.EatFoodTreeID:
                return((short)objd.BHAV_EatID);

            case VMOBJDVariable.PickupFromSlotTreeID:
                return((short)objd.BHAV_PickupFromSlotID);    //uh

            case VMOBJDVariable.WashDishTreeID:
                return((short)objd.BHAV_WashDishID);

            case VMOBJDVariable.EatingSurfaceTreeID:
                return((short)objd.BHAV_EatSurfaceID);

            case VMOBJDVariable.SitTreeID:
                return((short)objd.BHAV_SitID);

            case VMOBJDVariable.StandTreeID:
                return((short)objd.BHAV_StandID);

            case VMOBJDVariable.SalePrice:
                return((short)objd.SalePrice);

            case VMOBJDVariable.Unused35:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.Unused36:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.BrokenBaseGraphicOffset:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.Unused38:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.HasCriticalAttributes:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.BuyModeType:
                return((short)objd.FunctionFlags);

            case VMOBJDVariable.CatalogStringsID:
                return((short)objd.CatalogStringsID);

            case VMOBJDVariable.IsGlobalSimObject:
                return((short)objd.Global);

            case VMOBJDVariable.InitTreeID:
                return((short)objd.BHAV_Init);

            case VMOBJDVariable.PlaceTreeID:
                return((short)objd.BHAV_Place);

            case VMOBJDVariable.UserPickupTreeID:
                return((short)objd.BHAV_UserPickup);

            case VMOBJDVariable.WallStyle:
                return((short)objd.WallStyle);

            case VMOBJDVariable.LoadTreeID:
                return((short)objd.BHAV_Load);

            case VMOBJDVariable.UserPlaceTreeID:
                return((short)objd.BHAV_UserPlace);

            case VMOBJDVariable.ObjectVersion:
                return((short)objd.ObjectVersion);

            case VMOBJDVariable.RoomChangedTreeID:
                return((short)objd.BHAV_RoomChange);

            case VMOBJDVariable.MotiveEffectsID:
                return((short)objd.MotiveEffectsID);

            case VMOBJDVariable.CleanupTreeID:
                return((short)objd.BHAV_Cleanup);

            case VMOBJDVariable.LevelInfoRequestTreeID:
                return((short)objd.BHAV_LevelInfo);

            case VMOBJDVariable.CatalogPopupID:
                return((short)objd.CatalogID);

            case VMOBJDVariable.ServingSurfaceTreeID:
                return((short)objd.CatalogID);

            case VMOBJDVariable.LevelOffset:
                return((short)objd.LevelOffset);

            case VMOBJDVariable.Shadow:
                return((short)objd.Shadow);

            case VMOBJDVariable.NumAttributes:
                return((short)objd.NumAttributes);

            case VMOBJDVariable.CleanTreeID:
                return((short)objd.BHAV_Clean);

            case VMOBJDVariable.QueueSkippedTreeID:
                return((short)objd.BHAV_QueueSkipped);

            case VMOBJDVariable.FrontDirection:
                return((short)objd.FrontDirection);

            case VMOBJDVariable.WallAdjacencyChangedTreeID:
                return((short)objd.BHAV_WallAdjacencyChanged);

            case VMOBJDVariable.MyLeadObject:
                return((short)objd.MyLeadObject);

            case VMOBJDVariable.DynamicSpritesBaseID:
                return((short)objd.DynamicSpriteBaseId);

            case VMOBJDVariable.NumDynamicSprites:
                return((short)objd.NumDynamicSprites);

            case VMOBJDVariable.ChairEntryFlags:
                return((short)objd.ChairEntryFlags);

            case VMOBJDVariable.TileWidth:
                return((short)objd.TileWidth);

            case VMOBJDVariable.LotCategories:
                return(0);    //NOT IN OBJD RIGHT NOW!

            case VMOBJDVariable.BuildModeType:
                return((short)objd.BuildModeType);

            case VMOBJDVariable.OriginalGUID1:
                return((short)objd.OriginalGUID1);

            case VMOBJDVariable.OriginalGUID2:
                return((short)objd.OriginalGUID2);

            case VMOBJDVariable.SuitGUID1:
                return((short)objd.SuitGUID1);

            case VMOBJDVariable.SuitGUID2:
                return((short)objd.SuitGUID2);

            case VMOBJDVariable.PickupTreeID:
                return((short)objd.BHAV_Pickup);

            case VMOBJDVariable.ThumbnailGraphic:
                return((short)objd.ThumbnailGraphic);

            case VMOBJDVariable.ShadowFlags:
                return((short)objd.ShadowFlags);

            case VMOBJDVariable.FootprintMask:
                return((short)objd.FootprintMask);

            case VMOBJDVariable.DynamicMultiTileUpdateTreeID:
                return((short)objd.BHAV_DynamicMultiTileUpdate);

            case VMOBJDVariable.ShadowBrightness:
                return((short)objd.ShadowBrightness);

            case VMOBJDVariable.RepairTreeID:
                return((short)objd.BHAV_Repair);

            case VMOBJDVariable.WallStyleSpriteID:
                return((short)objd.WallStyleSpriteID);

            case VMOBJDVariable.RatingHunger:
                return((short)objd.RatingHunger);

            case VMOBJDVariable.RatingComfort:
                return((short)objd.CatalogID);

            case VMOBJDVariable.RatingHygiene:
                return((short)objd.RatingHygiene);

            case VMOBJDVariable.RatingBladder:
                return((short)objd.RatingBladder);

            case VMOBJDVariable.RatingEnergy:
                return((short)objd.RatingEnergy);

            case VMOBJDVariable.RatingFun:
                return((short)objd.RatingFun);

            case VMOBJDVariable.RatingRoom:
                return((short)objd.RatingRoom);

            case VMOBJDVariable.RatingSkillFlags:
                return((short)objd.RatingSkillFlags);

            case VMOBJDVariable.NumTypeAttributes:
                throw new VMSimanticsException("Not Implemented!", context);     //??

            case VMOBJDVariable.MiscFlags:
                throw new VMSimanticsException("Not Implemented!", context);     //??

            case VMOBJDVariable.TypeAttrGUID1:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.TypeAttrGUID2:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.InteractionResultStrings:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.ClientHouseJoinTreeID:
                throw new VMSimanticsException("Not Implemented!", context);

            case VMOBJDVariable.PrepareForSaleTreeID:
                throw new VMSimanticsException("Not Implemented!", context);

            default:
                throw new VMSimanticsException("Unknown definition var", context);
            }
        }
Ejemplo n.º 18
0
        public DGRP3DMesh(DGRP dgrp, OBJD obj, GraphicsDevice gd, string saveDirectory)
        {
            ReconstructVersion = CURRENT_RECONSTRUCT;
            SaveDirectory      = saveDirectory;
            Geoms = new List <Dictionary <Texture2D, DGRP3DGeometry> >();
            if (dgrp == null)
            {
                return;
            }
            Name = obj.ChunkParent.Filename.Replace('.', '_') + "_" + dgrp.ChunkID;
            var lower  = obj.ChunkParent.Filename.ToLowerInvariant();
            var config = obj.ChunkParent.List <FSOR>()?.FirstOrDefault()?.Params;

            if (config == null)
            {
                if (!ParamsByIff.TryGetValue(lower, out config))
                {
                    config = DefaultParams;
                }
            }
            if (!config.InRange(dgrp.ChunkID))
            {
                config = DefaultParams;
            }

            int totalSpr = 0;

            for (uint rotation = 0; rotation < 4; rotation++)
            {
                if (config.DoorFix)
                {
                    if ((obj.SubIndex & 0xFF) == 1)
                    {
                        if ((rotation + 1) % 4 > 1)
                        {
                            continue;
                        }
                    }
                    else
                    {
                        if ((rotation + 1) % 4 < 2)
                        {
                            continue;
                        }
                    }
                }
                else if (!config.Rotations[rotation])
                {
                    continue;
                }
                var img = dgrp.GetImage(1, 3, rotation);

                var zOff = (config.BlenderTweak) ? -57.5f : -55f;

                var mat = Matrix.CreateTranslation(new Vector3(-72, -344, zOff));
                mat *= Matrix.CreateScale((1f / (128)) * 1.43f);//1.4142135623730f);
                mat *= Matrix.CreateScale(1, -1, 1);

                mat *= Matrix.CreateRotationX((float)Math.PI / -6);
                mat *= Matrix.CreateRotationY(((float)Math.PI / 4) * (1 + rotation * 2));

                var factor = (config.BlenderTweak) ? 0.40f : 0.39f;

                int curSpr = 0;
                foreach (var sprite in img.Sprites)
                {
                    var sprMat = mat * Matrix.CreateTranslation(new Vector3(sprite.ObjectOffset.X, sprite.ObjectOffset.Z, sprite.ObjectOffset.Y) * new Vector3(1f / 16f, 1f / 5f, 1f / 16f));
                    var inv    = Matrix.Invert(sprMat);
                    var tex    = sprite.GetTexture(gd);

                    if (tex == null)
                    {
                        curSpr++;
                        continue;
                    }
                    var isDynamic = sprite.SpriteID >= obj.DynamicSpriteBaseId && sprite.SpriteID < (obj.DynamicSpriteBaseId + obj.NumDynamicSprites);
                    var dynid     = (isDynamic) ? (int)(1 + sprite.SpriteID - obj.DynamicSpriteBaseId) : 0;

                    while (Geoms.Count <= dynid)
                    {
                        Geoms.Add(new Dictionary <Texture2D, DGRP3DGeometry>());
                    }

                    DGRP3DGeometry geom = null;
                    if (!Geoms[dynid].TryGetValue(tex, out geom))
                    {
                        geom = new DGRP3DGeometry()
                        {
                            Pixel = tex
                        };
                        Geoms[dynid][geom.Pixel] = geom;
                    }
                    geom.PixelDir = (ushort)rotation;
                    geom.PixelSPR = (ushort)(curSpr++);
                    totalSpr++;

                    var depthB = sprite.GetDepth();

                    var     useDequantize  = false;
                    float[] depth          = null;
                    int     iterations     = 125;
                    int     triDivisor     = 100;
                    float   aggressiveness = 3.5f;
                    if (useDequantize)
                    {
                        var dtex = new Texture2D(gd, ((TextureInfo)tex.Tag).Size.X, ((TextureInfo)tex.Tag).Size.Y, false, SurfaceFormat.Color);
                        dtex.SetData(depthB.Select(x => new Color(x, x, x, x)).ToArray());
                        depth = DepthTreatment.DequantizeDepth(gd, dtex);
                        dtex.Dispose();

                        iterations     = 500;
                        aggressiveness = 2.5f;
                        MaxAllowedSq   = 0.05f * 0.05f;
                    }
                    else if (depthB != null)
                    {
                        depth          = depthB.Select(x => x / 255f).ToArray();
                        iterations     = 125;
                        aggressiveness = 3.5f;
                    }

                    if (depth == null)
                    {
                        continue;
                    }

                    QueueWork(() =>
                    {
                        var boundPts = new List <Vector3>();
                        //begin async part
                        var w = ((TextureInfo)tex.Tag).Size.X;
                        var h = ((TextureInfo)tex.Tag).Size.Y;

                        var pos     = sprite.SpriteOffset + new Vector2(72, 348 - h);
                        var tl      = Vector3.Transform(new Vector3(pos, 0), sprMat);
                        var tr      = Vector3.Transform(new Vector3(pos + new Vector2(w, 0), 0), sprMat);
                        var bl      = Vector3.Transform(new Vector3(pos + new Vector2(0, h), 0), sprMat);
                        var tlFront = Vector3.Transform(new Vector3(pos, 110.851251f), sprMat);

                        var xInc    = (tr - tl) / w;
                        var yInc    = (bl - tl) / h;
                        var dFactor = (tlFront - tl) / (factor);

                        if (sprite.Flip)
                        {
                            tl    = tr;
                            xInc *= -1;
                        }

                        var dict    = new Dictionary <int, int>();
                        var verts   = new List <VertexPositionTexture>();
                        var indices = new List <int>();

                        var lastPt = new Vector3();
                        var i      = 0;
                        var verti  = 0;
                        for (int y = 0; y < h; y++)
                        {
                            if (y > 0)
                            {
                                boundPts.Add(lastPt);
                            }
                            bool first = true;
                            var vpos   = tl;
                            for (int x = 0; x < w; x++)
                            {
                                var d = depth[i++];
                                if (d < 0.999f)
                                {
                                    lastPt = vpos + (1f - d) * dFactor;
                                    if (first)
                                    {
                                        boundPts.Add(lastPt); first = false;
                                    }
                                    var vert = new VertexPositionTexture(lastPt, new Vector2((float)x / w, (float)y / h));
                                    verts.Add(vert);
                                    dict.Add(y * w + x, verti++);
                                }
                                vpos += xInc;
                            }
                            tl += yInc;
                        }

                        for (int y = 0; y < h - 1; y++)
                        {
                            for (int x = 0; x < w - 1; x++)
                            {
                                //try make a triangle or two
                                var quad = new int?[] {
                                    QuickTryGet(dict, x + y * w),
                                    QuickTryGet(dict, x + 1 + y * w),
                                    QuickTryGet(dict, x + 1 + (y + 1) * w),
                                    QuickTryGet(dict, x + (y + 1) * w)
                                };
                                var total = quad.Sum(v => (v == null) ? 0 : 1);
                                if (total == 4)
                                {
                                    var d1 = Vector3.DistanceSquared(verts[quad[0].Value].Position, verts[quad[2].Value].Position);
                                    var d2 = Vector3.DistanceSquared(verts[quad[1].Value].Position, verts[quad[3].Value].Position);

                                    if (d1 > MaxAllowedSq || d2 > MaxAllowedSq)
                                    {
                                        continue;
                                    }

                                    indices.Add(quad[0].Value);
                                    indices.Add(quad[1].Value);
                                    indices.Add(quad[2].Value);

                                    indices.Add(quad[0].Value);
                                    indices.Add(quad[2].Value);
                                    indices.Add(quad[3].Value);
                                }
                                else if (total == 3)
                                {
                                    //clockwise anyways. we can only make one
                                    int?last  = null;
                                    int?first = null;
                                    bool exit = false;
                                    foreach (var v in quad)
                                    {
                                        if (v != null)
                                        {
                                            if (last != null && Vector3.DistanceSquared(verts[last.Value].Position, verts[v.Value].Position) > MaxAllowedSq)
                                            {
                                                exit = true;
                                                break;
                                            }
                                            last = v.Value;
                                            if (first == null)
                                            {
                                                first = last;
                                            }
                                        }
                                    }

                                    if (!exit && Vector3.DistanceSquared(verts[last.Value].Position, verts[first.Value].Position) > MaxAllowedSq)
                                    {
                                        exit = true;
                                    }
                                    if (exit)
                                    {
                                        continue;
                                    }

                                    foreach (var v in quad)
                                    {
                                        if (v != null)
                                        {
                                            indices.Add(v.Value);
                                        }
                                    }
                                }
                            }
                        }

                        if (config.CounterFix)
                        {
                            //x axis extrapolation
                            //clip: -0.4 to 0.4

                            //identify vertices very close to clipping range(border)
                            //! for each vertex outwith clipping range
                            //- idendify closest border pixel bp in image space
                            //- result.zy = bp.zy
                            //- result.x = (resultIMAGE.x - bpIMAGE.x) / 64;
                            //- clip x to -0.5, 0.5f.

                            var clip     = 0.4;
                            var bWidth   = 0.02;
                            var border1  = new List <Tuple <Vector2, Vector3> >();
                            var invalid1 = new List <KeyValuePair <int, int> >();
                            var border2  = new List <Tuple <Vector2, Vector3> >();
                            var invalid2 = new List <KeyValuePair <int, int> >();
                            foreach (var vert in dict)
                            {
                                var vpos = verts[vert.Value].Position;
                                var dist = Math.Abs(vpos.X);
                                if (dist > clip)
                                {
                                    if (vpos.X > 0)
                                    {
                                        invalid1.Add(vert);
                                    }
                                    else
                                    {
                                        invalid2.Add(vert);
                                    }
                                }
                                else if (dist > (clip - bWidth))
                                {
                                    if (vpos.X > 0)
                                    {
                                        border1.Add(new Tuple <Vector2, Vector3>(new Vector2(vert.Key % w, vert.Key / w), vpos));
                                    }
                                    else
                                    {
                                        border2.Add(new Tuple <Vector2, Vector3>(new Vector2(vert.Key % w, vert.Key / w), vpos));
                                    }
                                }
                            }

                            var edge = 0.498f + 0.001f * (rotation % 2);

                            if (border1.Count > 0)
                            {
                                foreach (var vert in invalid1)
                                {
                                    var vstr    = verts[vert.Value];
                                    var pos2d   = new Vector2(vert.Key % w, vert.Key / w);
                                    var vpos    = vstr.Position;
                                    var closest = border1.OrderBy(x => Vector2.DistanceSquared(x.Item1, pos2d)).First();

                                    vpos.X = closest.Item2.X + Vector2.Distance(closest.Item1, pos2d) / 71.55f;
                                    if (vpos.X > 0.5f)
                                    {
                                        vpos.X = edge;
                                    }
                                    else
                                    {
                                        vpos.Y = closest.Item2.Y;
                                        vpos.Z = closest.Item2.Z;
                                    }

                                    vstr.Position     = vpos;
                                    verts[vert.Value] = vstr;
                                }
                            }

                            if (border2.Count > 0)
                            {
                                foreach (var vert in invalid2)
                                {
                                    var vstr    = verts[vert.Value];
                                    var pos2d   = new Vector2(vert.Key % w, vert.Key / w);
                                    var vpos    = vstr.Position;
                                    var closest = border2.OrderBy(x => Vector2.DistanceSquared(x.Item1, pos2d)).First();

                                    vpos.X = closest.Item2.X - Vector2.Distance(closest.Item1, pos2d) / 71.55f;
                                    if (vpos.X < -0.5f)
                                    {
                                        vpos.X = -edge;
                                    }
                                    else
                                    {
                                        vpos.Y = closest.Item2.Y;
                                        vpos.Z = closest.Item2.Z;
                                    }

                                    vstr.Position     = vpos;
                                    verts[vert.Value] = vstr;
                                }
                            }
                        }


                        lock (BoundPts) BoundPts.AddRange(boundPts);
                        var useSimplification = config.Simplify;

                        if (useSimplification)
                        {
                            var simple      = new Simplify();
                            simple.vertices = verts.Select(x => new MSVertex()
                            {
                                p = x.Position, t = x.TextureCoordinate
                            }).ToList();
                            for (int t = 0; t < indices.Count; t += 3)
                            {
                                simple.triangles.Add(new MSTriangle()
                                {
                                    v = new int[] { indices[t], indices[t + 1], indices[t + 2] }
                                });
                            }
                            simple.simplify_mesh(simple.triangles.Count / triDivisor, agressiveness: aggressiveness, iterations: iterations);

                            verts = simple.vertices.Select(x =>
                            {
                                var iv = Vector3.Transform(x.p, inv);
                                //DGRP3DVert
                                return(new VertexPositionTexture(x.p,
                                                                 new Vector2(
                                                                     (sprite.Flip) ? (1 - ((iv.X - pos.X + 0.5f) / w)) : ((iv.X - pos.X + 0.5f) / w),
                                                                     (iv.Y - pos.Y + 0.5f) / h)));
                            }
                                                           ).ToList();
                            indices.Clear();
                            foreach (var t in simple.triangles)
                            {
                                indices.Add(t.v[0]);
                                indices.Add(t.v[1]);
                                indices.Add(t.v[2]);
                            }

                            GameThread.NextUpdate(x =>
                            {
                                if (geom.SVerts == null)
                                {
                                    geom.SVerts   = new List <DGRP3DVert>();
                                    geom.SIndices = new List <int>();
                                }

                                var bID = geom.SVerts.Count;
                                foreach (var id in indices)
                                {
                                    geom.SIndices.Add(id + bID);
                                }
                                var verts2 = verts.Select(v => new DGRP3DVert(v.Position, Vector3.Zero, v.TextureCoordinate)).ToList();
                                DGRP3DVert.GenerateNormals(!sprite.Flip, verts2, indices);
                                geom.SVerts.AddRange(verts2);

                                lock (this)
                                {
                                    if (++CompletedCount == TotalSprites)
                                    {
                                        Complete(gd);
                                    }
                                }
                            });
                        }
                        else
                        {
                            GameThread.NextUpdate(x =>
                            {
                                if (geom.SVerts == null)
                                {
                                    geom.SVerts   = new List <DGRP3DVert>();
                                    geom.SIndices = new List <int>();
                                }

                                var baseID = geom.SVerts.Count;
                                foreach (var id in indices)
                                {
                                    geom.SIndices.Add(id + baseID);
                                }
                                var verts2 = verts.Select(v => new DGRP3DVert(v.Position, Vector3.Zero, v.TextureCoordinate)).ToList();
                                DGRP3DVert.GenerateNormals(!sprite.Flip, verts2, indices);
                                geom.SVerts.AddRange(verts2);
                                lock (this)
                                {
                                    if (++CompletedCount == TotalSprites)
                                    {
                                        Complete(gd);
                                    }
                                }
                            });
                        }
                    });
                }
            }
            TotalSprites = totalSpr;
        }