コード例 #1
0
    public static void ReloadParams()
    {
        BND4 paramBnd = SFUtil.DecryptDS3Regulation(DarkSoulsTools.GetOverridenPath(ParamPath));

        DS3Param = PARAM64.Read(paramBnd.Files.Find(x => Path.GetFileName(x.Name) == "ItemLotParam.param").Bytes);
        PARAM64.Layout layout = PARAM64.Layout.ReadXMLFile($@"{Application.dataPath.Replace('/', '\\')}\dstools\ParamLayouts\DS3\{DS3Param.ID}.xml");
        DS3Param.SetLayout(layout);

        // Build and cache the item name list
        HashSet <int> usedItemIds = new HashSet <int>();

        ItemNameList = new List <Tuple <int, string> >();
        foreach (var row in DS3Param.Rows)
        {
            ItemLotParam param = new ItemLotParam(row);
            foreach (int id in param.ItemID)
            {
                if (!usedItemIds.Contains(id))
                {
                    usedItemIds.Add(id);
                    ItemNameList.Add(new Tuple <int, string>(id, FMGUtils.LookupItemName(id)));
                }
            }
        }
        ItemNameList.Sort((a, b) => StringComparer.InvariantCulture.Compare(a.Item2, b.Item2));
    }
コード例 #2
0
ファイル: FormMain.cs プロジェクト: elenabluz/Yapped
        private void LoadRegulation(string path)
        {
            BND4 bnd;

            try
            {
                bnd = SFUtil.DecryptDS3Regulation(path);
            }
            catch (Exception ex)
            {
                ShowError($"Failed to load regulation file:\r\n\r\n{path}\r\n\r\n{ex}");
                return;
            }

            paramFiles = new List <ParamFile>();
            foreach (BinderFile file in bnd.Files)
            {
                if (Path.GetExtension(file.Name) == ".param")
                {
                    try
                    {
                        PARAM64 param = PARAM64.Read(file.Bytes);
                        paramFiles.Add(new ParamFile(Path.GetFileNameWithoutExtension(file.Name), param, layouts));
                    }
                    catch
                    {
                    }
                }
            }

            paramFiles.Sort((p1, p2) => p1.Name.CompareTo(p2.Name));
            dgvParams.DataSource = paramFiles;
        }
コード例 #3
0
ファイル: ParamWrapper.cs プロジェクト: AinTunez/ModEngineGUI
 public ParamWrapper(string name, PARAM64 param, PARAM64.Layout layout, string description)
 {
     Name   = name;
     Param  = param;
     Layout = layout;
     Param.SetLayout(layout);
     Description = description;
 }
コード例 #4
0
ファイル: FormMain.cs プロジェクト: elenabluz/Yapped
            public ParamFile(string name, PARAM64 param, Dictionary <string, PARAM64.Layout> layouts)
            {
                Name  = name;
                Param = param;
                string format = Param.ID;

                if (!layouts.ContainsKey(format))
                {
                    layouts[format] = new PARAM64.Layout();
                }

                try
                {
                    Layout = layouts[format];
                    Param.SetLayout(Layout);
                    Rows = Param.Rows;
                }
                catch (Exception ex)
                {
                    Rows = new List <PARAM64.Row>();
                    ShowError($"Error in layout {format}, please try again.\r\n\r\n{ex}");
                }
            }
コード例 #5
0
        private void Randomize(IProgress <string> progress)
        {
            progress.Report("Loading regulation...");

            string regPath = Path.Combine(txtGameDir.Text, "Data0.bdt");

            if (!File.Exists(regPath))
            {
                progress.Report("Aborted.");
                ShowError($"Regulation file not found in game directory:\n{regPath}\nPlease make sure the path is correct.");
                return;
            }

            try
            {
                if (!File.Exists(regPath + ".bak"))
                {
                    File.Copy(regPath, regPath + ".bak");
                }
            }
            catch (Exception ex)
            {
                progress.Report("Aborted.");
                ShowError($"Failed to back up regulation file:\n{regPath}\n\n{ex}");
                return;
            }

            BND4 regulation;
            var  paramDict = new Dictionary <string, PARAM64>();

            try
            {
                regulation = Util.DecryptDS3Regulation(regPath);
                foreach (BND4.File f in regulation.Files)
                {
                    if (f.Name.EndsWith(".param"))
                    {
                        PARAM64        param  = PARAM64.Read(f.Bytes);
                        PARAM64.Layout layout = PARAM64.Layout.ReadXMLFile($"Layouts\\{param.ID}.xml");
                        param.SetLayout(layout);
                        paramDict[Path.GetFileNameWithoutExtension(f.Name)] = param;
                    }
                }
            }
            catch (Exception ex)
            {
                progress.Report("Aborted.");
                ShowError($"Failed to load regulation file:\n{regPath}\n\n{ex}");
                return;
            }

            progress.Report("Randomizing...");

            try
            {
                bool[]      weaponOptions = { radDefault.Checked, radBalanced.Checked, radNoShields.Checked };
                Irregulator irreg         = new Irregulator(txtSeed.Text);
                irreg.Randomize(paramDict,
                                cbxArmor.Checked, cbxWeapons.Checked, weaponOptions, cbxRings.Checked, cbxGoods.Checked,
                                cbxSpells.Checked, cbxBullets.Checked, cbxBulletsPlus.Checked, cbxHumans.Checked, cbxOther.Checked,
                                cbxTesting.Checked);
            }
            catch (Exception ex)
            {
                progress.Report("Aborted.");
                ShowError($"Failed to randomize regulation file:\n{regPath}\n\n{ex}");
                return;
            }

            progress.Report("Saving regulation...");

            try
            {
                foreach (BND4.File f in regulation.Files)
                {
                    if (paramDict.ContainsKey(Path.GetFileNameWithoutExtension(f.Name)))
                    {
                        f.Bytes = paramDict[Path.GetFileNameWithoutExtension(f.Name)].Write();
                    }
                }
                Util.EncryptDS3Regulation(regPath, regulation);
            }
            catch (Exception ex)
            {
                progress.Report("Aborted.");
                ShowError($"Failed to save regulation file:\n{regPath}\n\n{ex}");
                return;
            }

            progress.Report("Finished!");
            SystemSounds.Asterisk.Play();
        }
コード例 #6
0
ファイル: Util.cs プロジェクト: elenabluz/Yapped
        public static LoadParamsResult LoadParams(string paramPath, Dictionary <string, ParamInfo> paramInfo,
                                                  Dictionary <string, PARAM64.Layout> layouts, bool hideUnusedParams)
        {
            if (!File.Exists(paramPath))
            {
                ShowError($"Parambnd not found:\r\n{paramPath}\r\nPlease browse to the Data0.bdt or parambnd you would like to edit.");
                return(null);
            }

            var result = new LoadParamsResult();

            try
            {
                if (BND4.Is(paramPath))
                {
                    result.ParamBND  = BND4.Read(paramPath);
                    result.Encrypted = false;
                }
                else
                {
                    result.ParamBND  = SFUtil.DecryptDS3Regulation(paramPath);
                    result.Encrypted = true;
                }
            }
            catch (DllNotFoundException ex) when(ex.Message.Contains("oo2core_6_win64.dll"))
            {
                ShowError("In order to load Sekiro params, you must copy oo2core_6_win64.dll from Sekiro into Yapped's lib folder.");
                return(null);
            }
            catch (Exception ex)
            {
                ShowError($"Failed to load parambnd:\r\n{paramPath}\r\n\r\n{ex}");
                return(null);
            }

            result.ParamWrappers = new List <ParamWrapper>();
            foreach (BinderFile file in result.ParamBND.Files.Where(f => f.Name.EndsWith(".param")))
            {
                string name = Path.GetFileNameWithoutExtension(file.Name);
                if (paramInfo.ContainsKey(name))
                {
                    if (paramInfo[name].Blocked || paramInfo[name].Hidden && hideUnusedParams)
                    {
                        continue;
                    }
                }

                try
                {
                    PARAM64 param = PARAM64.Read(file.Bytes);
                    if (layouts.ContainsKey(param.ID))
                    {
                        PARAM64.Layout layout = layouts[param.ID];
                        if (layout.Size == param.DetectedSize)
                        {
                            string description = null;
                            if (paramInfo.ContainsKey(name))
                            {
                                description = paramInfo[name].Description;
                            }

                            var wrapper = new ParamWrapper(name, param, layout, description);
                            result.ParamWrappers.Add(wrapper);
                        }
                        else
                        {
                        }
                    }
                }
                catch (Exception ex)
                {
                    ShowError($"Failed to load param file: {name}.param\r\n\r\n{ex}");
                }
            }

            result.ParamWrappers.Sort();
            return(result);
        }
コード例 #7
0
ファイル: Irregulator.cs プロジェクト: JKAnderson/Irregulator
        public void Randomize(Dictionary <string, PARAM64> paramDict,
                              bool doArmor, bool doWeapons, bool doRings, bool doGoods, bool doSpells, bool doBullets, bool bulletsPlus, bool doHumans, bool doOthers)
        {
            if (doBullets)
            {
                PARAM64 param = paramDict["Bullet"];
                RandomizeAll(param.Rows, bulletsPlus);
            }

            if (doRings)
            {
                PARAM64 param = paramDict["EquipParamAccessory"];
                var     rings = param.Rows.Where(row => (byte)row["accessoryCategory"].Value == 0 && row.ID < 900000);
                RandomizeSome(rings, "weight", "refId0");
            }

            if (doGoods)
            {
                PARAM64 param = paramDict["EquipParamGoods"];
                // Skip estus flask and some other stuff
                var usable = param.Rows.Where(row => (byte)row["goodsType"].Value == 0 && row.ID >= 240);
                RandomizeSome(usable, "sfxVariationId", "goodsUseAnim");
                RandomizePair <byte, int>(usable, "refCategory", "refId1");
            }

            if (doArmor)
            {
                PARAM64 param = paramDict["EquipParamProtector"];
                var     valid = param.Rows.Where(row => row.ID >= 1000000);
                RandomizeSome(valid, "weight", "residentSpEffectId1", "residentSpEffectId2", "residentSpEffectId3", "resistPoison", "resistBlood", "resistCurse", "resistFrost", "Poise",
                              "PhysDamageCutRate", "SlashDamageCutRate", "StrikeDamageCutRate", "ThrustDamageCutRate", "MagicDamageCutRate", "FireDamageCutRate", "ThunderDamageCutRate", "DarkDamageCutRate");
            }

            if (doWeapons)
            {
                RandomizeAll(paramDict["HitEffectSfxParam"].Rows);
                PARAM64 param = paramDict["EquipParamWeapon"];

                // Get rid of test and ghost stuff
                var valid = param.Rows.Where(row => row.ID >= 100000 && row.ID < 30000000 && !(row.ID >= 409900 && row.ID <= 933900));
                RandomizeSome(valid, "weight", "correctStrength", "correctAgility", "corretMagic", "corretFaith", "physGuardCutRate", "magGuardCutRate", "fireGuardCutRate", "thunGuardCutRate",
                              "residentSpEffectId0", "residentSpEffectId1", "residentSpEffectId2", "parryDamageLife", "atkBasePhysics", "atkBaseMagic", "atkBaseFire", "atkBaseThunder", "atkBaseDark",
                              "atkBaseStamina", "saWeaponDamage", "saDurability", "guardAngle", "staminaGuardDef", "properStrength", "properAgility", "properMagic", "properFaith", "correctLuck");
                for (int i = 0; i < 24; i++)
                {
                    RandomizeOne <int>(valid, "HitSfx" + i);
                }
                for (int i = 0; i < 8; i++)
                {
                    RandomizeOne <int>(valid, "weaponVfx" + i);
                }

                var weapons = valid.Where(row => weaponCats.Contains((byte)row["weaponCategory"].Value));
                RandomizeSome(weapons,
                              "wepmotionCategory", "guardmotionCategory", "spAtkCategory", "wepmotionOneHandId", "wepmotionBothHandId", "swordArtId", "wepAbsorpPosId");

                var bows = valid.Where(row => bowCats.Contains((byte)row["weaponCategory"].Value));
                RandomizeSome(bows,
                              "wepmotionCategory", "guardmotionCategory", "spAtkCategory", "wepmotionOneHandId", "wepmotionBothHandId", "swordArtId", "wepAbsorpPosId");

                var catalysts = valid.Where(row => catalystCats.Contains((byte)row["weaponCategory"].Value));
                RandomizeSome(catalysts,
                              "wepmotionCategory", "guardmotionCategory", "spAtkCategory", "wepmotionOneHandId", "wepmotionBothHandId", "swordArtId", "wepAbsorpPosId");
            }

            if (doSpells)
            {
                PARAM64 param = paramDict["Magic"];
                RandomizeSome(param.Rows,
                              "refIdFpCost1", "refIdSpCost1", "sfxVariationId", "slotLength", "requirementIntellect", "requirementFaith", "analogDexterityMin", "analogDexterityMax", "spEffectCategory",
                              "refType", "CastSfx1", "CastSfx2", "CastSfx3", "refIdFpCost2", "refIdSpCost2", "refIdFpCost3", "refIdSpCost3", "refIdFpCost4", "refIdSpCost4");
                RandomizePair <byte, int>(param.Rows, "refCategory1", "refId1");
                RandomizePair <byte, int>(param.Rows, "refCategory2", "refId2");
                RandomizePair <byte, int>(param.Rows, "refCategory3", "refId3");
                RandomizePair <byte, int>(param.Rows, "refCategory4", "refId4");
            }

            if (doHumans)
            {
                PARAM64 param = paramDict["CharaInitParam"];
                RandomizeSome(param.Rows, "equip_Helm", "equip_Armor", "equip_Gaunt", "equip_Leg", "equip_Wep_Right", "equip_Subwep_Right", "equip_Wep_Left", "equip_Subwep_Left",
                              "equip_Accessory1", "equip_Accessory2", "equip_Accessory3", "equip_Accessory4", "bodyScaleHead", "bodyScaleBreast", "BodyScaleAbdomen", "BodyScaleArm", "BodyScaleLeg");
            }

            //{
            //    PARAM64 param = paramDict["NpcParam"];
            //    foreach (var cell in param.Rows[0].Cells)
            //    {
            //        if (cell.Name != "teamType" && !cell.Name.StartsWith("ModelDispMask"))
            //            RandomizeSome(param.Rows, cell.Name);
            //    }
            //}

            if (doOthers)
            {
                //RandomizeAll(paramDict["AtkParam_Npc"].Rows);
                //RandomizeAll(paramDict["AtkParam_Pc"].Rows);
                //RandomizeAll(paramDict["AttackElementCorrectParam"].Rows);
                //RandomizeAll(paramDict["BehaviorParam"].Rows);
                //RandomizeAll(paramDict["BehaviorParam_PC"].Rows);
                RandomizeAll(paramDict["DecalParam"].Rows);
                //RandomizeAll(paramDict["HitEffectSfxConceptParam"].Rows);
                //RandomizeAll(paramDict["ModelSfxParam"].Rows);
                //RandomizeAll(paramDict["NpcThinkParam"].Rows);
                //RandomizeAll(paramDict["ObjectMaterialSfxParam"].Rows);
                RandomizeAll(paramDict["PhantomParam"].Rows);
                //RandomizeAll(paramDict["SwordArtsParam"].Rows);
                //RandomizeAll(paramDict["UpperArmParam"].Rows);
                //RandomizeAll(paramDict["WepAbsorpPosParam"].Rows);
                RandomizeAll(paramDict["WetAspectParam"].Rows);
                RandomizeAll(paramDict["Wind"].Rows);
            }
        }
コード例 #8
0
ファイル: FormMain.cs プロジェクト: elenabluz/Yapped
        private void btnDump_Click(object sender, EventArgs e)
        {
            BND4 bnd;

            try
            {
                bnd = SFUtil.DecryptDS3Regulation(txtRegulation.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Failed to load regulation:\r\n\r\n{txtRegulation.Text}\r\n\r\n{ex}");
                return;
            }

            var translations = new Dictionary <string, string>();
            var xml          = new XmlDocument();

            xml.Load("translations.xml");

            foreach (XmlNode text in xml.SelectNodes("translations/text"))
            {
                string jp = text.SelectSingleNode("jp").InnerText;
                string en = text.SelectSingleNode("en").InnerText;
                translations[WebUtility.HtmlDecode(jp)] = WebUtility.HtmlDecode(en);
            }

            var package = new ExcelPackage();

            foreach (BinderFile file in bnd.Files)
            {
                if (Path.GetExtension(file.Name) == ".param")
                {
                    PARAM64 param      = PARAM64.Read(file.Bytes);
                    string  layoutPath = $"Layouts\\{param.ID}.xml";

                    txtStatus.AppendText(file.Name + "\r\n");

                    var worksheet = package.Workbook.Worksheets.Add(Path.GetFileNameWithoutExtension(file.Name));

                    PARAM64.Layout layout;
                    if (File.Exists(layoutPath))
                    {
                        layout = PARAM64.Layout.ReadXMLFile(layoutPath);
                        if (layout.Size != param.DetectedSize)
                        {
                            layout = new PARAM64.Layout();
                            for (int i = 0; i < param.DetectedSize / 4; i++)
                            {
                                layout.Add(new PARAM64.Layout.Entry(CellType.u32, $"unk0x{i * 4:X4}", (uint)0));
                            }
                            for (int i = 0; i < param.DetectedSize % 4; i++)
                            {
                                layout.Add(new PARAM64.Layout.Entry(CellType.u8, "unkb" + i, (byte)0));
                            }
                        }
                    }
                    else
                    {
                        layout = new PARAM64.Layout();
                    }

                    param.SetLayout(layout);
                    List <PARAM64.Row> rows = param.Rows;

                    worksheet.Cells[1, 1].Value = "ID";
                    worksheet.Cells[1, 2].Value = "Name";
                    worksheet.Cells[1, 3].Value = "Translated";
                    int columnCount = 3;
                    foreach (PARAM64.Layout.Entry lv in layout)
                    {
                        if (lv.Type != CellType.dummy8)
                        {
                            worksheet.Cells[1, ++columnCount].Value = lv.Name;
                        }
                    }

                    for (int i = 0; i < rows.Count; i++)
                    {
                        PARAM64.Row row = rows[i];
                        worksheet.Cells[i + 2, 1].Value = row.ID;
                        if (row.Name != null)
                        {
                            if (translations.ContainsKey(row.Name))
                            {
                                worksheet.Cells[i + 2, 2].Value = row.Name;
                                worksheet.Cells[i + 2, 3].Value = translations[row.Name];
                            }
                            else if (row.Name.Contains(" -- "))
                            {
                                worksheet.Cells[i + 2, 2].Value = row.Name.Substring(row.Name.IndexOf(" -- ") + 4);
                                worksheet.Cells[i + 2, 3].Value = row.Name.Substring(0, row.Name.IndexOf(" -- "));
                            }
                        }
                        else
                        {
                            worksheet.Cells[i + 2, 2].Value = row.Name;
                        }
                        columnCount = 3;

                        foreach (PARAM64.Cell cell in row.Cells)
                        {
                            CellType type = cell.Type;
                            if (type != CellType.dummy8)
                            {
                                var range = worksheet.Cells[i + 2, ++columnCount];
                                if (type == CellType.f32)
                                {
                                    range.Value = (double)(float)cell.Value;
                                }
                                else if (type == CellType.b8 || type == CellType.b32)
                                {
                                    bool b = (bool)cell.Value;
                                    range.Value = b.ToString();
                                    range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
                                    range.Style.Fill.BackgroundColor.SetColor(b ? Color.LightGreen : Color.LightPink);
                                }
                                else if (type == CellType.x8)
                                {
                                    range.Value = $"0x{cell.Value:X2}";
                                    range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right;
                                }
                                else if (type == CellType.x16)
                                {
                                    range.Value = $"0x{cell.Value:X4}";
                                    range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right;
                                }
                                else if (type == CellType.x32)
                                {
                                    range.Value = $"0x{cell.Value:X8}";
                                    range.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Right;
                                }
                                else
                                {
                                    range.Value = cell.Value;
                                }
                            }
                        }
                    }

                    worksheet.Row(1).Style.Font.Bold    = true;
                    worksheet.Column(1).Style.Font.Bold = true;
                    worksheet.View.FreezePanes(2, 4);
                    worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
                }
            }

            FileInfo f = new FileInfo(Path.Combine(txtOutput.Text, "dump.xlsx"));

            package.SaveAs(f);
        }
コード例 #9
0
        public void Randomize(Dictionary <string, PARAM64> paramDict,
                              bool doArmor, bool doWeapons, bool[] weaponStyle, bool doRings, bool doGoods, bool doSpells, bool doBullets, bool bulletsPlus, bool doHumans, bool doOthers, bool doTesting)
        {
            if (doBullets)
            {
                PARAM64 param = paramDict["Bullet"];
                RandomizeAll(param.Rows, bulletsPlus);
            }

            if (doRings)
            {
                PARAM64 param = paramDict["EquipParamAccessory"];
                var     rings = param.Rows.Where(row => (byte)row["accessoryCategory"].Value == 0 && row.ID < 900000);
                RandomizeSome(rings, false, "weight", "refId0");
            }

            if (doGoods)
            {
                PARAM64 goods  = paramDict["EquipParamGoods"];
                var     usable = goods.Rows.Where(row => (byte)row["goodsType"].Value == 0 &&           //Is a consumable (?) type good
                                                  row.ID >= 240 && !(row.ID >= 712 && row.ID <= 747) && //Not boss souls or estus
                                                  (int)row["refId1"].Value > 0);                        //Has an effect

                // Doing these sets of parameters together ensures an item can be used properly
                // for example, an effect that needs a text box will open that text box
                string[] goodsLockedParams =
                {
                    "refId1",
                    "refCategory",
                    "opmeMenuType",
                    "yesNoDialogMessageId",
                    "isEnhance",
                    "useBulletMaxNum",
                    "useHpCureMaxNum",
                    "isEnchantLeftHand",
                    "isApplySpecialEffect",
                    "refVirtualWepId",
                    "replaceItemId_BySpEffect",
                    "replaceTriggerSpEffectId",
                    "reinforceParamWeapon"
                };
                RandomizeSomeTogether(usable, goodsLockedParams);
                RandomizeSome(usable, false, "sfxVariationId", "goodsUseAnim"); // These do not affect the effect
            }

            if (doArmor)
            {
                PARAM64 param = paramDict["EquipParamProtector"];
                var     valid = param.Rows.Where(row => row.ID >= 1000000);
                RandomizeSome(valid, false, "weight", "residentSpEffectId1", "residentSpEffectId2", "residentSpEffectId3", "resistPoison", "resistBlood", "resistCurse", "resistFrost", "Poise",
                              "PhysDamageCutRate", "SlashDamageCutRate", "StrikeDamageCutRate", "ThrustDamageCutRate", "MagicDamageCutRate", "FireDamageCutRate", "ThunderDamageCutRate", "DarkDamageCutRate");
            }

            if (doWeapons)
            {
                bool flatten  = weaponStyle[1]; // Chose Balanced
                bool separate = weaponStyle[2]; // Chose No Shields

                RandomizeAll(paramDict["HitEffectSfxParam"].Rows);
                PARAM64 param = paramDict["EquipParamWeapon"];

                // Get rid of test and ghost stuff
                var valid = param.Rows.Where(row => row.ID >= 100000 && row.ID < 30000000 && !(row.ID >= 409900 && row.ID <= 933900));
                RandomizeSome(valid, false, "weight", "correctStrength", "correctAgility", "corretMagic", "corretFaith", "physGuardCutRate", "magGuardCutRate", "fireGuardCutRate", "thunGuardCutRate",
                              "residentSpEffectId0", "residentSpEffectId1", "residentSpEffectId2", "parryDamageLife", "atkBasePhysics", "atkBaseMagic", "atkBaseFire", "atkBaseThunder", "atkBaseDark",
                              "atkBaseStamina", "saWeaponDamage", "saDurability", "guardAngle", "staminaGuardDef", "properStrength", "properAgility", "properMagic", "properFaith", "correctLuck");
                for (int i = 0; i < 24; i++)
                {
                    RandomizeOne <int>(valid, "HitSfx" + i, true);
                }
                for (int i = 0; i < 8; i++)
                {
                    RandomizeOne <int>(valid, "weaponVfx" + i, true);
                }

                if (separate) // If wanting to remove shield movesets from the weapon's pool
                {
                    var weapons = valid.Where(row => weaponCats.Contains((byte)row["weaponCategory"].Value));
                    RandomizeSome(weapons, false,
                                  "wepmotionCategory", "guardmotionCategory", "spAtkCategory", "wepmotionOneHandId", "wepmotionBothHandId", "swordArtId", "wepAbsorpPosId");

                    var shields = valid.Where(row => shieldCats.Contains((byte)row["weapnCategory"].Value));
                    RandomizeSome(weapons, false,
                                  "wepmotionCategory", "guardmotionCategory", "spAtkCategory", "wepmotionOneHandId", "wepmotionBothHandId", "swordArtId", "wepAbsorpPosId");
                }
                else
                {
                    var weapons = valid.Where(row => swingableCats.Contains((byte)row["weaponCategory"].Value));
                    RandomizeSome(weapons, flatten,
                                  "wepmotionCategory", "guardmotionCategory", "spAtkCategory", "wepmotionOneHandId", "wepmotionBothHandId", "swordArtId", "wepAbsorpPosId");
                }

                var bows = valid.Where(row => bowCats.Contains((byte)row["weaponCategory"].Value));
                RandomizeSome(bows, false,
                              "wepmotionCategory", "guardmotionCategory", "spAtkCategory", "wepmotionOneHandId", "wepmotionBothHandId", "swordArtId", "wepAbsorpPosId");

                var catalysts = valid.Where(row => catalystCats.Contains((byte)row["weaponCategory"].Value));
                RandomizeSome(catalysts, false,
                              "wepmotionCategory", "guardmotionCategory", "spAtkCategory", "wepmotionOneHandId", "wepmotionBothHandId", "swordArtId", "wepAbsorpPosId");
            }

            if (doSpells)
            {
                PARAM64 param = paramDict["Magic"];
                RandomizeSome(param.Rows, false,
                              "refIdFpCost1", "refIdSpCost1", "sfxVariationId", "slotLength", "requirementIntellect", "requirementFaith", "analogDexterityMin", "analogDexterityMax", "spEffectCategory",
                              "refType", "CastSfx1", "CastSfx2", "CastSfx3", "refIdFpCost2", "refIdSpCost2", "refIdFpCost3", "refIdSpCost3", "refIdFpCost4", "refIdSpCost4");
                RandomizePair <byte, int>(param.Rows, "refCategory1", "refId1");
                RandomizePair <byte, int>(param.Rows, "refCategory2", "refId2");
                RandomizePair <byte, int>(param.Rows, "refCategory3", "refId3");
                RandomizePair <byte, int>(param.Rows, "refCategory4", "refId4");
            }

            if (doHumans)
            {
                PARAM64 param = paramDict["CharaInitParam"];
                RandomizeSome(param.Rows, false, "equip_Helm", "equip_Armor", "equip_Gaunt", "equip_Leg", "equip_Wep_Right", "equip_Subwep_Right", "equip_Wep_Left", "equip_Subwep_Left",
                              "equip_Accessory1", "equip_Accessory2", "equip_Accessory3", "equip_Accessory4", "bodyScaleHead", "bodyScaleBreast", "BodyScaleAbdomen", "BodyScaleArm", "BodyScaleLeg");
            }

            //{
            //    PARAM64 param = paramDict["NpcParam"];
            //    foreach (var cell in param.Rows[0].Cells)
            //    {
            //        if (cell.Name != "teamType" && !cell.Name.StartsWith("ModelDispMask"))
            //            RandomizeSome(param.Rows, cell.Name);
            //    }
            //}

            if (doOthers)
            {
                //TEXTURE
                RandomizeAll(paramDict["DecalParam"].Rows);     // Like bloody footprints?
                RandomizeAll(paramDict["PhantomParam"].Rows);   // Phantom Texture
                RandomizeAll(paramDict["WetAspectParam"].Rows); // Liquid Colors
                RandomizeAll(paramDict["Wind"].Rows);           // Wind directions and strengths?

                RandomizeAll(paramDict["HitEffectSfxParam"].Rows);
                RandomizeAll(paramDict["ObjectMaterialSfxParam"].Rows);
                RandomizeAll(paramDict["HitEffectSfxConceptParam"].Rows);
                RandomizeAll(paramDict["ModelSfxParam"].Rows);

                //SOUND
                RandomizeAll(paramDict["FootSfxParam"].Rows);
                RandomizeAll(paramDict["HitEffectSeParam"].Rows);
                RandomizeAll(paramDict["SeMaterialConvertParam"].Rows);

                IEnumerable <PARAM64.Row> breakables = paramDict["ObjectParam"].Rows.Where(row =>
                                                                                           (short)row["HP"].Value > 0 && !(bool)row["isAnimBreak"].Value);
                RandomizeAll(breakables, true);


                //ENEMY ATTACLS
                String[] some = { "KnockbackDist",  "HitStopTime", "spEffect0",  "spEffect1",    "spEffect2",      "spEffect3",    "spEffect4",
                                  "AtkPhys",        "AtkMag",      "AtkFire",    "AtkThun",      "AtkStam",        "GuardAtkRate", "GuardBreakRate","AtkSuperArmor",
                                  "AtkThrowEscape", "damageLevel", "mapHitType", "AtkAttribute", "atkPowForSfxSe", "atkDirForSfxSe" };

                PARAM64     param  = paramDict["AtkParam_Npc"];
                List <long> oldIDs = new List <long>();
                oldIDs.Add(0);
                for (int i = 3; i >= 0; i--)
                {
                    String toCheck = "Hit" + i + "_Radius";

                    var xhit = param.Rows.Where(row => (float)row[toCheck].Value > 0 && !oldIDs.Contains(row.ID));
                    RandomizeSome(xhit, false, some);

                    List <long> newIDs = xhit.Select(row => (long)row.ID).ToList();
                    Console.Out.WriteLine("Randomized " + newIDs.Count + " attacks with " + (i + 1) + " hits.");

                    oldIDs.AddRange(newIDs);
                }
            }

            if (doTesting)
            {
                //TODO:
                //SHIELDS AS WEAPONS
                //SWAMP NO HURT ENEMY
                //spEffectParam, row 4001-4004, set effectTargetFriend to no


                // AFAICT There's no way to stop the ground from affecting the NPCs
                // Turn off for Ash and Stone to protect shrine at least?
                IEnumerable <PARAM64.Row> materials = paramDict["HitMtrlParam"].Rows.Where(row => !dangerFloors.Contains(row.ID));

                string[] effect0  = { "spEffectIdOnHit0", "spEffectIdOnHit3", "spEffectIdOnHit4", "spEffectIdOnHit5", "spEffectIdOnHit6", "spEffectIdOnHit7", "spEffectIdOnHit8", "spEffectIdOnHit9" };
                string[] effect1  = { "spEffectIdOnHit1", "newSpType0", "spEffectIdOnHit10", "spEffectIdOnHit11", "spEffectIdOnHit12", "spEffectIdOnHit13", "spEffectIdOnHit14", "spEffectIdOnHit15", "spEffectIdOnHit16" };
                string[] effect2  = { "spEffectIdOnHit2", "FootEffectHeightType0", "FootEffectHeightType1" };
                string[] unlocked = { "HitMtrlType0", "HitMtrlType1", "HitMtrlType2" };
                RandomizeSomeTogether(materials, effect0);
                RandomizeSomeTogether(materials, effect1);
                RandomizeSomeTogether(materials, effect2);
                RandomizeSome(materials, false, unlocked);

                bool done = true;

                if (done)
                {
                    //BREAKABLES


                    //BALANCE
                    // This block randomizes enemy attack effects
                    // but we can only randomize between attack entries with the same number of attacks
                }
            }
        }