Beispiel #1
0
        private void LoadYcds()
        {
            int cutListCount = (CameraCutList?.Length ?? 0) + 1;
            var shortName    = CutFile.FileEntry?.GetShortNameLower() ?? "";

            Ycds = new YcdFile[cutListCount];
            if (!string.IsNullOrEmpty(shortName))
            {
                for (int i = 0; i < cutListCount; i++)
                {
                    var ycdname = shortName + "-" + i.ToString();
                    var ycdhash = JenkHash.GenHash(ycdname);
                    var ycd     = GameFileCache.GetYcd(ycdhash);
                    while ((ycd != null) && (!ycd.Loaded))
                    {
                        Thread.Sleep(1);//bite me
                        ycd = GameFileCache.GetYcd(ycdhash);
                    }
                    if (ycd != null)
                    {
                        ycd.BuildCutsceneMap(i);
                    }
                    Ycds[i] = ycd;
                }
            }
        }
Beispiel #2
0
        private Texture OpenDDSFile()
        {
            if (OpenDDSFileDialog.ShowDialog() != DialogResult.OK)
            {
                return(null);
            }

            var fn = OpenDDSFileDialog.FileName;

            if (!File.Exists(fn))
            {
                return(null);                  //couldn't find file?
            }
            try
            {
                var dds = File.ReadAllBytes(fn);
                var tex = DDSIO.GetTexture(dds);
                tex.Name     = Path.GetFileNameWithoutExtension(fn);
                tex.NameHash = JenkHash.GenHash(tex.Name?.ToLowerInvariant());
                JenkIndex.Ensure(tex.Name?.ToLowerInvariant());
                return(tex);
            }
            catch
            {
                MessageBox.Show("Unable to load " + fn + ".\nAre you sure it's a valid .dds file?");
            }

            return(null);
        }
        private void CategoryTextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            if (CurrentEmitter?.AudioEmitter == null)
            {
                return;
            }

            uint   hash = 0;
            string name = CategoryTextBox.Text;

            if (!uint.TryParse(name, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(name);
                JenkIndex.Ensure(name);
            }
            //HashLabel.Text = "Hash: " + hash.ToString();

            if (CurrentEmitter.AudioEmitter.Category != hash)
            {
                CurrentEmitter.AudioEmitter.Category = hash;

                ProjectItemChanged();
            }
        }
Beispiel #4
0
        private void YmapNameTextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            uint   hash = 0;
            string name = YmapNameTextBox.Text;

            if (!uint.TryParse(name, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(name);
                JenkIndex.Ensure(name);
            }
            YmapNameHashLabel.Text = "Hash: " + hash.ToString();

            if (Ymap != null)
            {
                lock (ProjectForm.ProjectSyncRoot)
                {
                    string ymname = name + ".ymap";
                    if (Ymap.Name != ymname)
                    {
                        Ymap.Name           = ymname;
                        Ymap._CMapData.name = new MetaHash(hash);
                        SetYmapHasChanged(true);
                        UpdateFormTitle();
                    }
                }
            }
        }
Beispiel #5
0
        public YmapEntityDef RenderEntity = new YmapEntityDef(); //placeholder entity object for rendering


        public void Init(string name, GameFileCache gfc)
        {
            var hash = JenkHash.GenHash(name.ToLowerInvariant());

            Init(hash, gfc);
            Name = name;
        }
Beispiel #6
0
        private void RenderVehicle()
        {
            YftFile yft = GameFileCache.GetYft(SelectedModelHash);

            if (yft != null)
            {
                if (yft.Loaded)
                {
                    if (yft.Fragment != null)
                    {
                        var f = yft.Fragment;

                        var txdhash = SelectedVehicleHash;// yft.RpfFileEntry?.ShortNameHash ?? 0;

                        var namelower = yft.RpfFileEntry?.GetShortNameLower();
                        if (namelower?.EndsWith("_hi") ?? false)
                        {
                            txdhash = JenkHash.GenHash(namelower.Substring(0, namelower.Length - 3));
                        }

                        Archetype arch = null;// TryGetArchetype(hash);

                        Renderer.RenderFragment(arch, null, f, txdhash);

                        //seldrwbl = f.Drawable;
                    }
                }
            }
        }
Beispiel #7
0
        private void HashesTextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            if (CurrentZone?.AudioZone == null)
            {
                return;
            }

            var hashstrs = HashesTextBox.Text.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

            if (hashstrs?.Length > 0)
            {
                var hashlist = new List <MetaHash>();
                foreach (var hashstr in hashstrs)
                {
                    uint hash = 0;
                    if (!uint.TryParse(hashstr, out hash))//don't re-hash hashes
                    {
                        hash = JenkHash.GenHash(hashstr);
                        JenkIndex.Ensure(hashstr);
                    }
                    hashlist.Add(hash);
                }

                CurrentZone.AudioZone.Rules      = hashlist.ToArray();
                CurrentZone.AudioZone.RulesCount = (byte)hashlist.Count;

                ProjectItemChanged();
            }
        }
        private void TextureDictTextBox_TextChanged(object sender, EventArgs e)
        {
            // Check that the form is not null before locking...
            if (ProjectForm == null)
            {
                return;
            }

            lock (ProjectForm.ProjectSyncRoot)
            {
                // Embedded...
                if (TextureDictTextBox.Text == ArchetypeNameTextBox.Text)
                {
                    TextureDictHashLabel.Text = "Embedded";
                    CurrentArchetype._BaseArchetypeDef.textureDictionary = CurrentArchetype._BaseArchetypeDef.name;
                    return;
                }

                var hash = JenkHash.GenHash(TextureDictTextBox.Text);

                if (CurrentArchetype._BaseArchetypeDef.textureDictionary != hash)
                {
                    var ytd = ProjectForm.GameFileCache.GetYtd(hash);
                    if (ytd == null)
                    {
                        TextureDictHashLabel.Text = "Hash: " + hash.ToString() + " (invalid)";
                        ProjectForm.SetYtypHasChanged(true);
                        return;
                    }
                    TextureDictHashLabel.Text = "Hash: " + hash.ToString();
                    CurrentArchetype._BaseArchetypeDef.textureDictionary = hash;
                    ProjectForm.SetYtypHasChanged(true);
                }
            }
        }
Beispiel #9
0
        public void Init(string name, GameFileCache gfc, bool hidef = true)
        {
            Name = name;
            var      modelnamel  = name.ToLowerInvariant();
            MetaHash modelhash   = JenkHash.GenHash(modelnamel);
            MetaHash modelhashhi = JenkHash.GenHash(modelnamel + "_hi");
            var      ydrhash     = hidef ? modelhashhi : modelhash;

            NameHash  = modelhash;
            ModelHash = ydrhash;

            var useHash = ModelHash;

            Ydr = gfc.GetYdr(ModelHash);
            if (Ydr == null)
            {
                useHash = NameHash;
                Ydr     = gfc.GetYdr(NameHash);
            }

            while ((Ydr != null) && (!Ydr.Loaded))
            {
                Thread.Sleep(20);//kinda hacky
                Ydr = gfc.GetYdr(useHash);
            }

            if (Ydr != null)
            {
                Drawable = Ydr.Drawable?.ShallowCopy() as Drawable;
            }


            UpdateEntity();
        }
Beispiel #10
0
        private void NameTextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            if (CurrentZone?.AudioZone == null)
            {
                return;
            }

            uint   hash = 0;
            string name = NameTextBox.Text;

            if (!uint.TryParse(name, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(name);
                JenkIndex.Ensure(name);
            }
            //NameHashLabel.Text = "Hash: " + hash.ToString();

            if (CurrentZone.AudioZone.NameHash != hash)
            {
                CurrentZone.AudioZone.Name     = NameTextBox.Text;
                CurrentZone.AudioZone.NameHash = hash;

                ProjectItemChanged();
                UpdateFormTitle();
            }
        }
Beispiel #11
0
        public void Init(XmlNode node)
        {
            Dict = new Dictionary <string, TimecycleModValue>();

            name      = Xml.GetStringAttribute(node, "name");
            numMods   = Xml.GetIntAttribute(node, "numMods");
            userFlags = Xml.GetIntAttribute(node, "userFlags");

            string namel = name.ToLowerInvariant();

            JenkIndex.Ensure(namel);
            nameHash = JenkHash.GenHash(namel);

            List <TimecycleModValue> vals = new List <TimecycleModValue>();

            foreach (XmlNode valnode in node.ChildNodes)
            {
                if (!(valnode is XmlElement))
                {
                    continue;
                }

                TimecycleModValue val = new TimecycleModValue();
                val.Init(valnode);

                vals.Add(val);
                Dict[val.name] = val;
            }
            Values = vals.ToArray();
        }
        private void PhysicsDictionaryTextBox_TextChanged(object sender, EventArgs e)
        {
            lock (ProjectForm.ProjectSyncRoot)
            {
                if (ProjectForm == null)
                {
                    return;
                }

                // Embedded...
                if (PhysicsDictionaryTextBox.Text == ArchetypeNameTextBox.Text)
                {
                    PhysicsDictHashLabel.Text = "Embedded";
                    CurrentArchetype._BaseArchetypeDef.physicsDictionary = CurrentArchetype._BaseArchetypeDef.name;
                    return;
                }

                var hash = JenkHash.GenHash(PhysicsDictionaryTextBox.Text);

                if (CurrentArchetype._BaseArchetypeDef.physicsDictionary != hash)
                {
                    var ytd = ProjectForm.GameFileCache.GetYbn(hash);
                    if (ytd == null)
                    {
                        PhysicsDictHashLabel.Text = "Hash: " + hash.ToString() + " (invalid)";
                        ProjectForm.SetYtypHasChanged(true);
                        return;
                    }
                    PhysicsDictHashLabel.Text = "Hash: " + hash.ToString();

                    CurrentArchetype._BaseArchetypeDef.physicsDictionary = hash;
                    ProjectForm.SetYtypHasChanged(true);
                }
            }
        }
Beispiel #13
0
        private void CreateSceneObjects()
        {
            SceneObjects = new Dictionary <int, CutsceneObject>();

            if (Objects == null)
            {
                return;
            }


            var refCounts = new Dictionary <MetaHash, int>();

            foreach (var obj in Objects.Values)
            {
                var sobj = new CutsceneObject();
                sobj.Init(obj, GameFileCache);
                SceneObjects[sobj.ObjectID] = sobj;

                if (sobj.AnimHash != 0)
                {
                    int refcount = 0;
                    var hash     = sobj.AnimHash;
                    refCounts.TryGetValue(hash, out refcount);
                    if (refcount > 0)
                    {
                        var newstr = hash.ToString() + "^" + refcount.ToString();
                        sobj.AnimHash = JenkHash.GenHash(newstr);
                    }
                    refcount++;
                    refCounts[hash] = refcount;
                }
            }
        }
Beispiel #14
0
        private void Hash1TextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            if (CurrentZone?.AudioZone == null)
            {
                return;
            }

            var  hashstr = Hash1TextBox.Text;
            uint hash    = 0;

            if (!uint.TryParse(hashstr, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(hashstr);
                JenkIndex.Ensure(hashstr);
            }

            if (CurrentZone.AudioZone.UnkHash1 != hash)
            {
                CurrentZone.AudioZone.UnkHash1 = hash;

                ProjectItemChanged();
            }
        }
        private void Unk14TextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            if (CurrentRoom == null)
            {
                return;
            }

            uint   hash = 0;
            string name = Unk14TextBox.Text;

            if (!uint.TryParse(name, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(name);
                JenkIndex.Ensure(name);
            }
            //NameHashLabel.Text = "Hash: " + hash.ToString();

            if (CurrentRoom.Unk14 != hash)
            {
                CurrentRoom.Unk14 = hash;

                ProjectItemChanged();
            }
        }
Beispiel #16
0
        private void YmapNameTextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            uint   hash = 0;
            string name = YmapNameTextBox.Text;

            if (!uint.TryParse(name, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(name);
                JenkIndex.Ensure(name);
            }
            YmapNameHashLabel.Text = "Hash: " + hash.ToString();

            if (Ymap != null)
            {
                lock (ProjectForm.ProjectSyncRoot)
                {
                    Ymap.SetName(name);
                    if (!File.Exists(Ymap.FilePath))
                    {
                        Ymap.FilePath = name;
                    }
                    SetYmapHasChanged(true);
                    UpdateFormTitle();
                }
            }
        }
Beispiel #17
0
        public void Init(string name, GameFileCache gfc, bool hidef = true)
        {
            Name = name;
            var      modelnamel  = name.ToLowerInvariant();
            MetaHash modelhash   = JenkHash.GenHash(modelnamel);
            MetaHash modelhashhi = JenkHash.GenHash(modelnamel + "_hi");
            var      yfthash     = hidef ? modelhashhi : modelhash;

            VehicleInitData vid = null;

            if (gfc.VehiclesInitDict.TryGetValue(modelhash, out vid))
            {
                bool vehiclechange = NameHash != modelhash;
                ConvRoofDict = null;
                ConvRoofClip = null;
                ModelHash    = yfthash;
                NameHash     = modelhash;
                InitData     = vid;
                Yft          = gfc.GetYft(ModelHash);
                while ((Yft != null) && (!Yft.Loaded))
                {
                    Thread.Sleep(20);//kinda hacky
                    Yft = gfc.GetYft(ModelHash);
                }

                DisplayMake = GlobalText.TryGetString(JenkHash.GenHash(vid.vehicleMakeName.ToLowerInvariant()));
                DisplayName = GlobalText.TryGetString(JenkHash.GenHash(vid.gameName.ToLowerInvariant()));

                if (!string.IsNullOrEmpty(vid.animConvRoofDictName) && (vid.animConvRoofDictName.ToLowerInvariant() != "null"))
                {
                    var ycdhash  = JenkHash.GenHash(vid.animConvRoofDictName.ToLowerInvariant());
                    var cliphash = JenkHash.GenHash(vid.animConvRoofName?.ToLowerInvariant());
                    ConvRoofDict = gfc.GetYcd(ycdhash);
                    while ((ConvRoofDict != null) && (!ConvRoofDict.Loaded))
                    {
                        Thread.Sleep(20);//kinda hacky
                        ConvRoofDict = gfc.GetYcd(ycdhash);
                    }
                    ClipMapEntry cme = null;
                    ConvRoofDict?.ClipMap?.TryGetValue(cliphash, out cme);
                    ConvRoofClip = cme;
                }
            }
            else
            {
                ModelHash    = 0;
                NameHash     = 0;
                InitData     = null;
                Yft          = null;
                DisplayMake  = "-";
                DisplayName  = "-";
                ConvRoofDict = null;
                ConvRoofClip = null;
            }


            UpdateEntity();
        }
        private void ClipDictionaryTextBox_TextChanged(object sender, EventArgs e)
        {
            var hash = JenkHash.GenHash(ClipDictionaryTextBox.Text);

            if (CurrentArchetype._BaseArchetypeDef.clipDictionary != hash)
            {
                CurrentArchetype._BaseArchetypeDef.clipDictionary = hash;
                ProjectForm.SetYtypHasChanged(true);
            }
        }
        private void AssetNameTextBox_TextChanged(object sender, EventArgs e)
        {
            var hash = JenkHash.GenHash(AssetNameTextBox.Text);

            if (CurrentArchetype._BaseArchetypeDef.assetName != hash)
            {
                CurrentArchetype._BaseArchetypeDef.assetName = hash;
                ProjectForm.SetYtypHasChanged(true);
            }
        }
Beispiel #20
0
        private void EntityArchetypeTextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            if (CurrentEntity == null)
            {
                return;
            }
            uint   hash = 0;
            string name = EntityArchetypeTextBox.Text;

            if (!uint.TryParse(name, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(name);
                JenkIndex.Ensure(name);
            }
            EntityArchetypeHashLabel.Text = "Hash: " + hash.ToString();

            var arch = ProjectForm.GameFileCache.GetArchetype(hash);

            if (arch == null)
            {
                EntityArchetypeHashLabel.Text += " (not found)";
            }

            if (CurrentEntity != null)
            {
                lock (ProjectForm.ProjectSyncRoot)
                {
                    CurrentEntity._CEntityDef.archetypeName = new MetaHash(hash);

                    if (CurrentMCEntity != null)
                    {
                        CurrentMCEntity._Data.archetypeName = new MetaHash(hash);
                    }

                    if (CurrentEntity.Archetype != arch)
                    {
                        CurrentEntity.SetArchetype(arch);

                        if (CurrentEntity.IsMlo)
                        {
                            CurrentEntity.MloInstance.InitYmapEntityArchetypes(ProjectForm.GameFileCache);
                        }

                        ProjectItemChanged();
                    }
                }
            }

            ProjectForm.ProjectExplorer?.UpdateEntityTreeNode(CurrentEntity);
        }
Beispiel #21
0
        // from CodeWalker
        private MetaHash GetMetaHash2(string name)
        {
            uint hash = 0;

            if (!uint.TryParse(name, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(name);
                JenkIndex.Ensure(name);
            }

            return(hash);
        }
Beispiel #22
0
        public void BuildVertices()
        {
            var vlist = new List <EditorVertex>();
            var v1    = new EditorVertex();
            var v2    = new EditorVertex();
            var v3    = new EditorVertex();
            var v4    = new EditorVertex();

            foreach (var group in Groups.Values)
            {
                var  hash = JenkHash.GenHash(group.NameLabel.ToLowerInvariant());
                byte cr   = (byte)((hash >> 8) & 0xFF);
                byte cg   = (byte)((hash >> 16) & 0xFF);
                byte cb   = (byte)((hash >> 24) & 0xFF);
                byte ca   = 60;
                uint cv   = (uint)new Color(cr, cg, cb, ca).ToRgba();
                v1.Colour = cv;
                v2.Colour = cv;
                v3.Colour = cv;
                v4.Colour = cv;

                foreach (var box in group.Boxes)
                {
                    var min = box.Box.Minimum;
                    var max = box.Box.Maximum;

                    v1.Position = new Vector3(min.X, min.Y, 0);
                    v2.Position = new Vector3(max.X, min.Y, 0);
                    v3.Position = new Vector3(min.X, max.Y, 0);
                    v4.Position = new Vector3(max.X, max.Y, 0);

                    vlist.Add(v1);
                    vlist.Add(v2);
                    vlist.Add(v3);
                    vlist.Add(v3);
                    vlist.Add(v2);
                    vlist.Add(v4);
                }
            }

            if (vlist.Count > 0)
            {
                TriangleVerts = vlist.ToArray();
            }
            else
            {
                TriangleVerts = null;
            }
        }
        private void ClipDictionaryTextBox_TextChanged(object sender, EventArgs e)
        {
            var hash = 0u;

            if (!uint.TryParse(ClipDictionaryTextBox.Text, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(ClipDictionaryTextBox.Text);
            }

            if (CurrentArchetype._BaseArchetypeDef.clipDictionary != hash)
            {
                CurrentArchetype._BaseArchetypeDef.clipDictionary = hash;
                ProjectForm.SetYtypHasChanged(true);
            }
        }
        private void AssetNameTextBox_TextChanged(object sender, EventArgs e)
        {
            var hash = 0u;

            if (!uint.TryParse(AssetNameTextBox.Text, out hash))//don't re-hash hashes
            {
                hash = JenkHash.GenHash(AssetNameTextBox.Text);
            }

            if (CurrentArchetype._BaseArchetypeDef.assetName != hash)
            {
                CurrentArchetype._BaseArchetypeDef.assetName = hash;
                ProjectForm.SetYtypHasChanged(true);
            }
        }
Beispiel #25
0
        public RelFile AddAudioRelFile(string filename)
        {
            RelFile relfile = new RelFile();

            relfile.RpfFileEntry          = new RpfResourceFileEntry();
            relfile.RpfFileEntry.Name     = Path.GetFileName(filename);
            relfile.RpfFileEntry.NameHash = JenkHash.GenHash(relfile.RpfFileEntry.Name);
            relfile.FilePath = GetFullFilePath(filename);
            relfile.Name     = relfile.RpfFileEntry.Name;
            if (!AddAudioRelFile(relfile))
            {
                return(null);
            }
            return(relfile);
        }
Beispiel #26
0
        private void GenerateHash()
        {
            JenkHashInputEncoding encoding = JenkHashInputEncoding.UTF8;

            if (ASCIIRadioButton.Checked)
            {
                encoding = JenkHashInputEncoding.ASCII;
            }

            JenkHash h = new JenkHash(InputTextBox.Text, encoding);

            HashHexTextBox.Text      = h.HashHex;
            HashSignedTextBox.Text   = h.HashInt.ToString();
            HashUnsignedTextBox.Text = h.HashUint.ToString();
        }
Beispiel #27
0
        private void InitPed(CutPedModelObject ped, GameFileCache gfc)
        {
            Ped = new Ped();
            Ped.Init(ped.StreamingName, gfc);
            Ped.LoadDefaultComponents(gfc);

            if (ped.StreamingName == JenkHash.GenHash("player_zero"))
            {
                //for michael, switch his outfit so it's not glitching everywhere (until it's fixed?)
                Ped.SetComponentDrawable(3, 27, 0, 0, gfc);
                Ped.SetComponentDrawable(4, 19, 0, 0, gfc);
                Ped.SetComponentDrawable(6, null, null, gfc);
            }

            AnimHash = ped.StreamingName;
        }
        private void ArchetypeNameTextBox_TextChanged(object sender, EventArgs e)
        {
            var hash = JenkHash.GenHash(ArchetypeNameTextBox.Text);

            if (CurrentArchetype._BaseArchetypeDef.name != hash)
            {
                CurrentArchetype._BaseArchetypeDef.name = hash;
                UpdateFormTitle();

                TreeNode tn = ProjectForm.ProjectExplorer?.FindArchetypeTreeNode(CurrentArchetype);
                if (tn != null)
                {
                    tn.Text = ArchetypeNameTextBox.Text ?? "0"; // using the text box text because the name may not be in the gfc.
                }
                ProjectForm.SetYtypHasChanged(true);
            }
        }
Beispiel #29
0
        private void RenameTexture(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                return;
            }
            if (TexDict?.Textures?.data_items == null)
            {
                return;
            }
            if (CurrentTexture == null)
            {
                return;
            }
            if (CurrentTexture.Name == name)
            {
                return;
            }

            var tex = CurrentTexture;

            tex.Name     = name;
            tex.NameHash = JenkHash.GenHash(name.ToLowerInvariant());

            var textures = new List <Texture>();

            textures.AddRange(TexDict.Textures.data_items);

            TexDict.BuildFromTextureList(textures);

            Modified = true;

            foreach (ListViewItem lvi in TexturesListView.Items)
            {
                if (lvi.Tag == tex)
                {
                    lvi.Text        = tex.Name;
                    lvi.ToolTipText = tex.Name;
                    break;
                }
            }

            UpdateFormTitle();
            UpdateSaveYTDAs();
            UpdateModelFormTextures();
        }
Beispiel #30
0
        private void ExtParamsTextBox_TextChanged(object sender, EventArgs e)
        {
            if (populatingui)
            {
                return;
            }
            if (CurrentEmitter?.AudioEmitter == null)
            {
                return;
            }

            var paramstrs = ExtParamsTextBox.Text.Split(new[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

            if (paramstrs?.Length > 0)
            {
                var paramlist = new List <Dat151AmbientRule.ExtParam>();
                foreach (var paramstr in paramstrs)
                {
                    var paramvals = paramstr.Split(',');
                    if (paramvals?.Length == 3)
                    {
                        var  param   = new Dat151AmbientRule.ExtParam();
                        var  hashstr = paramvals[0].Trim();
                        var  valstr  = paramvals[1].Trim();
                        var  flgstr  = paramvals[2].Trim();
                        uint hash    = 0;
                        if (!uint.TryParse(hashstr, out hash))//don't re-hash hashes
                        {
                            hash = JenkHash.GenHash(hashstr);
                            JenkIndex.Ensure(hashstr);
                        }
                        uint flags = 0;
                        uint.TryParse(flgstr, out flags);
                        param.Hash  = hash;
                        param.Value = FloatUtil.Parse(valstr);
                        param.Flags = flags;
                        paramlist.Add(param);
                    }
                }

                CurrentEmitter.AudioEmitter.ExtParams      = paramlist.ToArray();
                CurrentEmitter.AudioEmitter.ExtParamsCount = (ushort)paramlist.Count;

                ProjectItemChanged();
            }
        }